Chromium Code Reviews| Index: src/preparser.h |
| diff --git a/src/preparser.h b/src/preparser.h |
| index 1de6678c1e15ca8c627db9bc0612f1b9c1a32210..28e3606d9d7a8aa830559860762417a707375a05 100644 |
| --- a/src/preparser.h |
| +++ b/src/preparser.h |
| @@ -114,6 +114,7 @@ class ParserBase : public Traits { |
| allow_harmony_rest_parameters_(false), |
| allow_harmony_default_parameters_(false), |
| allow_harmony_destructuring_bind_(false), |
| + allow_harmony_destructuring_assignment_(false), |
| allow_strong_mode_(false), |
| allow_legacy_const_(true), |
| allow_harmony_do_expressions_(false) {} |
| @@ -130,6 +131,7 @@ class ParserBase : public Traits { |
| ALLOW_ACCESSORS(harmony_rest_parameters); |
| ALLOW_ACCESSORS(harmony_default_parameters); |
| ALLOW_ACCESSORS(harmony_destructuring_bind); |
| + ALLOW_ACCESSORS(harmony_destructuring_assignment); |
| ALLOW_ACCESSORS(strong_mode); |
| ALLOW_ACCESSORS(legacy_const); |
| ALLOW_ACCESSORS(harmony_do_expressions); |
| @@ -175,6 +177,15 @@ class ParserBase : public Traits { |
| Scope* outer_scope_; |
| }; |
| + struct DestructuringAssignment { |
| + public: |
| + DestructuringAssignment(ExpressionT expression, Scope* scope) |
| + : assignment(expression), scope(scope) {} |
| + |
| + ExpressionT assignment; |
| + Scope* scope; |
| + }; |
| + |
| class FunctionState BASE_EMBEDDED { |
| public: |
| FunctionState(FunctionState** function_state_stack, Scope** scope_stack, |
| @@ -227,6 +238,15 @@ class ParserBase : public Traits { |
| typename Traits::Type::Factory* factory() { return factory_; } |
| + const List<DestructuringAssignment>& destructuring_assignments_to_rewrite() |
| + const { |
| + return destructuring_assignments_to_rewrite_; |
| + } |
| + |
| + void AddDestructuringAssignment(DestructuringAssignment pair) { |
| + destructuring_assignments_to_rewrite_.Add(pair); |
| + } |
| + |
| private: |
| // Used to assign an index to each literal that needs materialization in |
| // the function. Includes regexp literals, and boilerplate for object and |
| @@ -255,6 +275,11 @@ class ParserBase : public Traits { |
| FunctionState* outer_function_state_; |
| Scope** scope_stack_; |
| Scope* outer_scope_; |
| + |
| + List<DestructuringAssignment> destructuring_assignments_to_rewrite_; |
|
adamk
2015/11/25 21:05:28
Please move this to Parser unless there's some rea
caitp (gmail)
2015/11/25 21:41:52
The list lives in FunctionState, so each FunctionS
|
| + |
| + void RewriteDestructuringAssignments(); |
|
adamk
2015/11/25 21:05:28
I don't see this defined anywhere (and I don't thi
caitp (gmail)
2015/11/25 21:41:52
Acknowledged.
|
| + |
| typename Traits::Type::Factory* factory_; |
| friend class ParserTraits; |
| @@ -460,6 +485,10 @@ class ParserBase : public Traits { |
| ok); |
| } |
| + void CheckDestructuringElement(ExpressionT element, |
| + ExpressionClassifier* classifier, int beg_pos, |
| + int end_pos); |
| + |
| // Checking the name of a function literal. This has to be done after parsing |
| // the function, since the function can declare itself strict. |
| void CheckFunctionName(LanguageMode language_mode, IdentifierT function_name, |
| @@ -538,12 +567,20 @@ class ParserBase : public Traits { |
| void ReportClassifierError(const ExpressionClassifier::Error& error) { |
| Traits::ReportMessageAt(error.location, error.message, error.arg, |
| - kSyntaxError); |
| + error.type); |
| } |
| void ValidateExpression(const ExpressionClassifier* classifier, bool* ok) { |
| - if (!classifier->is_valid_expression()) { |
| - ReportClassifierError(classifier->expression_error()); |
| + if (!classifier->is_valid_expression() || |
| + classifier->has_cover_initialized_name()) { |
| + const Scanner::Location& a = classifier->expression_error().location; |
| + const Scanner::Location& b = |
| + classifier->cover_initialized_name_error().location; |
| + if (a.beg_pos < 0 || (b.beg_pos >= 0 && a.beg_pos > b.beg_pos)) { |
| + ReportClassifierError(classifier->cover_initialized_name_error()); |
| + } else { |
| + ReportClassifierError(classifier->expression_error()); |
| + } |
| *ok = false; |
| } |
| } |
| @@ -692,6 +729,8 @@ class ParserBase : public Traits { |
| ExpressionT ParseExpression(bool accept_IN, bool* ok); |
| ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier, |
| bool* ok); |
| + ExpressionT ParseExpression(bool accept_IN, int flags, |
| + ExpressionClassifier* classifier, bool* ok); |
| ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok); |
| ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set, |
| bool* is_static, bool* is_computed_name, |
| @@ -705,9 +744,23 @@ 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 { |
| + kIsLeftHandSide = 0, |
| + kIsRightHandSide = 1 << 0, |
| + kIsPatternElement = 1 << 1, |
| + kIsPossibleArrowFormals = 1 << 2 |
| + }; |
| + |
| + ExpressionT ParseAssignmentExpression(bool accept_IN, int flags, |
| ExpressionClassifier* classifier, |
| bool* ok); |
| + ExpressionT ParseAssignmentExpression(bool accept_IN, |
| + ExpressionClassifier* classifier, |
| + bool* ok) { |
| + return ParseAssignmentExpression(accept_IN, kIsLeftHandSide, classifier, |
| + ok); |
| + } |
| ExpressionT ParseYieldExpression(ExpressionClassifier* classifier, bool* ok); |
| ExpressionT ParseConditionalExpression(bool accept_IN, |
| ExpressionClassifier* classifier, |
| @@ -755,10 +808,29 @@ class ParserBase : public Traits { |
| ExpressionT CheckAndRewriteReferenceExpression( |
| ExpressionT expression, int beg_pos, int end_pos, |
| MessageTemplate::Template message, bool* ok); |
| + ExpressionT ClassifyAndRewriteReferenceExpression( |
| + ExpressionClassifier* classifier, ExpressionT expression, int beg_pos, |
| + int end_pos, MessageTemplate::Template message, |
| + ParseErrorType type = kSyntaxError); |
| ExpressionT CheckAndRewriteReferenceExpression( |
| ExpressionT expression, int beg_pos, int end_pos, |
| MessageTemplate::Template message, ParseErrorType type, bool* ok); |
| + bool IsValidReferenceExpression(ExpressionT expression); |
| + |
| + bool IsAssignableIdentifier(ExpressionT expression) { |
| + if (!Traits::IsIdentifier(expression)) return false; |
| + if (is_strict(language_mode()) && |
| + Traits::IsEvalOrArguments(Traits::AsIdentifier(expression))) { |
| + return false; |
| + } |
| + if (is_strong(language_mode()) && |
| + Traits::IsUndefined(Traits::AsIdentifier(expression))) { |
| + return false; |
| + } |
| + return true; |
| + } |
| + |
| // Used to validate property names in object literals and class literals |
| enum PropertyKind { |
| kAccessorProperty, |
| @@ -847,6 +919,7 @@ class ParserBase : public Traits { |
| bool allow_harmony_rest_parameters_; |
| bool allow_harmony_default_parameters_; |
| bool allow_harmony_destructuring_bind_; |
| + bool allow_harmony_destructuring_assignment_; |
| bool allow_strong_mode_; |
| bool allow_legacy_const_; |
| bool allow_harmony_do_expressions_; |
| @@ -959,6 +1032,11 @@ class PreParserExpression { |
| right->IsSpreadExpression())); |
| } |
| + static PreParserExpression AssignmentPattern() { |
| + return PreParserExpression(TypeField::encode(kExpression) | |
| + ExpressionTypeField::encode(kAssignmentPattern)); |
| + } |
| + |
| static PreParserExpression ObjectLiteral() { |
| return PreParserExpression(TypeField::encode(kObjectLiteralExpression)); |
| } |
| @@ -1024,6 +1102,11 @@ class PreParserExpression { |
| return PreParserIdentifier(IdentifierTypeField::decode(code_)); |
| } |
| + bool IsAssignmentPattern() const { |
| + return TypeField::decode(code_) == kExpression && |
| + ExpressionTypeField::decode(code_) == kAssignmentPattern; |
| + } |
| + |
| bool IsObjectLiteral() const { |
| return TypeField::decode(code_) == kObjectLiteralExpression; |
| } |
| @@ -1131,7 +1214,8 @@ class PreParserExpression { |
| kPropertyExpression, |
| kCallExpression, |
| kSuperCallReference, |
| - kNoTemplateTagExpression |
| + kNoTemplateTagExpression, |
| + kAssignmentPattern |
| }; |
| explicit PreParserExpression(uint32_t expression_code) |
| @@ -1148,6 +1232,7 @@ class PreParserExpression { |
| typedef BitField<PreParserIdentifier::Type, TypeField::kNext, 10> |
| IdentifierTypeField; |
| typedef BitField<bool, TypeField::kNext, 1> HasRestField; |
| + typedef BitField<bool, TypeField::kNext, 1> HasCoverInitializedNameField; |
| uint32_t code_; |
| }; |
| @@ -1320,6 +1405,11 @@ class PreParserFactory { |
| int pos) { |
| return PreParserExpression::Default(); |
| } |
| + PreParserExpression NewAssignmentPattern(PreParserExpression pattern, |
| + int pos) { |
| + DCHECK(pattern->IsObjectLiteral() || pattern->IsArrayLiteral()); |
| + return PreParserExpression::AssignmentPattern(); |
| + } |
| PreParserExpression NewYield(PreParserExpression generator_object, |
| PreParserExpression expression, |
| Yield::Kind yield_kind, |
| @@ -1750,6 +1840,10 @@ class PreParserTraits { |
| PreParserExpressionList args, |
| int pos); |
| + inline void RewriteDestructuringAssignments() {} |
| + |
| + inline void ShouldRewriteDestructuringAssignment(PreParserExpression) {} |
| + |
| private: |
| PreParser* pre_parser_; |
| }; |
| @@ -2393,8 +2487,12 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, |
| // Heuristically try to detect immediately called functions before |
| // seeing the call parentheses. |
| parenthesized_function_ = (peek() == Token::FUNCTION); |
| - ExpressionT expr = this->ParseExpression(true, classifier, CHECK_OK); |
| + ExpressionT expr = this->ParseExpression(true, kIsPossibleArrowFormals, |
| + classifier, CHECK_OK); |
| Expect(Token::RPAREN, CHECK_OK); |
| + if (peek() != Token::ARROW) { |
|
adamk
2015/11/25 21:05:28
Sorry, I've forgotten if you've answered this alre
caitp (gmail)
2015/11/25 21:41:52
```
// Valid if: --harmony-destructuring-assignme
adamk
2015/11/25 21:54:20
Thanks!
|
| + ValidateExpression(classifier, CHECK_OK); |
| + } |
| return expr; |
| } |
| @@ -2462,17 +2560,23 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( |
| } |
| -// Precedence = 1 |
| template <class Traits> |
| typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( |
| bool accept_IN, ExpressionClassifier* classifier, bool* ok) { |
| + return ParseExpression(accept_IN, kIsLeftHandSide, classifier, ok); |
| +} |
| + |
| + |
| +template <class Traits> |
| +typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( |
| + bool accept_IN, int flags, ExpressionClassifier* classifier, bool* ok) { |
| // Expression :: |
| // AssignmentExpression |
| // Expression ',' AssignmentExpression |
| ExpressionClassifier binding_classifier; |
| - ExpressionT result = |
| - this->ParseAssignmentExpression(accept_IN, &binding_classifier, CHECK_OK); |
| + ExpressionT result = this->ParseAssignmentExpression( |
| + accept_IN, flags, &binding_classifier, CHECK_OK); |
| classifier->Accumulate(binding_classifier, |
| ExpressionClassifier::AllProductions); |
| bool is_simple_parameter_list = this->IsIdentifier(result); |
| @@ -2497,7 +2601,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( |
| } |
| int pos = position(); |
| ExpressionT right = this->ParseAssignmentExpression( |
| - accept_IN, &binding_classifier, CHECK_OK); |
| + accept_IN, flags, &binding_classifier, CHECK_OK); |
| if (is_rest) right = factory()->NewSpread(right, pos); |
| is_simple_parameter_list = |
| is_simple_parameter_list && this->IsIdentifier(right); |
| @@ -2508,6 +2612,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( |
| if (!is_simple_parameter_list || seen_rest) { |
| classifier->RecordNonSimpleParameter(); |
| } |
| + |
| return result; |
| } |
| @@ -2544,14 +2649,27 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral( |
| if (first_spread_index < 0) { |
| first_spread_index = values->length(); |
| } |
| + |
| + CheckDestructuringElement(argument, classifier, start_pos, |
| + scanner()->location().end_pos); |
| + |
| + if (peek() == Token::COMMA) { |
| + classifier->RecordPatternError( |
| + Scanner::Location(start_pos, scanner()->location().end_pos), |
| + MessageTemplate::kElementAfterRest); |
| + } |
| } else { |
| - elem = this->ParseAssignmentExpression(true, classifier, CHECK_OK); |
| + elem = this->ParseAssignmentExpression(true, kIsPatternElement, |
| + classifier, CHECK_OK); |
| + if (!this->IsValidReferenceExpression(elem) && |
| + !classifier->is_valid_assignment_pattern()) { |
| + classifier->RecordPatternError( |
| + Scanner::Location(pos, scanner()->location().end_pos), |
| + MessageTemplate::kInvalidDestructuringTarget); |
| + } |
| } |
| values->Add(elem, zone_); |
| if (peek() != Token::RBRACK) { |
| - if (seen_spread) { |
| - BindingPatternUnexpectedToken(classifier); |
| - } |
| Expect(Token::COMMA, CHECK_OK); |
| } |
| } |
| @@ -2675,8 +2793,18 @@ ParserBase<Traits>::ParsePropertyDefinition( |
| CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| } |
| Consume(Token::COLON); |
| + int pos = peek_position(); |
| value = this->ParseAssignmentExpression( |
| - true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| + true, kIsPatternElement, classifier, |
| + CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| + |
| + if (!this->IsValidReferenceExpression(value) && |
| + !classifier->is_valid_assignment_pattern()) { |
| + classifier->RecordPatternError( |
| + Scanner::Location(pos, scanner()->location().end_pos), |
| + MessageTemplate::kInvalidDestructuringTarget); |
| + } |
| + |
| return factory()->NewObjectLiteralProperty(name_expression, value, false, |
| *is_computed_name); |
| } |
| @@ -2711,7 +2839,6 @@ ParserBase<Traits>::ParsePropertyDefinition( |
| name, next_beg_pos, next_end_pos, scope_, factory()); |
| if (peek() == Token::ASSIGN) { |
| - this->ExpressionUnexpectedToken(classifier); |
| Consume(Token::ASSIGN); |
| ExpressionClassifier rhs_classifier; |
| ExpressionT rhs = this->ParseAssignmentExpression( |
| @@ -2720,6 +2847,9 @@ ParserBase<Traits>::ParsePropertyDefinition( |
| ExpressionClassifier::ExpressionProductions); |
| value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs, |
| RelocInfo::kNoPosition); |
| + classifier->RecordCoverInitializedNameError( |
| + Scanner::Location(next_beg_pos, scanner()->location().end_pos), |
| + MessageTemplate::kInvalidCoverInitializedName); |
| } else { |
| value = lhs; |
| } |
| @@ -2736,6 +2866,11 @@ ParserBase<Traits>::ParsePropertyDefinition( |
| return this->EmptyObjectLiteralProperty(); |
| } |
| + // Method definitions are never valid in patterns. |
| + classifier->RecordPatternError( |
| + Scanner::Location(next_beg_pos, scanner()->location().end_pos), |
| + MessageTemplate::kInvalidDestructuringTarget); |
| + |
| if (is_generator || peek() == Token::LPAREN) { |
| // MethodDefinition |
| // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}' |
| @@ -2958,7 +3093,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, int flags, |
| ExpressionClassifier* classifier, |
| bool* ok) { |
| // AssignmentExpression :: |
| @@ -2966,7 +3101,11 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| // ArrowFunction |
| // YieldExpression |
| // LeftHandSideExpression AssignmentOperator AssignmentExpression |
| - |
| + bool is_rhs = flags & kIsRightHandSide; |
| + bool is_pattern_element = flags & kIsPatternElement; |
| + bool is_destructuring_assignment = false; |
| + bool is_arrow_formals = flags & kIsPossibleArrowFormals; |
| + USE(is_arrow_formals); |
|
adamk
2015/11/25 21:05:28
This USE is not needed.
caitp (gmail)
2015/11/25 21:41:52
Acknowledged.
|
| int lhs_beg_pos = peek_position(); |
| if (peek() == Token::YIELD && is_generator()) { |
| @@ -3012,18 +3151,43 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| } |
| expression = this->ParseArrowFunctionLiteral( |
| accept_IN, parameters, arrow_formals_classifier, CHECK_OK); |
| + if (is_pattern_element) { |
| + classifier->RecordPatternError( |
| + Scanner::Location(lhs_beg_pos, scanner()->location().end_pos), |
| + MessageTemplate::kInvalidDestructuringTarget); |
| + } |
| return expression; |
| } |
| + if (this->IsValidReferenceExpression(expression)) { |
| + arrow_formals_classifier.ForgiveAssignmentPatternError(); |
| + } |
| + |
| // "expression" was not itself an arrow function parameter list, but it might |
| // form part of one. Propagate speculative formal parameter error locations. |
| - classifier->Accumulate(arrow_formals_classifier, |
| - ExpressionClassifier::StandardProductions | |
| - ExpressionClassifier::FormalParametersProductions); |
| + classifier->Accumulate( |
| + arrow_formals_classifier, |
| + ExpressionClassifier::StandardProductions | |
| + ExpressionClassifier::FormalParametersProductions | |
| + ExpressionClassifier::CoverInitializedNameProduction); |
| + |
| + bool maybe_pattern = |
| + expression->IsObjectLiteral() || expression->IsArrayLiteral(); |
| + // bool binding_pattern = |
| + // allow_harmony_destructuring_bind() && maybe_pattern && !is_rhs; |
| if (!Token::IsAssignmentOp(peek())) { |
| if (fni_ != NULL) fni_->Leave(); |
| // Parsed conditional expression only (no assignment). |
| + if (is_pattern_element && !this->IsValidReferenceExpression(expression) && |
| + !maybe_pattern) { |
| + classifier->RecordPatternError( |
| + Scanner::Location(lhs_beg_pos, scanner()->location().end_pos), |
| + MessageTemplate::kInvalidDestructuringTarget); |
| + } else if (is_rhs && maybe_pattern) { |
| + ValidateExpression(classifier, CHECK_OK); |
| + } |
| + |
| return expression; |
| } |
| @@ -3032,9 +3196,21 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| BindingPatternUnexpectedToken(classifier); |
| } |
| - expression = this->CheckAndRewriteReferenceExpression( |
| - expression, lhs_beg_pos, scanner()->location().end_pos, |
| - MessageTemplate::kInvalidLhsInAssignment, CHECK_OK); |
| + if (allow_harmony_destructuring_assignment() && maybe_pattern && |
| + peek() == Token::ASSIGN) { |
| + classifier->ForgiveCoverInitializedNameError(); |
| + ValidateAssignmentPattern(classifier, CHECK_OK); |
| + is_destructuring_assignment = true; |
| + } else if (is_arrow_formals) { |
| + expression = this->ClassifyAndRewriteReferenceExpression( |
| + classifier, expression, lhs_beg_pos, scanner()->location().end_pos, |
| + MessageTemplate::kInvalidLhsInAssignment); |
| + } else { |
| + expression = this->CheckAndRewriteReferenceExpression( |
| + expression, lhs_beg_pos, scanner()->location().end_pos, |
| + MessageTemplate::kInvalidLhsInAssignment, CHECK_OK); |
| + } |
| + |
| expression = this->MarkExpressionAsAssigned(expression); |
| Token::Value op = Next(); // Get assignment operator. |
| @@ -3046,10 +3222,15 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| int pos = position(); |
| ExpressionClassifier rhs_classifier; |
| - ExpressionT right = |
| - this->ParseAssignmentExpression(accept_IN, &rhs_classifier, CHECK_OK); |
| - classifier->Accumulate(rhs_classifier, |
| - ExpressionClassifier::ExpressionProductions); |
| + |
| + int rhs_flags = flags; |
| + rhs_flags &= ~(kIsPatternElement | kIsPossibleArrowFormals); |
| + rhs_flags |= kIsRightHandSide; |
| + ExpressionT right = this->ParseAssignmentExpression( |
| + accept_IN, rhs_flags, &rhs_classifier, CHECK_OK); |
| + classifier->Accumulate( |
| + rhs_classifier, ExpressionClassifier::ExpressionProductions | |
| + ExpressionClassifier::CoverInitializedNameProduction); |
| // TODO(1231235): We try to estimate the set of properties set by |
| // constructors. We define a new property whenever there is an |
| @@ -3075,7 +3256,13 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
| fni_->Leave(); |
| } |
| - return factory()->NewAssignment(op, expression, right, pos); |
| + ExpressionT result = factory()->NewAssignment(op, expression, right, pos); |
| + |
| + if (is_destructuring_assignment) { |
| + Traits::ShouldRewriteDestructuringAssignment(result); |
| + } |
| + |
| + return result; |
| } |
| template <class Traits> |
| @@ -4033,6 +4220,8 @@ ParserBase<Traits>::ParseArrowFunctionLiteral( |
| if (is_strict(language_mode()) || allow_harmony_sloppy()) { |
| this->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK); |
| } |
| + |
| + Traits::RewriteDestructuringAssignments(); |
| } |
| FunctionLiteralT function_literal = factory()->NewFunctionLiteral( |
| @@ -4164,21 +4353,33 @@ typename ParserBase<Traits>::ExpressionT |
| ParserBase<Traits>::CheckAndRewriteReferenceExpression( |
| ExpressionT expression, int beg_pos, int end_pos, |
| MessageTemplate::Template message, ParseErrorType type, bool* ok) { |
| + ExpressionClassifier classifier; |
| + ExpressionT result = ClassifyAndRewriteReferenceExpression( |
| + &classifier, expression, beg_pos, end_pos, message, type); |
| + ValidateExpression(&classifier, ok); |
| + if (!*ok) return this->EmptyExpression(); |
| + return result; |
| +} |
| + |
| + |
| +template <typename Traits> |
| +typename ParserBase<Traits>::ExpressionT |
| +ParserBase<Traits>::ClassifyAndRewriteReferenceExpression( |
| + ExpressionClassifier* classifier, ExpressionT expression, int beg_pos, |
| + int end_pos, MessageTemplate::Template message, ParseErrorType type) { |
| Scanner::Location location(beg_pos, end_pos); |
| if (this->IsIdentifier(expression)) { |
| if (is_strict(language_mode()) && |
| this->IsEvalOrArguments(this->AsIdentifier(expression))) { |
| - this->ReportMessageAt(location, MessageTemplate::kStrictEvalArguments, |
| - kSyntaxError); |
| - *ok = false; |
| - return this->EmptyExpression(); |
| + classifier->RecordExpressionError( |
| + location, MessageTemplate::kStrictEvalArguments, kSyntaxError); |
| + return expression; |
| } |
| if (is_strong(language_mode()) && |
| this->IsUndefined(this->AsIdentifier(expression))) { |
| - this->ReportMessageAt(location, MessageTemplate::kStrongUndefined, |
| - kSyntaxError); |
| - *ok = false; |
| - return this->EmptyExpression(); |
| + classifier->RecordExpressionError( |
| + location, MessageTemplate::kStrongUndefined, kSyntaxError); |
| + return expression; |
| } |
| } |
| if (expression->IsValidReferenceExpression()) { |
| @@ -4190,9 +4391,31 @@ ParserBase<Traits>::CheckAndRewriteReferenceExpression( |
| ExpressionT error = this->NewThrowReferenceError(message, pos); |
| return factory()->NewProperty(expression, error, pos); |
| } else { |
| - this->ReportMessageAt(location, message, type); |
| - *ok = false; |
| - return this->EmptyExpression(); |
| + classifier->RecordExpressionError(location, message, type); |
| + return expression; |
| + } |
| +} |
| + |
| + |
| +template <typename Traits> |
| +bool ParserBase<Traits>::IsValidReferenceExpression(ExpressionT expression) { |
| + return this->IsAssignableIdentifier(expression) || expression->IsProperty(); |
| +} |
| + |
| + |
| +template <typename Traits> |
| +void ParserBase<Traits>::CheckDestructuringElement( |
| + ExpressionT expression, ExpressionClassifier* classifier, int begin, |
| + int end) { |
| + static const MessageTemplate::Template message = |
| + MessageTemplate::kInvalidDestructuringTarget; |
| + if (!this->IsAssignableIdentifier(expression)) { |
| + const Scanner::Location location(begin, end); |
| + classifier->RecordBindingPatternError(location, message); |
| + if (!expression->IsProperty() && |
| + !(expression->IsObjectLiteral() || expression->IsArrayLiteral())) { |
| + classifier->RecordAssignmentPatternError(location, message); |
| + } |
| } |
| } |