fix corner cases in conditionals & if_return (#5680)

fixes #5679
This commit is contained in:
Alex Lam S.L
2022-09-26 18:28:03 +01:00
committed by GitHub
parent 8ca40070a4
commit 8e65413b99
2 changed files with 241 additions and 11 deletions

View File

@@ -3632,7 +3632,8 @@ Compressor.prototype.compress = function(node) {
var value = stat.body.value; var value = stat.body.value;
var in_bool = stat.body.in_bool || next instanceof AST_Return && next.in_bool; var in_bool = stat.body.in_bool || next instanceof AST_Return && next.in_bool;
// if (foo()) return x; return y; ---> return foo() ? x : y; // if (foo()) return x; return y; ---> return foo() ? x : y;
if (!stat.alternative && next instanceof AST_Return) { if (!stat.alternative && next instanceof AST_Return
&& (!value == !next.value || !in_async_generator(in_lambda))) {
changed = true; changed = true;
stat = stat.clone(); stat = stat.clone();
stat.alternative = make_node(AST_BlockStatement, next, { stat.alternative = make_node(AST_BlockStatement, next, {
@@ -9677,17 +9678,26 @@ Compressor.prototype.compress = function(node) {
alternative: null, alternative: null,
}); });
if (self.alternative instanceof AST_Exit && self.body.TYPE == self.alternative.TYPE) { if (self.alternative instanceof AST_Exit && self.body.TYPE == self.alternative.TYPE) {
var cons_value = self.body.value;
var alt_value = self.alternative.value;
if (!cons_value && !alt_value) return make_node(AST_BlockStatement, self, {
body: [
make_node(AST_SimpleStatement, self, { body: self.condition }),
self.body,
],
}).optimize(compressor);
if (cons_value && alt_value || !in_async_generator(compressor.find_parent(AST_Scope))) {
var exit = make_node(self.body.CTOR, self, { var exit = make_node(self.body.CTOR, self, {
value: make_node(AST_Conditional, self, { value: make_node(AST_Conditional, self, {
condition: self.condition, condition: self.condition,
consequent: self.body.value || make_node(AST_Undefined, self.body).transform(compressor), consequent: cons_value || make_node(AST_Undefined, self.body).transform(compressor),
alternative: self.alternative.value alternative: alt_value || make_node(AST_Undefined, self.alternative).transform(compressor),
|| make_node(AST_Undefined, self.alternative).transform(compressor),
}), }),
}); });
if (exit instanceof AST_Return) exit.in_bool = self.body.in_bool || self.alternative.in_bool; if (exit instanceof AST_Return) exit.in_bool = self.body.in_bool || self.alternative.in_bool;
return exit; return exit;
} }
}
if (self.body instanceof AST_If && !self.body.alternative && !self.alternative) { if (self.body instanceof AST_If && !self.body.alternative && !self.alternative) {
self = make_node(AST_If, self, { self = make_node(AST_If, self, {
condition: make_node(AST_Binary, self.condition, { condition: make_node(AST_Binary, self.condition, {

View File

@@ -1769,3 +1769,223 @@ issue_5663: {
] ]
node_version: ">=6" node_version: ">=6"
} }
issue_5679_1: {
options = {
conditionals: true,
}
input: {
var a = "FAIL";
async function* f(b) {
try {
if (b)
return;
else
return;
} finally {
a = "PASS";
}
}
f().next();
console.log(a);
}
expect: {
var a = "FAIL";
async function* f(b) {
try {
b;
return;
} finally {
a = "PASS";
}
}
f().next();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=10"
}
issue_5679_2: {
options = {
conditionals: true,
}
input: {
var a = "FAIL";
async function* f(b) {
try {
if (b)
return undefined;
else
return;
} finally {
a = "PASS";
}
}
f().next();
console.log(a);
}
expect: {
var a = "FAIL";
async function* f(b) {
try {
if (b)
return void 0;
return;
} finally {
a = "PASS";
}
}
f().next();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=10"
}
issue_5679_3: {
options = {
conditionals: true,
}
input: {
var a = "FAIL";
async function* f(b) {
try {
if (b)
return;
else
return undefined;
} finally {
a = "PASS";
}
}
f(42).next();
console.log(a);
}
expect: {
var a = "FAIL";
async function* f(b) {
try {
if (b)
return;
return void 0;
} finally {
a = "PASS";
}
}
f(42).next();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=10"
}
issue_5679_4: {
options = {
conditionals: true,
}
input: {
var a = "PASS";
async function* f(b) {
try {
if (b)
return undefined;
else
return undefined;
} finally {
a = "FAIL";
}
}
f(null).next();
console.log(a);
}
expect: {
var a = "PASS";
async function* f(b) {
try {
return b, void 0;
} finally {
a = "FAIL";
}
}
f(null).next();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=10"
}
issue_5679_5: {
options = {
conditionals: true,
if_return: true,
}
input: {
var a = "FAIL";
async function* f(b) {
try {
if (b)
return console;
else
return;
} finally {
a = "PASS";
}
}
f().next();
console.log(a);
}
expect: {
var a = "FAIL";
async function* f(b) {
try {
if (b)
return console;
return;
} finally {
a = "PASS";
}
}
f().next();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=10"
}
issue_5679_6: {
options = {
conditionals: true,
if_return: true,
}
input: {
var a = "PASS";
async function* f(b) {
try {
if (b)
return;
else
return console;
} finally {
a = "FAIL";
}
}
f().next();
console.log(a);
}
expect: {
var a = "PASS";
async function* f(b) {
try {
if (!b)
return console;
} finally {
a = "FAIL";
}
}
f().next();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=10"
}