diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index 4adb8f0234a7f0..4dcb3e573482a3 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 5 #define V8_MINOR_VERSION 1 #define V8_BUILD_NUMBER 281 -#define V8_PATCH_LEVEL 94 +#define V8_PATCH_LEVEL 95 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/messages.h b/deps/v8/src/messages.h index 4aa0b73e7179c1..5ea0bc2686e84e 100644 --- a/deps/v8/src/messages.h +++ b/deps/v8/src/messages.h @@ -449,6 +449,8 @@ class CallSite { "Too many arguments in function call (only 65535 allowed)") \ T(TooManyParameters, \ "Too many parameters in function definition (only 65535 allowed)") \ + T(TooManySpreads, \ + "Literal containing too many nested spreads (up to 65534 allowed)") \ T(TooManyVariables, "Too many variables declared (only 4194303 allowed)") \ T(TypedArrayTooShort, \ "Derived TypedArray constructor created an array which was too small") \ diff --git a/deps/v8/src/parsing/expression-classifier.h b/deps/v8/src/parsing/expression-classifier.h index 71fa3d3e89b160..e3b0b8c487be5a 100644 --- a/deps/v8/src/parsing/expression-classifier.h +++ b/deps/v8/src/parsing/expression-classifier.h @@ -13,32 +13,52 @@ namespace v8 { namespace internal { +#define ERROR_CODES(T) \ + T(ExpressionProduction, 0) \ + T(FormalParameterInitializerProduction, 1) \ + T(BindingPatternProduction, 2) \ + T(AssignmentPatternProduction, 3) \ + T(DistinctFormalParametersProduction, 4) \ + T(StrictModeFormalParametersProduction, 5) \ + T(ArrowFormalParametersProduction, 6) \ + T(LetPatternProduction, 7) \ + T(CoverInitializedNameProduction, 8) + + template class ExpressionClassifier { public: + enum ErrorKind : unsigned { +#define DEFINE_ERROR_KIND(NAME, CODE) k##NAME = CODE, + ERROR_CODES(DEFINE_ERROR_KIND) +#undef DEFINE_ERROR_KIND + kUnusedError = 15 // Larger than error codes; should fit in 4 bits + }; + struct Error { - Error() + V8_INLINE Error() : location(Scanner::Location::invalid()), message(MessageTemplate::kNone), + kind(kUnusedError), type(kSyntaxError), arg(nullptr) {} + V8_INLINE explicit Error(Scanner::Location loc, + MessageTemplate::Template msg, ErrorKind k, + const char* a = nullptr, + ParseErrorType t = kSyntaxError) + : location(loc), message(msg), kind(k), type(t), arg(a) {} Scanner::Location location; - MessageTemplate::Template message : 30; + MessageTemplate::Template message : 26; + unsigned kind : 4; ParseErrorType type : 2; const char* arg; }; - enum TargetProduction { - ExpressionProduction = 1 << 0, - FormalParameterInitializerProduction = 1 << 1, - BindingPatternProduction = 1 << 2, - AssignmentPatternProduction = 1 << 3, - DistinctFormalParametersProduction = 1 << 4, - StrictModeFormalParametersProduction = 1 << 5, - ArrowFormalParametersProduction = 1 << 6, - LetPatternProduction = 1 << 7, - CoverInitializedNameProduction = 1 << 8, + enum TargetProduction : unsigned { +#define DEFINE_PRODUCTION(NAME, CODE) NAME = 1 << CODE, + ERROR_CODES(DEFINE_PRODUCTION) +#undef DEFINE_PRODUCTION ExpressionProductions = (ExpressionProduction | FormalParameterInitializerProduction), @@ -52,102 +72,121 @@ class ExpressionClassifier { ArrowFormalParametersProduction | CoverInitializedNameProduction) }; - enum FunctionProperties { NonSimpleParameter = 1 << 0 }; + enum FunctionProperties : unsigned { + NonSimpleParameter = 1 << 0 + }; explicit ExpressionClassifier(const Traits* t) : zone_(t->zone()), non_patterns_to_rewrite_(t->GetNonPatternList()), + reported_errors_(t->GetReportedErrorList()), + duplicate_finder_(nullptr), invalid_productions_(0), - function_properties_(0), - duplicate_finder_(nullptr) { + function_properties_(0) { + reported_errors_begin_ = reported_errors_end_ = reported_errors_->length(); non_pattern_begin_ = non_patterns_to_rewrite_->length(); } ExpressionClassifier(const Traits* t, DuplicateFinder* duplicate_finder) : zone_(t->zone()), non_patterns_to_rewrite_(t->GetNonPatternList()), + reported_errors_(t->GetReportedErrorList()), + duplicate_finder_(duplicate_finder), invalid_productions_(0), - function_properties_(0), - duplicate_finder_(duplicate_finder) { + function_properties_(0) { + reported_errors_begin_ = reported_errors_end_ = reported_errors_->length(); non_pattern_begin_ = non_patterns_to_rewrite_->length(); } ~ExpressionClassifier() { Discard(); } - bool is_valid(unsigned productions) const { + V8_INLINE bool is_valid(unsigned productions) const { return (invalid_productions_ & productions) == 0; } - DuplicateFinder* duplicate_finder() const { return duplicate_finder_; } + V8_INLINE DuplicateFinder* duplicate_finder() const { + return duplicate_finder_; + } - bool is_valid_expression() const { return is_valid(ExpressionProduction); } + V8_INLINE bool is_valid_expression() const { + return is_valid(ExpressionProduction); + } - bool is_valid_formal_parameter_initializer() const { + V8_INLINE bool is_valid_formal_parameter_initializer() const { return is_valid(FormalParameterInitializerProduction); } - bool is_valid_binding_pattern() const { + V8_INLINE bool is_valid_binding_pattern() const { return is_valid(BindingPatternProduction); } - bool is_valid_assignment_pattern() const { + V8_INLINE bool is_valid_assignment_pattern() const { return is_valid(AssignmentPatternProduction); } - bool is_valid_arrow_formal_parameters() const { + V8_INLINE bool is_valid_arrow_formal_parameters() const { return is_valid(ArrowFormalParametersProduction); } - bool is_valid_formal_parameter_list_without_duplicates() const { + V8_INLINE bool is_valid_formal_parameter_list_without_duplicates() const { return is_valid(DistinctFormalParametersProduction); } // Note: callers should also check // is_valid_formal_parameter_list_without_duplicates(). - bool is_valid_strict_mode_formal_parameters() const { + V8_INLINE bool is_valid_strict_mode_formal_parameters() const { return is_valid(StrictModeFormalParametersProduction); } - bool is_valid_let_pattern() const { return is_valid(LetPatternProduction); } + V8_INLINE bool is_valid_let_pattern() const { + return is_valid(LetPatternProduction); + } - const Error& expression_error() const { return expression_error_; } + V8_INLINE const Error& expression_error() const { + return reported_error(kExpressionProduction); + } - const Error& formal_parameter_initializer_error() const { - return formal_parameter_initializer_error_; + V8_INLINE const Error& formal_parameter_initializer_error() const { + return reported_error(kFormalParameterInitializerProduction); } - const Error& binding_pattern_error() const { return binding_pattern_error_; } + V8_INLINE const Error& binding_pattern_error() const { + return reported_error(kBindingPatternProduction); + } - const Error& assignment_pattern_error() const { - return assignment_pattern_error_; + V8_INLINE const Error& assignment_pattern_error() const { + return reported_error(kAssignmentPatternProduction); } - const Error& arrow_formal_parameters_error() const { - return arrow_formal_parameters_error_; + V8_INLINE const Error& arrow_formal_parameters_error() const { + return reported_error(kArrowFormalParametersProduction); } - const Error& duplicate_formal_parameter_error() const { - return duplicate_formal_parameter_error_; + V8_INLINE const Error& duplicate_formal_parameter_error() const { + return reported_error(kDistinctFormalParametersProduction); } - const Error& strict_mode_formal_parameter_error() const { - return strict_mode_formal_parameter_error_; + V8_INLINE const Error& strict_mode_formal_parameter_error() const { + return reported_error(kStrictModeFormalParametersProduction); } - const Error& let_pattern_error() const { return let_pattern_error_; } + V8_INLINE const Error& let_pattern_error() const { + return reported_error(kLetPatternProduction); + } - bool has_cover_initialized_name() const { + V8_INLINE bool has_cover_initialized_name() const { return !is_valid(CoverInitializedNameProduction); } - const Error& cover_initialized_name_error() const { - return cover_initialized_name_error_; + + V8_INLINE const Error& cover_initialized_name_error() const { + return reported_error(kCoverInitializedNameProduction); } - bool is_simple_parameter_list() const { + V8_INLINE bool is_simple_parameter_list() const { return !(function_properties_ & NonSimpleParameter); } - void RecordNonSimpleParameter() { + V8_INLINE void RecordNonSimpleParameter() { function_properties_ |= NonSimpleParameter; } @@ -156,9 +195,7 @@ class ExpressionClassifier { const char* arg = nullptr) { if (!is_valid_expression()) return; invalid_productions_ |= ExpressionProduction; - expression_error_.location = loc; - expression_error_.message = message; - expression_error_.arg = arg; + Add(Error(loc, message, kExpressionProduction, arg)); } void RecordExpressionError(const Scanner::Location& loc, @@ -166,10 +203,7 @@ class ExpressionClassifier { ParseErrorType type, const char* arg = nullptr) { if (!is_valid_expression()) return; invalid_productions_ |= ExpressionProduction; - expression_error_.location = loc; - expression_error_.message = message; - expression_error_.arg = arg; - expression_error_.type = type; + Add(Error(loc, message, kExpressionProduction, arg, type)); } void RecordFormalParameterInitializerError(const Scanner::Location& loc, @@ -177,9 +211,7 @@ class ExpressionClassifier { const char* arg = nullptr) { if (!is_valid_formal_parameter_initializer()) return; invalid_productions_ |= FormalParameterInitializerProduction; - formal_parameter_initializer_error_.location = loc; - formal_parameter_initializer_error_.message = message; - formal_parameter_initializer_error_.arg = arg; + Add(Error(loc, message, kFormalParameterInitializerProduction, arg)); } void RecordBindingPatternError(const Scanner::Location& loc, @@ -187,9 +219,7 @@ class ExpressionClassifier { const char* arg = nullptr) { if (!is_valid_binding_pattern()) return; invalid_productions_ |= BindingPatternProduction; - binding_pattern_error_.location = loc; - binding_pattern_error_.message = message; - binding_pattern_error_.arg = arg; + Add(Error(loc, message, kBindingPatternProduction, arg)); } void RecordAssignmentPatternError(const Scanner::Location& loc, @@ -197,9 +227,7 @@ class ExpressionClassifier { const char* arg = nullptr) { if (!is_valid_assignment_pattern()) return; invalid_productions_ |= AssignmentPatternProduction; - assignment_pattern_error_.location = loc; - assignment_pattern_error_.message = message; - assignment_pattern_error_.arg = arg; + Add(Error(loc, message, kAssignmentPatternProduction, arg)); } void RecordPatternError(const Scanner::Location& loc, @@ -214,17 +242,14 @@ class ExpressionClassifier { const char* arg = nullptr) { if (!is_valid_arrow_formal_parameters()) return; invalid_productions_ |= ArrowFormalParametersProduction; - arrow_formal_parameters_error_.location = loc; - arrow_formal_parameters_error_.message = message; - arrow_formal_parameters_error_.arg = arg; + Add(Error(loc, message, kArrowFormalParametersProduction, arg)); } void RecordDuplicateFormalParameterError(const Scanner::Location& loc) { if (!is_valid_formal_parameter_list_without_duplicates()) return; invalid_productions_ |= DistinctFormalParametersProduction; - duplicate_formal_parameter_error_.location = loc; - duplicate_formal_parameter_error_.message = MessageTemplate::kParamDupe; - duplicate_formal_parameter_error_.arg = nullptr; + Add(Error(loc, MessageTemplate::kParamDupe, + kDistinctFormalParametersProduction)); } // Record a binding that would be invalid in strict mode. Confusingly this @@ -235,9 +260,7 @@ class ExpressionClassifier { const char* arg = nullptr) { if (!is_valid_strict_mode_formal_parameters()) return; invalid_productions_ |= StrictModeFormalParametersProduction; - strict_mode_formal_parameter_error_.location = loc; - strict_mode_formal_parameter_error_.message = message; - strict_mode_formal_parameter_error_.arg = arg; + Add(Error(loc, message, kStrictModeFormalParametersProduction, arg)); } void RecordLetPatternError(const Scanner::Location& loc, @@ -245,9 +268,7 @@ class ExpressionClassifier { const char* arg = nullptr) { if (!is_valid_let_pattern()) return; invalid_productions_ |= LetPatternProduction; - let_pattern_error_.location = loc; - let_pattern_error_.message = message; - let_pattern_error_.arg = arg; + Add(Error(loc, message, kLetPatternProduction, arg)); } void RecordCoverInitializedNameError(const Scanner::Location& loc, @@ -255,76 +276,102 @@ class ExpressionClassifier { const char* arg = nullptr) { if (has_cover_initialized_name()) return; invalid_productions_ |= CoverInitializedNameProduction; - cover_initialized_name_error_.location = loc; - cover_initialized_name_error_.message = message; - cover_initialized_name_error_.arg = arg; + Add(Error(loc, message, kCoverInitializedNameProduction, arg)); } void ForgiveCoverInitializedNameError() { + if (!(invalid_productions_ & CoverInitializedNameProduction)) return; + Error& e = reported_error(kCoverInitializedNameProduction); + e.kind = kUnusedError; invalid_productions_ &= ~CoverInitializedNameProduction; - cover_initialized_name_error_ = Error(); } void ForgiveAssignmentPatternError() { + if (!(invalid_productions_ & AssignmentPatternProduction)) return; + Error& e = reported_error(kAssignmentPatternProduction); + e.kind = kUnusedError; invalid_productions_ &= ~AssignmentPatternProduction; - assignment_pattern_error_ = Error(); } void Accumulate(ExpressionClassifier* inner, unsigned productions = StandardProductions, bool merge_non_patterns = true) { + DCHECK_EQ(inner->reported_errors_, reported_errors_); + DCHECK_EQ(inner->reported_errors_begin_, reported_errors_end_); + DCHECK_EQ(inner->reported_errors_end_, reported_errors_->length()); if (merge_non_patterns) MergeNonPatterns(inner); // Propagate errors from inner, but don't overwrite already recorded // errors. unsigned non_arrow_inner_invalid_productions = inner->invalid_productions_ & ~ArrowFormalParametersProduction; - if (non_arrow_inner_invalid_productions == 0) return; - unsigned non_arrow_productions = - productions & ~ArrowFormalParametersProduction; - unsigned errors = - non_arrow_productions & non_arrow_inner_invalid_productions; - errors &= ~invalid_productions_; - if (errors != 0) { - invalid_productions_ |= errors; - if (errors & ExpressionProduction) - expression_error_ = inner->expression_error_; - if (errors & FormalParameterInitializerProduction) - formal_parameter_initializer_error_ = - inner->formal_parameter_initializer_error_; - if (errors & BindingPatternProduction) - binding_pattern_error_ = inner->binding_pattern_error_; - if (errors & AssignmentPatternProduction) - assignment_pattern_error_ = inner->assignment_pattern_error_; - if (errors & DistinctFormalParametersProduction) - duplicate_formal_parameter_error_ = - inner->duplicate_formal_parameter_error_; - if (errors & StrictModeFormalParametersProduction) - strict_mode_formal_parameter_error_ = - inner->strict_mode_formal_parameter_error_; - if (errors & LetPatternProduction) - let_pattern_error_ = inner->let_pattern_error_; - if (errors & CoverInitializedNameProduction) - cover_initialized_name_error_ = inner->cover_initialized_name_error_; - } - - // As an exception to the above, the result continues to be a valid arrow - // formal parameters if the inner expression is a valid binding pattern. - if (productions & ArrowFormalParametersProduction && - is_valid_arrow_formal_parameters()) { - // Also copy function properties if expecting an arrow function - // parameter. - function_properties_ |= inner->function_properties_; - - if (!inner->is_valid_binding_pattern()) { - invalid_productions_ |= ArrowFormalParametersProduction; - arrow_formal_parameters_error_ = inner->binding_pattern_error_; + if (non_arrow_inner_invalid_productions) { + unsigned errors = non_arrow_inner_invalid_productions & productions & + ~invalid_productions_; + // The result will continue to be a valid arrow formal parameters if the + // inner expression is a valid binding pattern. + bool copy_BP_to_AFP = false; + if (productions & ArrowFormalParametersProduction && + is_valid_arrow_formal_parameters()) { + // Also copy function properties if expecting an arrow function + // parameter. + function_properties_ |= inner->function_properties_; + if (!inner->is_valid_binding_pattern()) { + copy_BP_to_AFP = true; + invalid_productions_ |= ArrowFormalParametersProduction; + } + } + // Traverse the list of errors reported by the inner classifier + // to copy what's necessary. + if (errors != 0 || copy_BP_to_AFP) { + invalid_productions_ |= errors; + int binding_pattern_index = inner->reported_errors_end_; + for (int i = inner->reported_errors_begin_; + i < inner->reported_errors_end_; i++) { + int k = reported_errors_->at(i).kind; + if (errors & (1 << k)) Copy(i); + // Check if it's a BP error that has to be copied to an AFP error. + if (k == kBindingPatternProduction && copy_BP_to_AFP) { + if (reported_errors_end_ <= i) { + // If the BP error itself has not already been copied, + // copy it now and change it to an AFP error. + Copy(i); + reported_errors_->at(reported_errors_end_-1).kind = + kArrowFormalParametersProduction; + } else { + // Otherwise, if the BP error was already copied, keep its + // position and wait until the end of the traversal. + DCHECK_EQ(reported_errors_end_, i+1); + binding_pattern_index = i; + } + } + } + // Do we still have to copy the BP error to an AFP error? + if (binding_pattern_index < inner->reported_errors_end_) { + // If there's still unused space in the list of the inner + // classifier, copy it there, otherwise add it to the end + // of the list. + if (reported_errors_end_ < inner->reported_errors_end_) + Copy(binding_pattern_index); + else + Add(reported_errors_->at(binding_pattern_index)); + reported_errors_->at(reported_errors_end_-1).kind = + kArrowFormalParametersProduction; + } } } + reported_errors_->Rewind(reported_errors_end_); + inner->reported_errors_begin_ = inner->reported_errors_end_ = + reported_errors_end_; } V8_INLINE int GetNonPatternBegin() const { return non_pattern_begin_; } V8_INLINE void Discard() { + if (reported_errors_end_ == reported_errors_->length()) { + reported_errors_->Rewind(reported_errors_begin_); + reported_errors_end_ = reported_errors_begin_; + } + DCHECK_EQ(reported_errors_begin_, reported_errors_end_); DCHECK_LE(non_pattern_begin_, non_patterns_to_rewrite_->length()); non_patterns_to_rewrite_->Rewind(non_pattern_begin_); } @@ -335,24 +382,70 @@ class ExpressionClassifier { } private: + V8_INLINE Error& reported_error(ErrorKind kind) const { + if (invalid_productions_ & (1 << kind)) { + for (int i = reported_errors_begin_; i < reported_errors_end_; i++) { + if (reported_errors_->at(i).kind == kind) + return reported_errors_->at(i); + } + UNREACHABLE(); + } + // We should only be looking for an error when we know that one has + // been reported. But we're not... So this is to make sure we have + // the same behaviour. + static Error none; + return none; + } + + // Adds e to the end of the list of reported errors for this classifier. + // It is expected that this classifier is the last one in the stack. + V8_INLINE void Add(const Error& e) { + DCHECK_EQ(reported_errors_end_, reported_errors_->length()); + reported_errors_->Add(e, zone_); + reported_errors_end_++; + } + + // Copies the error at position i of the list of reported errors, so that + // it becomes the last error reported for this classifier. Position i + // could be either after the existing errors of this classifier (i.e., + // in an inner classifier) or it could be an existing error (in case a + // copy is needed). + V8_INLINE void Copy(int i) { + DCHECK_LE(reported_errors_end_, i); + DCHECK_LT(i, reported_errors_->length()); + if (reported_errors_end_ != i) + reported_errors_->at(reported_errors_end_) = reported_errors_->at(i); + reported_errors_end_++; + } + Zone* zone_; ZoneList* non_patterns_to_rewrite_; - int non_pattern_begin_; - unsigned invalid_productions_; - unsigned function_properties_; - Error expression_error_; - Error formal_parameter_initializer_error_; - Error binding_pattern_error_; - Error assignment_pattern_error_; - Error arrow_formal_parameters_error_; - Error duplicate_formal_parameter_error_; - Error strict_mode_formal_parameter_error_; - Error let_pattern_error_; - Error cover_initialized_name_error_; + ZoneList* reported_errors_; DuplicateFinder* duplicate_finder_; + // The uint16_t for non_pattern_begin_ will not be enough in the case, + // e.g., of an array literal containing more than 64K inner array + // literals with spreads, as in: + // var N=65536; eval("var x=[];" + "[" + "[...x],".repeat(N) + "].length"); + // An implementation limit error in ParserBase::AddNonPatternForRewriting + // will be triggered in this case. + uint16_t non_pattern_begin_; + unsigned invalid_productions_ : 14; + unsigned function_properties_ : 2; + // The uint16_t for reported_errors_begin_ and reported_errors_end_ will + // not be enough in the case of a long series of expressions using nested + // classifiers, e.g., a long sequence of assignments, as in: + // literals with spreads, as in: + // var N=65536; eval("var x;" + "x=".repeat(N) + "42"); + // This should not be a problem, as such things currently fail with a + // stack overflow while parsing. + uint16_t reported_errors_begin_; + uint16_t reported_errors_end_; }; +#undef ERROR_CODES + + } // namespace internal } // namespace v8 diff --git a/deps/v8/src/parsing/parser-base.h b/deps/v8/src/parsing/parser-base.h index dde6b1dd863627..0eb19ceb83b13a 100644 --- a/deps/v8/src/parsing/parser-base.h +++ b/deps/v8/src/parsing/parser-base.h @@ -247,8 +247,8 @@ class ParserBase : public Traits { typename Traits::Type::Factory* factory() { return factory_; } - const List& destructuring_assignments_to_rewrite() - const { + const ZoneList& + destructuring_assignments_to_rewrite() const { return destructuring_assignments_to_rewrite_; } @@ -268,19 +268,26 @@ class ParserBase : public Traits { collect_expressions_in_tail_position_ = collect; } + ZoneList* GetReportedErrorList() { + return &reported_errors_; + } + ZoneList* non_patterns_to_rewrite() { return &non_patterns_to_rewrite_; } private: void AddDestructuringAssignment(DestructuringAssignment pair) { - destructuring_assignments_to_rewrite_.Add(pair); + destructuring_assignments_to_rewrite_.Add(pair, (*scope_stack_)->zone()); } V8_INLINE Scope* scope() { return *scope_stack_; } - void AddNonPatternForRewriting(ExpressionT expr) { + void AddNonPatternForRewriting(ExpressionT expr, bool* ok) { non_patterns_to_rewrite_.Add(expr, (*scope_stack_)->zone()); + if (non_patterns_to_rewrite_.length() >= + std::numeric_limits::max()) + *ok = false; } // Used to assign an index to each literal that needs materialization in @@ -311,11 +318,13 @@ class ParserBase : public Traits { Scope** scope_stack_; Scope* outer_scope_; - List destructuring_assignments_to_rewrite_; + ZoneList destructuring_assignments_to_rewrite_; List expressions_in_tail_position_; bool collect_expressions_in_tail_position_; ZoneList non_patterns_to_rewrite_; + ZoneList reported_errors_; + typename Traits::Type::Factory* factory_; friend class ParserTraits; @@ -945,8 +954,10 @@ ParserBase::FunctionState::FunctionState( outer_function_state_(*function_state_stack), scope_stack_(scope_stack), outer_scope_(*scope_stack), + destructuring_assignments_to_rewrite_(16, scope->zone()), collect_expressions_in_tail_position_(true), non_patterns_to_rewrite_(0, scope->zone()), + reported_errors_(16, scope->zone()), factory_(factory) { *scope_stack_ = scope; *function_state_stack = this; @@ -1274,12 +1285,11 @@ ParserBase::ParsePrimaryExpression(ExpressionClassifier* classifier, // Parentheses are not valid on the LHS of a BindingPattern, so we use the // is_valid_binding_pattern() check to detect multiple levels of // parenthesization. - if (!classifier->is_valid_binding_pattern()) { - ArrowFormalParametersUnexpectedToken(classifier); - } + bool pattern_error = !classifier->is_valid_binding_pattern(); classifier->RecordPatternError(scanner()->peek_location(), MessageTemplate::kUnexpectedToken, Token::String(Token::LPAREN)); + if (pattern_error) ArrowFormalParametersUnexpectedToken(classifier); Consume(Token::LPAREN); if (Check(Token::RPAREN)) { // ()=>x. The continuation that looks for the => is in @@ -1416,6 +1426,7 @@ typename ParserBase::ExpressionT ParserBase::ParseExpression( seen_rest = is_rest = true; } int pos = position(), expr_pos = peek_position(); + ExpressionClassifier binding_classifier(this); ExpressionT right = this->ParseAssignmentExpression( accept_IN, &binding_classifier, CHECK_OK); classifier->Accumulate(&binding_classifier, @@ -1501,7 +1512,15 @@ typename ParserBase::ExpressionT ParserBase::ParseArrayLiteral( literal_index, pos); if (first_spread_index >= 0) { result = factory()->NewRewritableExpression(result); - Traits::QueueNonPatternForRewriting(result); + Traits::QueueNonPatternForRewriting(result, ok); + if (!*ok) { + // If the non-pattern rewriting mechanism is used in the future for + // rewriting other things than spreads, this error message will have + // to change. Also, this error message will never appear while pre- + // parsing (this is OK, as it is an implementation limitation). + ReportMessage(MessageTemplate::kTooManySpreads); + return this->EmptyExpression(); + } } return result; } @@ -1907,9 +1926,7 @@ ParserBase::ParseAssignmentExpression(bool accept_IN, ExpressionT expression = this->ParseConditionalExpression( accept_IN, &arrow_formals_classifier, CHECK_OK); if (peek() == Token::ARROW) { - classifier->RecordPatternError(scanner()->peek_location(), - MessageTemplate::kUnexpectedToken, - Token::String(Token::ARROW)); + Scanner::Location arrow_loc = scanner()->peek_location(); ValidateArrowFormalParameters(&arrow_formals_classifier, expression, parenthesized_formals, CHECK_OK); // This reads strangely, but is correct: it checks whether any @@ -1944,6 +1961,10 @@ ParserBase::ParseAssignmentExpression(bool accept_IN, } expression = this->ParseArrowFunctionLiteral( accept_IN, parameters, arrow_formals_classifier, CHECK_OK); + arrow_formals_classifier.Discard(); + classifier->RecordPatternError(arrow_loc, + MessageTemplate::kUnexpectedToken, + Token::String(Token::ARROW)); if (fni_ != nullptr) fni_->Infer(); @@ -2113,8 +2134,8 @@ ParserBase::ParseConditionalExpression(bool accept_IN, this->ParseBinaryExpression(4, accept_IN, classifier, CHECK_OK); if (peek() != Token::CONDITIONAL) return expression; Traits::RewriteNonPattern(classifier, CHECK_OK); - ArrowFormalParametersUnexpectedToken(classifier); BindingPatternUnexpectedToken(classifier); + ArrowFormalParametersUnexpectedToken(classifier); Consume(Token::CONDITIONAL); // In parsing the first assignment expression in conditional // expressions we always accept the 'in' keyword; see ECMA-262, diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc index 48837f0ad62e27..bbb75de3ea3dab 100644 --- a/deps/v8/src/parsing/parser.cc +++ b/deps/v8/src/parsing/parser.cc @@ -2439,7 +2439,6 @@ Statement* Parser::ParseExpressionOrLabelledStatement( ReportUnexpectedToken(Next()); *ok = false; return nullptr; - default: break; } @@ -5405,13 +5404,19 @@ void ParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier, } -Zone* ParserTraits::zone() const { - return parser_->function_state_->scope()->zone(); +ZoneList* ParserTraits::GetNonPatternList() const { + return parser_->function_state_->non_patterns_to_rewrite(); } -ZoneList* ParserTraits::GetNonPatternList() const { - return parser_->function_state_->non_patterns_to_rewrite(); +ZoneList* +ParserTraits::GetReportedErrorList() const { + return parser_->function_state_->GetReportedErrorList(); +} + + +Zone* ParserTraits::zone() const { + return parser_->function_state_->scope()->zone(); } @@ -5628,9 +5633,9 @@ void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { } -void ParserTraits::QueueNonPatternForRewriting(Expression* expr) { +void ParserTraits::QueueNonPatternForRewriting(Expression* expr, bool* ok) { DCHECK(expr->IsRewritableExpression()); - parser_->function_state_->AddNonPatternForRewriting(expr); + parser_->function_state_->AddNonPatternForRewriting(expr, ok); } diff --git a/deps/v8/src/parsing/parser.h b/deps/v8/src/parsing/parser.h index 5df11e77a01337..a62ffbe72b3032 100644 --- a/deps/v8/src/parsing/parser.h +++ b/deps/v8/src/parsing/parser.h @@ -646,7 +646,7 @@ class ParserTraits { V8_INLINE void QueueDestructuringAssignmentForRewriting( Expression* assignment); - V8_INLINE void QueueNonPatternForRewriting(Expression* expr); + V8_INLINE void QueueNonPatternForRewriting(Expression* expr, bool* ok); void SetFunctionNameFromPropertyName(ObjectLiteralProperty* property, const AstRawString* name); @@ -658,6 +658,8 @@ class ParserTraits { V8_INLINE void RewriteNonPattern(Type::ExpressionClassifier* classifier, bool* ok); + V8_INLINE ZoneList* + GetReportedErrorList() const; V8_INLINE Zone* zone() const; V8_INLINE ZoneList* GetNonPatternList() const; diff --git a/deps/v8/src/parsing/preparser.h b/deps/v8/src/parsing/preparser.h index f2f69517b25b42..1c6c7e6d6fed45 100644 --- a/deps/v8/src/parsing/preparser.h +++ b/deps/v8/src/parsing/preparser.h @@ -916,7 +916,7 @@ class PreParserTraits { } inline void QueueDestructuringAssignmentForRewriting(PreParserExpression) {} - inline void QueueNonPatternForRewriting(PreParserExpression) {} + inline void QueueNonPatternForRewriting(PreParserExpression, bool* ok) {} void SetFunctionNameFromPropertyName(PreParserExpression, PreParserIdentifier) {} @@ -926,6 +926,8 @@ class PreParserTraits { inline void RewriteNonPattern(Type::ExpressionClassifier* classifier, bool* ok); + V8_INLINE ZoneList* + GetReportedErrorList() const; V8_INLINE Zone* zone() const; V8_INLINE ZoneList* GetNonPatternList() const; @@ -1126,13 +1128,19 @@ void PreParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier, } -Zone* PreParserTraits::zone() const { - return pre_parser_->function_state_->scope()->zone(); +ZoneList* PreParserTraits::GetNonPatternList() const { + return pre_parser_->function_state_->non_patterns_to_rewrite(); } -ZoneList* PreParserTraits::GetNonPatternList() const { - return pre_parser_->function_state_->non_patterns_to_rewrite(); +ZoneList* +PreParserTraits::GetReportedErrorList() const { + return pre_parser_->function_state_->GetReportedErrorList(); +} + + +Zone* PreParserTraits::zone() const { + return pre_parser_->function_state_->scope()->zone(); }