15
lib/parse.js
15
lib/parse.js
@@ -653,14 +653,15 @@ function parse($TEXT, options) {
|
|||||||
input : typeof $TEXT == "string"
|
input : typeof $TEXT == "string"
|
||||||
? tokenizer($TEXT, options.filename, options.html5_comments, options.shebang)
|
? tokenizer($TEXT, options.filename, options.html5_comments, options.shebang)
|
||||||
: $TEXT,
|
: $TEXT,
|
||||||
token : null,
|
|
||||||
prev : null,
|
|
||||||
peeked : null,
|
|
||||||
in_async : false,
|
in_async : false,
|
||||||
in_function : 0,
|
|
||||||
in_directives : true,
|
in_directives : true,
|
||||||
|
in_funarg : -1,
|
||||||
|
in_function : 0,
|
||||||
in_loop : 0,
|
in_loop : 0,
|
||||||
labels : []
|
labels : [],
|
||||||
|
peeked : null,
|
||||||
|
prev : null,
|
||||||
|
token : null,
|
||||||
};
|
};
|
||||||
|
|
||||||
S.token = next();
|
S.token = next();
|
||||||
@@ -1053,9 +1054,12 @@ function parse($TEXT, options) {
|
|||||||
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
|
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
|
||||||
unexpected(prev());
|
unexpected(prev());
|
||||||
expect("(");
|
expect("(");
|
||||||
|
var was_funarg = S.in_funarg;
|
||||||
|
S.in_funarg = S.in_function;
|
||||||
var argnames = expr_list(")", !options.strict, false, function() {
|
var argnames = expr_list(")", !options.strict, false, function() {
|
||||||
return maybe_destructured(AST_SymbolFunarg);
|
return maybe_destructured(AST_SymbolFunarg);
|
||||||
});
|
});
|
||||||
|
S.in_funarg = was_funarg;
|
||||||
var loop = S.in_loop;
|
var loop = S.in_loop;
|
||||||
var labels = S.labels;
|
var labels = S.labels;
|
||||||
++S.in_function;
|
++S.in_function;
|
||||||
@@ -1638,6 +1642,7 @@ function parse($TEXT, options) {
|
|||||||
function maybe_await() {
|
function maybe_await() {
|
||||||
var start = S.token;
|
var start = S.token;
|
||||||
if (!(S.in_async && is("name", "await"))) return maybe_unary();
|
if (!(S.in_async && is("name", "await"))) return maybe_unary();
|
||||||
|
if (S.in_funarg === S.in_function) croak("Invalid use of await in function argument");
|
||||||
S.input.context().regex_allowed = true;
|
S.input.context().regex_allowed = true;
|
||||||
next();
|
next();
|
||||||
return new AST_Await({
|
return new AST_Await({
|
||||||
|
|||||||
@@ -12,7 +12,12 @@ describe("async", function() {
|
|||||||
"function() { function await() {} }",
|
"function() { function await() {} }",
|
||||||
"function() { try {} catch (await) {} }",
|
"function() { try {} catch (await) {} }",
|
||||||
].forEach(function(code) {
|
].forEach(function(code) {
|
||||||
UglifyJS.parse("(" + code + ")();");
|
var ast = UglifyJS.parse("(" + code + ")();");
|
||||||
|
assert.strictEqual(ast.TYPE, "Toplevel");
|
||||||
|
assert.strictEqual(ast.body.length, 1);
|
||||||
|
assert.strictEqual(ast.body[0].TYPE, "SimpleStatement");
|
||||||
|
assert.strictEqual(ast.body[0].body.TYPE, "Call");
|
||||||
|
assert.strictEqual(ast.body[0].body.expression.TYPE, "Function");
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
UglifyJS.parse("(async " + code + ")();");
|
UglifyJS.parse("(async " + code + ")();");
|
||||||
}, function(e) {
|
}, function(e) {
|
||||||
@@ -20,4 +25,41 @@ describe("async", function() {
|
|||||||
}, code);
|
}, code);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("Should reject `await` expression outside of async functions", function() {
|
||||||
|
[
|
||||||
|
"await 42;",
|
||||||
|
"function f() { await 42; }",
|
||||||
|
"async function f() { function g() { await 42; } }",
|
||||||
|
].forEach(function(code) {
|
||||||
|
assert.throws(function() {
|
||||||
|
UglifyJS.parse(code);
|
||||||
|
}, function(e) {
|
||||||
|
return e instanceof UglifyJS.JS_Parse_Error;
|
||||||
|
}, code);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("Should reject `await` expression directly on computed key of function argument", function() {
|
||||||
|
[
|
||||||
|
"function f({ [await 42]: a }) {}",
|
||||||
|
"async function f({ [await 42]: a }) {}",
|
||||||
|
].forEach(function(code) {
|
||||||
|
assert.throws(function() {
|
||||||
|
UglifyJS.parse(code);
|
||||||
|
}, function(e) {
|
||||||
|
return e instanceof UglifyJS.JS_Parse_Error;
|
||||||
|
}, code);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("Should accept `await` expression nested within computed key of function argument", function() {
|
||||||
|
[
|
||||||
|
"function f({ [async function() { await 42; }()]: a }) {}",
|
||||||
|
"async function f({ [async function() { await 42; }()]: a }) {}",
|
||||||
|
].forEach(function(code) {
|
||||||
|
var ast = UglifyJS.parse(code);
|
||||||
|
assert.strictEqual(ast.TYPE, "Toplevel");
|
||||||
|
assert.strictEqual(ast.body.length, 1);
|
||||||
|
assert.strictEqual(ast.body[0].argnames.length, 1);
|
||||||
|
assert.strictEqual(ast.body[0].argnames[0].TYPE, "DestructuredObject");
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user