Compare commits

..

6 Commits

Author SHA1 Message Date
Alex Lam S.L
7aba2dc5f2 v3.15.3 2022-03-10 12:50:19 +08:00
Alex Lam S.L
12a6728c4e fix corner case in hoist_vars (#5379)
fixes #5378
2022-03-06 17:56:00 +08:00
Alex Lam S.L
042c228c7b fix corner case in inline (#5377)
fixes #5376
2022-03-06 03:29:56 +08:00
Alex Lam S.L
e2b00814a8 fix corner cases in inline (#5375) 2022-03-04 04:05:31 +08:00
Alex Lam S.L
104d385ba9 fix corner case in ie (#5372)
fixes #5370
2022-03-02 13:52:27 +08:00
Alex Lam S.L
fdbbef2991 enhance conditionals (#5371) 2022-03-02 11:00:37 +08:00
10 changed files with 224 additions and 49 deletions

View File

@@ -7844,15 +7844,15 @@ Compressor.prototype.compress = function(node) {
&& !consts.has(sym.name)
&& self.find_variable(sym.name) === sym.definition();
})) return node;
node.definitions.forEach(function(def) {
vars.set(def.name.name, def);
node.definitions.forEach(function(defn) {
vars.set(defn.name.name, defn);
++vars_found;
});
var seq = node.to_assignments();
if (p instanceof AST_ForEnumeration && p.init === node) {
if (seq) return seq;
var def = node.definitions[0].name;
return make_node(AST_SymbolRef, def, def);
var sym = node.definitions[0].name;
return make_node(AST_SymbolRef, sym, sym);
}
if (p instanceof AST_For && p.init === node) return seq;
if (!seq) return in_list ? List.skip : make_node(AST_EmptyStatement, node);
@@ -7867,21 +7867,22 @@ Compressor.prototype.compress = function(node) {
self.transform(tt);
if (vars_found > 0) {
// collect only vars which don't show up in self's arguments list
var defs = [];
var defns = [];
if (self instanceof AST_Lambda) self.each_argname(function(argname) {
vars.del(argname.name);
});
vars.each(function(def, name) {
def = def.clone();
def.value = null;
defs.push(def);
vars.set(name, def);
vars.each(function(defn, name) {
defn = defn.clone();
defn.name = defn.name.clone();
defn.value = null;
defns.push(defn);
vars.set(name, defn);
defn.name.definition().orig.unshift(defn.name);
});
if (defs.length > 0) {
if (defns.length > 0) {
// try to merge in assignments
insert_vars(self.body);
defs = make_node(AST_Var, self, { definitions: defs });
hoisted.push(defs);
hoisted.push(make_node(AST_Var, self, { definitions: defns }));
}
}
self.body = dirs.concat(hoisted, self.body);
@@ -7895,13 +7896,13 @@ Compressor.prototype.compress = function(node) {
&& expr.operator == "="
&& (sym = expr.left) instanceof AST_Symbol
&& vars.has(sym.name)) {
var def = vars.get(sym.name);
if (def.value) break;
var defn = vars.get(sym.name);
if (defn.value) break;
var value = expr.right;
if (value instanceof AST_Sequence) value = value.clone();
def.value = value;
remove(defs, def);
defs.push(def);
defn.value = value;
remove(defns, defn);
defns.push(defn);
body.shift();
continue;
}
@@ -7910,11 +7911,11 @@ Compressor.prototype.compress = function(node) {
&& assign.operator == "="
&& (sym = assign.left) instanceof AST_Symbol
&& vars.has(sym.name)) {
var def = vars.get(sym.name);
if (def.value) break;
def.value = assign.right;
remove(defs, def);
defs.push(def);
var defn = vars.get(sym.name);
if (defn.value) break;
defn.value = assign.right;
remove(defns, defn);
defns.push(defn);
stat.body = make_sequence(expr, expr.expressions.slice(1));
continue;
}
@@ -9157,14 +9158,16 @@ Compressor.prototype.compress = function(node) {
var cond = fuzzy_eval(compressor, self.condition);
if (!cond) {
AST_Node.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
var body = [ make_node(AST_SimpleStatement, self.condition, { body: self.condition }) ];
var body = [
make_node(AST_SimpleStatement, self.condition, { body: self.condition }).transform(compressor),
];
extract_declarations_from_unreachable_code(compressor, self.body, body);
if (self.alternative) body.push(self.alternative);
return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
} else if (!(cond instanceof AST_Node)) {
AST_Node.warn("Condition always true [{file}:{line},{col}]", self.condition.start);
var body = [
make_node(AST_SimpleStatement, self.condition, { body: self.condition }),
make_node(AST_SimpleStatement, self.condition, { body: self.condition }).transform(compressor),
self.body,
];
if (self.alternative) extract_declarations_from_unreachable_code(compressor, self.alternative, body);
@@ -9493,20 +9496,12 @@ Compressor.prototype.compress = function(node) {
left: self.expression,
right: exp,
}),
body: make_node(AST_BlockStatement, self, {
body: statements,
}),
body: make_node(AST_BlockStatement, self, { body: statements }),
alternative: null,
}).optimize(compressor);
if (exp) statements.unshift(make_node(AST_SimpleStatement, exp, {
body: exp,
}));
statements.unshift(make_node(AST_SimpleStatement, self.expression, {
body:self.expression,
}));
return make_node(AST_BlockStatement, self, {
body: statements,
}).optimize(compressor);
if (exp) statements.unshift(make_node(AST_SimpleStatement, exp, { body: exp }));
statements.unshift(make_node(AST_SimpleStatement, self.expression, { body: self.expression }));
return make_node(AST_BlockStatement, self, { body: statements }).optimize(compressor);
case 2:
if (!member(default_branch, body) || !no_break(body[1])) break;
var statements = body[0].body.slice();
@@ -9524,14 +9519,10 @@ Compressor.prototype.compress = function(node) {
left: self.expression,
right: body[0].expression,
}),
body: make_node(AST_BlockStatement, body[0], {
body: statements,
}),
body: make_node(AST_BlockStatement, body[0], { body: statements }),
alternative: exclusive && alternative || null,
});
if (!exclusive && alternative) node = make_node(AST_BlockStatement, self, {
body: [ node, alternative ],
});
if (!exclusive && alternative) node = make_node(AST_BlockStatement, self, { body: [ node, alternative ] });
return node.optimize(compressor);
}
return self;
@@ -10534,7 +10525,7 @@ Compressor.prototype.compress = function(node) {
insert = scope.body.indexOf(child) + 1;
if (!insert) return false;
if (!safe_from_await_yield(fn, avoid_await_yield(scope))) return false;
var safe_to_inject = exp !== fn || fn.parent_scope.resolve() === scope;
var safe_to_inject = (exp !== fn || fn.parent_scope.resolve() === scope) && !scope.pinned();
if (scope instanceof AST_Toplevel) {
if (compressor.toplevel.vars) {
defined.set("arguments", true);
@@ -13262,6 +13253,7 @@ Compressor.prototype.compress = function(node) {
if (!(fn instanceof AST_LambdaExpression)) return;
if (fn.name) return;
if (fn.uses_arguments) return;
if (fn.pinned()) return;
if (is_generator(fn)) return;
var arrow = is_arrow(fn);
if (arrow && fn.value) return;
@@ -13277,6 +13269,7 @@ Compressor.prototype.compress = function(node) {
scope = scope.parent_scope;
}
if (!member(scope, compressor.stack)) return;
if (scope.pinned() && fn.variables.size() > (arrow ? 0 : 1)) return;
if (scope instanceof AST_Toplevel) {
if (fn.variables.size() > (arrow ? 0 : 1)) {
if (!compressor.toplevel.vars) return;
@@ -13348,6 +13341,7 @@ Compressor.prototype.compress = function(node) {
def.single_use = false;
if (!in_loop) return;
if (def.references.length == def.replaced) return;
if (def.orig.length == def.eliminated) return;
if (def.orig.length == 1 && fn.functions.has(name)) return;
if (!all(def.orig, function(sym) {
if (sym instanceof AST_SymbolConst) return false;

View File

@@ -226,7 +226,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
defun.def_variable(node);
} else if (node instanceof AST_SymbolLambda) {
var def = defun.def_function(node, node.name == "arguments" ? undefined : defun);
if (options.ie) def.defun = defun.parent_scope.resolve();
if (options.ie && node.name != "arguments") def.defun = defun.parent_scope.resolve();
} else if (node instanceof AST_SymbolLet) {
var def = scope.def_variable(node);
if (exported) def.exported = true;

View File

@@ -3,7 +3,7 @@
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "3.15.2",
"version": "3.15.3",
"engines": {
"node": ">=0.8.0"
},

View File

@@ -82,14 +82,14 @@ ifs_3_should_warn: {
"WARN: Boolean && always false [test/compress/conditionals.js:3,12]",
"WARN: Condition left of && always false [test/compress/conditionals.js:3,12]",
"WARN: Condition always false [test/compress/conditionals.js:3,12]",
"WARN: Dropping side-effect-free statement [test/compress/conditionals.js:3,12]",
"WARN: Dropping unreachable code [test/compress/conditionals.js:3,34]",
"WARN: + in boolean context always true [test/compress/conditionals.js:10,19]",
"WARN: Boolean || always true [test/compress/conditionals.js:10,12]",
"WARN: Condition left of || always true [test/compress/conditionals.js:10,12]",
"WARN: Condition always true [test/compress/conditionals.js:10,12]",
"WARN: Dropping unreachable code [test/compress/conditionals.js:12,15]",
"WARN: Dropping side-effect-free statement [test/compress/conditionals.js:3,12]",
"WARN: Dropping side-effect-free statement [test/compress/conditionals.js:10,12]",
"WARN: Dropping unreachable code [test/compress/conditionals.js:12,15]",
]
}

View File

@@ -3473,3 +3473,27 @@ issue_5314_2: {
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5370: {
options = {
dead_code: true,
ie: true,
unused: true,
}
input: {
console.log(function arguments({}) {
return arguments;
try {} catch (e) {
var arguments;
}
}(42));
}
expect: {
console.log(function arguments({}) {
return arguments;
var arguments;
}(42));
}
expect_stdout: true
node_version: ">=6"
}

View File

@@ -1508,6 +1508,48 @@ unsafe_call_3: {
expect_stdout: "3"
}
inline_eval_inner: {
options = {
inline: true,
}
input: {
(function() {
console.log(typeof eval("arguments"));
})();
}
expect: {
(function() {
console.log(typeof eval("arguments"));
})();
}
expect_stdout: "object"
}
inline_eval_outer: {
options = {
inline: true,
toplevel: true,
}
input: {
A = 42;
(function(a) {
console.log(a);
})(A);
console.log(eval("typeof a"));
}
expect: {
A = 42;
(function(a) {
console.log(a);
})(A);
console.log(eval("typeof a"));
}
expect_stdout: [
"42",
"undefined",
]
}
issue_2616: {
options = {
evaluate: true,
@@ -8228,3 +8270,62 @@ issue_5366: {
"baz",
]
}
issue_5376_1: {
options = {
evaluate: true,
inline: true,
join_vars: true,
loops: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
var a;
for (;42;)
var b = function() {
var c;
throw new Error(c++);
}();
}
expect: {
"use strict";
for (;;) {
42;
throw new Error(NaN);
}
}
expect_stdout: Error("NaN")
}
issue_5376_2: {
options = {
evaluate: true,
inline: true,
join_vars: true,
loops: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
var a;
for (;42;)
var b = function() {
var c;
c++;
throw new Error("PASS");
}();
}
expect: {
"use strict";
for (;;) {
0;
throw new Error("PASS");
}
}
expect_stdout: Error("PASS")
}

View File

@@ -499,3 +499,34 @@ issue_5195: {
}
expect_stdout: "[object Object]"
}
issue_5378: {
options = {
hoist_vars: true,
inline: true,
toplevel: true,
}
input: {
var a = 2;
while (a--)
(function() {
var b;
var c;
while (console.log(b));
--b;
})();
}
expect: {
var a = 2;
while (a--) {
b = void 0;
var b, c;
while (console.log(b));
--b;
}
}
expect_stdout: [
"undefined",
"undefined",
]
}

View File

@@ -6,6 +6,7 @@ reduce_vars: {
C: 0,
},
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,

View File

@@ -1299,3 +1299,27 @@ issue_5360: {
expect_stdout: "PASS"
node_version: ">=8.3.0"
}
issue_5370: {
options = {
dead_code: true,
ie: true,
unused: true,
}
input: {
console.log(function arguments(...a) {
return arguments;
try {} catch (e) {
var arguments;
}
}());
}
expect: {
console.log(function arguments(...a) {
return arguments;
var arguments;
}());
}
expect_stdout: true
node_version: ">=6"
}

View File

@@ -1329,7 +1329,7 @@ issue_3490_2: {
expect: {
var b = 42, c = "FAIL";
var a;
for (c = "PASS", b; "" == typeof d;);
for (c = "PASS"; "" == typeof d;);
console.log(c, b);
}
expect_stdout: "PASS 42"