1pub mod amd;
2pub mod async_module;
3pub mod cjs;
4pub mod constant_condition;
5pub mod constant_value;
6pub mod cross_module_constants;
7pub mod dynamic_expression;
8pub mod emit_collect;
9pub mod esm;
10pub mod exports;
11pub mod exports_info;
12pub mod external_module;
13pub mod hot_module;
14pub mod ident;
15pub mod import_meta_glob;
16pub mod member;
17pub mod node;
18pub mod pattern_mapping;
19pub mod raw;
20pub mod removal;
21pub mod require_context;
22pub mod service_worker;
23#[cfg(test)]
24mod tests;
25pub mod type_issue;
26pub mod typescript;
27pub mod util;
28pub mod worker;
29
30use std::{
31 cell::RefCell,
32 future::Future,
33 mem::{replace, take},
34 sync::{Arc, LazyLock},
35};
36
37use anyhow::{Context, Result, bail};
38use bumpalo::boxed::Box as BumpBox;
39use constant_condition::{ConstantConditionCodeGen, ConstantConditionValue};
40use constant_value::ConstantValueCodeGen;
41use indexmap::map::Entry;
42use num_traits::Zero;
43use parking_lot::Mutex;
44use regex::Regex;
45use removal::RemovalCodeGen;
46use rustc_hash::{FxHashMap, FxHashSet};
47use service_worker::ServiceWorkerAssetReference;
48use swc_core::{
49 atoms::{Atom, Wtf8Atom, atom},
50 common::{
51 GLOBALS, Globals, Span, Spanned,
52 comments::{CommentKind, Comments},
53 errors::{DiagnosticId, HANDLER, Handler, Level},
54 source_map::SmallPos,
55 },
56 ecma::{
57 ast::*,
58 visit::{
59 AstParentKind,
60 fields::{
61 AssignExprField, AssignTargetField, BindingIdentField, SimpleAssignTargetField,
62 },
63 },
64 },
65};
66use tokio::sync::OnceCell;
67use tracing::Instrument;
68use turbo_rcstr::{RcStr, rcstr};
69use turbo_tasks::{
70 FxIndexMap, FxIndexSet, JoinIterExt, PrettyPrintError, ReadRef, ResolvedVc, TryJoinIterExt,
71 Upcast, ValueToString, Vc, turbofmt,
72};
73use turbo_tasks_fs::FileSystemPath;
74use turbopack_core::{
75 compile_time_info::{
76 CompileTimeDefineValue, CompileTimeDefines, CompileTimeInfo, DefinableNameSegment,
77 DefinableNameSegmentRef, FreeVarReference, FreeVarReferences, FreeVarReferencesMembers,
78 InputRelativeConstant,
79 },
80 environment::Rendering,
81 issue::{IssueExt, IssueSeverity, IssueSource, analyze::AnalyzeIssue},
82 module::Module,
83 reference::{ModuleReference, ModuleReferences},
84 reference_type::{CommonJsReferenceSubType, InnerAssets},
85 resolve::{
86 ExportUsage, FindContextFileResult, ImportUsage, ModulePart, ResolveErrorMode,
87 find_context_file,
88 origin::{PlainResolveOrigin, ResolveOrigin},
89 parse::Request,
90 pattern::Pattern,
91 },
92 source::Source,
93 source_map::GenerateSourceMap,
94};
95use turbopack_resolve::{ecmascript::cjs_resolve_source, typescript::tsconfig};
96use turbopack_swc_utils::emitter::IssueEmitter;
97use worker::{WorkerAssetReference, WorkerGlobalPlaceholder, WorkerGlobalsReplacementCodeGen};
98
99pub use crate::references::esm::export::{FollowExportsResult, follow_reexports};
100use crate::{
101 AnalyzeMode, EcmascriptModuleAsset, EcmascriptModuleAssetType, EcmascriptParsable,
102 EnvVarAccessMode, EnvVarInfo, ModuleTypeResult, TypeofWindow,
103 analyzer::{
104 Bump, BumpVec, ConstantNumber, ConstantString, ConstantValue as JsConstantValue, JsValue,
105 JsValueUrlKind, Modified, ModuleValue, ObjectPart, RequireContextValue, ThreadLocal,
106 WellKnownFunctionKind, WellKnownObjectKind,
107 builtin::{early_replace_builtin, replace_builtin},
108 graph::{ConditionalKind, Effect, EffectArg, VarGraph, create_graph},
109 imports::{ImportAnnotations, ImportAttributes, ImportMap},
110 linker::link,
111 parse_require_context,
112 top_level_await::has_top_level_await,
113 well_known::replace_well_known,
114 },
115 ast_path_trie::{AstPathId, AstPathTrieBuilder},
116 chunk::CjsStaticExports,
117 code_gen::{CodeGen, CodeGens, IntoCodeGenReference},
118 errors,
119 module_fragments::{part_of_module, split_module},
120 parse::ParseResult,
121 references::{
122 amd::{
123 AmdDefineAssetReference, AmdDefineDependencyElement, AmdDefineFactoryType,
124 AmdDefineWithDependenciesCodeGen,
125 },
126 async_module::{AsyncModule, OptionAsyncModule},
127 cjs::{CjsAssetReference, CjsRequireAssetReference, CjsRequireResolveAssetReference},
128 cross_module_constants::{
129 is_import_name_eligible_for_exports, module_value_to_constants_module,
130 },
131 dynamic_expression::DynamicExpression,
132 emit_collect::{CollectReference, EmitReference},
133 esm::{
134 EsmAssetReference, EsmAssetReferenceOptions, EsmAsyncAssetReference, ImportMetaBinding,
135 ImportMetaRef, UrlAssetReference, UrlRewriteBehavior, base::EsmAssetReferences,
136 binding::EsmBindingsBuilder, module_id::EsmModuleIdAssetReference,
137 },
138 exports::{EcmascriptExportsAnalysis, compute_ecmascript_module_exports},
139 exports_info::{ExportsInfoBinding, ExportsInfoRef},
140 hot_module::{ModuleHotReferenceAssetReference, ModuleHotReferenceCodeGen},
141 ident::IdentReplacement,
142 import_meta_glob::{ImportMetaGlobAssetReference, parse_import_meta_glob},
143 member::MemberReplacement,
144 node::PackageJsonReference,
145 raw::{DirAssetReference, FileSourceReference},
146 require_context::{RequireContextAssetReference, RequireContextMap},
147 typescript::{
148 TsConfigReference, TsReferencePathAssetReference, TsReferenceTypeAssetReference,
149 },
150 },
151 runtime_functions::{
152 TURBOPACK_EXPORTS, TURBOPACK_GLOBAL, TURBOPACK_REQUIRE_REAL, TURBOPACK_REQUIRE_STUB,
153 TURBOPACK_RUNTIME_FUNCTION_SHORTCUTS,
154 },
155 source_map::parse_source_map_comment,
156 utils::{AstPathRange, js_value_to_pattern, module_value_to_well_known_object},
157};
158
159#[turbo_tasks::value(shared)]
160pub struct AnalyzeEcmascriptModuleResult {
161 references: Vec<ResolvedVc<Box<dyn ModuleReference>>>,
162
163 pub esm_references: ResolvedVc<EsmAssetReferences>,
164 pub esm_local_references: ResolvedVc<EsmAssetReferences>,
165 pub esm_reexport_references: ResolvedVc<EsmAssetReferences>,
166
167 pub code_generation: ResolvedVc<CodeGens>,
168 pub async_module: ResolvedVc<OptionAsyncModule>,
169 pub successful: bool,
171 pub source_map: Option<ResolvedVc<Box<dyn GenerateSourceMap>>>,
172 pub cjs_static_exports: Option<CjsStaticExports>,
175 pub has_direct_eval: bool,
178
179 pub env_var_info: ResolvedVc<EnvVarInfo>,
180}
181
182#[turbo_tasks::value_impl]
183impl AnalyzeEcmascriptModuleResult {
184 #[turbo_tasks::function]
185 pub async fn references(&self) -> Result<Vc<ModuleReferences>> {
186 Ok(Vc::cell(
187 self.esm_references
188 .await?
189 .iter()
190 .map(|r| ResolvedVc::upcast(*r))
191 .chain(self.references.iter().copied())
192 .collect(),
193 ))
194 }
195
196 #[turbo_tasks::function]
197 pub async fn local_references(&self) -> Result<Vc<ModuleReferences>> {
198 Ok(Vc::cell(
199 self.esm_local_references
200 .await?
201 .iter()
202 .map(|r| ResolvedVc::upcast(*r))
203 .chain(self.references.iter().copied())
204 .collect(),
205 ))
206 }
207}
208
209#[cfg(debug_assertions)]
212type CodeGenCollection = FxIndexSet<CodeGen>;
213#[cfg(not(debug_assertions))]
214type CodeGenCollection = Vec<CodeGen>;
215
216struct AnalyzeEcmascriptModuleResultBuilder {
219 analyze_mode: AnalyzeMode,
220
221 references: FxIndexSet<ResolvedVc<Box<dyn ModuleReference>>>,
222
223 esm_references: FxHashSet<usize>,
224 esm_local_references: FxHashSet<usize>,
225 esm_reexport_references: FxHashSet<usize>,
226
227 esm_references_free_var: FxIndexMap<RcStr, ResolvedVc<EsmAssetReference>>,
228 esm_references_rewritten: FxHashMap<usize, FxIndexMap<RcStr, ResolvedVc<EsmAssetReference>>>,
231
232 esm_bindings: EsmBindingsBuilder,
233
234 code_gens: CodeGenCollection,
235 ast_paths: RefCell<AstPathTrieBuilder>,
240 async_module: ResolvedVc<OptionAsyncModule>,
241 successful: bool,
242 source_map: Option<ResolvedVc<Box<dyn GenerateSourceMap>>>,
243 cjs_static_exports: Option<CjsStaticExports>,
244 has_direct_eval: bool,
245
246 env_var_info_runtime: FxIndexMap<RcStr, EnvVarAccessMode>,
247
248 #[cfg(debug_assertions)]
249 ident: RcStr,
250}
251
252impl AnalyzeEcmascriptModuleResultBuilder {
253 fn new(analyze_mode: AnalyzeMode) -> Self {
254 Self {
255 analyze_mode,
256 references: Default::default(),
257 esm_references: Default::default(),
258 esm_local_references: Default::default(),
259 esm_reexport_references: Default::default(),
260 esm_references_rewritten: Default::default(),
261 esm_references_free_var: Default::default(),
262 esm_bindings: Default::default(),
263 code_gens: Default::default(),
264 ast_paths: Default::default(),
265 async_module: ResolvedVc::cell(None),
266 successful: false,
267 source_map: None,
268 cjs_static_exports: None,
269 has_direct_eval: false,
270 env_var_info_runtime: Default::default(),
271 #[cfg(debug_assertions)]
272 ident: Default::default(),
273 }
274 }
275
276 pub fn adopt_ast_paths(&mut self, paths: AstPathTrieBuilder) {
281 debug_assert_eq!(
282 self.ast_paths.borrow().node_count(),
283 0,
284 "adopting a trie would invalidate the paths already interned here",
285 );
286 *self.ast_paths.borrow_mut() = paths;
287 }
288
289 pub fn intern_path(&self, path: &[AstParentKind]) -> AstPathId {
291 self.ast_paths.borrow_mut().intern(path.iter().copied())
292 }
293
294 pub fn add_reference(&mut self, reference: ResolvedVc<impl Upcast<Box<dyn ModuleReference>>>) {
296 let r = ResolvedVc::upcast_non_strict(reference);
297 self.references.insert(r);
298 }
299
300 pub fn add_reference_code_gen<R: IntoCodeGenReference>(
302 &mut self,
303 reference: R,
304 path: AstPathId,
305 link_context: ValueLinkContext,
306 ) {
307 match link_context {
308 ValueLinkContext::Default => {
309 let (reference, code_gen) =
310 reference.into_code_gen_reference(&self.ast_paths.borrow(), path);
311 self.references.insert(reference);
312 self.add_code_gen(code_gen);
313 }
314 ValueLinkContext::InAlternative => {
315 self.references.insert(reference.into_reference());
316 }
317 }
318 }
319
320 pub fn add_esm_reference(&mut self, idx: usize) {
322 self.esm_references.insert(idx);
323 self.esm_local_references.insert(idx);
324 }
325
326 pub fn add_esm_reexport_reference(&mut self, idx: usize) {
329 self.esm_references.insert(idx);
330 self.esm_reexport_references.insert(idx);
331 }
332
333 pub fn add_esm_evaluation_reference(&mut self, idx: usize) {
336 self.esm_references.insert(idx);
337 self.esm_local_references.insert(idx);
338 }
339
340 pub fn add_code_gen<C>(&mut self, code_gen: C)
342 where
343 C: Into<CodeGen>,
344 {
345 if self.analyze_mode.is_codegen {
346 #[cfg(debug_assertions)]
347 {
348 let (index, added) = self.code_gens.insert_full(code_gen.into());
349 debug_assert!(
350 added,
351 "Duplicate code gen added: {:?} in {}",
352 self.code_gens.get_index(index).unwrap(),
353 self.ident
354 );
355 }
356 #[cfg(not(debug_assertions))]
357 {
358 self.code_gens.push(code_gen.into());
359 }
360 }
361 }
362
363 pub fn set_source_map(&mut self, source_map: ResolvedVc<Box<dyn GenerateSourceMap>>) {
365 self.source_map = Some(source_map);
366 }
367
368 pub fn set_async_module(&mut self, async_module: ResolvedVc<AsyncModule>) {
370 self.async_module = ResolvedVc::cell(Some(async_module));
371 }
372
373 pub fn set_successful(&mut self, successful: bool) {
375 self.successful = successful;
376 }
377
378 pub fn add_runtime_env_var_reference_read(&mut self, runtime_env: RcStr) {
379 self.env_var_info_runtime
380 .insert(runtime_env, EnvVarAccessMode::Read);
382 }
383
384 pub fn add_runtime_env_var_reference_existence(&mut self, runtime_env: RcStr) {
385 self.env_var_info_runtime
386 .entry(runtime_env)
387 .or_insert(EnvVarAccessMode::Existence);
389 }
390
391 pub fn add_esm_reference_namespace_resolved(
392 &mut self,
393 esm_reference_idx: usize,
394 export: RcStr,
395 on_insert: impl FnOnce() -> ResolvedVc<EsmAssetReference>,
396 ) -> ResolvedVc<EsmAssetReference> {
397 *self
398 .esm_references_rewritten
399 .entry(esm_reference_idx)
400 .or_default()
401 .entry(export)
402 .or_insert_with(on_insert)
403 }
404
405 pub async fn add_esm_reference_free_var(
406 &mut self,
407 request: RcStr,
408 on_insert: impl AsyncFnOnce() -> Result<ResolvedVc<EsmAssetReference>>,
409 ) -> Result<ResolvedVc<EsmAssetReference>> {
410 Ok(match self.esm_references_free_var.entry(request) {
411 Entry::Occupied(e) => *e.get(),
412 Entry::Vacant(e) => *e.insert(on_insert().await?),
413 })
414 }
415
416 pub async fn build(
418 mut self,
419 import_references: &[ResolvedVc<EsmAssetReference>],
420 track_reexport_references: bool,
421 ) -> Result<Vc<AnalyzeEcmascriptModuleResult>> {
422 let mut esm_references = Vec::with_capacity(
425 self.esm_references.len()
426 + self.esm_references_free_var.len()
427 + self.esm_references_rewritten.len(),
428 );
429 esm_references.extend(self.esm_references_free_var.values());
430
431 let mut esm_local_references = track_reexport_references.then(|| {
432 let mut esm_local_references = Vec::with_capacity(
433 self.esm_local_references.len()
434 + self.esm_references_free_var.len()
435 + self.esm_references_rewritten.len(),
436 );
437 esm_local_references.extend(self.esm_references_free_var.values());
438 esm_local_references
439 });
440 let mut esm_reexport_references = track_reexport_references
441 .then(|| Vec::with_capacity(self.esm_reexport_references.len()));
442 for (i, reference) in import_references.iter().enumerate() {
443 if self.esm_references.contains(&i) {
444 esm_references.push(*reference);
445 }
446 esm_references.extend(
447 self.esm_references_rewritten
448 .get(&i)
449 .iter()
450 .flat_map(|m| m.values().copied()),
451 );
452 if let Some(esm_local_references) = &mut esm_local_references {
453 if self.esm_local_references.contains(&i) {
454 esm_local_references.push(*reference);
455 }
456 esm_local_references.extend(
457 self.esm_references_rewritten
458 .get(&i)
459 .iter()
460 .flat_map(|m| m.values().copied()),
461 );
462 }
463 if let Some(esm_reexport_references) = &mut esm_reexport_references
464 && self.esm_reexport_references.contains(&i)
465 {
466 esm_reexport_references.push(*reference);
467 }
468 }
469
470 if let Some(esm_bindings) = std::mem::take(&mut self.esm_bindings).build() {
471 self.add_code_gen(CodeGen::EsmBindings(esm_bindings));
472 }
473
474 let references: Vec<_> = self.references.into_iter().collect();
475
476 if !self.analyze_mode.is_codegen {
477 debug_assert!(self.code_gens.is_empty());
478 }
479
480 self.code_gens.shrink_to_fit();
481
482 #[cfg(debug_assertions)]
483 let code_generation = self.code_gens.into_iter().collect::<Vec<_>>();
484 #[cfg(not(debug_assertions))]
485 let code_generation = self.code_gens;
486
487 Ok(AnalyzeEcmascriptModuleResult::cell(
488 AnalyzeEcmascriptModuleResult {
489 references,
490 esm_references: ResolvedVc::cell(esm_references),
491 esm_local_references: ResolvedVc::cell(esm_local_references.unwrap_or_default()),
492 esm_reexport_references: ResolvedVc::cell(
493 esm_reexport_references.unwrap_or_default(),
494 ),
495 code_generation: if code_generation.is_empty() {
496 CodeGens::empty().to_resolved().await?
497 } else {
498 CodeGens {
499 code_gens: code_generation,
500 ast_paths: self.ast_paths.into_inner().build(),
501 }
502 .resolved_cell()
503 },
504 async_module: self.async_module,
505 successful: self.successful,
506 source_map: self.source_map,
507 cjs_static_exports: self.cjs_static_exports,
508 has_direct_eval: self.has_direct_eval,
509 env_var_info: EnvVarInfo {
510 runtime: self.env_var_info_runtime,
511 }
512 .resolved_cell(),
513 },
514 ))
515 }
516}
517
518enum Action<'a> {
519 Effect(Effect<'a>),
520 LeaveScope(u32),
521}
522
523fn add_effects<'a, I>(queue_stack: &mut Vec<Action<'a>>, effects: I)
526where
527 I: IntoIterator<Item = Effect<'a>>,
528 I::IntoIter: DoubleEndedIterator,
529{
530 queue_stack.extend(effects.into_iter().map(Action::Effect).rev());
531}
532
533struct AnalysisState<'a> {
534 handler: &'a Handler,
535 module: ResolvedVc<EcmascriptModuleAsset>,
536 source: ResolvedVc<Box<dyn Source>>,
537 origin: ResolvedVc<Box<dyn ResolveOrigin>>,
538 origin_path: FileSystemPath,
539 compile_time_info: ResolvedVc<CompileTimeInfo>,
540 free_var_references_members: ResolvedVc<FreeVarReferencesMembers>,
541 compile_time_info_ref: ReadRef<CompileTimeInfo>,
542 arena: &'a ThreadLocal<Bump>,
543 var_graph: VarGraph<'a>,
544 allow_project_root_tracing: bool,
548 fun_args_values: Mutex<FxHashMap<u32, BumpVec<'a, JsValue<'a>>>>,
551 var_cache: Mutex<FxHashMap<Id, JsValue<'a>>>,
553 constants_cache: Mutex<FxHashMap<ModuleValue, Option<JsValue<'a>>>>,
555 first_import_meta: bool,
558 first_webpack_exports_info: bool,
561 module_fragments_enabled: bool,
562 cjs_tree_shaking: bool,
563 cross_module_constants: bool,
564 lazy_compilation: bool,
565 import_externals: bool,
566 ignore_dynamic_requests: bool,
567 url_rewrite_behavior: Option<UrlRewriteBehavior>,
568 collect_affecting_sources: bool,
571 tracing_only: bool,
574 is_esm: bool,
576 import_references: &'a [ResolvedVc<EsmAssetReference>],
578 imports: &'a ImportMap,
580 inner_assets: Option<ReadRef<InnerAssets>>,
582}
583
584impl<'a> AnalysisState<'a> {
585 async fn link_value(
587 &self,
588 value: JsValue<'a>,
589 attributes: &ImportAttributes,
590 ) -> Result<JsValue<'a>> {
591 Ok(link(
592 self.arena,
593 &self.var_graph,
594 value,
595 &|value| early_value_visitor(self.arena, value),
596 &|value| {
597 value_visitor(
598 self.arena,
599 *self.origin,
600 &self.origin_path,
601 value,
602 *self.compile_time_info,
603 &self.compile_time_info_ref,
604 &self.var_graph,
605 attributes,
606 self.allow_project_root_tracing,
607 &self.constants_cache,
608 self.import_references,
609 self.cross_module_constants,
610 )
611 },
612 &self.fun_args_values,
613 &self.var_cache,
614 )
615 .await?
616 .0)
617 }
618}
619
620fn set_handler_and_globals<F, R>(handler: &Handler, globals: &Arc<Globals>, f: F) -> R
621where
622 F: FnOnce() -> R,
623{
624 HANDLER.set(handler, || GLOBALS.set(globals, f))
625}
626
627#[turbo_tasks::function]
629pub async fn analyze_ecmascript_module(
630 module: ResolvedVc<EcmascriptModuleAsset>,
631 part: Option<ModulePart>,
632) -> Result<Vc<AnalyzeEcmascriptModuleResult>> {
633 let span = tracing::info_span!(
634 "analyze ecmascript module",
635 name = display(module.ident().to_string().await?)
636 );
637 let result = analyze_ecmascript_module_internal(module, part)
638 .instrument(span)
639 .await;
640
641 match result {
642 Ok(result) => Ok(result),
643 Err(err) => Err(err
645 .context(turbofmt!("failed to analyze ecmascript module '{}'", module.ident()).await?)),
646 }
647}
648
649async fn analyze_ecmascript_module_internal(
650 module: ResolvedVc<EcmascriptModuleAsset>,
651 part: Option<ModulePart>,
652) -> Result<Vc<AnalyzeEcmascriptModuleResult>> {
653 let raw_module = module.await?;
654
655 let source = raw_module.source;
656 let ty = raw_module.ty;
657 let options = raw_module.options;
658 let options = options.await?;
659 let import_externals = options.import_externals;
660 let analyze_mode = options.analyze_mode;
661
662 let origin = ResolvedVc::upcast::<Box<dyn ResolveOrigin>>(module);
663 let origin_ref = origin.into_trait_ref().await?;
664 let origin_path = origin_ref.origin_path();
665 let path = &origin_path;
666 let mut analysis = AnalyzeEcmascriptModuleResultBuilder::new(analyze_mode);
667 #[cfg(debug_assertions)]
668 {
669 analysis.ident = source.ident().to_string().owned().await?;
670 }
671
672 let inner_assets = if let Some(assets) = raw_module.inner_assets {
673 Some(assets.await?)
674 } else {
675 None
676 };
677
678 let analyze_types = match &ty {
680 EcmascriptModuleAssetType::Typescript { analyze_types, .. } => *analyze_types,
681 EcmascriptModuleAssetType::TypescriptDeclaration => true,
682 EcmascriptModuleAssetType::Ecmascript
683 | EcmascriptModuleAssetType::EcmascriptExtensionless => false,
684 };
685
686 let parsed = if let Some(part) = &part {
688 let split_data = split_module(*module);
689 part_of_module(split_data, part.clone())
690 } else {
691 module.failsafe_parse()
692 };
693
694 let ModuleTypeResult {
695 module_type: specified_type,
696 ref referenced_package_json,
697 } = *module.determine_module_type().await?;
698
699 if let Some(package_json) = referenced_package_json {
700 let span = tracing::trace_span!("package.json reference");
701 async {
702 analysis.add_reference(
703 PackageJsonReference::new(package_json.clone())
704 .to_resolved()
705 .await?,
706 );
707 anyhow::Ok(())
708 }
709 .instrument(span)
710 .await?;
711 }
712
713 if analyze_types {
714 let span = tracing::trace_span!("tsconfig reference");
715 async {
716 match &*find_context_file(path.parent(), tsconfig(), false).await? {
717 FindContextFileResult::Found(tsconfig, _) => {
718 analysis.add_reference(
719 TsConfigReference::new(*origin, tsconfig.clone())
720 .to_resolved()
721 .await?,
722 );
723 }
724 FindContextFileResult::NotFound(_) => {}
725 };
726 anyhow::Ok(())
727 }
728 .instrument(span)
729 .await?;
730 }
731
732 let EcmascriptExportsAnalysis {
733 exports: _,
734 import_references,
735 esm_reexport_reference_idxs,
736 esm_evaluation_reference_idxs,
737 } = &*compute_ecmascript_module_exports(*module, part).await?;
739
740 let parsed = if !analyze_mode.is_codegen {
741 parsed.final_read_hint().await?
743 } else {
744 parsed.await?
745 };
746
747 let ParseResult::Ok {
748 program,
749 globals,
750 eval_context,
751 comments,
752 source_map,
753 source_mapping_url,
754 program_source: _,
755 } = &*parsed
756 else {
757 return analysis.build(Default::default(), false).await;
758 };
759
760 for i in esm_reexport_reference_idxs {
761 analysis.add_esm_reexport_reference(*i);
762 }
763 for i in esm_evaluation_reference_idxs {
764 analysis.add_esm_evaluation_reference(*i);
765 }
766
767 let is_esm = eval_context.is_esm(specified_type);
768
769 let compile_time_info = compile_time_info_for_module_options(
770 *raw_module.compile_time_info,
771 is_esm,
772 options.enable_typeof_window_inlining,
773 )
774 .to_resolved()
775 .await?;
776
777 let pos = program.span().lo;
778 if analyze_types {
779 let span = tracing::trace_span!("type references");
780 async {
781 if let Some(comments) = comments.get_leading(pos) {
782 for comment in comments.iter() {
783 if let CommentKind::Line = comment.kind {
784 static REFERENCE_PATH: LazyLock<Regex> = LazyLock::new(|| {
785 Regex::new(r#"^/\s*<reference\s*path\s*=\s*["'](.+)["']\s*/>\s*$"#)
786 .unwrap()
787 });
788 static REFERENCE_TYPES: LazyLock<Regex> = LazyLock::new(|| {
789 Regex::new(r#"^/\s*<reference\s*types\s*=\s*["'](.+)["']\s*/>\s*$"#)
790 .unwrap()
791 });
792 let text = &comment.text;
793 if let Some(m) = REFERENCE_PATH.captures(text) {
794 let path = &m[1];
795 analysis.add_reference(
796 TsReferencePathAssetReference::new(*origin, path.into())
797 .to_resolved()
798 .await?,
799 );
800 } else if let Some(m) = REFERENCE_TYPES.captures(text) {
801 let types = &m[1];
802 analysis.add_reference(
803 TsReferenceTypeAssetReference::new(*origin, types.into())
804 .to_resolved()
805 .await?,
806 );
807 }
808 }
809 }
810 }
811 anyhow::Ok(())
812 }
813 .instrument(span)
814 .await?;
815 }
816
817 if options.extract_source_map {
818 let span = tracing::trace_span!("source map reference");
819 async {
820 if let Some((source_map, reference)) =
821 parse_source_map_comment(source, source_mapping_url.as_deref(), &origin_path)
822 .await?
823 {
824 analysis.set_source_map(source_map);
825 if let Some(reference) = reference {
826 analysis.add_reference(reference);
827 }
828 }
829 anyhow::Ok(())
830 }
831 .instrument(span)
832 .await?;
833 }
834
835 let (emitter, collector) = IssueEmitter::new(source, source_map.clone(), None);
836 let handler = Handler::with_emitter(true, false, Box::new(emitter));
837
838 let supports_block_scoping = *compile_time_info
839 .environment()
840 .runtime_versions()
841 .supports_block_scoping()
842 .await?;
843
844 let span = tracing::trace_span!("async module handling");
846 async {
847 let top_level_await_span =
848 set_handler_and_globals(&handler, globals, || has_top_level_await(program));
849 let has_top_level_await = top_level_await_span.is_some();
850
851 if eval_context.is_esm(specified_type) {
852 let async_module = AsyncModule {
853 has_top_level_await,
854 import_externals,
855 }
856 .resolved_cell();
857 analysis.set_async_module(async_module);
858 } else if let Some(span) = top_level_await_span {
859 AnalyzeIssue::new(
860 IssueSeverity::Error,
861 source.ident(),
862 rcstr!("unexpected top level await"),
863 rcstr!("top level await is only supported in ESM modules."),
864 None,
865 Some(issue_source(source, span)),
866 )
867 .to_resolved()
868 .await?
869 .emit();
870 }
871 anyhow::Ok(())
872 }
873 .instrument(span)
874 .await?;
875
876 let arena = ThreadLocal::new();
879 let arena = &arena;
880 let mut var_graph = {
881 let _span = tracing::trace_span!("analyze variable values").entered();
882 let mut graph = None;
883 set_handler_and_globals(&handler, globals, || {
884 graph = Some(create_graph(
885 arena.get_or_default(),
886 program,
887 eval_context,
888 analyze_mode,
889 supports_block_scoping,
890 specified_type,
891 options.cjs_tree_shaking,
892 options.cjs_scope_hoisting,
893 ));
894 });
895 graph.unwrap()
896 };
897
898 let span = tracing::trace_span!("effects processing");
899 async {
900 analysis.adopt_ast_paths(take(&mut var_graph.ast_paths));
904 analysis.code_gens.extend(take(&mut var_graph.code_gens));
905 let effects = take(&mut var_graph.effects);
906 let require_binding_usage = take(&mut var_graph.require_usage);
908 analysis.cjs_static_exports = take(&mut var_graph.cjs_static_exports);
910 analysis.has_direct_eval = var_graph.has_direct_eval;
911 let compile_time_info_ref = compile_time_info.await?;
912
913 let mut analysis_state = AnalysisState {
914 arena,
915 handler: &handler,
916 module,
917 source,
918 origin,
919 origin_path: origin_path.clone(),
920 compile_time_info,
921 free_var_references_members: compile_time_info_ref
922 .free_var_references
923 .members()
924 .to_resolved()
925 .await?,
926 compile_time_info_ref,
927 var_graph,
928 allow_project_root_tracing: !source.ident().await?.path.is_in_node_modules(),
929 fun_args_values: Default::default(),
930 var_cache: Default::default(),
931 constants_cache: Default::default(),
932 first_import_meta: true,
933 first_webpack_exports_info: true,
934 module_fragments_enabled: options.module_fragments_enabled,
935 cjs_tree_shaking: options.cjs_tree_shaking,
936 cross_module_constants: options.cross_module_constants,
937 lazy_compilation: options.lazy_compilation,
938 import_externals: options.import_externals,
939 ignore_dynamic_requests: options.ignore_dynamic_requests,
940 url_rewrite_behavior: options.url_rewrite_behavior,
941 collect_affecting_sources: options.analyze_mode.trace_file_references,
942 tracing_only: !options.analyze_mode.is_codegen,
943 is_esm,
944 import_references,
945 imports: &eval_context.imports,
946 inner_assets,
947 };
948
949 fn unreachable_comment() -> RcStr {
950 rcstr!("TURBOPACK unreachable")
951 }
952
953 let mut queue_stack = Vec::with_capacity(effects.len());
958 add_effects(&mut queue_stack, effects);
959
960 while let Some(action) = queue_stack.pop() {
961 let effect = match action {
962 Action::LeaveScope(func_ident) => {
963 analysis_state.fun_args_values.get_mut().remove(&func_ident);
964 continue;
965 }
966 Action::Effect(effect) => effect,
967 };
968
969 match effect {
970 Effect::Unreachable { start_ast_path } => {
971 debug_assert!(
972 analyze_mode.is_codegen,
973 "unexpected Effect::Unreachable in tracing mode"
974 );
975
976 analysis.add_code_gen(RemovalCodeGen::new(
977 unreachable_comment(),
978 AstPathRange::StartAfter(analysis.intern_path(&start_ast_path)),
979 ));
980 }
981 Effect::Conditional {
982 mut condition,
983 kind,
984 ast_path: condition_ast_path,
985 span: _,
986 } => {
987 let condition_has_side_effects = condition.has_side_effects();
990
991 let condition = analysis_state
992 .link_value(take(&mut *condition), ImportAttributes::empty_ref())
993 .await?;
994
995 macro_rules! inactive {
996 ($block:ident) => {
997 if analyze_mode.is_codegen {
998 analysis.add_code_gen(RemovalCodeGen::new(
999 unreachable_comment(),
1000 $block.range.clone(),
1001 ));
1002 }
1003 };
1004 }
1005 macro_rules! condition {
1006 ($expr:expr) => {
1007 if analyze_mode.is_codegen && !condition_has_side_effects {
1008 analysis.add_code_gen(ConstantConditionCodeGen::new(
1009 $expr,
1010 analysis.intern_path(&condition_ast_path),
1011 ));
1012 }
1013 };
1014 }
1015 macro_rules! active {
1016 ($block:ident) => {
1017 add_effects(&mut queue_stack, BumpVec::from($block.effects))
1018 };
1019 }
1020 match BumpBox::into_inner(kind) {
1021 ConditionalKind::If { then } => match condition.is_truthy() {
1022 Some(true) => {
1023 condition!(ConstantConditionValue::Truthy);
1024 active!(then);
1025 }
1026 Some(false) => {
1027 condition!(ConstantConditionValue::Falsy);
1028 inactive!(then);
1029 }
1030 None => {
1031 active!(then);
1032 }
1033 },
1034 ConditionalKind::Else { r#else } => match condition.is_truthy() {
1035 Some(true) => {
1036 condition!(ConstantConditionValue::Truthy);
1037 inactive!(r#else);
1038 }
1039 Some(false) => {
1040 condition!(ConstantConditionValue::Falsy);
1041 active!(r#else);
1042 }
1043 None => {
1044 active!(r#else);
1045 }
1046 },
1047 ConditionalKind::IfElse { then, r#else }
1048 | ConditionalKind::Ternary { then, r#else } => {
1049 match condition.is_truthy() {
1050 Some(true) => {
1051 condition!(ConstantConditionValue::Truthy);
1052 active!(then);
1053 inactive!(r#else);
1054 }
1055 Some(false) => {
1056 condition!(ConstantConditionValue::Falsy);
1057 active!(r#else);
1058 inactive!(then);
1059 }
1060 None => {
1061 active!(then);
1062 active!(r#else);
1063 }
1064 }
1065 }
1066 ConditionalKind::IfElseMultiple { then, r#else } => {
1067 match condition.is_truthy() {
1068 Some(true) => {
1069 condition!(ConstantConditionValue::Truthy);
1070 for then in BumpVec::from(then) {
1071 active!(then);
1072 }
1073 for r#else in BumpVec::from(r#else) {
1074 inactive!(r#else);
1075 }
1076 }
1077 Some(false) => {
1078 condition!(ConstantConditionValue::Falsy);
1079 for then in BumpVec::from(then) {
1080 inactive!(then);
1081 }
1082 for r#else in BumpVec::from(r#else) {
1083 active!(r#else);
1084 }
1085 }
1086 None => {
1087 for then in BumpVec::from(then) {
1088 active!(then);
1089 }
1090 for r#else in BumpVec::from(r#else) {
1091 active!(r#else);
1092 }
1093 }
1094 }
1095 }
1096 ConditionalKind::And { expr } => match condition.is_truthy() {
1097 Some(true) => {
1098 condition!(ConstantConditionValue::Truthy);
1099 active!(expr);
1100 }
1101 Some(false) => {
1102 inactive!(expr);
1104 }
1105 None => {
1106 active!(expr);
1107 }
1108 },
1109 ConditionalKind::Or { expr } => match condition.is_truthy() {
1110 Some(true) => {
1111 inactive!(expr);
1113 }
1114 Some(false) => {
1115 condition!(ConstantConditionValue::Falsy);
1116 active!(expr);
1117 }
1118 None => {
1119 active!(expr);
1120 }
1121 },
1122 ConditionalKind::NullishCoalescing { expr } => {
1123 match condition.is_nullish() {
1124 Some(true) => {
1125 condition!(ConstantConditionValue::Nullish);
1126 active!(expr);
1127 }
1128 Some(false) => {
1129 inactive!(expr);
1130 }
1131 None => {
1132 active!(expr);
1133 }
1134 }
1135 }
1136 ConditionalKind::Labeled { body } => {
1137 active!(body);
1138 }
1139 }
1140 }
1141 Effect::Call {
1142 mut func,
1143 args,
1144 ast_path,
1145 span,
1146 in_try,
1147 new,
1148 } => {
1149 let func = analysis_state
1150 .link_value(take(&mut *func), eval_context.imports.get_attributes(span))
1151 .await?;
1152
1153 let call_usage = require_binding_usage
1154 .get(&span.lo)
1155 .cloned()
1156 .unwrap_or(ExportUsage::All);
1157
1158 let args = process_effect_args(args, &mut queue_stack);
1159 handle_call(
1160 &ast_path,
1161 span,
1162 func,
1163 args,
1164 &analysis_state,
1165 &mut analysis,
1166 in_try,
1167 new,
1168 eval_context.imports.get_attributes(span),
1169 call_usage,
1170 )
1171 .await?;
1172 }
1173 Effect::DynamicImport {
1174 args,
1175 ast_path,
1176 span,
1177 in_try,
1178 export_usage,
1179 } => {
1180 let args = process_effect_args(args, &mut queue_stack);
1181 handle_dynamic_import(
1182 &ast_path,
1183 span,
1184 args,
1185 &analysis_state,
1186 &mut analysis,
1187 in_try,
1188 eval_context.imports.get_attributes(span),
1189 export_usage,
1190 ValueLinkContext::Default,
1191 )
1192 .await?;
1193 }
1194 Effect::MemberCall {
1195 mut obj,
1196 mut prop,
1197 mut args,
1198 ast_path,
1199 span,
1200 in_try,
1201 new,
1202 } => {
1203 let func = analysis_state
1204 .link_value(
1205 JsValue::member(
1206 arena.get_or_default(),
1207 obj.clone_in(arena.get_or_default()),
1208 take(&mut *prop),
1209 ),
1210 eval_context.imports.get_attributes(span),
1211 )
1212 .await?;
1213
1214 if !new
1215 && matches!(
1216 func,
1217 JsValue::WellKnownFunction(
1218 WellKnownFunctionKind::ArrayFilter
1219 | WellKnownFunctionKind::ArrayForEach
1220 | WellKnownFunctionKind::ArrayMap
1221 )
1222 )
1223 && let [EffectArg::Closure(value, block)] = &mut args[..]
1224 && let JsValue::Array {
1225 items: ref mut values,
1226 mutable,
1227 ..
1228 } = analysis_state
1229 .link_value(take(&mut *obj), eval_context.imports.get_attributes(span))
1230 .await?
1231 {
1232 *value = analysis_state
1233 .link_value(take(value), ImportAttributes::empty_ref())
1234 .await?;
1235 if let JsValue::Function(_, func_ident, _) = value {
1236 let mut closure_arg = JsValue::alternatives(take(values));
1237 if mutable {
1238 closure_arg.add_unknown_mutations(arena.get_or_default(), true);
1239 }
1240 analysis_state.fun_args_values.get_mut().insert(
1241 *func_ident,
1242 BumpVec::from_iter_in(arena.get_or_default(), [closure_arg]),
1243 );
1244 queue_stack.push(Action::LeaveScope(*func_ident));
1245 add_effects(
1246 &mut queue_stack,
1247 BumpVec::from(replace(
1248 &mut block.effects,
1249 BumpVec::new().into_boxed_slice(),
1250 )),
1251 );
1252 continue;
1253 }
1254 }
1255
1256 let args = process_effect_args(args, &mut queue_stack);
1257 handle_call(
1258 &ast_path,
1259 span,
1260 func,
1261 args,
1262 &analysis_state,
1263 &mut analysis,
1264 in_try,
1265 new,
1266 eval_context.imports.get_attributes(span),
1267 ExportUsage::All,
1270 )
1271 .await?;
1272 }
1273 Effect::FreeVar {
1274 var,
1275 ast_path,
1276 span,
1277 } => {
1278 debug_assert!(
1279 analyze_mode.is_codegen,
1280 "unexpected Effect::FreeVar in tracing mode"
1281 );
1282
1283 let worker_placeholder = match &*var {
1286 "_TURBOPACK_WORKER_FORWARDED_GLOBALS_" => {
1287 Some(WorkerGlobalPlaceholder::ForwardedGlobals)
1288 }
1289 "_TURBOPACK_WORKER_BASE_PATH_" => Some(WorkerGlobalPlaceholder::BasePath),
1290 _ => None,
1291 };
1292 if let Some(placeholder) = worker_placeholder {
1293 analysis.add_code_gen(WorkerGlobalsReplacementCodeGen::new(
1294 placeholder,
1295 analysis.intern_path(&ast_path),
1296 ));
1297 continue;
1298 }
1299
1300 if options.enable_exports_info_inlining && var == "__webpack_exports_info__" {
1301 if analysis_state.first_webpack_exports_info {
1302 analysis_state.first_webpack_exports_info = false;
1303 analysis.add_code_gen(ExportsInfoBinding::new());
1304 }
1305 analysis.add_code_gen(ExportsInfoRef::new(analysis.intern_path(&ast_path)));
1306 continue;
1307 }
1308
1309 if !analysis_state
1311 .link_value(
1312 JsValue::FreeVar(var.clone()),
1313 eval_context.imports.get_attributes(span),
1314 )
1315 .await?
1316 .is_unknown()
1317 {
1318 handle_free_var(
1320 &ast_path,
1321 JsValue::FreeVar(var),
1322 span,
1323 &analysis_state,
1324 &mut analysis,
1325 )
1326 .await?;
1327 }
1328 }
1329 Effect::Member {
1330 mut obj,
1331 mut prop,
1332 ast_path,
1333 span,
1334 in_truthiness_context,
1335 } => {
1336 let obj =
1338 analysis_state.link_value(take(&mut *obj), ImportAttributes::empty_ref());
1339
1340 let prop = analysis_state
1341 .link_value(take(&mut *prop), ImportAttributes::empty_ref())
1342 .await?;
1343
1344 handle_membership(
1345 &ast_path,
1346 obj,
1347 prop,
1348 span,
1349 &analysis_state,
1350 &mut analysis,
1351 MembershipType::Member {
1352 in_truthiness_context,
1353 },
1354 )
1355 .await?;
1356 }
1357 Effect::DestructuredMember {
1358 mut obj,
1359 mut prop,
1360 span: _,
1361 } => {
1362 let prop = analysis_state
1365 .link_value(take(&mut *prop), ImportAttributes::empty_ref())
1366 .await?;
1367 if let Some(prop) = prop.as_str() {
1368 let obj = analysis_state
1372 .link_value(take(&mut *obj), ImportAttributes::empty_ref())
1373 .await?;
1374
1375 if obj
1376 .get_definable_name(Some(&analysis_state.var_graph))
1377 .iter()
1378 .flatten()
1379 .any(|(name, reassigned)| {
1380 !reassigned
1381 && matches!(
1382 name.0.as_slice(),
1383 [
1384 DefinableNameSegmentRef::Name("process"),
1385 DefinableNameSegmentRef::Name("env")
1386 ]
1387 )
1388 })
1389 {
1390 analysis.add_runtime_env_var_reference_read(RcStr::from(prop));
1391 }
1392 }
1393 }
1394 Effect::In {
1395 mut left,
1396 mut right,
1397 ast_path,
1398 span,
1399 } => {
1400 let right =
1402 analysis_state.link_value(take(&mut *right), ImportAttributes::empty_ref());
1403
1404 let left = analysis_state
1405 .link_value(take(&mut *left), ImportAttributes::empty_ref())
1406 .await?;
1407
1408 handle_membership(
1409 &ast_path,
1410 right,
1411 left,
1412 span,
1413 &analysis_state,
1414 &mut analysis,
1415 MembershipType::In,
1416 )
1417 .await?;
1418 }
1419 Effect::ImportedBinding {
1420 esm_reference_index,
1421 export,
1422 member,
1423 ast_path,
1424 span: _,
1425 } => {
1426 let Some(r) = import_references.get(esm_reference_index) else {
1427 continue;
1428 };
1429
1430 if options.cross_module_constants
1431 && (eval_context
1432 .imports
1433 .get_annotations(esm_reference_index)
1434 .and_then(|a| a.turbopack_constants())
1435 .unwrap_or_else(|| {
1436 export
1437 .as_ref()
1438 .is_some_and(|v| is_import_name_eligible_for_exports(v))
1439 }))
1440 && let JsValue::Constant(c) = analysis_state
1441 .link_value(
1442 eval_context.imports.get_import_for_idx(
1443 arena.get_or_default(),
1444 esm_reference_index,
1445 export.clone().map(Into::into),
1446 ),
1447 ImportAttributes::empty_ref(),
1448 )
1449 .await?
1450 && let Ok(c) = CompileTimeDefineValue::try_from(&c)
1451 {
1454 analysis.add_code_gen(ConstantValueCodeGen::new(
1457 c,
1458 analysis.intern_path(&ast_path),
1459 ));
1460 } else if let Some("__turbopack_module_id__") = export.as_deref() {
1461 let chunking_type = r.await?.chunking_type();
1462 analysis.add_reference_code_gen(
1463 EsmModuleIdAssetReference::new(*r, chunking_type),
1464 analysis.intern_path(&ast_path),
1465 ValueLinkContext::Default,
1466 )
1467 } else {
1468 if options.follow_reexports && !options.module_fragments_enabled {
1469 let original_reference = r.await?;
1472 if original_reference.export_name.is_none()
1473 && export.is_some()
1474 && let Some(export) = export
1475 {
1476 let named_reference = analysis
1479 .add_esm_reference_namespace_resolved(
1480 esm_reference_index,
1481 export.clone(),
1482 || {
1483 original_reference
1484 .rewrite_for_export(ModulePart::export(
1485 export.clone(),
1486 ))
1487 .resolved_cell()
1488 },
1489 );
1490 analysis.esm_bindings.add_keep_this(
1491 named_reference,
1492 Some(export),
1493 analysis.intern_path(&ast_path),
1494 );
1495 continue;
1496 }
1497
1498 if let Some(ModulePart::Export(export_name)) =
1499 &original_reference.export_name
1500 && let Some(member) = member
1501 {
1502 let narrowed_reference = analysis
1505 .add_esm_reference_namespace_resolved(
1506 esm_reference_index,
1507 member.clone(),
1508 || {
1509 original_reference
1510 .rewrite_for_export(ModulePart::partial_export(
1511 export_name.clone(),
1512 member.clone(),
1513 ))
1514 .resolved_cell()
1515 },
1516 );
1517 analysis.esm_bindings.add(
1518 narrowed_reference,
1519 export,
1520 analysis.intern_path(&ast_path),
1521 );
1522 continue;
1523 }
1524 }
1525
1526 analysis.add_esm_reference(esm_reference_index);
1527 analysis
1528 .esm_bindings
1529 .add(*r, export, analysis.intern_path(&ast_path));
1530 }
1531 }
1532 Effect::TypeOf {
1533 mut arg,
1534 ast_path,
1535 span,
1536 } => {
1537 debug_assert!(
1538 analyze_mode.is_codegen,
1539 "unexpected Effect::TypeOf in tracing mode"
1540 );
1541 let arg = analysis_state
1542 .link_value(take(&mut *arg), ImportAttributes::empty_ref())
1543 .await?;
1544 handle_typeof(&ast_path, arg, span, &analysis_state, &mut analysis).await?;
1545 }
1546 Effect::ImportMeta { ast_path, span: _ } => {
1547 debug_assert!(
1548 analyze_mode.is_codegen,
1549 "unexpected Effect::ImportMeta in tracing mode"
1550 );
1551 if analysis_state.first_import_meta {
1552 analysis_state.first_import_meta = false;
1553 let mode = analysis_state
1554 .compile_time_info_ref
1555 .defines
1556 .read_process_env(rcstr!("NODE_ENV"))
1557 .owned()
1558 .await?
1559 .unwrap_or_else(|| rcstr!("development"));
1560 let is_ssr = matches!(
1561 *analysis_state
1562 .compile_time_info_ref
1563 .environment
1564 .rendering()
1565 .await?,
1566 Rendering::Server
1567 );
1568 analysis.add_code_gen(ImportMetaBinding::new(
1569 source.ident().await?.path.clone(),
1570 analysis_state
1571 .compile_time_info_ref
1572 .hot_module_replacement_enabled,
1573 mode,
1574 analysis_state
1575 .compile_time_info_ref
1576 .import_meta_env_base_url
1577 .clone(),
1578 is_ssr,
1579 ));
1580 }
1581
1582 analysis.add_code_gen(ImportMetaRef::new(analysis.intern_path(&ast_path)));
1583 }
1584 }
1585 }
1586 anyhow::Ok(())
1587 }
1588 .instrument(span)
1589 .await?;
1590
1591 analysis.set_successful(true);
1592
1593 collector.emit(false).await?;
1594
1595 analysis
1596 .build(
1597 import_references,
1598 options.follow_reexports && !options.module_fragments_enabled,
1599 )
1600 .await
1601}
1602
1603#[turbo_tasks::function]
1604async fn compile_time_info_for_module_options(
1605 compile_time_info: Vc<CompileTimeInfo>,
1606 is_esm: bool,
1607 enable_typeof_window_inlining: Option<TypeofWindow>,
1608) -> Result<Vc<CompileTimeInfo>> {
1609 let compile_time_info = compile_time_info.await?;
1610 let free_var_references = compile_time_info.free_var_references;
1611 let defines = compile_time_info.defines;
1612
1613 let mut free_var_references = free_var_references.owned().await?;
1614 let mut defines = defines.owned().await?;
1615
1616 let (typeof_exports, typeof_module, typeof_this, require) = if is_esm {
1617 (
1618 rcstr!("undefined"),
1619 rcstr!("undefined"),
1620 rcstr!("undefined"),
1621 TURBOPACK_REQUIRE_STUB,
1622 )
1623 } else {
1624 (
1625 rcstr!("object"),
1626 rcstr!("object"),
1627 rcstr!("object"),
1628 TURBOPACK_REQUIRE_REAL,
1629 )
1630 };
1631 let typeofs: [(&[RcStr], RcStr); _] = [
1632 (&[rcstr!("import"), rcstr!("meta")], rcstr!("object")),
1633 (&[rcstr!("exports")], typeof_exports),
1634 (&[rcstr!("module")], typeof_module),
1635 (&[rcstr!("this")], typeof_this),
1636 (&[rcstr!("require")], rcstr!("function")),
1637 (&[rcstr!("__dirname")], rcstr!("string")),
1638 (&[rcstr!("__filename")], rcstr!("string")),
1639 (&[rcstr!("global")], rcstr!("object")),
1640 ];
1641 for (typeof_path, typeof_value) in typeofs {
1642 let name = typeof_path
1643 .iter()
1644 .map(|s| DefinableNameSegment::Name(s.clone()))
1645 .chain(std::iter::once(DefinableNameSegment::TypeOf))
1646 .collect::<Vec<_>>();
1647 free_var_references
1648 .entry(name.clone())
1649 .or_insert(typeof_value.clone().into());
1650 defines.entry(name).or_insert(typeof_value.into());
1651 }
1652
1653 free_var_references
1654 .entry(vec![DefinableNameSegment::Name(rcstr!("require"))])
1655 .or_insert(require.into());
1656 free_var_references
1657 .entry(vec![DefinableNameSegment::Name(rcstr!("__dirname"))])
1658 .or_insert(FreeVarReference::InputRelative(
1659 InputRelativeConstant::DirName,
1660 ));
1661 free_var_references
1662 .entry(vec![DefinableNameSegment::Name(rcstr!("__filename"))])
1663 .or_insert(FreeVarReference::InputRelative(
1664 InputRelativeConstant::FileName,
1665 ));
1666
1667 free_var_references
1670 .entry(vec![DefinableNameSegment::Name(rcstr!("global"))])
1671 .or_insert(TURBOPACK_GLOBAL.into());
1672
1673 free_var_references.extend(TURBOPACK_RUNTIME_FUNCTION_SHORTCUTS.into_iter().map(
1674 |(name, shortcut)| {
1675 (
1676 vec![DefinableNameSegment::Name(name.into())],
1677 shortcut.into(),
1678 )
1679 },
1680 ));
1681 free_var_references
1686 .entry(vec![DefinableNameSegment::Name(rcstr!("this"))])
1687 .or_insert(if is_esm {
1688 FreeVarReference::Value(CompileTimeDefineValue::Undefined)
1689 } else {
1690 TURBOPACK_EXPORTS.into()
1693 });
1694
1695 if let Some(enable_typeof_window_inlining) = enable_typeof_window_inlining {
1696 let value = match enable_typeof_window_inlining {
1697 TypeofWindow::Object => rcstr!("object"),
1698 TypeofWindow::Undefined => rcstr!("undefined"),
1699 };
1700 let window = rcstr!("window");
1701 free_var_references
1702 .entry(vec![
1703 DefinableNameSegment::Name(window.clone()),
1704 DefinableNameSegment::TypeOf,
1705 ])
1706 .or_insert(value.clone().into());
1707 defines
1708 .entry(vec![
1709 DefinableNameSegment::Name(window),
1710 DefinableNameSegment::TypeOf,
1711 ])
1712 .or_insert(value.into());
1713 }
1714
1715 Ok(CompileTimeInfo {
1716 environment: compile_time_info.environment,
1717 defines: CompileTimeDefines(defines).resolved_cell(),
1718 free_var_references: FreeVarReferences(free_var_references).resolved_cell(),
1719 hot_module_replacement_enabled: compile_time_info.hot_module_replacement_enabled,
1720 import_meta_env_base_url: compile_time_info.import_meta_env_base_url.clone(),
1721 }
1722 .cell())
1723}
1724
1725fn process_effect_args<'a>(
1729 args: BumpVec<'a, EffectArg<'a>>,
1730 queue_stack: &mut Vec<Action<'a>>,
1731) -> Vec<JsValue<'a>> {
1732 args.into_iter()
1733 .map(|effect_arg| match effect_arg {
1734 EffectArg::Value(value) => value,
1735 EffectArg::Closure(value, block) => {
1736 add_effects(
1737 queue_stack,
1738 BumpVec::from(BumpBox::into_inner(block).effects),
1739 );
1740 value
1741 }
1742 EffectArg::Spread => {
1743 JsValue::unknown_empty(true, rcstr!("spread is not supported yet"))
1744 }
1745 })
1746 .collect()
1747}
1748
1749async fn handle_call<'a>(
1750 ast_path: &[AstParentKind],
1751 span: Span,
1752 func: JsValue<'a>,
1753 unlinked_args: Vec<JsValue<'a>>,
1754 state: &AnalysisState<'a>,
1755 analysis: &mut AnalyzeEcmascriptModuleResultBuilder,
1756 in_try: bool,
1757 new: bool,
1758 attributes: &ImportAttributes,
1759 call_usage: ExportUsage,
1760) -> Result<()> {
1761 let &AnalysisState {
1762 handler,
1763 origin,
1764 module,
1765 source,
1766 compile_time_info,
1767 ignore_dynamic_requests,
1768 url_rewrite_behavior,
1769 collect_affecting_sources,
1770 tracing_only,
1771 ..
1772 } = state;
1773
1774 let linked_args_cache = OnceCell::new();
1776
1777 let linked_args = || {
1779 linked_args_cache.get_or_try_init(|| {
1780 unlinked_args
1781 .iter()
1782 .map(|arg| arg.clone_in(state.arena.get_or_default()))
1783 .map(|arg| state.link_value(arg, ImportAttributes::empty_ref()))
1784 .try_join()
1785 })
1786 };
1787
1788 match func {
1789 JsValue::Alternatives {
1790 total_nodes: _,
1791 values,
1792 logical_property: _,
1793 } => {
1794 for alt in values {
1795 if let JsValue::WellKnownFunction(wkf) = alt {
1796 handle_well_known_function_call(
1800 wkf,
1801 new,
1802 ValueLinkContext::InAlternative,
1803 &linked_args,
1804 handler,
1805 span,
1806 ignore_dynamic_requests,
1807 analysis,
1808 origin,
1809 ResolvedVc::upcast(module),
1810 compile_time_info,
1811 url_rewrite_behavior,
1812 source,
1813 ast_path,
1814 in_try,
1815 state,
1816 collect_affecting_sources,
1817 tracing_only,
1818 attributes,
1819 call_usage.clone(),
1820 )
1821 .await?;
1822 }
1823 }
1824 }
1825 JsValue::WellKnownFunction(wkf) => {
1826 handle_well_known_function_call(
1827 wkf,
1828 new,
1829 ValueLinkContext::Default,
1830 &linked_args,
1831 handler,
1832 span,
1833 ignore_dynamic_requests,
1834 analysis,
1835 origin,
1836 ResolvedVc::upcast(module),
1837 compile_time_info,
1838 url_rewrite_behavior,
1839 source,
1840 ast_path,
1841 in_try,
1842 state,
1843 collect_affecting_sources,
1844 tracing_only,
1845 attributes,
1846 call_usage,
1847 )
1848 .await?;
1849 }
1850 _ => {}
1851 }
1852
1853 Ok(())
1854}
1855
1856async fn handle_dynamic_import<'a>(
1857 ast_path: &[AstParentKind],
1858 span: Span,
1859 unlinked_args: Vec<JsValue<'a>>,
1860 state: &AnalysisState<'a>,
1861 analysis: &mut AnalyzeEcmascriptModuleResultBuilder,
1862 in_try: bool,
1863 attributes: &ImportAttributes,
1864 export_usage: ExportUsage,
1865 link_context: ValueLinkContext,
1866) -> Result<()> {
1867 if attributes.ignore {
1870 return Ok(());
1871 }
1872
1873 let &AnalysisState {
1874 handler,
1875 origin,
1876 source,
1877 ignore_dynamic_requests,
1878 lazy_compilation,
1879 ..
1880 } = state;
1881
1882 let error_mode = if attributes.optional {
1883 ResolveErrorMode::Ignore
1884 } else if in_try {
1885 ResolveErrorMode::Warn
1886 } else {
1887 ResolveErrorMode::Error
1888 };
1889
1890 let linked_args = unlinked_args
1891 .iter()
1892 .map(|arg| arg.clone_in(state.arena.get_or_default()))
1893 .map(|arg| state.link_value(arg, ImportAttributes::empty_ref()))
1894 .try_join()
1895 .await?;
1896
1897 handle_dynamic_import_with_linked_args(
1898 ast_path,
1899 span,
1900 &linked_args,
1901 handler,
1902 origin,
1903 source,
1904 &state.inner_assets,
1905 ignore_dynamic_requests,
1906 analysis,
1907 error_mode,
1908 state.import_externals,
1909 export_usage,
1910 link_context,
1911 lazy_compilation,
1912 )
1913 .await
1914}
1915
1916async fn handle_dynamic_import_with_linked_args(
1917 ast_path: &[AstParentKind],
1918 span: Span,
1919 linked_args: &[JsValue<'_>],
1920 handler: &Handler,
1921 origin: ResolvedVc<Box<dyn ResolveOrigin>>,
1922 source: ResolvedVc<Box<dyn Source>>,
1923 inner_assets: &Option<ReadRef<InnerAssets>>,
1924 ignore_dynamic_requests: bool,
1925 analysis: &mut AnalyzeEcmascriptModuleResultBuilder,
1926 error_mode: ResolveErrorMode,
1927 import_externals: bool,
1928 export_usage: ExportUsage,
1929 link_context: ValueLinkContext,
1930 lazy_compilation: bool,
1931) -> Result<()> {
1932 if linked_args.len() == 1 || linked_args.len() == 2 {
1933 let pat = js_value_to_pattern(&linked_args[0]);
1934 let options = linked_args.get(1);
1935 let import_annotations = options
1936 .and_then(|options| {
1937 if let JsValue::Object { parts, .. } = options {
1938 parts.iter().find_map(|part| {
1939 if let ObjectPart::KeyValue(
1940 JsValue::Constant(super::analyzer::ConstantValue::Str(key)),
1941 value,
1942 ) = part
1943 && key.as_str() == "with"
1944 {
1945 return Some(value);
1946 }
1947 None
1948 })
1949 } else {
1950 None
1951 }
1952 })
1953 .and_then(ImportAnnotations::parse_dynamic)
1954 .unwrap_or_default();
1955 if !pat.has_constant_parts() {
1956 let (args, hints) = JsValue::explain_args(linked_args, 10, 2);
1957 handler.span_warn_with_code(
1958 span,
1959 &format!("import({args}) is very dynamic{hints}",),
1960 DiagnosticId::Lint(
1961 errors::failed_to_analyze::ecmascript::DYNAMIC_IMPORT.to_string(),
1962 ),
1963 );
1964 if ignore_dynamic_requests {
1965 if link_context != ValueLinkContext::InAlternative {
1966 analysis.add_code_gen(DynamicExpression::new_promise(
1967 analysis.intern_path(ast_path),
1968 ));
1969 }
1970 return Ok(());
1971 }
1972 }
1973
1974 let resolve_override = if let Some(inner_assets) = &inner_assets
1975 && let Some(req) = pat.as_constant_string()
1976 && let Some(a) = inner_assets.get(req)
1977 {
1978 Some(*a)
1979 } else {
1980 None
1981 };
1982
1983 analysis.add_reference_code_gen(
1984 EsmAsyncAssetReference::new(
1985 origin,
1986 Request::parse(pat).to_resolved().await?,
1987 issue_source(source, span),
1988 import_annotations,
1989 error_mode,
1990 import_externals,
1991 export_usage,
1992 resolve_override,
1993 lazy_compilation,
1994 )
1995 .await?,
1996 analysis.intern_path(ast_path),
1997 link_context,
1998 );
1999 return Ok(());
2000 }
2001 let (args, hints) = JsValue::explain_args(linked_args, 10, 2);
2002 handler.span_warn_with_code(
2003 span,
2004 &format!("import({args}) is not statically analyze-able{hints}",),
2005 DiagnosticId::Error(errors::failed_to_analyze::ecmascript::DYNAMIC_IMPORT.to_string()),
2006 );
2007
2008 Ok(())
2009}
2010
2011#[derive(Copy, Clone, PartialEq, Eq)]
2012enum ValueLinkContext {
2013 Default,
2014 InAlternative,
2017}
2018
2019async fn handle_well_known_function_call<'a, 'l, F, Fut>(
2020 func: WellKnownFunctionKind<'a>,
2021 new: bool,
2022 link_context: ValueLinkContext,
2023 linked_args: &F,
2024 handler: &Handler,
2025 span: Span,
2026 ignore_dynamic_requests: bool,
2027 analysis: &mut AnalyzeEcmascriptModuleResultBuilder,
2028 origin: ResolvedVc<Box<dyn ResolveOrigin>>,
2029 parent_module: ResolvedVc<Box<dyn Module>>,
2030 compile_time_info: ResolvedVc<CompileTimeInfo>,
2031 url_rewrite_behavior: Option<UrlRewriteBehavior>,
2032 source: ResolvedVc<Box<dyn Source>>,
2033 ast_path: &[AstParentKind],
2034 in_try: bool,
2035 state: &AnalysisState<'a>,
2036 collect_affecting_sources: bool,
2037 tracing_only: bool,
2038 attributes: &ImportAttributes,
2039 call_usage: ExportUsage,
2040) -> Result<()>
2041where
2042 'a: 'l,
2043 F: Fn() -> Fut,
2044 Fut: Future<Output = Result<&'l Vec<JsValue<'a>>>>,
2045{
2046 fn explain_args(args: &[JsValue<'_>]) -> (String, String) {
2047 JsValue::explain_args(args, 10, 2)
2048 }
2049
2050 if link_context == ValueLinkContext::InAlternative
2051 && analysis.analyze_mode.is_codegen
2052 && !analysis.analyze_mode.trace_file_references
2053 {
2054 return Ok(());
2058 }
2059
2060 let error_mode = if attributes.optional {
2061 ResolveErrorMode::Ignore
2063 } else if in_try || link_context == ValueLinkContext::InAlternative {
2064 ResolveErrorMode::Warn
2067 } else {
2068 ResolveErrorMode::Error
2069 };
2070
2071 let get_traced_project_dirs = async || -> Result<(Option<FileSystemPath>, FileSystemPath)> {
2072 let fallback = source.ident().await?.path.parent();
2073 if let Some(cwd) = compile_time_info.environment().cwd().owned().await? {
2074 if state.allow_project_root_tracing {
2075 return Ok((None, cwd));
2076 }
2077 return Ok((Some(cwd), fallback));
2080 }
2081 Ok((None, fallback))
2082 };
2083
2084 let get_issue_source =
2085 || IssueSource::from_swc_offsets(source, span.lo.to_u32(), span.hi.to_u32());
2086 if new {
2087 match func {
2088 WellKnownFunctionKind::URLConstructor => {
2089 let args = linked_args().await?;
2090 if let [url, JsValue::Member(_, member_obj, member_prop)] = &args[..]
2091 && let JsValue::WellKnownObject(WellKnownObjectKind::ImportMeta) = &**member_obj
2092 && let JsValue::Constant(super::analyzer::ConstantValue::Str(meta_prop)) =
2093 &**member_prop
2094 && meta_prop.as_str() == "url"
2095 {
2096 let pat = js_value_to_pattern(url);
2097 if !pat.has_constant_parts() {
2098 let (args, hints) = explain_args(args);
2099 handler.span_warn_with_code(
2100 span,
2101 &format!("new URL({args}) is very dynamic{hints}",),
2102 DiagnosticId::Lint(
2103 errors::failed_to_analyze::ecmascript::NEW_URL_IMPORT_META
2104 .to_string(),
2105 ),
2106 );
2107 if ignore_dynamic_requests {
2108 return Ok(());
2109 }
2110 }
2111 let error_mode = if in_try {
2112 ResolveErrorMode::Warn
2113 } else {
2114 ResolveErrorMode::Error
2115 };
2116 analysis.add_reference_code_gen(
2117 UrlAssetReference::new(
2118 origin,
2119 Request::parse(pat).to_resolved().await?,
2120 *compile_time_info.environment().rendering().await?,
2121 issue_source(source, span),
2122 error_mode,
2123 url_rewrite_behavior.unwrap_or(UrlRewriteBehavior::Relative),
2124 ),
2125 analysis.intern_path(ast_path),
2126 link_context,
2127 );
2128 }
2129 return Ok(());
2130 }
2131 WellKnownFunctionKind::WorkerConstructor
2132 | WellKnownFunctionKind::SharedWorkerConstructor => {
2133 let args = linked_args().await?;
2134 if let Some(url @ JsValue::Url(_, JsValueUrlKind::Relative)) = args.first() {
2135 let (name, is_shared) = match func {
2136 WellKnownFunctionKind::WorkerConstructor => ("Worker", false),
2137 WellKnownFunctionKind::SharedWorkerConstructor => ("SharedWorker", true),
2138 _ => unreachable!(),
2139 };
2140 let pat = js_value_to_pattern(url);
2141 if !pat.has_constant_parts() {
2142 let (args, hints) = explain_args(args);
2143 handler.span_warn_with_code(
2144 span,
2145 &format!("new {name}({args}) is very dynamic{hints}",),
2146 DiagnosticId::Lint(
2147 errors::failed_to_analyze::ecmascript::NEW_WORKER.to_string(),
2148 ),
2149 );
2150 if ignore_dynamic_requests {
2151 return Ok(());
2152 }
2153 }
2154
2155 if *compile_time_info.environment().rendering().await? == Rendering::Client {
2156 let error_mode = if in_try {
2157 ResolveErrorMode::Warn
2158 } else {
2159 ResolveErrorMode::Error
2160 };
2161 analysis.add_reference_code_gen(
2162 WorkerAssetReference::new_web_worker(
2163 origin,
2164 Request::parse(pat).to_resolved().await?,
2165 issue_source(source, span),
2166 error_mode,
2167 tracing_only,
2168 is_shared,
2169 ),
2170 analysis.intern_path(ast_path),
2171 link_context,
2172 );
2173 }
2174
2175 return Ok(());
2176 }
2177 return Ok(());
2179 }
2180 WellKnownFunctionKind::NodeWorkerConstructor => {
2181 let args = linked_args().await?;
2182 if !args.is_empty() {
2183 let mut dynamic_warning: Option<&str> = None;
2187 if let Some(opts) = args.get(1) {
2188 match opts {
2189 JsValue::Object { parts, .. } => {
2190 let eval_value = parts.iter().find_map(|part| match part {
2191 ObjectPart::KeyValue(
2192 JsValue::Constant(JsConstantValue::Str(key)),
2193 value,
2194 ) if key.as_str() == "eval" => Some(value),
2195 _ => None,
2196 });
2197 if let Some(eval_value) = eval_value {
2198 match eval_value {
2199 JsValue::Constant(JsConstantValue::True) => {
2202 return Ok(());
2203 }
2204 JsValue::Constant(JsConstantValue::False) => {}
2207 _ => {
2209 dynamic_warning = Some("has a dynamic `eval` option");
2210 }
2211 }
2212 }
2213 }
2214 _ => {
2217 dynamic_warning = Some("has a dynamic options argument");
2218 }
2219 }
2220 }
2221 if let Some(warning) = dynamic_warning {
2222 let (args, hints) = explain_args(args);
2223 handler.span_warn_with_code(
2224 span,
2225 &format!("new Worker({args}) {warning}{hints}"),
2226 DiagnosticId::Lint(
2227 errors::failed_to_analyze::ecmascript::NEW_WORKER.to_string(),
2228 ),
2229 );
2230 if ignore_dynamic_requests {
2231 return Ok(());
2232 }
2233 }
2234
2235 let pat = js_value_to_pattern(&args[0]);
2236 if !pat.has_constant_parts() {
2237 let (args, hints) = explain_args(args);
2238 handler.span_warn_with_code(
2239 span,
2240 &format!("new Worker({args}) is very dynamic{hints}",),
2241 DiagnosticId::Lint(
2242 errors::failed_to_analyze::ecmascript::NEW_WORKER.to_string(),
2243 ),
2244 );
2245 if ignore_dynamic_requests {
2246 return Ok(());
2247 }
2248 }
2249
2250 let error_mode = if in_try {
2251 ResolveErrorMode::Warn
2252 } else {
2253 ResolveErrorMode::Error
2254 };
2255 let (static_files_only_context_dir, fallback_context_dir) = if matches!(
2258 args.first(),
2259 Some(JsValue::Url(_, JsValueUrlKind::Relative))
2260 ) {
2261 (None, origin.into_trait_ref().await?.origin_path().parent())
2262 } else {
2263 get_traced_project_dirs().await?
2264 };
2265 analysis.add_reference_code_gen(
2266 WorkerAssetReference::new_node_worker_thread(
2267 origin,
2268 static_files_only_context_dir,
2269 fallback_context_dir,
2270 Pattern::new(pat).to_resolved().await?,
2271 collect_affecting_sources,
2272 get_issue_source(),
2273 error_mode,
2274 tracing_only,
2275 ),
2276 analysis.intern_path(ast_path),
2277 link_context,
2278 );
2279
2280 return Ok(());
2281 }
2282 let (args, hints) = explain_args(args);
2283 handler.span_warn_with_code(
2284 span,
2285 &format!("new Worker({args}) is not statically analyze-able{hints}",),
2286 DiagnosticId::Error(
2287 errors::failed_to_analyze::ecmascript::NEW_WORKER.to_string(),
2288 ),
2289 );
2290 return Ok(());
2292 }
2293 _ => {}
2294 }
2295
2296 return Ok(());
2297 }
2298
2299 match func {
2300 WellKnownFunctionKind::Import => {
2301 let args = linked_args().await?;
2302 let export_usage = match &attributes.export_names {
2303 Some(names) if names.is_empty() => ExportUsage::Evaluation,
2304 Some(names) => ExportUsage::PartialNamespaceObject(names.clone()),
2305 None => ExportUsage::All,
2306 };
2307 handle_dynamic_import_with_linked_args(
2308 ast_path,
2309 span,
2310 args,
2311 handler,
2312 origin,
2313 source,
2314 &state.inner_assets,
2315 ignore_dynamic_requests,
2316 analysis,
2317 error_mode,
2318 state.import_externals,
2319 export_usage,
2320 link_context,
2321 state.lazy_compilation,
2322 )
2323 .await?;
2324 }
2325 WellKnownFunctionKind::Require => {
2326 let args = linked_args().await?;
2327 if args.len() == 1 {
2328 let pat = js_value_to_pattern(&args[0]);
2329 if !pat.has_constant_parts() {
2330 let (args, hints) = explain_args(args);
2331 handler.span_warn_with_code(
2332 span,
2333 &format!("require({args}) is very dynamic{hints}",),
2334 DiagnosticId::Lint(
2335 errors::failed_to_analyze::ecmascript::REQUIRE.to_string(),
2336 ),
2337 );
2338 if ignore_dynamic_requests {
2339 if link_context != ValueLinkContext::InAlternative {
2340 analysis.add_code_gen(DynamicExpression::new(
2341 analysis.intern_path(ast_path),
2342 ));
2343 }
2344 return Ok(());
2345 }
2346 }
2347
2348 let resolve_override = if let Some(inner_assets) = &state.inner_assets
2349 && let Some(req) = pat.as_constant_string()
2350 && let Some(a) = inner_assets.get(req)
2351 {
2352 Some(*a)
2353 } else {
2354 None
2355 };
2356
2357 analysis.add_reference_code_gen(
2358 CjsRequireAssetReference::new(
2359 origin,
2360 Request::parse(pat).to_resolved().await?,
2361 issue_source(source, span),
2362 error_mode,
2363 attributes.chunking_type,
2364 resolve_override,
2365 call_usage.clone(),
2366 state.cjs_tree_shaking,
2367 ),
2368 analysis.intern_path(ast_path),
2369 link_context,
2370 );
2371 return Ok(());
2372 }
2373 let (args, hints) = explain_args(args);
2374 handler.span_warn_with_code(
2375 span,
2376 &format!("require({args}) is not statically analyze-able{hints}",),
2377 DiagnosticId::Error(errors::failed_to_analyze::ecmascript::REQUIRE.to_string()),
2378 )
2379 }
2380 WellKnownFunctionKind::RequireFrom(rel) => {
2381 let args = linked_args().await?;
2382 if args.len() == 1 {
2383 let pat = js_value_to_pattern(&args[0]);
2384 if !pat.has_constant_parts() {
2385 let (args, hints) = explain_args(args);
2386 handler.span_warn_with_code(
2387 span,
2388 &format!("createRequire()({args}) is very dynamic{hints}",),
2389 DiagnosticId::Lint(
2390 errors::failed_to_analyze::ecmascript::REQUIRE.to_string(),
2391 ),
2392 );
2393 if ignore_dynamic_requests {
2394 if link_context != ValueLinkContext::InAlternative {
2395 analysis.add_code_gen(DynamicExpression::new(
2396 analysis.intern_path(ast_path),
2397 ));
2398 }
2399 return Ok(());
2400 }
2401 }
2402 let origin_ref = origin.into_trait_ref().await?;
2403 let origin = ResolvedVc::upcast(
2404 PlainResolveOrigin::new(
2405 *origin_ref.asset_context(),
2406 origin_ref
2407 .origin_path()
2408 .parent()
2409 .join(rel.as_str())?
2410 .join("_")?,
2411 )
2412 .to_resolved()
2413 .await?,
2414 );
2415
2416 analysis.add_reference_code_gen(
2417 CjsRequireAssetReference::new(
2418 origin,
2419 Request::parse(pat).to_resolved().await?,
2420 issue_source(source, span),
2421 error_mode,
2422 attributes.chunking_type,
2423 None,
2424 call_usage.clone(),
2425 state.cjs_tree_shaking,
2426 ),
2427 analysis.intern_path(ast_path),
2428 link_context,
2429 );
2430 return Ok(());
2431 }
2432 let (args, hints) = explain_args(args);
2433 handler.span_warn_with_code(
2434 span,
2435 &format!("createRequire()({args}) is not statically analyze-able{hints}",),
2436 DiagnosticId::Error(errors::failed_to_analyze::ecmascript::REQUIRE.to_string()),
2437 )
2438 }
2439 WellKnownFunctionKind::Define => {
2440 analyze_amd_define(
2441 source,
2442 analysis,
2443 origin,
2444 handler,
2445 span,
2446 ast_path,
2447 linked_args().await?,
2448 error_mode,
2449 )
2450 .await?;
2451 }
2452
2453 WellKnownFunctionKind::RequireResolve => {
2454 let args = linked_args().await?;
2455 if args.len() == 1 || args.len() == 2 {
2456 let pat = js_value_to_pattern(&args[0]);
2460 if !pat.has_constant_parts() {
2461 let (args, hints) = explain_args(args);
2462 handler.span_warn_with_code(
2463 span,
2464 &format!("require.resolve({args}) is very dynamic{hints}",),
2465 DiagnosticId::Lint(
2466 errors::failed_to_analyze::ecmascript::REQUIRE_RESOLVE.to_string(),
2467 ),
2468 );
2469 if ignore_dynamic_requests {
2470 if link_context != ValueLinkContext::InAlternative {
2471 analysis.add_code_gen(DynamicExpression::new(
2472 analysis.intern_path(ast_path),
2473 ));
2474 }
2475 return Ok(());
2476 }
2477 }
2478
2479 let resolve_override = if let Some(inner_assets) = &state.inner_assets
2480 && let Some(req) = pat.as_constant_string()
2481 && let Some(a) = inner_assets.get(req)
2482 {
2483 Some(*a)
2484 } else {
2485 None
2486 };
2487
2488 analysis.add_reference_code_gen(
2489 CjsRequireResolveAssetReference::new(
2490 origin,
2491 Request::parse(pat).to_resolved().await?,
2492 issue_source(source, span),
2493 error_mode,
2494 attributes.chunking_type,
2495 resolve_override,
2496 ),
2497 analysis.intern_path(ast_path),
2498 link_context,
2499 );
2500 return Ok(());
2501 }
2502 let (args, hints) = explain_args(args);
2503 handler.span_warn_with_code(
2504 span,
2505 &format!("require.resolve({args}) is not statically analyze-able{hints}",),
2506 DiagnosticId::Error(
2507 errors::failed_to_analyze::ecmascript::REQUIRE_RESOLVE.to_string(),
2508 ),
2509 )
2510 }
2511
2512 WellKnownFunctionKind::ImportMetaGlob => {
2513 let args = linked_args().await?;
2514 let Some(options) = parse_import_meta_glob(
2515 args,
2516 handler,
2517 span,
2518 DiagnosticId::Error(
2519 errors::failed_to_analyze::ecmascript::IMPORT_META_GLOB.to_string(),
2520 ),
2521 ) else {
2522 return Ok(());
2523 };
2524
2525 analysis.add_reference_code_gen(
2526 ImportMetaGlobAssetReference::new(
2527 origin,
2528 options.patterns,
2529 options.eager,
2530 state.lazy_compilation,
2531 options.import,
2532 options.query,
2533 options.base,
2534 options.case_sensitive,
2535 Some(issue_source(source, span)),
2536 error_mode,
2537 ),
2538 analysis.intern_path(ast_path),
2539 link_context,
2540 );
2541 }
2542
2543 WellKnownFunctionKind::RequireContext => {
2544 let args = linked_args().await?;
2545 let options = match parse_require_context(args) {
2546 Ok(options) => options,
2547 Err(err) => {
2548 let (args, hints) = explain_args(args);
2549 handler.span_err_with_code(
2550 span,
2551 &format!(
2552 "require.context({args}) is not statically analyze-able: {}{hints}",
2553 PrettyPrintError(&err)
2554 ),
2555 DiagnosticId::Error(
2556 errors::failed_to_analyze::ecmascript::REQUIRE_CONTEXT.to_string(),
2557 ),
2558 );
2559 return Ok(());
2560 }
2561 };
2562
2563 analysis.add_reference_code_gen(
2564 RequireContextAssetReference::new(
2565 source,
2566 origin,
2567 options.dir,
2568 options.include_subdirs,
2569 options.filter.cell(),
2570 Some(issue_source(source, span)),
2571 error_mode,
2572 )
2573 .await?,
2574 analysis.intern_path(ast_path),
2575 link_context,
2576 );
2577 }
2578
2579 WellKnownFunctionKind::FsReadMethod(name)
2580 if analysis.analyze_mode.trace_file_references =>
2581 {
2582 let args = linked_args().await?;
2583 if !args.is_empty() {
2584 let pat = js_value_to_pattern(&args[0]);
2585 if !pat.has_constant_parts() {
2586 let (args, hints) = explain_args(args);
2587 handler.span_warn_with_code(
2588 span,
2589 &format!("fs.{name}({args}) is very dynamic{hints}",),
2590 DiagnosticId::Lint(
2591 errors::failed_to_analyze::ecmascript::FS_METHOD.to_string(),
2592 ),
2593 );
2594 if ignore_dynamic_requests {
2595 return Ok(());
2596 }
2597 }
2598 let (static_files_only_context_dir, fallback_context_dir) =
2599 get_traced_project_dirs().await?;
2600 analysis.add_reference(
2601 FileSourceReference::new(
2602 static_files_only_context_dir,
2603 fallback_context_dir,
2604 Pattern::new(pat),
2605 collect_affecting_sources,
2606 get_issue_source(),
2607 format!("fs.{name}").into(),
2608 )
2609 .to_resolved()
2610 .await?,
2611 );
2612 return Ok(());
2613 }
2614 let (args, hints) = explain_args(args);
2615 handler.span_warn_with_code(
2616 span,
2617 &format!("fs.{name}({args}) is not statically analyze-able{hints}",),
2618 DiagnosticId::Error(errors::failed_to_analyze::ecmascript::FS_METHOD.to_string()),
2619 )
2620 }
2621 WellKnownFunctionKind::FsReadDir if analysis.analyze_mode.trace_file_references => {
2622 let args = linked_args().await?;
2623 if !args.is_empty() {
2624 let pat = js_value_to_pattern(&args[0]);
2625 if !pat.has_constant_parts() {
2626 let (args, hints) = explain_args(args);
2627 handler.span_warn_with_code(
2628 span,
2629 &format!("fs.readdir({args}) is very dynamic{hints}"),
2630 DiagnosticId::Lint(
2631 errors::failed_to_analyze::ecmascript::FS_METHOD.to_string(),
2632 ),
2633 );
2634 if ignore_dynamic_requests {
2635 return Ok(());
2636 }
2637 }
2638 let (static_files_only_context_dir, fallback_context_dir) =
2639 get_traced_project_dirs().await?;
2640 analysis.add_reference(
2641 DirAssetReference::new(
2642 static_files_only_context_dir,
2643 fallback_context_dir,
2644 Pattern::new(pat),
2645 get_issue_source(),
2646 rcstr!("fs.readdir"),
2647 )
2648 .to_resolved()
2649 .await?,
2650 );
2651 return Ok(());
2652 }
2653 let (args, hints) = explain_args(args);
2654 handler.span_warn_with_code(
2655 span,
2656 &format!("fs.readdir({args}) is not statically analyze-able{hints}"),
2657 DiagnosticId::Error(errors::failed_to_analyze::ecmascript::FS_METHOD.to_string()),
2658 )
2659 }
2660 WellKnownFunctionKind::PathResolve(..) if analysis.analyze_mode.trace_file_references => {
2661 let parent_path = origin.into_trait_ref().await?.origin_path().parent();
2662 let args = linked_args().await?;
2663
2664 let linked_func_call = state
2665 .link_value(
2666 JsValue::call_from_parts(
2667 state.arena.get_or_default(),
2668 JsValue::WellKnownFunction(WellKnownFunctionKind::PathResolve(
2669 state
2670 .arena
2671 .get_or_default()
2672 .alloc(parent_path.path.as_str().into()),
2673 )),
2674 BumpVec::from_iter_in(
2675 state.arena.get_or_default(),
2676 args.iter()
2677 .map(|a| a.clone_in(state.arena.get_or_default())),
2678 ),
2679 ),
2680 ImportAttributes::empty_ref(),
2681 )
2682 .await?;
2683
2684 let pat = js_value_to_pattern(&linked_func_call);
2685 if !pat.has_constant_parts() {
2686 let (args, hints) = explain_args(args);
2687 handler.span_warn_with_code(
2688 span,
2689 &format!("path.resolve({args}) is very dynamic{hints}",),
2690 DiagnosticId::Lint(
2691 errors::failed_to_analyze::ecmascript::PATH_METHOD.to_string(),
2692 ),
2693 );
2694 if ignore_dynamic_requests {
2695 return Ok(());
2696 }
2697 }
2698 let (static_files_only_context_dir, fallback_context_dir) =
2699 get_traced_project_dirs().await?;
2700 analysis.add_reference(
2701 DirAssetReference::new(
2702 static_files_only_context_dir,
2703 fallback_context_dir,
2704 Pattern::new(pat),
2705 get_issue_source(),
2706 rcstr!("path.resolve"),
2707 )
2708 .to_resolved()
2709 .await?,
2710 );
2711 return Ok(());
2712 }
2713 WellKnownFunctionKind::PathJoin if analysis.analyze_mode.trace_file_references => {
2714 if source
2716 .ident()
2717 .await?
2718 .path
2719 .path
2720 .contains("node_modules/node-gyp")
2721 {
2722 return Ok(());
2723 }
2724 let args = linked_args().await?;
2725 let linked_func_call = state
2726 .link_value(
2727 JsValue::call_from_parts(
2728 state.arena.get_or_default(),
2729 JsValue::WellKnownFunction(WellKnownFunctionKind::PathJoin),
2730 BumpVec::from_iter_in(
2731 state.arena.get_or_default(),
2732 args.iter()
2733 .map(|a| a.clone_in(state.arena.get_or_default())),
2734 ),
2735 ),
2736 ImportAttributes::empty_ref(),
2737 )
2738 .await?;
2739 let pat = js_value_to_pattern(&linked_func_call);
2740 if !pat.has_constant_parts() {
2741 let (args, hints) = explain_args(args);
2742 handler.span_warn_with_code(
2743 span,
2744 &format!("path.join({args}) is very dynamic{hints}",),
2745 DiagnosticId::Lint(
2746 errors::failed_to_analyze::ecmascript::PATH_METHOD.to_string(),
2747 ),
2748 );
2749 if ignore_dynamic_requests {
2750 return Ok(());
2751 }
2752 }
2753 let (static_files_only_context_dir, fallback_context_dir) =
2754 get_traced_project_dirs().await?;
2755 analysis.add_reference(
2756 DirAssetReference::new(
2757 static_files_only_context_dir,
2758 fallback_context_dir,
2759 Pattern::new(pat),
2760 get_issue_source(),
2761 rcstr!("path.join"),
2762 )
2763 .to_resolved()
2764 .await?,
2765 );
2766 return Ok(());
2767 }
2768 WellKnownFunctionKind::ChildProcessSpawnMethod(name)
2769 if analysis.analyze_mode.trace_file_references =>
2770 {
2771 let args = linked_args().await?;
2772
2773 if is_invoking_node_process_eval(args) {
2775 return Ok(());
2776 }
2777
2778 if !args.is_empty() {
2779 let mut show_dynamic_warning = false;
2780 let pat = js_value_to_pattern(&args[0]);
2781 if pat.is_match_ignore_dynamic("node") && args.len() >= 2 {
2782 let first_arg = JsValue::member(
2783 state.arena.get_or_default(),
2784 args[1].clone_in(state.arena.get_or_default()),
2785 0_f64.into(),
2786 );
2787 let first_arg = state
2788 .link_value(first_arg, ImportAttributes::empty_ref())
2789 .await?;
2790 let pat = js_value_to_pattern(&first_arg);
2791 let dynamic = !pat.has_constant_parts();
2792 if dynamic {
2793 show_dynamic_warning = true;
2794 }
2795 if !dynamic || !ignore_dynamic_requests {
2796 let error_mode = if in_try {
2797 ResolveErrorMode::Warn
2798 } else {
2799 ResolveErrorMode::Error
2800 };
2801 analysis.add_reference(
2802 CjsAssetReference::new(
2803 *origin,
2804 Request::parse(pat),
2805 issue_source(source, span),
2806 error_mode,
2807 )
2808 .to_resolved()
2809 .await?,
2810 );
2811 }
2812 }
2813 let dynamic = !pat.has_constant_parts();
2814 if dynamic {
2815 show_dynamic_warning = true;
2816 }
2817 if !dynamic || !ignore_dynamic_requests {
2818 let (static_files_only_context_dir, fallback_context_dir) =
2819 get_traced_project_dirs().await?;
2820 analysis.add_reference(
2821 FileSourceReference::new(
2822 static_files_only_context_dir,
2823 fallback_context_dir,
2824 Pattern::new(pat),
2825 collect_affecting_sources,
2826 IssueSource::from_swc_offsets(
2827 source,
2828 span.lo.to_u32(),
2829 span.hi.to_u32(),
2830 ),
2831 format!("child_process.{name}").into(),
2832 )
2833 .to_resolved()
2834 .await?,
2835 );
2836 }
2837 if show_dynamic_warning {
2838 let (args, hints) = explain_args(args);
2839 handler.span_warn_with_code(
2840 span,
2841 &format!("child_process.{name}({args}) is very dynamic{hints}",),
2842 DiagnosticId::Lint(
2843 errors::failed_to_analyze::ecmascript::CHILD_PROCESS_SPAWN.to_string(),
2844 ),
2845 );
2846 }
2847 return Ok(());
2848 }
2849 let (args, hints) = explain_args(args);
2850 handler.span_warn_with_code(
2851 span,
2852 &format!("child_process.{name}({args}) is not statically analyze-able{hints}",),
2853 DiagnosticId::Error(
2854 errors::failed_to_analyze::ecmascript::CHILD_PROCESS_SPAWN.to_string(),
2855 ),
2856 )
2857 }
2858 WellKnownFunctionKind::ChildProcessFork if analysis.analyze_mode.trace_file_references => {
2859 let args = linked_args().await?;
2860 if !args.is_empty() {
2861 let first_arg = &args[0];
2862 let pat = js_value_to_pattern(first_arg);
2863 if !pat.has_constant_parts() {
2864 let (args, hints) = explain_args(args);
2865 handler.span_warn_with_code(
2866 span,
2867 &format!("child_process.fork({args}) is very dynamic{hints}",),
2868 DiagnosticId::Lint(
2869 errors::failed_to_analyze::ecmascript::CHILD_PROCESS_SPAWN.to_string(),
2870 ),
2871 );
2872 if ignore_dynamic_requests {
2873 return Ok(());
2874 }
2875 }
2876 let error_mode = if in_try {
2877 ResolveErrorMode::Warn
2878 } else {
2879 ResolveErrorMode::Error
2880 };
2881 analysis.add_reference(
2882 CjsAssetReference::new(
2883 *origin,
2884 Request::parse(pat),
2885 issue_source(source, span),
2886 error_mode,
2887 )
2888 .to_resolved()
2889 .await?,
2890 );
2891 return Ok(());
2892 }
2893 let (args, hints) = explain_args(args);
2894 handler.span_warn_with_code(
2895 span,
2896 &format!("child_process.fork({args}) is not statically analyze-able{hints}",),
2897 DiagnosticId::Error(
2898 errors::failed_to_analyze::ecmascript::CHILD_PROCESS_SPAWN.to_string(),
2899 ),
2900 )
2901 }
2902 WellKnownFunctionKind::NodePreGypFind if analysis.analyze_mode.trace_file_references => {
2903 use turbopack_resolve::node_native_binding::NodePreGypConfigReference;
2904
2905 let args = linked_args().await?;
2906 if args.len() == 1 {
2907 let first_arg = &args[0];
2908 let pat = js_value_to_pattern(first_arg);
2909 if !pat.has_constant_parts() {
2910 let (args, hints) = explain_args(args);
2911 handler.span_warn_with_code(
2912 span,
2913 &format!("node-pre-gyp.find({args}) is very dynamic{hints}",),
2914 DiagnosticId::Lint(
2915 errors::failed_to_analyze::ecmascript::NODE_PRE_GYP_FIND.to_string(),
2916 ),
2917 );
2918 return Ok(());
2920 }
2921 analysis.add_reference(
2922 NodePreGypConfigReference::new(
2923 origin.into_trait_ref().await?.origin_path().parent(),
2924 Pattern::new(pat),
2925 compile_time_info.environment().compile_target(),
2926 collect_affecting_sources,
2927 )
2928 .to_resolved()
2929 .await?,
2930 );
2931 return Ok(());
2932 }
2933 let (args, hints) = explain_args(args);
2934 handler.span_warn_with_code(
2935 span,
2936 &format!(
2937 "require('@mapbox/node-pre-gyp').find({args}) is not statically \
2938 analyze-able{hints}",
2939 ),
2940 DiagnosticId::Error(
2941 errors::failed_to_analyze::ecmascript::NODE_PRE_GYP_FIND.to_string(),
2942 ),
2943 )
2944 }
2945 WellKnownFunctionKind::NodeGypBuild if analysis.analyze_mode.trace_file_references => {
2946 use turbopack_resolve::node_native_binding::NodeGypBuildReference;
2947
2948 let args = linked_args().await?;
2949 if args.len() == 1 {
2950 let first_arg = state
2951 .link_value(
2952 args[0].clone_in(state.arena.get_or_default()),
2953 ImportAttributes::empty_ref(),
2954 )
2955 .await?;
2956 if let Some(s) = first_arg.as_str() {
2957 let current_context = origin
2959 .into_trait_ref()
2960 .await?
2961 .origin_path()
2962 .root()
2963 .await?
2964 .join(s.trim_start_matches("/ROOT/"))?;
2965 analysis.add_reference(
2966 NodeGypBuildReference::new(
2967 current_context,
2968 collect_affecting_sources,
2969 compile_time_info.environment().compile_target(),
2970 )
2971 .to_resolved()
2972 .await?,
2973 );
2974 return Ok(());
2975 }
2976 }
2977 let (args, hints) = explain_args(args);
2978 handler.span_warn_with_code(
2979 span,
2980 &format!(
2981 "require('node-gyp-build')({args}) is not statically analyze-able{hints}",
2982 ),
2983 DiagnosticId::Error(
2984 errors::failed_to_analyze::ecmascript::NODE_GYP_BUILD.to_string(),
2985 ),
2986 )
2987 }
2988 WellKnownFunctionKind::NodeBindings if analysis.analyze_mode.trace_file_references => {
2989 use turbopack_resolve::node_native_binding::NodeBindingsReference;
2990
2991 let args = linked_args().await?;
2992 if args.len() == 1 {
2993 let first_arg = state
2994 .link_value(
2995 args[0].clone_in(state.arena.get_or_default()),
2996 ImportAttributes::empty_ref(),
2997 )
2998 .await?;
2999 if let Some(s) = first_arg.as_str() {
3000 analysis.add_reference(
3001 NodeBindingsReference::new(
3002 origin.into_trait_ref().await?.origin_path(),
3003 s.into(),
3004 collect_affecting_sources,
3005 )
3006 .to_resolved()
3007 .await?,
3008 );
3009 return Ok(());
3010 }
3011 }
3012 let (args, hints) = explain_args(args);
3013 handler.span_warn_with_code(
3014 span,
3015 &format!("require('bindings')({args}) is not statically analyze-able{hints}",),
3016 DiagnosticId::Error(
3017 errors::failed_to_analyze::ecmascript::NODE_BINDINGS.to_string(),
3018 ),
3019 )
3020 }
3021 WellKnownFunctionKind::NodeExpressSet if analysis.analyze_mode.trace_file_references => {
3022 let args = linked_args().await?;
3023 if args.len() == 2
3024 && let Some(s) = args.first().and_then(|arg| arg.as_str())
3025 {
3026 let pkg_or_dir = args.get(1).unwrap();
3027 let pat = js_value_to_pattern(pkg_or_dir);
3028 if !pat.has_constant_parts() {
3029 let (args, hints) = explain_args(args);
3030 handler.span_warn_with_code(
3031 span,
3032 &format!("require('express')().set({args}) is very dynamic{hints}",),
3033 DiagnosticId::Lint(
3034 errors::failed_to_analyze::ecmascript::NODE_EXPRESS.to_string(),
3035 ),
3036 );
3037 return Ok(());
3039 }
3040 match s {
3041 "views" => {
3042 if let Pattern::Constant(p) = &pat {
3043 let abs_pattern = if p.starts_with("/ROOT/") {
3044 pat
3045 } else {
3046 let linked_func_call = state
3047 .link_value(
3048 JsValue::call_from_iter(
3049 state.arena.get_or_default(),
3050 JsValue::WellKnownFunction(
3051 WellKnownFunctionKind::PathJoin,
3052 ),
3053 [
3054 JsValue::FreeVar(atom!("__dirname")),
3055 pkg_or_dir.clone_in(state.arena.get_or_default()),
3056 ],
3057 ),
3058 ImportAttributes::empty_ref(),
3059 )
3060 .await?;
3061 js_value_to_pattern(&linked_func_call)
3062 };
3063 let (static_files_only_context_dir, fallback_context_dir) =
3064 get_traced_project_dirs().await?;
3065 analysis.add_reference(
3066 DirAssetReference::new(
3067 static_files_only_context_dir,
3068 fallback_context_dir,
3069 Pattern::new(abs_pattern),
3070 get_issue_source(),
3071 rcstr!("express().set"),
3072 )
3073 .to_resolved()
3074 .await?,
3075 );
3076 return Ok(());
3077 }
3078 }
3079 "view engine" => {
3080 if let Some(pkg) = pkg_or_dir.as_str() {
3081 if pkg != "html" {
3082 let pat = js_value_to_pattern(pkg_or_dir);
3083 let error_mode = if in_try {
3084 ResolveErrorMode::Warn
3085 } else {
3086 ResolveErrorMode::Error
3087 };
3088 analysis.add_reference(
3089 CjsAssetReference::new(
3090 *origin,
3091 Request::parse(pat),
3092 issue_source(source, span),
3093 error_mode,
3094 )
3095 .to_resolved()
3096 .await?,
3097 );
3098 }
3099 return Ok(());
3100 }
3101 }
3102 _ => {}
3103 }
3104 }
3105 let (args, hints) = explain_args(args);
3106 handler.span_warn_with_code(
3107 span,
3108 &format!("require('express')().set({args}) is not statically analyze-able{hints}",),
3109 DiagnosticId::Error(
3110 errors::failed_to_analyze::ecmascript::NODE_EXPRESS.to_string(),
3111 ),
3112 )
3113 }
3114 WellKnownFunctionKind::NodeStrongGlobalizeSetRootDir
3115 if analysis.analyze_mode.trace_file_references =>
3116 {
3117 let args = linked_args().await?;
3118 if let Some(p) = args.first().and_then(|arg| arg.as_str()) {
3119 let abs_pattern = if p.starts_with("/ROOT/") {
3120 Pattern::Constant(format!("{p}/intl").into())
3121 } else {
3122 let linked_func_call = state
3123 .link_value(
3124 JsValue::call_from_iter(
3125 state.arena.get_or_default(),
3126 JsValue::WellKnownFunction(WellKnownFunctionKind::PathJoin),
3127 [
3128 JsValue::FreeVar(atom!("__dirname")),
3129 p.into(),
3130 atom!("intl").into(),
3131 ],
3132 ),
3133 ImportAttributes::empty_ref(),
3134 )
3135 .await?;
3136 js_value_to_pattern(&linked_func_call)
3137 };
3138 let (static_files_only_context_dir, fallback_context_dir) =
3139 get_traced_project_dirs().await?;
3140 analysis.add_reference(
3141 DirAssetReference::new(
3142 static_files_only_context_dir,
3143 fallback_context_dir,
3144 Pattern::new(abs_pattern),
3145 get_issue_source(),
3146 rcstr!("strong-globalize.SetRootDir"),
3147 )
3148 .to_resolved()
3149 .await?,
3150 );
3151 return Ok(());
3152 }
3153 let (args, hints) = explain_args(args);
3154 handler.span_warn_with_code(
3155 span,
3156 &format!(
3157 "require('strong-globalize').SetRootDir({args}) is not statically \
3158 analyze-able{hints}",
3159 ),
3160 DiagnosticId::Error(
3161 errors::failed_to_analyze::ecmascript::NODE_GYP_BUILD.to_string(),
3162 ),
3163 )
3164 }
3165 WellKnownFunctionKind::NodeResolveFrom if analysis.analyze_mode.trace_file_references => {
3166 let args = linked_args().await?;
3167 if args.len() == 2 && args.get(1).and_then(|arg| arg.as_str()).is_some() {
3168 let error_mode = if in_try {
3169 ResolveErrorMode::Warn
3170 } else {
3171 ResolveErrorMode::Error
3172 };
3173 analysis.add_reference(
3174 CjsAssetReference::new(
3175 *origin,
3176 Request::parse(js_value_to_pattern(&args[1])),
3177 issue_source(source, span),
3178 error_mode,
3179 )
3180 .to_resolved()
3181 .await?,
3182 );
3183 return Ok(());
3184 }
3185 let (args, hints) = explain_args(args);
3186 handler.span_warn_with_code(
3187 span,
3188 &format!("require('resolve-from')({args}) is not statically analyze-able{hints}",),
3189 DiagnosticId::Error(
3190 errors::failed_to_analyze::ecmascript::NODE_RESOLVE_FROM.to_string(),
3191 ),
3192 )
3193 }
3194 WellKnownFunctionKind::NodeProtobufLoad if analysis.analyze_mode.trace_file_references => {
3195 let args = linked_args().await?;
3196 if args.len() == 2
3197 && let Some(JsValue::Object { parts, .. }) = args.get(1)
3198 {
3199 let (static_files_only_context_dir, fallback_context_dir) =
3200 get_traced_project_dirs().await?;
3201 let resolved_dirs = parts
3202 .iter()
3203 .filter_map(|object_part| match object_part {
3204 ObjectPart::KeyValue(
3205 JsValue::Constant(key),
3206 JsValue::Array { items: dirs, .. },
3207 ) if key.as_str() == Some("includeDirs") => {
3208 Some(dirs.iter().filter_map(|dir| dir.as_str()))
3209 }
3210 _ => None,
3211 })
3212 .flatten()
3213 .map(|dir| {
3214 DirAssetReference::new(
3215 static_files_only_context_dir.clone(),
3216 fallback_context_dir.clone(),
3217 Pattern::new(Pattern::Constant(dir.into())),
3218 get_issue_source(),
3219 rcstr!("protobufjs.load"),
3220 )
3221 .to_resolved()
3222 })
3223 .join()
3224 .await;
3225
3226 for resolved_dir_ref in resolved_dirs {
3227 analysis.add_reference(resolved_dir_ref?);
3228 }
3229
3230 return Ok(());
3231 }
3232 let (args, hints) = explain_args(args);
3233 handler.span_warn_with_code(
3234 span,
3235 &format!(
3236 "require('@grpc/proto-loader').load({args}) is not statically \
3237 analyze-able{hints}",
3238 ),
3239 DiagnosticId::Error(
3240 errors::failed_to_analyze::ecmascript::NODE_PROTOBUF_LOADER.to_string(),
3241 ),
3242 )
3243 }
3244 kind @ (WellKnownFunctionKind::ModuleHotAccept
3245 | WellKnownFunctionKind::ModuleHotDecline) => {
3246 let is_accept = matches!(kind, WellKnownFunctionKind::ModuleHotAccept);
3247 let args = linked_args().await?;
3248 if let Some(first_arg) = args.first() {
3249 if let Some(dep_strings) = extract_hot_dep_strings(first_arg) {
3250 let mut references = Vec::new();
3251 let mut esm_references = Vec::new();
3252 for dep_str in &dep_strings {
3253 let request = Request::parse_string(dep_str.clone()).to_resolved().await?;
3254 let reference = ModuleHotReferenceAssetReference::new(
3255 *origin,
3256 *request,
3257 issue_source(source, span),
3258 error_mode,
3259 state.is_esm,
3260 )
3261 .to_resolved()
3262 .await?;
3263 analysis.add_reference(reference);
3264 references.push(reference);
3265
3266 let esm_ref = if is_accept {
3269 state
3270 .imports
3271 .references()
3272 .enumerate()
3273 .find(|(_, r)| r.module_path.to_string_lossy() == dep_str.as_str())
3274 .and_then(|(idx, _)| state.import_references.get(idx).copied())
3275 } else {
3276 None
3277 };
3278 esm_references.push(esm_ref);
3279 }
3280 analysis.add_code_gen(ModuleHotReferenceCodeGen::new(
3281 references,
3282 esm_references,
3283 analysis.intern_path(ast_path),
3284 ));
3285 } else if first_arg.is_unknown() {
3286 let (args_str, hints) = explain_args(args);
3287 let method = if is_accept { "accept" } else { "decline" };
3288 let error_code = if is_accept {
3289 errors::failed_to_analyze::ecmascript::MODULE_HOT_ACCEPT
3290 } else {
3291 errors::failed_to_analyze::ecmascript::MODULE_HOT_DECLINE
3292 };
3293 handler.span_warn_with_code(
3294 span,
3295 &format!(
3296 "module.hot.{method}({args_str}) is not statically analyzable{hints}",
3297 ),
3298 DiagnosticId::Error(error_code.to_string()),
3299 )
3300 }
3301 }
3302 }
3303 WellKnownFunctionKind::ServiceWorkerRegister => {
3304 let args = linked_args().await?;
3305 if let Some(url @ JsValue::Url(_, JsValueUrlKind::Relative)) = args.first() {
3306 let pat = js_value_to_pattern(url);
3307 if !pat.has_constant_parts() {
3308 let (args, hints) = explain_args(args);
3309 handler.span_warn_with_code(
3310 span,
3311 &format!(
3312 "navigator.serviceWorker.register({args}) is very dynamic{hints}",
3313 ),
3314 DiagnosticId::Lint(
3315 errors::failed_to_analyze::ecmascript::NEW_WORKER.to_string(),
3316 ),
3317 );
3318 if ignore_dynamic_requests {
3319 return Ok(());
3320 }
3321 }
3322
3323 if *compile_time_info.environment().rendering().await? == Rendering::Client {
3324 let error_mode = if in_try {
3325 ResolveErrorMode::Warn
3326 } else {
3327 ResolveErrorMode::Error
3328 };
3329 let scope: RcStr = match args.get(1) {
3332 Some(JsValue::Object { parts, .. }) => {
3333 let scope_value = parts.iter().find_map(|part| match part {
3334 ObjectPart::KeyValue(
3335 JsValue::Constant(JsConstantValue::Str(key)),
3336 value,
3337 ) if key.as_str() == "scope" => Some(value),
3338 _ => None,
3339 });
3340 match scope_value {
3341 None => rcstr!("/"),
3343 Some(JsValue::Constant(JsConstantValue::Str(value))) => {
3344 let scope = value.as_str();
3345 if !scope.starts_with('/') {
3350 let (args, hints) = explain_args(args);
3351 handler.span_warn_with_code(
3352 span,
3353 &format!(
3354 "navigator.serviceWorker.register({args}) has a \
3355 `scope` that does not start with `/`{hints}",
3356 ),
3357 DiagnosticId::Error(
3358 errors::failed_to_analyze::ecmascript::NEW_WORKER
3359 .to_string(),
3360 ),
3361 );
3362 return Ok(());
3363 }
3364 scope.into()
3365 }
3366 Some(_) => {
3369 let (args, hints) = explain_args(args);
3370 handler.span_warn_with_code(
3371 span,
3372 &format!(
3373 "navigator.serviceWorker.register({args}) has a \
3374 `scope` that is not statically analyze-able{hints}",
3375 ),
3376 DiagnosticId::Error(
3377 errors::failed_to_analyze::ecmascript::NEW_WORKER
3378 .to_string(),
3379 ),
3380 );
3381 return Ok(());
3382 }
3383 }
3384 }
3385 _ => rcstr!("/"),
3387 };
3388 analysis.add_reference_code_gen(
3389 ServiceWorkerAssetReference::new(
3390 origin,
3391 Request::parse(pat).to_resolved().await?,
3392 scope,
3393 issue_source(source, span),
3394 error_mode,
3395 ),
3396 analysis.intern_path(ast_path),
3397 link_context,
3398 );
3399 }
3400 }
3401 return Ok(());
3402 }
3403 WellKnownFunctionKind::TurbopackEmit => {
3404 let args = linked_args().await?;
3405 let (specifier, options) = match &args[..] {
3406 [
3407 JsValue::Constant(JsConstantValue::Str(specifier)),
3408 JsValue::Object { parts: options, .. },
3409 ] => (Some(specifier), Some(options)),
3410 [JsValue::Object { parts: options, .. }] => (None, Some(options)),
3411 _ => (None, None),
3412 };
3413
3414 if let Some(options) = options {
3415 let invalid_args = |key: &str| {
3416 let (args, hints) = explain_args(args);
3417 handler.span_warn_with_code(
3418 span,
3419 &format!(
3420 "Unsupported property \"{key}\" for __turbopack_emit__({args}) \
3421 call{hints}",
3422 ),
3423 DiagnosticId::Error(
3424 errors::failed_to_analyze::ecmascript::TURBOPACK_EMIT.to_string(),
3425 ),
3426 );
3427 Ok(())
3428 };
3429
3430 let mut namespace = None;
3431 let mut data = None;
3432 let mut emit_scope = None;
3433 let mut with = None;
3434 let mut exports = None;
3435
3436 for part in options {
3437 if let ObjectPart::KeyValue(
3438 JsValue::Constant(JsConstantValue::Str(key)),
3439 value,
3440 ) = part
3441 {
3442 match key.as_str() {
3443 "namespace" => namespace = Some(value),
3444 "data" => data = Some(value),
3445 "scope" => emit_scope = Some(value),
3446 "with" => with = Some(value),
3447 "exports" => exports = Some(value),
3448 v => return invalid_args(v),
3449 }
3450 }
3451 }
3452
3453 let Some(JsValue::Constant(JsConstantValue::Str(namespace))) = namespace else {
3454 return invalid_args("namespace");
3455 };
3456 let Some(annotations) = with.map_or_else(
3457 || Some(ImportAnnotations::default()),
3458 |v| ImportAnnotations::parse_dynamic(v),
3459 ) else {
3460 return invalid_args("with");
3461 };
3462 let emit_to_all_entries = match emit_scope {
3463 Some(JsValue::Constant(JsConstantValue::Str(emit_scope))) => {
3464 match emit_scope.as_str() {
3465 "app" => true,
3466 "entry" => false,
3467 _ => return invalid_args("scope"),
3468 }
3469 }
3470 None => false,
3471 _ => return invalid_args("scope"),
3472 };
3473 let exports = match exports {
3474 Some(JsValue::Constant(JsConstantValue::Str(export))) => {
3475 ExportUsage::Named(export.as_rcstr())
3476 }
3477 Some(JsValue::Array { items, .. }) => {
3478 let mut result = vec![];
3479 for item in items {
3480 if let JsValue::Constant(JsConstantValue::Str(export)) = item {
3481 result.push(export.as_rcstr());
3482 } else {
3483 return invalid_args("exports");
3484 }
3485 }
3486 match result.len() {
3487 0 => ExportUsage::Evaluation,
3488 1 => ExportUsage::Named(result.into_iter().next().unwrap()),
3489 _ => ExportUsage::PartialNamespaceObject(result.into()),
3490 }
3491 }
3492 None => ExportUsage::All,
3493 _ => return invalid_args("exports"),
3494 };
3495
3496 analysis.add_reference_code_gen(
3497 EmitReference::new(
3498 origin,
3499 Request::parse_string(
3500 specifier
3501 .context("Data-only emit is currently not implemented")?
3503 .as_rcstr(),
3504 )
3505 .to_resolved()
3506 .await?,
3507 issue_source(source, span),
3508 annotations,
3509 ResolveErrorMode::Error,
3510 exports,
3511 namespace.as_rcstr(),
3512 match data {
3513 Some(value) => match CompileTimeDefineValue::try_from(value) {
3514 Ok(v) => Some(v),
3515 Err(e) => {
3516 bail!(
3517 "The data for __turbopack_emit__ is not a compile-time \
3518 constant: {value:?}: {e}"
3519 );
3520 }
3521 },
3522 None => None,
3523 },
3524 emit_to_all_entries,
3525 ),
3526 analysis.intern_path(ast_path),
3527 link_context,
3528 );
3529 return Ok(());
3530 }
3531 let (args, hints) = explain_args(args);
3532 handler.span_warn_with_code(
3533 span,
3534 &format!("Unsupported arguments for __turbopack_emit__({args}) call{hints}",),
3535 DiagnosticId::Error(
3536 errors::failed_to_analyze::ecmascript::TURBOPACK_EMIT.to_string(),
3537 ),
3538 )
3539 }
3540 WellKnownFunctionKind::TurbopackCollect => {
3541 let args = linked_args().await?;
3542 if let [JsValue::Object { parts: options, .. }] = &args[..] {
3543 let invalid_args = |key: &str| {
3544 let (args, hints) = explain_args(args);
3545 handler.span_warn_with_code(
3546 span,
3547 &format!(
3548 "Unsupported property \"{key}\" for __turbopack_collect__({args}) \
3549 call{hints}",
3550 ),
3551 DiagnosticId::Error(
3552 errors::failed_to_analyze::ecmascript::TURBOPACK_COLLECT.to_string(),
3553 ),
3554 );
3555 Ok(())
3556 };
3557
3558 let mut namespace = None;
3559
3560 for part in options {
3561 if let ObjectPart::KeyValue(
3562 JsValue::Constant(JsConstantValue::Str(key)),
3563 value,
3564 ) = part
3565 {
3566 match key.as_str() {
3567 "namespace" => namespace = Some(value),
3568 v => return invalid_args(v),
3569 }
3570 }
3571 }
3572
3573 let Some(JsValue::Constant(JsConstantValue::Str(namespace))) = namespace else {
3574 return invalid_args("namespace");
3575 };
3576
3577 analysis.add_reference_code_gen(
3578 CollectReference::new(origin, parent_module, namespace.as_rcstr()),
3579 analysis.intern_path(ast_path),
3580 link_context,
3581 );
3582 return Ok(());
3583 }
3584 let (args, hints) = explain_args(args);
3585 handler.span_warn_with_code(
3586 span,
3587 &format!("Unsupported arguments for __turbopack_collect__({args}) call{hints}",),
3588 DiagnosticId::Error(
3589 errors::failed_to_analyze::ecmascript::TURBOPACK_COLLECT.to_string(),
3590 ),
3591 )
3592 }
3593 _ => {}
3594 };
3595 Ok(())
3596}
3597
3598fn extract_hot_dep_strings(arg: &JsValue<'_>) -> Option<Vec<RcStr>> {
3602 if let Some(s) = arg.as_str() {
3604 return Some(vec![s.into()]);
3605 }
3606 if let JsValue::Array { items, .. } = arg {
3608 let mut deps = Vec::new();
3609 for item in items {
3610 deps.push(item.as_str()?.into());
3611 }
3612 return Some(deps);
3613 }
3614 None
3615}
3616
3617enum MembershipType {
3618 Member { in_truthiness_context: bool },
3619 In,
3620}
3621
3622async fn handle_membership<'a>(
3623 ast_path: &[AstParentKind],
3624 link_obj: impl Future<Output = Result<JsValue<'a>>> + Send + Sync,
3625 prop: JsValue<'a>,
3626 span: Span,
3627 state: &AnalysisState<'a>,
3628 analysis: &mut AnalyzeEcmascriptModuleResultBuilder,
3629 ty: MembershipType,
3630) -> Result<()> {
3631 if let Some(prop) = prop.as_str() {
3632 let has_member = state.free_var_references_members.contains_key(prop).await?;
3633 let is_prop_cache = prop == "cache";
3634
3635 let obj = link_obj.await?;
3636 let obj_name = obj.get_definable_name(Some(&state.var_graph));
3637
3638 if let [obj_name] = &*obj_name {
3639 if has_member && let Some((mut name, false)) = obj_name.clone() {
3641 name.0.push(DefinableNameSegmentRef::Name(prop));
3642 match ty {
3643 MembershipType::Member { .. } => {
3644 if let Some(value) = state
3645 .compile_time_info_ref
3646 .free_var_references
3647 .get(&name)
3648 .await?
3649 {
3650 handle_free_var_reference(ast_path, &value, span, state, analysis)
3652 .await?;
3653 return Ok(());
3654 }
3655 }
3656 MembershipType::In => {
3657 if state
3658 .compile_time_info_ref
3659 .free_var_references
3660 .get(&name)
3661 .await?
3662 .is_some()
3663 {
3664 analysis.add_code_gen(ConstantValueCodeGen::new(
3665 CompileTimeDefineValue::Bool(true),
3666 analysis.intern_path(ast_path),
3667 ));
3668 return Ok(());
3669 }
3670 }
3671 }
3672 }
3673 if is_prop_cache
3674 && let JsValue::WellKnownFunction(WellKnownFunctionKind::Require) = &obj
3675 {
3676 match ty {
3677 MembershipType::Member { .. } => {
3678 if analysis.analyze_mode.is_codegen {
3680 handle_free_var_reference(
3681 ast_path,
3682 &FreeVarReference::EcmaScriptModule {
3685 request: rcstr!("@turbopack/module-cache"),
3686 lookup_path: None,
3687 export: Some(rcstr!("cache")),
3688 },
3689 span,
3690 state,
3691 analysis,
3692 )
3693 .await?;
3694 }
3695 }
3696 MembershipType::In => {
3697 analysis.add_code_gen(ConstantValueCodeGen::new(
3698 CompileTimeDefineValue::Bool(true),
3699 analysis.intern_path(ast_path),
3700 ));
3701 }
3702 }
3703 return Ok(());
3704 }
3705 }
3706
3707 if obj_name.iter().flatten().any(|(name, reassigned)| {
3709 !reassigned
3710 && matches!(
3711 name.0.as_slice(),
3712 [
3713 DefinableNameSegmentRef::Name("process"),
3714 DefinableNameSegmentRef::Name("env")
3715 ]
3716 )
3717 }) {
3718 match ty {
3719 MembershipType::In => {
3720 analysis.add_runtime_env_var_reference_existence(RcStr::from(prop));
3721 }
3722 MembershipType::Member {
3723 in_truthiness_context,
3724 } => {
3725 if in_truthiness_context {
3726 analysis.add_runtime_env_var_reference_existence(RcStr::from(prop));
3727 } else {
3728 analysis.add_runtime_env_var_reference_read(RcStr::from(prop));
3729 }
3730 }
3731 }
3732 return Ok(());
3733 }
3734 }
3735 Ok(())
3736}
3737
3738async fn handle_typeof<'a>(
3739 ast_path: &[AstParentKind],
3740 arg: JsValue<'a>,
3741 span: Span,
3742 state: &AnalysisState<'a>,
3743 analysis: &mut AnalyzeEcmascriptModuleResultBuilder,
3744) -> Result<()> {
3745 let arg_name = arg.get_definable_name(Some(&state.var_graph));
3746 if arg_name.len() == 1
3747 && let Some((mut name, false)) = arg_name.into_iter().next().unwrap()
3748 {
3749 name.0.push(DefinableNameSegmentRef::TypeOf);
3751 if let Some(value) = state
3752 .compile_time_info_ref
3753 .free_var_references
3754 .get(&name)
3755 .await?
3756 {
3757 handle_free_var_reference(ast_path, &value, span, state, analysis).await?;
3758 return Ok(());
3759 }
3760 }
3761
3762 Ok(())
3763}
3764
3765async fn handle_free_var<'a>(
3766 ast_path: &[AstParentKind],
3767 var: JsValue<'a>,
3768 span: Span,
3769 state: &AnalysisState<'a>,
3770 analysis: &mut AnalyzeEcmascriptModuleResultBuilder,
3771) -> Result<()> {
3772 if let [Some((name, _))] = &*var.get_definable_name(None)
3774 && let Some(value) = state
3775 .compile_time_info_ref
3776 .free_var_references
3777 .get(name)
3778 .await?
3779 {
3780 handle_free_var_reference(ast_path, &value, span, state, analysis).await?;
3781 return Ok(());
3782 }
3783
3784 Ok(())
3785}
3786
3787async fn handle_free_var_reference(
3788 ast_path: &[AstParentKind],
3789 value: &FreeVarReference,
3790 span: Span,
3791 state: &AnalysisState<'_>,
3792 analysis: &mut AnalyzeEcmascriptModuleResultBuilder,
3793) -> Result<bool> {
3794 if matches!(
3796 ast_path,
3797 [
3799 ..,
3800 AstParentKind::AssignExpr(AssignExprField::Left),
3801 AstParentKind::AssignTarget(AssignTargetField::Simple),
3802 AstParentKind::SimpleAssignTarget(SimpleAssignTargetField::Member),
3803 ] |
3804 [
3806 ..,
3807 AstParentKind::AssignExpr(AssignExprField::Left),
3808 AstParentKind::AssignTarget(AssignTargetField::Simple),
3809 AstParentKind::SimpleAssignTarget(SimpleAssignTargetField::Ident),
3810 AstParentKind::BindingIdent(BindingIdentField::Id),
3811 ]
3812 ) {
3813 return Ok(false);
3814 }
3815
3816 match value {
3817 FreeVarReference::Value(value) => {
3818 analysis.add_code_gen(ConstantValueCodeGen::new(
3819 value.clone(),
3820 analysis.intern_path(ast_path),
3821 ));
3822 }
3823 FreeVarReference::Ident(value) => {
3824 analysis.add_code_gen(IdentReplacement::new(
3825 value.clone(),
3826 analysis.intern_path(ast_path),
3827 ));
3828 }
3829 FreeVarReference::Member(key, value) => {
3830 analysis.add_code_gen(MemberReplacement::new(
3831 key.clone(),
3832 value.clone(),
3833 analysis.intern_path(ast_path),
3834 ));
3835 }
3836 FreeVarReference::EcmaScriptModule {
3837 request,
3838 lookup_path,
3839 export,
3840 } => {
3841 let esm_reference = analysis
3842 .add_esm_reference_free_var(request.clone(), async || {
3843 Ok(EsmAssetReference::new_pure(
3848 state.module,
3849 if let Some(lookup_path) = lookup_path {
3850 ResolvedVc::upcast(
3851 PlainResolveOrigin::new(
3852 *state.origin.into_trait_ref().await?.asset_context(),
3853 lookup_path.clone(),
3854 )
3855 .to_resolved()
3856 .await?,
3857 )
3858 } else {
3859 state.origin
3860 },
3861 request.clone(),
3862 EsmAssetReferenceOptions {
3863 issue_source: IssueSource::from_swc_offsets(
3864 state.source,
3865 span.lo.to_u32(),
3866 span.hi.to_u32(),
3867 ),
3868 annotations: Default::default(),
3869 export_name: export.clone().map(ModulePart::export),
3870 import_usage: ImportUsage::TopLevel,
3873 import_externals: state.import_externals,
3874 module_fragments_enabled: state.module_fragments_enabled,
3875 export_usage_passthrough: None,
3876 resolve_override: None,
3877 },
3878 )
3879 .await?
3880 .resolved_cell())
3881 })
3882 .await?;
3883
3884 analysis.esm_bindings.add(
3885 esm_reference,
3886 export.clone(),
3887 analysis.intern_path(ast_path),
3888 );
3889 }
3890 FreeVarReference::InputRelative(kind) => {
3891 let source_path = (*state.source).ident().await?.path.clone();
3892 let source_path = match kind {
3893 InputRelativeConstant::DirName => source_path.parent(),
3894 InputRelativeConstant::FileName => source_path,
3895 };
3896 analysis.add_code_gen(ConstantValueCodeGen::new(
3897 as_abs_path(source_path).into(),
3898 analysis.intern_path(ast_path),
3899 ));
3900 }
3901 FreeVarReference::ReportUsage {
3902 message,
3903 severity,
3904 inner,
3905 } => {
3906 state.handler.emit_with_code(
3907 &span.into(),
3908 message,
3909 DiagnosticId::Error(
3910 errors::failed_to_analyze::ecmascript::FREE_VAR_REFERENCE.to_string(),
3911 ),
3912 match severity {
3913 IssueSeverity::Bug => Level::Bug,
3914 IssueSeverity::Fatal => Level::Fatal,
3915 IssueSeverity::Error => Level::Error,
3916 IssueSeverity::Warning => Level::Warning,
3917 IssueSeverity::Hint => Level::Help,
3918 IssueSeverity::Info | IssueSeverity::Note => Level::Note,
3919 IssueSeverity::Suggestion => Level::Cancelled,
3920 },
3921 );
3922
3923 if let Some(inner) = inner {
3924 return Box::pin(handle_free_var_reference(
3925 ast_path, inner, span, state, analysis,
3926 ))
3927 .await;
3928 }
3929 }
3930 }
3931 Ok(true)
3932}
3933
3934fn issue_source(source: ResolvedVc<Box<dyn Source>>, span: Span) -> IssueSource {
3935 IssueSource::from_swc_offsets(source, span.lo.to_u32(), span.hi.to_u32())
3936}
3937
3938async fn analyze_amd_define(
3939 source: ResolvedVc<Box<dyn Source>>,
3940 analysis: &mut AnalyzeEcmascriptModuleResultBuilder,
3941 origin: ResolvedVc<Box<dyn ResolveOrigin>>,
3942 handler: &Handler,
3943 span: Span,
3944 ast_path: &[AstParentKind],
3945 args: &[JsValue<'_>],
3946 error_mode: ResolveErrorMode,
3947) -> Result<()> {
3948 match args {
3949 [JsValue::Constant(id), JsValue::Array { items: deps, .. }, _] if id.as_str().is_some() => {
3950 analyze_amd_define_with_deps(
3951 source,
3952 analysis,
3953 origin,
3954 handler,
3955 span,
3956 ast_path,
3957 id.as_str(),
3958 deps,
3959 error_mode,
3960 )
3961 .await?;
3962 }
3963 [JsValue::Array { items: deps, .. }, _] => {
3964 analyze_amd_define_with_deps(
3965 source, analysis, origin, handler, span, ast_path, None, deps, error_mode,
3966 )
3967 .await?;
3968 }
3969 [JsValue::Constant(id), JsValue::Function(..)] if id.as_str().is_some() => {
3970 analysis.add_code_gen(AmdDefineWithDependenciesCodeGen::new(
3971 vec![
3972 AmdDefineDependencyElement::Require,
3973 AmdDefineDependencyElement::Exports,
3974 AmdDefineDependencyElement::Module,
3975 ],
3976 origin,
3977 analysis.intern_path(ast_path),
3978 AmdDefineFactoryType::Function,
3979 issue_source(source, span),
3980 error_mode,
3981 ));
3982 }
3983 [JsValue::Constant(id), _] if id.as_str().is_some() => {
3984 analysis.add_code_gen(AmdDefineWithDependenciesCodeGen::new(
3985 vec![
3986 AmdDefineDependencyElement::Require,
3987 AmdDefineDependencyElement::Exports,
3988 AmdDefineDependencyElement::Module,
3989 ],
3990 origin,
3991 analysis.intern_path(ast_path),
3992 AmdDefineFactoryType::Unknown,
3993 issue_source(source, span),
3994 error_mode,
3995 ));
3996 }
3997 [JsValue::Function(..)] => {
3998 analysis.add_code_gen(AmdDefineWithDependenciesCodeGen::new(
3999 vec![
4000 AmdDefineDependencyElement::Require,
4001 AmdDefineDependencyElement::Exports,
4002 AmdDefineDependencyElement::Module,
4003 ],
4004 origin,
4005 analysis.intern_path(ast_path),
4006 AmdDefineFactoryType::Function,
4007 issue_source(source, span),
4008 error_mode,
4009 ));
4010 }
4011 [JsValue::Object { .. }] => {
4012 analysis.add_code_gen(AmdDefineWithDependenciesCodeGen::new(
4013 vec![],
4014 origin,
4015 analysis.intern_path(ast_path),
4016 AmdDefineFactoryType::Value,
4017 issue_source(source, span),
4018 error_mode,
4019 ));
4020 }
4021 [_] => {
4022 analysis.add_code_gen(AmdDefineWithDependenciesCodeGen::new(
4023 vec![
4024 AmdDefineDependencyElement::Require,
4025 AmdDefineDependencyElement::Exports,
4026 AmdDefineDependencyElement::Module,
4027 ],
4028 origin,
4029 analysis.intern_path(ast_path),
4030 AmdDefineFactoryType::Unknown,
4031 issue_source(source, span),
4032 error_mode,
4033 ));
4034 }
4035 _ => {
4036 handler.span_err_with_code(
4037 span,
4038 "unsupported AMD define() form",
4039 DiagnosticId::Error(errors::failed_to_analyze::ecmascript::AMD_DEFINE.to_string()),
4040 );
4041 }
4042 }
4043
4044 Ok(())
4045}
4046
4047async fn analyze_amd_define_with_deps(
4048 source: ResolvedVc<Box<dyn Source>>,
4049 analysis: &mut AnalyzeEcmascriptModuleResultBuilder,
4050 origin: ResolvedVc<Box<dyn ResolveOrigin>>,
4051 handler: &Handler,
4052 span: Span,
4053 ast_path: &[AstParentKind],
4054 id: Option<&str>,
4055 deps: &[JsValue<'_>],
4056 error_mode: ResolveErrorMode,
4057) -> Result<()> {
4058 let mut requests = Vec::new();
4059 for dep in deps {
4060 if let Some(dep) = dep.as_str() {
4061 match dep {
4062 "exports" => {
4063 requests.push(AmdDefineDependencyElement::Exports);
4064 }
4065 "require" => {
4066 handler.span_warn_with_code(
4067 span,
4068 "using \"require\" as dependency in an AMD define() is not yet supported",
4069 DiagnosticId::Error(
4070 errors::failed_to_analyze::ecmascript::AMD_DEFINE.to_string(),
4071 ),
4072 );
4073 requests.push(AmdDefineDependencyElement::Require);
4074 }
4075 "module" => {
4076 requests.push(AmdDefineDependencyElement::Module);
4077 }
4078 _ => {
4079 let request = Request::parse_string(dep.into()).to_resolved().await?;
4080 let reference = AmdDefineAssetReference::new(
4081 *origin,
4082 *request,
4083 issue_source(source, span),
4084 error_mode,
4085 )
4086 .to_resolved()
4087 .await?;
4088 requests.push(AmdDefineDependencyElement::Request {
4089 request,
4090 request_str: dep.to_string(),
4091 });
4092 analysis.add_reference(reference);
4093 }
4094 }
4095 } else {
4096 handler.span_err_with_code(
4097 span,
4100 "unsupported AMD define() dependency element form",
4101 DiagnosticId::Error(errors::failed_to_analyze::ecmascript::AMD_DEFINE.to_string()),
4102 );
4103 }
4104 }
4105
4106 if id.is_some() {
4107 handler.span_warn_with_code(
4108 span,
4109 "passing an ID to AMD define() is not yet fully supported",
4110 DiagnosticId::Lint(errors::failed_to_analyze::ecmascript::AMD_DEFINE.to_string()),
4111 );
4112 }
4113
4114 analysis.add_code_gen(AmdDefineWithDependenciesCodeGen::new(
4115 requests,
4116 origin,
4117 analysis.intern_path(ast_path),
4118 AmdDefineFactoryType::Function,
4119 issue_source(source, span),
4120 error_mode,
4121 ));
4122
4123 Ok(())
4124}
4125
4126pub fn as_abs_path(path: FileSystemPath) -> String {
4129 require_resolve(path)
4134}
4135
4136fn require_resolve(path: FileSystemPath) -> String {
4138 format!("/ROOT/{}", path.path.as_str())
4139}
4140
4141async fn early_value_visitor<'a>(
4142 _arena: &'a ThreadLocal<Bump>,
4143 mut v: JsValue<'a>,
4144) -> Result<(JsValue<'a>, Modified)> {
4145 let modified = early_replace_builtin(&mut v);
4146 Ok((v, modified))
4147}
4148
4149async fn value_visitor<'a>(
4150 arena: &'a ThreadLocal<Bump>,
4151 origin: Vc<Box<dyn ResolveOrigin>>,
4152 origin_path: &FileSystemPath,
4153 v: JsValue<'a>,
4154 compile_time_info: Vc<CompileTimeInfo>,
4155 compile_time_info_ref: &CompileTimeInfo,
4156 var_graph: &VarGraph<'a>,
4157 attributes: &ImportAttributes,
4158 allow_project_root_tracing: bool,
4159 constants_cache: &Mutex<FxHashMap<ModuleValue, Option<JsValue<'a>>>>,
4160 import_references: &[ResolvedVc<EsmAssetReference>],
4161 cross_module_constants: bool,
4162) -> Result<(JsValue<'a>, Modified)> {
4163 let (mut v, modified) = value_visitor_inner(
4164 arena,
4165 origin,
4166 origin_path,
4167 v,
4168 compile_time_info,
4169 compile_time_info_ref,
4170 var_graph,
4171 attributes,
4172 allow_project_root_tracing,
4173 constants_cache,
4174 import_references,
4175 cross_module_constants,
4176 )
4177 .await?;
4178 v.normalize_shallow(arena.get_or_default());
4179 Ok((v, modified))
4180}
4181
4182async fn value_visitor_inner<'a>(
4183 arena: &'a ThreadLocal<Bump>,
4184 origin: Vc<Box<dyn ResolveOrigin>>,
4185 origin_path: &FileSystemPath,
4186 v: JsValue<'a>,
4187 compile_time_info: Vc<CompileTimeInfo>,
4188 compile_time_info_ref: &CompileTimeInfo,
4189 var_graph: &VarGraph<'a>,
4190 attributes: &ImportAttributes,
4191 allow_project_root_tracing: bool,
4192 constants_cache: &Mutex<FxHashMap<ModuleValue, Option<JsValue<'a>>>>,
4193 import_references: &[ResolvedVc<EsmAssetReference>],
4194 cross_module_constants: bool,
4195) -> Result<(JsValue<'a>, Modified)> {
4196 if let JsValue::In(_, left, right) = &v
4197 && let Some(left) = left.as_str()
4198 && let right_name = right.get_definable_name(Some(var_graph))
4199 && right_name.len() == 1
4200 && let Some((mut right_name, false)) = right_name.into_iter().next().unwrap()
4201 {
4202 right_name.0.push(DefinableNameSegmentRef::Name(left));
4203 if compile_time_info_ref
4204 .defines
4205 .contains_key(&right_name)
4206 .await?
4207 {
4208 return Ok((JsValue::Constant(JsConstantValue::True), Modified::Yes));
4209 }
4210 }
4211
4212 if let [Some((name, false))] = &*v.get_definable_name(Some(var_graph))
4213 && let Some(value) = compile_time_info_ref.defines.get(name).await?
4214 {
4215 return Ok((
4216 JsValue::from_compile_time_define_value_in(arena.get_or_default(), &value)?,
4217 Modified::Yes,
4218 ));
4219 }
4220
4221 let ImportAttributes { ignore, .. } = *attributes;
4222 let value = match v {
4223 JsValue::Call(_, call)
4224 if matches!(
4225 call.callee(),
4226 JsValue::WellKnownFunction(WellKnownFunctionKind::RequireResolve)
4227 ) =>
4228 {
4229 let (_, args) = call.into_parts();
4230 require_resolve_visitor(arena, origin, args).await?
4231 }
4232 JsValue::Call(_, ref call)
4233 if matches!(
4234 call.callee(),
4235 JsValue::WellKnownFunction(WellKnownFunctionKind::ImportMetaGlob)
4236 ) =>
4237 {
4238 v.into_unknown(false, rcstr!("import.meta.glob()"))
4241 }
4242 JsValue::Call(_, call)
4243 if matches!(
4244 call.callee(),
4245 JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContext)
4246 ) =>
4247 {
4248 let (_, args) = call.into_parts();
4249 require_context_visitor(arena, origin, origin_path, args).await?
4250 }
4251 JsValue::Call(_, ref call)
4252 if matches!(
4253 call.callee(),
4254 JsValue::WellKnownFunction(
4255 WellKnownFunctionKind::RequireContextRequire(..)
4256 | WellKnownFunctionKind::RequireContextRequireKeys(..)
4257 | WellKnownFunctionKind::RequireContextRequireResolve(..),
4258 )
4259 ) =>
4260 {
4261 v.into_unknown(
4264 true,
4265 rcstr!("require.context() static analysis is currently limited"),
4266 )
4267 }
4268 JsValue::Call(_, ref call)
4269 if matches!(
4270 call.callee(),
4271 JsValue::WellKnownFunction(WellKnownFunctionKind::CreateRequire)
4272 ) =>
4273 {
4274 if let [JsValue::Member(_, member_obj, member_prop)] = call.args()
4275 && let JsValue::WellKnownObject(WellKnownObjectKind::ImportMeta) = &**member_obj
4276 && let JsValue::Constant(super::analyzer::ConstantValue::Str(prop)) = &**member_prop
4277 && prop.as_str() == "url"
4278 {
4279 JsValue::WellKnownFunction(WellKnownFunctionKind::Require)
4281 } else if let [JsValue::Url(rel, JsValueUrlKind::Relative)] = call.args() {
4282 JsValue::WellKnownFunction(WellKnownFunctionKind::RequireFrom(Box::new(
4284 rel.clone(),
4285 )))
4286 } else {
4287 v.into_unknown(true, rcstr!("createRequire() non constant"))
4288 }
4289 }
4290 JsValue::New(_, ref call)
4291 if matches!(
4292 call.callee(),
4293 JsValue::WellKnownFunction(WellKnownFunctionKind::URLConstructor)
4294 ) =>
4295 {
4296 if let [
4297 JsValue::Constant(super::analyzer::ConstantValue::Str(url)),
4298 JsValue::Member(_, member_obj, member_prop),
4299 ] = call.args()
4300 && let JsValue::WellKnownObject(WellKnownObjectKind::ImportMeta) = &**member_obj
4301 && let JsValue::Constant(super::analyzer::ConstantValue::Str(prop)) = &**member_prop
4302 {
4303 if prop.as_str() == "url" {
4304 JsValue::Url(url.clone(), JsValueUrlKind::Relative)
4305 } else {
4306 v.into_unknown(true, rcstr!("new URL() non constant"))
4307 }
4308 } else {
4309 v.into_unknown(true, rcstr!("new non constant"))
4310 }
4311 }
4312 JsValue::WellKnownFunction(
4313 WellKnownFunctionKind::PathJoin
4314 | WellKnownFunctionKind::PathResolve(_)
4315 | WellKnownFunctionKind::FsReadMethod(_)
4316 | WellKnownFunctionKind::FsReadDir
4317 | WellKnownFunctionKind::ChildProcessSpawnMethod(_)
4318 | WellKnownFunctionKind::ChildProcessFork,
4319 ) => {
4320 if ignore {
4321 return Ok((
4322 JsValue::unknown(v, true, rcstr!("ignored well known function")),
4323 Modified::Yes,
4324 ));
4325 } else {
4326 return Ok((v, Modified::No));
4327 }
4328 }
4329 JsValue::FreeVar(ref kind) => match &**kind {
4330 "__dirname" => as_abs_path(origin_path.parent()).into(),
4331 "__filename" => as_abs_path(origin_path.clone()).into(),
4332
4333 "require" => JsValue::unknown_if(
4334 ignore,
4335 JsValue::WellKnownFunction(WellKnownFunctionKind::Require),
4336 true,
4337 rcstr!("ignored require"),
4338 ),
4339 "import" => JsValue::unknown_if(
4340 ignore,
4341 JsValue::WellKnownFunction(WellKnownFunctionKind::Import),
4342 true,
4343 rcstr!("ignored import"),
4344 ),
4345 "Worker" => JsValue::unknown_if(
4346 ignore,
4347 JsValue::WellKnownFunction(WellKnownFunctionKind::WorkerConstructor),
4348 true,
4349 rcstr!("ignored Worker constructor"),
4350 ),
4351 "SharedWorker" => JsValue::unknown_if(
4352 ignore,
4353 JsValue::WellKnownFunction(WellKnownFunctionKind::SharedWorkerConstructor),
4354 true,
4355 rcstr!("ignored SharedWorker constructor"),
4356 ),
4357 "define" => JsValue::WellKnownFunction(WellKnownFunctionKind::Define),
4358 "URL" => JsValue::WellKnownFunction(WellKnownFunctionKind::URLConstructor),
4359 "process" => JsValue::WellKnownObject(WellKnownObjectKind::NodeProcessModule),
4360 "Object" => JsValue::WellKnownObject(WellKnownObjectKind::GlobalObject),
4361 "Buffer" => JsValue::WellKnownObject(WellKnownObjectKind::NodeBuffer),
4362 "navigator" => JsValue::WellKnownObject(WellKnownObjectKind::Navigator),
4363 "__turbopack_emit__" => {
4364 JsValue::WellKnownFunction(WellKnownFunctionKind::TurbopackEmit)
4365 }
4366 "__turbopack_collect__" => {
4367 JsValue::WellKnownFunction(WellKnownFunctionKind::TurbopackCollect)
4368 }
4369 _ => return Ok((v, Modified::No)),
4370 },
4371
4372 JsValue::Module(ref mv) => {
4373 if *compile_time_info.environment().node_externals().await?
4374 && let Some(external) = module_value_to_well_known_object(mv)
4375 {
4376 external
4377 } else if cross_module_constants
4378 && (mv
4379 .annotations
4380 .as_ref()
4381 .and_then(|a| a.turbopack_constants())
4382 .unwrap_or(mv.analyze_for_constants))
4383 && let cache = {
4384 let constants_cache = constants_cache.lock();
4387 constants_cache
4388 .get(mv)
4389 .as_ref()
4390 .map(|v| v.as_ref().map(|v| v.clone_in(arena.get_or_default())))
4391 }
4392 && let cache_entry = (if let Some(cache_entry) = cache {
4393 cache_entry
4394 } else {
4395 let module = module_value_to_constants_module(
4396 arena,
4397 mv,
4398 compile_time_info,
4399 import_references,
4400 )
4401 .await?;
4402 constants_cache.lock().insert(
4403 mv.clone(),
4404 module.as_ref().map(|v| v.clone_in(arena.get_or_default())),
4405 );
4406 module
4407 })
4408 && let Some(module) = cache_entry
4409 {
4410 module
4411 } else {
4412 v.into_unknown(true, rcstr!("cross module analyzing is not yet supported"))
4413 }
4414 }
4415 JsValue::Argument(..) => v.into_unknown(
4416 true,
4417 rcstr!("cross function analyzing is not yet supported"),
4418 ),
4419 _ => {
4420 let (mut v, mut modified) =
4421 replace_well_known(arena, v, compile_time_info, allow_project_root_tracing).await?;
4422 if replace_builtin(arena.get_or_default(), &mut v).is_modified() {
4423 modified = Modified::Yes;
4424 }
4425 if !modified.is_modified() {
4426 modified = Modified::from(v.make_nested_operations_unknown());
4427 }
4428 return Ok((v, modified));
4429 }
4430 };
4431 Ok((value, Modified::Yes))
4432}
4433
4434async fn require_resolve_visitor<'a>(
4435 arena: &'a ThreadLocal<Bump>,
4436 origin: Vc<Box<dyn ResolveOrigin>>,
4437 args: BumpVec<'a, JsValue<'a>>,
4438) -> Result<JsValue<'a>> {
4439 Ok(if args.len() == 1 {
4440 let pat = js_value_to_pattern(&args[0]);
4441 let request = Request::parse(pat.clone());
4442 let resolved = cjs_resolve_source(
4443 origin,
4444 request,
4445 CommonJsReferenceSubType::Undefined,
4446 None,
4447 ResolveErrorMode::Warn,
4448 )
4449 .to_resolved()
4450 .await?;
4451 let mut values = resolved
4452 .await?
4453 .primary_sources()
4454 .map(async |source| Ok(require_resolve(source.ident().await?.path.clone()).into()))
4455 .try_join()
4456 .await?;
4457
4458 match values.len() {
4459 0 => JsValue::unknown(
4460 JsValue::call_from_parts(
4461 arena.get_or_default(),
4462 JsValue::WellKnownFunction(WellKnownFunctionKind::RequireResolve),
4463 args,
4464 ),
4465 false,
4466 rcstr!("unresolvable request"),
4467 ),
4468 1 => values.pop().unwrap(),
4469 _ => JsValue::alternatives(BumpVec::from_iter_in(arena.get_or_default(), values)),
4470 }
4471 } else {
4472 JsValue::unknown(
4473 JsValue::call_from_parts(
4474 arena.get_or_default(),
4475 JsValue::WellKnownFunction(WellKnownFunctionKind::RequireResolve),
4476 args,
4477 ),
4478 true,
4479 rcstr!("only a single argument is supported"),
4480 )
4481 })
4482}
4483
4484async fn require_context_visitor<'a>(
4485 arena: &'a ThreadLocal<Bump>,
4486 origin: Vc<Box<dyn ResolveOrigin>>,
4487 origin_path: &FileSystemPath,
4488 args: BumpVec<'a, JsValue<'a>>,
4489) -> Result<JsValue<'a>> {
4490 let options = match parse_require_context(&args) {
4491 Ok(options) => options,
4492 Err(err) => {
4493 return Ok(JsValue::unknown(
4494 JsValue::call_from_parts(
4495 arena.get_or_default(),
4496 JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContext),
4497 args,
4498 ),
4499 true,
4500 PrettyPrintError(&err).to_string().into(),
4501 ));
4502 }
4503 };
4504
4505 let dir = origin_path.parent().join(options.dir.as_str())?;
4506
4507 let map = RequireContextMap::generate(
4508 origin,
4509 dir,
4510 options.include_subdirs,
4511 options.filter.cell(),
4512 None,
4513 ResolveErrorMode::Warn,
4514 );
4515
4516 Ok(JsValue::WellKnownFunction(
4517 WellKnownFunctionKind::RequireContextRequire(Box::new(
4518 RequireContextValue::from_context_map(map).await?,
4519 )),
4520 ))
4521}
4522
4523pub static TURBOPACK_HELPER: LazyLock<Atom> = LazyLock::new(|| atom!("__turbopack-helper__"));
4524pub static TURBOPACK_HELPER_WTF8: LazyLock<Wtf8Atom> =
4525 LazyLock::new(|| atom!("__turbopack-helper__").into());
4526
4527fn is_invoking_node_process_eval(args: &[JsValue<'_>]) -> bool {
4532 if args.len() < 2 {
4533 return false;
4534 }
4535
4536 if let JsValue::Member(_, obj, constant) = &args[0] {
4537 if let (
4539 JsValue::WellKnownObject(WellKnownObjectKind::NodeProcessArgv),
4540 JsValue::Constant(JsConstantValue::Num(ConstantNumber(num))),
4541 ) = (&**obj, &**constant)
4542 {
4543 if num.is_zero()
4545 && let JsValue::Array {
4546 total_nodes: _,
4547 items,
4548 mutable: _,
4549 } = &args[1]
4550 {
4551 if items.iter().any(|e| {
4553 if let JsValue::Constant(JsConstantValue::Str(ConstantString::Atom(arg))) = e {
4554 arg == "-e"
4555 } else {
4556 false
4557 }
4558 }) {
4559 return true;
4562 }
4563 }
4564 }
4565 }
4566
4567 false
4568}