15
lib/parse.js
15
lib/parse.js
@@ -653,14 +653,15 @@ function parse($TEXT, options) {
|
||||
input : typeof $TEXT == "string"
|
||||
? tokenizer($TEXT, options.filename, options.html5_comments, options.shebang)
|
||||
: $TEXT,
|
||||
token : null,
|
||||
prev : null,
|
||||
peeked : null,
|
||||
in_async : false,
|
||||
in_function : 0,
|
||||
in_directives : true,
|
||||
in_funarg : -1,
|
||||
in_function : 0,
|
||||
in_loop : 0,
|
||||
labels : []
|
||||
labels : [],
|
||||
peeked : null,
|
||||
prev : null,
|
||||
token : null,
|
||||
};
|
||||
|
||||
S.token = next();
|
||||
@@ -1053,9 +1054,12 @@ function parse($TEXT, options) {
|
||||
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
|
||||
unexpected(prev());
|
||||
expect("(");
|
||||
var was_funarg = S.in_funarg;
|
||||
S.in_funarg = S.in_function;
|
||||
var argnames = expr_list(")", !options.strict, false, function() {
|
||||
return maybe_destructured(AST_SymbolFunarg);
|
||||
});
|
||||
S.in_funarg = was_funarg;
|
||||
var loop = S.in_loop;
|
||||
var labels = S.labels;
|
||||
++S.in_function;
|
||||
@@ -1638,6 +1642,7 @@ function parse($TEXT, options) {
|
||||
function maybe_await() {
|
||||
var start = S.token;
|
||||
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;
|
||||
next();
|
||||
return new AST_Await({
|
||||
|
||||
@@ -12,7 +12,12 @@ describe("async", function() {
|
||||
"function() { function await() {} }",
|
||||
"function() { try {} catch (await) {} }",
|
||||
].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() {
|
||||
UglifyJS.parse("(async " + code + ")();");
|
||||
}, function(e) {
|
||||
@@ -20,4 +25,41 @@ describe("async", function() {
|
||||
}, 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