aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2021-02-27 02:15:14 +0000
committerGitHub <noreply@github.com>2021-02-27 10:15:14 +0800
commite6ebf827ce8eaf75b0ad137aa19d09da2c03df46 (patch)
tree5a7ea57681bcd5de18e465b3ed44b6e01631801f
parent0a42457df64944187a069b26491fcebd8ce55ce0 (diff)
downloadtracifyjs-e6ebf827ce8eaf75b0ad137aa19d09da2c03df46.tar.gz
tracifyjs-e6ebf827ce8eaf75b0ad137aa19d09da2c03df46.zip
fix corner cases with `export` (#4699)
fixes #4698 fixes #4700 fixes #4701 fixes #4702
-rw-r--r--lib/output.js13
-rw-r--r--lib/utils.js4
-rw-r--r--test/compress/exports.js21
-rw-r--r--test/sandbox.js2
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);
});
};