diff --git a/crates/turbopack-ecmascript/src/references/mod.rs b/crates/turbopack-ecmascript/src/references/mod.rs index 3047f918ab90a..f327cb88115bb 100644 --- a/crates/turbopack-ecmascript/src/references/mod.rs +++ b/crates/turbopack-ecmascript/src/references/mod.rs @@ -24,7 +24,7 @@ use std::{ sync::Arc, }; -use anyhow::Result; +use anyhow::{bail, Result}; use constant_condition::{ConstantCondition, ConstantConditionValue}; use constant_value::ConstantValue; use indexmap::IndexSet; @@ -194,7 +194,10 @@ impl AnalyzeEcmascriptModuleResultBuilder { } /// Adds an asset reference to the analysis result. - pub fn add_import_reference(&mut self, reference: Vc) { + pub fn add_import_reference(&mut self, reference: Vc) + where + R: Upcast>, + { self.references.insert(Vc::upcast(reference)); } @@ -576,7 +579,10 @@ pub(crate) async fn analyse_ecmascript_module_internal( Some(ModulePart::evaluation()) } ImportedSymbol::Symbol(name) => Some(ModulePart::export((&**name).into())), - ImportedSymbol::Part(part_id) => Some(ModulePart::internal(*part_id)), + ImportedSymbol::Part(part_id) => { + evaluation_references.push(i); + Some(ModulePart::internal(*part_id)) + } ImportedSymbol::Exports => Some(ModulePart::exports()), }, Some(TreeShakingMode::ReexportsOnly) => match &r.imported_symbol { @@ -585,10 +591,15 @@ pub(crate) async fn analyse_ecmascript_module_internal( Some(ModulePart::evaluation()) } ImportedSymbol::Symbol(name) => Some(ModulePart::export((&**name).into())), - ImportedSymbol::Part(part_id) => Some(ModulePart::internal(*part_id)), + ImportedSymbol::Part(_) => { + bail!("Internal imports doesn't exist in reexports only mode") + } ImportedSymbol::Exports => None, }, - None => None, + None => { + evaluation_references.push(i); + None + } }, special_exports, import_externals, @@ -603,12 +614,10 @@ pub(crate) async fn analyse_ecmascript_module_internal( *r = r.resolve().await?; } - for r in import_references.iter() { - // `add_import_reference` will avoid adding duplicate references - analysis.add_import_reference(*r); - } for i in evaluation_references { - analysis.add_evaluation_reference(import_references[i]); + let reference = import_references[i]; + analysis.add_evaluation_reference(reference); + analysis.add_import_reference(reference); } let (webpack_runtime, webpack_entry, webpack_chunks, esm_exports, esm_star_exports) = @@ -661,15 +670,18 @@ pub(crate) async fn analyse_ecmascript_module_internal( EsmExport::LocalBinding(..) => {} EsmExport::ImportedNamespace(reference) => { analysis.add_reexport_reference(reference); + analysis.add_import_reference(reference); } EsmExport::ImportedBinding(reference, ..) => { analysis.add_reexport_reference(reference); + analysis.add_import_reference(reference); } EsmExport::Error => {} } } for &export in esm_star_exports.iter() { analysis.add_reexport_reference(export); + analysis.add_import_reference(export); } let mut ignore_effect_span = None; @@ -1076,6 +1088,7 @@ pub(crate) async fn analyse_ecmascript_module_internal( .add_reference(EsmModuleIdAssetReference::new(*r, Vc::cell(ast_path))) } else { analysis.add_local_reference(*r); + analysis.add_import_reference(*r); analysis.add_binding(EsmBinding::new(*r, export, Vc::cell(ast_path))); } } diff --git a/crates/turbopack-ecmascript/tests/analyzer/graph/conditional-import/graph-effects.snapshot b/crates/turbopack-ecmascript/tests/analyzer/graph/conditional-import/graph-effects.snapshot index 64eed55d89c43..b3724a9a77977 100644 --- a/crates/turbopack-ecmascript/tests/analyzer/graph/conditional-import/graph-effects.snapshot +++ b/crates/turbopack-ecmascript/tests/analyzer/graph/conditional-import/graph-effects.snapshot @@ -8,13 +8,16 @@ effects: [], ast_path: [ Program( - Script, + Module, ), - Script( + Module( Body( 0, ), ), + ModuleItem( + Stmt, + ), Stmt( Decl, ), @@ -52,13 +55,16 @@ effects: [], ast_path: [ Program( - Script, + Module, ), - Script( + Module( Body( 0, ), ), + ModuleItem( + Stmt, + ), Stmt( Decl, ), @@ -95,13 +101,16 @@ }, ast_path: [ Program( - Script, + Module, ), - Script( + Module( Body( 0, ), ), + ModuleItem( + Stmt, + ), Stmt( Decl, ), @@ -154,13 +163,16 @@ ], ast_path: [ Program( - Script, + Module, ), - Script( + Module( Body( 0, ), ), + ModuleItem( + Stmt, + ), Stmt( Decl, ), @@ -205,13 +217,16 @@ ), ast_path: [ Program( - Script, + Module, ), - Script( + Module( Body( 1, ), ), + ModuleItem( + Stmt, + ), Stmt( Decl, ), @@ -253,7 +268,7 @@ Member, ), ], - span: 53..77#0, + span: 57..81#0, in_try: false, }, Member { @@ -269,13 +284,16 @@ ), ast_path: [ Program( - Script, + Module, ), - Script( + Module( Body( 1, ), ), + ModuleItem( + Stmt, + ), Stmt( Decl, ), @@ -323,7 +341,7 @@ Member, ), ], - span: 53..64#0, + span: 57..68#0, in_try: false, }, FreeVar { @@ -332,13 +350,16 @@ ), ast_path: [ Program( - Script, + Module, ), - Script( + Module( Body( 1, ), ), + ModuleItem( + Stmt, + ), Stmt( Decl, ), @@ -392,7 +413,7 @@ Ident, ), ], - span: 53..60#1, + span: 57..64#1, in_try: false, }, Conditional { @@ -435,13 +456,16 @@ effects: [], ast_path: [ Program( - Script, + Module, ), - Script( + Module( Body( 1, ), ), + ModuleItem( + Stmt, + ), Stmt( Decl, ), @@ -479,13 +503,16 @@ effects: [], ast_path: [ Program( - Script, + Module, ), - Script( + Module( Body( 1, ), ), + ModuleItem( + Stmt, + ), Stmt( Decl, ), @@ -522,13 +549,16 @@ }, ast_path: [ Program( - Script, + Module, ), - Script( + Module( Body( 1, ), ), + ModuleItem( + Stmt, + ), Stmt( Decl, ), @@ -561,7 +591,7 @@ Test, ), ], - span: 53..188#0, + span: 57..196#0, in_try: false, }, Call { @@ -625,13 +655,16 @@ ], ast_path: [ Program( - Script, + Module, ), - Script( + Module( Body( 1, ), ), + ModuleItem( + Stmt, + ), Stmt( Decl, ), @@ -650,7 +683,7 @@ Call, ), ], - span: 46..189#0, + span: 47..198#0, in_try: false, }, Conditional { @@ -677,13 +710,16 @@ ], ast_path: [ Program( - Script, + Module, ), - Script( + Module( Body( 3, ), ), + ModuleItem( + Stmt, + ), Stmt( If, ), @@ -714,19 +750,22 @@ Call, ), ], - span: 216..227#0, + span: 226..237#0, in_try: false, }, ], ast_path: [ Program( - Script, + Module, ), - Script( + Module( Body( 3, ), ), + ModuleItem( + Stmt, + ), Stmt( If, ), @@ -754,13 +793,16 @@ ], ast_path: [ Program( - Script, + Module, ), - Script( + Module( Body( 3, ), ), + ModuleItem( + Stmt, + ), Stmt( If, ), @@ -791,19 +833,22 @@ Call, ), ], - span: 243..254#0, + span: 254..265#0, in_try: false, }, ], ast_path: [ Program( - Script, + Module, ), - Script( + Module( Body( 3, ), ), + ModuleItem( + Stmt, + ), Stmt( If, ), @@ -815,13 +860,178 @@ }, ast_path: [ Program( - Script, + Module, ), - Script( + Module( Body( 3, ), ), + ModuleItem( + Stmt, + ), + Stmt( + If, + ), + IfStmt( + Test, + ), + ], + span: 208..268#0, + in_try: false, + }, + Conditional { + condition: Constant( + True, + ), + kind: IfElse { + then: EffectsBlock { + effects: [ + ImportedBinding { + esm_reference_index: 1, + export: Some( + "x", + ), + ast_path: [ + Program( + Module, + ), + Module( + Body( + 6, + ), + ), + ModuleItem( + Stmt, + ), + Stmt( + If, + ), + IfStmt( + Cons, + ), + Stmt( + Block, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Ident, + ), + ], + span: 331..332#2, + in_try: false, + }, + ], + ast_path: [ + Program( + Module, + ), + Module( + Body( + 6, + ), + ), + ModuleItem( + Stmt, + ), + Stmt( + If, + ), + IfStmt( + Cons, + ), + ], + }, + else: EffectsBlock { + effects: [ + ImportedBinding { + esm_reference_index: 3, + export: Some( + "y", + ), + ast_path: [ + Program( + Module, + ), + Module( + Body( + 6, + ), + ), + ModuleItem( + Stmt, + ), + Stmt( + If, + ), + IfStmt( + Alt, + ), + Stmt( + Block, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Ident, + ), + ], + span: 345..346#2, + in_try: false, + }, + ], + ast_path: [ + Program( + Module, + ), + Module( + Body( + 6, + ), + ), + ModuleItem( + Stmt, + ), + Stmt( + If, + ), + IfStmt( + Alt, + ), + ], + }, + }, + ast_path: [ + Program( + Module, + ), + Module( + Body( + 6, + ), + ), + ModuleItem( + Stmt, + ), Stmt( If, ), @@ -829,7 +1039,7 @@ Test, ), ], - span: 198..256#0, + span: 317..349#0, in_try: false, }, ] diff --git a/crates/turbopack-ecmascript/tests/analyzer/graph/conditional-import/input.js b/crates/turbopack-ecmascript/tests/analyzer/graph/conditional-import/input.js index 4fe69c7f6bc6d..a647f189f4f13 100644 --- a/crates/turbopack-ecmascript/tests/analyzer/graph/conditional-import/input.js +++ b/crates/turbopack-ecmascript/tests/analyzer/graph/conditional-import/input.js @@ -1,11 +1,22 @@ -const a = import(true ? "a" : "b") -const c = import(process.env.NEXT_RUNTIME === 'edge' - ? 'next/dist/compiled/@vercel/og/index.edge.js' - : 'next/dist/compiled/@vercel/og/index.node.js') +const a = import(true ? "a" : "b"); +const c = import( + process.env.NEXT_RUNTIME === "edge" + ? "next/dist/compiled/@vercel/og/index.edge.js" + : "next/dist/compiled/@vercel/og/index.node.js" +); let b; if (true) { - b = import("a") + b = import("a"); } else { - b = import("b") + b = import("b"); +} + +import { x } from "x"; +import { y } from "y"; + +if (true) { + x; +} else { + y; } diff --git a/crates/turbopack-ecmascript/tests/analyzer/graph/conditional-import/resolved-effects.snapshot b/crates/turbopack-ecmascript/tests/analyzer/graph/conditional-import/resolved-effects.snapshot index a79f0a9546548..fde76dc6ed13e 100644 --- a/crates/turbopack-ecmascript/tests/analyzer/graph/conditional-import/resolved-effects.snapshot +++ b/crates/turbopack-ecmascript/tests/analyzer/graph/conditional-import/resolved-effects.snapshot @@ -23,3 +23,5 @@ 8 -> 10 call = import*0*("b") - *0* import: The dynamic import() method from the ESM specification: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#dynamic_imports + +0 -> 11 conditional = true diff --git a/crates/turbopack-tests/tests/execution/turbopack/side-effects-optimization/comptime/input/index.js b/crates/turbopack-tests/tests/execution/turbopack/side-effects-optimization/comptime/input/index.js new file mode 100644 index 0000000000000..7e2aef16b7a9b --- /dev/null +++ b/crates/turbopack-tests/tests/execution/turbopack/side-effects-optimization/comptime/input/index.js @@ -0,0 +1,10 @@ +import { something } from "package/dep.js"; +import { something2 } from "package/dep2.js"; + +it("should not include a module that is side effect free and exports are not used due to static analysis", () => { + if (false) { + something(); + } else { + something2(); + } +}); diff --git a/crates/turbopack-tests/tests/execution/turbopack/side-effects-optimization/comptime/input/node_modules/package/dep.js b/crates/turbopack-tests/tests/execution/turbopack/side-effects-optimization/comptime/input/node_modules/package/dep.js new file mode 100644 index 0000000000000..2741e3dfa705c --- /dev/null +++ b/crates/turbopack-tests/tests/execution/turbopack/side-effects-optimization/comptime/input/node_modules/package/dep.js @@ -0,0 +1,2 @@ +throw new Error("Should never be executed"); +export const something = () => {}; diff --git a/crates/turbopack-tests/tests/execution/turbopack/side-effects-optimization/comptime/input/node_modules/package/dep2.js b/crates/turbopack-tests/tests/execution/turbopack/side-effects-optimization/comptime/input/node_modules/package/dep2.js new file mode 100644 index 0000000000000..1fb169f16e5b7 --- /dev/null +++ b/crates/turbopack-tests/tests/execution/turbopack/side-effects-optimization/comptime/input/node_modules/package/dep2.js @@ -0,0 +1 @@ +export const something2 = () => {}; diff --git a/crates/turbopack-tests/tests/execution/turbopack/side-effects-optimization/comptime/input/node_modules/package/package.json b/crates/turbopack-tests/tests/execution/turbopack/side-effects-optimization/comptime/input/node_modules/package/package.json new file mode 100644 index 0000000000000..a43829151e142 --- /dev/null +++ b/crates/turbopack-tests/tests/execution/turbopack/side-effects-optimization/comptime/input/node_modules/package/package.json @@ -0,0 +1,3 @@ +{ + "sideEffects": false +} diff --git a/crates/turbopack-tests/tests/execution/turbopack/side-effects-optimization/comptime/options.json b/crates/turbopack-tests/tests/execution/turbopack/side-effects-optimization/comptime/options.json new file mode 100644 index 0000000000000..af13697f09f93 --- /dev/null +++ b/crates/turbopack-tests/tests/execution/turbopack/side-effects-optimization/comptime/options.json @@ -0,0 +1,3 @@ +{ + "treeShakingMode": "reexports-only" +} diff --git a/crates/turbopack-tests/tests/execution/turbopack/tree-shaking/comptime/input/index.js b/crates/turbopack-tests/tests/execution/turbopack/tree-shaking/comptime/input/index.js new file mode 100644 index 0000000000000..32e53fe6658cd --- /dev/null +++ b/crates/turbopack-tests/tests/execution/turbopack/tree-shaking/comptime/input/index.js @@ -0,0 +1 @@ +import "../../../side-effects-optimization/comptime/input/index.js"; diff --git a/crates/turbopack-tests/tests/execution/turbopack/tree-shaking/comptime/options.json b/crates/turbopack-tests/tests/execution/turbopack/tree-shaking/comptime/options.json new file mode 100644 index 0000000000000..000d78a6b3cbb --- /dev/null +++ b/crates/turbopack-tests/tests/execution/turbopack/tree-shaking/comptime/options.json @@ -0,0 +1,3 @@ +{ + "treeShakingMode": "module-fragments" +}