Chromium Code Reviews| 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: |