correctly parse export of function & class (#2135)
This commit is contained in:
96
lib/parse.js
96
lib/parse.js
@@ -2413,72 +2413,60 @@ function parse($TEXT, options) {
|
|||||||
function export_() {
|
function export_() {
|
||||||
var start = S.token;
|
var start = S.token;
|
||||||
var is_default;
|
var is_default;
|
||||||
var exported_value;
|
|
||||||
var exported_definition;
|
|
||||||
var exported_names;
|
var exported_names;
|
||||||
|
|
||||||
if (is("keyword", "default")) {
|
if (is("keyword", "default")) {
|
||||||
is_default = true;
|
is_default = true;
|
||||||
next();
|
next();
|
||||||
} else {
|
} else if (exported_names = map_names(false)) {
|
||||||
exported_names = map_names(false);
|
if (is("name", "from")) {
|
||||||
|
next();
|
||||||
|
|
||||||
if (exported_names) {
|
var mod_str = S.token;
|
||||||
if (is("name", "from")) {
|
if (mod_str.type !== 'string') {
|
||||||
next();
|
unexpected();
|
||||||
|
|
||||||
var mod_str = S.token;
|
|
||||||
if (mod_str.type !== 'string') {
|
|
||||||
unexpected();
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
|
|
||||||
return new AST_Export({
|
|
||||||
start: start,
|
|
||||||
is_default: is_default,
|
|
||||||
exported_names: exported_names,
|
|
||||||
module_name: new AST_String({
|
|
||||||
start: mod_str,
|
|
||||||
value: mod_str.value,
|
|
||||||
quote: mod_str.quote,
|
|
||||||
end: mod_str,
|
|
||||||
}),
|
|
||||||
end: prev(),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return new AST_Export({
|
|
||||||
start: start,
|
|
||||||
is_default: is_default,
|
|
||||||
exported_names: exported_names,
|
|
||||||
end: prev(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
next();
|
||||||
|
|
||||||
|
return new AST_Export({
|
||||||
|
start: start,
|
||||||
|
is_default: is_default,
|
||||||
|
exported_names: exported_names,
|
||||||
|
module_name: new AST_String({
|
||||||
|
start: mod_str,
|
||||||
|
value: mod_str.value,
|
||||||
|
quote: mod_str.quote,
|
||||||
|
end: mod_str,
|
||||||
|
}),
|
||||||
|
end: prev(),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return new AST_Export({
|
||||||
|
start: start,
|
||||||
|
is_default: is_default,
|
||||||
|
exported_names: exported_names,
|
||||||
|
end: prev(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var is_definition = is("keyword", "var") || is("keyword", "let") || is("keyword", "const");
|
var node;
|
||||||
if (is_definition) {
|
var exported_value;
|
||||||
if (is_default) unexpected();
|
var exported_definition;
|
||||||
exported_definition = statement();
|
if (is("punc", "{")
|
||||||
} else if (is("keyword", "class")) {
|
|| is_default
|
||||||
var cls = expr_atom(false);
|
&& (is("keyword", "class") || is("keyword", "function"))
|
||||||
if (cls.name) {
|
&& is_token(peek(), "punc")) {
|
||||||
cls.name = new AST_SymbolDefClass(cls.name);
|
|
||||||
exported_definition = new AST_DefClass(cls);
|
|
||||||
} else {
|
|
||||||
exported_value = cls;
|
|
||||||
}
|
|
||||||
} else if (is("keyword", "function")) {
|
|
||||||
var func = expr_atom(false);
|
|
||||||
if (func.name) {
|
|
||||||
func.name = new AST_SymbolDefun(func.name);
|
|
||||||
exported_definition = new AST_Defun(func);
|
|
||||||
} else {
|
|
||||||
exported_value = func;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
exported_value = expression(false);
|
exported_value = expression(false);
|
||||||
semicolon();
|
semicolon();
|
||||||
|
} else if ((node = statement()) instanceof AST_Definitions && is_default) {
|
||||||
|
unexpected(node.start);
|
||||||
|
} else if (node instanceof AST_Definitions || node instanceof AST_Defun || node instanceof AST_DefClass) {
|
||||||
|
exported_definition = node;
|
||||||
|
} else if (node instanceof AST_SimpleStatement) {
|
||||||
|
exported_value = node.body;
|
||||||
|
} else {
|
||||||
|
unexpected(node.start);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new AST_Export({
|
return new AST_Export({
|
||||||
|
|||||||
@@ -107,3 +107,16 @@ issue_2129: {
|
|||||||
export const { keys } = Object;
|
export const { keys } = Object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async_func: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: false,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
export async function Foo(x){};
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
export async function Foo(){};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
1
test/input/invalid/export_2.js
Normal file
1
test/input/invalid/export_2.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export class{};
|
||||||
1
test/input/invalid/export_3.js
Normal file
1
test/input/invalid/export_3.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export function(){};
|
||||||
@@ -534,13 +534,13 @@ describe("bin/uglifyjs", function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should throw syntax error (block-level export)", function(done) {
|
it("Should throw syntax error (block-level export)", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/invalid/export.js -m';
|
var command = uglifyjscmd + ' test/input/invalid/export_1.js -m';
|
||||||
|
|
||||||
exec(command, function (err, stdout, stderr) {
|
exec(command, function (err, stdout, stderr) {
|
||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||||
"Parse error at test/input/invalid/export.js:2,4",
|
"Parse error at test/input/invalid/export_1.js:2,4",
|
||||||
" export var V = 1;",
|
" export var V = 1;",
|
||||||
" ^",
|
" ^",
|
||||||
"ERROR: Export statement may only appear at top level"
|
"ERROR: Export statement may only appear at top level"
|
||||||
@@ -563,6 +563,36 @@ describe("bin/uglifyjs", function () {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("Should throw syntax error (anonymous class)", function(done) {
|
||||||
|
var command = uglifyjscmd + ' test/input/invalid/export_2.js';
|
||||||
|
|
||||||
|
exec(command, function (err, stdout, stderr) {
|
||||||
|
assert.ok(err);
|
||||||
|
assert.strictEqual(stdout, "");
|
||||||
|
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||||
|
"Parse error at test/input/invalid/export_2.js:1,12",
|
||||||
|
"export class{};",
|
||||||
|
" ^",
|
||||||
|
"ERROR: Unexpected token: punc ({)"
|
||||||
|
].join("\n"));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("Should throw syntax error (anonymous function)", function(done) {
|
||||||
|
var command = uglifyjscmd + ' test/input/invalid/export_3.js';
|
||||||
|
|
||||||
|
exec(command, function (err, stdout, stderr) {
|
||||||
|
assert.ok(err);
|
||||||
|
assert.strictEqual(stdout, "");
|
||||||
|
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||||
|
"Parse error at test/input/invalid/export_3.js:1,15",
|
||||||
|
"export function(){};",
|
||||||
|
" ^",
|
||||||
|
"ERROR: Unexpected token: punc (()"
|
||||||
|
].join("\n"));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
it("Should handle literal string as source map input", function(done) {
|
it("Should handle literal string as source map input", function(done) {
|
||||||
var command = [
|
var command = [
|
||||||
uglifyjscmd,
|
uglifyjscmd,
|
||||||
|
|||||||
Reference in New Issue
Block a user