aboutsummaryrefslogtreecommitdiff
path: root/lib/compress.js
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2020-10-19 01:32:39 +0100
committerGitHub <noreply@github.com>2020-10-19 08:32:39 +0800
commit96bf7fceabf1670ca07c08a04a3130e742775c8f (patch)
tree71a28df4db6ce0ec1a5e0423dad6b74ab00fa065 /lib/compress.js
parent6c7226c10ef1328c726ce7c5d364efed8ed0d374 (diff)
downloadtracifyjs-96bf7fceabf1670ca07c08a04a3130e742775c8f.tar.gz
tracifyjs-96bf7fceabf1670ca07c08a04a3130e742775c8f.zip
support `let` (#4227)
Diffstat (limited to 'lib/compress.js')
-rw-r--r--lib/compress.js66
1 files changed, 41 insertions, 25 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 015ee306..d4be93ee 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -97,6 +97,7 @@ function Compressor(options, false_by_default) {
unsafe_regexp : false,
unsafe_undefined: false,
unused : !false_by_default,
+ varify : !false_by_default,
}, true);
var evaluate = this.options["evaluate"];
this.eval_threshold = /eager/.test(evaluate) ? 1 / 0 : +evaluate;
@@ -488,7 +489,9 @@ merge(Compressor.prototype, {
if (!(declare || all(def.orig, function(sym) {
return !(sym instanceof AST_SymbolConst);
}))) return false;
- if (def.fixed === undefined) return true;
+ if (def.fixed === undefined) return declare || all(def.orig, function(sym) {
+ return !(sym instanceof AST_SymbolLet);
+ });
if (def.fixed === null && def.safe_ids) {
def.safe_ids[def.id] = false;
delete def.safe_ids;
@@ -1616,7 +1619,7 @@ merge(Compressor.prototype, {
if (side_effects && may_modify(node)) return true;
var def = node.definition();
return (in_try || def.scope.resolve() !== scope) && !all(def.orig, function(sym) {
- return !(sym instanceof AST_SymbolConst);
+ return !(sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet);
});
}
if (node instanceof AST_This) return symbol_in_lvalues(node, parent);
@@ -2177,7 +2180,7 @@ merge(Compressor.prototype, {
var stat = statements[i];
if (stat instanceof AST_BlockStatement) {
if (all(stat.body, function(stat) {
- return !(stat instanceof AST_Const);
+ return !(stat instanceof AST_Const || stat instanceof AST_Let);
})) {
CHANGED = true;
eliminate_spurious_blocks(stat.body);
@@ -2513,7 +2516,7 @@ merge(Compressor.prototype, {
var line = block.body[i];
if (line instanceof AST_Var && declarations_only(line)) {
decls.push(line);
- } else if (stat || line instanceof AST_Const) {
+ } else if (stat || line instanceof AST_Const || line instanceof AST_Let) {
return false;
} else {
stat = line;
@@ -2829,7 +2832,7 @@ merge(Compressor.prototype, {
function push(node) {
if (block) {
block.push(node);
- if (node instanceof AST_Const) block.required = true;
+ if (node instanceof AST_Const || node instanceof AST_Let) block.required = true;
} else {
target.push(node);
}
@@ -4106,7 +4109,7 @@ merge(Compressor.prototype, {
def(AST_SymbolDeclaration, return_false);
def(AST_SymbolRef, function(compressor) {
return !(this.is_declared(compressor) && all(this.definition().orig, function(sym) {
- return !(sym instanceof AST_SymbolConst);
+ return !(sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet);
}));
});
def(AST_This, return_false);
@@ -4360,7 +4363,7 @@ merge(Compressor.prototype, {
return make_node(AST_EmptyStatement, node);
case 1:
var stat = node.body[0];
- if (!(stat instanceof AST_Const)) return stat;
+ if (!(stat instanceof AST_Const || stat instanceof AST_Let)) return stat;
}
return node;
}
@@ -4460,10 +4463,7 @@ merge(Compressor.prototype, {
}
if (node instanceof AST_Const) {
node.definitions.forEach(function(defn) {
- var def = defn.name.definition();
- references[def.id] = false;
- def = def.redefined();
- if (def) references[def.id] = false;
+ references[defn.name.definition().id] = false;
defn.value.walk(tw);
});
return true;
@@ -4516,6 +4516,13 @@ merge(Compressor.prototype, {
pop();
return true;
}
+ if (node instanceof AST_Let) {
+ node.definitions.forEach(function(defn) {
+ references[defn.name.definition().id] = false;
+ if (defn.value) defn.value.walk(tw);
+ });
+ return true;
+ }
if (node instanceof AST_Scope) {
push();
segment.block = node;
@@ -4618,7 +4625,10 @@ merge(Compressor.prototype, {
if (!tail_refs) continue;
if (head_refs.start.block !== tail_refs.start.block
|| !mergeable(head_refs, tail_refs)
- || head_refs.start.loop && !mergeable(tail_refs, head_refs)) {
+ || head_refs.start.loop && !mergeable(tail_refs, head_refs)
+ || !all(tail_refs, function(sym) {
+ return sym.scope.find_variable(def.name) === def;
+ })) {
skipped.unshift(tail);
continue;
}
@@ -4715,7 +4725,7 @@ merge(Compressor.prototype, {
if (!(sym instanceof AST_SymbolRef)) return;
if (compressor.exposed(sym.definition())) return;
if (!all(sym.definition().orig, function(sym) {
- return !(sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLambda);
+ return !(sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLambda || sym instanceof AST_SymbolLet);
})) return;
return sym;
};
@@ -4956,7 +4966,7 @@ merge(Compressor.prototype, {
}
} else if (compressor.option("functions")
&& !compressor.option("ie8")
- && !(node instanceof AST_Const)
+ && !(node instanceof AST_Const || node instanceof AST_Let)
&& var_defs.length == 1
&& sym.assignments == 0
&& def.value instanceof AST_Function
@@ -5100,7 +5110,7 @@ merge(Compressor.prototype, {
return in_list ? List.skip : make_node(AST_EmptyStatement, node);
case 1:
var stat = node.body[0];
- if (!(stat instanceof AST_Const)) return stat;
+ if (!(stat instanceof AST_Const || stat instanceof AST_Let)) return stat;
} else if (node instanceof AST_For) {
// Certain combination of unused name + side effect leads to invalid AST:
// https://github.com/mishoo/UglifyJS/issues/44
@@ -5665,7 +5675,7 @@ merge(Compressor.prototype, {
return ref.fixed_value() === right;
})
&& all(def.orig, function(sym) {
- return !(sym instanceof AST_SymbolConst);
+ return !(sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet);
});
}
});
@@ -5883,7 +5893,7 @@ merge(Compressor.prototype, {
});
function drop_symbol(ref) {
return all(ref.definition().orig, function(sym) {
- return !(sym instanceof AST_SymbolConst);
+ return !(sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet);
});
}
def(AST_SymbolRef, function(compressor) {
@@ -6623,6 +6633,12 @@ merge(Compressor.prototype, {
});
});
+ AST_Let.DEFMETHOD("remove_initializers", function() {
+ this.definitions.forEach(function(def) {
+ def.value = null;
+ });
+ });
+
AST_Var.DEFMETHOD("remove_initializers", function() {
this.definitions.forEach(function(def) {
def.value = null;
@@ -6650,20 +6666,17 @@ merge(Compressor.prototype, {
return make_sequence(this, assignments);
});
- OPT(AST_Const, function(self, compressor) {
- return all(self.definitions, function(defn) {
+ function varify(self, compressor) {
+ return compressor.option("varify") && all(self.definitions, function(defn) {
var node = defn.name;
if (!node.fixed_value()) return false;
var def = node.definition();
if (compressor.exposed(def)) return false;
var scope = def.scope.resolve();
- if (def.scope === scope) return true;
- if (scope instanceof AST_Toplevel) return !scope.variables.has(node.name) && !scope.globals.has(node.name);
- var s = def.scope;
- do {
+ for (var s = def.scope; s !== scope;) {
s = s.parent_scope;
if (s.var_names()[node.name]) return false;
- } while (s !== scope);
+ }
return true;
}) ? make_node(AST_Var, self, {
definitions: self.definitions.map(function(defn) {
@@ -6678,7 +6691,10 @@ merge(Compressor.prototype, {
});
})
}) : self;
- });
+ }
+
+ OPT(AST_Const, varify);
+ OPT(AST_Let, varify);
function lift_sequence_in_expression(node, compressor) {
var exp = node.expression;