Bug 1501928 - Part 1: Add GeneralParser::mustMatchToken and use it instead of simple variants of MUST_MATCH_TOKEN_*. r=Waldo
authorTooru Fujisawa <arai_a@mac.com>
Fri, 02 Nov 2018 15:50:13 +0900
changeset 445355 b07f54650288bf8664ca7a1ef67ca747ff46fdbb
parent 445354 d3303c33ff84dffa70e517ea3ca627846937aef1
child 445356 6af00f47b82911306268990c6c45a3e5b9dc622d
push id109719
push userarai_a@mac.com
push dateFri, 09 Nov 2018 06:25:57 +0000
treeherdermozilla-inbound@a922413f0f74 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1501928
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1501928 - Part 1: Add GeneralParser::mustMatchToken and use it instead of simple variants of MUST_MATCH_TOKEN_*. r=Waldo
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -86,28 +86,16 @@ using BindingNameVector = Vector<Binding
         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())
@@ -160,16 +148,32 @@ GeneralParser<ParseHandler, Unit>::asFin
 {
     static_assert(mozilla::IsBaseOf<GeneralParser<ParseHandler, Unit>, FinalParser>::value,
                   "inheritance relationship required by the static_cast<> below");
 
     return static_cast<const FinalParser*>(this);
 }
 
 template <class ParseHandler, typename Unit>
+bool
+GeneralParser<ParseHandler, Unit>::mustMatchToken(TokenKind expected, Modifier modifier,
+                                                  unsigned errorNumber)
+{
+    TokenKind actual;
+    if (!tokenStream.getToken(&actual, modifier)) {
+        return false;
+    }
+    if (actual != expected) {
+        error(errorNumber);
+        return false;
+    }
+    return true;
+}
+
+template <class ParseHandler, typename Unit>
 void
 GeneralParser<ParseHandler, Unit>::error(unsigned errorNumber, ...)
 {
     va_list args;
     va_start(args, errorNumber);
 
     ErrorMetadata metadata;
     if (tokenStream.computeErrorMetadata(&metadata, pos().begin)) {
@@ -3882,24 +3886,28 @@ GeneralParser<ParseHandler, Unit>::state
 
     return stmtList;
 }
 
 template <class ParseHandler, typename Unit>
 typename ParseHandler::Node
 GeneralParser<ParseHandler, Unit>::condition(InHandling inHandling, YieldHandling yieldHandling)
 {
-    MUST_MATCH_TOKEN(TokenKind::LeftParen, JSMSG_PAREN_BEFORE_COND);
+    if (!mustMatchToken(TokenKind::LeftParen, JSMSG_PAREN_BEFORE_COND)) {
+        return null();
+    }
 
     Node pn = exprInParens(inHandling, yieldHandling, TripledotProhibited);
     if (!pn) {
         return null();
     }
 
-    MUST_MATCH_TOKEN_MOD(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_AFTER_COND);
+    if (!mustMatchToken(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_AFTER_COND)) {
+        return null();
+    }
 
     /* Check for (a = b) and warn about possible (a == b) mistype. */
     if (handler.isUnparenthesizedAssignment(pn)) {
         if (!extraWarning(JSMSG_EQUAL_AS_ASSIGN)) {
             return null();
         }
     }
     return pn;
@@ -4522,17 +4530,19 @@ GeneralParser<ParseHandler, Unit>::decla
             if (!*forInOrOfExpression) {
                 return null();
             }
 
             return pattern;
         }
     }
 
-    MUST_MATCH_TOKEN_MOD(TokenKind::Assign, TokenStream::Operand, JSMSG_BAD_DESTRUCT_DECL);
+    if (!mustMatchToken(TokenKind::Assign, TokenStream::Operand, JSMSG_BAD_DESTRUCT_DECL)) {
+        return null();
+    }
 
     Node init = assignExpr(forHeadKind ? InProhibited : InAllowed,
                            yieldHandling, TripledotProhibited);
     if (!init) {
         return null();
     }
 
     return handler.newAssignment(ParseNodeKind::Assign, pattern, init);
