diff --git a/turbopack/crates/turbopack-core/Cargo.toml b/turbopack/crates/turbopack-core/Cargo.toml index be29ad91192f3..b99a524857cf3 100644 --- a/turbopack/crates/turbopack-core/Cargo.toml +++ b/turbopack/crates/turbopack-core/Cargo.toml @@ -22,7 +22,7 @@ indexmap = { workspace = true } lazy_static = { workspace = true } once_cell = { workspace = true } patricia_tree = "0.5.5" -petgraph = { workspace = true } +petgraph = { workspace = true, features = ["serde-1"] } ref-cast = "1.0.20" regex = { workspace = true } serde = { workspace = true, features = ["rc"] } diff --git a/turbopack/crates/turbopack-ecmascript/src/analyzer/graph.rs b/turbopack/crates/turbopack-ecmascript/src/analyzer/graph.rs index 7d3bc58036cfb..a6639d1584602 100644 --- a/turbopack/crates/turbopack-ecmascript/src/analyzer/graph.rs +++ b/turbopack/crates/turbopack-ecmascript/src/analyzer/graph.rs @@ -10,6 +10,7 @@ use swc_core::{ ecma::{ ast::*, atoms::js_word, + utils::contains_ident_ref, visit::{fields::*, *}, }, }; @@ -863,6 +864,13 @@ impl Analyzer<'_> { let mut ast_path = ast_path .with_guard(AstParentNodeRef::FnExpr(fn_expr, FnExprField::Ident)); self.visit_opt_ident(ident, &mut ast_path); + + // We cannot analyze recursive IIFE + if let Some(ident) = ident { + if contains_ident_ref(&function.body, &ident.to_id()) { + return false; + } + } } { diff --git a/turbopack/crates/turbopack-ecmascript/tests/analyzer/graph/iife-2/graph-effects.snapshot b/turbopack/crates/turbopack-ecmascript/tests/analyzer/graph/iife-2/graph-effects.snapshot new file mode 100644 index 0000000000000..15bdf10d717b9 --- /dev/null +++ b/turbopack/crates/turbopack-ecmascript/tests/analyzer/graph/iife-2/graph-effects.snapshot @@ -0,0 +1,1915 @@ +[ + Member { + obj: FreeVar( + "Object", + ), + prop: Constant( + Str( + Atom( + "keys", + ), + ), + ), + ast_path: [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + For, + ), + ForStmt( + Init, + ), + VarDeclOrExpr( + VarDecl, + ), + VarDecl( + Decls( + 1, + ), + ), + VarDeclarator( + Init, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Member, + ), + ], + span: 80..91, + in_try: false, + }, + FreeVar { + var: FreeVar( + "Object", + ), + ast_path: [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + For, + ), + ForStmt( + Init, + ), + VarDeclOrExpr( + VarDecl, + ), + VarDecl( + Decls( + 1, + ), + ), + VarDeclarator( + Init, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Member, + ), + MemberExpr( + Obj, + ), + Expr( + Ident, + ), + ], + span: 80..86, + in_try: false, + }, + MemberCall { + obj: FreeVar( + "Object", + ), + prop: Constant( + Str( + Atom( + "keys", + ), + ), + ), + args: [ + Value( + Variable( + ( + "namespace", + #4, + ), + ), + ), + ], + ast_path: [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + For, + ), + ForStmt( + Init, + ), + VarDeclOrExpr( + VarDecl, + ), + VarDecl( + Decls( + 1, + ), + ), + VarDeclarator( + Init, + ), + Expr( + Call, + ), + ], + span: 80..102, + in_try: false, + new: false, + }, + Member { + obj: Variable( + ( + "keys", + #4, + ), + ), + prop: Constant( + Str( + Atom( + "length", + ), + ), + ), + ast_path: [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + For, + ), + ForStmt( + Test, + ), + Expr( + Bin, + ), + BinExpr( + Right, + ), + Expr( + Member, + ), + ], + span: 108..119, + in_try: false, + }, + Member { + obj: Variable( + ( + "keys", + #4, + ), + ), + prop: Variable( + ( + "i", + #4, + ), + ), + ast_path: [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + For, + ), + ForStmt( + Body, + ), + Stmt( + Block, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + Decl, + ), + Decl( + Var, + ), + VarDecl( + Decls( + 0, + ), + ), + VarDeclarator( + Init, + ), + Expr( + Member, + ), + ], + span: 142..149, + in_try: false, + }, + Member { + obj: FreeVar( + "console", + ), + prop: Constant( + Str( + Atom( + "debug", + ), + ), + ), + ast_path: [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + For, + ), + ForStmt( + Body, + ), + Stmt( + Block, + ), + BlockStmt( + Stmts( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Member, + ), + ], + span: 155..168, + in_try: false, + }, + FreeVar { + var: FreeVar( + "console", + ), + ast_path: [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + For, + ), + ForStmt( + Body, + ), + Stmt( + Block, + ), + BlockStmt( + Stmts( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Member, + ), + MemberExpr( + Obj, + ), + Expr( + Ident, + ), + ], + span: 155..162, + in_try: false, + }, + Conditional { + condition: Variable( + ( + "path", + #4, + ), + ), + kind: Ternary { + then: EffectsBlock { + effects: [], + range: Exact( + [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + For, + ), + ForStmt( + Body, + ), + Stmt( + Block, + ), + BlockStmt( + Stmts( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Args( + 2, + ), + ), + ExprOrSpread( + Expr, + ), + Expr( + Cond, + ), + CondExpr( + Cons, + ), + ], + ), + }, + else: EffectsBlock { + effects: [], + range: Exact( + [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + For, + ), + ForStmt( + Body, + ), + Stmt( + Block, + ), + BlockStmt( + Stmts( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Args( + 2, + ), + ), + ExprOrSpread( + Expr, + ), + Expr( + Cond, + ), + CondExpr( + Alt, + ), + ], + ), + }, + }, + ast_path: [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + For, + ), + ForStmt( + Body, + ), + Stmt( + Block, + ), + BlockStmt( + Stmts( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Args( + 2, + ), + ), + ExprOrSpread( + Expr, + ), + Expr( + Cond, + ), + CondExpr( + Test, + ), + ], + span: 183..202, + in_try: false, + }, + MemberCall { + obj: FreeVar( + "console", + ), + prop: Constant( + Str( + Atom( + "debug", + ), + ), + ), + args: [ + Value( + Constant( + Str( + Word( + "####", + ), + ), + ), + ), + Value( + Variable( + ( + "path", + #4, + ), + ), + ), + Value( + Tenary( + 4, + Variable( + ( + "path", + #4, + ), + ), + Constant( + True, + ), + Constant( + False, + ), + ), + ), + ], + ast_path: [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + For, + ), + ForStmt( + Body, + ), + Stmt( + Block, + ), + BlockStmt( + Stmts( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + ], + span: 155..203, + in_try: false, + new: false, + }, + Member { + obj: Variable( + ( + "parent", + #4, + ), + ), + prop: Variable( + ( + "key", + #4, + ), + ), + ast_path: [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + For, + ), + ForStmt( + Body, + ), + Stmt( + Block, + ), + BlockStmt( + Stmts( + 2, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Assign, + ), + AssignExpr( + Left, + ), + AssignTarget( + Simple, + ), + SimpleAssignTarget( + Member, + ), + ], + span: 208..219, + in_try: false, + }, + Member { + obj: Variable( + ( + "namespace", + #4, + ), + ), + prop: Variable( + ( + "key", + #4, + ), + ), + ast_path: [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + For, + ), + ForStmt( + Body, + ), + Stmt( + Block, + ), + BlockStmt( + Stmts( + 2, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Assign, + ), + AssignExpr( + Right, + ), + Expr( + Call, + ), + CallExpr( + Args( + 0, + ), + ), + ExprOrSpread( + Expr, + ), + Expr( + Member, + ), + ], + span: 224..238, + in_try: false, + }, + Conditional { + condition: Variable( + ( + "path", + #4, + ), + ), + kind: Ternary { + then: EffectsBlock { + effects: [], + range: Exact( + [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + For, + ), + ForStmt( + Body, + ), + Stmt( + Block, + ), + BlockStmt( + Stmts( + 2, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Assign, + ), + AssignExpr( + Right, + ), + Expr( + Call, + ), + CallExpr( + Args( + 1, + ), + ), + ExprOrSpread( + Expr, + ), + Expr( + Cond, + ), + CondExpr( + Cons, + ), + ], + ), + }, + else: EffectsBlock { + effects: [], + range: Exact( + [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + For, + ), + ForStmt( + Body, + ), + Stmt( + Block, + ), + BlockStmt( + Stmts( + 2, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Assign, + ), + AssignExpr( + Right, + ), + Expr( + Call, + ), + CallExpr( + Args( + 1, + ), + ), + ExprOrSpread( + Expr, + ), + Expr( + Cond, + ), + CondExpr( + Alt, + ), + ], + ), + }, + }, + ast_path: [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + For, + ), + ForStmt( + Body, + ), + Stmt( + Block, + ), + BlockStmt( + Stmts( + 2, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Assign, + ), + AssignExpr( + Right, + ), + Expr( + Call, + ), + CallExpr( + Args( + 1, + ), + ), + ExprOrSpread( + Expr, + ), + Expr( + Cond, + ), + CondExpr( + Test, + ), + ], + span: 240..269, + in_try: false, + }, + Member { + obj: Variable( + ( + "parent", + #4, + ), + ), + prop: Variable( + ( + "key", + #4, + ), + ), + ast_path: [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + For, + ), + ForStmt( + Body, + ), + Stmt( + Block, + ), + BlockStmt( + Stmts( + 2, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Assign, + ), + AssignExpr( + Right, + ), + Expr( + Call, + ), + CallExpr( + Args( + 2, + ), + ), + ExprOrSpread( + Expr, + ), + Expr( + Bin, + ), + BinExpr( + Left, + ), + Expr( + Member, + ), + ], + span: 271..282, + in_try: false, + }, + Call { + func: Variable( + ( + "_", + #3, + ), + ), + args: [ + Value( + Member( + 3, + Variable( + ( + "namespace", + #4, + ), + ), + Variable( + ( + "key", + #4, + ), + ), + ), + ), + Value( + Tenary( + 7, + Variable( + ( + "path", + #4, + ), + ), + Concat( + 4, + [ + Variable( + ( + "path", + #4, + ), + ), + Constant( + Str( + Atom( + ".", + ), + ), + ), + Variable( + ( + "key", + #4, + ), + ), + ], + ), + Variable( + ( + "key", + #4, + ), + ), + ), + ), + Value( + Logical( + 5, + Or, + [ + Member( + 3, + Variable( + ( + "parent", + #4, + ), + ), + Variable( + ( + "key", + #4, + ), + ), + ), + Object { + total_nodes: 1, + parts: [], + mutable: true, + }, + ], + ), + ), + ], + ast_path: [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 0, + ), + ), + Stmt( + For, + ), + ForStmt( + Body, + ), + Stmt( + Block, + ), + BlockStmt( + Stmts( + 2, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Assign, + ), + AssignExpr( + Right, + ), + Expr( + Call, + ), + ], + span: 222..289, + in_try: false, + new: false, + }, + Unreachable { + start_ast_path: [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + CallExpr( + Callee, + ), + Callee( + Expr, + ), + Expr( + Paren, + ), + ParenExpr( + Expr, + ), + Expr( + Fn, + ), + FnExpr( + Function, + ), + Function( + Body, + ), + BlockStmt( + Stmts( + 1, + ), + ), + Stmt( + Return, + ), + ], + }, + Call { + func: Variable( + ( + "_", + #3, + ), + ), + args: [ + Value( + Object { + total_nodes: 7, + parts: [ + KeyValue( + Constant( + Str( + Atom( + "wrapper", + ), + ), + ), + Object { + total_nodes: 5, + parts: [ + KeyValue( + Constant( + Str( + Atom( + "data", + ), + ), + ), + Object { + total_nodes: 3, + parts: [ + KeyValue( + Constant( + Str( + Atom( + "key", + ), + ), + ), + Object { + total_nodes: 1, + parts: [], + mutable: true, + }, + ), + ], + mutable: true, + }, + ), + ], + mutable: true, + }, + ), + ], + mutable: true, + }, + ), + Value( + Constant( + Str( + Word( + "", + ), + ), + ), + ), + Value( + Variable( + ( + "root", + #2, + ), + ), + ), + ], + ast_path: [ + Program( + Script, + ), + Script( + Body( + 1, + ), + ), + Stmt( + Expr, + ), + ExprStmt( + Expr, + ), + Expr( + Call, + ), + ], + span: 16..379, + in_try: false, + new: false, + }, +] diff --git a/turbopack/crates/turbopack-ecmascript/tests/analyzer/graph/iife-2/graph-explained.snapshot b/turbopack/crates/turbopack-ecmascript/tests/analyzer/graph/iife-2/graph-explained.snapshot new file mode 100644 index 0000000000000..8144da8f3bd4c --- /dev/null +++ b/turbopack/crates/turbopack-ecmascript/tests/analyzer/graph/iife-2/graph-explained.snapshot @@ -0,0 +1,17 @@ +_ = (...) => parent + +i = (0 | ???*0*) +- *0* updated with update expression + ⚠️ This value might have side effects + +key = keys[i] + +keys = FreeVar(Object)["keys"](namespace) + +namespace = arguments[0] + +parent = arguments[2] + +path = arguments[1] + +root = {} diff --git a/turbopack/crates/turbopack-ecmascript/tests/analyzer/graph/iife-2/graph.snapshot b/turbopack/crates/turbopack-ecmascript/tests/analyzer/graph/iife-2/graph.snapshot new file mode 100644 index 0000000000000..6948cdded97b1 --- /dev/null +++ b/turbopack/crates/turbopack-ecmascript/tests/analyzer/graph/iife-2/graph.snapshot @@ -0,0 +1,107 @@ +[ + ( + "_", + Function( + 2, + 17, + Variable( + ( + "parent", + #4, + ), + ), + ), + ), + ( + "i", + Alternatives { + total_nodes: 3, + values: [ + Constant( + Num( + ConstantNumber( + 0.0, + ), + ), + ), + Unknown { + original_value: None, + reason: "updated with update expression", + has_side_effects: true, + }, + ], + logical_property: None, + }, + ), + ( + "key", + Member( + 3, + Variable( + ( + "keys", + #4, + ), + ), + Variable( + ( + "i", + #4, + ), + ), + ), + ), + ( + "keys", + MemberCall( + 4, + FreeVar( + "Object", + ), + Constant( + Str( + Atom( + "keys", + ), + ), + ), + [ + Variable( + ( + "namespace", + #4, + ), + ), + ], + ), + ), + ( + "namespace", + Argument( + 17, + 0, + ), + ), + ( + "parent", + Argument( + 17, + 2, + ), + ), + ( + "path", + Argument( + 17, + 1, + ), + ), + ( + "root", + Object { + total_nodes: 1, + parts: [], + mutable: true, + }, + ), +] diff --git a/turbopack/crates/turbopack-ecmascript/tests/analyzer/graph/iife-2/input.js b/turbopack/crates/turbopack-ecmascript/tests/analyzer/graph/iife-2/input.js new file mode 100644 index 0000000000000..e4cf9c52dddf8 --- /dev/null +++ b/turbopack/crates/turbopack-ecmascript/tests/analyzer/graph/iife-2/input.js @@ -0,0 +1,15 @@ +var root = {}; +(function _(namespace, path, parent) { + for (var i = 0, keys = Object.keys(namespace); i < keys.length; i++) { + var key = keys[i]; + console.debug("####", path, path ? true : false) + parent[key] = _(namespace[key], path ? `${path}.${key}` : key, parent[key] || {}); + } + return parent; +})({ + wrapper: { + data: { + key: {} + }, + } +}, "", root); diff --git a/turbopack/crates/turbopack-ecmascript/tests/analyzer/graph/iife-2/resolved-effects.snapshot b/turbopack/crates/turbopack-ecmascript/tests/analyzer/graph/iife-2/resolved-effects.snapshot new file mode 100644 index 0000000000000..43340e4d495c3 --- /dev/null +++ b/turbopack/crates/turbopack-ecmascript/tests/analyzer/graph/iife-2/resolved-effects.snapshot @@ -0,0 +1,71 @@ +0 -> 2 free var = FreeVar(Object) + +0 -> 3 member call = Object*0*["keys"](???*1*) +- *0* Object: The global Object variable +- *1* arguments[0] + ⚠️ function calls are not analysed yet + +0 -> 7 free var = FreeVar(console) + +0 -> 8 conditional = ???*0* +- *0* arguments[1] + ⚠️ function calls are not analysed yet + +0 -> 9 member call = ???*0*["debug"]("####", ???*1*, (???*2* ? true : false)) +- *0* FreeVar(console) + ⚠️ unknown global + ⚠️ This value might have side effects +- *1* arguments[1] + ⚠️ function calls are not analysed yet +- *2* arguments[1] + ⚠️ function calls are not analysed yet + +0 -> 12 conditional = ???*0* +- *0* arguments[1] + ⚠️ function calls are not analysed yet + +0 -> 14 call = (...) => parent(???*0*, (???*2* ? ???*3* : ???*10*), (???*15* | {}){truthy}) +- *0* ???*1*[key] + ⚠️ unknown object +- *1* arguments[0] + ⚠️ function calls are not analysed yet +- *2* arguments[1] + ⚠️ function calls are not analysed yet +- *3* `${???*4*}.${???*5*}` + ⚠️ nested operation +- *4* arguments[1] + ⚠️ function calls are not analysed yet +- *5* ???*6*[i] + ⚠️ unknown object + ⚠️ This value might have side effects +- *6* ???*7*(???*9*) + ⚠️ unknown callee + ⚠️ This value might have side effects +- *7* Object*8*["keys"] + ⚠️ unsupported property on global Object + ⚠️ This value might have side effects +- *8* Object: The global Object variable +- *9* arguments[0] + ⚠️ function calls are not analysed yet +- *10* ???*11*[i] + ⚠️ unknown object + ⚠️ This value might have side effects +- *11* ???*12*(???*14*) + ⚠️ unknown callee + ⚠️ This value might have side effects +- *12* Object*13*["keys"] + ⚠️ unsupported property on global Object + ⚠️ This value might have side effects +- *13* Object: The global Object variable +- *14* arguments[0] + ⚠️ function calls are not analysed yet +- *15* ???*16*[key] + ⚠️ unknown object +- *16* arguments[2] + ⚠️ function calls are not analysed yet + +0 -> 15 unreachable = ???*0* +- *0* unreachable + ⚠️ This value might have side effects + +0 -> 16 call = (...) => parent({"wrapper": {"data": {"key": {}}}}, "", {}) diff --git a/turbopack/crates/turbopack-ecmascript/tests/analyzer/graph/iife-2/resolved-explained.snapshot b/turbopack/crates/turbopack-ecmascript/tests/analyzer/graph/iife-2/resolved-explained.snapshot new file mode 100644 index 0000000000000..5945eeee6c55a --- /dev/null +++ b/turbopack/crates/turbopack-ecmascript/tests/analyzer/graph/iife-2/resolved-explained.snapshot @@ -0,0 +1,44 @@ +_ = (...) => parent + +i = (0 | ???*0*) +- *0* updated with update expression + ⚠️ This value might have side effects + +key = ???*0* +- *0* ???*1*[i] + ⚠️ unknown object + ⚠️ This value might have side effects +- *1* ???*2*(???*4*) + ⚠️ unknown callee + ⚠️ This value might have side effects +- *2* Object*3*["keys"] + ⚠️ unsupported property on global Object + ⚠️ This value might have side effects +- *3* Object: The global Object variable +- *4* arguments[0] + ⚠️ function calls are not analysed yet + +keys = ???*0* +- *0* ???*1*(???*3*) + ⚠️ unknown callee + ⚠️ This value might have side effects +- *1* Object*2*["keys"] + ⚠️ unsupported property on global Object + ⚠️ This value might have side effects +- *2* Object: The global Object variable +- *3* arguments[0] + ⚠️ function calls are not analysed yet + +namespace = ???*0* +- *0* arguments[0] + ⚠️ function calls are not analysed yet + +parent = ???*0* +- *0* arguments[2] + ⚠️ function calls are not analysed yet + +path = ???*0* +- *0* arguments[1] + ⚠️ function calls are not analysed yet + +root = {} diff --git a/turbopack/crates/turbopack-tests/tests/execution/turbopack/basic/next-74190/input/index.js b/turbopack/crates/turbopack-tests/tests/execution/turbopack/basic/next-74190/input/index.js new file mode 100644 index 0000000000000..cdb2168a8816d --- /dev/null +++ b/turbopack/crates/turbopack-tests/tests/execution/turbopack/basic/next-74190/input/index.js @@ -0,0 +1,25 @@ +var root = {}; +const result = (function _(namespace, path, parent) { + console.debug("####", path, path ? true : false) + for (var i = 0, keys = Object.keys(namespace); i < keys.length; i++) { + var key = keys[i]; + parent[key] = _(namespace[key], path ? `${path}.${key}` : key, parent[key] || {}); + } + return parent; +})({ + wrapper: { + data: { + key: {} + }, + } +}, "", root); + +it('should evaluate IIFE correctly', () => { + expect(result).toEqual({ + wrapper: { + data: { + key: {} + }, + } + }); +});