aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2017-03-27 01:30:21 +0800
committerGitHub <noreply@github.com>2017-03-27 01:30:21 +0800
commit57ce5bd9e085546a5c1cb8dd4a3ea71ab6c56f26 (patch)
treeee5e196f4aa4fcbe867eb82287b73b9db6b4174e /lib
parent861a79ac9fdb2cdbb54054306eb896e2c134af73 (diff)
downloadtracifyjs-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.js17
-rw-r--r--lib/scope.js32
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) {