diff options
author | 2022-12-11 11:55:06 -0800 | |
---|---|---|
committer | 2022-12-11 11:55:06 -0800 | |
commit | 9d94f148dca8aa683151845960f93521861a5d02 (patch) | |
tree | a6c7e92e3d430722869b1d839dc3aaa1487a5ee8 /src/js_parser.zig | |
parent | 5cf64b07be7099968df4cdda40408d8a8f6dc3f6 (diff) | |
download | bun-9d94f148dca8aa683151845960f93521861a5d02.tar.gz bun-9d94f148dca8aa683151845960f93521861a5d02.tar.zst bun-9d94f148dca8aa683151845960f93521861a5d02.zip |
Avoid re-visting AST nodes which create scopes
Diffstat (limited to 'src/js_parser.zig')
-rw-r--r-- | src/js_parser.zig | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/src/js_parser.zig b/src/js_parser.zig index fc9baac1d..d48afe7a4 100644 --- a/src/js_parser.zig +++ b/src/js_parser.zig @@ -3700,7 +3700,9 @@ fn NewParser_( loop_body: Stmt.Data, module_scope: *js_ast.Scope = undefined, is_control_flow_dead: bool = false, - is_substituting: bool = false, + + /// We must be careful to avoid revisiting nodes that have scopes. + is_revisit_for_substitution: bool = false, // Inside a TypeScript namespace, an "export declare" statement can be used // to cause a namespace to be emitted even though it has no other observable @@ -4360,7 +4362,7 @@ fn NewParser_( } pub fn recordUsage(p: *P, ref: Ref) void { - if (p.is_substituting) return; + if (p.is_revisit_for_substitution) return; // The use count stored in the symbol is used for generating symbol names // during minification. These counts shouldn't include references inside dead // code regions since those will be culled. @@ -4589,9 +4591,9 @@ fn NewParser_( switch (p.substituteSingleUseSymbolInExpr(expr.*, ref, replacement, replacement_can_be_removed)) { .success => |result| { if (result.data == .e_binary or result.data == .e_unary or result.data == .e_if) { - const prev_substituting = p.is_substituting; - p.is_substituting = true; - defer p.is_substituting = prev_substituting; + const prev_substituting = p.is_revisit_for_substitution; + p.is_revisit_for_substitution = true; + defer p.is_revisit_for_substitution = prev_substituting; // O(n^2) and we will need to think more carefully about // this once we implement syntax compression expr.* = p.visitExpr(result); @@ -14633,6 +14635,10 @@ fn NewParser_( } }, .e_arrow => |e_| { + if (p.is_revisit_for_substitution) { + return expr; + } + const old_fn_or_arrow_data = std.mem.toBytes(p.fn_or_arrow_data_visit); p.fn_or_arrow_data_visit = FnOrArrowDataVisit{ .is_arrow = true, @@ -14668,12 +14674,19 @@ fn NewParser_( p.fn_or_arrow_data_visit = std.mem.bytesToValue(@TypeOf(p.fn_or_arrow_data_visit), &old_fn_or_arrow_data); }, .e_function => |e_| { + if (p.is_revisit_for_substitution) { + return expr; + } + e_.func = p.visitFunc(e_.func, expr.loc); if (e_.func.name) |name| { return p.keepExprSymbolName(expr, p.symbols.items[name.ref.?.innerIndex()].original_name); } }, .e_class => |e_| { + if (p.is_revisit_for_substitution) { + return expr; + } // This might be wrong. _ = p.visitClass(expr.loc, e_); @@ -15388,7 +15401,7 @@ fn NewParser_( } pub fn ignoreUsage(p: *P, ref: Ref) void { - if (!p.is_control_flow_dead and !p.is_substituting) { + if (!p.is_control_flow_dead and !p.is_revisit_for_substitution) { if (comptime Environment.allow_assert) assert(@as(usize, ref.innerIndex()) < p.symbols.items.len); p.symbols.items[ref.innerIndex()].use_count_estimate -|= 1; var use = p.symbol_uses.get(ref) orelse return; |