diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2017-03-27 01:30:21 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-27 01:30:21 +0800 |
commit | 57ce5bd9e085546a5c1cb8dd4a3ea71ab6c56f26 (patch) | |
tree | ee5e196f4aa4fcbe867eb82287b73b9db6b4174e /lib | |
parent | 861a79ac9fdb2cdbb54054306eb896e2c134af73 (diff) | |
download | tracifyjs-57ce5bd9e085546a5c1cb8dd4a3ea71ab6c56f26.tar.gz tracifyjs-57ce5bd9e085546a5c1cb8dd4a3ea71ab6c56f26.zip |
handle overlapped variable definitions (#1691)
Process variable definitions with or without assigned values against:
- `arguments`
- named function arguments
- multiple definitions within same scope
Essentially demote variable declarations with no value assignments.
Also fixed invalid use of `AST_VarDef` over `arguments` - should use a member of `AST_SymbolDeclaration` instead.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/compress.js | 17 | ||||
-rw-r--r-- | lib/scope.js | 32 |
2 files changed, 28 insertions, 21 deletions
diff --git a/lib/compress.js b/lib/compress.js index 83486b61..590015ff 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -260,7 +260,7 @@ merge(Compressor.prototype, { if (node instanceof AST_SymbolRef) { var d = node.definition(); d.references.push(node); - if (!d.fixed || !is_safe(d) + if (d.fixed === undefined || !is_safe(d) || is_modified(node, 0, d.fixed instanceof AST_Lambda)) { d.fixed = false; } @@ -270,10 +270,10 @@ merge(Compressor.prototype, { } if (node instanceof AST_VarDef) { var d = node.name.definition(); - if (d.fixed === undefined) { - d.fixed = node.value || make_node(AST_Undefined, node); + if (d.fixed == null) { + d.fixed = node.value; mark_as_safe(d); - } else { + } else if (node.value) { d.fixed = false; } } @@ -357,7 +357,14 @@ merge(Compressor.prototype, { function is_safe(def) { for (var i = safe_ids.length, id = def.id; --i >= 0;) { - if (safe_ids[i][id]) return true; + if (safe_ids[i][id]) { + if (def.fixed == null) { + var orig = def.orig[0]; + if (orig instanceof AST_SymbolFunarg || orig.name == "arguments") return false; + def.fixed = make_node(AST_Undefined, orig); + } + return true; + } } } diff --git a/lib/scope.js b/lib/scope.js index 483503ee..b255032c 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -100,15 +100,14 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ if (node instanceof AST_Catch) { var save_scope = scope; scope = new AST_Scope(node); - scope.init_scope_vars(); - scope.parent_scope = save_scope; + scope.init_scope_vars(save_scope); descend(); scope = save_scope; return true; } if (node instanceof AST_Scope) { - node.init_scope_vars(); - var save_scope = node.parent_scope = scope; + node.init_scope_vars(scope); + var save_scope = scope; var save_defun = defun; var save_labels = labels; defun = scope = node; @@ -243,23 +242,24 @@ AST_Toplevel.DEFMETHOD("def_global", function(node){ } }); -AST_Scope.DEFMETHOD("init_scope_vars", function(){ - this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions) - this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope) - this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement - this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval` - this.parent_scope = null; // the parent scope - this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes - this.cname = -1; // the current index for mangling functions/variables +AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope){ + this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions) + this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope) + this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement + this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval` + this.parent_scope = parent_scope; // the parent scope + this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes + this.cname = -1; // the current index for mangling functions/variables }); AST_Lambda.DEFMETHOD("init_scope_vars", function(){ AST_Scope.prototype.init_scope_vars.apply(this, arguments); this.uses_arguments = false; - - var symbol = new AST_VarDef({ name: "arguments", start: this.start, end: this.end }); - var def = new SymbolDef(this, this.variables.size(), symbol); - this.variables.set(symbol.name, def); + this.def_variable(new AST_SymbolVar({ + name: "arguments", + start: this.start, + end: this.end + })); }); AST_SymbolRef.DEFMETHOD("reference", function(options) { |