@@ -4878,17 +4888,19 @@ Parser<FullParseHandler, Unit>::namedImp
             if (next != TokenKind::Comma) {
                 error(JSMSG_RC_AFTER_IMPORT_SPEC_LIST);
                 return false;
             }
         }
     } else {
         MOZ_ASSERT(tt == TokenKind::Mul);
 
-        MUST_MATCH_TOKEN_OR(TokenKind::As, JSMSG_AS_AFTER_IMPORT_STAR, false);
+        if (!mustMatchToken(TokenKind::As, JSMSG_AS_AFTER_IMPORT_STAR)) {
+            return false;
+        }
 
         MUST_MATCH_TOKEN_FUNC_OR(TokenKindIsPossibleIdentifierName, JSMSG_NO_BINDING_NAME, false);
 
         NameNodeType importName = newName(context->names().star);
         if (!importName) {
             return false;
         }
 
@@ -5004,19 +5016,23 @@ Parser<FullParseHandler, Unit>::importDe
                     return null();
                 }
             }
         } else {
             error(JSMSG_DECLARATION_AFTER_IMPORT);
             return null();
         }
 
-        MUST_MATCH_TOKEN(TokenKind::From, JSMSG_FROM_AFTER_IMPORT_CLAUSE);
-
-        MUST_MATCH_TOKEN(TokenKind::String, JSMSG_MODULE_SPEC_AFTER_FROM);
+        if (!mustMatchToken(TokenKind::From, JSMSG_FROM_AFTER_IMPORT_CLAUSE)) {
+            return null();
+        }
+
+        if (!mustMatchToken(TokenKind::String, JSMSG_MODULE_SPEC_AFTER_FROM)) {
+            return null();
+        }
     }
 
     NameNodeType moduleSpec = stringLiteral();
     if (!moduleSpec) {
         return null();
     }
 
     if (!matchOrInsertSemicolon()) {
@@ -5367,17 +5383,19 @@ GeneralParser<ParseHandler, Unit>::expor
     }
 
     MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::From));
 
     if (!abortIfSyntaxParser()) {
         return null();
     }
 
