| Index: src/parsing/preparser.h
|
| diff --git a/src/parsing/preparser.h b/src/parsing/preparser.h
|
| index 0b41e3bfe817c98ee51de84cc72ea59e267e7288..7a699670bbdf3b87d01cb465a02ded7cbfdda698 100644
|
| --- a/src/parsing/preparser.h
|
| +++ b/src/parsing/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_;
|
| +
|
| + void RewriteDestructuringAssignments();
|
| +
|
| 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_;
|
| };
|
| @@ -1312,12 +1397,21 @@ class PreParserFactory {
|
| PreParserExpression right, int pos) {
|
| return PreParserExpression::Default();
|
| }
|
| + PreParserExpression NewRewritableAssignmentExpression(
|
| + PreParserExpression expression) {
|
| + return expression;
|
| + }
|
| PreParserExpression NewAssignment(Token::Value op,
|
| PreParserExpression left,
|
| PreParserExpression right,
|
| 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,
|
| @@ -1749,6 +1843,10 @@ class PreParserTraits {
|
| PreParserExpressionList args,
|
| int pos);
|
|
|
| + inline void RewriteDestructuringAssignments() {}
|
| +
|
| + inline void QueueDestructuringAssignmentForRewriting(PreParserExpression) {}
|
| +
|
| private:
|
| PreParser* pre_parser_;
|
| };
|
| @@ -2394,8 +2492,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) {
|
| + ValidateExpression(classifier, CHECK_OK);
|
| + }
|
| return expr;
|
| }
|
|
|
| @@ -2463,17 +2565,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);
|
| @@ -2498,7 +2606,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);
|
| @@ -2509,6 +2617,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression(
|
| if (!is_simple_parameter_list || seen_rest) {
|
| classifier->RecordNonSimpleParameter();
|
| }
|
| +
|
| return result;
|
| }
|
|
|
| @@ -2525,7 +2634,6 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral(
|
| int first_spread_index = -1;
|
| Expect(Token::LBRACK, CHECK_OK);
|
| while (peek() != Token::RBRACK) {
|
| - bool seen_spread = false;
|
| ExpressionT elem = this->EmptyExpression();
|
| if (peek() == Token::COMMA) {
|
| if (is_strong(language_mode())) {
|
| @@ -2541,18 +2649,31 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral(
|
| ExpressionT argument =
|
| this->ParseAssignmentExpression(true, classifier, CHECK_OK);
|
| elem = factory()->NewSpread(argument, start_pos);
|
| - seen_spread = true;
|
| +
|
| 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);
|
| }
|
| }
|
| @@ -2676,8 +2797,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);
|
| }
|
| @@ -2712,7 +2843,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(
|
| @@ -2721,6 +2851,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;
|
| }
|
| @@ -2737,7 +2870,10 @@ ParserBase<Traits>::ParsePropertyDefinition(
|
| return this->EmptyObjectLiteralProperty();
|
| }
|
|
|
| - BindingPatternUnexpectedToken(classifier);
|
| + // 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
|
| @@ -2961,7 +3097,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 ::
|
| @@ -2969,7 +3105,10 @@ 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;
|
| int lhs_beg_pos = peek_position();
|
|
|
| if (peek() == Token::YIELD && is_generator()) {
|
| @@ -3015,18 +3154,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;
|
| }
|
|
|
| @@ -3035,9 +3199,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.
|
| @@ -3049,10 +3225,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
|
| @@ -3078,7 +3259,14 @@ 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) {
|
| + result = factory()->NewRewritableAssignmentExpression(result);
|
| + Traits::QueueDestructuringAssignmentForRewriting(result);
|
| + }
|
| +
|
| + return result;
|
| }
|
|
|
| template <class Traits>
|
| @@ -4041,6 +4229,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(
|
| @@ -4172,21 +4362,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()) {
|
| @@ -4198,9 +4400,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);
|
| + }
|
| }
|
| }
|
|
|
|
|