fix corner cases with `export` (#4699)
authorAlex Lam S.L <alexlamsl@gmail.com>
Sat, 27 Feb 2021 02:15:14 +0000 (02:15 +0000)
committerGitHub <noreply@github.com>
Sat, 27 Feb 2021 02:15:14 +0000 (10:15 +0800)
fixes #4698
fixes #4700
fixes #4701
fixes #4702

lib/output.js
lib/utils.js
test/compress/exports.js
test/sandbox.js

index bebcd7f..ff05356 100644 (file)
@@ -662,12 +662,15 @@ function OutputStream(options) {
     // a function expression needs parens around it when it's provably
     // the first token to appear in a statement.
     function needs_parens_function(output) {
-        if (!output.has_parens() && first_in_statement(output)) return true;
         var p = output.parent();
-        // export default (function foo() {});
-        if (this.name && p instanceof AST_ExportDefault) return true;
-        // export default (function() {})(foo);
-        if (p && p.TYPE == "Call" && output.parent(1) instanceof AST_ExportDefault) return true;
+        if (!output.has_parens() && first_in_statement(output, false, true)) {
+            // export default function() {}
+            // export default (function foo() {});
+            // export default (function() {})(foo);
+            // export default (function() {})`foo`;
+            // export default (function() {}) ? foo : bar;
+            return this.name || !(p instanceof AST_ExportDefault);
+        }
         if (output.option("webkit") && p instanceof AST_PropAccess && p.expression === this) return true;
         if (output.option("wrap_iife") && p instanceof AST_Call && p.expression === this) return true;
     }
index f9c7843..28c8b43 100644 (file)
@@ -238,7 +238,7 @@ function HOP(obj, prop) {
 // return true if the node at the top of the stack (that means the
 // innermost node in the current output) is lexically the first in
 // a statement.
-function first_in_statement(stack, arrow) {
+function first_in_statement(stack, arrow, export_default) {
     var node = stack.parent(-1);
     for (var i = 0, p; p = stack.parent(i++); node = p) {
         if (is_arrow(p)) {
@@ -250,7 +250,7 @@ function first_in_statement(stack, arrow) {
         } else if (p instanceof AST_Conditional) {
             if (p.condition === node) continue;
         } else if (p instanceof AST_ExportDefault) {
-            return false;
+            return export_default;
         } else if (p instanceof AST_PropAccess) {
             if (p.expression === node) continue;
         } else if (p instanceof AST_Sequence) {
index c573223..2da1ee3 100644 (file)
@@ -70,6 +70,27 @@ defaults_parentheses_4: {
     expect_exact: "export default(function f(){});"
 }
 
+defaults_parentheses_5: {
+    input: {
+        export default (function(a) {
+            console.log(a[0]);
+        }`PASS`);
+    }
+    expect_exact: "export default(function(a){console.log(a[0])})`PASS`;"
+}
+
+defaults_parentheses_6: {
+    options = {
+        conditionals: true,
+    }
+    input: {
+        export default !function() {
+            while (!console);
+        }() ? "PASS" : "FAIL";
+    }
+    expect_exact: 'export default(function(){while(!console);})()?"FAIL":"PASS";'
+}
+
 foreign: {
     input: {
         export * from "foo";
index 1585c98..ceaf008 100644 (file)
@@ -53,7 +53,7 @@ exports.strip_exports = function(code) {
     var count = 0;
     return code.replace(/\bexport(?:\s*\{[^}]*};|\s+default\b(?:\s*(\(|\{|class\s*\{|class\s+(?=extends\b)|(?:async\s+)?function\s*(?:\*\s*)?\())?|\b)/g, function(match, header) {
         if (!header) return "";
-        if (header.length == 1) return "~" + header;
+        if (header.length == 1) return "!!" + header;
         return header.slice(0, -1) + " _" + ++count + header.slice(-1);
     });
 };