fix corner case with optional chain operator (#4927)

This commit is contained in:
Alex Lam S.L
2021-05-12 03:12:19 +01:00
committed by GitHub
parent 689f8f504d
commit 60f3b55156
2 changed files with 65 additions and 8 deletions

View File

@@ -790,10 +790,23 @@ function OutputStream(options) {
if (p instanceof AST_Unary) return true; if (p instanceof AST_Unary) return true;
}); });
function lhs_has_optional(node, output) {
var p = output.parent();
if (p instanceof AST_PropAccess && p.expression === node && is_lhs(p, output.parent(1))) {
// ++(foo?.bar).baz
// (foo?.()).bar = baz
do {
if (node.optional) return true;
node = node.expression;
} while (node.TYPE == "Call" || node instanceof AST_PropAccess);
}
}
PARENS(AST_PropAccess, function(output) { PARENS(AST_PropAccess, function(output) {
var node = this; var node = this;
var p = output.parent(); var p = output.parent();
if (p instanceof AST_New && p.expression === node) { if (p instanceof AST_New) {
if (p.expression !== node) return false;
// i.e. new (foo().bar) // i.e. new (foo().bar)
// //
// if there's one call into this subtree, then we need // if there's one call into this subtree, then we need
@@ -805,20 +818,22 @@ function OutputStream(options) {
} while (node instanceof AST_PropAccess); } while (node instanceof AST_PropAccess);
return node.TYPE == "Call"; return node.TYPE == "Call";
} }
return lhs_has_optional(node, output);
}); });
PARENS(AST_Call, function(output) { PARENS(AST_Call, function(output) {
var node = this;
var p = output.parent(); var p = output.parent();
if (p instanceof AST_New) return p.expression === this; if (p instanceof AST_New) return p.expression === node;
// https://bugs.webkit.org/show_bug.cgi?id=123506 // https://bugs.webkit.org/show_bug.cgi?id=123506
if (output.option("webkit")) { if (output.option("webkit")
var g = output.parent(1); && node.expression instanceof AST_Function
return this.expression instanceof AST_Function
&& p instanceof AST_PropAccess && p instanceof AST_PropAccess
&& p.expression === this && p.expression === node) {
&& g instanceof AST_Assign var g = output.parent(1);
&& g.left === p; if (g instanceof AST_Assign && g.left === p) return true;
} }
return lhs_has_optional(node, output);
}); });
PARENS(AST_New, function(output) { PARENS(AST_New, function(output) {

View File

@@ -43,6 +43,48 @@ ternary_decimal: {
expect_stdout: "PASS" expect_stdout: "PASS"
} }
assign_parentheses_call: {
input: {
var o = {};
((() => o)?.()).p = "PASS";
console.log(o.p);
}
expect_exact: 'var o={};((()=>o)?.()).p="PASS";console.log(o.p);'
expect_stdout: "PASS"
node_version: ">=14"
}
assign_parentheses_dot: {
input: {
(console?.log).name.p = console.log("PASS");
}
expect_exact: '(console?.log.name).p=console.log("PASS");'
expect_stdout: "PASS"
node_version: ">=14"
}
assign_no_parentheses: {
input: {
console[console.log?.("PASS")] = 42;
}
expect_exact: 'console[console.log?.("PASS")]=42;'
expect_stdout: "PASS"
node_version: ">=14"
}
unary_parentheses: {
input: {
var o = { p: 41 };
(function() {
return o;
}?.()).p++;
console.log(o.p);
}
expect_exact: "var o={p:41};(function(){return o}?.()).p++;console.log(o.p);"
expect_stdout: "42"
node_version: ">=14"
}
collapse_vars_1: { collapse_vars_1: {
options = { options = {
collapse_vars: true, collapse_vars: true,