support export statements (#4650)
This commit is contained in:
95
lib/ast.js
95
lib/ast.js
@@ -207,6 +207,7 @@ var AST_Directive = DEFNODE("Directive", "quote value", {
|
||||
_validate: function() {
|
||||
if (this.quote != null) {
|
||||
if (typeof this.quote != "string") throw new Error("quote must be string");
|
||||
if (!/^["']$/.test(this.quote)) throw new Error("invalid quote: " + this.quote);
|
||||
}
|
||||
if (typeof this.value != "string") throw new Error("value must be string");
|
||||
},
|
||||
@@ -238,7 +239,7 @@ function must_be_expression(node, prop) {
|
||||
var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
|
||||
$documentation: "A statement consisting of an expression, i.e. a = 1 + 2",
|
||||
$propdoc: {
|
||||
body: "[AST_Node] an expression node (should not be instanceof AST_Statement)"
|
||||
body: "[AST_Node] an expression node (should not be instanceof AST_Statement)",
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
@@ -1038,6 +1039,86 @@ var AST_VarDef = DEFNODE("VarDef", "name value", {
|
||||
|
||||
/* -----[ OTHER ]----- */
|
||||
|
||||
var AST_ExportDeclaration = DEFNODE("ExportDeclaration", "body", {
|
||||
$documentation: "An `export` statement",
|
||||
$propdoc: {
|
||||
body: "[AST_Definitions|AST_LambdaDefinition] the statement to export",
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
node.body.walk(visitor);
|
||||
});
|
||||
},
|
||||
_validate: function() {
|
||||
if (!(this.body instanceof AST_Definitions || this.body instanceof AST_LambdaDefinition)) {
|
||||
throw new Error("body must be AST_Definitions or AST_LambdaDefinition");
|
||||
}
|
||||
},
|
||||
}, AST_Statement);
|
||||
|
||||
var AST_ExportDefault = DEFNODE("ExportDefault", "body", {
|
||||
$documentation: "An `export default` statement",
|
||||
$propdoc: {
|
||||
body: "[AST_Node] an expression node (should not be instanceof AST_Statement)",
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
node.body.walk(visitor);
|
||||
});
|
||||
},
|
||||
_validate: function() {
|
||||
must_be_expression(this, "body");
|
||||
},
|
||||
}, AST_Statement);
|
||||
|
||||
var AST_ExportForeign = DEFNODE("ExportForeign", "aliases keys path quote", {
|
||||
$documentation: "An `export ... from '...'` statement",
|
||||
$propdoc: {
|
||||
aliases: "[string*] array of aliases to export",
|
||||
keys: "[string*] array of keys to import",
|
||||
path: "[string] the path to import module",
|
||||
quote: "[string?] the original quote character",
|
||||
},
|
||||
_validate: function() {
|
||||
if (this.aliases.length != this.keys.length) {
|
||||
throw new Error("aliases:key length mismatch: " + this.aliases.length + " != " + this.keys.length);
|
||||
}
|
||||
this.aliases.forEach(function(name) {
|
||||
if (typeof name != "string") throw new Error("aliases must contain string");
|
||||
});
|
||||
this.keys.forEach(function(name) {
|
||||
if (typeof name != "string") throw new Error("keys must contain string");
|
||||
});
|
||||
if (typeof this.path != "string") throw new Error("path must be string");
|
||||
if (this.quote != null) {
|
||||
if (typeof this.quote != "string") throw new Error("quote must be string");
|
||||
if (!/^["']$/.test(this.quote)) throw new Error("invalid quote: " + this.quote);
|
||||
}
|
||||
},
|
||||
}, AST_Statement);
|
||||
|
||||
var AST_ExportReferences = DEFNODE("ExportReferences", "properties", {
|
||||
$documentation: "An `export { ... }` statement",
|
||||
$propdoc: {
|
||||
properties: "[AST_SymbolExport*] array of aliases to export",
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
node.properties.forEach(function(prop) {
|
||||
prop.walk(visitor);
|
||||
});
|
||||
});
|
||||
},
|
||||
_validate: function() {
|
||||
this.properties.forEach(function(prop) {
|
||||
if (!(prop instanceof AST_SymbolExport)) throw new Error("properties must contain AST_SymbolExport");
|
||||
});
|
||||
},
|
||||
}, AST_Statement);
|
||||
|
||||
var AST_Import = DEFNODE("Import", "all default path properties quote", {
|
||||
$documentation: "An `import` statement",
|
||||
$propdoc: {
|
||||
@@ -1072,6 +1153,7 @@ var AST_Import = DEFNODE("Import", "all default path properties quote", {
|
||||
});
|
||||
if (this.quote != null) {
|
||||
if (typeof this.quote != "string") throw new Error("quote must be string");
|
||||
if (!/^["']$/.test(this.quote)) throw new Error("invalid quote: " + this.quote);
|
||||
}
|
||||
},
|
||||
}, AST_Statement);
|
||||
@@ -1572,6 +1654,16 @@ var AST_SymbolRef = DEFNODE("SymbolRef", "fixed in_arg redef", {
|
||||
$documentation: "Reference to some symbol (not definition/declaration)",
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_SymbolExport = DEFNODE("SymbolExport", "alias", {
|
||||
$documentation: "Reference in an `export` statement",
|
||||
$propdoc: {
|
||||
alias: "[string] the `export` alias",
|
||||
},
|
||||
_validate: function() {
|
||||
if (typeof this.alias != "string") throw new Error("alias must be string");
|
||||
},
|
||||
}, AST_SymbolRef);
|
||||
|
||||
var AST_LabelRef = DEFNODE("LabelRef", null, {
|
||||
$documentation: "Reference to a label symbol",
|
||||
}, AST_Symbol);
|
||||
@@ -1627,6 +1719,7 @@ var AST_String = DEFNODE("String", "quote value", {
|
||||
_validate: function() {
|
||||
if (this.quote != null) {
|
||||
if (typeof this.quote != "string") throw new Error("quote must be string");
|
||||
if (!/^["']$/.test(this.quote)) throw new Error("invalid quote: " + this.quote);
|
||||
}
|
||||
if (typeof this.value != "string") throw new Error("value must be string");
|
||||
},
|
||||
|
||||
@@ -173,6 +173,7 @@ Compressor.prototype = new TreeTransformer;
|
||||
merge(Compressor.prototype, {
|
||||
option: function(key) { return this.options[key] },
|
||||
exposed: function(def) {
|
||||
if (def.exported) return true;
|
||||
if (def.undeclared) return true;
|
||||
if (!(def.global || def.scope.resolve() instanceof AST_Toplevel)) return false;
|
||||
var toplevel = this.toplevel;
|
||||
@@ -5583,7 +5584,7 @@ merge(Compressor.prototype, {
|
||||
if (scope === self) {
|
||||
if (node instanceof AST_LambdaDefinition) {
|
||||
var def = node.name.definition();
|
||||
if (!drop_funcs && !(def.id in in_use_ids)) {
|
||||
if ((!drop_funcs || def.exported) && !(def.id in in_use_ids)) {
|
||||
in_use_ids[def.id] = true;
|
||||
in_use.push(def);
|
||||
}
|
||||
@@ -5602,7 +5603,7 @@ merge(Compressor.prototype, {
|
||||
var redef = def.redefined();
|
||||
if (redef) var_defs[redef.id] = (var_defs[redef.id] || 0) + 1;
|
||||
}
|
||||
if (!(def.id in in_use_ids) && (!drop_vars
|
||||
if (!(def.id in in_use_ids) && (!drop_vars || def.exported
|
||||
|| (node instanceof AST_Const ? def.redefined() : def.const_redefs)
|
||||
|| !(node instanceof AST_Var || is_safe_lexical(def)))) {
|
||||
in_use_ids[def.id] = true;
|
||||
|
||||
@@ -892,10 +892,6 @@ function OutputStream(options) {
|
||||
use_asm = was_asm;
|
||||
}
|
||||
|
||||
DEFPRINT(AST_Statement, function(output) {
|
||||
this.body.print(output);
|
||||
output.semicolon();
|
||||
});
|
||||
DEFPRINT(AST_Toplevel, function(output) {
|
||||
display_body(this.body, true, output, true);
|
||||
output.print("");
|
||||
@@ -1011,6 +1007,64 @@ function OutputStream(options) {
|
||||
output.space();
|
||||
force_statement(self.body, output);
|
||||
});
|
||||
DEFPRINT(AST_ExportDeclaration, function(output) {
|
||||
output.print("export");
|
||||
output.space();
|
||||
this.body.print(output);
|
||||
});
|
||||
DEFPRINT(AST_ExportDefault, function(output) {
|
||||
output.print("export");
|
||||
output.space();
|
||||
output.print("default");
|
||||
output.space();
|
||||
this.body.print(output);
|
||||
output.semicolon();
|
||||
});
|
||||
DEFPRINT(AST_ExportForeign, function(output) {
|
||||
var self = this;
|
||||
output.print("export");
|
||||
output.space();
|
||||
var len = self.keys.length;
|
||||
if (len == 0) {
|
||||
print_braced_empty(self, output);
|
||||
} else if (self.keys[0] == "*") {
|
||||
print_entry(0);
|
||||
} else output.with_block(function() {
|
||||
output.indent();
|
||||
print_entry(0);
|
||||
for (var i = 1; i < len; i++) {
|
||||
output.print(",");
|
||||
output.newline();
|
||||
output.indent();
|
||||
print_entry(i);
|
||||
}
|
||||
output.newline();
|
||||
});
|
||||
output.space();
|
||||
output.print("from");
|
||||
output.space();
|
||||
output.print_string(self.path, self.quote);
|
||||
output.semicolon();
|
||||
|
||||
function print_entry(index) {
|
||||
var alias = self.aliases[index];
|
||||
var key = self.keys[index];
|
||||
output.print_name(key);
|
||||
if (alias != key) {
|
||||
output.space();
|
||||
output.print("as");
|
||||
output.space();
|
||||
output.print_name(alias);
|
||||
}
|
||||
}
|
||||
});
|
||||
DEFPRINT(AST_ExportReferences, function(output) {
|
||||
var self = this;
|
||||
output.print("export");
|
||||
output.space();
|
||||
print_properties(self, output);
|
||||
output.semicolon();
|
||||
});
|
||||
DEFPRINT(AST_Import, function(output) {
|
||||
var self = this;
|
||||
output.print("import");
|
||||
@@ -1543,6 +1597,16 @@ function OutputStream(options) {
|
||||
DEFPRINT(AST_Symbol, function(output) {
|
||||
print_symbol(this, output);
|
||||
});
|
||||
DEFPRINT(AST_SymbolExport, function(output) {
|
||||
var self = this;
|
||||
print_symbol(self, output);
|
||||
if (self.alias) {
|
||||
output.space();
|
||||
output.print("as");
|
||||
output.space();
|
||||
output.print_name(self.alias);
|
||||
}
|
||||
});
|
||||
DEFPRINT(AST_SymbolImport, function(output) {
|
||||
var self = this;
|
||||
if (self.key) {
|
||||
|
||||
117
lib/parse.js
117
lib/parse.js
@@ -844,6 +844,9 @@ function parse($TEXT, options) {
|
||||
case "await":
|
||||
if (S.in_async) return simple_statement();
|
||||
break;
|
||||
case "export":
|
||||
next();
|
||||
return export_();
|
||||
case "import":
|
||||
next();
|
||||
return import_();
|
||||
@@ -1275,6 +1278,115 @@ function parse($TEXT, options) {
|
||||
});
|
||||
}
|
||||
|
||||
function is_alias() {
|
||||
return is("name") || is_identifier_string(S.token.value);
|
||||
}
|
||||
|
||||
function export_() {
|
||||
if (is("operator", "*")) {
|
||||
next();
|
||||
var alias = "*";
|
||||
if (is("name", "as")) {
|
||||
next();
|
||||
if (!is_alias()) expect_token("name");
|
||||
alias = S.token.value;
|
||||
next();
|
||||
}
|
||||
expect_token("name", "from");
|
||||
var path = S.token;
|
||||
expect_token("string");
|
||||
semicolon();
|
||||
return new AST_ExportForeign({
|
||||
aliases: [ alias ],
|
||||
keys: [ "*" ],
|
||||
path: path.value,
|
||||
quote: path.quote,
|
||||
});
|
||||
}
|
||||
if (is("punc", "{")) {
|
||||
next();
|
||||
var aliases = [];
|
||||
var keys = [];
|
||||
while (is_alias()) {
|
||||
var key = S.token;
|
||||
next();
|
||||
keys.push(key);
|
||||
if (is("name", "as")) {
|
||||
next();
|
||||
if (!is_alias()) expect_token("name");
|
||||
aliases.push(S.token.value);
|
||||
next();
|
||||
} else {
|
||||
aliases.push(key.value);
|
||||
}
|
||||
if (!is("punc", "}")) expect(",");
|
||||
}
|
||||
expect("}");
|
||||
if (is("name", "from")) {
|
||||
next();
|
||||
var path = S.token;
|
||||
expect_token("string");
|
||||
semicolon();
|
||||
return new AST_ExportForeign({
|
||||
aliases: aliases,
|
||||
keys: keys.map(function(token) {
|
||||
return token.value;
|
||||
}),
|
||||
path: path.value,
|
||||
quote: path.quote,
|
||||
});
|
||||
}
|
||||
semicolon();
|
||||
return new AST_ExportReferences({
|
||||
properties: keys.map(function(token, index) {
|
||||
if (!is_token(token, "name")) token_error(token, "Name expected");
|
||||
var sym = _make_symbol(AST_SymbolExport, token);
|
||||
sym.alias = aliases[index];
|
||||
return sym;
|
||||
}),
|
||||
});
|
||||
}
|
||||
if (is("keyword", "default")) {
|
||||
next();
|
||||
var body = expression();
|
||||
semicolon();
|
||||
return new AST_ExportDefault({ body: body });
|
||||
}
|
||||
return new AST_ExportDeclaration({ body: export_decl() });
|
||||
}
|
||||
|
||||
var export_decl = embed_tokens(function() {
|
||||
switch (S.token.value) {
|
||||
case "async":
|
||||
next();
|
||||
expect_token("keyword", "function");
|
||||
if (!is("operator", "*")) return function_(AST_AsyncDefun);
|
||||
next();
|
||||
return function_(AST_AsyncGeneratorDefun);
|
||||
case "const":
|
||||
next();
|
||||
var node = const_();
|
||||
semicolon();
|
||||
return node;
|
||||
case "function":
|
||||
next();
|
||||
if (!is("operator", "*")) return function_(AST_Defun);
|
||||
next();
|
||||
return function_(AST_GeneratorDefun);
|
||||
case "let":
|
||||
next();
|
||||
var node = let_();
|
||||
semicolon();
|
||||
return node;
|
||||
case "var":
|
||||
next();
|
||||
var node = var_();
|
||||
semicolon();
|
||||
return node;
|
||||
}
|
||||
unexpected();
|
||||
});
|
||||
|
||||
function import_() {
|
||||
var all = null;
|
||||
var def = as_symbol(AST_SymbolImport, true);
|
||||
@@ -1288,7 +1400,7 @@ function parse($TEXT, options) {
|
||||
} else {
|
||||
expect("{");
|
||||
props = [];
|
||||
while (is("name") || is_identifier_string(S.token.value)) {
|
||||
while (is_alias()) {
|
||||
var alias;
|
||||
if (is_token(peek(), "name", "as")) {
|
||||
var key = S.token.value;
|
||||
@@ -1307,9 +1419,8 @@ function parse($TEXT, options) {
|
||||
}
|
||||
}
|
||||
if (all || def || props) expect_token("name", "from");
|
||||
if (!is("string")) unexpected();
|
||||
var path = S.token;
|
||||
next();
|
||||
expect_token("string");
|
||||
semicolon();
|
||||
return new AST_Import({
|
||||
all: all,
|
||||
|
||||
23
lib/scope.js
23
lib/scope.js
@@ -45,6 +45,7 @@
|
||||
|
||||
function SymbolDef(id, scope, orig, init) {
|
||||
this.eliminated = 0;
|
||||
this.exported = false;
|
||||
this.global = false;
|
||||
this.id = id;
|
||||
this.init = init;
|
||||
@@ -91,6 +92,7 @@ SymbolDef.prototype = {
|
||||
},
|
||||
unmangleable: function(options) {
|
||||
return this.global && !options.toplevel
|
||||
|| this.exported
|
||||
|| this.undeclared
|
||||
|| !options.eval && this.scope.pinned()
|
||||
|| options.keep_fnames
|
||||
@@ -118,11 +120,22 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
// pass 1: setup scope chaining and handle definitions
|
||||
var self = this;
|
||||
var defun = null;
|
||||
var exported = false;
|
||||
var next_def_id = 0;
|
||||
var scope = self.parent_scope = null;
|
||||
var tw = new TreeWalker(function(node, descend) {
|
||||
if (node instanceof AST_Definitions) {
|
||||
var save_exported = exported;
|
||||
exported = tw.parent() instanceof AST_ExportDeclaration;
|
||||
descend();
|
||||
exported = save_exported;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_LambdaDefinition) {
|
||||
var save_exported = exported;
|
||||
exported = tw.parent() instanceof AST_ExportDeclaration;
|
||||
node.name.walk(tw);
|
||||
exported = save_exported;
|
||||
walk_scope(function() {
|
||||
node.argnames.forEach(function(argname) {
|
||||
argname.walk(tw);
|
||||
@@ -169,9 +182,11 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
if (node instanceof AST_SymbolCatch) {
|
||||
scope.def_variable(node).defun = defun;
|
||||
} else if (node instanceof AST_SymbolConst) {
|
||||
scope.def_variable(node).defun = defun;
|
||||
var def = scope.def_variable(node);
|
||||
def.defun = defun;
|
||||
def.exported = exported;
|
||||
} else if (node instanceof AST_SymbolDefun) {
|
||||
defun.def_function(node, tw.parent());
|
||||
defun.def_function(node, tw.parent()).exported = exported;
|
||||
entangle(defun, scope);
|
||||
} else if (node instanceof AST_SymbolFunarg) {
|
||||
defun.def_variable(node);
|
||||
@@ -180,9 +195,9 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
var def = defun.def_function(node, node.name == "arguments" ? undefined : defun);
|
||||
if (options.ie8) def.defun = defun.parent_scope.resolve();
|
||||
} else if (node instanceof AST_SymbolLet) {
|
||||
scope.def_variable(node);
|
||||
scope.def_variable(node).exported = exported;
|
||||
} else if (node instanceof AST_SymbolVar) {
|
||||
defun.def_variable(node, null);
|
||||
defun.def_variable(node, null).exported = exported;
|
||||
entangle(defun, scope);
|
||||
}
|
||||
|
||||
|
||||
@@ -204,6 +204,15 @@ TreeTransformer.prototype = new TreeWalker;
|
||||
if (self.key instanceof AST_Node) self.key = self.key.transform(tw);
|
||||
self.value = self.value.transform(tw);
|
||||
});
|
||||
DEF(AST_ExportDeclaration, function(self, tw) {
|
||||
self.body = self.body.transform(tw);
|
||||
});
|
||||
DEF(AST_ExportDefault, function(self, tw) {
|
||||
self.body = self.body.transform(tw);
|
||||
});
|
||||
DEF(AST_ExportReferences, function(self, tw) {
|
||||
self.properties = do_list(self.properties, tw);
|
||||
});
|
||||
DEF(AST_Import, function(self, tw) {
|
||||
if (self.all) self.all = self.all.transform(tw);
|
||||
if (self.default) self.default = self.default.transform(tw);
|
||||
|
||||
@@ -249,12 +249,14 @@ function first_in_statement(stack, arrow) {
|
||||
if (p.expression === node) continue;
|
||||
} else if (p instanceof AST_Conditional) {
|
||||
if (p.condition === node) continue;
|
||||
} else if (p instanceof AST_ExportDefault) {
|
||||
return false;
|
||||
} else if (p instanceof AST_PropAccess) {
|
||||
if (p.expression === node) continue;
|
||||
} else if (p instanceof AST_Sequence) {
|
||||
if (p.expressions[0] === node) continue;
|
||||
} else if (p instanceof AST_Statement) {
|
||||
return p.body === node;
|
||||
} else if (p instanceof AST_SimpleStatement) {
|
||||
return true;
|
||||
} else if (p instanceof AST_Template) {
|
||||
if (p.tag === node) continue;
|
||||
} else if (p instanceof AST_UnaryPostfix) {
|
||||
|
||||
144
test/compress/exports.js
Normal file
144
test/compress/exports.js
Normal file
@@ -0,0 +1,144 @@
|
||||
refs: {
|
||||
input: {
|
||||
export {};
|
||||
export { a, b as B, c as case, d as default };
|
||||
}
|
||||
expect_exact: "export{};export{a as a,b as B,c as case,d as default};"
|
||||
}
|
||||
|
||||
var_defs: {
|
||||
input: {
|
||||
export const a = 1;
|
||||
export let b = 2, c = 3;
|
||||
export var { d, e: [] } = f;
|
||||
}
|
||||
expect_exact: "export const a=1;export let b=2,c=3;export var{d:d,e:[]}=f;"
|
||||
}
|
||||
|
||||
defuns: {
|
||||
input: {
|
||||
export function e() {}
|
||||
export function* f(a) {}
|
||||
export async function g(b, c) {}
|
||||
export async function* h({}, ...[]) {}
|
||||
}
|
||||
expect_exact: "export function e(){}export function*f(a){}export async function g(b,c){}export async function*h({},...[]){}"
|
||||
}
|
||||
|
||||
defaults: {
|
||||
input: {
|
||||
export default 42;
|
||||
export default (x, y) => x * x;
|
||||
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]){};"
|
||||
}
|
||||
|
||||
foreign: {
|
||||
input: {
|
||||
export * from "foo";
|
||||
export {} from "bar";
|
||||
export * as a from "baz";
|
||||
export { default } from "moo";
|
||||
export { b, c as case, default as delete, d } from "moz";
|
||||
}
|
||||
expect_exact: 'export*from"foo";export{}from"bar";export*as a from"baz";export{default}from"moo";export{b,c as case,default as delete,d}from"moz";'
|
||||
}
|
||||
|
||||
same_quotes: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
quote_style: 3,
|
||||
}
|
||||
input: {
|
||||
export * from 'foo';
|
||||
export {} from "bar";
|
||||
}
|
||||
expect_exact: [
|
||||
"export * from 'foo';",
|
||||
"",
|
||||
'export {} from "bar";',
|
||||
]
|
||||
}
|
||||
|
||||
drop_unused: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
export default 42;
|
||||
export default (x, y) => x * x;
|
||||
export default function*(a, b) {};
|
||||
export default async function f({ c }, ...[ d ]) {};
|
||||
export var e;
|
||||
export function g(x, [ y ], ...z) {}
|
||||
}
|
||||
expect: {
|
||||
export default 42;
|
||||
export default (x, y) => x * x;
|
||||
export default function*(a, b) {};
|
||||
export default async function({}) {};
|
||||
export var e;
|
||||
export function g(x, []) {}
|
||||
}
|
||||
}
|
||||
|
||||
mangle: {
|
||||
rename = false
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
const a = 42;
|
||||
export let b, { foo: c } = a;
|
||||
export function f(d, { [b]: e }) {
|
||||
d(e, f);
|
||||
}
|
||||
export default a;
|
||||
export default async function g(x, ...{ [c]: y }) {
|
||||
(await x)(g, y);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
const t = 42;
|
||||
export let b, { foo: c } = t;
|
||||
export function f(t, { [b]: o }) {
|
||||
t(o, f);
|
||||
}
|
||||
export default t;
|
||||
export default async function t(o, ...{ [c]: e}) {
|
||||
(await o)(t, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mangle_rename: {
|
||||
rename = true
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
const a = 42;
|
||||
export let b, { foo: c } = a;
|
||||
export function f(d, { [b]: e }) {
|
||||
d(e, f);
|
||||
}
|
||||
export default a;
|
||||
export default async function g(x, ...{ [c]: y }) {
|
||||
(await x)(g, y);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
const t = 42;
|
||||
export let b, { foo: c } = t;
|
||||
export function f(t, { [b]: o }) {
|
||||
t(o, f);
|
||||
}
|
||||
export default t;
|
||||
export default async function t(o, ...{ [c]: e}) {
|
||||
(await o)(t, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
71
test/mocha/exports.js
Normal file
71
test/mocha/exports.js
Normal file
@@ -0,0 +1,71 @@
|
||||
var assert = require("assert");
|
||||
var UglifyJS = require("../node");
|
||||
|
||||
describe("export", function() {
|
||||
it("Should reject invalid `export ...` statement syntax", function() {
|
||||
[
|
||||
"export *;",
|
||||
"export A;",
|
||||
"export 42;",
|
||||
"export var;",
|
||||
"export * as A;",
|
||||
"export A as B;",
|
||||
"export const A;",
|
||||
"export function(){};",
|
||||
].forEach(function(code) {
|
||||
assert.throws(function() {
|
||||
UglifyJS.parse(code);
|
||||
}, function(e) {
|
||||
return e instanceof UglifyJS.JS_Parse_Error;
|
||||
}, code);
|
||||
});
|
||||
});
|
||||
it("Should reject invalid `export { ... }` statement syntax", function() {
|
||||
[
|
||||
"export { * };",
|
||||
"export { * as A };",
|
||||
"export { 42 as A };",
|
||||
"export { A as B-C };",
|
||||
"export { default as A };",
|
||||
].forEach(function(code) {
|
||||
assert.throws(function() {
|
||||
UglifyJS.parse(code);
|
||||
}, function(e) {
|
||||
return e instanceof UglifyJS.JS_Parse_Error;
|
||||
}, code);
|
||||
});
|
||||
});
|
||||
it("Should reject invalid `export default ...` statement syntax", function() {
|
||||
[
|
||||
"export default *;",
|
||||
"export default var;",
|
||||
"export default A as B;",
|
||||
].forEach(function(code) {
|
||||
assert.throws(function() {
|
||||
UglifyJS.parse(code);
|
||||
}, function(e) {
|
||||
return e instanceof UglifyJS.JS_Parse_Error;
|
||||
}, code);
|
||||
});
|
||||
});
|
||||
it("Should reject invalid `export ... from ...` statement syntax", function() {
|
||||
[
|
||||
"export from 'path';",
|
||||
"export * from `path`;",
|
||||
"export A as B from 'path';",
|
||||
"export default from 'path';",
|
||||
"export { A }, B from 'path';",
|
||||
"export * as A, B from 'path';",
|
||||
"export * as A, {} from 'path';",
|
||||
"export { * as A } from 'path';",
|
||||
"export { 42 as A } from 'path';",
|
||||
"export { A-B as C } from 'path';",
|
||||
].forEach(function(code) {
|
||||
assert.throws(function() {
|
||||
UglifyJS.parse(code);
|
||||
}, function(e) {
|
||||
return e instanceof UglifyJS.JS_Parse_Error;
|
||||
}, code);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user