From 4a84afdc892dcc3a1732b45e5ac65812daa53fae Mon Sep 17 00:00:00 2001 From: Gaming4JC Date: Sun, 14 Jul 2019 22:12:08 -0400 Subject: 1353691 - Report SyntaxError when arrow function has await-identifier in async function context. --- js/src/frontend/Parser.cpp | 59 ++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 25 deletions(-) (limited to 'js/src/frontend') diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 47e0f943d..0c279591f 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -3623,9 +3623,14 @@ Parser::functionFormalParametersAndBody(InHandling inHandling, FunctionBox* funbox = pc->functionBox(); RootedFunction fun(context, funbox->function()); - AutoAwaitIsKeyword awaitIsKeyword(this, funbox->isAsync()); - if (!functionArguments(yieldHandling, kind, pn)) - return false; + // See below for an explanation why arrow function parameters and arrow + // function bodies are parsed with different yield/await settings. + { + bool asyncOrArrowInAsync = funbox->isAsync() || (kind == Arrow && awaitIsKeyword()); + AutoAwaitIsKeyword awaitIsKeyword(this, asyncOrArrowInAsync); + if (!functionArguments(yieldHandling, kind, pn)) + return false; + } Maybe varScope; if (funbox->hasParameterExprs) { @@ -3689,32 +3694,36 @@ Parser::functionFormalParametersAndBody(InHandling inHandling, // |yield| in the parameters is either a name or keyword, depending on // 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()); - Node body = functionBody(inHandling, bodyYieldHandling, kind, bodyType); - if (!body) - return false; + Node body; + { + AutoAwaitIsKeyword awaitIsKeyword(this, funbox->isAsync()); + body = functionBody(inHandling, bodyYieldHandling, kind, bodyType); + if (!body) + return false; + } - if ((kind != Method && !IsConstructorKind(kind)) && fun->explicitName()) { + if ((kind == Statement || kind == Expression) && fun->explicitName()) { RootedPropertyName propertyName(context, fun->explicitName()->asPropertyName()); - // `await` cannot be checked at this point because of different context. - // It should already be checked before this point. - if (propertyName != context->names().await) { - YieldHandling nameYieldHandling; - if (kind == Expression) { - // Named lambda has binding inside it. - nameYieldHandling = bodyYieldHandling; - } else { - // Otherwise YieldHandling cannot be checked at this point - // because of different context. - // It should already be checked before this point. - nameYieldHandling = YieldIsName; - } + YieldHandling nameYieldHandling; + if (kind == Expression) { + // Named lambda has binding inside it. + nameYieldHandling = bodyYieldHandling; + } else { + // Otherwise YieldHandling cannot be checked at this point + // because of different context. + // It should already be checked before this point. + nameYieldHandling = YieldIsName; + } - if (!checkBindingIdentifier(propertyName, handler.getPosition(pn).begin, - nameYieldHandling)) - { - return false; - } + // We already use the correct await-handling at this point, therefore + // we don't need call AutoAwaitIsKeyword here. + + if (!checkBindingIdentifier(propertyName, handler.getPosition(pn).begin, + nameYieldHandling)) + { + return false; } } -- cgit v1.2.3