Chromium Code Reviews| Index: src/preparser.h |
| diff --git a/src/preparser.h b/src/preparser.h |
| index 862b7fb40dd894b53dfcec80d36aedde5b441e3f..23cc57d41bb2676773b3c109786e13e02f5f5333 100644 |
| --- a/src/preparser.h |
| +++ b/src/preparser.h |
| @@ -504,6 +504,29 @@ class ParserBase : public Traits { |
| void ReportUnexpectedToken(Token::Value token); |
| void ReportUnexpectedTokenAt(Scanner::Location location, Token::Value token); |
| + ExpressionT CheckDestructuringAssignment(ExpressionT expr, |
| + ExpressionClassifier* classifier, |
| + bool needs_destructuring, |
| + unsigned flags, bool* ok) { |
| + // Don't rewrite AssignmentElement or RHS |
| + // An AssignmentElement's optional initializer is parsed as a separate |
| + // assignment expression. |
| + const bool rewrite = |
| + !(flags & (ASSIGNMENT_RHS | ASSIGNMENT_ELEMENT)) && needs_destructuring; |
| + if (classifier->is_destructuring_assignment()) { |
| + if (!classifier->is_valid_assignment_pattern()) { |
| + this->ReportClassifierError(classifier->assignment_pattern_error()); |
| + *ok = false; |
| + return this->EmptyExpression(); |
| + } |
| + } else if (flags & ~ASSIGNMENT_ELEMENT) { |
| + // If not a destructuring assignment, expect an expression |
| + ValidateExpression(classifier, ok); |
| + if (!*ok) return this->EmptyExpression(); |
| + } |
| + if (rewrite) return Traits::RewriteDestructuringAssignment(expr, ok); |
| + return expr; |
| + } |
| void ReportClassifierError(const ExpressionClassifier::Error& error) { |
| Traits::ReportMessageAt(error.location, error.message, error.arg, |
| @@ -579,6 +602,17 @@ class ParserBase : public Traits { |
| Token::String(peek())); |
| } |
| + void AssignmentPatternUnexpectedToken(ExpressionClassifier* classifier) { |
| + classifier->RecordAssignmentPatternError(scanner()->peek_location(), |
| + MessageTemplate::kUnexpectedToken, |
| + Token::String(peek())); |
| + } |
| + |
| + void PatternUnexpectedToken(ExpressionClassifier* classifier) { |
| + BindingPatternUnexpectedToken(classifier); |
| + AssignmentPatternUnexpectedToken(classifier); |
| + } |
| + |
| void ArrowFormalParametersUnexpectedToken(ExpressionClassifier* classifier) { |
| classifier->RecordArrowFormalParametersError( |
| scanner()->peek_location(), MessageTemplate::kUnexpectedToken, |
| @@ -625,9 +659,32 @@ class ParserBase : public Traits { |
| typename Traits::Type::ExpressionList ParseArguments( |
| Scanner::Location* first_spread_pos, ExpressionClassifier* classifier, |
| bool* ok); |
| - ExpressionT ParseAssignmentExpression(bool accept_IN, |
| + enum AssignmentExpressionFlags { |
| + ACCEPT_IN = 1 << 0, |
| + ASSIGNMENT_RHS = 1 << 1, |
| + ASSIGNMENT_ELEMENT = 1 << 2 |
| + }; |
| + ExpressionT ParseAssignmentExpression(unsigned flags, |
| + bool* needs_destructuring, |
| ExpressionClassifier* classifier, |
| bool* ok); |
| + ExpressionT ParseAssignmentExpression(bool accept_IN, |
| + ExpressionClassifier* classifier, |
| + bool* ok) { |
| + // Overloaded for legacy compat |
| + bool destructuring = false; |
| + unsigned flags = accept_IN ? ACCEPT_IN : 0; |
| + return ParseAssignmentExpression(flags, &destructuring, classifier, ok); |
| + } |
| + ExpressionT ParseAssignmentElement(bool accept_IN, |
| + ExpressionClassifier* classifier, |
| + bool* ok) { |
| + // Don't automatically rewrite AssignmentExpressions which are meant to be |
| + // AssignmentElements |
| + bool destructuring = false; |
| + unsigned flags = (accept_IN ? ACCEPT_IN : 0) | ASSIGNMENT_ELEMENT; |
| + return ParseAssignmentExpression(flags, &destructuring, classifier, ok); |
| + } |
| ExpressionT ParseYieldExpression(ExpressionClassifier* classifier, bool* ok); |
| ExpressionT ParseConditionalExpression(bool accept_IN, |
| ExpressionClassifier* classifier, |
| @@ -1586,6 +1643,11 @@ class PreParserTraits { |
| PreParserExpressionList args, |
| int pos); |
| + inline PreParserExpression RewriteDestructuringAssignment( |
| + PreParserExpression expr, bool* ok) { |
| + return expr; |
| + } |
| + |
| private: |
| PreParser* pre_parser_; |
| }; |
| @@ -2060,6 +2122,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); |
| @@ -2100,6 +2164,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()); |
| @@ -2181,6 +2246,7 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, |
| // Heuristically try to detect immediately called functions before |
| // seeing the call parentheses. |
| parenthesized_function_ = (peek() == Token::FUNCTION); |
| + lhs_part = ExpressionClassifier::TARGET_NONE; |
| result = this->ParseExpression(true, classifier, CHECK_OK); |
| Expect(Token::RPAREN, CHECK_OK); |
| } |
| @@ -2218,6 +2284,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 |
| @@ -2230,6 +2297,10 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, |
| } |
| } |
| + if (*ok && lhs_part != ExpressionClassifier::TARGET_NONE) { |
| + classifier->AppendAssignmentTarget(lhs_part); |
| + } |
| + |
| return result; |
| } |
| @@ -2252,13 +2323,19 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( |
| // AssignmentExpression |
| // Expression ',' AssignmentExpression |
| - ExpressionClassifier binding_classifier; |
| + ExpressionClassifier expr_classifier; |
| ExpressionT result = |
| - this->ParseAssignmentExpression(accept_IN, &binding_classifier, CHECK_OK); |
| - classifier->Accumulate(binding_classifier, |
| - ExpressionClassifier::AllProductions); |
| + this->ParseAssignmentExpression(accept_IN, &expr_classifier, CHECK_OK); |
| + ExpressionClassifier::AssignmentTargetType lhs_type = |
| + expr_classifier.AssignmentTarget(); |
| + classifier->Accumulate(expr_classifier, |
| + expr_classifier.is_destructuring_assignment() |
| + ? ExpressionClassifier::PatternProductions |
| + : ExpressionClassifier::AllProductions); |
| bool seen_rest = false; |
| while (peek() == Token::COMMA) { |
| + ExpressionClassifier expr_classifier; |
| + lhs_type = ExpressionClassifier::TARGET_PRIMARY; |
| if (seen_rest) { |
| // At this point the production can't possibly be valid, but we don't know |
| // which error to signal. |
| @@ -2277,13 +2354,17 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( |
| seen_rest = is_rest = true; |
| } |
| int pos = position(); |
| - ExpressionT right = this->ParseAssignmentExpression( |
| - accept_IN, &binding_classifier, CHECK_OK); |
| + ExpressionT right = |
| + this->ParseAssignmentExpression(accept_IN, &expr_classifier, CHECK_OK); |
| if (is_rest) right = factory()->NewSpread(right, pos); |
| - classifier->Accumulate(binding_classifier, |
| - ExpressionClassifier::AllProductions); |
| + classifier->Accumulate(expr_classifier, |
| + expr_classifier.is_destructuring_assignment() |
| + ? ExpressionClassifier::PatternProductions |
| + : ExpressionClassifier::AllProductions); |
| + |
| result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos); |
| } |
| + classifier->AppendAssignmentTarget(lhs_type); |
| return result; |
| } |
| @@ -2301,6 +2382,9 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral( |
| while (peek() != Token::RBRACK) { |
| bool seen_spread = false; |
| ExpressionT elem = this->EmptyExpression(); |
| + ExpressionClassifier element_classifier; |
| + bool accumulate_element = true; |
| + int start_pos = peek_position(); |
| if (peek() == Token::COMMA) { |
| if (is_strong(language_mode())) { |
| ReportMessageAt(scanner()->peek_location(), |
| @@ -2309,23 +2393,40 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral( |
| return this->EmptyExpression(); |
| } |
| elem = this->GetLiteralTheHole(peek_position(), factory()); |
| + accumulate_element = false; |
| } else if (peek() == Token::ELLIPSIS) { |
| if (!allow_harmony_spread_arrays()) { |
| ExpressionUnexpectedToken(classifier); |
| } |
| - int start_pos = peek_position(); |
| Consume(Token::ELLIPSIS); |
| ExpressionT argument = |
| - this->ParseAssignmentExpression(true, classifier, CHECK_OK); |
| + this->ParseAssignmentElement(true, &element_classifier, CHECK_OK); |
| elem = factory()->NewSpread(argument, start_pos); |
| seen_spread = true; |
| + |
| + // AssignmentRestElements may not have initializers |
| + if (element_classifier.IsAssigned()) { |
| + Scanner::Location location(start_pos, scanner()->location().end_pos); |
| + classifier->RecordAssignmentPatternError( |
| + location, MessageTemplate::kInitializedAssignmentRestElement); |
| + } |
| } else { |
| - elem = this->ParseAssignmentExpression(true, classifier, CHECK_OK); |
| + elem = this->ParseAssignmentElement(true, &element_classifier, CHECK_OK); |
| } |
| + if (accumulate_element) { |
| + if (!element_classifier.IsValidSimpleAssignmentTarget() && |
| + !element_classifier.IsValidPattern()) { |
| + 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) { |
| if (seen_spread) { |
| - BindingPatternUnexpectedToken(classifier); |
| + PatternUnexpectedToken(classifier); |
| } |
| Expect(Token::COMMA, CHECK_OK); |
| } |
| @@ -2414,13 +2515,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); |
| @@ -2434,12 +2538,16 @@ ParserBase<Traits>::ParsePropertyDefinition( |
| CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| } |
| Consume(Token::COLON); |
| - value = this->ParseAssignmentExpression( |
| - true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| - |
| + property_classifier = ExpressionClassifier(); |
| + value_start = peek_position(); |
| + value = this->ParseAssignmentElement( |
| + 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, |
| @@ -2470,10 +2578,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(); |
| @@ -2505,6 +2615,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, |
| @@ -2540,6 +2655,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); |
| } |
| @@ -2682,7 +2805,8 @@ 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(unsigned flags, |
| + bool* needs_destructuring, |
| ExpressionClassifier* classifier, |
| bool* ok) { |
| // AssignmentExpression :: |
| @@ -2690,6 +2814,8 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| // ArrowFunction |
| // YieldExpression |
| // LeftHandSideExpression AssignmentOperator AssignmentExpression |
| + bool accept_IN = flags & ACCEPT_IN; |
| + bool is_assignment_element = flags & ASSIGNMENT_ELEMENT; |
| Scanner::Location lhs_location = scanner()->peek_location(); |
| @@ -2697,6 +2823,11 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| return this->ParseYieldExpression(classifier, ok); |
| } |
| + bool maybe_assignment_pattern = |
| + allow_harmony_destructuring() && |
| + 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; |
| @@ -2708,9 +2839,20 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| ExpressionT expression = this->ParseConditionalExpression( |
| accept_IN, &arrow_formals_classifier, CHECK_OK); |
| + if (!arrow_formals_classifier.is_valid_assignment_pattern()) { |
| + if (maybe_assignment_pattern && peek() == Token::ASSIGN) { |
| + // ObjectAssignmentPattern or ArrayAssignmentPattern contains an error |
| + ReportClassifierError( |
| + arrow_formals_classifier.assignment_pattern_error()); |
| + *ok = false; |
| + return this->EmptyExpression(); |
| + } |
| + } |
| + |
| 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); |
| @@ -2736,6 +2878,25 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| ExpressionClassifier::StandardProductions | |
| ExpressionClassifier::FormalParametersProductions); |
| + bool valid_destructuring_assignment_target = |
| + arrow_formals_classifier.IsValidSimpleAssignmentTarget(); |
| + if (valid_destructuring_assignment_target) { |
| + classifier->AccumulateValidSimpleAssignmentTarget(arrow_formals_classifier); |
| + } else if (!maybe_assignment_pattern || |
| + !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 (maybe_assignment_pattern) { |
| + classifier->AppendAssignmentTarget(ExpressionClassifier::TARGET_PATTERN); |
| + if ((maybe_assignment_pattern = peek() == Token::ASSIGN)) { |
| + *needs_destructuring = true; |
| + } |
| + } |
| + |
| if (!Token::IsAssignmentOp(peek())) { |
| if (fni_ != NULL) fni_->Leave(); |
| // Parsed conditional expression only (no assignment). |
| @@ -2746,13 +2907,18 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| BindingPatternUnexpectedToken(classifier); |
| } |
| - expression = this->CheckAndRewriteReferenceExpression( |
| - expression, lhs_location, MessageTemplate::kInvalidLhsInAssignment, |
| - CHECK_OK); |
| + if (!maybe_assignment_pattern) { |
| + expression = this->CheckAndRewriteReferenceExpression( |
| + expression, lhs_location, MessageTemplate::kInvalidLhsInAssignment, |
| + CHECK_OK); |
| + } |
| + |
| expression = this->MarkExpressionAsAssigned(expression); |
| Token::Value op = Next(); // Get assignment operator. |
| - if (op != Token::ASSIGN) { |
| + if (op == Token::ASSIGN) { |
| + classifier->set_assigned(); |
| + } else { |
| classifier->RecordBindingPatternError(scanner()->location(), |
| MessageTemplate::kUnexpectedToken, |
| Token::String(op)); |
| @@ -2760,8 +2926,14 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| int pos = position(); |
| ExpressionClassifier rhs_classifier; |
| - ExpressionT right = |
| - this->ParseAssignmentExpression(accept_IN, &rhs_classifier, CHECK_OK); |
| + unsigned rhs_flags = flags | ASSIGNMENT_RHS; |
| + if (is_assignment_element) { |
| + // Parse an assignment element's initializer as a regular |
| + // AssignmentExpression |
| + rhs_flags &= ~(ASSIGNMENT_RHS | ASSIGNMENT_ELEMENT); |
| + } |
| + ExpressionT right = this->ParseAssignmentExpression( |
| + rhs_flags, needs_destructuring, &rhs_classifier, CHECK_OK); |
|
arv (Not doing code reviews)
2015/06/19 18:49:05
Don't we need to pass in a new boolean here? The o
|
| classifier->AccumulateReclassifyingAsPattern(rhs_classifier); |
| // TODO(1231235): We try to estimate the set of properties set by |
| @@ -2790,7 +2962,9 @@ 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, *needs_destructuring, flags, CHECK_OK); |
| } |
| template <class Traits> |
| @@ -2854,6 +3028,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, |
| @@ -2878,6 +3053,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(); |
| @@ -2940,7 +3116,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); |
| @@ -2962,6 +3138,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); |
| @@ -2994,7 +3171,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); |
| @@ -3025,9 +3202,11 @@ 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); |
| + ExpressionT index = ParseExpression(true, CHECK_OK); |
| result = factory()->NewProperty(result, index, pos); |
| Expect(Token::RBRACK, CHECK_OK); |
| break; |
| @@ -3035,7 +3214,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); |
| @@ -3086,6 +3265,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); |
| @@ -3135,6 +3316,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(); |
| @@ -3188,7 +3370,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); |
| @@ -3376,12 +3558,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(), |
| @@ -3437,10 +3621,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); |
| @@ -3450,6 +3638,8 @@ ParserBase<Traits>::ParseMemberExpressionContinuation( |
| } |
| case Token::PERIOD: { |
| BindingPatternUnexpectedToken(classifier); |
| + classifier->AppendAssignmentTarget( |
| + ExpressionClassifier::TARGET_PROPERTY); |
| Consume(Token::PERIOD); |
| int pos = position(); |
| @@ -3464,6 +3654,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(); |
| @@ -3475,8 +3666,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: |