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