| Index: src/preparser.h
|
| diff --git a/src/preparser.h b/src/preparser.h
|
| index 7a68e835ff2870e5397c2be37f7f17acb4fed00f..acf00b80f46e7b78f97c75f653a0c6bce0f37f80 100644
|
| --- a/src/preparser.h
|
| +++ b/src/preparser.h
|
| @@ -570,7 +570,86 @@ 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 AssignmentTargetType AssignmentTarget() const { return lhs_type_; }
|
| +
|
| + inline void AppendAssignmentTarget(AssignmentTargetType type) {
|
| + if (lhs_type_ == UNACCEPTABLE_TARGET) return;
|
| + lhs_type_ = type;
|
| + }
|
| +
|
| + 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 +786,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 +841,8 @@ class ParserBase : public Traits {
|
| }
|
|
|
| private:
|
| + AssignmentTargetType lhs_type_;
|
| + bool assigned_;
|
| Error expression_error_;
|
| Error binding_pattern_error_;
|
| Error assignment_pattern_error_;
|
| @@ -764,6 +852,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 +987,15 @@ class ParserBase : public Traits {
|
| typename Traits::Type::ExpressionList ParseArguments(
|
| Scanner::Location* first_spread_pos, ExpressionClassifier* classifier,
|
| bool* ok);
|
| - ExpressionT ParseAssignmentExpression(bool accept_IN,
|
| + // TODO(caitp): Use enums for accept_IN / pattern_lhs?
|
| + ExpressionT ParseAssignmentExpression(bool accept_IN, bool pattern_lhs,
|
| 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,
|
| @@ -1840,6 +1948,11 @@ class PreParserTraits {
|
| PreParserExpressionList args,
|
| int pos);
|
|
|
| + inline PreParserExpression RewriteDestructuringAssignment(
|
| + PreParserExpression expr) {
|
| + return expr;
|
| + }
|
| +
|
| private:
|
| PreParser* pre_parser_;
|
| };
|
| @@ -2317,6 +2430,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);
|
| @@ -2357,6 +2472,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());
|
| @@ -2420,8 +2536,17 @@ 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);
|
| + } else {
|
| + lhs_part = expr_classifier.AssignmentTarget();
|
| + }
|
| }
|
| break;
|
|
|
| @@ -2457,6 +2582,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
|
| @@ -2469,6 +2595,10 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
|
| }
|
| }
|
|
|
| + if (*ok && lhs_part != ExpressionClassifier::TARGET_NONE) {
|
| + classifier->AppendAssignmentTarget(lhs_part);
|
| + }
|
| +
|
| return result;
|
| }
|
|
|
| @@ -2491,18 +2621,27 @@ 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);
|
| + classifier->AccumulateValidSimpleAssignmentTarget(expr_classifier);
|
| + classifier->Accumulate(expr_classifier,
|
| + expr_classifier.is_destructuring_assignment()
|
| + ? ExpressionClassifier::PatternProductions
|
| + : ExpressionClassifier::AllProductions);
|
| while (peek() == Token::COMMA) {
|
| Expect(Token::COMMA, CHECK_OK);
|
| int pos = position();
|
| - ExpressionT right = this->ParseAssignmentExpression(
|
| - accept_IN, &binding_classifier, CHECK_OK);
|
| - classifier->Accumulate(binding_classifier,
|
| - ExpressionClassifier::AllProductions);
|
| + classifier->ReportInvalidSimpleAssignmentTarget();
|
| + ExpressionClassifier expr_classifier;
|
| + ExpressionT right =
|
| + this->ParseAssignmentExpression(accept_IN, &expr_classifier, CHECK_OK);
|
| + classifier->Accumulate(expr_classifier,
|
| + expr_classifier.is_destructuring_assignment()
|
| + ? ExpressionClassifier::PatternProductions
|
| + : ExpressionClassifier::AllProductions);
|
| +
|
| +
|
| result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos);
|
| }
|
| return result;
|
| @@ -2522,6 +2661,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(),
|
| @@ -2541,7 +2681,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) {
|
| @@ -2635,13 +2784,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);
|
| @@ -2655,12 +2807,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,
|
| @@ -2691,10 +2847,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();
|
| @@ -2726,6 +2884,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,
|
| @@ -2744,7 +2907,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);
|
| @@ -2761,6 +2925,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);
|
| }
|
| @@ -2903,7 +3075,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 pattern_lhs,
|
| ExpressionClassifier* classifier,
|
| bool* ok) {
|
| // AssignmentExpression ::
|
| @@ -2918,6 +3090,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;
|
| @@ -2926,13 +3103,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 (maybe_assignment_pattern && 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);
|
| @@ -2957,6 +3147,29 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
|
| classifier->Accumulate(arrow_formals_classifier,
|
| ExpressionClassifier::FormalParametersProduction);
|
|
|
| + 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 (pattern_lhs && peek() != Token::ASSIGN) {
|
| + // If LHS was an AssignmentPattern and there is no additional assignment,
|
| + // ensure that the RHS is a valid expression
|
| + ValidateExpression(classifier, CHECK_OK);
|
| + return expression;
|
| + }
|
| +
|
| if (!Token::IsAssignmentOp(peek())) {
|
| if (fni_ != NULL) fni_->Leave();
|
| // Parsed conditional expression only (no assignment).
|
| @@ -2967,9 +3180,12 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
|
| BindingPatternUnexpectedToken(classifier);
|
| }
|
|
|
| - expression = this->CheckAndRewriteReferenceExpression(
|
| - expression, lhs_location, MessageTemplate::kInvalidLhsInAssignment,
|
| - CHECK_OK);
|
| + if (!maybe_assignment_pattern || peek() != Token::ASSIGN) {
|
| + expression = this->CheckAndRewriteReferenceExpression(
|
| + expression, lhs_location, MessageTemplate::kInvalidLhsInAssignment,
|
| + CHECK_OK);
|
| + }
|
| +
|
| expression = this->MarkExpressionAsAssigned(expression);
|
|
|
| Token::Value op = Next(); // Get assignment operator.
|
| @@ -2977,12 +3193,14 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
|
| classifier->RecordBindingPatternError(scanner()->location(),
|
| MessageTemplate::kUnexpectedToken,
|
| Token::String(op));
|
| + } else {
|
| + classifier->set_assigned();
|
| }
|
| int pos = position();
|
|
|
| ExpressionClassifier rhs_classifier;
|
| - ExpressionT right =
|
| - this->ParseAssignmentExpression(accept_IN, &rhs_classifier, CHECK_OK);
|
| + ExpressionT right = this->ParseAssignmentExpression(
|
| + accept_IN, maybe_assignment_pattern, &rhs_classifier, CHECK_OK);
|
| classifier->AccumulateReclassifyingAsPattern(rhs_classifier);
|
|
|
| // TODO(1231235): We try to estimate the set of properties set by
|
| @@ -3011,7 +3229,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>
|
| @@ -3078,6 +3297,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,
|
| @@ -3102,6 +3322,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();
|
| @@ -3164,7 +3385,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);
|
| @@ -3186,6 +3407,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);
|
| @@ -3218,7 +3440,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);
|
| @@ -3249,9 +3471,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;
|
| @@ -3259,7 +3483,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);
|
| @@ -3310,6 +3534,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);
|
| @@ -3349,6 +3575,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();
|
| @@ -3400,7 +3627,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);
|
| @@ -3589,12 +3816,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(),
|
| @@ -3625,10 +3854,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);
|
| @@ -3638,6 +3871,8 @@ ParserBase<Traits>::ParseMemberExpressionContinuation(
|
| }
|
| case Token::PERIOD: {
|
| BindingPatternUnexpectedToken(classifier);
|
| + classifier->AppendAssignmentTarget(
|
| + ExpressionClassifier::TARGET_PROPERTY);
|
|
|
| Consume(Token::PERIOD);
|
| int pos = position();
|
| @@ -3652,6 +3887,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();
|
| @@ -3663,8 +3899,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:
|
|
|