Reject object binding pattern rest followed by a binding pattern (Issue #1334)

BindingRestProperty in an object binding pattern only accepts a
BindingIdentifier, unlike BindingRestElement in an array binding pattern
which also accepts a BindingPattern. Throw a SyntaxError when `...` is
followed by `{` or `[` in a declaration context.

Signed-off-by: Seonghyun Kim <sh8281.kim@samsung.com>
This commit is contained in:
Seonghyun Kim 2026-06-18 11:58:58 +09:00 committed by Boram Bae
commit 181019c0c3
3 changed files with 9 additions and 3 deletions

View file

@ -81,6 +81,7 @@ public:
static constexpr const char* ParameterAfterRestParameter = "Rest parameter must be last formal parameter";
static constexpr const char* DefaultRestParameter = "Unexpected token =";
static constexpr const char* ObjectPatternAsRestParameter = "Unexpected token {";
static constexpr const char* RestElementMustBeFollowedByIdentifier = "`...` must be followed by an identifier in declaration contexts";
static constexpr const char* DuplicateProtoProperty = "Duplicate __proto__ fields are not allowed in object literals";
static constexpr const char* ConstructorSpecialMethod = "Class constructor may not be an accessor";
static constexpr const char* ConstructorGenerator = "Class constructor may not be a generator";

View file

@ -1351,10 +1351,15 @@ public:
}
template <class ASTBuilder>
ASTNode parseBindingRestElement(ASTBuilder& builder, SmallScannerResultVector& params, KeywordKind kind = KeywordKindEnd, bool isExplicitVariableDeclaration = false)
ASTNode parseBindingRestElement(ASTBuilder& builder, SmallScannerResultVector& params, KeywordKind kind = KeywordKindEnd, bool isExplicitVariableDeclaration = false, bool restrictToIdentifier = false)
{
MetaNode node = this->createNode();
this->nextToken();
// BindingRestProperty (object binding pattern rest) only accepts a BindingIdentifier,
// unlike BindingRestElement (array binding pattern rest) which also accepts a BindingPattern.
if (restrictToIdentifier && (this->match(LeftBrace) || this->match(LeftSquareBracket))) {
this->throwError(Messages::RestElementMustBeFollowedByIdentifier);
}
ASTNode arg = this->parsePattern(builder, params, kind, isExplicitVariableDeclaration);
return this->finalize(node, builder.createRestElementNode(arg));
}
@ -1459,7 +1464,7 @@ public:
while (!this->match(RightBrace)) {
if (this->match(PeriodPeriodPeriod)) {
hasRestElement = true;
properties.append(this->allocator, this->parseBindingRestElement(builder, params, kind, isExplicitVariableDeclaration));
properties.append(this->allocator, this->parseBindingRestElement(builder, params, kind, isExplicitVariableDeclaration, true));
break;
} else {
properties.append(this->allocator, this->parsePropertyPattern(builder, params, kind, isExplicitVariableDeclaration));

@ -1 +1 @@
Subproject commit 8cce9e0598052a8b6b3766f1100b3c1ef01fa093
Subproject commit 6a5e25ea0a0fa51f56e14217dcfb277ebad3d876