Commit 2e052332 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[parser] Cleanup pattern classification

This changes the split from AssignmentPattern and BindingPattern to Pattern and
BindingPattern. Pattern collects all errors that are invalid in both assignment
and binding pattern contexts. Binding pattern additionally collects errors for
binding pattern contexts (property access isn't a valid target). The
distinction is piggybacked on to distinguish assignment vs binding pattern
errors since binding pattern verification will first throw the binding pattern
error.

Since we don't throw pattern error as binding pattern as well, this can mean
that a later binding pattern syntax error will show up before an early pattern
error. Since that just changes the message to another syntax violation, I think
that's fine.

Change-Id: Ib6a22c8d11c49eacc6667ae8ee5e98bababadd43
Reviewed-on: https://chromium-review.googlesource.com/c/1349273Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57774}
parent f69dd4bf
...@@ -379,6 +379,7 @@ namespace internal { ...@@ -379,6 +379,7 @@ namespace internal {
T(IntrinsicWithSpread, "Intrinsic calls do not support spread arguments") \ T(IntrinsicWithSpread, "Intrinsic calls do not support spread arguments") \
T(InvalidRestBindingPattern, \ T(InvalidRestBindingPattern, \
"`...` must be followed by an identifier in declaration contexts") \ "`...` must be followed by an identifier in declaration contexts") \
T(InvalidPropertyBindingPattern, "Illegal property in declaration context") \
T(InvalidRestAssignmentPattern, \ T(InvalidRestAssignmentPattern, \
"`...` must be followed by an assignable reference in assignment " \ "`...` must be followed by an assignable reference in assignment " \
"contexts") \ "contexts") \
......
...@@ -20,8 +20,8 @@ class ZoneList; ...@@ -20,8 +20,8 @@ class ZoneList;
#define ERROR_CODES(T) \ #define ERROR_CODES(T) \
T(ExpressionProduction, 0) \ T(ExpressionProduction, 0) \
T(FormalParameterInitializerProduction, 1) \ T(FormalParameterInitializerProduction, 1) \
T(BindingPatternProduction, 2) \ T(PatternProduction, 2) \
T(AssignmentPatternProduction, 3) \ T(BindingPatternProduction, 3) \
T(StrictModeFormalParametersProduction, 4) \ T(StrictModeFormalParametersProduction, 4) \
T(LetPatternProduction, 5) \ T(LetPatternProduction, 5) \
T(AsyncArrowFormalParametersProduction, 6) T(AsyncArrowFormalParametersProduction, 6)
...@@ -136,12 +136,12 @@ class ExpressionClassifierBase { ...@@ -136,12 +136,12 @@ class ExpressionClassifierBase {
return is_valid(FormalParameterInitializerProduction); return is_valid(FormalParameterInitializerProduction);
} }
V8_INLINE bool is_valid_binding_pattern() const { V8_INLINE bool is_valid_pattern() const {
return is_valid(BindingPatternProduction); return is_valid(PatternProduction);
} }
V8_INLINE bool is_valid_assignment_pattern() const { V8_INLINE bool is_valid_binding_pattern() const {
return is_valid(AssignmentPatternProduction); return is_valid(BindingPatternProduction);
} }
// Note: callers should also check // Note: callers should also check
...@@ -374,12 +374,12 @@ class ExpressionClassifier ...@@ -374,12 +374,12 @@ class ExpressionClassifier
ErrorKind::kFormalParameterInitializerProduction); ErrorKind::kFormalParameterInitializerProduction);
} }
V8_INLINE const Error& binding_pattern_error() const { V8_INLINE const Error& pattern_error() const {
return this->reported_error(ErrorKind::kBindingPatternProduction); return this->reported_error(ErrorKind::kPatternProduction);
} }
V8_INLINE const Error& assignment_pattern_error() const { V8_INLINE const Error& binding_pattern_error() const {
return this->reported_error(ErrorKind::kAssignmentPatternProduction); return this->reported_error(ErrorKind::kBindingPatternProduction);
} }
V8_INLINE const Error& strict_mode_formal_parameter_error() const { V8_INLINE const Error& strict_mode_formal_parameter_error() const {
...@@ -413,6 +413,12 @@ class ExpressionClassifier ...@@ -413,6 +413,12 @@ class ExpressionClassifier
ErrorKind::kFormalParameterInitializerProduction, arg)); ErrorKind::kFormalParameterInitializerProduction, arg));
} }
void RecordPatternError(const Scanner::Location& loc, MessageTemplate message,
const char* arg = nullptr) {
this->Add(TP::PatternProduction,
Error(loc, message, ErrorKind::kPatternProduction, arg));
}
void RecordBindingPatternError(const Scanner::Location& loc, void RecordBindingPatternError(const Scanner::Location& loc,
MessageTemplate message, MessageTemplate message,
const char* arg = nullptr) { const char* arg = nullptr) {
...@@ -420,20 +426,6 @@ class ExpressionClassifier ...@@ -420,20 +426,6 @@ class ExpressionClassifier
Error(loc, message, ErrorKind::kBindingPatternProduction, arg)); Error(loc, message, ErrorKind::kBindingPatternProduction, arg));
} }
void RecordAssignmentPatternError(const Scanner::Location& loc,
MessageTemplate message,
const char* arg = nullptr) {
this->Add(
TP::AssignmentPatternProduction,
Error(loc, message, ErrorKind::kAssignmentPatternProduction, arg));
}
void RecordPatternError(const Scanner::Location& loc, MessageTemplate message,
const char* arg = nullptr) {
RecordBindingPatternError(loc, message, arg);
RecordAssignmentPatternError(loc, message, arg);
}
void RecordAsyncArrowFormalParametersError(const Scanner::Location& loc, void RecordAsyncArrowFormalParametersError(const Scanner::Location& loc,
MessageTemplate message, MessageTemplate message,
const char* arg = nullptr) { const char* arg = nullptr) {
......
...@@ -891,11 +891,12 @@ class ParserBase { ...@@ -891,11 +891,12 @@ class ParserBase {
if (!classifier()->is_valid_binding_pattern()) { if (!classifier()->is_valid_binding_pattern()) {
ReportClassifierError(classifier()->binding_pattern_error()); ReportClassifierError(classifier()->binding_pattern_error());
} }
ValidatePattern();
} }
void ValidateAssignmentPattern() { void ValidatePattern() {
if (!classifier()->is_valid_assignment_pattern()) { if (!classifier()->is_valid_pattern()) {
ReportClassifierError(classifier()->assignment_pattern_error()); ReportClassifierError(classifier()->pattern_error());
} }
} }
...@@ -934,12 +935,12 @@ class ParserBase { ...@@ -934,12 +935,12 @@ class ParserBase {
} }
} }
void BindingPatternUnexpectedToken() { void PatternUnexpectedToken() {
MessageTemplate message = MessageTemplate::kUnexpectedToken; MessageTemplate message = MessageTemplate::kUnexpectedToken;
const char* arg = nullptr; const char* arg = nullptr;
Scanner::Location location = scanner()->peek_location(); Scanner::Location location = scanner()->peek_location();
impl()->GetUnexpectedTokenMessage(peek(), &message, &location, &arg); impl()->GetUnexpectedTokenMessage(peek(), &message, &location, &arg);
classifier()->RecordBindingPatternError(location, message, arg); classifier()->RecordPatternError(location, message, arg);
} }
// Parses an identifier that is valid for the current scope, in particular it // Parses an identifier that is valid for the current scope, in particular it
...@@ -1449,7 +1450,7 @@ typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParseIdentifier( ...@@ -1449,7 +1450,7 @@ typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParseIdentifier(
auto result = ParseAndClassifyIdentifier(); auto result = ParseAndClassifyIdentifier();
if (allow_restricted_identifiers == kDontAllowRestrictedIdentifiers) { if (allow_restricted_identifiers == kDontAllowRestrictedIdentifiers) {
ValidateBindingPattern(); ValidatePattern();
} }
return result; return result;
...@@ -1478,8 +1479,8 @@ ParserBase<Impl>::ParseAndClassifyIdentifier() { ...@@ -1478,8 +1479,8 @@ ParserBase<Impl>::ParseAndClassifyIdentifier() {
classifier()->RecordStrictModeFormalParameterError( classifier()->RecordStrictModeFormalParameterError(
scanner()->location(), MessageTemplate::kStrictEvalArguments); scanner()->location(), MessageTemplate::kStrictEvalArguments);
if (is_strict(language_mode())) { if (is_strict(language_mode())) {
classifier()->RecordBindingPatternError( classifier()->RecordPatternError(scanner()->location(),
scanner()->location(), MessageTemplate::kStrictEvalArguments); MessageTemplate::kStrictEvalArguments);
} }
} }
...@@ -1644,7 +1645,7 @@ ParserBase<Impl>::ParsePrimaryExpression() { ...@@ -1644,7 +1645,7 @@ ParserBase<Impl>::ParsePrimaryExpression() {
if (V8_UNLIKELY(impl()->IsAsync(name) && if (V8_UNLIKELY(impl()->IsAsync(name) &&
!scanner()->HasLineTerminatorBeforeNext())) { !scanner()->HasLineTerminatorBeforeNext())) {
if (peek() == Token::FUNCTION) { if (peek() == Token::FUNCTION) {
BindingPatternUnexpectedToken(); PatternUnexpectedToken();
return ParseAsyncFunctionLiteral(); return ParseAsyncFunctionLiteral();
} }
// async Identifier => AsyncConciseBody // async Identifier => AsyncConciseBody
...@@ -1666,21 +1667,21 @@ ParserBase<Impl>::ParsePrimaryExpression() { ...@@ -1666,21 +1667,21 @@ ParserBase<Impl>::ParsePrimaryExpression() {
DCHECK_IMPLIES(Token::IsAnyIdentifier(token), token == Token::ENUM); DCHECK_IMPLIES(Token::IsAnyIdentifier(token), token == Token::ENUM);
if (Token::IsLiteral(token)) { if (Token::IsLiteral(token)) {
BindingPatternUnexpectedToken(); PatternUnexpectedToken();
return impl()->ExpressionFromLiteral(Next(), beg_pos); return impl()->ExpressionFromLiteral(Next(), beg_pos);
} }
switch (token) { switch (token) {
case Token::THIS: { case Token::THIS: {
BindingPatternUnexpectedToken(); PatternUnexpectedToken();
Consume(Token::THIS); Consume(Token::THIS);
return impl()->ThisExpression(beg_pos); return impl()->ThisExpression(beg_pos);
} }
case Token::ASSIGN_DIV: case Token::ASSIGN_DIV:
case Token::DIV: case Token::DIV:
classifier()->RecordBindingPatternError( classifier()->RecordPatternError(scanner()->peek_location(),
scanner()->peek_location(), MessageTemplate::kUnexpectedTokenRegExp); MessageTemplate::kUnexpectedTokenRegExp);
return ParseRegExpLiteral(); return ParseRegExpLiteral();
case Token::LBRACK: case Token::LBRACK:
...@@ -1718,7 +1719,7 @@ ParserBase<Impl>::ParsePrimaryExpression() { ...@@ -1718,7 +1719,7 @@ ParserBase<Impl>::ParsePrimaryExpression() {
} }
case Token::CLASS: { case Token::CLASS: {
BindingPatternUnexpectedToken(); PatternUnexpectedToken();
Consume(Token::CLASS); Consume(Token::CLASS);
int class_token_pos = position(); int class_token_pos = position();
IdentifierT name = impl()->NullIdentifier(); IdentifierT name = impl()->NullIdentifier();
...@@ -1740,12 +1741,12 @@ ParserBase<Impl>::ParsePrimaryExpression() { ...@@ -1740,12 +1741,12 @@ ParserBase<Impl>::ParsePrimaryExpression() {
case Token::TEMPLATE_SPAN: case Token::TEMPLATE_SPAN:
case Token::TEMPLATE_TAIL: case Token::TEMPLATE_TAIL:
BindingPatternUnexpectedToken(); PatternUnexpectedToken();
return ParseTemplateLiteral(impl()->NullExpression(), beg_pos, false); return ParseTemplateLiteral(impl()->NullExpression(), beg_pos, false);
case Token::MOD: case Token::MOD:
if (allow_natives() || extension_ != nullptr) { if (allow_natives() || extension_ != nullptr) {
BindingPatternUnexpectedToken(); PatternUnexpectedToken();
return ParseV8Intrinsic(); return ParseV8Intrinsic();
} }
break; break;
...@@ -1856,6 +1857,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral() { ...@@ -1856,6 +1857,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral() {
Consume(Token::LBRACK); Consume(Token::LBRACK);
while (!Check(Token::RBRACK)) { while (!Check(Token::RBRACK)) {
ExpressionT elem; ExpressionT elem;
ExpressionClassifier destructuring_classifier(this);
if (peek() == Token::COMMA) { if (peek() == Token::COMMA) {
elem = factory()->NewTheHoleLiteral(); elem = factory()->NewTheHoleLiteral();
} else if (Check(Token::ELLIPSIS)) { } else if (Check(Token::ELLIPSIS)) {
...@@ -1870,6 +1872,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral() { ...@@ -1870,6 +1872,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral() {
} }
if (argument->IsAssignment()) { if (argument->IsAssignment()) {
Accumulate(ExpressionClassifier::AllProductions);
classifier()->RecordPatternError( classifier()->RecordPatternError(
Scanner::Location(start_pos, end_position()), Scanner::Location(start_pos, end_position()),
MessageTemplate::kInvalidDestructuringTarget); MessageTemplate::kInvalidDestructuringTarget);
...@@ -2042,19 +2045,27 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName( ...@@ -2042,19 +2045,27 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
*name = impl()->NullIdentifier(); *name = impl()->NullIdentifier();
Consume(Token::ELLIPSIS); Consume(Token::ELLIPSIS);
AcceptINScope scope(this, true); AcceptINScope scope(this, true);
ExpressionClassifier destructuring_classifier(this);
ExpressionT expression = ParseAssignmentExpression(); ExpressionT expression = ParseAssignmentExpression();
*kind = ParsePropertyKind::kSpread; *kind = ParsePropertyKind::kSpread;
if (!impl()->IsIdentifier(expression)) { if (IsValidReferenceExpression(expression)) {
classifier()->RecordBindingPatternError( Accumulate(~ExpressionClassifier::PatternProduction);
scanner()->location(), if (expression->IsProperty()) {
MessageTemplate::kInvalidRestBindingPattern); classifier()->RecordBindingPatternError(
} Scanner::Location(expression->position(), end_position()),
MessageTemplate::kInvalidPropertyBindingPattern);
if (!expression->IsValidReferenceExpression()) { }
classifier()->RecordAssignmentPatternError( } else {
scanner()->location(), Accumulate(ExpressionClassifier::AllProductions);
MessageTemplate::kInvalidRestAssignmentPattern); if (expression->IsValidPattern()) {
classifier()->RecordBindingPatternError(
Scanner::Location(expression->position(), end_position()),
MessageTemplate::kInvalidRestBindingPattern);
classifier()->RecordPatternError(
Scanner::Location(expression->position(), end_position()),
MessageTemplate::kInvalidRestAssignmentPattern);
}
} }
if (peek() != Token::RBRACE) { if (peek() != Token::RBRACE) {
...@@ -2304,8 +2315,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(bool* has_seen_proto, ...@@ -2304,8 +2315,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(bool* has_seen_proto,
IdentifierT name = impl()->NullIdentifier(); IdentifierT name = impl()->NullIdentifier();
Token::Value name_token = peek(); Token::Value name_token = peek();
int next_beg_pos = peek_position(); Scanner::Location next_loc = scanner()->peek_location();
int next_end_pos = peek_end_position();
bool is_private = false; bool is_private = false;
ExpressionT name_expression = ParsePropertyName( ExpressionT name_expression = ParsePropertyName(
...@@ -2338,6 +2348,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(bool* has_seen_proto, ...@@ -2338,6 +2348,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(bool* has_seen_proto,
Consume(Token::COLON); Consume(Token::COLON);
int beg_pos = peek_position(); int beg_pos = peek_position();
AcceptINScope scope(this, true); AcceptINScope scope(this, true);
ExpressionClassifier destructuring_classifier(this);
ExpressionT value = ParseAssignmentExpression(); ExpressionT value = ParseAssignmentExpression();
CheckDestructuringElement(value, beg_pos, end_position()); CheckDestructuringElement(value, beg_pos, end_position());
...@@ -2368,8 +2379,8 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(bool* has_seen_proto, ...@@ -2368,8 +2379,8 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(bool* has_seen_proto,
DCHECK(!*is_computed_name); DCHECK(!*is_computed_name);
if (impl()->IsEvalOrArguments(name) && is_strict(language_mode())) { if (impl()->IsEvalOrArguments(name) && is_strict(language_mode())) {
classifier()->RecordBindingPatternError( classifier()->RecordPatternError(scanner()->location(),
scanner()->location(), MessageTemplate::kStrictEvalArguments); MessageTemplate::kStrictEvalArguments);
} }
if (name_token == Token::LET) { if (name_token == Token::LET) {
...@@ -2379,11 +2390,14 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(bool* has_seen_proto, ...@@ -2379,11 +2390,14 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(bool* has_seen_proto,
if (name_token == Token::AWAIT) { if (name_token == Token::AWAIT) {
DCHECK(!is_async_function()); DCHECK(!is_async_function());
classifier()->RecordAsyncArrowFormalParametersError( classifier()->RecordAsyncArrowFormalParametersError(
Scanner::Location(next_beg_pos, next_end_pos), next_loc, MessageTemplate::kAwaitBindingIdentifier);
MessageTemplate::kAwaitBindingIdentifier); }
ExpressionT lhs =
impl()->ExpressionFromIdentifier(name, next_loc.beg_pos);
if (!IsAssignableIdentifier(lhs)) {
classifier()->RecordPatternError(
next_loc, MessageTemplate::kInvalidDestructuringTarget);
} }
ExpressionT lhs = impl()->ExpressionFromIdentifier(name, next_beg_pos);
CheckDestructuringElement(lhs, next_beg_pos, next_end_pos);
ExpressionT value; ExpressionT value;
if (peek() == Token::ASSIGN) { if (peek() == Token::ASSIGN) {
...@@ -2396,7 +2410,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(bool* has_seen_proto, ...@@ -2396,7 +2410,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(bool* has_seen_proto,
value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs, value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs,
kNoSourcePosition); kNoSourcePosition);
classifier()->RecordExpressionError( classifier()->RecordExpressionError(
Scanner::Location(next_beg_pos, end_position()), Scanner::Location(next_loc.beg_pos, end_position()),
MessageTemplate::kInvalidCoverInitializedName); MessageTemplate::kInvalidCoverInitializedName);
impl()->SetFunctionNameFromIdentifierRef(rhs, lhs); impl()->SetFunctionNameFromIdentifierRef(rhs, lhs);
...@@ -2416,14 +2430,14 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(bool* has_seen_proto, ...@@ -2416,14 +2430,14 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(bool* has_seen_proto,
// '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
classifier()->RecordPatternError( classifier()->RecordPatternError(
Scanner::Location(next_beg_pos, end_position()), Scanner::Location(next_loc.beg_pos, end_position()),
MessageTemplate::kInvalidDestructuringTarget); MessageTemplate::kInvalidDestructuringTarget);
FunctionKind kind = MethodKindFor(function_flags); FunctionKind kind = MethodKindFor(function_flags);
ExpressionT value = impl()->ParseFunctionLiteral( ExpressionT value = impl()->ParseFunctionLiteral(
name, scanner()->location(), kSkipFunctionNameCheck, kind, name, scanner()->location(), kSkipFunctionNameCheck, kind,
next_beg_pos, FunctionLiteral::kAccessorOrMethod, language_mode(), next_loc.beg_pos, FunctionLiteral::kAccessorOrMethod, language_mode(),
nullptr); nullptr);
ObjectLiteralPropertyT result = factory()->NewObjectLiteralProperty( ObjectLiteralPropertyT result = factory()->NewObjectLiteralProperty(
...@@ -2439,7 +2453,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(bool* has_seen_proto, ...@@ -2439,7 +2453,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(bool* has_seen_proto,
bool is_get = kind == ParsePropertyKind::kAccessorGetter; bool is_get = kind == ParsePropertyKind::kAccessorGetter;
classifier()->RecordPatternError( classifier()->RecordPatternError(
Scanner::Location(next_beg_pos, end_position()), Scanner::Location(next_loc.beg_pos, end_position()),
MessageTemplate::kInvalidDestructuringTarget); MessageTemplate::kInvalidDestructuringTarget);
if (!*is_computed_name) { if (!*is_computed_name) {
...@@ -2455,7 +2469,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(bool* has_seen_proto, ...@@ -2455,7 +2469,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(bool* has_seen_proto,
FunctionLiteralT value = impl()->ParseFunctionLiteral( FunctionLiteralT value = impl()->ParseFunctionLiteral(
name, scanner()->location(), kSkipFunctionNameCheck, kind, name, scanner()->location(), kSkipFunctionNameCheck, kind,
next_beg_pos, FunctionLiteral::kAccessorOrMethod, language_mode(), next_loc.beg_pos, FunctionLiteral::kAccessorOrMethod, language_mode(),
nullptr); nullptr);
ObjectLiteralPropertyT result = factory()->NewObjectLiteralProperty( ObjectLiteralPropertyT result = factory()->NewObjectLiteralProperty(
...@@ -2620,15 +2634,7 @@ ParserBase<Impl>::ParseAssignmentExpression() { ...@@ -2620,15 +2634,7 @@ ParserBase<Impl>::ParseAssignmentExpression() {
Token::Value op = peek(); Token::Value op = peek();
if (!Token::IsArrowOrAssignmentOp(op)) { if (!Token::IsArrowOrAssignmentOp(op)) {
if (IsValidReferenceExpression(expression)) { Accumulate(ExpressionClassifier::AllProductions);
// Parenthesized identifiers and property references are allowed as part
// of a larger assignment pattern, even though parenthesized patterns
// themselves are not allowed, e.g., "[(x)] = []". Only accumulate
// assignment pattern errors if the parsed expression is more complex.
Accumulate(~ExpressionClassifier::AssignmentPatternProduction);
} else {
Accumulate(ExpressionClassifier::AllProductions);
}
return expression; return expression;
} }
...@@ -2676,7 +2682,7 @@ ParserBase<Impl>::ParseAssignmentExpression() { ...@@ -2676,7 +2682,7 @@ ParserBase<Impl>::ParseAssignmentExpression() {
// Destructuring assignmment. // Destructuring assignmment.
if (V8_UNLIKELY(expression->IsValidPattern() && op == Token::ASSIGN)) { if (V8_UNLIKELY(expression->IsValidPattern() && op == Token::ASSIGN)) {
ValidateAssignmentPattern(); ValidatePattern();
// This is definitely not an expression so don't accumulate // This is definitely not an expression so don't accumulate
// expression-related errors. // expression-related errors.
...@@ -2701,7 +2707,7 @@ ParserBase<Impl>::ParseAssignmentExpression() { ...@@ -2701,7 +2707,7 @@ ParserBase<Impl>::ParseAssignmentExpression() {
// This is definitely not an assignment pattern, so don't accumulate // This is definitely not an assignment pattern, so don't accumulate
// assignment pattern-related errors. // assignment pattern-related errors.
Accumulate(~ExpressionClassifier::AssignmentPatternProduction); Accumulate(~ExpressionClassifier::PatternProduction);
if (V8_UNLIKELY(!IsValidReferenceExpression(expression))) { if (V8_UNLIKELY(!IsValidReferenceExpression(expression))) {
expression = RewriteInvalidReferenceExpression( expression = RewriteInvalidReferenceExpression(
...@@ -2830,7 +2836,7 @@ typename ParserBase<Impl>::ExpressionT ...@@ -2830,7 +2836,7 @@ typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseConditionalContinuation(ExpressionT expression, ParserBase<Impl>::ParseConditionalContinuation(ExpressionT expression,
int pos) { int pos) {
SourceRange then_range, else_range; SourceRange then_range, else_range;
BindingPatternUnexpectedToken(); PatternUnexpectedToken();
ExpressionT left; ExpressionT left;
{ {
...@@ -2857,7 +2863,7 @@ ParserBase<Impl>::ParseConditionalContinuation(ExpressionT expression, ...@@ -2857,7 +2863,7 @@ ParserBase<Impl>::ParseConditionalContinuation(ExpressionT expression,
template <typename Impl> template <typename Impl>
typename ParserBase<Impl>::ExpressionT typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseBinaryContinuation(ExpressionT x, int prec, int prec1) { ParserBase<Impl>::ParseBinaryContinuation(ExpressionT x, int prec, int prec1) {
BindingPatternUnexpectedToken(); PatternUnexpectedToken();
do { do {
// prec1 >= 4 // prec1 >= 4
while (Token::Precedence(peek(), accept_IN_) == prec1) { while (Token::Precedence(peek(), accept_IN_) == prec1) {
...@@ -2922,7 +2928,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression( ...@@ -2922,7 +2928,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
template <typename Impl> template <typename Impl>
typename ParserBase<Impl>::ExpressionT typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseUnaryOpExpression() { ParserBase<Impl>::ParseUnaryOpExpression() {
BindingPatternUnexpectedToken(); PatternUnexpectedToken();
Token::Value op = Next(); Token::Value op = Next();
int pos = position(); int pos = position();
...@@ -2961,7 +2967,7 @@ ParserBase<Impl>::ParseUnaryOpExpression() { ...@@ -2961,7 +2967,7 @@ ParserBase<Impl>::ParseUnaryOpExpression() {
template <typename Impl> template <typename Impl>
typename ParserBase<Impl>::ExpressionT typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParsePrefixExpression() { ParserBase<Impl>::ParsePrefixExpression() {
BindingPatternUnexpectedToken(); PatternUnexpectedToken();
Token::Value op = Next(); Token::Value op = Next();
int beg_pos = peek_position(); int beg_pos = peek_position();
...@@ -2992,7 +2998,7 @@ ParserBase<Impl>::ParseAwaitExpression() { ...@@ -2992,7 +2998,7 @@ ParserBase<Impl>::ParseAwaitExpression() {
ExpressionT value = ParseUnaryExpression(); ExpressionT value = ParseUnaryExpression();
classifier()->RecordBindingPatternError( classifier()->RecordPatternError(
Scanner::Location(await_pos, end_position()), Scanner::Location(await_pos, end_position()),
MessageTemplate::kInvalidDestructuringTarget); MessageTemplate::kInvalidDestructuringTarget);
...@@ -3036,7 +3042,7 @@ ParserBase<Impl>::ParsePostfixExpression() { ...@@ -3036,7 +3042,7 @@ ParserBase<Impl>::ParsePostfixExpression() {
int lhs_beg_pos = peek_position(); int lhs_beg_pos = peek_position();
ExpressionT expression = ParseLeftHandSideExpression(); ExpressionT expression = ParseLeftHandSideExpression();
if (!scanner()->HasLineTerminatorBeforeNext() && Token::IsCountOp(peek())) { if (!scanner()->HasLineTerminatorBeforeNext() && Token::IsCountOp(peek())) {
BindingPatternUnexpectedToken(); PatternUnexpectedToken();
if (V8_UNLIKELY(!IsValidReferenceExpression(expression))) { if (V8_UNLIKELY(!IsValidReferenceExpression(expression))) {
expression = RewriteInvalidReferenceExpression( expression = RewriteInvalidReferenceExpression(
...@@ -3083,7 +3089,7 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) { ...@@ -3083,7 +3089,7 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {
ParseArguments(&args, &has_spread, true); ParseArguments(&args, &has_spread, true);
if (V8_LIKELY(peek() == Token::ARROW)) { if (V8_LIKELY(peek() == Token::ARROW)) {
fni_.RemoveAsyncKeywordFromEnd(); fni_.RemoveAsyncKeywordFromEnd();
ValidateBindingPattern(); ValidatePattern();
ValidateFormalParameterInitializer(); ValidateFormalParameterInitializer();
if (!classifier()->is_valid_async_arrow_formal_parameters()) { if (!classifier()->is_valid_async_arrow_formal_parameters()) {
ReportClassifierError( ReportClassifierError(
...@@ -3114,11 +3120,12 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) { ...@@ -3114,11 +3120,12 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {
fni_.RemoveLastFunction(); fni_.RemoveLastFunction();
if (!Token::IsPropertyOrCall(peek())) return result; if (!Token::IsPropertyOrCall(peek())) return result;
} else { } else {
BindingPatternUnexpectedToken(); PatternUnexpectedToken();
} }
do { do {
switch (peek()) { switch (peek()) {
/* Property */
case Token::LBRACK: { case Token::LBRACK: {
Consume(Token::LBRACK); Consume(Token::LBRACK);
int pos = position(); int pos = position();
...@@ -3129,6 +3136,16 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) { ...@@ -3129,6 +3136,16 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {
break; break;
} }
/* Property */
case Token::PERIOD: {
Consume(Token::PERIOD);
int pos = position();
ExpressionT key = ParseIdentifierNameOrPrivateName();
result = factory()->NewProperty(result, key, pos);
break;
}
/* Call */
case Token::LPAREN: { case Token::LPAREN: {
int pos; int pos;
if (Token::IsCallable(scanner()->current_token())) { if (Token::IsCallable(scanner()->current_token())) {
...@@ -3174,14 +3191,7 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) { ...@@ -3174,14 +3191,7 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {
break; break;
} }
case Token::PERIOD: { /* Call */
Consume(Token::PERIOD);
int pos = position();
ExpressionT key = ParseIdentifierNameOrPrivateName();
result = factory()->NewProperty(result, key, pos);
break;
}
default: default:
DCHECK(peek() == Token::TEMPLATE_SPAN || DCHECK(peek() == Token::TEMPLATE_SPAN ||
peek() == Token::TEMPLATE_TAIL); peek() == Token::TEMPLATE_TAIL);
...@@ -3214,7 +3224,7 @@ ParserBase<Impl>::ParseMemberWithPresentNewPrefixesExpression() { ...@@ -3214,7 +3224,7 @@ ParserBase<Impl>::ParseMemberWithPresentNewPrefixesExpression() {
// new new foo means new (new foo) // new new foo means new (new foo)
// new new foo() means new (new foo()) // new new foo() means new (new foo())
// new new foo().bar().baz means (new (new foo()).bar()).baz // new new foo().bar().baz means (new (new foo()).bar()).baz
BindingPatternUnexpectedToken(); PatternUnexpectedToken();
Consume(Token::NEW); Consume(Token::NEW);
int new_pos = position(); int new_pos = position();
ExpressionT result; ExpressionT result;
...@@ -3266,7 +3276,7 @@ ParserBase<Impl>::ParseMemberWithNewPrefixesExpression() { ...@@ -3266,7 +3276,7 @@ ParserBase<Impl>::ParseMemberWithNewPrefixesExpression() {
template <typename Impl> template <typename Impl>
typename ParserBase<Impl>::ExpressionT typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseFunctionExpression() { ParserBase<Impl>::ParseFunctionExpression() {
BindingPatternUnexpectedToken(); PatternUnexpectedToken();
Consume(Token::FUNCTION); Consume(Token::FUNCTION);
int function_token_position = position(); int function_token_position = position();
...@@ -3413,7 +3423,7 @@ ParserBase<Impl>::ParseNewTargetExpression() { ...@@ -3413,7 +3423,7 @@ ParserBase<Impl>::ParseNewTargetExpression() {
int pos = position(); int pos = position();
ExpectMetaProperty(ast_value_factory()->target_string(), "new.target", pos); ExpectMetaProperty(ast_value_factory()->target_string(), "new.target", pos);
classifier()->RecordAssignmentPatternError( classifier()->RecordPatternError(
Scanner::Location(pos, end_position()), Scanner::Location(pos, end_position()),
MessageTemplate::kInvalidDestructuringTarget); MessageTemplate::kInvalidDestructuringTarget);
...@@ -3430,7 +3440,7 @@ template <typename Impl> ...@@ -3430,7 +3440,7 @@ template <typename Impl>
typename ParserBase<Impl>::ExpressionT typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::DoParseMemberExpressionContinuation(ExpressionT expression) { ParserBase<Impl>::DoParseMemberExpressionContinuation(ExpressionT expression) {
DCHECK(Token::IsProperty(peek())); DCHECK(Token::IsProperty(peek()));
BindingPatternUnexpectedToken(); PatternUnexpectedToken();
// Parses this part of MemberExpression: // Parses this part of MemberExpression:
// ('[' Expression ']' | '.' Identifier | TemplateLiteral)* // ('[' Expression ']' | '.' Identifier | TemplateLiteral)*
do { do {
...@@ -4453,10 +4463,24 @@ bool ParserBase<Impl>::IsValidReferenceExpression(ExpressionT expression) { ...@@ -4453,10 +4463,24 @@ bool ParserBase<Impl>::IsValidReferenceExpression(ExpressionT expression) {
template <typename Impl> template <typename Impl>
void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression, void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression,
int begin, int end) { int begin, int end) {
if (!expression->IsValidPattern() && !expression->IsAssignment() && if (expression->IsProperty() || IsAssignableIdentifier(expression)) {
!IsValidReferenceExpression(expression)) { // Parenthesized identifiers and property references are allowed as part of
if (expression->IsProperty()) ValidateExpression(); // a larger assignment pattern, even though parenthesized patterns
classifier()->RecordAssignmentPatternError( // themselves are not allowed, e.g., "[(x)] = []". Only accumulate
// assignment pattern errors if the parsed expression is more complex.
Accumulate(~ExpressionClassifier::PatternProduction);
if (expression->IsProperty()) {
ValidateExpression();
classifier()->RecordBindingPatternError(
Scanner::Location(begin, end),
MessageTemplate::kInvalidPropertyBindingPattern);
}
return;
}
Accumulate(ExpressionClassifier::AllProductions);
if (!expression->IsValidPattern() && !expression->IsAssignment()) {
classifier()->RecordPatternError(
Scanner::Location(begin, end), Scanner::Location(begin, end),
MessageTemplate::kInvalidDestructuringTarget); MessageTemplate::kInvalidDestructuringTarget);
} }
...@@ -5406,7 +5430,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement( ...@@ -5406,7 +5430,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
bool is_destructuring = is_for_each && expression->IsValidPattern(); bool is_destructuring = is_for_each && expression->IsValidPattern();
if (is_destructuring) { if (is_destructuring) {
ValidateAssignmentPattern(); ValidatePattern();
} else { } else {
ValidateExpression(); ValidateExpression();
} }
...@@ -5741,7 +5765,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement( ...@@ -5741,7 +5765,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
int lhs_end_pos = end_position(); int lhs_end_pos = end_position();
if (lhs->IsValidPattern()) { if (lhs->IsValidPattern()) {
ValidateAssignmentPattern(); ValidatePattern();
} else { } else {
ValidateExpression(); ValidateExpression();
if (V8_UNLIKELY(!IsValidReferenceExpression(lhs))) { if (V8_UNLIKELY(!IsValidReferenceExpression(lhs))) {
......
*%(basename)s:5: SyntaxError: `...` must be followed by an assignable reference in assignment contexts *%(basename)s:5: SyntaxError: `...` must be followed by an assignable reference in assignment contexts
({...{}} = {}); ({...{}} = {});
^ ^^
SyntaxError: `...` must be followed by an assignable reference in assignment contexts SyntaxError: `...` must be followed by an assignable reference in assignment contexts
*%(basename)s:5: SyntaxError: `...` must be followed by an identifier in declaration contexts *%(basename)s:5: SyntaxError: `...` must be followed by an identifier in declaration contexts
let {...{}} = {}; let {...{}} = {};
^ ^^
SyntaxError: `...` must be followed by an identifier in declaration contexts SyntaxError: `...` must be followed by an identifier in declaration contexts
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment