Bug 1066827 - Part3: Check error in TokenStream.peekTokenSameLine. r=Waldo
☠☠ backed out by 4bd196e44548 ☠ ☠
authorTooru Fujisawa <arai_a@mac.com>
Fri, 24 Oct 2014 20:59:00 +0200
changeset 212608 09e37ba34968d6b850c9057152ae1f50a95f6461
parent 212607 bc56d0664d0282c691a3273323c89ef56ab5d43e
child 212609 f023c533e279fd4bd850c5cb89be9743bf2610eb
push id27721
push usercbook@mozilla.com
push dateTue, 28 Oct 2014 14:55:05 +0000
treeherdermozilla-central@c0ddb1b098ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1066827
milestone36.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 1066827 - Part3: Check error in TokenStream.peekTokenSameLine. r=Waldo
js/src/frontend/Parser.cpp
js/src/frontend/TokenStream.h
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -1217,18 +1217,18 @@ Parser<ParseHandler>::newFunction(Generi
     if (options().selfHostingMode)
         fun->setIsSelfHostedBuiltin();
     return fun;
 }
 
 static bool
 MatchOrInsertSemicolon(TokenStream &ts)
 {
-    TokenKind tt = ts.peekTokenSameLine(TokenStream::Operand);
-    if (tt == TOK_ERROR)
+    TokenKind tt;
+    if (!ts.peekTokenSameLine(&tt, TokenStream::Operand))
         return false;
     if (tt != TOK_EOF && tt != TOK_EOL && tt != TOK_SEMI && tt != TOK_RC) {
         /* Advance the scanner for proper error location reporting. */
         ts.consumeKnownToken(tt);
         ts.reportError(JSMSG_SEMI_BEFORE_STMNT);
         return false;
     }
     (void) ts.matchToken(TOK_SEMI);
@@ -2785,18 +2785,18 @@ Parser<ParseHandler>::condition()
     }
     return pn;
 }
 
 template <typename ParseHandler>
 bool
 Parser<ParseHandler>::matchLabel(MutableHandle<PropertyName*> label)
 {
-    TokenKind tt = tokenStream.peekTokenSameLine(TokenStream::Operand);
-    if (tt == TOK_ERROR)
+    TokenKind tt;
+    if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand))
         return false;
     if (tt == TOK_NAME) {
         tokenStream.consumeKnownToken(TOK_NAME);
         label.set(tokenStream.currentName());
     } else if (tt == TOK_YIELD) {
         tokenStream.consumeKnownToken(TOK_YIELD);
         if (!checkYieldNameValidity())
             return false;
@@ -5038,19 +5038,20 @@ Parser<ParseHandler>::returnStatement()
         report(ParseError, false, null(), JSMSG_BAD_RETURN_OR_YIELD, js_return_str);
         return null();
     }
 
     // Parse an optional operand.
     //
     // This is ugly, but we don't want to require a semicolon.
     Node exprNode;
-    switch (tokenStream.peekTokenSameLine(TokenStream::Operand)) {
-      case TOK_ERROR:
-        return null();
+    TokenKind tt;
+    if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand))
+        return null();
+    switch (tt) {
       case TOK_EOF:
       case TOK_EOL:
       case TOK_SEMI:
       case TOK_RC:
         exprNode = null();
         pc->funHasReturnVoid = true;
         break;
       default: {
@@ -5104,19 +5105,20 @@ Parser<ParseHandler>::yieldExpression()
       case StarGenerator:
       {
         MOZ_ASSERT(pc->sc->isFunctionBox());
 
         pc->lastYieldOffset = begin;
 
         Node exprNode;
         ParseNodeKind kind = PNK_YIELD;
-        switch (tokenStream.peekTokenSameLine(TokenStream::Operand)) {
-          case TOK_ERROR:
-            return null();
+        TokenKind tt;
+        if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand))
+            return null();
+        switch (tt) {
           // TOK_EOL is special; it implements the [no LineTerminator here]
           // quirk in the grammar.
           case TOK_EOL:
           // The rest of these make up the complete set of tokens that can
           // appear after any of the places where AssignmentExpression is used
           // throughout the grammar.  Conveniently, none of them can also be the
           // start an expression.
           case TOK_EOF:
@@ -5171,19 +5173,20 @@ Parser<ParseHandler>::yieldExpression()
         // We are in a legacy generator: a function that has already seen a
         // yield, or in a legacy generator comprehension.
         MOZ_ASSERT(pc->sc->isFunctionBox());
 
         pc->lastYieldOffset = begin;
 
         // Legacy generators do not require a value.
         Node exprNode;
-        switch (tokenStream.peekTokenSameLine(TokenStream::Operand)) {
-          case TOK_ERROR:
-            return null();
+        TokenKind tt;
+        if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand))
+            return null();
+        switch (tt) {
           case TOK_EOF:
           case TOK_EOL:
           case TOK_SEMI:
           case TOK_RC:
           case TOK_RB:
           case TOK_RP:
           case TOK_COLON:
           case TOK_COMMA:
@@ -5310,18 +5313,18 @@ Parser<ParseHandler>::labeledStatement()
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::throwStatement()
 {
     MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_THROW));
     uint32_t begin = pos().begin;
 
     /* ECMA-262 Edition 3 says 'throw [no LineTerminator here] Expr'. */
-    TokenKind tt = tokenStream.peekTokenSameLine(TokenStream::Operand);
-    if (tt == TOK_ERROR)
+    TokenKind tt;
+    if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand))
         return null();
     if (tt == TOK_EOF || tt == TOK_SEMI || tt == TOK_RC) {
         report(ParseError, false, null(), JSMSG_MISSING_EXPR_AFTER_THROW);
         return null();
     }
     if (tt == TOK_EOL) {
         report(ParseError, false, null(), JSMSG_LINE_BREAK_AFTER_THROW);
         return null();
@@ -6116,17 +6119,18 @@ Parser<ParseHandler>::unaryExpr()
       }
 
       default:
         pn = memberExpr(tt, true);
         if (!pn)
             return null();
 
         /* Don't look across a newline boundary for a postfix incop. */