-    MUST_MATCH_TOKEN(TokenKind::String, JSMSG_MODULE_SPEC_AFTER_FROM);
+    if (!mustMatchToken(TokenKind::String, JSMSG_MODULE_SPEC_AFTER_FROM)) {
+        return null();
+    }
 
     NameNodeType moduleSpec = stringLiteral();
     if (!moduleSpec) {
         return null();
     }
 
     if (!matchOrInsertSemicolon()) {
         return null();
@@ -5414,17 +5432,19 @@ GeneralParser<ParseHandler, Unit>::expor
     // specifier to the list.
     NullaryNodeType exportSpec = handler.newExportBatchSpec(pos());
     if (!exportSpec) {
         return null();
     }
 
     handler.addList(kid, exportSpec);
 
-    MUST_MATCH_TOKEN(TokenKind::From, JSMSG_FROM_AFTER_EXPORT_STAR);
+    if (!mustMatchToken(TokenKind::From, JSMSG_FROM_AFTER_EXPORT_STAR)) {
+        return null();
+    }
 
     return exportFrom(begin, kid);
 }
 
 template<typename Unit>
 bool
 Parser<FullParseHandler, Unit>::checkLocalExportNames(ListNode* node)
 {
@@ -6071,17 +6091,19 @@ typename ParseHandler::BinaryNodeType
 GeneralParser<ParseHandler, Unit>::doWhileStatement(YieldHandling yieldHandling)
 {
     uint32_t begin = pos().begin;
     ParseContext::Statement stmt(pc, StatementKind::DoLoop);
     Node body = statement(yieldHandling);
     if (!body) {
         return null();
     }
-    MUST_MATCH_TOKEN_MOD(TokenKind::While, TokenStream::Operand, JSMSG_WHILE_AFTER_DO);
+    if (!mustMatchToken(TokenKind::While, TokenStream::Operand, JSMSG_WHILE_AFTER_DO)) {
+        return null();
+    }
     Node cond = condition(InAllowed, yieldHandling);
     if (!cond) {
         return null();
     }
 
     // The semicolon after do-while is even more optional than most
     // semicolons in JS.  Web compat required this by 2004:
     //   http://bugzilla.mozilla.org/show_bug.cgi?id=238945
@@ -6377,50 +6399,56 @@ GeneralParser<ParseHandler, Unit>::forSt
     }
 
     TernaryNodeType forHead;
     if (headKind == ParseNodeKind::ForHead) {
         Node init = startNode;
 
         // Look for an operand: |for (;| means we might have already examined
         // this semicolon with that modifier.
-        MUST_MATCH_TOKEN_MOD(TokenKind::Semi, TokenStream::Operand, JSMSG_SEMI_AFTER_FOR_INIT);
+        if (!mustMatchToken(TokenKind::Semi, TokenStream::Operand, JSMSG_SEMI_AFTER_FOR_INIT)) {
+            return null();
+        }
 
         TokenKind tt;
         if (!tokenStream.peekToken(&tt, TokenStream::Operand)) {
             return null();
         }
 
         Node test;
         if (tt == TokenKind::Semi) {
             test = null();
         } else {
             test = expr(InAllowed, yieldHandling, TripledotProhibited);
             if (!test) {
                 return null();
             }
         }
 
-        MUST_MATCH_TOKEN_MOD(TokenKind::Semi, TokenStream::Operand, JSMSG_SEMI_AFTER_FOR_COND);
+        if (!mustMatchToken(TokenKind::Semi, TokenStream::Operand, JSMSG_SEMI_AFTER_FOR_COND)) {
+            return null();
+        }
 
         if (!tokenStream.peekToken(&tt, TokenStream::Operand)) {
             return null();
         }
 
         Node update;
         if (tt == TokenKind::RightParen) {
             update = null();
         } else {
             update = expr(InAllowed, yieldHandling, TripledotProhibited);
             if (!update) {
                 return null();
             }
         }
 
-        MUST_MATCH_TOKEN_MOD(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_AFTER_FOR_CTRL);
+        if (!mustMatchToken(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_AFTER_FOR_CTRL)) {
+            return null();
+        }
 
         TokenPos headPos(begin, pos().end);
         forHead = handler.newForHead(init, test, update, headPos);
         if (!forHead) {
             return null();
         }
     } else {
         MOZ_ASSERT(headKind == ParseNodeKind::ForIn || headKind == ParseNodeKind::ForOf);
@@ -6435,17 +6463,19 @@ GeneralParser<ParseHandler, Unit>::forSt
             stmt.refineForKind(StatementKind::ForInLoop);
         } else {
             stmt.refineForKind(StatementKind::ForOfLoop);
         }
 
         // Parser::declaration consumed everything up to the closing ')'.  That
         // token follows an {Assignment,}Expression and so must be interpreted
         // as an operand to be consistent with normal expression tokenizing.
-        MUST_MATCH_TOKEN_MOD(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_AFTER_FOR_CTRL);
+        if (!mustMatchToken(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_AFTER_FOR_CTRL)) {
+            return null();
+        }
 
         TokenPos headPos(begin, pos().end);
         forHead = handler.newForInOrOfHead(headKind, target, iteratedExpr, headPos);
         if (!forHead) {
             return null();
         }
     }
 
@@ -6468,25 +6498,31 @@ GeneralParser<ParseHandler, Unit>::forSt
 
 template <class ParseHandler, typename Unit>
 typename ParseHandler::SwitchStatementType
 GeneralParser<ParseHandler, Unit>::switchStatement(YieldHandling yieldHandling)
 {
     MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Switch));
     uint32_t begin = pos().begin;
 
-    MUST_MATCH_TOKEN(TokenKind::LeftParen, JSMSG_PAREN_BEFORE_SWITCH);
+    if (!mustMatchToken(TokenKind::LeftParen, JSMSG_PAREN_BEFORE_SWITCH)) {
+        return null();
+    }
 
     Node discriminant = exprInParens(InAllowed, yieldHandling, TripledotProhibited);
     if (!discriminant) {
         return null();
     }
 
-    MUST_MATCH_TOKEN_MOD(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_AFTER_SWITCH);
-    MUST_MATCH_TOKEN(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_SWITCH);
+    if (!mustMatchToken(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_AFTER_SWITCH)) {
+        return null();
+    }
+    if (!mustMatchToken(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_SWITCH)) {
+        return null();
+    }
 
     ParseContext::Statement stmt(pc, StatementKind::Switch);
     ParseContext::Scope scope(this);
     if (!scope.init(pc)) {
         return null();
     }
 
     ListNodeType caseList = handler.newStatementList(pos());
