diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2021-05-12 03:12:19 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-12 10:12:19 +0800 |
commit | 60f3b5515675644cde8ef1a980295f5c841956d8 (patch) | |
tree | fa39dd8e00cb5ffc85b47e66bed3455abd48bb9c | |
parent | 689f8f504d03d47f184c45c85d0b3eb597fafe85 (diff) | |
download | tracifyjs-60f3b5515675644cde8ef1a980295f5c841956d8.tar.gz tracifyjs-60f3b5515675644cde8ef1a980295f5c841956d8.zip |
fix corner case with optional chain operator (#4927)
-rw-r--r-- | lib/output.js | 31 | ||||
-rw-r--r-- | test/compress/optional-chains.js | 42 |
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, |