aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2021-05-12 03:12:19 +0100
committerGitHub <noreply@github.com>2021-05-12 10:12:19 +0800
commit60f3b5515675644cde8ef1a980295f5c841956d8 (patch)
treefa39dd8e00cb5ffc85b47e66bed3455abd48bb9c
parent689f8f504d03d47f184c45c85d0b3eb597fafe85 (diff)
downloadtracifyjs-60f3b5515675644cde8ef1a980295f5c841956d8.tar.gz
tracifyjs-60f3b5515675644cde8ef1a980295f5c841956d8.zip
fix corner case with optional chain operator (#4927)
-rw-r--r--lib/output.js31
-rw-r--r--test/compress/optional-chains.js42
2 files changed, 65 insertions, 8 deletions
diff --git a/lib/output.js b/lib/output.js
index 308fcf54..c82d2d84 100644
--- a/lib/output.js
+++ b/lib/output.js
@@ -790,10 +790,23 @@ function OutputStream(options) {
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) {
var node = this;
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)
//
// if there's one call into this subtree, then we need
@@ -805,20 +818,22 @@ function OutputStream(options) {
} while (node instanceof AST_PropAccess);
return node.TYPE == "Call";
}
+ return lhs_has_optional(node, output);
});
PARENS(AST_Call, function(output) {
+ var node = this;
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
- if (output.option("webkit")) {
+ if (output.option("webkit")
+ && node.expression instanceof AST_Function
+ && p instanceof AST_PropAccess
+ && p.expression === node) {
var g = output.parent(1);
- return this.expression instanceof AST_Function
- && p instanceof AST_PropAccess
- && p.expression === this
- && g instanceof AST_Assign
- && g.left === p;
+ if (g instanceof AST_Assign && g.left === p) return true;
}
+ return lhs_has_optional(node, output);
});
PARENS(AST_New, function(output) {
diff --git a/test/compress/optional-chains.js b/test/compress/optional-chains.js
index fbee6743..43033c92 100644
--- a/test/compress/optional-chains.js
+++ b/test/compress/optional-chains.js
@@ -43,6 +43,48 @@ ternary_decimal: {
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: {
options = {
collapse_vars: true,