@@ -6523,17 +6559,19 @@ GeneralParser<ParseHandler, Unit>::switc
             }
             break;
 
           default:
             error(JSMSG_BAD_SWITCH);
             return null();
         }
 
-        MUST_MATCH_TOKEN_MOD(TokenKind::Colon, TokenStream::Operand, JSMSG_COLON_AFTER_CASE);
+        if (!mustMatchToken(TokenKind::Colon, TokenStream::Operand, JSMSG_COLON_AFTER_CASE)) {
+            return null();
+        }
 
         ListNodeType body = handler.newStatementList(pos());
         if (!body) {
             return null();
         }
 
         bool afterReturn = false;
         bool warnedAboutStatementsAfterReturn = false;
@@ -6768,24 +6806,28 @@ GeneralParser<ParseHandler, Unit>::withS
     // mode code, it doesn't even merit a warning in non-strict code.  See
     // https://bugzilla.mozilla.org/show_bug.cgi?id=514576#c1.
     if (pc->sc()->strict()) {
         if (!strictModeError(JSMSG_STRICT_CODE_WITH)) {
             return null();
         }
     }
 
-    MUST_MATCH_TOKEN(TokenKind::LeftParen, JSMSG_PAREN_BEFORE_WITH);
+    if (!mustMatchToken(TokenKind::LeftParen, JSMSG_PAREN_BEFORE_WITH)) {
+        return null();
+    }
 
     Node objectExpr = exprInParens(InAllowed, yieldHandling, TripledotProhibited);
     if (!objectExpr) {
         return null();
     }
 
-    MUST_MATCH_TOKEN_MOD(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_AFTER_WITH);
+    if (!mustMatchToken(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_AFTER_WITH)) {
+        return null();
+    }
 
     Node innerBlock;
     {
         ParseContext::Statement stmt(pc, StatementKind::With);
         innerBlock = statement(yieldHandling);
         if (!innerBlock) {
             return null();
         }
@@ -6919,17 +6961,19 @@ GeneralParser<ParseHandler, Unit>::trySt
      *   a single identifier
      *   TokenKind::RightBracket or TokenKind::RightCurly for a destructuring left-hand side
      *
      * finally nodes are TokenKind::LeftCurly statement lists.
      */
 
     Node innerBlock;
     {
-        MUST_MATCH_TOKEN(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_TRY);
+        if (!mustMatchToken(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_TRY)) {
+            return null();
+        }
 
         uint32_t openedPos = pos().begin;
 
         ParseContext::Statement stmt(pc, StatementKind::Try);
         ParseContext::Scope scope(this);
         if (!scope.init(pc)) {
             return null();
         }
@@ -6975,17 +7019,19 @@ GeneralParser<ParseHandler, Unit>::trySt
         if (!tokenStream.matchToken(&omittedBinding, TokenKind::LeftCurly)) {
             return null();
         }
 
         Node catchName;
         if (omittedBinding) {
             catchName = null();
         } else {
-            MUST_MATCH_TOKEN(TokenKind::LeftParen, JSMSG_PAREN_BEFORE_CATCH);
+            if (!mustMatchToken(TokenKind::LeftParen, JSMSG_PAREN_BEFORE_CATCH)) {
+                return null();
+            }
 
             if (!tokenStream.getToken(&tt)) {
                 return null();
             }
             switch (tt) {
               case TokenKind::LeftBracket:
               case TokenKind::LeftCurly:
                 catchName = destructuringDeclaration(DeclarationKind::CatchParameter,
@@ -7005,19 +7051,23 @@ GeneralParser<ParseHandler, Unit>::trySt
                                               yieldHandling);
                 if (!catchName) {
                     return null();
                 }
                 break;
               }
             }
 
-            MUST_MATCH_TOKEN_MOD(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_AFTER_CATCH);
-
-            MUST_MATCH_TOKEN(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_CATCH);
+            if (!mustMatchToken(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_AFTER_CATCH)) {
+                return null();
+            }
+
+            if (!mustMatchToken(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_CATCH)) {
+                return null();
+            }
         }
 
         LexicalScopeNodeType catchBody = catchBlockStatement(yieldHandling, scope);
         if (!catchBody) {
             return null();
         }
 
         catchScope = finishLexicalScope(scope, catchBody);
@@ -7033,17 +7083,19 @@ GeneralParser<ParseHandler, Unit>::trySt
         if (!tokenStream.getToken(&tt, TokenStream::Operand)) {
             return null();
         }
     }
 
     Node finallyBlock = null();
 
     if (tt == TokenKind::Finally) {
-        MUST_MATCH_TOKEN(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_FINALLY);
+        if (!mustMatchToken(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_FINALLY)) {
+            return null();
+        }
 
         uint32_t openedPos = pos().begin;
 
         ParseContext::Statement stmt(pc, StatementKind::Finally);
         ParseContext::Scope scope(this);
         if (!scope.init(pc)) {
             return null();
         }
@@ -7218,17 +7270,19 @@ GeneralParser<ParseHandler, Unit>::class
             return null();
         }
         classHeritage = memberExpr(yieldHandling, TripledotProhibited, tt);
         if (!classHeritage) {
             return null();
         }
     }
 
-    MUST_MATCH_TOKEN(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_CLASS);
+    if (!mustMatchToken(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_CLASS)) {
+        return null();
+    }
 
     ListNodeType classMembers = handler.newClassMemberList(pos().begin);
     if (!classMembers) {
         return null();
     }
 
     Maybe<DeclarationKind> declKind = Nothing();
     for (;;) {
@@ -8150,17 +8204,19 @@ GeneralParser<ParseHandler, Unit>::condE
         return condition;
     }
 
     Node thenExpr = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
     if (!thenExpr) {
         return null();
     }
 
-    MUST_MATCH_TOKEN_MOD(TokenKind::Colon, TokenStream::Operand, JSMSG_COLON_IN_COND);
+    if (!mustMatchToken(TokenKind::Colon, TokenStream::Operand, JSMSG_COLON_IN_COND)) {
+        return null();
+    }
 
     Node elseExpr = assignExpr(inHandling, yieldHandling, TripledotProhibited);
     if (!elseExpr) {
         return null();
     }
 
     return handler.newConditional(condition, thenExpr, elseExpr);
 }
@@ -8718,17 +8774,19 @@ GeneralParser<ParseHandler, Unit>::argum
         if (!tokenStream.peekToken(&tt, TokenStream::Operand)) {
             return null();
         }
         if (tt == TokenKind::RightParen) {
             break;
         }
     }
 