-        tt = tokenStream.peekTokenSameLine(TokenStream::Operand);
+        if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand))
+            return null();
         if (tt == TOK_INC || tt == TOK_DEC) {
             tokenStream.consumeKnownToken(tt);
             if (!checkAndMarkAsIncOperand(pn, tt, false))
                 return null();
             return handler.newUnary((tt == TOK_INC) ? PNK_POSTINCREMENT : PNK_POSTDECREMENT,
                                     JSOP_NOP,
                                     begin,
                                     pn);
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -409,45 +409,52 @@ class MOZ_STACK_CLASS TokenStream
         getTokenInternal(modifier);
         ungetToken();
         MOZ_ASSERT(lookahead != 0);
         return tokens[(cursor + 1) & ntokensMask].pos;
     }
 
     // This is like peekToken(), with one exception:  if there is an EOL
     // between the end of the current token and the start of the next token, it
-    // returns TOK_EOL.  In that case, no token with TOK_EOL is actually
-    // created, just a TOK_EOL TokenKind is returned, and currentToken()
-    // shouldn't be consulted.  (This is the only place TOK_EOL is produced.)
-    MOZ_ALWAYS_INLINE TokenKind peekTokenSameLine(Modifier modifier = None) {
-       const Token &curr = currentToken();
+    // return true and store TOK_EOL in |*ttp|.  In that case, no token with
+    // TOK_EOL is actually created, just a TOK_EOL TokenKind is returned, and
+    // currentToken() shouldn't be consulted.  (This is the only place TOK_EOL
+    // is produced.)
+    MOZ_ALWAYS_INLINE bool
+    peekTokenSameLine(TokenKind *ttp, Modifier modifier = None) {
+        const Token &curr = currentToken();
 
         // If lookahead != 0, we have scanned ahead at least one token, and
         // |lineno| is the line that the furthest-scanned token ends on.  If
         // it's the same as the line that the current token ends on, that's a
         // stronger condition than what we are looking for, and we don't need
         // to return TOK_EOL.
-        if (lookahead != 0 && srcCoords.isOnThisLine(curr.pos.end, lineno))
-            return tokens[(cursor + 1) & ntokensMask].type;
+        if (lookahead != 0 && srcCoords.isOnThisLine(curr.pos.end, lineno)) {
+            TokenKind tt = tokens[(cursor + 1) & ntokensMask].type;
+            *ttp = tt;
+            return tt != TOK_ERROR;
+        }
 
         // The above check misses two cases where we don't have to return
         // TOK_EOL.
         // - The next token starts on the same line, but is a multi-line token.
         // - The next token starts on the same line, but lookahead==2 and there
         //   is a newline between the next token and the one after that.
         // The following test is somewhat expensive but gets these cases (and
         // all others) right.
         TokenKind tmp;
         if (!getToken(&tmp, modifier))
-            return TOK_ERROR;
+            return false;
         const Token &next = currentToken();
         ungetToken();
-        return srcCoords.lineNum(curr.pos.end) == srcCoords.lineNum(next.pos.begin)
-               ? next.type
-               : TOK_EOL;
+
+        *ttp = srcCoords.lineNum(curr.pos.end) == srcCoords.lineNum(next.pos.begin)
+             ? next.type
+             : TOK_EOL;
+        return true;
     }
 
     // Get the next token from the stream if its kind is |tt|.
     bool matchToken(TokenKind tt, Modifier modifier = None) {
         TokenKind token;
         if (!getToken(&token, modifier)) {
             ungetToken();
             return false;