author | André Bargull <andre.bargull@gmail.com> |
Sat, 22 Apr 2017 02:04:27 -0700 | |
changeset 354592 | 0ad2e4e4cd72b84f178a7b7f1af70760493da1c9 |
parent 354591 | 3e2f102ce3b260a6ad809d31de28bd4c0403f1ea |
child 354593 | d6e29a56658e1931b181eb8c6a7a18d6d1c5b152 |
push id | 31707 |
push user | kwierso@gmail.com |
push date | Mon, 24 Apr 2017 22:53:41 +0000 |
treeherder | mozilla-central@abdcc8dfc283 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | shu |
bugs | 1303703 |
milestone | 55.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
|
js/src/frontend/Parser.cpp | file | annotate | diff | comparison | revisions | |
js/src/frontend/Parser.h | file | annotate | diff | comparison | revisions |
--- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -4281,47 +4281,30 @@ Parser<ParseHandler, CharT>::PossibleErr "Can't transfer fields to an instance which belongs to a different parser"); transferErrorTo(ErrorKind::Destructuring, other); transferErrorTo(ErrorKind::Expression, other); } template <> bool -Parser<FullParseHandler, char16_t>::checkDestructuringName(ParseNode* expr, - const Maybe<DeclarationKind>& maybeDecl) +Parser<FullParseHandler, char16_t>::checkDestructuringAssignmentName(ParseNode* expr) { MOZ_ASSERT(!handler.isUnparenthesizedDestructuringPattern(expr)); // Parentheses are forbidden around destructuring *patterns* (but allowed // around names). Use our nicer error message for parenthesized, nested // patterns. if (handler.isParenthesizedDestructuringPattern(expr)) { errorAt(expr->pn_pos.begin, JSMSG_BAD_DESTRUCT_PARENS); return false; } - // This expression might be in a variable-binding pattern where only plain, - // unparenthesized names are permitted. - if (maybeDecl) { - // Destructuring patterns in declarations must only contain - // unparenthesized names. - if (!handler.isUnparenthesizedName(expr)) { - errorAt(expr->pn_pos.begin, JSMSG_NO_VARIABLE_NAME); - return false; - } - - RootedPropertyName name(context, expr->name()); - // `yield` is already checked, so pass YieldIsName to skip that check. - if (!checkBindingIdentifier(name, expr->pn_pos.begin, YieldIsName)) - return false; - return noteDeclaredName(name, *maybeDecl, expr->pn_pos); - } - - // Otherwise this is an expression in destructuring outside a declaration. + // The expression must be a simple assignment target, i.e. either a name + // or a property accessor. if (handler.isNameAnyParentheses(expr)) { if (const char* chars = handler.nameIsArgumentsEvalAnyParentheses(expr, context)) { if (!strictModeErrorAt(expr->pn_pos.begin, JSMSG_BAD_STRICT_ASSIGN, chars)) return false; } return true; } @@ -4330,33 +4313,30 @@ Parser<FullParseHandler, char16_t>::chec return true; errorAt(expr->pn_pos.begin, JSMSG_BAD_DESTRUCT_TARGET); return false; } template <> bool -Parser<FullParseHandler, char16_t>::checkDestructuringPattern(ParseNode* pattern, - const Maybe<DeclarationKind>& maybeDecl, - PossibleError* possibleError /* = nullptr */); +Parser<FullParseHandler, char16_t>::checkDestructuringAssignmentPattern(ParseNode* pattern, + PossibleError* possibleError /* = nullptr */); template <> bool -Parser<SyntaxParseHandler, char16_t>::checkDestructuringPattern(Node pattern, - const Maybe<DeclarationKind>& maybeDecl, - PossibleError* possibleError /* = nullptr */) +Parser<SyntaxParseHandler, char16_t>::checkDestructuringAssignmentPattern(Node pattern, + PossibleError* possibleError /* = nullptr */) { return abortIfSyntaxParser(); } template <> bool -Parser<FullParseHandler, char16_t>::checkDestructuringObject(ParseNode* objectPattern, - const Maybe<DeclarationKind>& maybeDecl) +Parser<FullParseHandler, char16_t>::checkDestructuringAssignmentObject(ParseNode* objectPattern) { MOZ_ASSERT(objectPattern->isKind(PNK_OBJECT)); for (ParseNode* member = objectPattern->pn_head; member; member = member->pn_next) { ParseNode* target; if (member->isKind(PNK_MUTATEPROTO)) { target = member->pn_kid; } else { @@ -4367,31 +4347,30 @@ Parser<FullParseHandler, char16_t>::chec member->pn_left->pn_atom == member->pn_right->pn_atom); target = member->pn_right; } if (handler.isUnparenthesizedAssignment(target)) target = target->pn_left; if (handler.isUnparenthesizedDestructuringPattern(target)) { - if (!checkDestructuringPattern(target, maybeDecl)) + if (!checkDestructuringAssignmentPattern(target)) return false; } else { - if (!checkDestructuringName(target, maybeDecl)) + if (!checkDestructuringAssignmentName(target)) return false; } } return true; } template <> bool -Parser<FullParseHandler, char16_t>::checkDestructuringArray(ParseNode* arrayPattern, - const Maybe<DeclarationKind>& maybeDecl) +Parser<FullParseHandler, char16_t>::checkDestructuringAssignmentArray(ParseNode* arrayPattern) { MOZ_ASSERT(arrayPattern->isKind(PNK_ARRAY)); for (ParseNode* element = arrayPattern->pn_head; element; element = element->pn_next) { if (element->isKind(PNK_ELISION)) continue; ParseNode* target; @@ -4403,20 +4382,20 @@ Parser<FullParseHandler, char16_t>::chec target = element->pn_kid; } else if (handler.isUnparenthesizedAssignment(element)) { target = element->pn_left; } else { target = element; } if (handler.isUnparenthesizedDestructuringPattern(target)) { - if (!this->checkDestructuringPattern(target, maybeDecl)) + if (!this->checkDestructuringAssignmentPattern(target)) return false; } else { - if (!checkDestructuringName(target, maybeDecl)) + if (!checkDestructuringAssignmentName(target)) return false; } } return true; } /* @@ -4427,79 +4406,342 @@ Parser<FullParseHandler, char16_t>::chec * arbitrary lvalue expressions; the destructuring is just a fancy * assignment. * * - binding-like: |var| and |let| declarations, functions' formal * parameter lists, |catch| clauses, and comprehension tails. In * these cases, the patterns' property value positions must be * simple names; the destructuring defines them as new variables. * - * In both cases, other code parses the pattern as an arbitrary - * primaryExpr, and then, here in checkDestructuringPattern, verify - * that the tree is a valid AssignmentPattern or BindingPattern. + * In the first case, other code parses the pattern as an arbitrary + * primaryExpr, and then, here in checkDestructuringAssignmentPattern, verify + * that the tree is a valid AssignmentPattern. * * In assignment-like contexts, we parse the pattern with - * pc->inDestructuringDecl clear, so the lvalue expressions in the - * pattern are parsed normally. primaryExpr links variable references - * into the appropriate use chains; creates placeholder definitions; - * and so on. checkDestructuringPattern won't bind any new names and - * we specialize lvalues as appropriate. + * pc->inDestructuringDecl clear, so the lvalue expressions in the pattern are + * parsed normally. identifierReference() links variable references into the + * appropriate use chains; creates placeholder definitions; and so on. + * checkDestructuringAssignmentPattern won't bind any new names and we + * specialize lvalues as appropriate. * - * In declaration-like contexts, the normal variable reference - * processing would just be an obstruction, because we're going to - * define the names that appear in the property value positions as new - * variables anyway. In this case, we parse the pattern with - * pc->inDestructuringDecl set, which directs primaryExpr to leave - * whatever name nodes it creates unconnected. Then, here in - * checkDestructuringPattern, we require the pattern's property value - * positions to be simple names, and define them as appropriate to the - * context. + * In declaration-like contexts, the normal variable reference processing + * would just be an obstruction, because we're going to define the names that + * appear in the property value positions as new variables anyway. In this + * case, we parse the pattern in destructuringDeclaration() with + * pc->inDestructuringDecl set, which directs identifierReference() to leave + * whatever name nodes it creates unconnected. */ template <> bool -Parser<FullParseHandler, char16_t>::checkDestructuringPattern(ParseNode* pattern, - const Maybe<DeclarationKind>& maybeDecl, - PossibleError* possibleError /* = nullptr */) +Parser<FullParseHandler, char16_t>::checkDestructuringAssignmentPattern(ParseNode* pattern, + PossibleError* possibleError /* = nullptr */) { if (pattern->isKind(PNK_ARRAYCOMP)) { errorAt(pattern->pn_pos.begin, JSMSG_ARRAY_COMP_LEFTSIDE); return false; } bool isDestructuring = pattern->isKind(PNK_ARRAY) - ? checkDestructuringArray(pattern, maybeDecl) - : checkDestructuringObject(pattern, maybeDecl); + ? checkDestructuringAssignmentArray(pattern) + : checkDestructuringAssignmentObject(pattern); // Report any pending destructuring error. if (isDestructuring && possibleError && !possibleError->checkForDestructuringError()) return false; return isDestructuring; } +class AutoClearInDestructuringDecl +{ + ParseContext* pc_; + Maybe<DeclarationKind> saved_; + + public: + explicit AutoClearInDestructuringDecl(ParseContext* pc) + : pc_(pc), + saved_(pc->inDestructuringDecl) + { + pc->inDestructuringDecl = Nothing(); + if (saved_ && *saved_ == DeclarationKind::FormalParameter) + pc->functionBox()->hasParameterExprs = true; + } + + ~AutoClearInDestructuringDecl() { + pc_->inDestructuringDecl = saved_; + } +}; + +template <template <typename CharT> class ParseHandler, typename CharT> +typename ParseHandler<CharT>::Node +Parser<ParseHandler, CharT>::bindingInitializer(Node lhs, YieldHandling yieldHandling) +{ + MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_ASSIGN)); + + Node rhs; + { + AutoClearInDestructuringDecl autoClear(pc); + rhs = assignExpr(InAllowed, yieldHandling, TripledotProhibited); + if (!rhs) + return null(); + } + + handler.checkAndSetIsDirectRHSAnonFunction(rhs); + + Node assign = handler.newAssignment(PNK_ASSIGN, lhs, rhs, JSOP_NOP); + if (!assign) + return null(); + + if (foldConstants && !FoldConstants(context, &assign, this)) + return null(); + + return assign; +} + +template <template <typename CharT> class ParseHandler, typename CharT> +typename ParseHandler<CharT>::Node +Parser<ParseHandler, CharT>::bindingIdentifier(DeclarationKind kind, YieldHandling yieldHandling) +{ + Rooted<PropertyName*> name(context, bindingIdentifier(yieldHandling)); + if (!name) + return null(); + + Node binding = newName(name); + if (!binding || !noteDeclaredName(name, kind, pos())) + return null(); + + return binding; +} + +template <template <typename CharT> class ParseHandler, typename CharT> +typename ParseHandler<CharT>::Node +Parser<ParseHandler, CharT>::bindingIdentifierOrPattern(DeclarationKind kind, + YieldHandling yieldHandling, TokenKind tt) +{ + if (tt == TOK_LB) + return arrayBindingPattern(kind, yieldHandling); + + if (tt == TOK_LC) + return objectBindingPattern(kind, yieldHandling); + + if (!TokenKindIsPossibleIdentifierName(tt)) { + error(JSMSG_NO_VARIABLE_NAME); + return null(); + } + + return bindingIdentifier(kind, yieldHandling); +} + +template <template <typename CharT> class ParseHandler, typename CharT> +typename ParseHandler<CharT>::Node +Parser<ParseHandler, CharT>::objectBindingPattern(DeclarationKind kind, + YieldHandling yieldHandling) +{ + MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LC)); + + if (!CheckRecursionLimit(context)) + return null(); + + uint32_t begin = pos().begin; + Node literal = handler.newObjectLiteral(begin); + if (!literal) + return null(); + + RootedAtom propAtom(context); + for (;;) { + TokenKind tt; + if (!tokenStream.getToken(&tt)) + return null(); + if (tt == TOK_RC) + break; + + TokenPos namePos = pos(); + + tokenStream.ungetToken(); + + PropertyType propType; + Node propName = propertyName(yieldHandling, literal, &propType, &propAtom); + if (!propName) + return null(); + + if (propType == PropertyType::Normal) { + // Handle e.g., |var {p: x} = o| and |var {p: x=0} = o|. + + if (!tokenStream.getToken(&tt, TokenStream::Operand)) + return null(); + + Node binding = bindingIdentifierOrPattern(kind, yieldHandling, tt); + if (!binding) + return null(); + + bool hasInitializer; + if (!tokenStream.matchToken(&hasInitializer, TOK_ASSIGN)) + return null(); + + Node bindingExpr = hasInitializer + ? bindingInitializer(binding, yieldHandling) + : binding; + if (!bindingExpr) + 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 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)); + + Node binding = bindingIdentifier(kind, yieldHandling); + if (!binding) + return null(); + + tokenStream.consumeKnownToken(TOK_ASSIGN); + + Node bindingExpr = bindingInitializer(binding, yieldHandling); + if (!bindingExpr) + return null(); + + if (!handler.addPropertyDefinition(literal, propName, bindingExpr)) + return null(); + } else { + errorAt(namePos.begin, JSMSG_NO_VARIABLE_NAME); + return null(); + } + + if (!tokenStream.getToken(&tt)) + return null(); + if (tt == TOK_RC) + break; + if (tt != TOK_COMMA) { + reportMissingClosing(JSMSG_CURLY_AFTER_LIST, JSMSG_CURLY_OPENED, begin); + return null(); + } + } + + handler.setEndPosition(literal, pos().end); + return literal; +} + +template <template <typename CharT> class ParseHandler, typename CharT> +typename ParseHandler<CharT>::Node +Parser<ParseHandler, CharT>::arrayBindingPattern(DeclarationKind kind, YieldHandling yieldHandling) +{ + MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LB)); + + if (!CheckRecursionLimit(context)) + return null(); + + uint32_t begin = pos().begin; + Node literal = handler.newArrayLiteral(begin); + if (!literal) + return null(); + + uint32_t index = 0; + TokenStream::Modifier modifier = TokenStream::Operand; + for (; ; index++) { + if (index >= NativeObject::MAX_DENSE_ELEMENTS_COUNT) { + error(JSMSG_ARRAY_INIT_TOO_BIG); + return null(); + } + + TokenKind tt; + if (!tokenStream.getToken(&tt, TokenStream::Operand)) + return null(); + + if (tt == TOK_RB) { + tokenStream.ungetToken(); + break; + } + + if (tt == TOK_COMMA) { + if (!handler.addElision(literal, pos())) + return null(); + } else if (tt == TOK_TRIPLEDOT) { + uint32_t begin = pos().begin; + + TokenKind tt; + if (!tokenStream.getToken(&tt, TokenStream::Operand)) + return null(); + + Node inner = bindingIdentifierOrPattern(kind, yieldHandling, tt); + if (!inner) + return null(); + + if (!handler.addSpreadElement(literal, begin, inner)) + return null(); + } else { + Node binding = bindingIdentifierOrPattern(kind, yieldHandling, tt); + if (!binding) + return null(); + + bool hasInitializer; + if (!tokenStream.matchToken(&hasInitializer, TOK_ASSIGN)) + return null(); + + Node element = hasInitializer ? bindingInitializer(binding, yieldHandling) : binding; + if (!element) + return null(); + + handler.addArrayElement(literal, element); + } + + if (tt != TOK_COMMA) { + // If we didn't already match TOK_COMMA in above case. + bool matched; + if (!tokenStream.matchToken(&matched, TOK_COMMA)) + return null(); + if (!matched) { + modifier = TokenStream::None; + break; + } + if (tt == TOK_TRIPLEDOT) { + error(JSMSG_REST_WITH_COMMA); + return null(); + } + } + } + + MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RB, modifier, + reportMissingClosing(JSMSG_BRACKET_AFTER_LIST, + JSMSG_BRACKET_OPENED, begin)); + + handler.setEndPosition(literal, pos().end); + return literal; +} + template <template <typename CharT> class ParseHandler, typename CharT> typename ParseHandler<CharT>::Node Parser<ParseHandler, CharT>::destructuringDeclaration(DeclarationKind kind, YieldHandling yieldHandling, TokenKind tt) { MOZ_ASSERT(tokenStream.isCurrentTokenType(tt)); MOZ_ASSERT(tt == TOK_LB || tt == TOK_LC); - PossibleError possibleError(*this); Node pattern; { pc->inDestructuringDecl = Some(kind); - pattern = primaryExpr(yieldHandling, TripledotProhibited, tt, &possibleError); + if (tt == TOK_LB) + pattern = arrayBindingPattern(kind, yieldHandling); + else + pattern = objectBindingPattern(kind, yieldHandling); pc->inDestructuringDecl = Nothing(); } - if (!pattern || !checkDestructuringPattern(pattern, Some(kind), &possibleError)) - return null(); - return pattern; } template <template <typename CharT> class ParseHandler, typename CharT> typename ParseHandler<CharT>::Node Parser<ParseHandler, CharT>::destructuringDeclarationWithoutYieldOrAwait(DeclarationKind kind, YieldHandling yieldHandling, TokenKind tt) @@ -4606,16 +4848,22 @@ Parser<ParseHandler, CharT>::declaration handler.checkAndSetIsDirectRHSAnonFunction(init); if (forHeadKind) { // For for(;;) declarations, consistency with |for (;| parsing requires // that the ';' first be examined as Operand, even though absence of a // binary operator (examined with modifier None) terminated |init|. // For all other declarations, through ASI's infinite majesty, a next // token on a new line would begin an expression. + // Similar to the case in initializerInNameDeclaration(), we need to + // peek at the next token when assignExpr() is a lazily parsed arrow + // function. + TokenKind ignored; + if (!tokenStream.peekToken(&ignored)) + return null(); tokenStream.addModifierException(TokenStream::OperandIsNone); } return handler.newBinary(PNK_ASSIGN, pattern, init); } template <template <typename CharT> class ParseHandler, typename CharT> bool @@ -6036,17 +6284,17 @@ Parser<ParseHandler, CharT>::forHeadStar errorAt(exprOffset, JSMSG_LET_STARTING_FOROF_LHS); return false; } *forHeadKind = isForIn ? PNK_FORIN : PNK_FOROF; // Verify the left-hand side expression doesn't have a forbidden form. if (handler.isUnparenthesizedDestructuringPattern(*forInitialPart)) { - if (!checkDestructuringPattern(*forInitialPart, Nothing(), &possibleError)) + if (!checkDestructuringAssignmentPattern(*forInitialPart, &possibleError)) return false; } else if (handler.isNameAnyParentheses(*forInitialPart)) { const char* chars = handler.nameIsArgumentsEvalAnyParentheses(*forInitialPart, context); if (chars) { // |chars| is "arguments" or "eval" here. if (!strictModeErrorAt(exprOffset, JSMSG_BAD_STRICT_ASSIGN, chars)) return false; } @@ -7983,36 +8231,16 @@ Parser<ParseHandler, CharT>::condExpr1(I // Advance to the next token; the caller is responsible for interpreting it. TokenKind ignored; if (!tokenStream.getToken(&ignored)) return null(); return handler.newConditional(condition, thenExpr, elseExpr); } -class AutoClearInDestructuringDecl -{ - ParseContext* pc_; - Maybe<DeclarationKind> saved_; - - public: - explicit AutoClearInDestructuringDecl(ParseContext* pc) - : pc_(pc), - saved_(pc->inDestructuringDecl) - { - pc->inDestructuringDecl = Nothing(); - if (saved_ && *saved_ == DeclarationKind::FormalParameter) - pc->functionBox()->hasParameterExprs = true; - } - - ~AutoClearInDestructuringDecl() { - pc_->inDestructuringDecl = saved_; - } -}; - template <template <typename CharT> class ParseHandler, typename CharT> typename ParseHandler<CharT>::Node Parser<ParseHandler, CharT>::assignExpr(InHandling inHandling, YieldHandling yieldHandling, TripledotHandling tripledotHandling, PossibleError* possibleError /* = nullptr */, InvokedPrediction invoked /* = PredictUninvoked */) { if (!CheckRecursionLimit(context)) @@ -8234,17 +8462,17 @@ Parser<ParseHandler, CharT>::assignExpr( // Verify the left-hand side expression doesn't have a forbidden form. if (handler.isUnparenthesizedDestructuringPattern(lhs)) { if (kind != PNK_ASSIGN) { error(JSMSG_BAD_DESTRUCT_ASS); return null(); } - if (!checkDestructuringPattern(lhs, Nothing(), &possibleErrorInner)) + if (!checkDestructuringAssignmentPattern(lhs, &possibleErrorInner)) return null(); } else if (handler.isNameAnyParentheses(lhs)) { if (const char* chars = handler.nameIsArgumentsEvalAnyParentheses(lhs, context)) { // |chars| is "arguments" or "eval" here. if (!strictModeErrorAt(exprOffset, JSMSG_BAD_STRICT_ASSIGN, chars)) return null(); } @@ -9584,17 +9812,17 @@ Parser<ParseHandler, CharT>::computedPro { uint32_t begin = pos().begin; Node assignNode; { // Turn off the inDestructuringDecl flag when parsing computed property // names. In short, when parsing 'let {[x + y]: z} = obj;', noteUsedName() // should be called on x and y, but not on z. See the comment on - // Parser<>::checkDestructuringPattern() for details. + // Parser<>::checkDestructuringAssignmentPattern() for details. AutoClearInDestructuringDecl autoClear(pc); assignNode = assignExpr(InAllowed, yieldHandling, TripledotProhibited); if (!assignNode) return null(); } MUST_MATCH_TOKEN(TOK_RB, JSMSG_COMP_PROP_UNTERM_EXPR); Node propname = handler.newComputedName(assignNode, begin, pos().end); @@ -9673,33 +9901,33 @@ Parser<ParseHandler, CharT>::objectLiter 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., |var {x, y} = o| as destructuring shorthand - * for |var {x: x, y: y} = o|, and |var o = {x, y}| as initializer + * 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(); if (!handler.addShorthand(literal, propName, nameExpr)) return null(); } else if (propType == PropertyType::CoverInitializedName) { /* - * Support, e.g., |var {x=1, y=2} = o| as destructuring shorthand + * 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)
--- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -1521,27 +1521,35 @@ class Parser final : public ParserBase, Node propertyName(YieldHandling yieldHandling, Node propList, PropertyType* propType, MutableHandleAtom propAtom); Node computedPropertyName(YieldHandling yieldHandling, Node literal); Node arrayInitializer(YieldHandling yieldHandling, PossibleError* possibleError); Node newRegExp(); Node objectLiteral(YieldHandling yieldHandling, PossibleError* possibleError); - // Top-level entrypoint into destructuring pattern checking/name-analyzing. - bool checkDestructuringPattern(Node pattern, const mozilla::Maybe<DeclarationKind>& maybeDecl, - PossibleError* possibleError = nullptr); + Node bindingInitializer(Node lhs, YieldHandling yieldHandling); + Node bindingIdentifier(DeclarationKind kind, YieldHandling yieldHandling); + Node bindingIdentifierOrPattern(DeclarationKind kind, YieldHandling yieldHandling, + TokenKind tt); + Node objectBindingPattern(DeclarationKind kind, YieldHandling yieldHandling); + Node arrayBindingPattern(DeclarationKind kind, YieldHandling yieldHandling); - // Recursive methods for checking/name-analyzing subcomponents of a - // destructuring pattern. The array/object methods *must* be passed arrays - // or objects. The name method may be passed anything but will report an - // error if not passed a name. - bool checkDestructuringArray(Node arrayPattern, const mozilla::Maybe<DeclarationKind>& maybeDecl); - bool checkDestructuringObject(Node objectPattern, const mozilla::Maybe<DeclarationKind>& maybeDecl); - bool checkDestructuringName(Node expr, const mozilla::Maybe<DeclarationKind>& maybeDecl); + // Top-level entrypoint into destructuring assignment pattern checking and + // name-analyzing. + bool checkDestructuringAssignmentPattern(Node pattern, + PossibleError* possibleError = nullptr); + + // Recursive methods for checking/name-analyzing subcomponents of an + // destructuring assignment pattern. The array/object methods *must* be + // passed arrays or objects. The name method may be passed anything but + // will report an error if not passed a name. + bool checkDestructuringAssignmentArray(Node arrayPattern); + bool checkDestructuringAssignmentObject(Node objectPattern); + bool checkDestructuringAssignmentName(Node expr); Node newNumber(const Token& tok) { return handler.newNumber(tok.number(), tok.decimalPoint(), tok.pos); } static Node null() { return ParseHandler<CharT>::null(); } JSAtom* prefixAccessorName(PropertyType propType, HandleAtom propAtom);