support async function (#4333)

This commit is contained in:
Alex Lam S.L
2020-12-06 21:22:40 +00:00
committed by GitHub
parent 3c384cf9a8
commit 2cbbf5c375
11 changed files with 434 additions and 62 deletions

View File

@@ -47,7 +47,7 @@
var KEYWORDS = "break case catch const continue debugger default delete do else finally for function if in instanceof let new return switch throw try typeof var void while with";
var KEYWORDS_ATOM = "false null true";
var RESERVED_WORDS = [
"abstract boolean byte char class double enum export extends final float goto implements import int interface let long native package private protected public short static super synchronized this throws transient volatile yield",
"await abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile yield",
KEYWORDS_ATOM,
KEYWORDS,
].join(" ");
@@ -656,6 +656,7 @@ function parse($TEXT, options) {
token : null,
prev : null,
peeked : null,
in_async : false,
in_function : 0,
in_directives : true,
in_loop : 0,
@@ -786,9 +787,20 @@ function parse($TEXT, options) {
return simple_statement();
case "name":
return is_token(peek(), "punc", ":")
? labeled_statement()
: simple_statement();
switch (S.token.value) {
case "async":
if (is_token(peek(), "keyword", "function")) {
next();
next();
return function_(AST_AsyncDefun);
}
case "await":
if (S.in_async) return simple_statement();
default:
return is_token(peek(), "punc", ":")
? labeled_statement()
: simple_statement();
}
case "punc":
switch (S.token.value) {
@@ -1026,10 +1038,18 @@ function parse($TEXT, options) {
}
var function_ = function(ctor) {
var in_statement = ctor === AST_Defun;
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
if (in_statement && !name)
expect_token("name");
var was_async = S.in_async;
var name;
if (ctor === AST_AsyncDefun) {
name = as_symbol(AST_SymbolDefun);
S.in_async = true;
} else if (ctor === AST_Defun) {
name = as_symbol(AST_SymbolDefun);
S.in_async = false;
} else {
S.in_async = ctor === AST_AsyncFunction;
name = as_symbol(AST_SymbolLambda, true);
}
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
unexpected(prev());
expect("(");
@@ -1055,6 +1075,7 @@ function parse($TEXT, options) {
--S.in_function;
S.in_loop = loop;
S.labels = labels;
S.in_async = was_async;
return new ctor({
name: name,
argnames: argnames,
@@ -1304,9 +1325,16 @@ function parse($TEXT, options) {
}
unexpected();
}
if (is("keyword", "function")) {
var ctor;
if (is("name", "async") && is_token(peek(), "keyword", "function")) {
next();
var func = function_(AST_Function);
ctor = AST_AsyncFunction;
} else if (is("keyword", "function")) {
ctor = AST_Function;
}
if (ctor) {
next();
var func = function_(ctor);
func.start = start;
func.end = prev();
return subscripts(func, allow_calls);
@@ -1451,6 +1479,7 @@ function parse($TEXT, options) {
function _make_symbol(type, token) {
var name = token.value;
if (name === "await" && S.in_async) unexpected(token);
return new (name === "this" ? AST_This : type)({
name: "" + name,
start: token,
@@ -1573,17 +1602,17 @@ function parse($TEXT, options) {
return expr;
};
var maybe_unary = function(allow_calls) {
function maybe_unary() {
var start = S.token;
if (is("operator") && UNARY_PREFIX[start.value]) {
next();
handle_regexp();
var ex = make_unary(AST_UnaryPrefix, start, maybe_unary(allow_calls));
var ex = make_unary(AST_UnaryPrefix, start, maybe_await());
ex.start = start;
ex.end = prev();
return ex;
}
var val = expr_atom(allow_calls);
var val = expr_atom(true);
while (is("operator") && UNARY_POSTFIX[S.token.value] && !has_newline_before(S.token)) {
val = make_unary(AST_UnaryPostfix, S.token, val);
val.start = start;
@@ -1591,7 +1620,7 @@ function parse($TEXT, options) {
next();
}
return val;
};
}
function make_unary(ctor, token, expr) {
var op = token.value;
@@ -1609,13 +1638,24 @@ function parse($TEXT, options) {
return new ctor({ operator: op, expression: expr });
}
function maybe_await() {
var start = S.token;
if (!(S.in_async && is("name", "await"))) return maybe_unary();
next();
return new AST_Await({
start: start,
expression: maybe_await(),
end: prev(),
});
}
var expr_op = function(left, min_prec, no_in) {
var op = is("operator") ? S.token.value : null;
if (op == "in" && no_in) op = null;
var prec = op != null ? PRECEDENCE[op] : null;
if (prec != null && prec > min_prec) {
next();
var right = expr_op(maybe_unary(true), prec, no_in);
var right = expr_op(maybe_await(), prec, no_in);
return expr_op(new AST_Binary({
start : left.start,
left : left,
@@ -1628,7 +1668,7 @@ function parse($TEXT, options) {
};
function expr_ops(no_in) {
return expr_op(maybe_unary(true), 0, no_in);
return expr_op(maybe_await(), 0, no_in);
}
var maybe_conditional = function(no_in) {