Issue #2142 - Ensure 'await' is always a restricted identifier when parsing modules

Based-on: m-c 1356189
This commit is contained in:
Martok 2023-04-26 18:21:35 +02:00 • committed by roytam1
commit faed047e3f
2 changed files with 38 additions and 21 deletions

View file

@ -785,7 +785,7 @@ ParserBase::ParserBase(ExclusiveContext* cx, LifoAlloc& alloc,
#endif #endif
abortedSyntaxParse(false), abortedSyntaxParse(false),
isUnexpectedEOF_(false), isUnexpectedEOF_(false),
awaitIsKeyword_(false), awaitHandling_(AwaitIsName),
parseGoal_(uint8_t(parseGoal)) parseGoal_(uint8_t(parseGoal))
{ {
cx->perThreadData->frontendCollectionPool.addActiveCompilation(); cx->perThreadData->frontendCollectionPool.addActiveCompilation();
@ -846,18 +846,18 @@ Parser<ParseHandler>::~Parser()
template <> template <>
void void
Parser<SyntaxParseHandler>::setAwaitIsKeyword(bool isKeyword) Parser<SyntaxParseHandler>::setAwaitHandling(AwaitHandling awaitHandling)
{ {
awaitIsKeyword_ = isKeyword; awaitHandling_ = awaitHandling;
} }
template <> template <>
void void
Parser<FullParseHandler>::setAwaitIsKeyword(bool isKeyword) Parser<FullParseHandler>::setAwaitHandling(AwaitHandling awaitHandling)
{ {
awaitIsKeyword_ = isKeyword; awaitHandling_ = awaitHandling;
if (Parser<SyntaxParseHandler>* parser = handler.syntaxParser) if (Parser<SyntaxParseHandler>* parser = handler.syntaxParser)
parser->setAwaitIsKeyword(isKeyword); parser->setAwaitHandling(awaitHandling);
} }
template <typename ParseHandler> template <typename ParseHandler>
@ -2217,7 +2217,7 @@ Parser<FullParseHandler>::moduleBody(ModuleSharedContext* modulesc)
if (!moduleNode) if (!moduleNode)
return null(); return null();
AutoAwaitIsKeyword<FullParseHandler> awaitIsKeyword(this, true); AutoAwaitIsKeyword<FullParseHandler> awaitIsKeyword(this, AwaitIsModuleKeyword);
ListNode* stmtList = statementList(YieldIsName); ListNode* stmtList = statementList(YieldIsName);
if (!stmtList) { if (!stmtList) {
return null(); return null();
@ -2490,6 +2490,14 @@ GetYieldHandling(GeneratorKind generatorKind)
return YieldIsKeyword; return YieldIsKeyword;
} }
static AwaitHandling
GetAwaitHandling(FunctionAsyncKind asyncKind)
{
if (asyncKind == SyncFunction)
return AwaitIsName;
return AwaitIsKeyword;
}
template <> template <>
FunctionNode* FunctionNode*
Parser<FullParseHandler>::standaloneFunction(HandleFunction fun, Parser<FullParseHandler>::standaloneFunction(HandleFunction fun,
@ -2549,7 +2557,8 @@ Parser<FullParseHandler>::standaloneFunction(HandleFunction fun,
funpc.setIsStandaloneFunctionBody(); funpc.setIsStandaloneFunctionBody();
YieldHandling yieldHandling = GetYieldHandling(generatorKind); YieldHandling yieldHandling = GetYieldHandling(generatorKind);
AutoAwaitIsKeyword<FullParseHandler> awaitIsKeyword(this, asyncKind == AsyncFunction); AwaitHandling awaitHandling = GetAwaitHandling(asyncKind);
AutoAwaitIsKeyword<FullParseHandler> awaitIsKeyword(this, awaitHandling);
if (!functionFormalParametersAndBody(InAllowed, yieldHandling, funNode, FunctionSyntaxKind::Statement, if (!functionFormalParametersAndBody(InAllowed, yieldHandling, funNode, FunctionSyntaxKind::Statement,
parameterListEnd, /* isStandaloneFunction = */ true)) parameterListEnd, /* isStandaloneFunction = */ true))
{ {
@ -3641,9 +3650,11 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling,
// See below for an explanation why arrow function parameters and arrow // See below for an explanation why arrow function parameters and arrow
// function bodies are parsed with different yield/await settings. // function bodies are parsed with different yield/await settings.
{ {
bool asyncOrArrowInAsync = funbox->isAsync() || AwaitHandling awaitHandling = funbox->isAsync() ||
(kind == FunctionSyntaxKind::Arrow && awaitIsKeyword()); (kind == FunctionSyntaxKind::Arrow && awaitIsKeyword())
AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, asyncOrArrowInAsync); ? AwaitIsKeyword
: AwaitIsName;
AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, awaitHandling);
if (!functionArguments(yieldHandling, kind, funNode)) if (!functionArguments(yieldHandling, kind, funNode))
return false; return false;
} }
@ -3713,9 +3724,10 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling,
// Whereas the |yield| in the function body is always parsed as a name. // Whereas the |yield| in the function body is always parsed as a name.
// The same goes when parsing |await| in arrow functions. // The same goes when parsing |await| in arrow functions.
YieldHandling bodyYieldHandling = GetYieldHandling(pc->generatorKind()); YieldHandling bodyYieldHandling = GetYieldHandling(pc->generatorKind());
AwaitHandling bodyAwaitHandling = GetAwaitHandling(pc->asyncKind());
LexicalScopeNodeType body; LexicalScopeNodeType body;
{ {
AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, funbox->isAsync()); AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, bodyAwaitHandling);
body = functionBody(inHandling, bodyYieldHandling, kind, bodyType); body = functionBody(inHandling, bodyYieldHandling, kind, bodyType);
if (!body) if (!body)
return false; return false;
@ -3873,7 +3885,7 @@ Parser<ParseHandler>::functionExpr(uint32_t toStringStart, InvokedPrediction inv
{ {
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION)); MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, asyncKind == AsyncFunction); AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, GetAwaitHandling(asyncKind));
GeneratorKind generatorKind = NotGenerator; GeneratorKind generatorKind = NotGenerator;
TokenKind tt; TokenKind tt;
if (!tokenStream.getToken(&tt)) if (!tokenStream.getToken(&tt))

View file

@ -591,6 +591,7 @@ enum class PropertyType {
// we're in a function box -- easier and simpler than passing an extra // we're in a function box -- easier and simpler than passing an extra
// parameter everywhere. // parameter everywhere.
enum YieldHandling { YieldIsName, YieldIsKeyword }; enum YieldHandling { YieldIsName, YieldIsKeyword };
enum AwaitHandling : uint8_t { AwaitIsName, AwaitIsKeyword, AwaitIsModuleKeyword };
enum InHandling { InAllowed, InProhibited }; enum InHandling { InAllowed, InProhibited };
enum DefaultHandling { NameRequired, AllowDefaultName }; enum DefaultHandling { NameRequired, AllowDefaultName };
enum TripledotHandling { TripledotAllowed, TripledotProhibited }; enum TripledotHandling { TripledotAllowed, TripledotProhibited };
@ -800,13 +801,13 @@ class ParserBase : public StrictModeGetter
/* Unexpected end of input, i.e. TOK_EOF not at top-level. */ /* Unexpected end of input, i.e. TOK_EOF not at top-level. */
bool isUnexpectedEOF_:1; bool isUnexpectedEOF_:1;
bool awaitIsKeyword_:1; /* AwaitHandling */ uint8_t awaitHandling_:2;
uint8_t parseGoal_:1; uint8_t parseGoal_:1;
public: public:
bool awaitIsKeyword() const { bool awaitIsKeyword() const {
return awaitIsKeyword_; return awaitHandling_ != AwaitIsName;
} }
ParseGoal parseGoal() const { ParseGoal parseGoal() const {
@ -1058,7 +1059,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
~Parser(); ~Parser();
friend class AutoAwaitIsKeyword<ParseHandler>; friend class AutoAwaitIsKeyword<ParseHandler>;
void setAwaitIsKeyword(bool isKeyword); void setAwaitHandling(AwaitHandling awaitHandling);
bool checkOptions(); bool checkOptions();
@ -1643,17 +1644,21 @@ class MOZ_STACK_CLASS AutoAwaitIsKeyword
{ {
private: private:
Parser<ParseHandler>* parser_; Parser<ParseHandler>* parser_;
bool oldAwaitIsKeyword_; AwaitHandling oldAwaitHandling_;
public: public:
AutoAwaitIsKeyword(Parser<ParseHandler>* parser, bool awaitIsKeyword) { AutoAwaitIsKeyword(Parser<ParseHandler>* parser, AwaitHandling awaitHandling) {
parser_ = parser; parser_ = parser;
oldAwaitIsKeyword_ = parser_->awaitIsKeyword_; oldAwaitHandling_ = static_cast<AwaitHandling>(parser_->awaitHandling_);
parser_->setAwaitIsKeyword(awaitIsKeyword);
// 'await' is always a keyword in module contexts, so we don't modify
// the state when the original handling is AwaitIsModuleKeyword.
if (oldAwaitHandling_ != AwaitIsModuleKeyword)
parser_->setAwaitHandling(awaitHandling);
} }
~AutoAwaitIsKeyword() { ~AutoAwaitIsKeyword() {
parser_->setAwaitIsKeyword(oldAwaitIsKeyword_); parser_->setAwaitHandling(oldAwaitHandling_);
} }
}; };