fix corner cases with template literals (#4780)
authorAlex Lam S.L <alexlamsl@gmail.com>
Mon, 15 Mar 2021 13:54:05 +0000 (13:54 +0000)
committerGitHub <noreply@github.com>
Mon, 15 Mar 2021 13:54:05 +0000 (21:54 +0800)
lib/compress.js
lib/output.js
test/compress/templates.js
test/ufuzz/index.js

index 0d87e30..3560c13 100644 (file)
@@ -1511,6 +1511,8 @@ merge(Compressor.prototype, {
         var wrap = false;
         if (parent.TYPE == "Call") {
             wrap = parent.expression === orig && needs_unbinding(compressor, val);
+        } else if (parent instanceof AST_Template) {
+            wrap = parent.tag === orig && needs_unbinding(compressor, val);
         } else if (parent instanceof AST_UnaryPrefix) {
             wrap = parent.operator == "delete"
                 || parent.operator == "typeof" && is_undeclared_ref(val);
index 00037ce..e6b4980 100644 (file)
@@ -746,6 +746,8 @@ function OutputStream(options) {
             || p instanceof AST_PropAccess && p.expression === this
             // ...(foo, bar, baz)
             || p instanceof AST_Spread
+            // (foo, bar)`baz`
+            || p instanceof AST_Template && p.tag === this
             // !(foo, bar, baz)
             || p instanceof AST_Unary
             // var a = (1, 2), b = a + a; ---> b == 4
index b75dc7d..a27c6b8 100644 (file)
@@ -73,6 +73,20 @@ tag_parentheses_new: {
     node_version: ">=4"
 }
 
+tag_parentheses_sequence: {
+    input: {
+        var o = {
+            f() {
+                console.log(this === o ? "FAIL" : "PASS");
+            },
+        };
+        (42, o.f)``;
+    }
+    expect_exact: 'var o={f(){console.log(this===o?"FAIL":"PASS")}};(42,o.f)``;'
+    expect_stdout: "PASS"
+    node_version: ">=4"
+}
+
 malformed_escape: {
     input: {
         (function(s) {
@@ -211,7 +225,7 @@ unsafe_evaluate: {
     node_version: ">=8"
 }
 
-side_effects: {
+side_effects_1: {
     options = {
         side_effects: true,
     }
@@ -228,6 +242,30 @@ side_effects: {
     node_version: ">=4"
 }
 
+side_effects_2: {
+    options = {
+        side_effects: true,
+    }
+    input: {
+        var o = {
+            f() {
+                console.log(this === o ? "FAIL" : "PASS");
+            },
+        };
+        (42, o.f)``;
+    }
+    expect: {
+        var o = {
+            f() {
+                console.log(this === o ? "FAIL" : "PASS");
+            },
+        };
+        (0, o.f)``;
+    }
+    expect_stdout: "PASS"
+    node_version: ">=4"
+}
+
 unsafe_side_effects: {
     options = {
         side_effects: true,
index c90eb55..c5a2e75 100644 (file)
@@ -1493,7 +1493,9 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
       case p++:
         var name = getVarName();
         var fn = name + "." + getDotKey();
-        var s = "typeof " + fn + ' == "function" && --_calls_ >= 0 && ' + fn + createArgs(recurmax, stmtDepth, canThrow);
+        var s = "typeof " + fn + ' == "function" && --_calls_ >= 0 && ';
+        s += rng(5) ? fn : "(" + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ", " + fn + ")";
+        s += createArgs(recurmax, stmtDepth, canThrow);
         return mayDefer(canThrow && rng(20) == 0 ? s : name + " && " + s);
       case p++:
         if (SUPPORT.class) {