summaryrefslogtreecommitdiffstats
path: root/js/src/frontend/Parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/frontend/Parser.cpp')
-rw-r--r--js/src/frontend/Parser.cpp129
1 files changed, 54 insertions, 75 deletions
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
index 0c279591f..cf9f1e27c 100644
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -2474,10 +2474,8 @@ Parser<SyntaxParseHandler>::finishFunction(bool isStandaloneFunction /* = false
}
static YieldHandling
-GetYieldHandling(GeneratorKind generatorKind, FunctionAsyncKind asyncKind)
+GetYieldHandling(GeneratorKind generatorKind)
{
- if (asyncKind == AsyncFunction)
- return YieldIsName;
if (generatorKind == NotGenerator)
return YieldIsName;
return YieldIsKeyword;
@@ -2541,7 +2539,7 @@ Parser<FullParseHandler>::standaloneFunction(HandleFunction fun,
return null();
funpc.setIsStandaloneFunctionBody();
- YieldHandling yieldHandling = GetYieldHandling(generatorKind, asyncKind);
+ YieldHandling yieldHandling = GetYieldHandling(generatorKind);
AutoAwaitIsKeyword<FullParseHandler> awaitIsKeyword(this, asyncKind == AsyncFunction);
if (!functionFormalParametersAndBody(InAllowed, yieldHandling, fn, Statement,
parameterListEnd, /* isStandaloneFunction = */ true))
@@ -2699,7 +2697,7 @@ Parser<ParseHandler>::functionBody(InHandling inHandling, YieldHandling yieldHan
switch (pc->generatorKind()) {
case NotGenerator:
- MOZ_ASSERT(pc->lastYieldOffset == startYieldOffset);
+ MOZ_ASSERT_IF(!pc->isAsync(), pc->lastYieldOffset == startYieldOffset);
break;
case LegacyGenerator:
@@ -2715,12 +2713,12 @@ Parser<ParseHandler>::functionBody(InHandling inHandling, YieldHandling yieldHan
break;
case StarGenerator:
- MOZ_ASSERT_IF(!pc->isAsync(), kind != Arrow);
- MOZ_ASSERT_IF(!pc->isAsync(), type == StatementListBody);
+ MOZ_ASSERT(kind != Arrow);
+ MOZ_ASSERT(type == StatementListBody);
break;
}
- if (pc->isGenerator()) {
+ if (pc->needsDotGeneratorName()) {
MOZ_ASSERT_IF(!pc->isAsync(), type == StatementListBody);
if (!declareDotGeneratorName())
return null();
@@ -2761,9 +2759,9 @@ Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
#endif
switch (kind) {
case Expression:
- flags = (generatorKind == NotGenerator
+ flags = (generatorKind == NotGenerator && asyncKind == SyncFunction
? JSFunction::INTERPRETED_LAMBDA
- : JSFunction::INTERPRETED_LAMBDA_GENERATOR);
+ : JSFunction::INTERPRETED_LAMBDA_GENERATOR_OR_ASYNC);
break;
case Arrow:
flags = JSFunction::INTERPRETED_LAMBDA_ARROW;
@@ -2771,9 +2769,9 @@ Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
break;
case Method:
MOZ_ASSERT(generatorKind == NotGenerator || generatorKind == StarGenerator);
- flags = (generatorKind == NotGenerator
+ flags = (generatorKind == NotGenerator && asyncKind == SyncFunction
? JSFunction::INTERPRETED_METHOD
- : JSFunction::INTERPRETED_METHOD_GENERATOR);
+ : JSFunction::INTERPRETED_METHOD_GENERATOR_OR_ASYNC);
allocKind = gc::AllocKind::FUNCTION_EXTENDED;
break;
case ClassConstructor:
@@ -2799,9 +2797,9 @@ Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
allocKind = gc::AllocKind::FUNCTION_EXTENDED;
}
#endif
- flags = (generatorKind == NotGenerator
+ flags = (generatorKind == NotGenerator && asyncKind == SyncFunction
? JSFunction::INTERPRETED_NORMAL
- : JSFunction::INTERPRETED_GENERATOR);
+ : JSFunction::INTERPRETED_GENERATOR_OR_ASYNC);
}
// We store the async wrapper in a slot for later access.
@@ -3324,7 +3322,6 @@ Parser<ParseHandler>::functionDefinition(uint32_t toStringStart, Node pn, InHand
bool tryAnnexB /* = false */)
{
MOZ_ASSERT_IF(kind == Statement, funName);
- MOZ_ASSERT_IF(asyncKind == AsyncFunction, generatorKind == StarGenerator);
// When fully parsing a LazyScript, we do not fully reparse its inner
// functions, which are also lazy. Instead, their free variables and
@@ -3336,7 +3333,7 @@ Parser<ParseHandler>::functionDefinition(uint32_t toStringStart, Node pn, InHand
}
RootedObject proto(context);
- if (generatorKind == StarGenerator) {
+ if (generatorKind == StarGenerator || asyncKind == AsyncFunction) {
// If we are off the main thread, the generator meta-objects have
// already been created by js::StartOffThreadParseScript, so cx will not
// be necessary.
@@ -3408,7 +3405,7 @@ Parser<FullParseHandler>::trySyntaxParseInnerFunction(ParseNode* pn, HandleFunct
// parse to avoid the overhead of a lazy syntax-only parse. Although
// the prediction may be incorrect, IIFEs are common enough that it
// pays off for lots of code.
- if (pn->isLikelyIIFE() && generatorKind == NotGenerator)
+ if (pn->isLikelyIIFE() && generatorKind == NotGenerator && asyncKind == SyncFunction)
break;
Parser<SyntaxParseHandler>* parser = handler.syntaxParser;
@@ -3584,7 +3581,7 @@ Parser<FullParseHandler>::standaloneLazyFunction(HandleFunction fun, bool strict
if (!tokenStream.peekTokenPos(&pn->pn_pos, modifier))
return null();
- YieldHandling yieldHandling = GetYieldHandling(generatorKind, asyncKind);
+ YieldHandling yieldHandling = GetYieldHandling(generatorKind);
FunctionSyntaxKind syntaxKind = Statement;
if (fun->isClassConstructor())
syntaxKind = ClassConstructor;
@@ -3665,7 +3662,7 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling,
return false;
uint32_t openedPos = 0;
if (tt != TOK_LC) {
- if ((funbox->isStarGenerator() && !funbox->isAsync()) || kind == Method ||
+ if (funbox->isStarGenerator() || kind == Method ||
kind == GetterNoExpressionClosure || kind == SetterNoExpressionClosure ||
IsConstructorKind(kind)) {
error(JSMSG_CURLY_BEFORE_BODY);
@@ -3695,7 +3692,7 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling,
// whether the arrow function is enclosed in a generator function or not.
// Whereas the |yield| in the function body is always parsed as a name.
// The same goes when parsing |await| in arrow functions.
- YieldHandling bodyYieldHandling = GetYieldHandling(pc->generatorKind(), pc->asyncKind());
+ YieldHandling bodyYieldHandling = GetYieldHandling(pc->generatorKind());
Node body;
{
AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, funbox->isAsync());
@@ -3786,12 +3783,8 @@ Parser<ParseHandler>::functionStmt(uint32_t toStringStart, YieldHandling yieldHa
if (!tokenStream.getToken(&tt))
return null();
- GeneratorKind generatorKind = asyncKind == AsyncFunction ? StarGenerator : NotGenerator;
+ GeneratorKind generatorKind = NotGenerator;
if (tt == TOK_MUL) {
- if (asyncKind != SyncFunction) {
- error(JSMSG_ASYNC_GENERATOR);
- return null();
- }
generatorKind = StarGenerator;
if (!tokenStream.getToken(&tt))
return null();
@@ -3817,7 +3810,7 @@ Parser<ParseHandler>::functionStmt(uint32_t toStringStart, YieldHandling yieldHa
MOZ_ASSERT(declaredInStmt->kind() != StatementKind::Label);
MOZ_ASSERT(StatementKindIsBraced(declaredInStmt->kind()));
- if (!pc->sc()->strict() && generatorKind == NotGenerator) {
+ if (!pc->sc()->strict() && generatorKind == NotGenerator && asyncKind == SyncFunction) {
// In sloppy mode, try Annex B.3.3 semantics. If making an
// additional 'var' binding of the same name does not throw an
// early error, do so. This 'var' binding would be assigned
@@ -3841,7 +3834,7 @@ Parser<ParseHandler>::functionStmt(uint32_t toStringStart, YieldHandling yieldHa
if (!pn)
return null();
- YieldHandling newYieldHandling = GetYieldHandling(generatorKind, asyncKind);
+ YieldHandling newYieldHandling = GetYieldHandling(generatorKind);
return functionDefinition(toStringStart, pn, InAllowed, newYieldHandling,
name, Statement, generatorKind, asyncKind, tryAnnexB);
}
@@ -3854,22 +3847,18 @@ Parser<ParseHandler>::functionExpr(uint32_t toStringStart, InvokedPrediction inv
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, asyncKind == AsyncFunction);
- GeneratorKind generatorKind = asyncKind == AsyncFunction ? StarGenerator : NotGenerator;
+ GeneratorKind generatorKind = NotGenerator;
TokenKind tt;
if (!tokenStream.getToken(&tt))
return null();
if (tt == TOK_MUL) {
- if (asyncKind != SyncFunction) {
- error(JSMSG_ASYNC_GENERATOR);
- return null();
- }
generatorKind = StarGenerator;
if (!tokenStream.getToken(&tt))
return null();
}
- YieldHandling yieldHandling = GetYieldHandling(generatorKind, asyncKind);
+ YieldHandling yieldHandling = GetYieldHandling(generatorKind);
RootedPropertyName name(context);
if (TokenKindIsPossibleIdentifier(tt)) {
@@ -5971,6 +5960,7 @@ Parser<ParseHandler>::matchInOrOf(bool* isForInp, bool* isForOfp)
template <class ParseHandler>
bool
Parser<ParseHandler>::forHeadStart(YieldHandling yieldHandling,
+ IteratorKind iterKind,
ParseNodeKind* forHeadKind,
Node* forInitialPart,
Maybe<ParseContext::Scope>& forLoopLexicalScope,
@@ -6061,6 +6051,11 @@ Parser<ParseHandler>::forHeadStart(YieldHandling yieldHandling,
if (!matchInOrOf(&isForIn, &isForOf))
return false;
+ if (iterKind == IteratorKind::Async && !isForOf) {
+ error(JSMSG_FOR_AWAIT_NOT_OF);
+ return false;
+ }
+
// If we don't encounter 'in'/'of', we have a for(;;) loop. We've handled
// the init expression; the caller handles the rest. Allow the Operand
// modifier when regetting: Operand must be used to examine the ';' in
@@ -6134,6 +6129,7 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
ParseContext::Statement stmt(pc, StatementKind::ForLoop);
bool isForEach = false;
+ IteratorKind iterKind = IteratorKind::Sync;
unsigned iflags = 0;
if (allowsForEachIn()) {
@@ -6148,6 +6144,17 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
}
}
+ if (pc->isAsync()) {
+ bool matched;
+ if (!tokenStream.matchToken(&matched, TOK_AWAIT))
+ return null();
+
+ if (matched) {
+ iflags |= JSITER_FORAWAITOF;
+ iterKind = IteratorKind::Async;
+ }
+ }
+
MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
// PNK_FORHEAD, PNK_FORIN, or PNK_FOROF depending on the loop type.
@@ -6185,7 +6192,7 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
//
// In either case the subsequent token can be consistently accessed using
// TokenStream::None semantics.
- if (!forHeadStart(yieldHandling, &headKind, &startNode, forLoopLexicalScope,
+ if (!forHeadStart(yieldHandling, iterKind, &headKind, &startNode, forLoopLexicalScope,
&iteratedExpr))
{
return null();
@@ -6551,29 +6558,6 @@ Parser<ParseHandler>::returnStatement(YieldHandling yieldHandling)
template <typename ParseHandler>
typename ParseHandler::Node
-Parser<ParseHandler>::newYieldExpression(uint32_t begin, typename ParseHandler::Node expr,
- bool isYieldStar)
-{
- Node generator = newDotGeneratorName();
- if (!generator)
- return null();
- if (isYieldStar)
- return handler.newYieldStarExpression(begin, expr, generator);
- return handler.newYieldExpression(begin, expr, generator);
-}
-
-template <typename ParseHandler>
-typename ParseHandler::Node
-Parser<ParseHandler>::newAwaitExpression(uint32_t begin, typename ParseHandler::Node expr)
-{
- Node generator = newDotGeneratorName();
- if (!generator)
- return null();
- return handler.newAwaitExpression(begin, expr, generator);
-}
-
-template <typename ParseHandler>
-typename ParseHandler::Node
Parser<ParseHandler>::yieldExpression(InHandling inHandling)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_YIELD));
@@ -6620,7 +6604,9 @@ Parser<ParseHandler>::yieldExpression(InHandling inHandling)
if (!exprNode)
return null();
}
- return newYieldExpression(begin, exprNode, kind == PNK_YIELD_STAR);
+ if (kind == PNK_YIELD_STAR)
+ return handler.newYieldStarExpression(begin, exprNode);
+ return handler.newYieldExpression(begin, exprNode);
}
case NotGenerator:
@@ -6697,7 +6683,7 @@ Parser<ParseHandler>::yieldExpression(InHandling inHandling)
return null();
}
- return newYieldExpression(begin, exprNode);
+ return handler.newYieldExpression(begin, exprNode);
}
}
@@ -8187,7 +8173,6 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
uint32_t toStringStart = pos().begin;
tokenStream.ungetToken();
- GeneratorKind generatorKind = NotGenerator;
FunctionAsyncKind asyncKind = SyncFunction;
if (next == TOK_ASYNC) {
@@ -8200,7 +8185,6 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
if (nextSameLine == TOK_ARROW) {
tokenStream.ungetToken();
} else {
- generatorKind = StarGenerator;
asyncKind = AsyncFunction;
}
}
@@ -8210,7 +8194,7 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
return null();
Node arrowFunc = functionDefinition(toStringStart, pn, inHandling, yieldHandling, nullptr,
- Arrow, generatorKind, asyncKind);
+ Arrow, NotGenerator, asyncKind);
if (!arrowFunc)
return null();
@@ -8454,7 +8438,7 @@ Parser<ParseHandler>::unaryExpr(YieldHandling yieldHandling, TripledotHandling t
if (!kid)
return null();
pc->lastAwaitOffset = begin;
- return newAwaitExpression(begin, kid);
+ return handler.newAwaitExpression(begin, kid);
}
}
@@ -8712,7 +8696,7 @@ Parser<ParseHandler>::comprehensionTail(GeneratorKind comprehensionKind)
return handler.newArrayPush(begin, bodyExpr);
MOZ_ASSERT(comprehensionKind == StarGenerator);
- Node yieldExpr = newYieldExpression(begin, bodyExpr);
+ Node yieldExpr = handler.newYieldExpression(begin, bodyExpr);
if (!yieldExpr)
return null();
yieldExpr = handler.parenthesize(yieldExpr);
@@ -9494,11 +9478,6 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling,
bool isGenerator = false;
bool isAsync = false;
- if (ltok == TOK_MUL) {
- isGenerator = true;
- if (!tokenStream.getToken(&ltok))
- return null();
- }
if (ltok == TOK_ASYNC) {
// AsyncMethod[Yield, Await]:
@@ -9526,9 +9505,10 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling,
}
}
- if (isAsync && isGenerator) {
- error(JSMSG_ASYNC_GENERATOR);
- return null();
+ if (ltok == TOK_MUL) {
+ isGenerator = true;
+ if (!tokenStream.getToken(&ltok))
+ return null();
}
propAtom.set(nullptr);
@@ -9950,8 +9930,7 @@ Parser<ParseHandler>::methodDefinition(uint32_t toStringStart, PropertyType prop
MOZ_CRASH("Parser: methodDefinition: unexpected property type");
}
- GeneratorKind generatorKind = (propType == PropertyType::GeneratorMethod ||
- propType == PropertyType::AsyncMethod)
+ GeneratorKind generatorKind = propType == PropertyType::GeneratorMethod
? StarGenerator
: NotGenerator;
@@ -9959,7 +9938,7 @@ Parser<ParseHandler>::methodDefinition(uint32_t toStringStart, PropertyType prop
? AsyncFunction
: SyncFunction;
- YieldHandling yieldHandling = GetYieldHandling(generatorKind, asyncKind);
+ YieldHandling yieldHandling = GetYieldHandling(generatorKind);
Node pn = handler.newFunctionExpression();
if (!pn)