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