Index: src/preparser.h |
diff --git a/src/preparser.h b/src/preparser.h |
index 34295c71f297bce5cdca1fc81aa80252298304e5..3a25790377e62ac27ed4426cac5c646071cfb8f6 100644 |
--- a/src/preparser.h |
+++ b/src/preparser.h |
@@ -570,7 +570,84 @@ class ParserBase : public Traits { |
bool HasError() const { return location.IsValid(); } |
}; |
- ExpressionClassifier() {} |
+ ExpressionClassifier() : lhs_type_(TARGET_NONE), assigned_(false) {} |
+ |
+ enum AssignmentTargetType { |
+ TARGET_NONE = 0, |
+ |
+ // IdentifierReference |
+ TARGET_IDENTIFIER, |
+ |
+ // MemberExpression . <property name> |
+ // MemberExpression [<property name>] |
+ TARGET_PROPERTY, |
+ |
+ // MemberExpression ( arguments ) |
+ // new MemberExpression ( arguments ) |
+ // MemberExpression TemplateLiteral |
+ TARGET_CALL, |
+ |
+ // this |
+ // Literal |
+ // ArrayLiteral |
+ // ObjectLiteral |
+ // FunctionExpression |
+ // ClassExpression |
+ // GeneratorExpression |
+ // RegularExpressionLiteral |
+ // TemplateLiteral |
+ // CoverParenthesizedExpressionAndArrowParameterList |
+ TARGET_PRIMARY, |
+ |
+ // new.target |
+ // yield (in generator) |
+ TARGET_RESTRICTED, |
+ |
+ // UnaryExpression |
+ // MultiplicativeExpression |
+ // AdditiveExpression |
+ // ShiftExpression |
+ // RelationalExpression |
+ // EqualityExpression |
+ // BitwiseANDExpression |
+ // BitwiseXORExpression |
+ // BitwiseORExpression |
+ // LogicalANDExpression |
+ // LogicalORExpression |
+ // ConditionalExpression |
+ // AssignmentExpression |
+ // ... Pretty much any binary operator |
+ UNACCEPTABLE_TARGET, |
+ |
+ // BindingPattern |
+ TARGET_PATTERN |
+ }; |
+ |
+ inline void AppendAssignmentTarget(AssignmentTargetType value) { |
arv (Not doing code reviews)
2015/06/04 20:08:03
s/value/type/
caitp (gmail)
2015/06/05 18:37:13
Done.
|
+ if (lhs_type_ == UNACCEPTABLE_TARGET) return; |
+ lhs_type_ = value; |
+ } |
+ |
+ inline void ReportInvalidSimpleAssignmentTarget() { |
+ lhs_type_ = UNACCEPTABLE_TARGET; |
+ } |
+ |
+ inline bool IsValidSimpleAssignmentTarget() const { |
+ // Only identifiers and properties are valid targets. |
+ return lhs_type_ >= TARGET_IDENTIFIER && lhs_type_ <= TARGET_PROPERTY; |
+ } |
+ |
+ inline bool IsPatternAssignmentElement() const { |
+ // Any AssignmentElement for which IsValidSimpleAssignmentTarget is false. |
+ // Used for nested AssignmentPatterns |
+ return lhs_type_ == TARGET_PATTERN && is_valid_assignment_pattern(); |
+ } |
+ |
+ void set_assigned() { assigned_ = true; } |
+ |
+ bool is_destructuring_assignment() const { |
+ return lhs_type_ == TARGET_PATTERN && assigned_; |
+ } |
bool is_valid_expression() const { return !expression_error_.HasError(); } |
@@ -707,6 +784,13 @@ class ParserBase : public Traits { |
ArrowFormalParametersProduction), |
}; |
+ void AccumulateValidSimpleAssignmentTarget( |
+ const ExpressionClassifier& inner) { |
+ if (lhs_type_ != UNACCEPTABLE_TARGET) { |
+ lhs_type_ = inner.lhs_type_; |
+ } |
+ } |
+ |
void Accumulate(const ExpressionClassifier& inner, |
unsigned productions = StandardProductions) { |
if (productions & ExpressionProduction && is_valid_expression()) { |
@@ -755,6 +839,8 @@ class ParserBase : public Traits { |
} |
private: |
+ AssignmentTargetType lhs_type_; |
+ bool assigned_; |
Error expression_error_; |
Error binding_pattern_error_; |
Error assignment_pattern_error_; |
@@ -764,6 +850,20 @@ class ParserBase : public Traits { |
Error strong_mode_formal_parameter_error_; |
}; |
+ ExpressionT CheckDestructuringAssignment(ExpressionT expr, |
+ ExpressionClassifier* classifier, |
+ bool* ok) { |
+ if (classifier->is_destructuring_assignment()) { |
+ if (!classifier->is_valid_assignment_pattern()) { |
+ this->ReportClassifierError(classifier->assignment_pattern_error()); |
+ *ok = false; |
+ return this->EmptyExpression(); |
+ } |
+ return Traits::RewriteDestructuringAssignment(expr); |
+ } |
+ return expr; |
+ } |
+ |
void ReportClassifierError( |
const typename ExpressionClassifier::Error& error) { |
Traits::ReportMessageAt(error.location, error.message, error.arg, |
@@ -885,9 +985,14 @@ class ParserBase : public Traits { |
typename Traits::Type::ExpressionList ParseArguments( |
Scanner::Location* first_spread_pos, ExpressionClassifier* classifier, |
bool* ok); |
- ExpressionT ParseAssignmentExpression(bool accept_IN, |
+ ExpressionT ParseAssignmentExpression(bool accept_IN, bool is_rhs, |
ExpressionClassifier* classifier, |
bool* ok); |
+ ExpressionT ParseAssignmentExpression(bool accept_IN, |
+ ExpressionClassifier* classifier, |
+ bool* ok) { |
+ return ParseAssignmentExpression(accept_IN, false, classifier, ok); |
+ } |
ExpressionT ParseYieldExpression(ExpressionClassifier* classifier, bool* ok); |
ExpressionT ParseConditionalExpression(bool accept_IN, |
ExpressionClassifier* classifier, |
@@ -1836,6 +1941,11 @@ class PreParserTraits { |
PreParserExpressionList args, |
int pos); |
+ inline PreParserExpression RewriteDestructuringAssignment( |
+ PreParserExpression expr) { |
+ return expr; |
+ } |
+ |
private: |
PreParser* pre_parser_; |
}; |
@@ -2313,6 +2423,8 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, |
int end_pos = scanner()->peek_location().end_pos; |
ExpressionT result = this->EmptyExpression(); |
Token::Value token = peek(); |
+ typename ExpressionClassifier::AssignmentTargetType lhs_part = |
+ ExpressionClassifier::TARGET_PRIMARY; |
switch (token) { |
case Token::THIS: { |
BindingPatternUnexpectedToken(classifier); |
@@ -2353,6 +2465,7 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, |
case Token::YIELD: |
case Token::FUTURE_STRICT_RESERVED_WORD: { |
// Using eval or arguments in this context is OK even in strict mode. |
+ lhs_part = ExpressionClassifier::TARGET_IDENTIFIER; |
IdentifierT name = ParseAndClassifyIdentifier(classifier, CHECK_OK); |
result = this->ExpressionFromIdentifier(name, beg_pos, end_pos, scope_, |
factory()); |
@@ -2416,8 +2529,15 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, |
// Heuristically try to detect immediately called functions before |
// seeing the call parentheses. |
parenthesized_function_ = (peek() == Token::FUNCTION); |
- result = this->ParseExpression(true, classifier, CHECK_OK); |
+ ExpressionClassifier expr_classifier; |
+ result = this->ParseExpression(true, &expr_classifier, CHECK_OK); |
Expect(Token::RPAREN, CHECK_OK); |
+ if (peek() == Token::ARROW || parenthesized_function_) { |
+ classifier->Accumulate( |
+ expr_classifier, |
+ ExpressionClassifier::ArrowFormalParametersProduction | |
+ ExpressionClassifier::FormalParametersProduction); |
+ } |
} |
break; |
@@ -2453,6 +2573,7 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, |
case Token::MOD: |
if (allow_natives() || extension_ != NULL) { |
result = this->ParseV8Intrinsic(CHECK_OK); |
+ lhs_part = ExpressionClassifier::TARGET_CALL; |
break; |
} |
// If we're not allowing special syntax we fall-through to the |
@@ -2465,6 +2586,10 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, |
} |
} |
+ if (*ok && lhs_part != ExpressionClassifier::TARGET_NONE) { |
+ classifier->AppendAssignmentTarget(lhs_part); |
+ } |
+ |
return result; |
} |
@@ -2490,15 +2615,27 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( |
ExpressionClassifier binding_classifier; |
arv (Not doing code reviews)
2015/06/04 20:08:03
rename this?
caitp (gmail)
2015/06/05 18:37:13
Done.
|
ExpressionT result = |
this->ParseAssignmentExpression(accept_IN, &binding_classifier, CHECK_OK); |
- classifier->Accumulate(binding_classifier, |
- ExpressionClassifier::AllProductions); |
+ if (binding_classifier.is_destructuring_assignment()) { |
+ classifier->Accumulate(binding_classifier, |
+ ExpressionClassifier::PatternProductions); |
+ } else { |
+ classifier->Accumulate(binding_classifier, |
+ ExpressionClassifier::AllProductions); |
+ } |
while (peek() == Token::COMMA) { |
Expect(Token::COMMA, CHECK_OK); |
int pos = position(); |
+ ExpressionClassifier binding_classifier; |
ExpressionT right = this->ParseAssignmentExpression( |
accept_IN, &binding_classifier, CHECK_OK); |
- classifier->Accumulate(binding_classifier, |
- ExpressionClassifier::AllProductions); |
+ if (binding_classifier.is_destructuring_assignment()) { |
+ classifier->Accumulate(binding_classifier, |
+ ExpressionClassifier::PatternProductions); |
+ } else { |
+ classifier->Accumulate(binding_classifier, |
+ ExpressionClassifier::AllProductions); |
+ } |
+ |
result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos); |
} |
return result; |
@@ -2518,6 +2655,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral( |
while (peek() != Token::RBRACK) { |
bool seen_spread = false; |
ExpressionT elem = this->EmptyExpression(); |
+ ExpressionClassifier element_classifier; |
if (peek() == Token::COMMA) { |
if (is_strong(language_mode())) { |
ReportMessageAt(scanner()->peek_location(), |
@@ -2537,7 +2675,16 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral( |
elem = factory()->NewSpread(argument, start_pos); |
seen_spread = true; |
} else { |
- elem = this->ParseAssignmentExpression(true, classifier, CHECK_OK); |
+ int start_pos = peek_position(); |
+ elem = |
+ this->ParseAssignmentExpression(true, &element_classifier, CHECK_OK); |
+ if (!element_classifier.IsValidSimpleAssignmentTarget() && |
+ !element_classifier.IsPatternAssignmentElement()) { |
+ Scanner::Location location(start_pos, scanner()->location().end_pos); |
+ classifier->RecordAssignmentPatternError( |
+ location, MessageTemplate::kInvalidDestructuringAssignmentTarget); |
+ } |
+ classifier->Accumulate(element_classifier); |
} |
values->Add(elem, zone_); |
if (peek() != Token::RBRACK) { |
@@ -2631,13 +2778,16 @@ ParserBase<Traits>::ParsePropertyDefinition( |
bool is_set = false; |
bool name_is_static = false; |
bool is_generator = allow_harmony_object_literals_ && Check(Token::MUL); |
- |
+ // Classify destructuring assignment target for ObjectAssignmentPattern |
+ ExpressionClassifier property_classifier; |
Token::Value name_token = peek(); |
int next_beg_pos = scanner()->peek_location().beg_pos; |
int next_end_pos = scanner()->peek_location().end_pos; |
+ int value_start = next_beg_pos; |
+ int value_end = next_end_pos; |
ExpressionT name_expression = ParsePropertyName( |
- &name, &is_get, &is_set, &name_is_static, is_computed_name, classifier, |
- CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
+ &name, &is_get, &is_set, &name_is_static, is_computed_name, |
+ &property_classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
if (fni_ != nullptr && !*is_computed_name) { |
this->PushLiteralName(fni_, name); |
@@ -2651,12 +2801,16 @@ ParserBase<Traits>::ParsePropertyDefinition( |
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
} |
Consume(Token::COLON); |
+ property_classifier = ExpressionClassifier(); |
+ value_start = peek_position(); |
value = this->ParseAssignmentExpression( |
- true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
- |
+ true, &property_classifier, |
+ CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
+ value_end = scanner()->location().end_pos; |
} else if (is_generator || |
(allow_harmony_object_literals_ && peek() == Token::LPAREN)) { |
// Concise Method |
+ property_classifier.ReportInvalidSimpleAssignmentTarget(); |
if (!*is_computed_name) { |
checker->CheckProperty(name_token, kMethodProperty, is_static, |
is_generator, |
@@ -2687,10 +2841,12 @@ ParserBase<Traits>::ParsePropertyDefinition( |
} else if (in_class && name_is_static && !is_static) { |
// static MethodDefinition |
+ property_classifier.ReportInvalidSimpleAssignmentTarget(); |
return ParsePropertyDefinition(checker, true, has_extends, true, |
is_computed_name, nullptr, classifier, ok); |
} else if (is_get || is_set) { |
// Accessor |
+ property_classifier.ReportInvalidSimpleAssignmentTarget(); |
name = this->EmptyIdentifier(); |
bool dont_care = false; |
name_token = peek(); |
@@ -2722,6 +2878,11 @@ ParserBase<Traits>::ParsePropertyDefinition( |
factory()->NewStringLiteral(name, name_expression->position()); |
} |
+ value_end = scanner()->location().end_pos; |
+ Scanner::Location location(value_start, value_end); |
+ classifier->RecordAssignmentPatternError( |
+ location, MessageTemplate::kInvalidDestructuringAssignmentTarget); |
+ |
return factory()->NewObjectLiteralProperty( |
name_expression, value, |
is_get ? ObjectLiteralProperty::GETTER : ObjectLiteralProperty::SETTER, |
@@ -2740,7 +2901,8 @@ ParserBase<Traits>::ParsePropertyDefinition( |
Consume(Token::ASSIGN); |
ExpressionClassifier rhs_classifier; |
ExpressionT rhs = this->ParseAssignmentExpression( |
- true, &rhs_classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
+ true, true, &rhs_classifier, |
+ CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
classifier->AccumulateReclassifyingAsPattern(rhs_classifier); |
value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs, |
RelocInfo::kNoPosition); |
@@ -2757,6 +2919,14 @@ ParserBase<Traits>::ParsePropertyDefinition( |
return this->EmptyObjectLiteralProperty(); |
} |
+ if (!property_classifier.IsValidSimpleAssignmentTarget() && |
+ !property_classifier.IsPatternAssignmentElement()) { |
+ Scanner::Location location(value_start, value_end); |
+ classifier->RecordAssignmentPatternError( |
+ location, MessageTemplate::kInvalidDestructuringAssignmentTarget); |
+ } |
+ classifier->Accumulate(property_classifier); |
+ |
return factory()->NewObjectLiteralProperty(name_expression, value, is_static, |
*is_computed_name); |
} |
@@ -2899,7 +3069,7 @@ typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments( |
// Precedence = 2 |
template <class Traits> |
typename ParserBase<Traits>::ExpressionT |
-ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
+ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool is_rhs, |
arv (Not doing code reviews)
2015/06/04 20:08:03
TODO: Maybe add enums for this and accept_IN?
caitp (gmail)
2015/06/05 18:37:13
Done.
|
ExpressionClassifier* classifier, |
bool* ok) { |
// AssignmentExpression :: |
@@ -2914,6 +3084,11 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
return this->ParseYieldExpression(classifier, ok); |
} |
+ bool maybeAssignmentPattern = |
arv (Not doing code reviews)
2015/06/04 20:08:03
maybe_assignment_pattern
caitp (gmail)
2015/06/05 18:37:13
Done.
|
+ allow_harmony_destructuring() && !is_rhs && |
arv (Not doing code reviews)
2015/06/04 20:08:04
maybe rename is_rhs to is_lhs?
caitp (gmail)
2015/06/05 18:37:13
renamed to `pattern_lhs` in a previous patch
|
+ classifier->is_valid_assignment_pattern() && |
+ (peek() == Token::LBRACK || peek() == Token::LBRACE); |
+ |
if (fni_ != NULL) fni_->Enter(); |
ParserBase<Traits>::Checkpoint checkpoint(this); |
ExpressionClassifier arrow_formals_classifier; |
@@ -2922,13 +3097,26 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
// formal parameter list. |
ArrowFormalParametersUnexpectedToken(&arrow_formals_classifier); |
} |
+ |
ExpressionT expression = this->ParseConditionalExpression( |
accept_IN, &arrow_formals_classifier, CHECK_OK); |
+ |
+ if (!arrow_formals_classifier.is_valid_assignment_pattern()) { |
+ if (maybeAssignmentPattern && peek() == Token::ASSIGN) { |
+ // ObjectAssignmentPattern or ArrayAssignmentPattern contains an error |
+ ReportClassifierError( |
+ arrow_formals_classifier.assignment_pattern_error()); |
+ *ok = false; |
+ return this->EmptyExpression(); |
+ } |
+ } |
+ |
classifier->Accumulate(arrow_formals_classifier); |
if (allow_harmony_arrow_functions() && peek() == Token::ARROW) { |
checkpoint.Restore(); |
BindingPatternUnexpectedToken(classifier); |
+ classifier->AppendAssignmentTarget(ExpressionClassifier::TARGET_PRIMARY); |
ValidateArrowFormalParameters(&arrow_formals_classifier, expression, |
CHECK_OK); |
Scanner::Location loc(lhs_location.beg_pos, scanner()->location().end_pos); |
@@ -2953,6 +3141,22 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
classifier->Accumulate(arrow_formals_classifier, |
ExpressionClassifier::FormalParametersProduction); |
+ bool validDestructuringAssignmentTarget = |
arv (Not doing code reviews)
2015/06/04 20:08:04
s/validDestructuringAssignmentTarget/valid_destruc
caitp (gmail)
2015/06/05 18:37:13
Done.
|
+ arrow_formals_classifier.IsValidSimpleAssignmentTarget(); |
+ if (validDestructuringAssignmentTarget) { |
+ classifier->AccumulateValidSimpleAssignmentTarget(arrow_formals_classifier); |
+ } else if (!maybeAssignmentPattern || |
+ !arrow_formals_classifier.is_valid_assignment_pattern()) { |
+ // Potentially a bad DestructuringAssignmentTarget |
+ classifier->RecordAssignmentPatternError( |
+ Scanner::Location(lhs_location.beg_pos, scanner()->location().end_pos), |
+ MessageTemplate::kInvalidDestructuringAssignmentTarget); |
+ } |
+ |
+ if (maybeAssignmentPattern) { |
+ classifier->AppendAssignmentTarget(ExpressionClassifier::TARGET_PATTERN); |
+ } |
+ |
if (!Token::IsAssignmentOp(peek())) { |
if (fni_ != NULL) fni_->Leave(); |
// Parsed conditional expression only (no assignment). |
@@ -2963,9 +3167,12 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
BindingPatternUnexpectedToken(classifier); |
} |
- expression = this->CheckAndRewriteReferenceExpression( |
- expression, lhs_location, MessageTemplate::kInvalidLhsInAssignment, |
- CHECK_OK); |
+ if (!maybeAssignmentPattern || peek() != Token::ASSIGN) { |
+ expression = this->CheckAndRewriteReferenceExpression( |
+ expression, lhs_location, MessageTemplate::kInvalidLhsInAssignment, |
+ CHECK_OK); |
+ } |
+ |
expression = this->MarkExpressionAsAssigned(expression); |
Token::Value op = Next(); // Get assignment operator. |
@@ -2973,6 +3180,8 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
classifier->RecordBindingPatternError(scanner()->location(), |
MessageTemplate::kUnexpectedToken, |
Token::String(op)); |
+ } else { |
+ classifier->set_assigned(); |
} |
int pos = position(); |
@@ -3007,7 +3216,8 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
fni_->Leave(); |
} |
- return factory()->NewAssignment(op, expression, right, pos); |
+ ExpressionT result = factory()->NewAssignment(op, expression, right, pos); |
+ return this->CheckDestructuringAssignment(result, classifier, CHECK_OK); |
} |
template <class Traits> |
@@ -3074,6 +3284,7 @@ ParserBase<Traits>::ParseConditionalExpression(bool accept_IN, |
this->ParseBinaryExpression(4, accept_IN, classifier, CHECK_OK); |
if (peek() != Token::CONDITIONAL) return expression; |
BindingPatternUnexpectedToken(classifier); |
+ classifier->ReportInvalidSimpleAssignmentTarget(); |
Consume(Token::CONDITIONAL); |
// In parsing the first assignment expression in conditional |
// expressions we always accept the 'in' keyword; see ECMA-262, |
@@ -3098,6 +3309,7 @@ ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN, |
// prec1 >= 4 |
while (Precedence(peek(), accept_IN) == prec1) { |
BindingPatternUnexpectedToken(classifier); |
+ classifier->ReportInvalidSimpleAssignmentTarget(); |
Token::Value op = Next(); |
Scanner::Location op_location = scanner()->location(); |
int pos = position(); |
@@ -3160,7 +3372,7 @@ ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier, |
Token::Value op = peek(); |
if (Token::IsUnaryOp(op)) { |
BindingPatternUnexpectedToken(classifier); |
- |
+ classifier->ReportInvalidSimpleAssignmentTarget(); |
op = Next(); |
int pos = position(); |
ExpressionT expression = ParseUnaryExpression(classifier, CHECK_OK); |
@@ -3182,6 +3394,7 @@ ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier, |
return this->BuildUnaryExpression(expression, op, pos, factory()); |
} else if (Token::IsCountOp(op)) { |
BindingPatternUnexpectedToken(classifier); |
+ classifier->ReportInvalidSimpleAssignmentTarget(); |
op = Next(); |
Scanner::Location lhs_location = scanner()->peek_location(); |
ExpressionT expression = this->ParseUnaryExpression(classifier, CHECK_OK); |
@@ -3214,7 +3427,7 @@ ParserBase<Traits>::ParsePostfixExpression(ExpressionClassifier* classifier, |
if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
Token::IsCountOp(peek())) { |
BindingPatternUnexpectedToken(classifier); |
- |
+ classifier->ReportInvalidSimpleAssignmentTarget(); |
expression = this->CheckAndRewriteReferenceExpression( |
expression, lhs_location, MessageTemplate::kInvalidLhsInPostfixOp, |
CHECK_OK); |
@@ -3245,6 +3458,8 @@ ParserBase<Traits>::ParseLeftHandSideExpression( |
switch (peek()) { |
case Token::LBRACK: { |
BindingPatternUnexpectedToken(classifier); |
+ classifier->AppendAssignmentTarget( |
+ ExpressionClassifier::TARGET_PROPERTY); |
Consume(Token::LBRACK); |
int pos = position(); |
ExpressionT index = ParseExpression(true, classifier, CHECK_OK); |
@@ -3255,7 +3470,7 @@ ParserBase<Traits>::ParseLeftHandSideExpression( |
case Token::LPAREN: { |
BindingPatternUnexpectedToken(classifier); |
- |
+ classifier->AppendAssignmentTarget(ExpressionClassifier::TARGET_CALL); |
if (is_strong(language_mode()) && this->IsIdentifier(result) && |
this->IsEval(this->AsIdentifier(result))) { |
ReportMessage(MessageTemplate::kStrongDirectEval); |
@@ -3306,6 +3521,8 @@ ParserBase<Traits>::ParseLeftHandSideExpression( |
case Token::PERIOD: { |
BindingPatternUnexpectedToken(classifier); |
+ classifier->AppendAssignmentTarget( |
+ ExpressionClassifier::TARGET_PROPERTY); |
Consume(Token::PERIOD); |
int pos = position(); |
IdentifierT name = ParseIdentifierName(CHECK_OK); |
@@ -3345,6 +3562,7 @@ ParserBase<Traits>::ParseMemberWithNewPrefixesExpression( |
if (peek() == Token::NEW) { |
BindingPatternUnexpectedToken(classifier); |
+ classifier->AppendAssignmentTarget(ExpressionClassifier::TARGET_CALL); |
Consume(Token::NEW); |
int new_pos = position(); |
ExpressionT result = this->EmptyExpression(); |
@@ -3396,7 +3614,7 @@ ParserBase<Traits>::ParseMemberExpression(ExpressionClassifier* classifier, |
ExpressionT result = this->EmptyExpression(); |
if (peek() == Token::FUNCTION) { |
BindingPatternUnexpectedToken(classifier); |
- |
+ classifier->AppendAssignmentTarget(ExpressionClassifier::TARGET_PRIMARY); |
Consume(Token::FUNCTION); |
int function_token_position = position(); |
bool is_generator = Check(Token::MUL); |
@@ -3585,12 +3803,14 @@ ParserBase<Traits>::ParseSuperExpression(bool is_new, |
if (IsConciseMethod(kind) || IsAccessorFunction(kind) || |
i::IsConstructor(kind)) { |
if (peek() == Token::PERIOD || peek() == Token::LBRACK) { |
+ classifier->AppendAssignmentTarget(ExpressionClassifier::TARGET_PROPERTY); |
scope->RecordSuperPropertyUsage(); |
return this->SuperPropertyReference(scope_, factory(), pos); |
} |
// new super() is never allowed. |
// super() is only allowed in derived constructor |
if (!is_new && peek() == Token::LPAREN && IsSubclassConstructor(kind)) { |
+ classifier->AppendAssignmentTarget(ExpressionClassifier::TARGET_CALL); |
if (is_strong(language_mode())) { |
// Super calls in strong mode are parsed separately. |
ReportMessageAt(scanner()->location(), |
@@ -3621,10 +3841,14 @@ ParserBase<Traits>::ParseMemberExpressionContinuation( |
switch (peek()) { |
case Token::LBRACK: { |
BindingPatternUnexpectedToken(classifier); |
- |
+ classifier->AppendAssignmentTarget( |
+ ExpressionClassifier::TARGET_PROPERTY); |
Consume(Token::LBRACK); |
int pos = position(); |
- ExpressionT index = this->ParseExpression(true, classifier, CHECK_OK); |
+ // Ignore pattern errors within expression |
+ ExpressionClassifier prop_classifier; |
+ ExpressionT index = |
+ this->ParseExpression(true, &prop_classifier, CHECK_OK); |
expression = factory()->NewProperty(expression, index, pos); |
if (fni_ != NULL) { |
this->PushPropertyName(fni_, index); |
@@ -3634,6 +3858,8 @@ ParserBase<Traits>::ParseMemberExpressionContinuation( |
} |
case Token::PERIOD: { |
BindingPatternUnexpectedToken(classifier); |
+ classifier->AppendAssignmentTarget( |
+ ExpressionClassifier::TARGET_PROPERTY); |
Consume(Token::PERIOD); |
int pos = position(); |
@@ -3648,6 +3874,7 @@ ParserBase<Traits>::ParseMemberExpressionContinuation( |
case Token::TEMPLATE_SPAN: |
case Token::TEMPLATE_TAIL: { |
BindingPatternUnexpectedToken(classifier); |
+ classifier->AppendAssignmentTarget(ExpressionClassifier::TARGET_CALL); |
int pos; |
if (scanner()->current_token() == Token::IDENTIFIER) { |
pos = position(); |
@@ -3659,8 +3886,10 @@ ParserBase<Traits>::ParseMemberExpressionContinuation( |
expression->AsFunctionLiteral()->set_should_eager_compile(); |
} |
} |
+ // Ignore classifying tagged template |
+ ExpressionClassifier call_classifier; |
expression = |
- ParseTemplateLiteral(expression, pos, classifier, CHECK_OK); |
+ ParseTemplateLiteral(expression, pos, &call_classifier, CHECK_OK); |
break; |
} |
default: |