diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2020-10-04 01:24:41 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-04 08:24:41 +0800 |
commit | 95ef4d5377efc159c7102f134d844ba617b28996 (patch) | |
tree | d3768efb468f24ba872c9ac39a981c0a7e0a7742 /lib/scope.js | |
parent | 04017215cc0bd9a19492cd8792dac556a0912043 (diff) | |
download | tracifyjs-95ef4d5377efc159c7102f134d844ba617b28996.tar.gz tracifyjs-95ef4d5377efc159c7102f134d844ba617b28996.zip |
fix corner case in `mangle` (#4174)
Diffstat (limited to 'lib/scope.js')
-rw-r--r-- | lib/scope.js | 91 |
1 files changed, 57 insertions, 34 deletions
diff --git a/lib/scope.js b/lib/scope.js index 27acf20f..359bd883 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -59,13 +59,9 @@ function SymbolDef(id, scope, orig, init) { } SymbolDef.prototype = { - unmangleable: function(options) { - return this.global && !options.toplevel - || this.undeclared - || !options.eval && this.scope.pinned() - || options.keep_fnames - && (this.orig[0] instanceof AST_SymbolLambda - || this.orig[0] instanceof AST_SymbolDefun); + forEach: function(fn) { + this.orig.forEach(fn); + this.references.forEach(fn); }, mangle: function(options) { var cache = options.cache && options.cache.props; @@ -85,7 +81,15 @@ SymbolDef.prototype = { }, redefined: function() { return this.defun && this.defun.variables.get(this.name); - } + }, + unmangleable: function(options) { + return this.global && !options.toplevel + || this.undeclared + || !options.eval && this.scope.pinned() + || options.keep_fnames + && (this.orig[0] instanceof AST_SymbolLambda + || this.orig[0] instanceof AST_SymbolDefun); + }, }; AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) { @@ -100,15 +104,18 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) { var next_def_id = 0; var scope = self.parent_scope = null; var tw = new TreeWalker(function(node, descend) { + if (node instanceof AST_Defun) { + node.name.walk(tw); + walk_scope(function() { + node.argnames.forEach(function(argname) { + argname.walk(tw); + }); + walk_body(node, tw); + }); + return true; + } if (node instanceof AST_BlockScope) { - node.init_scope_vars(scope); - var save_defun = defun; - var save_scope = scope; - if (node instanceof AST_Scope) defun = node; - scope = node; - descend(); - scope = save_scope; - defun = save_defun; + walk_scope(descend); return true; } if (node instanceof AST_With) { @@ -122,25 +129,41 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) { node.thedef = node; node.references = []; } - if (node instanceof AST_SymbolDefun) { - // This should be defined in the parent scope, as we encounter the - // AST_Defun node before getting to its AST_Symbol. - (node.scope = defun.parent_scope.resolve()).def_function(node, defun); + if (node instanceof AST_SymbolCatch) { + scope.def_variable(node).defun = defun; + } else if (node instanceof AST_SymbolDefun) { + defun.def_function(node, tw.parent()); + entangle(defun, scope); + } else if (node instanceof AST_SymbolFunarg) { + defun.def_variable(node); + entangle(defun, scope); } else if (node instanceof AST_SymbolLambda) { var def = defun.def_function(node, node.name == "arguments" ? undefined : defun); if (options.ie8) def.defun = defun.parent_scope.resolve(); } else if (node instanceof AST_SymbolVar) { - defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined); - if (defun !== scope) { - node.mark_enclosed(options); - var def = scope.find_variable(node); - if (node.thedef !== def) { - node.thedef = def; - } - node.reference(options); - } - } else if (node instanceof AST_SymbolCatch) { - scope.def_variable(node).defun = defun; + defun.def_variable(node, null); + entangle(defun, scope); + } + + function walk_scope(descend) { + node.init_scope_vars(scope); + var save_defun = defun; + var save_scope = scope; + if (node instanceof AST_Scope) defun = node; + scope = node; + descend(); + scope = save_scope; + defun = save_defun; + } + + function entangle(defun, scope) { + if (defun === scope) return; + node.mark_enclosed(options); + var def = scope.find_variable(node); + if (node.thedef === def) return; + node.thedef = def; + def.orig.push(node); + node.mark_enclosed(options); } }); self.make_def = function(orig, init) { @@ -227,7 +250,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) { new_def = scope.def_variable(node); } old_def.defun = new_def.scope; - old_def.orig.concat(old_def.references).forEach(function(node) { + old_def.forEach(function(node) { node.redef = true; node.thedef = new_def; node.reference(options); @@ -341,7 +364,7 @@ function next_mangled_name(scope, options, def) { var holes = scope.cname_holes; var names = Object.create(null); var scopes = [ scope ]; - def.references.forEach(function(sym) { + def.forEach(function(sym) { var scope = sym.scope; do { if (scopes.indexOf(scope) < 0) { @@ -525,7 +548,7 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) { var redef = def.redefined(); var name = redef ? redef.rename || redef.name : next_name(); def.rename = name; - def.orig.concat(def.references).forEach(function(sym) { + def.forEach(function(sym) { if (sym.definition() === def) sym.name = name; }); } |