fix corner cases in varify (#4719)
This commit is contained in:
@@ -7723,7 +7723,10 @@ merge(Compressor.prototype, {
|
|||||||
var name = self.init.definitions[0].name;
|
var name = self.init.definitions[0].name;
|
||||||
if ((name instanceof AST_Destructured || name instanceof AST_SymbolLet)
|
if ((name instanceof AST_Destructured || name instanceof AST_SymbolLet)
|
||||||
&& !name.match_symbol(function(node) {
|
&& !name.match_symbol(function(node) {
|
||||||
if (node instanceof AST_SymbolDeclaration) return may_overlap(compressor, node.definition());
|
if (node instanceof AST_SymbolDeclaration) {
|
||||||
|
var def = node.definition();
|
||||||
|
return !same_scope(def) || may_overlap(compressor, def);
|
||||||
|
}
|
||||||
}, true)) {
|
}, true)) {
|
||||||
self.init = to_var(self.init);
|
self.init = to_var(self.init);
|
||||||
}
|
}
|
||||||
@@ -8269,7 +8272,7 @@ merge(Compressor.prototype, {
|
|||||||
function can_varify(compressor, sym) {
|
function can_varify(compressor, sym) {
|
||||||
if (!sym.fixed_value()) return false;
|
if (!sym.fixed_value()) return false;
|
||||||
var def = sym.definition();
|
var def = sym.definition();
|
||||||
return is_safe_lexical(def) && !may_overlap(compressor, def);
|
return is_safe_lexical(def) && same_scope(def) && !may_overlap(compressor, def);
|
||||||
}
|
}
|
||||||
|
|
||||||
function varify(self, compressor) {
|
function varify(self, compressor) {
|
||||||
@@ -10214,6 +10217,13 @@ merge(Compressor.prototype, {
|
|||||||
} while (node = compressor.parent(level++));
|
} while (node = compressor.parent(level++));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function same_scope(def) {
|
||||||
|
var scope = def.scope.resolve();
|
||||||
|
return all(def.references, function(ref) {
|
||||||
|
return scope === ref.scope.resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
OPT(AST_SymbolRef, function(self, compressor) {
|
OPT(AST_SymbolRef, function(self, compressor) {
|
||||||
if (!compressor.option("ie8")
|
if (!compressor.option("ie8")
|
||||||
&& is_undeclared_ref(self)
|
&& is_undeclared_ref(self)
|
||||||
@@ -10380,13 +10390,6 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
|
|
||||||
function same_scope(def) {
|
|
||||||
var scope = def.scope.resolve();
|
|
||||||
return all(def.references, function(ref) {
|
|
||||||
return scope === ref.scope.resolve();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function has_symbol_ref(value) {
|
function has_symbol_ref(value) {
|
||||||
var found;
|
var found;
|
||||||
value.walk(new TreeWalker(function(node) {
|
value.walk(new TreeWalker(function(node) {
|
||||||
|
|||||||
@@ -354,6 +354,92 @@ forin_let_2: {
|
|||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loop_scope_1: {
|
||||||
|
options = {
|
||||||
|
toplevel: true,
|
||||||
|
varify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
var o = { foo: 1, bar: 2 };
|
||||||
|
for (let i in o) {
|
||||||
|
console.log(i);
|
||||||
|
}
|
||||||
|
for (const j in o)
|
||||||
|
setTimeout(() => console.log(j), 0);
|
||||||
|
for (let k in o)
|
||||||
|
setTimeout(function() {
|
||||||
|
console.log(k);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var o = { foo: 1, bar: 2 };
|
||||||
|
for (var i in o)
|
||||||
|
console.log(i);
|
||||||
|
for (const j in o)
|
||||||
|
setTimeout(() => console.log(j), 0);
|
||||||
|
for (let k in o)
|
||||||
|
setTimeout(function() {
|
||||||
|
console.log(k);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
]
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
loop_scope_2: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
varify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
var a = [ "foo", "bar" ];
|
||||||
|
for (var i = 0; i < a.length; i++) {
|
||||||
|
const x = a[i];
|
||||||
|
console.log(x);
|
||||||
|
let y = a[i];
|
||||||
|
setTimeout(() => console.log(y), 0);
|
||||||
|
const z = a[i];
|
||||||
|
setTimeout(function() {
|
||||||
|
console.log(z);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var a = [ "foo", "bar" ];
|
||||||
|
for (var i = 0; i < a.length; i++) {
|
||||||
|
var x = a[i];
|
||||||
|
console.log(x);
|
||||||
|
let y = a[i];
|
||||||
|
setTimeout(() => console.log(y), 0);
|
||||||
|
const z = a[i];
|
||||||
|
setTimeout(function() {
|
||||||
|
console.log(z);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
"foo",
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
"bar",
|
||||||
|
]
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
issue_4290_1_const: {
|
issue_4290_1_const: {
|
||||||
options = {
|
options = {
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
|
|||||||
@@ -919,6 +919,12 @@ function getLabel(label) {
|
|||||||
return label && " L" + label;
|
return label && " L" + label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function declareVarName(name, no_var) {
|
||||||
|
if (!SUPPORT.let || !no_var && rng(10)) return "var ";
|
||||||
|
block_vars.push(name);
|
||||||
|
return rng(2) ? "let " : "const ";
|
||||||
|
}
|
||||||
|
|
||||||
function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth, target) {
|
function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth, target) {
|
||||||
++stmtDepth;
|
++stmtDepth;
|
||||||
var loop = ++loops;
|
var loop = ++loops;
|
||||||
@@ -955,6 +961,8 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
|||||||
canContinue = label.continue || enableLoopControl(canContinue, CAN_CONTINUE);
|
canContinue = label.continue || enableLoopControl(canContinue, CAN_CONTINUE);
|
||||||
return label.target + "for (var brake" + loop + " = 5; " + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + " && brake" + loop + " > 0; --brake" + loop + ")" + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth);
|
return label.target + "for (var brake" + loop + " = 5; " + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + " && brake" + loop + " > 0; --brake" + loop + ")" + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth);
|
||||||
case STMT_FOR_ENUM:
|
case STMT_FOR_ENUM:
|
||||||
|
var block_len = block_vars.length;
|
||||||
|
var nameLenBefore = VAR_NAMES.length;
|
||||||
var label = createLabel(canBreak, canContinue);
|
var label = createLabel(canBreak, canContinue);
|
||||||
canBreak = label.break || enableLoopControl(canBreak, CAN_BREAK);
|
canBreak = label.break || enableLoopControl(canBreak, CAN_BREAK);
|
||||||
canContinue = label.continue || enableLoopControl(canContinue, CAN_CONTINUE);
|
canContinue = label.continue || enableLoopControl(canContinue, CAN_CONTINUE);
|
||||||
@@ -963,12 +971,8 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
|||||||
var init = "";
|
var init = "";
|
||||||
if (!/^key/.test(key)) {
|
if (!/^key/.test(key)) {
|
||||||
if (!(of && bug_for_of_var) && rng(10) == 0) init = "var ";
|
if (!(of && bug_for_of_var) && rng(10) == 0) init = "var ";
|
||||||
} else if (!SUPPORT.let || !(of && bug_for_of_var) && rng(10)) {
|
|
||||||
init = "var ";
|
|
||||||
} else if (rng(2)) {
|
|
||||||
init = "let ";
|
|
||||||
} else {
|
} else {
|
||||||
init = "const ";
|
init = declareVarName(key, of && bug_for_of_var);
|
||||||
}
|
}
|
||||||
if (!SUPPORT.destructuring || of && !(canThrow && rng(20) == 0) || rng(10)) {
|
if (!SUPPORT.destructuring || of && !(canThrow && rng(20) == 0) || rng(10)) {
|
||||||
init += key;
|
init += key;
|
||||||
@@ -1003,8 +1007,15 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
|||||||
s += createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "; ";
|
s += createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "; ";
|
||||||
s += label.target + " for (" + init + " in expr" + loop + ") {";
|
s += label.target + " for (" + init + " in expr" + loop + ") {";
|
||||||
}
|
}
|
||||||
if (rng(3)) s += "c = 1 + c; var " + createVarName(MANDATORY) + " = expr" + loop + "[" + key + "]; ";
|
if (/^key/.test(key)) VAR_NAMES.push(key);
|
||||||
|
if (rng(3)) {
|
||||||
|
s += "c = 1 + c; ";
|
||||||
|
var name = createVarName(MANDATORY);
|
||||||
|
s += declareVarName(name) + name + " = expr" + loop + "[" + key + "]; ";
|
||||||
|
}
|
||||||
s += createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + "}";
|
s += createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + "}";
|
||||||
|
VAR_NAMES.length = nameLenBefore;
|
||||||
|
block_vars.length = block_len;
|
||||||
return "{" + s + "}";
|
return "{" + s + "}";
|
||||||
case STMT_SEMI:
|
case STMT_SEMI:
|
||||||
return use_strict && rng(20) === 0 ? '"use strict";' : ";";
|
return use_strict && rng(20) === 0 ? '"use strict";' : ";";
|
||||||
|
|||||||
Reference in New Issue
Block a user