mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-08 08:48:39 +09:00
Issue #1691 - Part 13: Remove MUST_MATCH_TOKEN* macros in Parser. https://bugzilla.mozilla.org/show_bug.cgi?id=1501928 This was helpful in debugging one of the crashes, the macros made debugging a nightmare.
(cherry picked from commit 7bceec3f7dff086305c3f50939a8c830ca7f107b)
This commit is contained in:
parent
a892a75903
commit
bc895eba9b
3 changed files with 284 additions and 111 deletions
|
|
@ -1321,7 +1321,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
|||
return true;
|
||||
|
||||
case PNK_CALL_IMPORT:
|
||||
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
||||
MOZ_ASSERT(pn->is<BinaryNode>());
|
||||
*answer = true;
|
||||
return true;
|
||||
|
||||
|
|
|
|||
|
|
@ -65,46 +65,6 @@ using AddDeclaredNamePtr = ParseContext::Scope::AddDeclaredNamePtr;
|
|||
using BindingIter = ParseContext::Scope::BindingIter;
|
||||
using UsedNamePtr = UsedNameTracker::UsedNameMap::Ptr;
|
||||
|
||||
// Read a token. Report an error and return null() if that token doesn't match
|
||||
// to the condition. Do not use MUST_MATCH_TOKEN_INTERNAL directly.
|
||||
#define MUST_MATCH_TOKEN_INTERNAL(cond, modifier, errorReport, failureValue) \
|
||||
JS_BEGIN_MACRO \
|
||||
TokenKind token; \
|
||||
if (!tokenStream.getToken(&token, modifier)) \
|
||||
return failureValue; \
|
||||
if (!(cond)) { \
|
||||
errorReport; \
|
||||
return failureValue; \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
#define MUST_MATCH_TOKEN_MOD_OR(tt, modifier, errorNumber, failureValue) \
|
||||
MUST_MATCH_TOKEN_INTERNAL(token == tt, modifier, error(errorNumber), failureValue)
|
||||
|
||||
#define MUST_MATCH_TOKEN_MOD(tt, modifier, errorNumber) \
|
||||
MUST_MATCH_TOKEN_MOD_OR(tt, modifier, errorNumber, null())
|
||||
|
||||
#define MUST_MATCH_TOKEN_OR(tt, errorNumber, failureValue) \
|
||||
MUST_MATCH_TOKEN_MOD_OR(tt, TokenStream::None, errorNumber, failureValue)
|
||||
|
||||
#define MUST_MATCH_TOKEN(tt, errorNumber) \
|
||||
MUST_MATCH_TOKEN_OR(tt, errorNumber, null())
|
||||
|
||||
#define MUST_MATCH_TOKEN_FUNC_MOD_OR(func, modifier, errorNumber, failureValue) \
|
||||
MUST_MATCH_TOKEN_INTERNAL((func)(token), modifier, error(errorNumber), failureValue)
|
||||
|
||||
#define MUST_MATCH_TOKEN_FUNC_OR(func, errorNumber, failureValue) \
|
||||
MUST_MATCH_TOKEN_FUNC_MOD_OR(func, TokenStream::None, errorNumber, failureValue)
|
||||
|
||||
#define MUST_MATCH_TOKEN_FUNC(func, errorNumber) \
|
||||
MUST_MATCH_TOKEN_FUNC_OR(func, errorNumber, null())
|
||||
|
||||
#define MUST_MATCH_TOKEN_MOD_WITH_REPORT_OR(tt, modifier, errorReport, failureValue) \
|
||||
MUST_MATCH_TOKEN_INTERNAL(token == tt, modifier, errorReport, failureValue)
|
||||
|
||||
#define MUST_MATCH_TOKEN_MOD_WITH_REPORT(tt, modifier, errorReport) \
|
||||
MUST_MATCH_TOKEN_MOD_WITH_REPORT_OR(tt, modifier, errorReport, null())
|
||||
|
||||
template <class T, class U>
|
||||
static inline void
|
||||
PropagateTransitiveParseFlags(const T* inner, U* outer)
|
||||
|
|
@ -611,6 +571,23 @@ FunctionBox::initWithEnclosingScope(Scope* enclosingScope)
|
|||
computeInWith(enclosingScope);
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
template <typename ConditionT, typename ErrorReportT>
|
||||
bool
|
||||
Parser<ParseHandler>::mustMatchTokenInternal(ConditionT condition, Modifier modifier,
|
||||
ErrorReportT errorReport)
|
||||
{
|
||||
TokenKind actual;
|
||||
if (!tokenStream.getToken(&actual, modifier)) {
|
||||
return false;
|
||||
}
|
||||
if (!condition(actual)) {
|
||||
errorReport(actual);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ParserBase::error(unsigned errorNumber, ...)
|
||||
{
|
||||
|
|
@ -3769,10 +3746,14 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling,
|
|||
}
|
||||
|
||||
if (bodyType == StatementListBody) {
|
||||
MUST_MATCH_TOKEN_MOD_WITH_REPORT_OR(TOK_RC, TokenStream::Operand,
|
||||
reportMissingClosing(JSMSG_CURLY_AFTER_BODY,
|
||||
JSMSG_CURLY_OPENED, openedPos),
|
||||
false);
|
||||
if (!mustMatchToken(TOK_RC, TokenStream::Operand,
|
||||
[this, openedPos](TokenKind actual) {
|
||||
this->reportMissingClosing(JSMSG_CURLY_AFTER_BODY,
|
||||
JSMSG_CURLY_OPENED, openedPos);
|
||||
}))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
funbox->setEnd(pos().end);
|
||||
} else {
|
||||
#if !JS_HAS_EXPR_CLOSURES
|
||||
|
|
@ -4140,11 +4121,16 @@ template <typename ParseHandler>
|
|||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::condition(InHandling inHandling, YieldHandling yieldHandling)
|
||||
{
|
||||
MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_COND);
|
||||
if (!mustMatchToken(TOK_LP, JSMSG_PAREN_BEFORE_COND)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
Node pn = exprInParens(inHandling, yieldHandling, TripledotProhibited);
|
||||
if (!pn)
|
||||
return null();
|
||||
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_COND);
|
||||
if (!mustMatchToken(TOK_RP, JSMSG_PAREN_AFTER_COND)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
/* Check for (a = b) and warn about possible (a == b) mistype. */
|
||||
if (handler.isUnparenthesizedAssignment(pn)) {
|
||||
|
|
@ -4505,9 +4491,14 @@ Parser<ParseHandler>::objectBindingPattern(DeclarationKind kind, YieldHandling y
|
|||
}
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::None,
|
||||
reportMissingClosing(JSMSG_CURLY_AFTER_LIST,
|
||||
JSMSG_CURLY_OPENED, begin));
|
||||
if (!mustMatchToken(TOK_RC, TokenStream::None,
|
||||
[this, begin](TokenKind actual) {
|
||||
this->reportMissingClosing(JSMSG_CURLY_AFTER_LIST,
|
||||
JSMSG_CURLY_OPENED, begin);
|
||||
}))
|
||||
{
|
||||
return null();
|
||||
}
|
||||
|
||||
handler.setEndPosition(literal, pos().end);
|
||||
return literal;
|
||||
|
|
@ -4593,9 +4584,14 @@ Parser<ParseHandler>::arrayBindingPattern(DeclarationKind kind, YieldHandling yi
|
|||
}
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RB, modifier,
|
||||
reportMissingClosing(JSMSG_BRACKET_AFTER_LIST,
|
||||
JSMSG_BRACKET_OPENED, begin));
|
||||
if (!mustMatchToken(TOK_RB, modifier,
|
||||
[this, begin](TokenKind actual) {
|
||||
this->reportMissingClosing(JSMSG_BRACKET_AFTER_LIST,
|
||||
JSMSG_BRACKET_OPENED, begin);
|
||||
}))
|
||||
{
|
||||
return null();
|
||||
}
|
||||
|
||||
handler.setEndPosition(literal, pos().end);
|
||||
return literal;
|
||||
|
|
@ -4652,9 +4648,13 @@ Parser<ParseHandler>::blockStatement(YieldHandling yieldHandling, unsigned error
|
|||
if (!list)
|
||||
return null();
|
||||
|
||||
MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand,
|
||||
reportMissingClosing(errorNumber, JSMSG_CURLY_OPENED,
|
||||
openedPos));
|
||||
if (!mustMatchToken(TOK_RC, TokenStream::Operand,
|
||||
[this, errorNumber, openedPos](TokenKind actual) {
|
||||
this->reportMissingClosing(errorNumber, JSMSG_CURLY_OPENED, openedPos);
|
||||
}))
|
||||
{
|
||||
return null();
|
||||
}
|
||||
|
||||
return finishLexicalScope(scope, list);
|
||||
}
|
||||
|
|
@ -4710,7 +4710,9 @@ Parser<ParseHandler>::declarationPattern(Node decl, DeclarationKind declKind, To
|
|||
}
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_ASSIGN, JSMSG_BAD_DESTRUCT_DECL);
|
||||
if (!mustMatchToken(TOK_ASSIGN, JSMSG_BAD_DESTRUCT_DECL)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
Node init = assignExpr(forHeadKind ? InProhibited : InAllowed,
|
||||
yieldHandling, TripledotProhibited);
|
||||
|
|
@ -5078,9 +5080,13 @@ Parser<FullParseHandler>::namedImportsOrNamespaceImport(TokenKind tt, ListNodeTy
|
|||
} else {
|
||||
MOZ_ASSERT(tt == TOK_MUL);
|
||||
|
||||
MUST_MATCH_TOKEN_OR(TOK_AS, JSMSG_AS_AFTER_IMPORT_STAR, false);
|
||||
if (!mustMatchToken(TOK_AS, JSMSG_AS_AFTER_IMPORT_STAR)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN_FUNC_OR(TokenKindIsPossibleIdentifierName, JSMSG_NO_BINDING_NAME, false);
|
||||
if (!mustMatchToken(TokenKindIsPossibleIdentifierName, JSMSG_NO_BINDING_NAME)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NameNodeType importName = newName(context->names().star);
|
||||
if (!importName)
|
||||
|
|
@ -5188,9 +5194,13 @@ Parser<FullParseHandler>::importDeclaration()
|
|||
return null();
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_FROM, JSMSG_FROM_AFTER_IMPORT_CLAUSE);
|
||||
if (!mustMatchToken(TOK_FROM, JSMSG_FROM_AFTER_IMPORT_CLAUSE)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_STRING, JSMSG_MODULE_SPEC_AFTER_FROM);
|
||||
if (!mustMatchToken(TOK_STRING, JSMSG_MODULE_SPEC_AFTER_FROM)) {
|
||||
return null();
|
||||
}
|
||||
}
|
||||
|
||||
NameNodeType moduleSpec = stringLiteral();
|
||||
|
|
@ -5495,7 +5505,9 @@ Parser<ParseHandler>::exportFrom(uint32_t begin, Node specList)
|
|||
if (!abortIfSyntaxParser())
|
||||
return null();
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_STRING, JSMSG_MODULE_SPEC_AFTER_FROM);
|
||||
if (!mustMatchToken(TOK_STRING, JSMSG_MODULE_SPEC_AFTER_FROM)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
NameNodeType moduleSpec = stringLiteral();
|
||||
if (!moduleSpec)
|
||||
|
|
@ -5535,7 +5547,9 @@ Parser<ParseHandler>::exportBatch(uint32_t begin)
|
|||
|
||||
handler.addList(kid, exportSpec);
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_FROM, JSMSG_FROM_AFTER_EXPORT_STAR);
|
||||
if (!mustMatchToken(TOK_FROM, JSMSG_FROM_AFTER_EXPORT_STAR)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
return exportFrom(begin, kid);
|
||||
}
|
||||
|
|
@ -5600,8 +5614,11 @@ Parser<ParseHandler>::exportClause(uint32_t begin)
|
|||
bool foundAs;
|
||||
if (!tokenStream.matchToken(&foundAs, TOK_AS))
|
||||
return null();
|
||||
if (foundAs)
|
||||
MUST_MATCH_TOKEN_FUNC(TokenKindIsPossibleIdentifierName, JSMSG_NO_EXPORT_NAME);
|
||||
if (foundAs) {
|
||||
if (!mustMatchToken(TokenKindIsPossibleIdentifierName, JSMSG_NO_EXPORT_NAME)) {
|
||||
return null();
|
||||
}
|
||||
}
|
||||
|
||||
NameNodeType exportName = newName(tokenStream.currentName());
|
||||
if (!exportName)
|
||||
|
|
@ -6105,7 +6122,9 @@ Parser<ParseHandler>::doWhileStatement(YieldHandling yieldHandling)
|
|||
Node body = statement(yieldHandling);
|
||||
if (!body)
|
||||
return null();
|
||||
MUST_MATCH_TOKEN_MOD(TOK_WHILE, TokenStream::Operand, JSMSG_WHILE_AFTER_DO);
|
||||
if (!mustMatchToken(TOK_WHILE, TokenStream::Operand, JSMSG_WHILE_AFTER_DO)) {
|
||||
return null();
|
||||
}
|
||||
Node cond = condition(InAllowed, yieldHandling);
|
||||
if (!cond)
|
||||
return null();
|
||||
|
|
@ -6352,7 +6371,9 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
|
|||
}
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
|
||||
if (!mustMatchToken(TOK_LP, JSMSG_PAREN_AFTER_FOR)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
// PNK_FORHEAD, PNK_FORIN, or PNK_FOROF depending on the loop type.
|
||||
ParseNodeKind headKind;
|
||||
|
|
@ -6408,7 +6429,9 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
|
|||
|
||||
// Look for an operand: |for (;| means we might have already examined
|
||||
// this semicolon with that modifier.
|
||||
MUST_MATCH_TOKEN_MOD(TOK_SEMI, TokenStream::Operand, JSMSG_SEMI_AFTER_FOR_INIT);
|
||||
if (!mustMatchToken(TOK_SEMI, TokenStream::Operand, JSMSG_SEMI_AFTER_FOR_INIT)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
TokenKind tt;
|
||||
if (!tokenStream.peekToken(&tt, TokenStream::Operand))
|
||||
|
|
@ -6426,7 +6449,9 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
|
|||
mod = TokenStream::None;
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN_MOD(TOK_SEMI, mod, JSMSG_SEMI_AFTER_FOR_COND);
|
||||
if (!mustMatchToken(TOK_SEMI, mod, JSMSG_SEMI_AFTER_FOR_COND)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
if (!tokenStream.peekToken(&tt, TokenStream::Operand))
|
||||
return null();
|
||||
|
|
@ -6442,7 +6467,9 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
|
|||
mod = TokenStream::None;
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN_MOD(TOK_RP, mod, JSMSG_PAREN_AFTER_FOR_CTRL);
|
||||
if (!mustMatchToken(TOK_RP, mod, JSMSG_PAREN_AFTER_FOR_CTRL)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
TokenPos headPos(begin, pos().end);
|
||||
forHead = handler.newForHead(init, test, update, headPos);
|
||||
|
|
@ -6472,7 +6499,9 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
|
|||
// Parser::declaration consumed everything up to the closing ')'. That
|
||||
// token follows an {Assignment,}Expression, so the next token must be
|
||||
// consumed as if an operator continued the expression, i.e. as None.
|
||||
MUST_MATCH_TOKEN_MOD(TOK_RP, TokenStream::None, JSMSG_PAREN_AFTER_FOR_CTRL);
|
||||
if (!mustMatchToken(TOK_RP, TokenStream::None, JSMSG_PAREN_AFTER_FOR_CTRL)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
TokenPos headPos(begin, pos().end);
|
||||
forHead = handler.newForInOrOfHead(headKind, target, iteratedExpr, headPos);
|
||||
|
|
@ -6501,14 +6530,20 @@ Parser<ParseHandler>::switchStatement(YieldHandling yieldHandling)
|
|||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_SWITCH));
|
||||
uint32_t begin = pos().begin;
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_SWITCH);
|
||||
if (!mustMatchToken(TOK_LP, JSMSG_PAREN_BEFORE_SWITCH)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
Node discriminant = exprInParens(InAllowed, yieldHandling, TripledotProhibited);
|
||||
if (!discriminant)
|
||||
return null();
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_SWITCH);
|
||||
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_SWITCH);
|
||||
if (!mustMatchToken(TOK_RP, JSMSG_PAREN_AFTER_SWITCH)) {
|
||||
return null();
|
||||
}
|
||||
if (!mustMatchToken(TOK_LC, JSMSG_CURLY_BEFORE_SWITCH)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
ParseContext::Statement stmt(pc, StatementKind::Switch);
|
||||
ParseContext::Scope scope(this);
|
||||
|
|
@ -6550,7 +6585,9 @@ Parser<ParseHandler>::switchStatement(YieldHandling yieldHandling)
|
|||
return null();
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_AFTER_CASE);
|
||||
if (!mustMatchToken(TOK_COLON, JSMSG_COLON_AFTER_CASE)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
ListNodeType body = handler.newStatementList(pos());
|
||||
if (!body)
|
||||
|
|
@ -6904,11 +6941,15 @@ Parser<ParseHandler>::withStatement(YieldHandling yieldHandling)
|
|||
return null();
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_WITH);
|
||||
if (!mustMatchToken(TOK_LP, JSMSG_PAREN_BEFORE_WITH)) {
|
||||
return null();
|
||||
}
|
||||
Node objectExpr = exprInParens(InAllowed, yieldHandling, TripledotProhibited);
|
||||
if (!objectExpr)
|
||||
return null();
|
||||
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_WITH);
|
||||
if (!mustMatchToken(TOK_RP, JSMSG_PAREN_AFTER_WITH)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
Node innerBlock;
|
||||
{
|
||||
|
|
@ -7045,7 +7086,9 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
|||
|
||||
LexicalScopeNodeType innerBlock;
|
||||
{
|
||||
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_TRY);
|
||||
if (!mustMatchToken(TOK_LC, JSMSG_CURLY_BEFORE_TRY)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
uint32_t openedPos = pos().begin;
|
||||
|
||||
|
|
@ -7062,9 +7105,14 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
|||
if (!innerBlock)
|
||||
return null();
|
||||
|
||||
MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand,
|
||||
reportMissingClosing(JSMSG_CURLY_AFTER_TRY,
|
||||
JSMSG_CURLY_OPENED, openedPos));
|
||||
if (!mustMatchToken(TOK_RC, TokenStream::Operand,
|
||||
[this, openedPos](TokenKind actual) {
|
||||
this->reportMissingClosing(JSMSG_CURLY_AFTER_TRY,
|
||||
JSMSG_CURLY_OPENED, openedPos);
|
||||
}))
|
||||
{
|
||||
return null();
|
||||
}
|
||||
}
|
||||
|
||||
bool hasUnconditionalCatch = false;
|
||||
|
|
@ -7111,7 +7159,9 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
|||
if (omittedBinding) {
|
||||
catchName = null();
|
||||
} else {
|
||||
MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_CATCH);
|
||||
if (!mustMatchToken(TOK_LP, JSMSG_PAREN_BEFORE_CATCH)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
if (!tokenStream.getToken(&tt))
|
||||
return null();
|
||||
|
|
@ -7153,9 +7203,13 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
|||
return null();
|
||||
}
|
||||
#endif
|
||||
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_CATCH);
|
||||
if (!mustMatchToken(TOK_RP, JSMSG_PAREN_AFTER_CATCH)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_CATCH);
|
||||
if (!mustMatchToken(TOK_LC, JSMSG_CURLY_BEFORE_CATCH)) {
|
||||
return null();
|
||||
}
|
||||
}
|
||||
|
||||
LexicalScopeNodeType catchBody = catchBlockStatement(yieldHandling, scope);
|
||||
|
|
@ -7182,7 +7236,9 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
|||
LexicalScopeNodeType finallyBlock = null();
|
||||
|
||||
if (tt == TOK_FINALLY) {
|
||||
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_FINALLY);
|
||||
if (!mustMatchToken(TOK_LC, JSMSG_CURLY_BEFORE_FINALLY)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
uint32_t openedPos = pos().begin;
|
||||
|
||||
|
|
@ -7199,9 +7255,15 @@ Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling)
|
|||
if (!finallyBlock)
|
||||
return null();
|
||||
|
||||
MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand,
|
||||
reportMissingClosing(JSMSG_CURLY_AFTER_FINALLY,
|
||||
JSMSG_CURLY_OPENED, openedPos));
|
||||
if (!mustMatchToken(TOK_RC, TokenStream::Operand,
|
||||
[this, openedPos](TokenKind actual) {
|
||||
this->reportMissingClosing(JSMSG_CURLY_AFTER_FINALLY,
|
||||
JSMSG_CURLY_OPENED, openedPos);
|
||||
}))
|
||||
{
|
||||
return null();
|
||||
}
|
||||
|
||||
} else {
|
||||
tokenStream.ungetToken();
|
||||
}
|
||||
|
|
@ -7239,9 +7301,14 @@ Parser<ParseHandler>::catchBlockStatement(YieldHandling yieldHandling,
|
|||
if (!list)
|
||||
return null();
|
||||
|
||||
MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::Operand,
|
||||
reportMissingClosing(JSMSG_CURLY_AFTER_CATCH,
|
||||
JSMSG_CURLY_OPENED, openedPos));
|
||||
if (!mustMatchToken(TOK_RC, TokenStream::Operand,
|
||||
[this, openedPos](TokenKind actual) {
|
||||
this->reportMissingClosing(JSMSG_CURLY_AFTER_CATCH,
|
||||
JSMSG_CURLY_OPENED, openedPos);
|
||||
}))
|
||||
{
|
||||
return null();
|
||||
}
|
||||
|
||||
// The catch parameter names are not bound in the body scope, so remove
|
||||
// them before generating bindings.
|
||||
|
|
@ -7356,7 +7423,9 @@ Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling,
|
|||
return null();
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_CLASS);
|
||||
if (!mustMatchToken(TOK_LC, JSMSG_CURLY_BEFORE_CLASS)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
ListNodeType classMethods = handler.newClassMethodList(pos().begin);
|
||||
if (!classMethods)
|
||||
|
|
@ -8270,7 +8339,9 @@ Parser<ParseHandler>::condExpr1(InHandling inHandling, YieldHandling yieldHandli
|
|||
if (!thenExpr)
|
||||
return null();
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_IN_COND);
|
||||
if (!mustMatchToken(TOK_COLON, JSMSG_COLON_IN_COND)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
Node elseExpr = assignExpr(inHandling, yieldHandling, TripledotProhibited);
|
||||
if (!elseExpr)
|
||||
|
|
@ -8900,7 +8971,9 @@ Parser<ParseHandler>::generatorComprehensionLambda(unsigned begin)
|
|||
if (!comp)
|
||||
return null();
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN);
|
||||
if (!mustMatchToken(TOK_RP, JSMSG_PAREN_IN_PAREN)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
uint32_t end = pos().end;
|
||||
handler.setBeginPosition(comp, begin);
|
||||
|
|
@ -8941,11 +9014,15 @@ Parser<ParseHandler>::comprehensionFor(GeneratorKind comprehensionKind)
|
|||
|
||||
uint32_t begin = pos().begin;
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
|
||||
if (!mustMatchToken(TOK_LP, JSMSG_PAREN_AFTER_FOR)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
// FIXME: Destructuring binding (bug 980828).
|
||||
|
||||
MUST_MATCH_TOKEN_FUNC(TokenKindIsPossibleIdentifier, JSMSG_NO_VARIABLE_NAME);
|
||||
if (!mustMatchToken(TokenKindIsPossibleIdentifier, JSMSG_NO_VARIABLE_NAME)) {
|
||||
return null();
|
||||
}
|
||||
RootedPropertyName name(context, bindingIdentifier(YieldIsKeyword));
|
||||
if (!name)
|
||||
return null();
|
||||
|
|
@ -8969,7 +9046,9 @@ Parser<ParseHandler>::comprehensionFor(GeneratorKind comprehensionKind)
|
|||
if (!rhs)
|
||||
return null();
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FOR_OF_ITERABLE);
|
||||
if (!mustMatchToken(TOK_RP, JSMSG_PAREN_AFTER_FOR_OF_ITERABLE)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
TokenPos headPos(begin, pos().end);
|
||||
|
||||
|
|
@ -9014,11 +9093,15 @@ Parser<ParseHandler>::comprehensionIf(GeneratorKind comprehensionKind)
|
|||
|
||||
uint32_t begin = pos().begin;
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_COND);
|
||||
if (!mustMatchToken(TOK_LP, JSMSG_PAREN_BEFORE_COND)) {
|
||||
return null();
|
||||
}
|
||||
Node cond = assignExpr(InAllowed, YieldIsKeyword, TripledotProhibited);
|
||||
if (!cond)
|
||||
return null();
|
||||
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_COND);
|
||||
if (!mustMatchToken(TOK_RP, JSMSG_PAREN_AFTER_COND)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
/* Check for (a = b) and warn about possible (a == b) mistype. */
|
||||
if (handler.isUnparenthesizedAssignment(cond)) {
|
||||
|
|
@ -9098,7 +9181,9 @@ Parser<ParseHandler>::arrayComprehension(uint32_t begin)
|
|||
if (!inner)
|
||||
return null();
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_ARRAY_COMPREHENSION);
|
||||
if (!mustMatchToken(TOK_RB, JSMSG_BRACKET_AFTER_ARRAY_COMPREHENSION)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
ListNodeType comp = handler.newList(PNK_ARRAYCOMP, inner);
|
||||
if (!comp)
|
||||
|
|
@ -9216,7 +9301,9 @@ Parser<ParseHandler>::argumentList(YieldHandling yieldHandling, bool* isSpread,
|
|||
}
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_ARGS);
|
||||
if (!mustMatchToken(TOK_RP, JSMSG_PAREN_AFTER_ARGS)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
handler.setEndPosition(argsList, pos().end);
|
||||
return argsList;
|
||||
|
|
@ -9449,7 +9536,9 @@ Parser<ParseHandler>::memberElemAccess(
|
|||
return null();
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_IN_INDEX);
|
||||
if (!mustMatchToken(TOK_RB, JSMSG_BRACKET_IN_INDEX)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
if (handler.isSuperBase(lhs) && !checkAndMarkSuperScope()) {
|
||||
error(JSMSG_BAD_SUPERPROP, "member");
|
||||
|
|
@ -9923,9 +10012,14 @@ Parser<ParseHandler>::arrayInitializer(YieldHandling yieldHandling, PossibleErro
|
|||
}
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RB, modifier,
|
||||
reportMissingClosing(JSMSG_BRACKET_AFTER_LIST,
|
||||
JSMSG_BRACKET_OPENED, begin));
|
||||
if (!mustMatchToken(TOK_RB, modifier,
|
||||
[this, begin](TokenKind actual) {
|
||||
this->reportMissingClosing(JSMSG_BRACKET_AFTER_LIST,
|
||||
JSMSG_BRACKET_OPENED, begin);
|
||||
}))
|
||||
{
|
||||
return null();
|
||||
}
|
||||
}
|
||||
handler.setEndPosition(literal, pos().end);
|
||||
return literal;
|
||||
|
|
@ -10150,7 +10244,9 @@ Parser<ParseHandler>::computedPropertyName(YieldHandling yieldHandling,
|
|||
if (!assignNode)
|
||||
return null();
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_RB, JSMSG_COMP_PROP_UNTERM_EXPR);
|
||||
if (!mustMatchToken(TOK_RB, JSMSG_COMP_PROP_UNTERM_EXPR)) {
|
||||
return null();
|
||||
}
|
||||
return handler.newComputedName(assignNode, begin, pos().end);
|
||||
}
|
||||
|
||||
|
|
@ -10362,9 +10458,14 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
|
|||
possibleError->setPendingDestructuringErrorAt(pos(), JSMSG_REST_WITH_COMMA);
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::None,
|
||||
reportMissingClosing(JSMSG_CURLY_AFTER_LIST,
|
||||
JSMSG_CURLY_OPENED, openedPos));
|
||||
if (!mustMatchToken(TOK_RC, TokenStream::None,
|
||||
[this, openedPos](TokenKind actual) {
|
||||
this->reportMissingClosing(JSMSG_CURLY_AFTER_LIST,
|
||||
JSMSG_CURLY_OPENED, openedPos);
|
||||
}))
|
||||
{
|
||||
return null();
|
||||
}
|
||||
|
||||
handler.setEndPosition(literal, pos().end);
|
||||
return literal;
|
||||
|
|
@ -10513,7 +10614,9 @@ Parser<ParseHandler>::importExpr(YieldHandling yieldHandling)
|
|||
if (!arg)
|
||||
return null();
|
||||
|
||||
MUST_MATCH_TOKEN_MOD(TOK_RP, TokenStream::Operand, JSMSG_PAREN_AFTER_ARGS);
|
||||
if (!mustMatchToken(TOK_RP, JSMSG_PAREN_AFTER_ARGS)) {
|
||||
return null();
|
||||
}
|
||||
|
||||
if (!context->compartment()->runtimeFromAnyThread()->moduleDynamicImportHook && !abortIfSyntaxParser()) {
|
||||
return null();
|
||||
|
|
@ -10581,7 +10684,9 @@ Parser<ParseHandler>::primaryExpr(YieldHandling yieldHandling, TripledotHandling
|
|||
Node expr = exprInParens(InAllowed, yieldHandling, TripledotAllowed, possibleError);
|
||||
if (!expr)
|
||||
return null();
|
||||
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN);
|
||||
if (!mustMatchToken(TOK_RP, JSMSG_PAREN_IN_PAREN)) {
|
||||
return null();
|
||||
}
|
||||
return handler.parenthesize(expr);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "frontend/NameCollections.h"
|
||||
#include "frontend/SharedContext.h"
|
||||
#include "frontend/SyntaxParseHandler.h"
|
||||
#include "frontend/TokenStream.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
|
|
@ -906,6 +907,8 @@ class ParserBase : public StrictModeGetter
|
|||
template <typename ParseHandler>
|
||||
class Parser final : public ParserBase, private JS::AutoGCRooter
|
||||
{
|
||||
protected:
|
||||
using Modifier = TokenStream::Modifier;
|
||||
private:
|
||||
using Node = typename ParseHandler::Node;
|
||||
|
||||
|
|
@ -1086,6 +1089,71 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
|
|||
*/
|
||||
ListNodeType parse();
|
||||
|
||||
private:
|
||||
/*
|
||||
* Gets the next token and checks if it matches to the given `condition`.
|
||||
* If it matches, returns true.
|
||||
* If it doesn't match, calls `errorReport` to report the error, and
|
||||
* returns false.
|
||||
* If other error happens, it returns false but `errorReport` may not be
|
||||
* called and other error will be thrown in that case.
|
||||
*
|
||||
* In any case, the already gotten token is not ungotten.
|
||||
*
|
||||
* The signature of `condition` is [...](TokenKind actual) -> bool, and
|
||||
* the signature of `errorReport` is [...](TokenKind actual).
|
||||
*/
|
||||
template<typename ConditionT, typename ErrorReportT>
|
||||
MOZ_MUST_USE bool mustMatchTokenInternal(ConditionT condition, Modifier modifier,
|
||||
ErrorReportT errorReport);
|
||||
|
||||
public:
|
||||
/*
|
||||
* The following mustMatchToken variants follow the behavior and parameter
|
||||
* types of mustMatchTokenInternal above.
|
||||
*
|
||||
* If modifier is omitted, `None` is used.
|
||||
* If TokenKind is passed instead of `condition`, it checks if the next
|
||||
* token is the passed token.
|
||||
* If error number is passed instead of `errorReport`, it reports an
|
||||
* error with the passed errorNumber.
|
||||
*/
|
||||
MOZ_MUST_USE bool mustMatchToken(TokenKind expected, Modifier modifier, JSErrNum errorNumber) {
|
||||
return mustMatchTokenInternal([expected](TokenKind actual) {
|
||||
return actual == expected;
|
||||
},
|
||||
modifier,
|
||||
[this, errorNumber](TokenKind) {
|
||||
this->error(errorNumber);
|
||||
});
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool mustMatchToken(TokenKind excpected, JSErrNum errorNumber) {
|
||||
return mustMatchToken(excpected, TokenStream::None, errorNumber);
|
||||
}
|
||||
|
||||
template<typename ConditionT>
|
||||
MOZ_MUST_USE bool mustMatchToken(ConditionT condition, JSErrNum errorNumber) {
|
||||
return mustMatchTokenInternal(condition, TokenStream::None,
|
||||
[this, errorNumber](TokenKind) {
|
||||
this->error(errorNumber);
|
||||
});
|
||||
}
|
||||
|
||||
template<typename ErrorReportT>
|
||||
MOZ_MUST_USE bool mustMatchToken(TokenKind expected, Modifier modifier,
|
||||
ErrorReportT errorReport) {
|
||||
return mustMatchTokenInternal([expected](TokenKind actual) {
|
||||
return actual == expected;
|
||||
},
|
||||
modifier, errorReport);
|
||||
}
|
||||
|
||||
template<typename ErrorReportT>
|
||||
MOZ_MUST_USE bool mustMatchToken(TokenKind expected, ErrorReportT errorReport) {
|
||||
return mustMatchToken(expected, TokenStream::None, errorReport);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new parsed object or function container from
|
||||
* cx->tempLifoAlloc.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue