Bug 1296814 - Introduce Parser::errorAt to reduce reporting an error at a particular offset to its bare essentials. r=anba
authorJeff Walden <jwalden@mit.edu>
Sun, 13 Nov 2016 00:10:54 -0800
changeset 322558 9ec9d6149b5e8bc091775e67aa921738f0b5624a
parent 322557 4b4b6a642aeb2c5d6c8098e6c49d6d44ec550afb
child 322559 a09a93a0b5a9a3218fb621ee44f6cba5d1f5367e
push id21
push usermaklebus@msu.edu
push dateThu, 01 Dec 2016 06:22:08 +0000
reviewersanba
bugs1296814
milestone52.0a1
Bug 1296814 - Introduce Parser::errorAt to reduce reporting an error at a particular offset to its bare essentials. r=anba
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -598,16 +598,30 @@ Parser<ParseHandler>::error(unsigned err
     bool result =
 #endif
         reportHelper(ParseError, false, pos().begin, errorNumber, args);
     MOZ_ASSERT(!result, "reporting an error returned true?");
     va_end(args);
 }
 
 template <typename ParseHandler>
+void
+Parser<ParseHandler>::errorAt(uint32_t offset, unsigned errorNumber, ...)
+{
+    va_list args;
+    va_start(args, errorNumber);
+#ifdef DEBUG
+    bool result =
+#endif
+        reportHelper(ParseError, false, offset, errorNumber, args);
+    MOZ_ASSERT(!result, "reporting an error returned true?");
+    va_end(args);
+}
+
+template <typename ParseHandler>
 bool
 Parser<ParseHandler>::warning(unsigned errorNumber, ...)
 {
     va_list args;
     va_start(args, errorNumber);
     bool result = reportHelper(ParseWarning, false, pos().begin, errorNumber, args);
     va_end(args);
     return result;
@@ -927,18 +941,17 @@ Parser<ParseHandler>::checkStrictBinding
 {
     if (!pc->sc()->needStrictChecks())
         return true;
 
     if (!isValidStrictBinding(name)) {
         JSAutoByteString bytes;
         if (!AtomToPrintableString(context, name, &bytes))
             return false;
-        return reportWithOffset(ParseStrictError, pc->sc()->strict(), pos.begin,
-                                JSMSG_BAD_BINDING, bytes.ptr());
+        return strictModeErrorAt(pos.begin, JSMSG_BAD_BINDING, bytes.ptr());
     }
 
     return true;
 }
 
 /*
  * Returns true if all parameter names are valid strict mode binding names and
  * no duplicate parameter names are present.
@@ -964,18 +977,17 @@ Parser<ParseHandler>::hasValidSimpleStri
 template <typename ParseHandler>
 void
 Parser<ParseHandler>::reportRedeclaration(HandlePropertyName name, DeclarationKind kind,
                                           TokenPos pos)
 {
     JSAutoByteString bytes;
     if (!AtomToPrintableString(context, name, &bytes))
         return;
-    reportWithOffset(ParseError, false, pos.begin, JSMSG_REDECLARED_VAR,
-                     DeclarationKindString(kind), bytes.ptr());
+    errorAt(pos.begin, JSMSG_REDECLARED_VAR, DeclarationKindString(kind), bytes.ptr());
 }
 
 // notePositionalFormalParameter is called for both the arguments of a regular
 // function definition and the arguments specified by the Function
 // constructor.
 //
 // The 'disallowDuplicateParams' bool indicates whether the use of another
 // feature (destructuring or default arguments) disables duplicate arguments.
@@ -1234,21 +1246,21 @@ Parser<ParseHandler>::checkLexicalDeclar
 {
     MOZ_ASSERT(DeclarationKindIsLexical(kind));
 
     // It is an early error to declare a lexical binding not directly
     // within a block.
     if (!StatementKindIsBraced(stmt.kind()) &&
         stmt.kind() != StatementKind::ForLoopLexicalHead)
     {
-        reportWithOffset(ParseError, false, pos.begin,
-                         stmt.kind() == StatementKind::Label
-                         ? JSMSG_LEXICAL_DECL_LABEL
-                         : JSMSG_LEXICAL_DECL_NOT_IN_BLOCK,
-                         DeclarationKindString(kind));
+        errorAt(pos.begin,
+                stmt.kind() == StatementKind::Label
+                ? JSMSG_LEXICAL_DECL_LABEL
+                : JSMSG_LEXICAL_DECL_NOT_IN_BLOCK,
+                DeclarationKindString(kind));
         return false;
     }
 
     return true;
 }
 
 template <typename ParseHandler>
 bool
@@ -1328,17 +1340,17 @@ Parser<ParseHandler>::noteDeclaredName(H
       }
 
       case DeclarationKind::Let:
       case DeclarationKind::Const:
         // The BoundNames of LexicalDeclaration and ForDeclaration must not
         // contain 'let'. (CatchParameter is the only lexical binding form
         // without this restriction.)
         if (name == context->names().let) {
-            reportWithOffset(ParseError, false, pos.begin, JSMSG_LEXICAL_DECL_DEFINES_LET);
+            errorAt(pos.begin, JSMSG_LEXICAL_DECL_DEFINES_LET);
             return false;
         }
 
         MOZ_FALLTHROUGH;
 
       case DeclarationKind::Import:
         // Module code is always strict, so 'let' is always a keyword and never a name.
         MOZ_ASSERT(name != context->names().let);
@@ -3645,17 +3657,17 @@ IsEscapeFreeStringLiteral(const TokenPos
 template <typename ParseHandler>
 bool
 Parser<ParseHandler>::checkUnescapedName()
 {
     const Token& token = tokenStream.currentToken();
     if (!token.nameContainsEscape())
         return true;
 
-    reportWithOffset(ParseError, false, token.pos.begin, JSMSG_ESCAPED_KEYWORD);
+    errorAt(token.pos.begin, JSMSG_ESCAPED_KEYWORD);
     return false;
 }
 
 template <>
 bool
 Parser<SyntaxParseHandler>::asmJS(Node list)
 {
     // While asm.js could technically be validated and compiled during syntax
@@ -3755,18 +3767,17 @@ Parser<ParseHandler>::maybeParseDirectiv
             if (pc->isFunctionBox()) {
                 FunctionBox* funbox = pc->functionBox();
                 if (!funbox->hasSimpleParameterList()) {
                     const char* parameterKind = funbox->hasDestructuringArgs
                                                 ? "destructuring"
                                                 : funbox->hasParameterExprs
                                                 ? "default"
                                                 : "rest";
-                    reportWithOffset(ParseError, false, directivePos.begin,
-                                     JSMSG_STRICT_NON_SIMPLE_PARAMS, parameterKind);
+                    errorAt(directivePos.begin, JSMSG_STRICT_NON_SIMPLE_PARAMS, parameterKind);
                     return false;
                 }
             }
 
             // We're going to be in strict mode. Note that this scope explicitly
             // had "use strict";
             pc->sc()->setExplicitUseStrict();
             if (!pc->sc()->strict()) {
@@ -3953,17 +3964,17 @@ Parser<ParseHandler>::PossibleError::set
 template <typename ParseHandler>
 bool
 Parser<ParseHandler>::PossibleError::checkForError(ErrorKind kind)
 {
     if (!hasError(kind))
         return true;
 
     Error& err = error(kind);
-    parser_.reportWithOffset(ParseError, false, err.offset_, err.errorNumber_);
+    parser_.errorAt(err.offset_, err.errorNumber_);
     return false;
 }
 
 template <typename ParseHandler>
 bool
 Parser<ParseHandler>::PossibleError::checkForDestructuringError()
 {
     // Clear pending expression error, because we're definitely not in an
@@ -4242,21 +4253,21 @@ Parser<ParseHandler>::destructuringDecla
                                                                   YieldHandling yieldHandling,
                                                                   TokenKind tt)
 {
     uint32_t startYieldOffset = pc->lastYieldOffset;
     uint32_t startAwaitOffset = pc->lastAwaitOffset;
     Node res = destructuringDeclaration(kind, yieldHandling, tt);
     if (res) {
         if (pc->lastYieldOffset != startYieldOffset) {
-            reportWithOffset(ParseError, false, pc->lastYieldOffset, JSMSG_YIELD_IN_DEFAULT);
+            errorAt(pc->lastYieldOffset, JSMSG_YIELD_IN_DEFAULT);
             return null();
         }
         if (pc->lastAwaitOffset != startAwaitOffset) {
-            reportWithOffset(ParseError, false, pc->lastAwaitOffset, JSMSG_AWAIT_IN_DEFAULT);
+            errorAt(pc->lastAwaitOffset, JSMSG_AWAIT_IN_DEFAULT);
             return null();
         }
     }
     return res;
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
@@ -4690,17 +4701,17 @@ Parser<FullParseHandler>::namedImportsOr
 
         MUST_MATCH_TOKEN_MOD(TOK_RC, modifier, JSMSG_RC_AFTER_IMPORT_SPEC_LIST);
     } else {
         MOZ_ASSERT(tt == TOK_MUL);
         if (!tokenStream.getToken(&tt))
             return false;
 
         if (tt != TOK_NAME || tokenStream.currentName() != context->names().as) {
-            reportWithOffset(ParseError, false, pos().begin, JSMSG_AS_AFTER_IMPORT_STAR);
+            error(JSMSG_AS_AFTER_IMPORT_STAR);
             return false;
         }
 
         if (!checkUnescapedName())
             return false;
 
         MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_BINDING_NAME);
 
@@ -5596,17 +5607,17 @@ Parser<ParseHandler>::forStatement(Yield
 
     MOZ_ASSERT(headKind == PNK_FORIN || headKind == PNK_FOROF || headKind == PNK_FORHEAD);
 
     Node forHead;
     if (headKind == PNK_FORHEAD) {
         Node init = startNode;
 
         if (isForEach) {
-            reportWithOffset(ParseError, false, begin, JSMSG_BAD_FOR_EACH_LOOP);
+            errorAt(begin, JSMSG_BAD_FOR_EACH_LOOP);
             return null();
         }
 
         // 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);
 
         TokenKind tt;
@@ -5831,17 +5842,17 @@ Parser<ParseHandler>::continueStatement(
         bool foundLoop = false;
 
         for (;;) {
             stmt = ParseContext::Statement::findNearest(stmt, isLoop);
             if (!stmt) {
                 if (foundLoop)
                     error(JSMSG_LABEL_NOT_FOUND);
                 else
-                    reportWithOffset(ParseError, false, begin, JSMSG_BAD_CONTINUE);
+                    errorAt(begin, JSMSG_BAD_CONTINUE);
                 return null();
             }
 
             foundLoop = true;
 
             // Is it labeled by our label?
             bool foundTarget = false;
             stmt = stmt->enclosing();
@@ -5890,17 +5901,17 @@ Parser<ParseHandler>::breakStatement(Yie
             return null();
         }
     } else {
         auto isBreakTarget = [](ParseContext::Statement* stmt) {
             return StatementKindIsUnlabeledBreakTarget(stmt->kind());
         };
 
         if (!pc->findInnermostStatement(isBreakTarget)) {
-            reportWithOffset(ParseError, false, begin, JSMSG_TOUGH_BREAK);
+            errorAt(begin, JSMSG_TOUGH_BREAK);
             return null();
         }
     }
 
     if (!MatchOrInsertSemicolonAfterNonExpression(tokenStream))
         return null();
 
     return handler.newBreakStatement(label, TokenPos(begin, pos().end));
@@ -6045,27 +6056,25 @@ Parser<ParseHandler>::yieldExpression(In
             return null();
 
         if (!pc->isFunctionBox()) {
             error(JSMSG_BAD_RETURN_OR_YIELD, js_yield_str);
             return null();
         }
 
         if (pc->functionBox()->isArrow()) {
-            reportWithOffset(ParseError, false, begin,
-                             JSMSG_YIELD_IN_ARROW, js_yield_str);
+            errorAt(begin, JSMSG_YIELD_IN_ARROW, js_yield_str);
             return null();
         }
 
         if (pc->functionBox()->function()->isMethod() ||
             pc->functionBox()->function()->isGetter() ||
             pc->functionBox()->function()->isSetter())
         {
-            reportWithOffset(ParseError, false, begin,
-                             JSMSG_YIELD_IN_METHOD, js_yield_str);
+            errorAt(begin, JSMSG_YIELD_IN_METHOD, js_yield_str);
             return null();
         }
 
         if (pc->funHasReturnExpr
 #if JS_HAS_EXPR_CLOSURES
             || pc->functionBox()->function()->isExprBody()
 #endif
             )
@@ -6201,17 +6210,17 @@ Parser<ParseHandler>::labeledStatement(Y
 
     auto hasSameLabel = [&label](ParseContext::LabelStatement* stmt) {
         return stmt->label() == label;
     };
 
     uint32_t begin = pos().begin;
 
     if (pc->findInnermostStatement<ParseContext::LabelStatement>(hasSameLabel)) {
-        reportWithOffset(ParseError, false, begin, JSMSG_DUPLICATE_LABEL);
+        errorAt(begin, JSMSG_DUPLICATE_LABEL);
         return null();
     }
 
     tokenStream.consumeKnownToken(TOK_COLON);
 
     /* Push a label struct and parse the statement. */
     ParseContext::LabelStatement stmt(pc, label);
     Node pn = labeledItem(yieldHandling);
@@ -8234,18 +8243,17 @@ Parser<ParseHandler>::comprehension(Gene
 
     uint32_t startYieldOffset = pc->lastYieldOffset;
 
     Node body = comprehensionFor(comprehensionKind);
     if (!body)
         return null();
 
     if (comprehensionKind != NotGenerator && pc->lastYieldOffset != startYieldOffset) {
-        reportWithOffset(ParseError, false, pc->lastYieldOffset,
-                         JSMSG_BAD_GENEXP_BODY, js_yield_str);
+        errorAt(pc->lastYieldOffset, JSMSG_BAD_GENEXP_BODY, js_yield_str);
         return null();
     }
 
     return body;
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
@@ -8297,21 +8305,21 @@ template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::assignExprWithoutYieldOrAwait(YieldHandling yieldHandling)
 {
     uint32_t startYieldOffset = pc->lastYieldOffset;
     uint32_t startAwaitOffset = pc->lastAwaitOffset;
     Node res = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
     if (res) {
         if (pc->lastYieldOffset != startYieldOffset) {
-            reportWithOffset(ParseError, false, pc->lastYieldOffset, JSMSG_YIELD_IN_DEFAULT);
+            errorAt(pc->lastYieldOffset, JSMSG_YIELD_IN_DEFAULT);
             return null();
         }
         if (pc->lastAwaitOffset != startAwaitOffset) {
-            reportWithOffset(ParseError, false, pc->lastAwaitOffset, JSMSG_AWAIT_IN_DEFAULT);
+            errorAt(pc->lastAwaitOffset, JSMSG_AWAIT_IN_DEFAULT);
             return null();
         }
     }
     return res;
 }
 
 template <typename ParseHandler>
 bool
@@ -9133,18 +9141,17 @@ Parser<ParseHandler>::objectLiteral(Yiel
             if (foldConstants && !FoldConstants(context, &propExpr, this))
                 return null();
 
             if (propAtom == context->names().proto) {
                 if (seenPrototypeMutation) {
                     // Directly report the error when we're not in a
                     // destructuring context.
                     if (!possibleError) {
-                        reportWithOffset(ParseError, false, namePos.begin,
-                                         JSMSG_DUPLICATE_PROTO_PROPERTY);
+                        errorAt(namePos.begin, JSMSG_DUPLICATE_PROTO_PROPERTY);
                         return null();
                     }
 
                     // Otherwise delay error reporting until we've determined
                     // whether or not we're destructuring.
                     possibleError->setPendingExpressionErrorAt(namePos,
                                                                JSMSG_DUPLICATE_PROTO_PROPERTY);
                 }
@@ -9377,17 +9384,17 @@ Parser<ParseHandler>::tryNewTarget(Node 
         error(JSMSG_UNEXPECTED_TOKEN, "target", TokenKindToDesc(next));
         return false;
     }
 
     if (!checkUnescapedName())
         return false;
 
     if (!pc->sc()->allowNewTarget()) {
-        reportWithOffset(ParseError, false, begin, JSMSG_BAD_NEWTARGET);
+        errorAt(begin, JSMSG_BAD_NEWTARGET);
         return false;
     }
 
     Node targetHolder = handler.newPosHolder(pos());
     if (!targetHolder)
         return false;
 
     newTarget = handler.newNewTarget(newHolder, targetHolder);
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -910,16 +910,19 @@ class Parser final : private JS::AutoGCR
     bool reportWithNode(ParseReportKind kind, bool strict, Node pn, unsigned errorNumber, ...);
     bool reportNoOffset(ParseReportKind kind, bool strict, unsigned errorNumber, ...);
     bool reportWithOffset(ParseReportKind kind, bool strict, uint32_t offset, unsigned errorNumber,
                           ...);
 
     /* Report the given error at the current offset. */
     void error(unsigned errorNumber, ...);
 
+    /* Report the given error at the given offset. */
+    void errorAt(uint32_t offset, unsigned errorNumber, ...);
+
     /*
      * Handle a strict mode error at the current offset.  Report an error if in
      * strict mode code, or warn if not, using the given error number and
      * arguments.
      */
     MOZ_MUST_USE bool strictModeError(unsigned errorNumber, ...);
 
     /*