diff --git a/lib/compress.js b/lib/compress.js index 1f311f0668f..8358e70c5a2 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -364,7 +364,7 @@ Compressor.prototype.compress = function(node) { expression: make_node(AST_Function, self, { argnames: [], body: self.body, - }).init_vars(self), + }).init_vars(self, self), args: [], }); } @@ -8963,7 +8963,7 @@ Compressor.prototype.compress = function(node) { argnames: [], body: [], value: make_value(), - }).init_vars(self.parent_scope), + }).init_vars(self.parent_scope, self), args: [], })); return make_sequence(self, exprs); diff --git a/lib/scope.js b/lib/scope.js index c2108c50f16..4f80ad9dd74 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -439,35 +439,43 @@ AST_Toplevel.DEFMETHOD("def_global", function(node) { } }); -function init_block_vars(scope, parent) { - scope.enclosed = []; // variables from this or outer scope(s) that are referenced from this or inner scopes - scope.parent_scope = parent; // the parent scope (null if this is the top level) - scope.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope) - scope.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions) - if (parent) scope.make_def = parent.make_def; // top-level tracking of SymbolDef instances +function init_block_vars(scope, parent, orig) { + // variables from this or outer scope(s) that are referenced from this or inner scopes + scope.enclosed = orig ? orig.enclosed.slice() : []; + // map name to AST_SymbolDefun (functions defined in this scope) + scope.functions = orig ? orig.functions.clone() : new Dictionary(); + // map name to AST_SymbolVar (variables defined in this scope; includes functions) + scope.variables = orig ? orig.variables.clone() : new Dictionary(); + if (!parent) return; + // top-level tracking of SymbolDef instances + scope.make_def = parent.make_def; + // the parent scope (null if this is the top level) + scope.parent_scope = parent; } -function init_scope_vars(scope, parent) { - init_block_vars(scope, parent); - scope.uses_eval = false; // will be set to true if this or nested scope uses the global `eval` - scope.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement +function init_scope_vars(scope, parent, orig) { + init_block_vars(scope, parent, orig); + // will be set to true if this or nested scope uses the global `eval` + scope.uses_eval = false; + // will be set to true if this or some nested scope uses the `with` statement + scope.uses_with = false; } -AST_BlockScope.DEFMETHOD("init_vars", function(parent_scope) { - init_block_vars(this, parent_scope); +AST_BlockScope.DEFMETHOD("init_vars", function(parent, orig) { + init_block_vars(this, parent, orig); }); -AST_Scope.DEFMETHOD("init_vars", function(parent_scope) { - init_scope_vars(this, parent_scope); +AST_Scope.DEFMETHOD("init_vars", function(parent, orig) { + init_scope_vars(this, parent, orig); }); -AST_Arrow.DEFMETHOD("init_vars", function(parent_scope) { - init_scope_vars(this, parent_scope); +AST_Arrow.DEFMETHOD("init_vars", function(parent, orig) { + init_scope_vars(this, parent, orig); return this; }); -AST_AsyncArrow.DEFMETHOD("init_vars", function(parent_scope) { - init_scope_vars(this, parent_scope); +AST_AsyncArrow.DEFMETHOD("init_vars", function(parent, orig) { + init_scope_vars(this, parent, orig); }); -AST_Lambda.DEFMETHOD("init_vars", function(parent_scope) { - init_scope_vars(this, parent_scope); +AST_Lambda.DEFMETHOD("init_vars", function(parent, orig) { + init_scope_vars(this, parent, orig); this.uses_arguments = false; this.def_variable(new AST_SymbolFunarg({ name: "arguments", diff --git a/test/compress/classes.js b/test/compress/classes.js index 8b6c8b59ae3..bb56f71aa2b 100644 --- a/test/compress/classes.js +++ b/test/compress/classes.js @@ -3901,3 +3901,29 @@ issue_5682_class_key_computed: { expect_stdout: "PASS" node_version: ">=4" } + +issue_5724: { + options = { + arrows: true, + inline: true, + keep_fargs: true, + toplevel: true, + unused: true, + } + input: { + "use strict"; + class A { + static P = function(a) { + console.log(a, a); + }(a); + } + } + expect: { + "use strict"; + (function(a) { + console.log(a, a); + })(a); + } + expect_stdout: ReferenceError("a is not defined") + node_version: ">=12" +}