зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1303703 - Part 1: Separate binding pattern parsing from object/array literal parsing. r=shu
--HG-- extra : rebase_source : 75919aca29f8d2267efc2dd0012ec80f308081fc
This commit is contained in:
Родитель
63a52fdeab
Коммит
3eb0058955
|
@ -4286,8 +4286,7 @@ Parser<ParseHandler, CharT>::PossibleError::transferErrorsTo(PossibleError* othe
|
|||
|
||||
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));
|
||||
|
||||
|
@ -4299,24 +4298,8 @@ Parser<FullParseHandler, char16_t>::checkDestructuringName(ParseNode* expr,
|
|||
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))
|
||||
|
@ -4335,23 +4318,20 @@ Parser<FullParseHandler, char16_t>::checkDestructuringName(ParseNode* expr,
|
|||
|
||||
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));
|
||||
|
||||
|
@ -4372,10 +4352,10 @@ Parser<FullParseHandler, char16_t>::checkDestructuringObject(ParseNode* objectPa
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
@ -4385,8 +4365,7 @@ Parser<FullParseHandler, char16_t>::checkDestructuringObject(ParseNode* objectPa
|
|||
|
||||
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));
|
||||
|
||||
|
@ -4408,10 +4387,10 @@ Parser<FullParseHandler, char16_t>::checkDestructuringArray(ParseNode* arrayPatt
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -4432,32 +4411,28 @@ Parser<FullParseHandler, char16_t>::checkDestructuringArray(ParseNode* arrayPatt
|
|||
* 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);
|
||||
|
@ -4465,8 +4440,8 @@ Parser<FullParseHandler, char16_t>::checkDestructuringPattern(ParseNode* pattern
|
|||
}
|
||||
|
||||
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())
|
||||
|
@ -4475,6 +4450,274 @@ Parser<FullParseHandler, char16_t>::checkDestructuringPattern(ParseNode* pattern
|
|||
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,
|
||||
|
@ -4484,17 +4727,16 @@ Parser<ParseHandler, CharT>::destructuringDeclaration(DeclarationKind kind,
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -4611,6 +4853,12 @@ Parser<ParseHandler, CharT>::declarationPattern(Node decl, DeclarationKind declK
|
|||
// 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);
|
||||
}
|
||||
|
||||
|
@ -6041,7 +6289,7 @@ Parser<ParseHandler, CharT>::forHeadStart(YieldHandling yieldHandling,
|
|||
|
||||
// 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);
|
||||
|
@ -7988,26 +8236,6 @@ Parser<ParseHandler, CharT>::condExpr1(InHandling inHandling, YieldHandling yiel
|
|||
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,
|
||||
|
@ -8239,7 +8467,7 @@ Parser<ParseHandler, CharT>::assignExpr(InHandling inHandling, YieldHandling yie
|
|||
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)) {
|
||||
|
@ -9589,7 +9817,7 @@ Parser<ParseHandler, CharT>::computedPropertyName(YieldHandling yieldHandling, N
|
|||
// 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)
|
||||
|
@ -9678,8 +9906,8 @@ Parser<ParseHandler, CharT>::objectLiteral(YieldHandling yieldHandling,
|
|||
}
|
||||
} 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));
|
||||
|
@ -9694,7 +9922,7 @@ Parser<ParseHandler, CharT>::objectLiteral(YieldHandling yieldHandling,
|
|||
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));
|
||||
|
|
|
@ -1526,17 +1526,25 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
|
||||
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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче