summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--js/src/frontend/FullParseHandler.h5
-rw-r--r--js/src/frontend/Parser.cpp377
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;
}