From e6ebf827ce8eaf75b0ad137aa19d09da2c03df46 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Sat, 27 Feb 2021 02:15:14 +0000 Subject: fix corner cases with `export` (#4699) fixes #4698 fixes #4700 fixes #4701 fixes #4702 --- lib/output.js | 13 ++++++++----- lib/utils.js | 4 ++-- test/compress/exports.js | 21 +++++++++++++++++++++ test/sandbox.js | 2 +- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/lib/output.js b/lib/output.js index bebcd7fd..ff05356e 100644 --- a/lib/output.js +++ b/lib/output.js @@ -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; } diff --git a/lib/utils.js b/lib/utils.js index f9c78431..28c8b43e 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -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) { diff --git a/test/compress/exports.js b/test/compress/exports.js index c573223d..2da1ee33 100644 --- a/test/compress/exports.js +++ b/test/compress/exports.js @@ -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"; diff --git a/test/sandbox.js b/test/sandbox.js index 1585c988..ceaf0088 100644 --- a/test/sandbox.js +++ b/test/sandbox.js @@ -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); }); }; -- cgit v1.2.3