var AST_ExportDefault = DEFNODE("ExportDefault", "body", {
$documentation: "An `export default` statement",
$propdoc: {
- body: "[AST_Node] an expression node (should not be instanceof AST_Statement)",
+ body: "[AST_Node] the default export",
},
walk: function(visitor) {
var node = this;
});
},
_validate: function() {
- must_be_expression(this, "body");
+ if (this.body instanceof AST_Lambda && this.body.name) {
+ if (!(this.body instanceof AST_LambdaDefinition)) throw new Error("body must be AST_LambdaDefinition");
+ } else {
+ must_be_expression(this, "body");
+ }
},
}, AST_Statement);
}
}
+ function to_func_expr(defun, drop_name) {
+ var ctor;
+ switch (defun.CTOR) {
+ case AST_AsyncDefun:
+ ctor = AST_AsyncFunction;
+ break;
+ case AST_AsyncGeneratorDefun:
+ ctor = AST_AsyncGeneratorFunction;
+ break;
+ case AST_Defun:
+ ctor = AST_Function;
+ break;
+ case AST_GeneratorDefun:
+ ctor = AST_GeneratorFunction;
+ break;
+ }
+ var fn = make_node(ctor, defun, defun);
+ fn.name = drop_name ? null : make_node(AST_SymbolLambda, defun.name, defun.name);
+ return fn;
+ }
+
AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
if (!compressor.option("unused")) return;
var self = this;
in_use.push(def);
}
initializations.add(def.id, node);
- return true; // don't go in nested scopes
+ if (!(tw.parent() instanceof AST_ExportDefault)) return true;
}
if (node instanceof AST_Definitions) {
node.definitions.forEach(function(defn) {
if (!(def.id in in_use_ids)) {
log(node.name, "Dropping unused function {name}");
def.eliminated++;
+ if (parent instanceof AST_ExportDefault) return to_func_expr(node, true);
return in_list ? List.skip : make_node(AST_EmptyStatement, node);
}
}
def.single_use = false;
fixed._squeezed = true;
fixed.single_use = true;
- if (fixed instanceof AST_LambdaDefinition) {
- var ctor;
- switch (fixed.CTOR) {
- case AST_AsyncDefun:
- ctor = AST_AsyncFunction;
- break;
- case AST_AsyncGeneratorDefun:
- ctor = AST_AsyncGeneratorFunction;
- break;
- case AST_Defun:
- ctor = AST_Function;
- break;
- case AST_GeneratorDefun:
- ctor = AST_GeneratorFunction;
- break;
- }
- fixed = make_node(ctor, fixed, fixed);
- fixed.name = make_node(AST_SymbolLambda, fixed.name, fixed.name);
- }
+ if (fixed instanceof AST_LambdaDefinition) fixed = to_func_expr(fixed);
if (fixed instanceof AST_Lambda) {
var scope = self.scope.resolve();
fixed.enclosed.forEach(function(def) {
// the first token to appear in a statement.
function needs_parens_function(output) {
if (!output.has_parens() && first_in_statement(output)) return true;
- if (output.option("webkit")) {
- var p = output.parent();
- if (p instanceof AST_PropAccess && p.expression === this) return true;
- }
- if (output.option("wrap_iife")) {
- var p = output.parent();
- if (p instanceof AST_Call && p.expression === this) return true;
- }
+ var p = output.parent();
+ // export default (function() {})()
+ if (p && p.TYPE == "Call" && output.parent(1) instanceof AST_ExportDefault) return true;
+ 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;
}
PARENS(AST_AsyncFunction, needs_parens_function);
PARENS(AST_AsyncGeneratorFunction, needs_parens_function);
output.print("default");
output.space();
this.body.print(output);
- output.semicolon();
+ if (!(this.body instanceof AST_Lambda) || is_arrow(this.body)) output.semicolon();
});
DEFPRINT(AST_ExportForeign, function(output) {
var self = this;
}
if (is("keyword", "default")) {
next();
- var body = expression();
- semicolon();
+ var start = S.token;
+ var body = export_default_decl();
+ if (body) {
+ body.start = start;
+ body.end = prev();
+ } else {
+ body = expression();
+ semicolon();
+ }
return new AST_ExportDefault({ body: body });
}
return new AST_ExportDeclaration({ body: export_decl() });
}
+ function maybe_named(def, exp) {
+ var node = function_(exp);
+ if (node.name) {
+ node = new def(node);
+ node.name = new AST_SymbolDefun(node.name);
+ }
+ return node;
+ }
+
+ function export_default_decl() {
+ switch (S.token.value) {
+ case "async":
+ if (!is_token(peek(), "keyword", "function")) return;
+ next();
+ next();
+ if (!is("operator", "*")) return maybe_named(AST_AsyncDefun, AST_AsyncFunction);
+ next();
+ return maybe_named(AST_AsyncGeneratorDefun, AST_AsyncGeneratorFunction);
+ case "function":
+ next();
+ if (!is("operator", "*")) return maybe_named(AST_Defun, AST_Function);
+ next();
+ return maybe_named(AST_GeneratorDefun, AST_GeneratorFunction);
+ }
+ }
+
var export_decl = embed_tokens(function() {
switch (S.token.value) {
case "async":
export default function*(a, b) {};
export default async function f({ c }, ...[ d ]) {};
}
- expect_exact: "export default 42;export default(x,y)=>x*x;export default function*(a,b){};export default async function f({c:c},...[d]){};"
+ expect_exact: "export default 42;export default(x,y)=>x*x;export default function*(a,b){}export default async function f({c:c},...[d]){}"
+}
+
+defaults_parenthesis_1: {
+ input: {
+ export default function() {
+ console.log("FAIL");
+ }(console.log("PASS"));
+ }
+ expect_exact: 'export default function(){console.log("FAIL")}console.log("PASS");'
+}
+
+defaults_parenthesis_2: {
+ input: {
+ export default (async function() {
+ console.log("PASS");
+ })();
+ }
+ expect_exact: 'export default(async function(){console.log("PASS")})();'
}
foreign: {
t(o, f);
}
export default t;
- export default async function t(o, ...{ [c]: e}) {
- (await o)(t, e);
+ export default async function e(t, ...{ [c]: o}) {
+ (await t)(e, o);
}
}
}
t(o, f);
}
export default t;
- export default async function t(o, ...{ [c]: e}) {
- (await o)(t, e);
+ export default async function e(t, ...{ [c]: o}) {
+ (await t)(e, o);
}
}
}
t(a, c);
}
export default 42;
- export default async function t(a, ...{ [o]: f }) {
- (await a)(t, f);
+ export default async function e(t, ...{ [o]: a }) {
+ (await t)(e, a);
};
export { f as bbb, o as ccc, c as fff };
}