fix corner cases in typeofs (#5301)

This commit is contained in:
Alex Lam S.L
2022-01-17 06:03:41 +00:00
committed by GitHub
parent 43807c26fb
commit 35d7f316ef
3 changed files with 139 additions and 7 deletions

View File

@@ -142,6 +142,7 @@ DEF_BITPROPS(AST_Node, [
"_squeezed", "_squeezed",
// AST_Call // AST_Call
"call_only", "call_only",
// AST_Lambda
"collapse_scanning", "collapse_scanning",
// AST_SymbolRef // AST_SymbolRef
"defined", "defined",

View File

@@ -8715,6 +8715,7 @@ Compressor.prototype.compress = function(node) {
}); });
function mark_locally_defined(condition, consequent, alternative) { function mark_locally_defined(condition, consequent, alternative) {
if (condition instanceof AST_Sequence) condition = condition.tail_node();
if (!(condition instanceof AST_Binary)) return; if (!(condition instanceof AST_Binary)) return;
if (!(condition.left instanceof AST_String)) { if (!(condition.left instanceof AST_String)) {
switch (condition.operator) { switch (condition.operator) {
@@ -8749,6 +8750,8 @@ Compressor.prototype.compress = function(node) {
var abort = false; var abort = false;
var def = sym.definition(); var def = sym.definition();
var fn; var fn;
var refs = [];
var scanned = [];
var tw = new TreeWalker(function(node, descend) { var tw = new TreeWalker(function(node, descend) {
if (abort) return true; if (abort) return true;
if (node instanceof AST_Assign) { if (node instanceof AST_Assign) {
@@ -8765,11 +8768,40 @@ Compressor.prototype.compress = function(node) {
if (node instanceof AST_Call) { if (node instanceof AST_Call) {
descend(); descend();
fn = node.expression.tail_node(); fn = node.expression.tail_node();
if (fn instanceof AST_Lambda) { var save;
fn.walk(tw); if (fn instanceof AST_SymbolRef) {
} else { fn = fn.fixed_value();
abort = true; save = refs.length;
} }
if (!(fn instanceof AST_Lambda)) {
abort = true;
} else if (push_uniq(scanned, fn)) {
fn.walk(tw);
}
if (save >= 0) refs.length = save;
return true;
}
if (node instanceof AST_DWLoop) {
var save = refs.length;
descend();
if (abort) refs.length = save;
return true;
}
if (node instanceof AST_For) {
if (node.init) node.init.walk(tw);
var save = refs.length;
if (node.condition) node.condition.walk(tw);
node.body.walk(tw);
if (node.step) node.step.walk(tw);
if (abort) refs.length = save;
return true;
}
if (node instanceof AST_ForEnumeration) {
node.object.walk(tw);
var save = refs.length;
node.init.walk(tw);
node.body.walk(tw);
if (abort) refs.length = save;
return true; return true;
} }
if (node instanceof AST_Scope) { if (node instanceof AST_Scope) {
@@ -8777,11 +8809,14 @@ Compressor.prototype.compress = function(node) {
return true; return true;
} }
if (node instanceof AST_SymbolRef) { if (node instanceof AST_SymbolRef) {
if (node.definition() === def) node.defined = true; if (node.definition() === def) refs.push(node);
return true; return true;
} }
}); });
body.walk(tw); body.walk(tw);
refs.forEach(function(ref) {
ref.defined = true;
});
function negate(node) { function negate(node) {
if (!(node instanceof AST_Binary)) return; if (!(node instanceof AST_Binary)) return;

View File

@@ -527,6 +527,102 @@ reassign_conditional: {
node_version: ">=15" node_version: ">=15"
} }
reassign_do: {
options = {
comparisons: true,
conditionals: true,
if_return: true,
passes: 2,
reduce_vars: true,
typeofs: true,
}
input: {
A = console;
(function() {
if ("undefined" == typeof A)
return;
var a = A, i = 2;
do {
console.log(void 0 === A, void 0 === a);
A = void 0;
} while (--i);
})();
}
expect: {
A = console;
(function() {
if ("undefined" != typeof A) {
var a = A, i = 2;
do {
console.log(void 0 === A, (a, false));
A = void 0;
} while (--i);
}
})();
}
expect_stdout: [
"false false",
"true false",
]
}
reassign_for: {
options = {
comparisons: true,
conditionals: true,
passes: 2,
reduce_vars: true,
toplevel: true,
typeofs: true,
}
input: {
if (A = console, "undefined" != typeof A)
for (var a = A, i = 0; i < 2; i++)
console.log(void 0 === A, void 0 === a),
A = void 0;
}
expect: {
if (A = console, "undefined" != typeof A)
for (var a = A, i = 0; i < 2; i++)
console.log(void 0 === A, (a, false)),
A = void 0;
}
expect_stdout: [
"false false",
"true false",
]
}
reassign_for_in: {
options = {
comparisons: true,
conditionals: true,
passes: 2,
reduce_vars: true,
typeofs: true,
}
input: {
(A = console) && "undefined" != typeof A && function(a) {
for (var k in [ a = A, 42 ]) {
console.log(void 0 === A, void 0 === a);
A = void 0;
}
}();
}
expect: {
(A = console) && "undefined" != typeof A && function(a) {
for (var k in [ a = A, 42 ]) {
console.log(void 0 === A, (a, false));
A = void 0;
}
}();
}
expect_stdout: [
"false false",
"true false",
]
}
reassign_iife: { reassign_iife: {
options = { options = {
comparisons: true, comparisons: true,
@@ -564,7 +660,7 @@ reassign_property: {
console.log("FAIL 1"); console.log("FAIL 1");
else { else {
A.p = void 0; A.p = void 0;
while (console.log(void 0 === A ? "FAIL 2" : "PASS")); console.log(void 0 === A ? "FAIL 2" : "PASS");
} }
} }
expect: { expect: {
@@ -573,7 +669,7 @@ reassign_property: {
console.log("FAIL 1"); console.log("FAIL 1");
else { else {
A.p = void 0; A.p = void 0;
while (console.log((A, false) ? "FAIL 2" : "PASS")); console.log((A, false) ? "FAIL 2" : "PASS");
} }
} }
expect_stdout: "PASS" expect_stdout: "PASS"