-    MUST_MATCH_TOKEN_MOD(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_AFTER_ARGS);
+    if (!mustMatchToken(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_AFTER_ARGS)) {
+        return null();
+    }
 
     handler.setEndPosition(argsList, pos().end);
     return argsList;
 }
 
 bool
 ParserBase::checkAndMarkSuperScope()
 {
@@ -8860,17 +8918,19 @@ GeneralParser<ParseHandler, Unit>::membe
                 return null();
             }
         } else if (tt == TokenKind::LeftBracket) {
             Node propExpr = expr(InAllowed, yieldHandling, TripledotProhibited);
             if (!propExpr) {
                 return null();
             }
 
-            MUST_MATCH_TOKEN_MOD(TokenKind::RightBracket, TokenStream::Operand, JSMSG_BRACKET_IN_INDEX);
+            if (!mustMatchToken(TokenKind::RightBracket, TokenStream::Operand, JSMSG_BRACKET_IN_INDEX)) {
+                return null();
+            }
 
             if (handler.isSuperBase(lhs) && !checkAndMarkSuperScope()) {
                 error(JSMSG_BAD_SUPERPROP, "member");
                 return null();
             }
             nextMember = handler.newPropertyByValue(lhs, propExpr, pos().end);
             if (!nextMember) {
                 return null();
@@ -9752,17 +9812,19 @@ GeneralParser<ParseHandler, Unit>::compu
         handler.setListHasNonConstInitializer(literal);
     }
 
     Node assignNode = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
     if (!assignNode) {
         return null();
     }
 
-    MUST_MATCH_TOKEN_MOD(TokenKind::RightBracket, TokenStream::Operand, JSMSG_COMP_PROP_UNTERM_EXPR);
+    if (!mustMatchToken(TokenKind::RightBracket, TokenStream::Operand, JSMSG_COMP_PROP_UNTERM_EXPR)) {
+        return null();
+    }
     return handler.newComputedName(assignNode, begin, pos().end);
 }
 
 template <class ParseHandler, typename Unit>
 typename ParseHandler::ListNodeType
 GeneralParser<ParseHandler, Unit>::objectLiteral(YieldHandling yieldHandling,
                                                  PossibleError* possibleError)
 {
@@ -10156,17 +10218,19 @@ GeneralParser<ParseHandler, Unit>::impor
 
         return handler.newImportMeta(importHolder, metaHolder);
     } else if (next == TokenKind::LeftParen) {
         Node arg = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
         if (!arg) {
             return null();
         }
 
-        MUST_MATCH_TOKEN_MOD(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_AFTER_ARGS);
+        if (!mustMatchToken(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_AFTER_ARGS)) {
+            return null();
+        }
 
         if (!context->runtime()->moduleDynamicImportHook) {
             error(JSMSG_NO_DYNAMIC_IMPORT);
             return null();
         }
 
         return handler.newCallImport(importHolder, arg);
     } else {
@@ -10225,17 +10289,19 @@ GeneralParser<ParseHandler, Unit>::prima
             return handler.newNullLiteral(pos());
         }
 
         // Pass |possibleError| to support destructuring in arrow parameters.
         Node expr = exprInParens(InAllowed, yieldHandling, TripledotAllowed, possibleError);
         if (!expr) {
             return null();
         }
-        MUST_MATCH_TOKEN_MOD(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_IN_PAREN);
+        if (!mustMatchToken(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_IN_PAREN)) {
+            return null();
+        }
         return handler.parenthesize(expr);
       }
 
       case TokenKind::TemplateHead:
         return templateLiteral(yieldHandling);
 
       case TokenKind::NoSubsTemplate:
         return noSubstitutionUntaggedTemplate();
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -871,16 +871,22 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE
     inline void setAwaitHandling(AwaitHandling awaitHandling);
     inline void setInParametersOfAsyncFunction(bool inParameters);
 
     /*
      * Parse a top-level JS script.
      */
     ListNodeType parse();
 
+    MOZ_MUST_USE bool mustMatchToken(TokenKind excpected, unsigned errorNumber) {
+        return mustMatchToken(excpected, TokenStream::None, errorNumber);
+    }
+
+    MOZ_MUST_USE bool mustMatchToken(TokenKind expected, Modifier modifier, unsigned errorNumber);
+
     /* Report the given error at the current offset. */
     void error(unsigned errorNumber, ...);
     void errorWithNotes(UniquePtr<JSErrorNotes> notes, unsigned errorNumber, ...);
 
     /* Report the given error at the given offset. */
     void errorAt(uint32_t offset, unsigned errorNumber, ...);
     void errorWithNotesAt(UniquePtr<JSErrorNotes> notes, uint32_t offset,
                           unsigned errorNumber, ...);
@@ -1297,16 +1303,17 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE
     using Base::innerFunctionForFunctionBox;
     using Base::tokenStream;
 
   private:
     using Base::alloc;
 #if DEBUG
     using Base::checkOptionsCalled;
 #endif
+    using Base::mustMatchToken;
     using Base::error;
     using Base::errorAt;
     using Base::finishFunctionScopes;
     using Base::functionFormalParametersAndBody;
     using Base::handler;
     using Base::innerFunction;
     using Base::keepAtoms;
     using Base::matchOrInsertSemicolon;
@@ -1421,16 +1428,17 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE
 
   private:
     using Base::alloc;
     using Base::checkLabelOrIdentifierReference;
 #if DEBUG
     using Base::checkOptionsCalled;
 #endif
     using Base::context;
+    using Base::mustMatchToken;
     using Base::error;
     using Base::errorAt;
     using Base::finishFunctionScopes;
     using Base::finishLexicalScope;
     using Base::innerFunction;
     using Base::innerFunctionForFunctionBox;
     using Base::keepAtoms;
     using Base::matchOrInsertSemicolon;