diff options
-rw-r--r-- | js/src/frontend/FullParseHandler.h | 5 | ||||
-rw-r--r-- | js/src/frontend/Parser.cpp | 377 |
2 files changed, 199 insertions, 183 deletions
diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index c7a7e0843..d34cdf43d 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -302,10 +302,9 @@ class FullParseHandler } MOZ_MUST_USE bool addSpreadElement(ParseNode* literal, uint32_t begin, ParseNode* inner) { - TokenPos pos(begin, inner->pn_pos.end); - ParseNode* spread = new_<UnaryNode>(PNK_SPREAD, JSOP_NOP, pos, inner); + ParseNode* spread = newSpread(begin, inner); if (!spread) - return null(); + return false; literal->append(spread); literal->pn_xflags |= PNX_ARRAYHOLESPREAD | PNX_NONCONST; return true; diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index bbdffa064..585eef59d 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -4361,85 +4361,90 @@ Parser<ParseHandler>::objectBindingPattern(DeclarationKind kind, YieldHandling y RootedAtom propAtom(context); for (;;) { TokenKind tt; - if (!tokenStream.getToken(&tt)) + if (!tokenStream.peekToken(&tt)) return null(); if (tt == TOK_RC) break; - TokenPos namePos = pos(); - - tokenStream.ungetToken(); - - PropertyType propType; - Node propName = propertyName(yieldHandling, declKind, literal, &propType, &propAtom); - if (!propName) + if (tt == TOK_TRIPLEDOT) { + // TODO: rest-binding property + error(JSMSG_UNEXPECTED_TOKEN, "property name", TokenKindToDesc(tt)); return null(); + } else { + TokenPos namePos = tokenStream.nextToken().pos; - if (propType == PropertyType::Normal) { - // Handle e.g., |var {p: x} = o| and |var {p: x=0} = o|. - - if (!tokenStream.getToken(&tt, TokenStream::Operand)) + PropertyType propType; + Node propName = propertyName(yieldHandling, declKind, literal, &propType, &propAtom); + if (!propName) return null(); + if (propType == PropertyType::Normal) { + // Handle e.g., |var {p: x} = o| and |var {p: x=0} = o|. - Node binding = bindingIdentifierOrPattern(kind, yieldHandling, tt); - if (!binding) - return null(); + if (!tokenStream.getToken(&tt, TokenStream::Operand)) + return null(); - bool hasInitializer; - if (!tokenStream.matchToken(&hasInitializer, TOK_ASSIGN)) - return null(); + Node binding = bindingIdentifierOrPattern(kind, yieldHandling, tt); + if (!binding) + return null(); - Node bindingExpr = hasInitializer - ? bindingInitializer(binding, kind, yieldHandling) - : binding; - if (!bindingExpr) - return null(); + bool hasInitializer; + if (!tokenStream.matchToken(&hasInitializer, TOK_ASSIGN)) + return null(); - if (!handler.addPropertyDefinition(literal, propName, bindingExpr)) - return null(); - } else if (propType == PropertyType::Shorthand) { - // Handle e.g., |var {x, y} = o| as destructuring shorthand - // for |var {x: x, y: y} = o|. - MOZ_ASSERT(TokenKindIsPossibleIdentifierName(tt)); + Node bindingExpr = hasInitializer + ? bindingInitializer(binding, kind, yieldHandling) + : binding; + if (!bindingExpr) + return null(); - Node binding = bindingIdentifier(kind, yieldHandling); - if (!binding) - return null(); + if (!handler.addPropertyDefinition(literal, propName, bindingExpr)) + return null(); + } else if (propType == PropertyType::Shorthand) { + // Handle e.g., |var {x, y} = o| as destructuring shorthand + // for |var {x: x, y: y} = o|. + MOZ_ASSERT(TokenKindIsPossibleIdentifierName(tt)); - if (!handler.addShorthand(literal, propName, binding)) - return null(); - } else if (propType == PropertyType::CoverInitializedName) { - // Handle e.g., |var {x=1, y=2} = o| as destructuring shorthand - // with default values. - MOZ_ASSERT(TokenKindIsPossibleIdentifierName(tt)); + Node binding = bindingIdentifier(kind, yieldHandling); + if (!binding) + return null(); - Node binding = bindingIdentifier(kind, yieldHandling); - if (!binding) - return null(); + if (!handler.addShorthand(literal, propName, binding)) + return null(); + } else if (propType == PropertyType::CoverInitializedName) { + // Handle e.g., |var {x=1, y=2} = o| as destructuring + // shorthand with default values. + MOZ_ASSERT(TokenKindIsPossibleIdentifierName(tt)); - tokenStream.consumeKnownToken(TOK_ASSIGN); + Node binding = bindingIdentifier(kind, yieldHandling); + if (!binding) + return null(); - Node bindingExpr = bindingInitializer(binding, kind, yieldHandling); - if (!bindingExpr) - return null(); + tokenStream.consumeKnownToken(TOK_ASSIGN); + + Node bindingExpr = bindingInitializer(binding, kind, yieldHandling); + if (!bindingExpr) + return null(); - if (!handler.addPropertyDefinition(literal, propName, bindingExpr)) + if (!handler.addPropertyDefinition(literal, propName, bindingExpr)) + return null(); + } else { + errorAt(namePos.begin, JSMSG_NO_VARIABLE_NAME); return null(); - } else { - errorAt(namePos.begin, JSMSG_NO_VARIABLE_NAME); - return null(); + + } } - if (!tokenStream.getToken(&tt)) + bool matched; + if (!tokenStream.matchToken(&matched, TOK_COMMA)) return null(); - if (tt == TOK_RC) + if (!matched) break; - if (tt != TOK_COMMA) { - reportMissingClosing(JSMSG_CURLY_AFTER_LIST, JSMSG_CURLY_OPENED, begin); - return null(); - } } + MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::None, + reportMissingClosing(JSMSG_CURLY_AFTER_LIST, + JSMSG_CURLY_OPENED, begin)); + handler.setEndPosition(literal, pos().end); return literal; } @@ -9682,173 +9687,185 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError* RootedAtom propAtom(context); for (;;) { TokenKind tt; - if (!tokenStream.getToken(&tt)) + if (!tokenStream.peekToken(&tt)) return null(); if (tt == TOK_RC) break; - TokenPos namePos = pos(); - - tokenStream.ungetToken(); - - PropertyType propType; - Node propName = propertyName(yieldHandling, declKind, literal, &propType, &propAtom); - if (!propName) + if (tt == TOK_TRIPLEDOT) { + // TODO: object spread + error(JSMSG_UNEXPECTED_TOKEN, "property name", TokenKindToDesc(tt)); return null(); + } else { + TokenPos namePos = tokenStream.nextToken().pos; + + PropertyType propType; + Node propName = propertyName(yieldHandling, declKind, literal, &propType, &propAtom); + if (!propName) - if (propType == PropertyType::Normal) { - TokenPos exprPos; - if (!tokenStream.peekTokenPos(&exprPos, TokenStream::Operand)) - return null(); - Node propExpr = assignExpr(InAllowed, yieldHandling, TripledotProhibited, - possibleError); - if (!propExpr) return null(); - handler.checkAndSetIsDirectRHSAnonFunction(propExpr); + if (propType == PropertyType::Normal) { + TokenPos exprPos; + if (!tokenStream.peekTokenPos(&exprPos, TokenStream::Operand)) + return null(); - if (foldConstants && !FoldConstants(context, &propExpr, this)) - return null(); + Node propExpr = assignExpr(InAllowed, yieldHandling, TripledotProhibited, + possibleError); + if (!propExpr) + return null(); - if (propAtom == context->names().proto) { - if (seenPrototypeMutation) { - // Directly report the error when we're not in a - // destructuring context. - if (!possibleError) { - errorAt(namePos.begin, JSMSG_DUPLICATE_PROTO_PROPERTY); - return null(); - } + handler.checkAndSetIsDirectRHSAnonFunction(propExpr); - // Otherwise delay error reporting until we've determined - // whether or not we're destructuring. - possibleError->setPendingExpressionErrorAt(namePos, - JSMSG_DUPLICATE_PROTO_PROPERTY); - } - seenPrototypeMutation = true; + if (possibleError) + checkDestructuringAssignmentElement(propExpr, exprPos, possibleError); - // Note: this occurs *only* if we observe TOK_COLON! Only - // __proto__: v mutates [[Prototype]]. Getters, setters, - // method/generator definitions, computed property name - // versions of all of these, and shorthands do not. - if (!handler.addPrototypeMutation(literal, namePos.begin, propExpr)) + if (foldConstants && !FoldConstants(context, &propExpr, this)) return null(); - } else { - if (!handler.isConstant(propExpr)) - handler.setListFlag(literal, PNX_NONCONST); - if (!handler.addPropertyDefinition(literal, propName, propExpr)) + if (propAtom == context->names().proto) { + if (seenPrototypeMutation) { + // Directly report the error when we're not in a + // destructuring context. + if (!possibleError) { + 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); + } + seenPrototypeMutation = true; + + // Note: this occurs *only* if we observe TOK_COLON! Only + // __proto__: v mutates [[Prototype]]. Getters, setters, + // method/generator definitions, computed property name + // versions of all of these, and shorthands do not. + if (!handler.addPrototypeMutation(literal, namePos.begin, propExpr)) + return null(); + } else { + if (!handler.isConstant(propExpr)) + handler.setListFlag(literal, PNX_NONCONST); + + if (!handler.addPropertyDefinition(literal, propName, propExpr)) + return null(); + } + } else if (propType == PropertyType::Shorthand) { + /* + * Support, e.g., |({x, y} = o)| as destructuring shorthand + * for |({x: x, y: y} = o)|, and |var o = {x, y}| as + * initializer shorthand for |var o = {x: x, y: y}|. + */ + Rooted<PropertyName*> name(context, identifierReference(yieldHandling)); + if (!name) return null(); - } - if (possibleError) - checkDestructuringAssignmentElement(propExpr, exprPos, possibleError); - } else if (propType == PropertyType::Shorthand) { - /* - * Support, e.g., |({x, y} = o)| as destructuring shorthand - * for |({x: x, y: y} = o)|, and |var o = {x, y}| as initializer - * shorthand for |var o = {x: x, y: y}|. - */ - Rooted<PropertyName*> name(context, identifierReference(yieldHandling)); - if (!name) - return null(); + Node nameExpr = identifierReference(name); + if (!nameExpr) + return null(); - Node nameExpr = identifierReference(name); - if (!nameExpr) - return null(); + if (possibleError) + checkDestructuringAssignmentTarget(nameExpr, namePos, possibleError); - if (possibleError) - checkDestructuringAssignmentTarget(nameExpr, namePos, possibleError); + if (!handler.addShorthand(literal, propName, nameExpr)) + return null(); + } else if (propType == PropertyType::CoverInitializedName) { + /* + * Support, e.g., |({x=1, y=2} = o)| as destructuring + * shorthand with default values, as per ES6 12.14.5 + */ + Rooted<PropertyName*> name(context, identifierReference(yieldHandling)); + if (!name) + return null(); - if (!handler.addShorthand(literal, propName, nameExpr)) - return null(); - } else if (propType == PropertyType::CoverInitializedName) { - /* - * Support, e.g., |({x=1, y=2} = o)| as destructuring shorthand - * with default values, as per ES6 12.14.5 - */ - Rooted<PropertyName*> name(context, identifierReference(yieldHandling)); - if (!name) - return null(); + Node lhs = identifierReference(name); + if (!lhs) + return null(); - Node lhs = identifierReference(name); - if (!lhs) - return null(); + tokenStream.consumeKnownToken(TOK_ASSIGN); - tokenStream.consumeKnownToken(TOK_ASSIGN); + if (!seenCoverInitializedName) { + // "shorthand default" or "CoverInitializedName" syntax is + // only valid in the case of destructuring. + seenCoverInitializedName = true; - if (!seenCoverInitializedName) { - // "shorthand default" or "CoverInitializedName" syntax is only - // valid in the case of destructuring. - seenCoverInitializedName = true; + if (!possibleError) { + // Destructuring defaults are definitely not allowed + // in this object literal, because of something the + // caller knows about the preceding code. For example, + // maybe the preceding token is an operator: + // |x + {y=z}|. + error(JSMSG_COLON_AFTER_ID); + return null(); + } - if (!possibleError) { - // Destructuring defaults are definitely not allowed in this object literal, - // because of something the caller knows about the preceding code. - // For example, maybe the preceding token is an operator: `x + {y=z}`. - error(JSMSG_COLON_AFTER_ID); - return null(); + // Here we set a pending error so that later in the parse, + // once we've determined whether or not we're + // destructuring, the error can be reported or ignored + // appropriately. + possibleError->setPendingExpressionErrorAt(pos(), JSMSG_COLON_AFTER_ID); } - // Here we set a pending error so that later in the parse, once we've - // determined whether or not we're destructuring, the error can be - // reported or ignored appropriately. - possibleError->setPendingExpressionErrorAt(pos(), JSMSG_COLON_AFTER_ID); - } + if (const char* chars = handler.nameIsArgumentsEvalAnyParentheses(lhs, context)) { + // |chars| is "arguments" or "eval" here. + if (!strictModeErrorAt(namePos.begin, JSMSG_BAD_STRICT_ASSIGN, chars)) + return null(); + } - if (const char* chars = handler.nameIsArgumentsEvalAnyParentheses(lhs, context)) { - // |chars| is "arguments" or "eval" here. - if (!strictModeErrorAt(namePos.begin, JSMSG_BAD_STRICT_ASSIGN, chars)) + Node rhs = assignExpr(InAllowed, yieldHandling, TripledotProhibited); + if (!rhs) return null(); - } - Node rhs = assignExpr(InAllowed, yieldHandling, TripledotProhibited); - if (!rhs) - return null(); + handler.checkAndSetIsDirectRHSAnonFunction(rhs); - handler.checkAndSetIsDirectRHSAnonFunction(rhs); - - Node propExpr = handler.newAssignment(PNK_ASSIGN, lhs, rhs, JSOP_NOP); - if (!propExpr) - return null(); + Node propExpr = handler.newAssignment(PNK_ASSIGN, lhs, rhs, JSOP_NOP); + if (!propExpr) + return null(); - if (!handler.addPropertyDefinition(literal, propName, propExpr)) - return null(); - } else { - RootedAtom funName(context); - if (!tokenStream.isCurrentTokenType(TOK_RB)) { - funName = propAtom; + if (!handler.addPropertyDefinition(literal, propName, propExpr)) + return null(); + } else { + RootedAtom funName(context); + if (!tokenStream.isCurrentTokenType(TOK_RB)) { + funName = propAtom; - if (propType == PropertyType::Getter || propType == PropertyType::Setter) { - funName = prefixAccessorName(propType, propAtom); - if (!funName) - return null(); + if (propType == PropertyType::Getter || propType == PropertyType::Setter) { + funName = prefixAccessorName(propType, propAtom); + if (!funName) + return null(); + } } - } - Node fn = methodDefinition(namePos.begin, propType, funName); - if (!fn) - return null(); + Node fn = methodDefinition(namePos.begin, propType, funName); + if (!fn) + return null(); - handler.checkAndSetIsDirectRHSAnonFunction(fn); + handler.checkAndSetIsDirectRHSAnonFunction(fn); - JSOp op = JSOpFromPropertyType(propType); - if (!handler.addObjectMethodDefinition(literal, propName, fn, op)) - return null(); + JSOp op = JSOpFromPropertyType(propType); + if (!handler.addObjectMethodDefinition(literal, propName, fn, op)) + return null(); - if (possibleError) - possibleError->setPendingDestructuringErrorAt(namePos, JSMSG_BAD_DESTRUCT_TARGET); + if (possibleError) { + possibleError->setPendingDestructuringErrorAt(namePos, + JSMSG_BAD_DESTRUCT_TARGET); + } + } } - if (!tokenStream.getToken(&tt)) + bool matched; + if (!tokenStream.matchToken(&matched, TOK_COMMA)) return null(); - if (tt == TOK_RC) + if (!matched) break; - if (tt != TOK_COMMA) { - reportMissingClosing(JSMSG_CURLY_AFTER_LIST, JSMSG_CURLY_OPENED, openedPos); - return null(); - } } + MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::None, + reportMissingClosing(JSMSG_CURLY_AFTER_LIST, + JSMSG_CURLY_OPENED, openedPos)); + handler.setEndPosition(literal, pos().end); return literal; } |