diff options
author | Michaël Zasso <targos@protonmail.com> | 2018-03-07 08:54:53 +0100 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2018-03-07 16:48:52 +0100 |
commit | 88786fecff336342a56e6f2e7ff3b286be716e47 (patch) | |
tree | 92e6ba5b8ac8dae1a058988d20c9d27bfa654390 /deps/v8/src/parsing | |
parent | 4e86f9b5ab83cbabf43839385bf383e6a7ef7d19 (diff) | |
download | node-new-88786fecff336342a56e6f2e7ff3b286be716e47.tar.gz |
deps: update V8 to 6.5.254.31
PR-URL: https://github.com/nodejs/node/pull/18453
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Yang Guo <yangguo@chromium.org>
Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Diffstat (limited to 'deps/v8/src/parsing')
-rw-r--r-- | deps/v8/src/parsing/background-parsing-task.cc | 3 | ||||
-rw-r--r-- | deps/v8/src/parsing/expression-classifier.h | 25 | ||||
-rw-r--r-- | deps/v8/src/parsing/expression-scope-reparenter.cc | 8 | ||||
-rw-r--r-- | deps/v8/src/parsing/parse-info.cc | 14 | ||||
-rw-r--r-- | deps/v8/src/parsing/parse-info.h | 10 | ||||
-rw-r--r-- | deps/v8/src/parsing/parser-base.h | 387 | ||||
-rw-r--r-- | deps/v8/src/parsing/parser.cc | 350 | ||||
-rw-r--r-- | deps/v8/src/parsing/parser.h | 54 | ||||
-rw-r--r-- | deps/v8/src/parsing/pattern-rewriter.cc | 10 | ||||
-rw-r--r-- | deps/v8/src/parsing/preparsed-scope-data.cc | 6 | ||||
-rw-r--r-- | deps/v8/src/parsing/preparser.cc | 20 | ||||
-rw-r--r-- | deps/v8/src/parsing/preparser.h | 25 | ||||
-rw-r--r-- | deps/v8/src/parsing/rewriter.cc | 4 | ||||
-rw-r--r-- | deps/v8/src/parsing/scanner-character-streams.cc | 57 | ||||
-rw-r--r-- | deps/v8/src/parsing/scanner.cc | 117 | ||||
-rw-r--r-- | deps/v8/src/parsing/scanner.h | 17 | ||||
-rw-r--r-- | deps/v8/src/parsing/token.h | 1 |
17 files changed, 581 insertions, 527 deletions
diff --git a/deps/v8/src/parsing/background-parsing-task.cc b/deps/v8/src/parsing/background-parsing-task.cc index 387cd3a1c6..cb811566df 100644 --- a/deps/v8/src/parsing/background-parsing-task.cc +++ b/deps/v8/src/parsing/background-parsing-task.cc @@ -31,7 +31,8 @@ BackgroundParsingTask::BackgroundParsingTask( DCHECK(options == ScriptCompiler::kProduceParserCache || options == ScriptCompiler::kProduceCodeCache || options == ScriptCompiler::kProduceFullCodeCache || - options == ScriptCompiler::kNoCompileOptions); + options == ScriptCompiler::kNoCompileOptions || + options == ScriptCompiler::kEagerCompile); VMState<PARSER> state(isolate); diff --git a/deps/v8/src/parsing/expression-classifier.h b/deps/v8/src/parsing/expression-classifier.h index 6c6c813b3e..709d5736b5 100644 --- a/deps/v8/src/parsing/expression-classifier.h +++ b/deps/v8/src/parsing/expression-classifier.h @@ -97,14 +97,12 @@ class ExpressionClassifier { : base_(base), previous_(base->classifier_), zone_(base->impl()->zone()), - non_patterns_to_rewrite_(base->impl()->GetNonPatternList()), reported_errors_(base->impl()->GetReportedErrorList()), duplicate_finder_(duplicate_finder), invalid_productions_(0), function_properties_(0) { base->classifier_ = this; reported_errors_begin_ = reported_errors_end_ = reported_errors_->length(); - non_pattern_begin_ = non_patterns_to_rewrite_->length(); } V8_INLINE ~ExpressionClassifier() { @@ -291,19 +289,10 @@ class ExpressionClassifier { Add(Error(loc, message, kLetPatternProduction, arg)); } - void Accumulate(ExpressionClassifier* inner, unsigned productions, - bool merge_non_patterns = true) { + void Accumulate(ExpressionClassifier* inner, unsigned productions) { 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()); - DCHECK_EQ(inner->non_patterns_to_rewrite_, non_patterns_to_rewrite_); - DCHECK_LE(non_pattern_begin_, inner->non_pattern_begin_); - DCHECK_LE(inner->non_pattern_begin_, non_patterns_to_rewrite_->length()); - // Merge non-patterns from the inner classifier, or discard them. - if (merge_non_patterns) - inner->non_pattern_begin_ = non_patterns_to_rewrite_->length(); - else - non_patterns_to_rewrite_->Rewind(inner->non_pattern_begin_); // Propagate errors from inner, but don't overwrite already recorded // errors. unsigned non_arrow_inner_invalid_productions = @@ -368,16 +357,12 @@ class ExpressionClassifier { 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_); } ExpressionClassifier* previous() const { return previous_; } @@ -424,16 +409,8 @@ class ExpressionClassifier { typename Types::Base* base_; ExpressionClassifier* previous_; Zone* zone_; - ZoneList<typename Types::RewritableExpression>* non_patterns_to_rewrite_; ZoneList<Error>* 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 diff --git a/deps/v8/src/parsing/expression-scope-reparenter.cc b/deps/v8/src/parsing/expression-scope-reparenter.cc index 18c52add11..bdb0aeadd6 100644 --- a/deps/v8/src/parsing/expression-scope-reparenter.cc +++ b/deps/v8/src/parsing/expression-scope-reparenter.cc @@ -85,7 +85,7 @@ void Reparenter::VisitRewritableExpression(RewritableExpression* expr) { } void Reparenter::VisitBlock(Block* stmt) { - if (stmt->scope() != nullptr) + if (stmt->scope()) stmt->scope()->ReplaceOuterScope(scope_); else VisitStatements(stmt->statements()); @@ -93,7 +93,11 @@ void Reparenter::VisitBlock(Block* stmt) { void Reparenter::VisitTryCatchStatement(TryCatchStatement* stmt) { Visit(stmt->try_block()); - stmt->scope()->ReplaceOuterScope(scope_); + if (stmt->scope()) { + stmt->scope()->ReplaceOuterScope(scope_); + } else { + Visit(stmt->catch_block()); + } } void Reparenter::VisitWithStatement(WithStatement* stmt) { diff --git a/deps/v8/src/parsing/parse-info.cc b/deps/v8/src/parsing/parse-info.cc index 1c9d648a1e..b8f191dd5a 100644 --- a/deps/v8/src/parsing/parse-info.cc +++ b/deps/v8/src/parsing/parse-info.cc @@ -45,7 +45,13 @@ ParseInfo::ParseInfo(Handle<SharedFunctionInfo> shared) Isolate* isolate = shared->GetIsolate(); InitFromIsolate(isolate); + // Do not support re-parsing top-level function of a wrapped script. + // TODO(yangguo): consider whether we need a top-level function in a + // wrapped script at all. + DCHECK_IMPLIES(is_toplevel(), !Script::cast(shared->script())->is_wrapped()); + set_toplevel(shared->is_toplevel()); + set_wrapped_as_function(shared->is_wrapped()); set_allow_lazy_parsing(FLAG_lazy_inner_functions); set_is_named_expression(shared->is_named_expression()); set_compiler_hints(shared->compiler_hints()); @@ -54,8 +60,6 @@ ParseInfo::ParseInfo(Handle<SharedFunctionInfo> shared) function_literal_id_ = shared->function_literal_id(); set_language_mode(shared->language_mode()); set_asm_wasm_broken(shared->is_asm_wasm_broken()); - set_requires_instance_fields_initializer( - shared->requires_instance_fields_initializer()); Handle<Script> script(Script::cast(shared->script())); set_script(script); @@ -90,6 +94,7 @@ ParseInfo::ParseInfo(Handle<Script> script) set_allow_lazy_parsing(); set_toplevel(); set_script(script); + set_wrapped_as_function(script->is_wrapped()); set_native(script->type() == Script::TYPE_NATIVE); set_eval(script->compilation_type() == Script::COMPILATION_TYPE_EVAL); @@ -151,6 +156,11 @@ FunctionKind ParseInfo::function_kind() const { return SharedFunctionInfo::FunctionKindBits::decode(compiler_hints_); } +bool ParseInfo::requires_instance_fields_initializer() const { + return SharedFunctionInfo::RequiresInstanceFieldsInitializer::decode( + compiler_hints_); +} + void ParseInfo::InitFromIsolate(Isolate* isolate) { DCHECK_NOT_NULL(isolate); set_hash_seed(isolate->heap()->HashSeed()); diff --git a/deps/v8/src/parsing/parse-info.h b/deps/v8/src/parsing/parse-info.h index 9deea1ecac..e93c7137ca 100644 --- a/deps/v8/src/parsing/parse-info.h +++ b/deps/v8/src/parsing/parse-info.h @@ -79,13 +79,12 @@ class V8_EXPORT_PRIVATE ParseInfo { FLAG_ACCESSOR(kCollectTypeProfile, collect_type_profile, set_collect_type_profile) FLAG_ACCESSOR(kIsAsmWasmBroken, is_asm_wasm_broken, set_asm_wasm_broken) - FLAG_ACCESSOR(kRequiresInstanceFieldsInitializer, - requires_instance_fields_initializer, - set_requires_instance_fields_initializer) FLAG_ACCESSOR(kBlockCoverageEnabled, block_coverage_enabled, set_block_coverage_enabled) FLAG_ACCESSOR(kOnBackgroundThread, on_background_thread, set_on_background_thread) + FLAG_ACCESSOR(kWrappedAsFunction, is_wrapped_as_function, + set_wrapped_as_function) #undef FLAG_ACCESSOR void set_parse_restriction(ParseRestriction restriction) { @@ -208,6 +207,7 @@ class V8_EXPORT_PRIVATE ParseInfo { // Getters for individual compiler hints. bool is_declaration() const; FunctionKind function_kind() const; + bool requires_instance_fields_initializer() const; //-------------------------------------------------------------------------- // TODO(titzer): these should not be part of ParseInfo. @@ -261,8 +261,8 @@ class V8_EXPORT_PRIVATE ParseInfo { kCollectTypeProfile = 1 << 10, kBlockCoverageEnabled = 1 << 11, kIsAsmWasmBroken = 1 << 12, - kRequiresInstanceFieldsInitializer = 1 << 13, - kOnBackgroundThread = 1 << 14, + kOnBackgroundThread = 1 << 13, + kWrappedAsFunction = 1 << 14, // Implicitly wrapped as function. }; //------------- Inputs to parsing and scope analysis ----------------------- diff --git a/deps/v8/src/parsing/parser-base.h b/deps/v8/src/parsing/parser-base.h index c393bc5ec2..faefe44011 100644 --- a/deps/v8/src/parsing/parser-base.h +++ b/deps/v8/src/parsing/parser-base.h @@ -279,9 +279,11 @@ class ParserBase { allow_harmony_do_expressions_(false), allow_harmony_function_sent_(false), allow_harmony_public_fields_(false), + allow_harmony_static_fields_(false), allow_harmony_dynamic_import_(false), allow_harmony_import_meta_(false), - allow_harmony_async_iteration_(false) {} + allow_harmony_optional_catch_binding_(false), + allow_harmony_private_fields_(false) {} #define ALLOW_ACCESSORS(name) \ bool allow_##name() const { return allow_##name##_; } \ @@ -291,9 +293,10 @@ class ParserBase { ALLOW_ACCESSORS(harmony_do_expressions); ALLOW_ACCESSORS(harmony_function_sent); ALLOW_ACCESSORS(harmony_public_fields); + ALLOW_ACCESSORS(harmony_static_fields); ALLOW_ACCESSORS(harmony_dynamic_import); ALLOW_ACCESSORS(harmony_import_meta); - ALLOW_ACCESSORS(harmony_async_iteration); + ALLOW_ACCESSORS(harmony_optional_catch_binding); #undef ALLOW_ACCESSORS @@ -304,6 +307,13 @@ class ParserBase { scanner()->set_allow_harmony_bigint(allow); } + bool allow_harmony_private_fields() const { + return scanner()->allow_harmony_private_fields(); + } + void set_allow_harmony_private_fields(bool allow) { + scanner()->set_allow_harmony_private_fields(allow); + } + uintptr_t stack_limit() const { return stack_limit_; } void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } @@ -383,18 +393,27 @@ class ParserBase { void AddProperty() { expected_property_count_++; } int expected_property_count() { return expected_property_count_; } + void DisableOptimization(BailoutReason reason) { + dont_optimize_reason_ = reason; + } + BailoutReason dont_optimize_reason() { return dont_optimize_reason_; } + FunctionKind kind() const { return scope()->function_kind(); } - FunctionState* outer() const { return outer_function_state_; } void RewindDestructuringAssignments(int pos) { destructuring_assignments_to_rewrite_.Rewind(pos); } - void SetDestructuringAssignmentsScope(int pos, Scope* scope) { - for (int i = pos; i < destructuring_assignments_to_rewrite_.length(); - ++i) { - destructuring_assignments_to_rewrite_[i]->set_scope(scope); + void AdoptDestructuringAssignmentsFromParentState(int pos) { + const auto& outer_assignments = + outer_function_state_->destructuring_assignments_to_rewrite_; + DCHECK_GE(outer_assignments.length(), pos); + for (int i = pos; i < outer_assignments.length(); ++i) { + auto expr = outer_assignments[i]; + expr->set_scope(scope_); + destructuring_assignments_to_rewrite_.Add(expr, scope_->zone()); } + outer_function_state_->RewindDestructuringAssignments(pos); } const ZoneList<RewritableExpressionT>& @@ -451,14 +470,6 @@ class ParserBase { destructuring_assignments_to_rewrite_.Add(expr, scope_->zone()); } - void AddNonPatternForRewriting(RewritableExpressionT expr, bool* ok) { - non_patterns_to_rewrite_.Add(expr, scope_->zone()); - if (non_patterns_to_rewrite_.length() >= - std::numeric_limits<uint16_t>::max()) { - *ok = false; - } - } - // Properties count estimation. int expected_property_count_; @@ -471,6 +482,9 @@ class ParserBase { ZoneList<typename ExpressionClassifier::Error> reported_errors_; + // A reason, if any, why this function should not be optimized. + BailoutReason dont_optimize_reason_; + // Record whether the next (=== immediately following) function literal is // preceded by a parenthesis / exclamation mark. Also record the previous // state. @@ -1078,10 +1092,8 @@ class ParserBase { return ParsePrimaryExpression(&is_async, ok); } - // This method wraps the parsing of the expression inside a new expression - // classifier and calls RewriteNonPattern if parsing is successful. - // It should be used whenever we're parsing an expression that is known - // to not be a pattern or part of a pattern. + // Use when parsing an expression that is known to not be a pattern or part + // of a pattern. V8_INLINE ExpressionT ParseExpression(bool accept_IN, bool* ok); // This method does not wrap the parsing of the expression inside a @@ -1201,14 +1213,15 @@ class ParserBase { // by value. The method is expected to add the parsed statements to the // list. This works because in the case of the parser, StatementListT is // a pointer whereas the preparser does not really modify the body. - V8_INLINE void ParseStatementList(StatementListT body, int end_token, + V8_INLINE void ParseStatementList(StatementListT body, Token::Value end_token, bool* ok) { LazyParsingResult result = ParseStatementList(body, end_token, false, ok); USE(result); DCHECK_EQ(result, kLazyParsingComplete); } - LazyParsingResult ParseStatementList(StatementListT body, int end_token, - bool may_abort, bool* ok); + LazyParsingResult ParseStatementList(StatementListT body, + Token::Value end_token, bool may_abort, + bool* ok); StatementT ParseStatementListItem(bool* ok); StatementT ParseStatement(ZoneList<const AstRawString*>* labels, bool* ok) { return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok); @@ -1463,21 +1476,18 @@ class ParserBase { // Accumulates the classifier that is on top of the stack (inner) to // the one that is right below (outer) and pops the inner. - V8_INLINE void Accumulate(unsigned productions, - bool merge_non_patterns = true) { + V8_INLINE void Accumulate(unsigned productions) { DCHECK_NOT_NULL(classifier_); ExpressionClassifier* previous = classifier_->previous(); DCHECK_NOT_NULL(previous); - previous->Accumulate(classifier_, productions, merge_non_patterns); + previous->Accumulate(classifier_, productions); classifier_ = previous; } V8_INLINE void AccumulateNonBindingPatternErrors() { - static const bool kMergeNonPatterns = true; this->Accumulate(ExpressionClassifier::AllProductions & - ~(ExpressionClassifier::BindingPatternProduction | - ExpressionClassifier::LetPatternProduction), - kMergeNonPatterns); + ~(ExpressionClassifier::BindingPatternProduction | + ExpressionClassifier::LetPatternProduction)); } // Pops and discards the classifier that is on top of the stack @@ -1534,9 +1544,11 @@ class ParserBase { bool allow_harmony_do_expressions_; bool allow_harmony_function_sent_; bool allow_harmony_public_fields_; + bool allow_harmony_static_fields_; bool allow_harmony_dynamic_import_; bool allow_harmony_import_meta_; - bool allow_harmony_async_iteration_; + bool allow_harmony_optional_catch_binding_; + bool allow_harmony_private_fields_; friend class DiscardableZoneScope; }; @@ -1553,6 +1565,7 @@ ParserBase<Impl>::FunctionState::FunctionState( destructuring_assignments_to_rewrite_(16, scope->zone()), non_patterns_to_rewrite_(0, scope->zone()), reported_errors_(16, scope->zone()), + dont_optimize_reason_(BailoutReason::kNoReason), next_function_is_likely_called_(false), previous_function_was_likely_called_(false), contains_function_or_eval_(false) { @@ -1587,6 +1600,7 @@ void ParserBase<Impl>::GetUnexpectedTokenMessage( case Token::STRING: *message = MessageTemplate::kUnexpectedTokenString; break; + case Token::PRIVATE_NAME: case Token::IDENTIFIER: *message = MessageTemplate::kUnexpectedTokenIdentifier; break; @@ -1664,6 +1678,13 @@ ParserBase<Impl>::ParseAndClassifyIdentifier(bool* ok) { if (next == Token::IDENTIFIER || next == Token::ASYNC || (next == Token::AWAIT && !parsing_module_ && !is_async_function())) { IdentifierT name = impl()->GetSymbol(); + + if (impl()->IsArguments(name) && scope()->ShouldBanArguments()) { + ReportMessage(MessageTemplate::kArgumentsDisallowedInInitializer); + *ok = false; + return impl()->NullIdentifier(); + } + // When this function is used to read a formal parameter, we don't always // know whether the function is going to be strict or sloppy. Indeed for // arrow functions we don't always know that the identifier we are reading @@ -1942,7 +1963,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseExpression( bool accept_IN, bool* ok) { ExpressionClassifier classifier(this); ExpressionT result = ParseExpressionCoverGrammar(accept_IN, CHECK_OK); - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); return result; } @@ -2068,22 +2089,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral( } Expect(Token::RBRACK, CHECK_OK); - ExpressionT result = - factory()->NewArrayLiteral(values, first_spread_index, pos); - if (first_spread_index >= 0) { - auto rewritable = factory()->NewRewritableExpression(result, scope()); - impl()->QueueNonPatternForRewriting(rewritable, 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 impl()->NullExpression(); - } - result = rewritable; - } - return result; + return factory()->NewArrayLiteral(values, first_spread_index, pos); } template <class Impl> @@ -2108,6 +2114,9 @@ bool ParserBase<Impl>::SetPropertyKindFromToken(Token::Value token, case Token::SEMICOLON: *kind = PropertyKind::kClassField; return true; + case Token::PRIVATE_NAME: + *kind = PropertyKind::kClassField; + return true; default: break; } @@ -2137,8 +2146,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName( !scanner()->HasAnyLineTerminatorAfterNext()) { Consume(Token::ASYNC); token = peek(); - if (token == Token::MUL && allow_harmony_async_iteration() && - !scanner()->HasAnyLineTerminatorBeforeNext()) { + if (token == Token::MUL && !scanner()->HasAnyLineTerminatorBeforeNext()) { Consume(Token::MUL); token = peek(); *is_generator = true; @@ -2198,7 +2206,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName( Consume(Token::LBRACK); ExpressionClassifier computed_name_classifier(this); expression = ParseAssignmentExpression(true, CHECK_OK); - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); AccumulateFormalParameterContainmentErrors(); Expect(Token::RBRACK, CHECK_OK); break; @@ -2270,6 +2278,8 @@ ParserBase<Impl>::ParseClassPropertyDefinition( PropertyKind kind = PropertyKind::kNotSet; Token::Value name_token = peek(); + DCHECK_IMPLIES(name_token == Token::PRIVATE_NAME, + allow_harmony_private_fields()); int name_token_position = scanner()->peek_location().beg_pos; IdentifierT name = impl()->NullIdentifier(); @@ -2285,12 +2295,22 @@ ParserBase<Impl>::ParseClassPropertyDefinition( peek() == Token::RBRACE) { name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'static' name_expression = factory()->NewStringLiteral(name, position()); + } else if (peek() == Token::PRIVATE_NAME) { + DCHECK(allow_harmony_private_fields()); + // TODO(gsathya): Make a better error message for this. + ReportUnexpectedToken(Next()); + *ok = false; + return impl()->NullLiteralProperty(); } else { *is_static = true; name_expression = ParsePropertyName(&name, &kind, &is_generator, &is_get, &is_set, &is_async, is_computed_name, CHECK_OK_CUSTOM(NullLiteralProperty)); } + } else if (name_token == Token::PRIVATE_NAME) { + Consume(Token::PRIVATE_NAME); + name = impl()->GetSymbol(); + name_expression = factory()->NewStringLiteral(name, position()); } else { name_expression = ParsePropertyName(&name, &kind, &is_generator, &is_get, &is_set, &is_async, is_computed_name, @@ -2312,9 +2332,14 @@ ParserBase<Impl>::ParseClassPropertyDefinition( // as an uninitialized field. case PropertyKind::kShorthandProperty: case PropertyKind::kValueProperty: - if (allow_harmony_public_fields()) { + if (allow_harmony_public_fields() || allow_harmony_private_fields()) { *property_kind = ClassLiteralProperty::FIELD; - if (!*is_computed_name) { + if (*is_static && !allow_harmony_static_fields()) { + ReportUnexpectedToken(Next()); + *ok = false; + return impl()->NullLiteralProperty(); + } + if (!*is_computed_name && name_token != Token::PRIVATE_NAME) { checker->CheckClassFieldName(*is_static, CHECK_OK_CUSTOM(NullLiteralProperty)); } @@ -2362,7 +2387,7 @@ ParserBase<Impl>::ParseClassPropertyDefinition( name, scanner()->location(), kSkipFunctionNameCheck, kind, FLAG_harmony_function_tostring ? name_token_position : kNoSourcePosition, - FunctionLiteral::kAccessorOrMethod, language_mode(), + FunctionLiteral::kAccessorOrMethod, language_mode(), nullptr, CHECK_OK_CUSTOM(NullLiteralProperty)); *property_kind = ClassLiteralProperty::METHOD; @@ -2394,7 +2419,7 @@ ParserBase<Impl>::ParseClassPropertyDefinition( name, scanner()->location(), kSkipFunctionNameCheck, kind, FLAG_harmony_function_tostring ? name_token_position : kNoSourcePosition, - FunctionLiteral::kAccessorOrMethod, language_mode(), + FunctionLiteral::kAccessorOrMethod, language_mode(), nullptr, CHECK_OK_CUSTOM(NullLiteralProperty)); *property_kind = @@ -2427,7 +2452,8 @@ ParserBase<Impl>::ParseClassFieldInitializer(ClassInfo* class_info, : class_info->instance_fields_scope; if (initializer_scope == nullptr) { - initializer_scope = NewFunctionScope(FunctionKind::kConciseMethod); + initializer_scope = + NewFunctionScope(FunctionKind::kClassFieldsInitializerFunction); // TODO(gsathya): Make scopes be non contiguous. initializer_scope->set_start_position(scanner()->location().end_pos); initializer_scope->SetLanguageMode(LanguageMode::kStrict); @@ -2441,7 +2467,7 @@ ParserBase<Impl>::ParseClassFieldInitializer(ClassInfo* class_info, initializer = ParseAssignmentExpression(true, CHECK_OK_CUSTOM(NullExpression)); - impl()->RewriteNonPattern(CHECK_OK_CUSTOM(NullExpression)); + ValidateExpression(CHECK_OK_CUSTOM(NullExpression)); } else { initializer = factory()->NewUndefinedLiteral(kNoSourcePosition); } @@ -2560,7 +2586,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker, ExpressionClassifier rhs_classifier(this); ExpressionT rhs = ParseAssignmentExpression( true, CHECK_OK_CUSTOM(NullLiteralProperty)); - impl()->RewriteNonPattern(CHECK_OK_CUSTOM(NullLiteralProperty)); + ValidateExpression(CHECK_OK_CUSTOM(NullLiteralProperty)); AccumulateFormalParameterContainmentErrors(); value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs, kNoSourcePosition); @@ -2595,7 +2621,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker, ExpressionT value = impl()->ParseFunctionLiteral( name, scanner()->location(), kSkipFunctionNameCheck, kind, FLAG_harmony_function_tostring ? next_beg_pos : kNoSourcePosition, - FunctionLiteral::kAccessorOrMethod, language_mode(), + FunctionLiteral::kAccessorOrMethod, language_mode(), nullptr, CHECK_OK_CUSTOM(NullLiteralProperty)); ObjectLiteralPropertyT result = factory()->NewObjectLiteralProperty( @@ -2627,7 +2653,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker, FunctionLiteralT value = impl()->ParseFunctionLiteral( name, scanner()->location(), kSkipFunctionNameCheck, kind, FLAG_harmony_function_tostring ? next_beg_pos : kNoSourcePosition, - FunctionLiteral::kAccessorOrMethod, language_mode(), + FunctionLiteral::kAccessorOrMethod, language_mode(), nullptr, CHECK_OK_CUSTOM(NullLiteralProperty)); ObjectLiteralPropertyT result = factory()->NewObjectLiteralProperty( @@ -2711,8 +2737,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral( MessageTemplate::kTooManyArguments); } - return factory()->NewObjectLiteral( - properties, number_of_boilerplate_properties, pos, has_rest_property); + return impl()->InitializeObjectLiteral(factory()->NewObjectLiteral( + properties, number_of_boilerplate_properties, pos, has_rest_property)); } template <typename Impl> @@ -2738,7 +2764,7 @@ typename ParserBase<Impl>::ExpressionListT ParserBase<Impl>::ParseArguments( *is_simple_parameter_list = false; } if (!maybe_arrow) { - impl()->RewriteNonPattern(CHECK_OK_CUSTOM(NullExpressionList)); + ValidateExpression(CHECK_OK_CUSTOM(NullExpressionList)); } if (is_spread) { if (is_simple_parameter_list != nullptr) { @@ -2784,7 +2810,7 @@ typename ParserBase<Impl>::ExpressionListT ParserBase<Impl>::ParseArguments( if (!maybe_arrow || peek() != Token::ARROW) { if (maybe_arrow) { - impl()->RewriteNonPattern(CHECK_OK_CUSTOM(NullExpressionList)); + ValidateExpression(CHECK_OK_CUSTOM(NullExpressionList)); } } @@ -2864,7 +2890,6 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) { // Because the arrow's parameters were parsed in the outer scope, // we need to fix up the scope chain appropriately. scope_snapshot.Reparent(scope); - function_state_->SetDestructuringAssignmentsScope(rewritable_length, scope); FormalParametersT parameters(scope); if (!classifier()->is_simple_parameter_list()) { @@ -2914,15 +2939,8 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) { productions &= ~ExpressionClassifier::ExpressionProduction; } - if (!Token::IsAssignmentOp(peek())) { - // Parsed conditional expression only (no assignment). - // Pending non-pattern expressions must be merged. - Accumulate(productions); - return expression; - } else { - // Pending non-pattern expressions must be discarded. - Accumulate(productions, false); - } + Accumulate(productions); + if (!Token::IsAssignmentOp(peek())) return expression; if (is_destructuring_assignment) { ValidateAssignmentPattern(CHECK_OK); @@ -2945,7 +2963,7 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) { ExpressionClassifier rhs_classifier(this); ExpressionT right = ParseAssignmentExpression(accept_IN, CHECK_OK); - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); AccumulateFormalParameterContainmentErrors(); // We try to estimate the set of properties set by constructors. We define a @@ -3019,7 +3037,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseYieldExpression( // Delegating yields require an RHS; fall through. default: expression = ParseAssignmentExpression(accept_IN, CHECK_OK); - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); break; } } @@ -3052,7 +3070,7 @@ ParserBase<Impl>::ParseConditionalExpression(bool accept_IN, // We start using the binary expression parser for prec >= 4 only! ExpressionT expression = ParseBinaryExpression(4, accept_IN, CHECK_OK); if (peek() != Token::CONDITIONAL) return expression; - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); BindingPatternUnexpectedToken(); ArrowFormalParametersUnexpectedToken(); @@ -3067,7 +3085,7 @@ ParserBase<Impl>::ParseConditionalExpression(bool accept_IN, left = ParseAssignmentExpression(true, CHECK_OK); AccumulateNonBindingPatternErrors(); } - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); ExpressionT right; { SourceRangeScope range_scope(scanner(), &else_range); @@ -3076,7 +3094,7 @@ ParserBase<Impl>::ParseConditionalExpression(bool accept_IN, right = ParseAssignmentExpression(accept_IN, CHECK_OK); AccumulateNonBindingPatternErrors(); } - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); ExpressionT expr = factory()->NewConditional(expression, left, right, pos); impl()->RecordConditionalSourceRange(expr, then_range, else_range); return expr; @@ -3093,7 +3111,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression( for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) { // prec1 >= 4 while (Precedence(peek(), accept_IN) == prec1) { - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); BindingPatternUnexpectedToken(); ArrowFormalParametersUnexpectedToken(); @@ -3105,7 +3123,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression( const int next_prec = is_right_associative ? prec1 : prec1 + 1; ExpressionT y = ParseBinaryExpression(next_prec, accept_IN, CHECK_OK); right_range_scope.Finalize(); - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); if (impl()->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos)) { continue; @@ -3171,7 +3189,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseUnaryExpression( } ExpressionT expression = ParseUnaryExpression(CHECK_OK); - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); if (op == Token::DELETE && is_strict(language_mode())) { if (impl()->IsIdentifier(expression)) { @@ -3200,7 +3218,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseUnaryExpression( expression, beg_pos, scanner()->location().end_pos, MessageTemplate::kInvalidLhsInPrefixOp, CHECK_OK); impl()->MarkExpressionAsAssigned(expression); - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); return factory()->NewCountOperation(op, true /* prefix */, @@ -3211,12 +3229,15 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseUnaryExpression( classifier()->RecordFormalParameterInitializerError( scanner()->peek_location(), MessageTemplate::kAwaitExpressionFormalParameter); - int await_pos = peek_position(); Consume(Token::AWAIT); ExpressionT value = ParseUnaryExpression(CHECK_OK); + classifier()->RecordBindingPatternError( + Scanner::Location(await_pos, scanner()->location().end_pos), + MessageTemplate::kInvalidDestructuringTarget); + ExpressionT expr = factory()->NewAwait(value, await_pos); impl()->RecordSuspendSourceRange(expr, PositionAfterSemicolon()); return expr; @@ -3242,7 +3263,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePostfixExpression( expression, lhs_beg_pos, scanner()->location().end_pos, MessageTemplate::kInvalidLhsInPostfixOp, CHECK_OK); impl()->MarkExpressionAsAssigned(expression); - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); Token::Value next = Next(); expression = @@ -3267,13 +3288,13 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) { while (true) { switch (peek()) { case Token::LBRACK: { - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); BindingPatternUnexpectedToken(); ArrowFormalParametersUnexpectedToken(); Consume(Token::LBRACK); int pos = position(); ExpressionT index = ParseExpressionCoverGrammar(true, CHECK_OK); - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); result = factory()->NewProperty(result, index, pos); Expect(Token::RBRACK, CHECK_OK); break; @@ -3281,7 +3302,7 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) { case Token::LPAREN: { int pos; - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); BindingPatternUnexpectedToken(); if (scanner()->current_token() == Token::IDENTIFIER || scanner()->current_token() == Token::SUPER || @@ -3373,7 +3394,7 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) { } case Token::PERIOD: { - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); BindingPatternUnexpectedToken(); ArrowFormalParametersUnexpectedToken(); Consume(Token::PERIOD); @@ -3387,7 +3408,7 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) { case Token::TEMPLATE_SPAN: case Token::TEMPLATE_TAIL: { - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); BindingPatternUnexpectedToken(); ArrowFormalParametersUnexpectedToken(); result = ParseTemplateLiteral(result, position(), true, CHECK_OK); @@ -3446,7 +3467,7 @@ ParserBase<Impl>::ParseMemberWithNewPrefixesExpression(bool* is_async, } else { result = ParseMemberWithNewPrefixesExpression(is_async, CHECK_OK); } - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); if (peek() == Token::LPAREN) { // NewExpression with arguments. Scanner::Location spread_pos; @@ -3537,7 +3558,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseMemberExpression( is_strict_reserved_name ? kFunctionNameIsStrictReserved : kFunctionNameValidityUnknown, function_kind, function_token_position, function_type, language_mode(), - CHECK_OK); + nullptr, CHECK_OK); } else if (peek() == Token::SUPER) { const bool is_new = false; result = ParseSuperExpression(is_new, CHECK_OK); @@ -3657,14 +3678,14 @@ ParserBase<Impl>::ParseMemberExpressionContinuation(ExpressionT expression, switch (peek()) { case Token::LBRACK: { *is_async = false; - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); BindingPatternUnexpectedToken(); ArrowFormalParametersUnexpectedToken(); Consume(Token::LBRACK); int pos = position(); ExpressionT index = ParseExpressionCoverGrammar(true, CHECK_OK); - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); expression = factory()->NewProperty(expression, index, pos); impl()->PushPropertyName(index); Expect(Token::RBRACK, CHECK_OK); @@ -3672,13 +3693,19 @@ ParserBase<Impl>::ParseMemberExpressionContinuation(ExpressionT expression, } case Token::PERIOD: { *is_async = false; - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); BindingPatternUnexpectedToken(); ArrowFormalParametersUnexpectedToken(); Consume(Token::PERIOD); int pos = peek_position(); - IdentifierT name = ParseIdentifierName(CHECK_OK); + IdentifierT name; + if (allow_harmony_private_fields() && peek() == Token::PRIVATE_NAME) { + Consume(Token::PRIVATE_NAME); + name = impl()->GetSymbol(); + } else { + name = ParseIdentifierName(CHECK_OK); + } expression = factory()->NewProperty( expression, factory()->NewStringLiteral(name, pos), pos); impl()->PushLiteralName(name); @@ -3687,7 +3714,7 @@ ParserBase<Impl>::ParseMemberExpressionContinuation(ExpressionT expression, case Token::TEMPLATE_SPAN: case Token::TEMPLATE_TAIL: { *is_async = false; - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); BindingPatternUnexpectedToken(); ArrowFormalParametersUnexpectedToken(); int pos; @@ -3743,7 +3770,7 @@ void ParserBase<Impl>::ParseFormalParameter(FormalParametersT* parameters, } ExpressionClassifier init_classifier(this); initializer = ParseAssignmentExpression(true, CHECK_OK_CUSTOM(Void)); - impl()->RewriteNonPattern(CHECK_OK_CUSTOM(Void)); + ValidateExpression(CHECK_OK_CUSTOM(Void)); ValidateFormalParameterInitializer(CHECK_OK_CUSTOM(Void)); parameters->is_simple = false; DiscardExpressionClassifier(); @@ -3882,7 +3909,7 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations( ExpressionClassifier classifier(this); value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK_CUSTOM(NullStatement)); - impl()->RewriteNonPattern(CHECK_OK_CUSTOM(NullStatement)); + ValidateExpression(CHECK_OK_CUSTOM(NullStatement)); variable_loc.end_pos = scanner()->location().end_pos; if (!parsing_result->first_initializer_loc.IsValid()) { @@ -3997,7 +4024,7 @@ ParserBase<Impl>::ParseHoistableDeclaration( const bool is_async = flags & ParseFunctionFlags::kIsAsync; DCHECK(!is_generator || !is_async); - if (allow_harmony_async_iteration() && is_async && Check(Token::MUL)) { + if (is_async && Check(Token::MUL)) { // Async generator is_generator = true; } @@ -4025,7 +4052,7 @@ ParserBase<Impl>::ParseHoistableDeclaration( FunctionLiteralT function = impl()->ParseFunctionLiteral( name, scanner()->location(), name_validity, kind, pos, - FunctionLiteral::kDeclaration, language_mode(), + FunctionLiteral::kDeclaration, language_mode(), nullptr, CHECK_OK_CUSTOM(NullStatement)); // In ES6, a function behaves as a lexical binding, except in @@ -4096,6 +4123,8 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseClassDeclaration( template <typename Impl> typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseNativeDeclaration( bool* ok) { + function_state_->DisableOptimization(BailoutReason::kNativeFunctionLiteral); + int pos = peek_position(); Expect(Token::FUNCTION, CHECK_OK_CUSTOM(NullStatement)); // Allow "eval" or "arguments" for backward compatibility. @@ -4150,6 +4179,11 @@ void ParserBase<Impl>::ParseFunctionBody( body = inner_block->statements(); } + // If we are parsing the source as if it is wrapped in a function, the source + // ends without a closing brace. + Token::Value closing_token = + function_type == FunctionLiteral::kWrapped ? Token::EOS : Token::RBRACE; + { BlockState block_state(&scope_, inner_scope); @@ -4162,7 +4196,7 @@ void ParserBase<Impl>::ParseFunctionBody( } else if (IsAsyncFunction(kind)) { ParseAsyncFunctionBody(inner_scope, body, CHECK_OK_VOID); } else { - ParseStatementList(body, Token::RBRACE, CHECK_OK_VOID); + ParseStatementList(body, closing_token, CHECK_OK_VOID); } if (IsDerivedConstructor(kind)) { @@ -4172,7 +4206,7 @@ void ParserBase<Impl>::ParseFunctionBody( } } - Expect(Token::RBRACE, CHECK_OK_VOID); + Expect(closing_token, CHECK_OK_VOID); scope()->set_end_position(scanner()->location().end_pos); if (!parameters.is_simple) { @@ -4298,11 +4332,11 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrowFunctionLiteral( bool accept_IN, const FormalParametersT& formal_parameters, int rewritable_length, bool* ok) { - const RuntimeCallStats::CounterId counters[2][2] = { - {&RuntimeCallStats::ParseBackgroundArrowFunctionLiteral, - &RuntimeCallStats::ParseArrowFunctionLiteral}, - {&RuntimeCallStats::PreParseBackgroundArrowFunctionLiteral, - &RuntimeCallStats::PreParseArrowFunctionLiteral}}; + const RuntimeCallCounterId counters[2][2] = { + {RuntimeCallCounterId::kParseBackgroundArrowFunctionLiteral, + RuntimeCallCounterId::kParseArrowFunctionLiteral}, + {RuntimeCallCounterId::kPreParseBackgroundArrowFunctionLiteral, + RuntimeCallCounterId::kPreParseArrowFunctionLiteral}}; RuntimeCallTimerScope runtime_timer( runtime_call_stats_, counters[Impl::IsPreParser()][parsing_on_main_thread_]); @@ -4337,6 +4371,11 @@ ParserBase<Impl>::ParseArrowFunctionLiteral( FunctionState function_state(&function_state_, &scope_, formal_parameters.scope); + // Move any queued destructuring assignments which appeared + // in this function's parameter list into its own function_state. + function_state.AdoptDestructuringAssignmentsFromParentState( + rewritable_length); + Expect(Token::ARROW, CHECK_OK); if (peek() == Token::LBRACE) { @@ -4360,14 +4399,10 @@ ParserBase<Impl>::ParseArrowFunctionLiteral( USE(result); formal_parameters.scope->ResetAfterPreparsing(ast_value_factory_, false); - // Discard any queued destructuring assignments which appeared - // in this function's parameter list. - FunctionState* parent_state = function_state.outer(); - DCHECK_NOT_NULL(parent_state); - DCHECK_GE(parent_state->destructuring_assignments_to_rewrite().length(), - rewritable_length); - parent_state->RewindDestructuringAssignments(rewritable_length); + // in this function's parameter list, and which were adopted + // into this function state, above. + function_state.RewindDestructuringAssignments(0); } else { Consume(Token::LBRACE); body = impl()->NewStatementList(8); @@ -4467,9 +4502,10 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral( scope()->set_start_position(scanner()->location().end_pos); if (Check(Token::EXTENDS)) { + FuncNameInferrer::State fni_state(fni_); ExpressionClassifier extends_classifier(this); class_info.extends = ParseLeftHandSideExpression(CHECK_OK); - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); AccumulateFormalParameterContainmentErrors(); } @@ -4501,7 +4537,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral( class_info.computed_field_count++; } is_constructor &= class_info.has_seen_constructor; - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); AccumulateFormalParameterContainmentErrors(); impl()->DeclareClassProperty(name, property, property_kind, is_static, @@ -4526,7 +4562,7 @@ void ParserBase<Impl>::ParseSingleExpressionFunctionBody(StatementListT body, ExpressionClassifier classifier(this); ExpressionT expression = ParseAssignmentExpression(accept_IN, CHECK_OK_VOID); - impl()->RewriteNonPattern(CHECK_OK_VOID); + ValidateExpression(CHECK_OK_VOID); if (is_async) { BlockT block = factory()->NewBlock(1, true); @@ -4564,7 +4600,7 @@ ParserBase<Impl>::ParseAsyncFunctionLiteral(bool* ok) { IdentifierT name = impl()->NullIdentifier(); FunctionLiteral::FunctionType type = FunctionLiteral::kAnonymousExpression; - bool is_generator = allow_harmony_async_iteration() && Check(Token::MUL); + bool is_generator = Check(Token::MUL); const bool kIsAsync = true; const FunctionKind kind = FunctionKindFor(is_generator, kIsAsync); @@ -4590,7 +4626,7 @@ ParserBase<Impl>::ParseAsyncFunctionLiteral(bool* ok) { name, scanner()->location(), is_strict_reserved ? kFunctionNameIsStrictReserved : kFunctionNameValidityUnknown, - kind, pos, type, language_mode(), CHECK_OK); + kind, pos, type, language_mode(), nullptr, CHECK_OK); } template <typename Impl> @@ -4650,7 +4686,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral( int expr_pos = peek_position(); ExpressionT expression = ParseExpressionCoverGrammar(true, CHECK_OK); - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); impl()->AddTemplateExpression(&ts, expression); if (peek() != Token::RBRACE) { @@ -4781,8 +4817,9 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseDoExpression( template <typename Impl> typename ParserBase<Impl>::LazyParsingResult -ParserBase<Impl>::ParseStatementList(StatementListT body, int end_token, - bool may_abort, bool* ok) { +ParserBase<Impl>::ParseStatementList(StatementListT body, + Token::Value end_token, bool may_abort, + bool* ok) { // StatementList :: // (StatementListItem)* <end_token> @@ -4953,8 +4990,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatement( case Token::WHILE: return ParseWhileStatement(labels, ok); case Token::FOR: - if (V8_UNLIKELY(allow_harmony_async_iteration() && is_async_function() && - PeekAhead() == Token::AWAIT)) { + if (V8_UNLIKELY(is_async_function() && PeekAhead() == Token::AWAIT)) { return ParseForAwaitStatement(labels, ok); } return ParseForStatement(labels, ok); @@ -5175,11 +5211,6 @@ ParserBase<Impl>::ParseExpressionOrLabelledStatement( // Parsed expression statement, followed by semicolon. ExpectSemicolon(CHECK_OK); - if (labels != nullptr) { - // TODO(adamk): Also measure in the PreParser by passing something - // non-null as |labels|. - impl()->CountUsage(v8::Isolate::kLabeledExpressionStatement); - } return factory()->NewExpressionStatement(expr, pos); } @@ -5204,8 +5235,9 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseIfStatement( StatementT else_statement = impl()->NullStatement(); if (Check(Token::ELSE)) { - SourceRangeScope range_scope(scanner(), &else_range); + else_range = SourceRange::ContinuationOf(then_range); else_statement = ParseScopedStatement(labels, CHECK_OK); + else_range.end = scanner_->location().end_pos; } else { else_statement = factory()->NewEmptyStatement(kNoSourcePosition); } @@ -5547,50 +5579,60 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseTryStatement( { SourceRangeScope catch_range_scope(scanner(), &catch_range); if (Check(Token::CATCH)) { - Expect(Token::LPAREN, CHECK_OK); - catch_info.scope = NewScope(CATCH_SCOPE); - catch_info.scope->set_start_position(scanner()->location().beg_pos); - - { - BlockState catch_block_state(&scope_, catch_info.scope); + bool has_binding; + if (allow_harmony_optional_catch_binding()) { + has_binding = Check(Token::LPAREN); + } else { + has_binding = true; + Expect(Token::LPAREN, CHECK_OK); + } - catch_block = factory()->NewBlock(16, false); + if (has_binding) { + catch_info.scope = NewScope(CATCH_SCOPE); + catch_info.scope->set_start_position(scanner()->location().beg_pos); - // Create a block scope to hold any lexical declarations created - // as part of destructuring the catch parameter. { - BlockState catch_variable_block_state(zone(), &scope_); - scope()->set_start_position(scanner()->location().beg_pos); - typename Types::Target target(this, catch_block); - - // This does not simply call ParsePrimaryExpression to avoid - // ExpressionFromIdentifier from being called in the first - // branch, which would introduce an unresolved symbol and mess - // with arrow function names. - if (peek_any_identifier()) { - catch_info.name = - ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK); - } else { - ExpressionClassifier pattern_classifier(this); - catch_info.pattern = ParsePrimaryExpression(CHECK_OK); - ValidateBindingPattern(CHECK_OK); - } + BlockState catch_block_state(&scope_, catch_info.scope); + + catch_block = factory()->NewBlock(16, false); + + // Create a block scope to hold any lexical declarations created + // as part of destructuring the catch parameter. + { + BlockState catch_variable_block_state(zone(), &scope_); + scope()->set_start_position(scanner()->location().beg_pos); + + // This does not simply call ParsePrimaryExpression to avoid + // ExpressionFromIdentifier from being called in the first + // branch, which would introduce an unresolved symbol and mess + // with arrow function names. + if (peek_any_identifier()) { + catch_info.name = + ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK); + } else { + ExpressionClassifier pattern_classifier(this); + catch_info.pattern = ParsePrimaryExpression(CHECK_OK); + ValidateBindingPattern(CHECK_OK); + } - Expect(Token::RPAREN, CHECK_OK); - impl()->RewriteCatchPattern(&catch_info, CHECK_OK); - if (!impl()->IsNull(catch_info.init_block)) { - catch_block->statements()->Add(catch_info.init_block, zone()); - } + Expect(Token::RPAREN, CHECK_OK); + impl()->RewriteCatchPattern(&catch_info, CHECK_OK); + if (!impl()->IsNull(catch_info.init_block)) { + catch_block->statements()->Add(catch_info.init_block, zone()); + } - catch_info.inner_block = ParseBlock(nullptr, CHECK_OK); - catch_block->statements()->Add(catch_info.inner_block, zone()); - impl()->ValidateCatchBlock(catch_info, CHECK_OK); - scope()->set_end_position(scanner()->location().end_pos); - catch_block->set_scope(scope()->FinalizeBlockScope()); + catch_info.inner_block = ParseBlock(nullptr, CHECK_OK); + catch_block->statements()->Add(catch_info.inner_block, zone()); + impl()->ValidateCatchBlock(catch_info, CHECK_OK); + scope()->set_end_position(scanner()->location().end_pos); + catch_block->set_scope(scope()->FinalizeBlockScope()); + } } - } - catch_info.scope->set_end_position(scanner()->location().end_pos); + catch_info.scope->set_end_position(scanner()->location().end_pos); + } else { + catch_block = ParseBlock(nullptr, CHECK_OK); + } } } @@ -5687,7 +5729,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement( if (is_destructuring) { ValidateAssignmentPattern(CHECK_OK); } else { - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); } if (is_for_each) { @@ -5750,7 +5792,7 @@ ParserBase<Impl>::ParseForEachStatementWithDeclarations( if (for_info->mode == ForEachStatement::ITERATE) { ExpressionClassifier classifier(this); enumerable = ParseAssignmentExpression(true, CHECK_OK); - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); } else { enumerable = ParseExpression(true, CHECK_OK); } @@ -5826,7 +5868,7 @@ ParserBase<Impl>::ParseForEachStatementWithoutDeclarations( if (for_info->mode == ForEachStatement::ITERATE) { ExpressionClassifier classifier(this); enumerable = ParseAssignmentExpression(true, CHECK_OK); - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); } else { enumerable = ParseExpression(true, CHECK_OK); } @@ -5945,7 +5987,6 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement( ZoneList<const AstRawString*>* labels, bool* ok) { // for await '(' ForDeclaration of AssignmentExpression ')' DCHECK(is_async_function()); - DCHECK(allow_harmony_async_iteration()); int stmt_pos = peek_position(); @@ -6014,7 +6055,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement( if (lhs->IsArrayLiteral() || lhs->IsObjectLiteral()) { ValidateAssignmentPattern(CHECK_OK); } else { - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); each_variable = CheckAndRewriteReferenceExpression( lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor, kSyntaxError, CHECK_OK); @@ -6030,7 +6071,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement( { ExpressionClassifier classifier(this); iterable = ParseAssignmentExpression(kAllowIn, CHECK_OK); - impl()->RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); } Expect(Token::RPAREN, CHECK_OK); diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc index 4d291a741e..0497958c82 100644 --- a/deps/v8/src/parsing/parser.cc +++ b/deps/v8/src/parsing/parser.cc @@ -276,18 +276,18 @@ bool Parser::ShortcutNumericLiteralBinaryExpression(Expression** x, return true; } case Token::SHL: { - int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f); + int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1F); *x = factory()->NewNumberLiteral(value, pos); return true; } case Token::SHR: { - uint32_t shift = DoubleToInt32(y_val) & 0x1f; + uint32_t shift = DoubleToInt32(y_val) & 0x1F; uint32_t value = DoubleToUint32(x_val) >> shift; *x = factory()->NewNumberLiteral(value, pos); return true; } case Token::SAR: { - uint32_t shift = DoubleToInt32(y_val) & 0x1f; + uint32_t shift = DoubleToInt32(y_val) & 0x1F; int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift); *x = factory()->NewNumberLiteral(value, pos); return true; @@ -506,7 +506,7 @@ Parser::Parser(ParseInfo* info) info->runtime_call_stats(), info->logger(), info->script().is_null() ? -1 : info->script()->id(), info->is_module(), true), - scanner_(info->unicode_cache(), use_counts_), + scanner_(info->unicode_cache()), reusable_preparser_(nullptr), mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly. source_range_map_(info->source_range_map()), @@ -543,10 +543,12 @@ Parser::Parser(ParseInfo* info) set_allow_harmony_do_expressions(FLAG_harmony_do_expressions); set_allow_harmony_function_sent(FLAG_harmony_function_sent); set_allow_harmony_public_fields(FLAG_harmony_public_fields); + set_allow_harmony_static_fields(FLAG_harmony_static_fields); set_allow_harmony_dynamic_import(FLAG_harmony_dynamic_import); set_allow_harmony_import_meta(FLAG_harmony_import_meta); - set_allow_harmony_async_iteration(FLAG_harmony_async_iteration); set_allow_harmony_bigint(FLAG_harmony_bigint); + set_allow_harmony_optional_catch_binding(FLAG_harmony_optional_catch_binding); + set_allow_harmony_private_fields(FLAG_harmony_private_fields); for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; ++feature) { use_counts_[feature] = 0; @@ -592,8 +594,9 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) { // called in the main thread. DCHECK(parsing_on_main_thread_); RuntimeCallTimerScope runtime_timer( - runtime_call_stats_, info->is_eval() ? &RuntimeCallStats::ParseEval - : &RuntimeCallStats::ParseProgram); + runtime_call_stats_, info->is_eval() + ? RuntimeCallCounterId::kParseEval + : RuntimeCallCounterId::kParseProgram); TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseProgram"); base::ElapsedTimer timer; if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start(); @@ -667,11 +670,9 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { } DeclarationScope* scope = outer->AsDeclarationScope(); - scope->set_start_position(0); FunctionState function_state(&function_state_, &scope_, scope); - ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); bool ok = true; int beg_pos = scanner()->location().beg_pos; @@ -689,7 +690,6 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { var->AllocateTo(VariableLocation::PARAMETER, 0); PrepareGeneratorVariables(); - scope->ForceContextAllocation(); Expression* initial_yield = BuildInitialYield(kNoSourcePosition, kGeneratorFunction); body->Add( @@ -699,6 +699,8 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { ParseModuleItemList(body, &ok); ok = ok && module()->Validate(this->scope()->AsModuleScope(), pending_error_handler(), zone()); + } else if (info->is_wrapped_as_function()) { + ParseWrapped(info, body, scope, zone(), &ok); } else { // Don't count the mode in the use counters--give the program a chance // to enable script-wide strict mode below. @@ -751,13 +753,53 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { return result; } +ZoneList<const AstRawString*>* Parser::PrepareWrappedArguments(ParseInfo* info, + Zone* zone) { + DCHECK(parsing_on_main_thread_); + Handle<FixedArray> arguments(info->script()->wrapped_arguments()); + int arguments_length = arguments->length(); + ZoneList<const AstRawString*>* arguments_for_wrapped_function = + new (zone) ZoneList<const AstRawString*>(arguments_length, zone); + for (int i = 0; i < arguments_length; i++) { + const AstRawString* argument_string = ast_value_factory()->GetString( + Handle<String>(String::cast(arguments->get(i)))); + arguments_for_wrapped_function->Add(argument_string, zone); + } + return arguments_for_wrapped_function; +} + +void Parser::ParseWrapped(ParseInfo* info, ZoneList<Statement*>* body, + DeclarationScope* outer_scope, Zone* zone, bool* ok) { + DCHECK(info->is_wrapped_as_function()); + ParsingModeScope parsing_mode(this, PARSE_EAGERLY); + + // Set function and block state for the outer eval scope. + DCHECK(outer_scope->is_eval_scope()); + FunctionState function_state(&function_state_, &scope_, outer_scope); + + const AstRawString* function_name = nullptr; + Scanner::Location location(0, 0); + + ZoneList<const AstRawString*>* arguments_for_wrapped_function = + PrepareWrappedArguments(info, zone); + + FunctionLiteral* function_literal = ParseFunctionLiteral( + function_name, location, kSkipFunctionNameCheck, kNormalFunction, + kNoSourcePosition, FunctionLiteral::kWrapped, LanguageMode::kSloppy, + arguments_for_wrapped_function, CHECK_OK_VOID); + + Statement* return_statement = factory()->NewReturnStatement( + function_literal, kNoSourcePosition, kNoSourcePosition); + body->Add(return_statement, zone); +} + FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info, Handle<SharedFunctionInfo> shared_info) { // It's OK to use the Isolate & counters here, since this function is only // called in the main thread. DCHECK(parsing_on_main_thread_); RuntimeCallTimerScope runtime_timer(runtime_call_stats_, - &RuntimeCallStats::ParseFunction); + RuntimeCallCounterId::kParseFunction); TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseFunction"); base::ElapsedTimer timer; if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start(); @@ -794,7 +836,9 @@ FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info, } static FunctionLiteral::FunctionType ComputeFunctionType(ParseInfo* info) { - if (info->is_declaration()) { + if (info->is_wrapped_as_function()) { + return FunctionLiteral::kWrapped; + } else if (info->is_declaration()) { return FunctionLiteral::kDeclaration; } else if (info->is_named_expression()) { return FunctionLiteral::kNamedExpression; @@ -927,9 +971,13 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info, result = DefaultConstructor(raw_name, IsDerivedConstructor(kind), info->start_position(), info->end_position()); } else { + ZoneList<const AstRawString*>* arguments_for_wrapped_function = + info->is_wrapped_as_function() ? PrepareWrappedArguments(info, zone()) + : nullptr; result = ParseFunctionLiteral( raw_name, Scanner::Location::invalid(), kSkipFunctionNameCheck, kind, - kNoSourcePosition, function_type, info->language_mode(), &ok); + kNoSourcePosition, function_type, info->language_mode(), + arguments_for_wrapped_function, &ok); } if (ok) { @@ -1251,7 +1299,7 @@ Statement* Parser::ParseExportDefault(bool* ok) { int pos = position(); ExpressionClassifier classifier(this); Expression* value = ParseAssignmentExpression(true, CHECK_OK); - RewriteNonPattern(CHECK_OK); + ValidateExpression(CHECK_OK); SetFunctionName(value, ast_value_factory()->default_string()); const AstRawString* local_name = @@ -1714,7 +1762,6 @@ Statement* Parser::RewriteTryStatement(Block* try_block, Block* catch_block, if (catch_block != nullptr && finally_block != nullptr) { // If we have both, create an inner try/catch. - DCHECK_NOT_NULL(catch_info.scope); TryCatchStatement* statement; statement = factory()->NewTryCatchStatement(try_block, catch_info.scope, catch_block, kNoSourcePosition); @@ -1727,7 +1774,6 @@ Statement* Parser::RewriteTryStatement(Block* try_block, Block* catch_block, if (catch_block != nullptr) { DCHECK_NULL(finally_block); - DCHECK_NOT_NULL(catch_info.scope); TryCatchStatement* stmt = factory()->NewTryCatchStatement( try_block, catch_info.scope, catch_block, pos); RecordTryCatchStatementSourceRange(stmt, catch_range); @@ -1844,13 +1890,11 @@ void Parser::DeclareFunctionNameVar(const AstRawString* function_name, // !%_IsJSReceiver(result = Await(iterator.next())) && // %ThrowIteratorResultNotAnObject(result) // [endif] -Expression* Parser::BuildIteratorNextResult(Expression* iterator, +Expression* Parser::BuildIteratorNextResult(VariableProxy* iterator, + VariableProxy* next, Variable* result, IteratorType type, int pos) { - Expression* next_literal = factory()->NewStringLiteral( - ast_value_factory()->next_string(), kNoSourcePosition); - Expression* next_property = - factory()->NewProperty(iterator, next_literal, kNoSourcePosition); + Expression* next_property = factory()->NewResolvedProperty(iterator, next); ZoneList<Expression*>* next_arguments = new (zone()) ZoneList<Expression*>(0, zone()); Expression* next_call = @@ -2053,6 +2097,7 @@ Statement* Parser::InitializeForOfStatement( auto avfactory = ast_value_factory(); Variable* iterator = NewTemporary(avfactory->dot_iterator_string()); + Variable* next = NewTemporary(avfactory->empty_string()); Variable* result = NewTemporary(avfactory->dot_result_string()); Variable* completion = NewTemporary(avfactory->empty_string()); @@ -2065,6 +2110,17 @@ Statement* Parser::InitializeForOfStatement( iterable->position()); } + Expression* assign_next; + { + assign_next = factory()->NewAssignment( + Token::ASSIGN, factory()->NewVariableProxy(next), + factory()->NewProperty(factory()->NewVariableProxy(iterator), + factory()->NewStringLiteral( + avfactory->next_string(), kNoSourcePosition), + kNoSourcePosition), + kNoSourcePosition); + } + // [if (IteratorType == kNormal)] // !%_IsJSReceiver(result = iterator.next()) && // %ThrowIteratorResultNotAnObject(result) @@ -2074,9 +2130,10 @@ Statement* Parser::InitializeForOfStatement( // [endif] Expression* next_result; { - Expression* iterator_proxy = factory()->NewVariableProxy(iterator); - next_result = - BuildIteratorNextResult(iterator_proxy, result, type, next_result_pos); + VariableProxy* iterator_proxy = factory()->NewVariableProxy(iterator); + VariableProxy* next_proxy = factory()->NewVariableProxy(next); + next_result = BuildIteratorNextResult(iterator_proxy, next_proxy, result, + type, next_result_pos); } // result.done @@ -2146,8 +2203,8 @@ Statement* Parser::InitializeForOfStatement( body = block; } - for_of->Initialize(body, iterator, assign_iterator, next_result, result_done, - assign_each); + for_of->Initialize(body, iterator, assign_iterator, assign_next, next_result, + result_done, assign_each); return finalize ? FinalizeForOfStatement(for_of, completion, type, nopos) : for_of; } @@ -2510,7 +2567,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral( const AstRawString* function_name, Scanner::Location function_name_location, FunctionNameValidity function_name_validity, FunctionKind kind, int function_token_pos, FunctionLiteral::FunctionType function_type, - LanguageMode language_mode, bool* ok) { + LanguageMode language_mode, + ZoneList<const AstRawString*>* arguments_for_wrapped_function, bool* ok) { // Function :: // '(' FormalParameterList? ')' '{' FunctionBody '}' // @@ -2520,8 +2578,12 @@ FunctionLiteral* Parser::ParseFunctionLiteral( // Setter :: // '(' PropertySetParameterList ')' '{' FunctionBody '}' + bool is_wrapped = function_type == FunctionLiteral::kWrapped; + DCHECK_EQ(is_wrapped, arguments_for_wrapped_function != nullptr); + int pos = function_token_pos == kNoSourcePosition ? peek_position() : function_token_pos; + DCHECK_NE(kNoSourcePosition, pos); // Anonymous functions were passed either the empty symbol or a null // handle as the function name. Remember if we were passed a non-empty @@ -2535,7 +2597,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( } FunctionLiteral::EagerCompileHint eager_compile_hint = - function_state_->next_function_is_likely_called() + function_state_->next_function_is_likely_called() || is_wrapped ? FunctionLiteral::kShouldEagerCompile : default_eager_compile_hint(); @@ -2587,8 +2649,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral( RuntimeCallTimerScope runtime_timer( runtime_call_stats_, parsing_on_main_thread_ - ? &RuntimeCallStats::ParseFunctionLiteral - : &RuntimeCallStats::ParseBackgroundFunctionLiteral); + ? RuntimeCallCounterId::kParseFunctionLiteral + : RuntimeCallCounterId::kParseBackgroundFunctionLiteral); base::ElapsedTimer timer; if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start(); @@ -2650,7 +2712,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( if (should_preparse) scope->set_needs_migration(); #endif - Expect(Token::LPAREN, CHECK_OK); + if (!is_wrapped) Expect(Token::LPAREN, CHECK_OK); scope->set_start_position(scanner()->location().beg_pos); // Eager or lazy parse? If is_lazy_top_level_function, we'll parse @@ -2661,6 +2723,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( if (should_preparse) { DCHECK(parse_lazily()); DCHECK(is_lazy_top_level_function || is_lazy_inner_function); + DCHECK(!is_wrapped); Scanner::BookmarkScope bookmark(scanner()); bookmark.Set(); LazyParsingResult result = SkipFunction( @@ -2687,7 +2750,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( body = ParseFunction(function_name, pos, kind, function_type, scope, &num_parameters, &function_length, &has_duplicate_parameters, &expected_property_count, - CHECK_OK); + arguments_for_wrapped_function, CHECK_OK); } DCHECK_EQ(should_preparse, temp_zoned_); @@ -2705,18 +2768,20 @@ FunctionLiteral* Parser::ParseFunctionLiteral( } if (V8_UNLIKELY(FLAG_runtime_stats)) { if (should_preparse) { - RuntimeCallStats::CounterId counter_id = + RuntimeCallCounterId counter_id = parsing_on_main_thread_ - ? &RuntimeCallStats::PreParseWithVariableResolution - : &RuntimeCallStats::PreParseBackgroundWithVariableResolution; + ? RuntimeCallCounterId::kPreParseWithVariableResolution + : RuntimeCallCounterId:: + kPreParseBackgroundWithVariableResolution; if (is_top_level) { - counter_id = - parsing_on_main_thread_ - ? &RuntimeCallStats::PreParseNoVariableResolution - : &RuntimeCallStats::PreParseBackgroundNoVariableResolution; + counter_id = parsing_on_main_thread_ + ? RuntimeCallCounterId::kPreParseNoVariableResolution + : RuntimeCallCounterId:: + kPreParseBackgroundNoVariableResolution; + } + if (runtime_call_stats_) { + runtime_call_stats_->CorrectCurrentCounterId(counter_id); } - RuntimeCallStats::CorrectCurrentCounterId(runtime_call_stats_, - counter_id); } } @@ -3118,11 +3183,14 @@ ZoneList<Statement*>* Parser::ParseFunction( const AstRawString* function_name, int pos, FunctionKind kind, FunctionLiteral::FunctionType function_type, DeclarationScope* function_scope, int* num_parameters, int* function_length, - bool* has_duplicate_parameters, int* expected_property_count, bool* ok) { + bool* has_duplicate_parameters, int* expected_property_count, + ZoneList<const AstRawString*>* arguments_for_wrapped_function, bool* ok) { ParsingModeScope mode(this, allow_lazy_ ? PARSE_LAZILY : PARSE_EAGERLY); FunctionState function_state(&function_state_, &scope_, function_scope); + bool is_wrapped = function_type == FunctionLiteral::kWrapped; + DuplicateFinder duplicate_finder; ExpressionClassifier formals_classifier(this, &duplicate_finder); @@ -3136,34 +3204,53 @@ ZoneList<Statement*>* Parser::ParseFunction( } ParserFormalParameters formals(function_scope); - ParseFormalParameterList(&formals, CHECK_OK); - if (expected_parameters_end_pos != kNoSourcePosition) { - // Check for '(' or ')' shenanigans in the parameter string for dynamic - // functions. - int position = peek_position(); - if (position < expected_parameters_end_pos) { - ReportMessageAt(Scanner::Location(position, position + 1), - MessageTemplate::kArgStringTerminatesParametersEarly); - *ok = false; - return nullptr; - } else if (position > expected_parameters_end_pos) { - ReportMessageAt(Scanner::Location(expected_parameters_end_pos - 2, - expected_parameters_end_pos), - MessageTemplate::kUnexpectedEndOfArgString); - *ok = false; - return nullptr; + + if (is_wrapped) { + // For a function implicitly wrapped in function header and footer, the + // function arguments are provided separately to the source, and are + // declared directly here. + int arguments_length = arguments_for_wrapped_function->length(); + for (int i = 0; i < arguments_length; i++) { + const bool is_rest = false; + Expression* argument = ExpressionFromIdentifier( + arguments_for_wrapped_function->at(i), kNoSourcePosition); + AddFormalParameter(&formals, argument, NullExpression(), + kNoSourcePosition, is_rest); + } + DCHECK_EQ(arguments_length, formals.num_parameters()); + DeclareFormalParameters(formals.scope, formals.params, formals.is_simple); + } else { + // For a regular function, the function arguments are parsed from source. + DCHECK_NULL(arguments_for_wrapped_function); + ParseFormalParameterList(&formals, CHECK_OK); + if (expected_parameters_end_pos != kNoSourcePosition) { + // Check for '(' or ')' shenanigans in the parameter string for dynamic + // functions. + int position = peek_position(); + if (position < expected_parameters_end_pos) { + ReportMessageAt(Scanner::Location(position, position + 1), + MessageTemplate::kArgStringTerminatesParametersEarly); + *ok = false; + return nullptr; + } else if (position > expected_parameters_end_pos) { + ReportMessageAt(Scanner::Location(expected_parameters_end_pos - 2, + expected_parameters_end_pos), + MessageTemplate::kUnexpectedEndOfArgString); + *ok = false; + return nullptr; + } } + Expect(Token::RPAREN, CHECK_OK); + int formals_end_position = scanner()->location().end_pos; + + CheckArityRestrictions(formals.arity, kind, formals.has_rest, + function_scope->start_position(), + formals_end_position, CHECK_OK); + Expect(Token::LBRACE, CHECK_OK); } - Expect(Token::RPAREN, CHECK_OK); - int formals_end_position = scanner()->location().end_pos; *num_parameters = formals.num_parameters(); *function_length = formals.function_length; - CheckArityRestrictions(formals.arity, kind, formals.has_rest, - function_scope->start_position(), formals_end_position, - CHECK_OK); - Expect(Token::LBRACE, CHECK_OK); - ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(8, zone()); ParseFunctionBody(body, function_name, pos, formals, kind, function_type, ok); @@ -3240,9 +3327,10 @@ void Parser::DeclareClassProperty(const AstRawString* class_name, return; } - DCHECK(allow_harmony_public_fields()); + DCHECK(allow_harmony_public_fields() || allow_harmony_private_fields()); if (is_static) { + DCHECK(allow_harmony_static_fields()); class_info->static_fields->Add(property, zone()); } else { class_info->instance_fields->Add(property, zone()); @@ -3262,6 +3350,8 @@ void Parser::DeclareClassProperty(const AstRawString* class_name, FunctionLiteral* Parser::CreateInitializerFunction( DeclarationScope* scope, ZoneList<ClassLiteral::Property*>* fields) { + DCHECK_EQ(scope->function_kind(), + FunctionKind::kClassFieldsInitializerFunction); // function() { .. class fields initializer .. } ZoneList<Statement*>* statements = NewStatementList(1); InitializeClassFieldsStatement* static_fields = @@ -3450,8 +3540,8 @@ void Parser::UpdateStatistics(Isolate* isolate, Handle<Script> script) { } void Parser::ParseOnBackground(ParseInfo* info) { - RuntimeCallTimerScope runtimeTimer(runtime_call_stats_, - &RuntimeCallStats::ParseBackgroundProgram); + RuntimeCallTimerScope runtimeTimer( + runtime_call_stats_, RuntimeCallCounterId::kParseBackgroundProgram); parsing_on_main_thread_ = false; if (!info->script().is_null()) { set_script_id(info->script()->id()); @@ -3581,11 +3671,11 @@ namespace { // http://burtleburtle.net/bob/hash/integer.html uint32_t HalfAvalance(uint32_t a) { - a = (a + 0x479ab41d) + (a << 8); - a = (a ^ 0xe4aa10ce) ^ (a >> 5); - a = (a + 0x9942f0a6) - (a << 14); - a = (a ^ 0x5aedd67d) ^ (a >> 3); - a = (a + 0x17bea992) + (a << 7); + a = (a + 0x479AB41D) + (a << 8); + a = (a ^ 0xE4AA10CE) ^ (a >> 5); + a = (a + 0x9942F0A6) - (a << 14); + a = (a ^ 0x5AEDD67D) ^ (a >> 3); + a = (a + 0x17BEA992) + (a << 7); return a; } @@ -3808,24 +3898,6 @@ void Parser::RewriteAsyncFunctionBody(ZoneList<Statement*>* body, Block* block, body->Add(block, zone()); } -void Parser::RewriteNonPattern(bool* ok) { - ValidateExpression(CHECK_OK_VOID); - auto non_patterns_to_rewrite = function_state_->non_patterns_to_rewrite(); - int begin = classifier()->GetNonPatternBegin(); - int end = non_patterns_to_rewrite->length(); - if (begin < end) { - for (int i = begin; i < end; i++) { - RewritableExpression* expr = non_patterns_to_rewrite->at(i); - // TODO(adamk): Make this more typesafe. - DCHECK(expr->expression()->IsArrayLiteral()); - ArrayLiteral* lit = expr->expression()->AsArrayLiteral(); - expr->Rewrite(RewriteSpreads(lit)); - } - non_patterns_to_rewrite->Rewind(begin); - } -} - - void Parser::RewriteDestructuringAssignments() { const auto& assignments = function_state_->destructuring_assignments_to_rewrite(); @@ -3845,102 +3917,11 @@ void Parser::RewriteDestructuringAssignments() { } } -Expression* Parser::RewriteSpreads(ArrayLiteral* lit) { - // Array literals containing spreads are rewritten using do expressions, e.g. - // [1, 2, 3, ...x, 4, ...y, 5] - // is roughly rewritten as: - // do { - // $R = [1, 2, 3]; - // for ($i of x) %AppendElement($R, $i); - // %AppendElement($R, 4); - // for ($j of y) %AppendElement($R, $j); - // %AppendElement($R, 5); - // $R - // } - // where $R, $i and $j are fresh temporary variables. - ZoneList<Expression*>::iterator s = lit->FirstSpread(); - if (s == lit->EndValue()) return nullptr; // no spread, no rewriting... - Variable* result = NewTemporary(ast_value_factory()->dot_result_string()); - // NOTE: The value assigned to R is the whole original array literal, - // spreads included. This will be fixed before the rewritten AST is returned. - // $R = lit - Expression* init_result = factory()->NewAssignment( - Token::INIT, factory()->NewVariableProxy(result), lit, kNoSourcePosition); - Block* do_block = factory()->NewBlock(16, false); - do_block->statements()->Add( - factory()->NewExpressionStatement(init_result, kNoSourcePosition), - zone()); - // Traverse the array literal starting from the first spread. - while (s != lit->EndValue()) { - Expression* value = *s++; - Spread* spread = value->AsSpread(); - if (spread == nullptr) { - // If the element is not a spread, we're adding a single: - // %AppendElement($R, value) - // or, in case of a hole, - // ++($R.length) - if (!value->IsTheHoleLiteral()) { - ZoneList<Expression*>* append_element_args = NewExpressionList(2); - append_element_args->Add(factory()->NewVariableProxy(result), zone()); - append_element_args->Add(value, zone()); - do_block->statements()->Add( - factory()->NewExpressionStatement( - factory()->NewCallRuntime(Runtime::kAppendElement, - append_element_args, - kNoSourcePosition), - kNoSourcePosition), - zone()); - } else { - Property* length_property = factory()->NewProperty( - factory()->NewVariableProxy(result), - factory()->NewStringLiteral(ast_value_factory()->length_string(), - kNoSourcePosition), - kNoSourcePosition); - CountOperation* count_op = factory()->NewCountOperation( - Token::INC, true /* prefix */, length_property, kNoSourcePosition); - do_block->statements()->Add( - factory()->NewExpressionStatement(count_op, kNoSourcePosition), - zone()); - } - } else { - // If it's a spread, we're adding a for/of loop iterating through it. - Variable* each = NewTemporary(ast_value_factory()->dot_for_string()); - Expression* subject = spread->expression(); - // %AppendElement($R, each) - Statement* append_body; - { - ZoneList<Expression*>* append_element_args = NewExpressionList(2); - append_element_args->Add(factory()->NewVariableProxy(result), zone()); - append_element_args->Add(factory()->NewVariableProxy(each), zone()); - append_body = factory()->NewExpressionStatement( - factory()->NewCallRuntime(Runtime::kAppendElement, - append_element_args, kNoSourcePosition), - kNoSourcePosition); - } - // for (each of spread) %AppendElement($R, each) - ForOfStatement* loop = - factory()->NewForOfStatement(nullptr, kNoSourcePosition); - const bool finalize = false; - InitializeForOfStatement(loop, factory()->NewVariableProxy(each), subject, - append_body, finalize, IteratorType::kNormal); - do_block->statements()->Add(loop, zone()); - } - } - // Now, rewind the original array literal to truncate everything from the - // first spread (included) until the end. This fixes $R's initialization. - lit->RewindSpreads(); - return factory()->NewDoExpression(do_block, result, lit->position()); -} - void Parser::QueueDestructuringAssignmentForRewriting( RewritableExpression* expr) { function_state_->AddDestructuringAssignment(expr); } -void Parser::QueueNonPatternForRewriting(RewritableExpression* expr, bool* ok) { - function_state_->AddNonPatternForRewriting(expr, ok); -} - void Parser::SetFunctionNameFromPropertyName(LiteralProperty* property, const AstRawString* name, const AstRawString* prefix) { @@ -4315,9 +4296,8 @@ void Parser::BuildIteratorCloseForCompletion(ZoneList<Statement*>* statements, zone()); Block* catch_block = factory()->NewBlock(0, false); - Scope* catch_scope = NewHiddenCatchScope(); - try_call_return = factory()->NewTryCatchStatement(try_block, catch_scope, - catch_block, nopos); + try_call_return = + factory()->NewTryCatchStatement(try_block, nullptr, catch_block, nopos); } // let output = %_Call(iteratorReturn, iterator); diff --git a/deps/v8/src/parsing/parser.h b/deps/v8/src/parsing/parser.h index aa800dafc5..f92eddcd9d 100644 --- a/deps/v8/src/parsing/parser.h +++ b/deps/v8/src/parsing/parser.h @@ -267,6 +267,15 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { // Called by ParseProgram after setting up the scanner. FunctionLiteral* DoParseProgram(ParseInfo* info); + // Parse with the script as if the source is implicitly wrapped in a function. + // We manually construct the AST and scopes for a top-level function and the + // function wrapper. + void ParseWrapped(ParseInfo* info, ZoneList<Statement*>* body, + DeclarationScope* scope, Zone* zone, bool* ok); + + ZoneList<const AstRawString*>* PrepareWrappedArguments(ParseInfo* info, + Zone* zone); + void SetCachedData(ParseInfo* info); void StitchAst(ParseInfo* top_level_parse_info, Isolate* isolate); @@ -292,10 +301,12 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { SET_ALLOW(harmony_do_expressions); SET_ALLOW(harmony_function_sent); SET_ALLOW(harmony_public_fields); + SET_ALLOW(harmony_static_fields); SET_ALLOW(harmony_dynamic_import); SET_ALLOW(harmony_import_meta); - SET_ALLOW(harmony_async_iteration); SET_ALLOW(harmony_bigint); + SET_ALLOW(harmony_optional_catch_binding); + SET_ALLOW(harmony_private_fields); #undef SET_ALLOW } return reusable_preparser_; @@ -391,13 +402,14 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { Expression* RewriteDestructuringAssignment(Assignment* assignment); // [if (IteratorType == kAsync)] - // !%_IsJSReceiver(result = Await(iterator.next()) && + // !%_IsJSReceiver(result = Await(next.[[Call]](iterator, « »)) && // %ThrowIteratorResultNotAnObject(result) // [else] - // !%_IsJSReceiver(result = iterator.next()) && + // !%_IsJSReceiver(result = next.[[Call]](iterator, « »)) && // %ThrowIteratorResultNotAnObject(result) // [endif] - Expression* BuildIteratorNextResult(Expression* iterator, Variable* result, + Expression* BuildIteratorNextResult(VariableProxy* iterator, + VariableProxy* next, Variable* result, IteratorType type, int pos); // Initialize the components of a for-in / for-of statement. @@ -425,7 +437,13 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { const AstRawString* name, Scanner::Location function_name_location, FunctionNameValidity function_name_validity, FunctionKind kind, int function_token_position, FunctionLiteral::FunctionType type, - LanguageMode language_mode, bool* ok); + LanguageMode language_mode, + ZoneList<const AstRawString*>* arguments_for_wrapped_function, bool* ok); + + ObjectLiteral* InitializeObjectLiteral(ObjectLiteral* object_literal) { + object_literal->CalculateEmitStore(main_zone()); + return object_literal; + } // Check if the scope has conflicting var/let declarations from different // scopes. This covers for example @@ -488,7 +506,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { FunctionLiteral::FunctionType function_type, DeclarationScope* function_scope, int* num_parameters, int* function_length, bool* has_duplicate_parameters, - int* expected_property_count, bool* ok); + int* expected_property_count, + ZoneList<const AstRawString*>* arguments_for_wrapped_function, bool* ok); void ThrowPendingError(Isolate* isolate, Handle<Script> script); @@ -553,13 +572,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { Expression* RewriteSpreads(ArrayLiteral* lit); - // Rewrite expressions that are not used as patterns - V8_INLINE void RewriteNonPattern(bool* ok); - V8_INLINE void QueueDestructuringAssignmentForRewriting( RewritableExpression* assignment); - V8_INLINE void QueueNonPatternForRewriting(RewritableExpression* expr, - bool* ok); friend class InitializerRewriter; void RewriteParameterInitializer(Expression* expr); @@ -760,17 +774,11 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { bool CollapseNaryExpression(Expression** x, Expression* y, Token::Value op, int pos, const SourceRange& range); - // Rewrites the following types of unary expressions: - // not <literal> -> true / false - // + <numeric literal> -> <numeric literal> - // - <numeric literal> -> <numeric literal with value negated> + // Returns a UnaryExpression or, in one of the following cases, a Literal. // ! <literal> -> true / false - // The following rewriting rules enable the collection of type feedback - // without any special stub and the multiplication is removed later in - // Crankshaft's canonicalization pass. - // + foo -> foo * 1 - // - foo -> foo * (-1) - // ~ foo -> foo ^(~0) + // + <Number literal> -> <Number literal> + // - <Number literal> -> <Number literal with value negated> + // ~ <literal> -> true / false Expression* BuildUnaryExpression(Expression* expression, Token::Value op, int pos); @@ -990,10 +998,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { return function_state_->GetReportedErrorList(); } - V8_INLINE ZoneList<RewritableExpression*>* GetNonPatternList() const { - return function_state_->non_patterns_to_rewrite(); - } - V8_INLINE void CountUsage(v8::Isolate::UseCounterFeature feature) { ++use_counts_[feature]; } diff --git a/deps/v8/src/parsing/pattern-rewriter.cc b/deps/v8/src/parsing/pattern-rewriter.cc index faecb5bb0c..daa126d443 100644 --- a/deps/v8/src/parsing/pattern-rewriter.cc +++ b/deps/v8/src/parsing/pattern-rewriter.cc @@ -445,6 +445,11 @@ void PatternRewriter::VisitArrayLiteral(ArrayLiteral* node, auto iterator = CreateTempVar(factory()->NewGetIterator( factory()->NewVariableProxy(temp), current_value_, IteratorType::kNormal, current_value_->position())); + auto next = CreateTempVar(factory()->NewProperty( + factory()->NewVariableProxy(iterator), + factory()->NewStringLiteral(ast_value_factory()->next_string(), + kNoSourcePosition), + kNoSourcePosition)); auto done = CreateTempVar(factory()->NewBooleanLiteral(false, kNoSourcePosition)); auto result = CreateTempVar(); @@ -525,7 +530,8 @@ void PatternRewriter::VisitArrayLiteral(ArrayLiteral* node, next_block->statements()->Add( factory()->NewExpressionStatement( parser_->BuildIteratorNextResult( - factory()->NewVariableProxy(iterator), result, + factory()->NewVariableProxy(iterator), + factory()->NewVariableProxy(next), result, IteratorType::kNormal, kNoSourcePosition), kNoSourcePosition), zone()); @@ -599,6 +605,7 @@ void PatternRewriter::VisitArrayLiteral(ArrayLiteral* node, // result = IteratorNext(iterator); Statement* get_next = factory()->NewExpressionStatement( parser_->BuildIteratorNextResult(factory()->NewVariableProxy(iterator), + factory()->NewVariableProxy(next), result, IteratorType::kNormal, nopos), nopos); @@ -756,6 +763,7 @@ NOT_A_PATTERN(ImportCallExpression) NOT_A_PATTERN(Literal) NOT_A_PATTERN(NativeFunctionLiteral) NOT_A_PATTERN(RegExpLiteral) +NOT_A_PATTERN(ResolvedProperty) NOT_A_PATTERN(ReturnStatement) NOT_A_PATTERN(SloppyBlockFunctionStatement) NOT_A_PATTERN(Spread) diff --git a/deps/v8/src/parsing/preparsed-scope-data.cc b/deps/v8/src/parsing/preparsed-scope-data.cc index 7191639cf8..786be3f0e5 100644 --- a/deps/v8/src/parsing/preparsed-scope-data.cc +++ b/deps/v8/src/parsing/preparsed-scope-data.cc @@ -24,7 +24,7 @@ class VariableMaybeAssignedField : public BitField8<bool, 0, 1> {}; class VariableContextAllocatedField : public BitField8<bool, VariableMaybeAssignedField::kNext, 1> {}; -const int kMagicValue = 0xc0de0de; +const int kMagicValue = 0xC0DE0DE; #ifdef DEBUG const size_t kUint32Size = 5; @@ -571,8 +571,8 @@ void ConsumedPreParsedScopeData::RestoreData(Scope* scope) { if (scope_data_->RemainingBytes() < kUint8Size) { // Temporary debugging code for detecting inconsistent data. Write debug // information on the stack, then crash. - data_->GetIsolate()->PushStackTraceAndDie(0xc0defee, nullptr, nullptr, - 0xc0defee); + data_->GetIsolate()->PushStackTraceAndDie(0xC0DEFEE, nullptr, nullptr, + 0xC0DEFEE); } // scope_type is stored only in debug mode. diff --git a/deps/v8/src/parsing/preparser.cc b/deps/v8/src/parsing/preparser.cc index 16879e518c..b28eab2e75 100644 --- a/deps/v8/src/parsing/preparser.cc +++ b/deps/v8/src/parsing/preparser.cc @@ -207,12 +207,12 @@ PreParser::PreParseResult PreParser::PreParseFunction( if (!IsArrowFunction(kind) && track_unresolved_variables_ && result == kLazyParsingComplete) { - DeclareFunctionNameVar(function_name, function_type, function_scope); - // Declare arguments after parsing the function since lexical 'arguments' // masks the arguments object. Declare arguments before declaring the // function var since the arguments object masks 'function arguments'. function_scope->DeclareArguments(ast_value_factory()); + + DeclareFunctionNameVar(function_name, function_type, function_scope); } use_counts_ = nullptr; @@ -266,14 +266,18 @@ PreParser::Expression PreParser::ParseFunctionLiteral( Identifier function_name, Scanner::Location function_name_location, FunctionNameValidity function_name_validity, FunctionKind kind, int function_token_pos, FunctionLiteral::FunctionType function_type, - LanguageMode language_mode, bool* ok) { + LanguageMode language_mode, + ZoneList<const AstRawString*>* arguments_for_wrapped_function, bool* ok) { + // Wrapped functions are not parsed in the preparser. + DCHECK_NULL(arguments_for_wrapped_function); + DCHECK_NE(FunctionLiteral::kWrapped, function_type); // Function :: // '(' FormalParameterList? ')' '{' FunctionBody '}' - const RuntimeCallStats::CounterId counters[2][2] = { - {&RuntimeCallStats::PreParseBackgroundNoVariableResolution, - &RuntimeCallStats::PreParseNoVariableResolution}, - {&RuntimeCallStats::PreParseBackgroundWithVariableResolution, - &RuntimeCallStats::PreParseWithVariableResolution}}; + const RuntimeCallCounterId counters[2][2] = { + {RuntimeCallCounterId::kPreParseBackgroundNoVariableResolution, + RuntimeCallCounterId::kPreParseNoVariableResolution}, + {RuntimeCallCounterId::kPreParseBackgroundWithVariableResolution, + RuntimeCallCounterId::kPreParseWithVariableResolution}}; RuntimeCallTimerScope runtime_timer( runtime_call_stats_, counters[track_unresolved_variables_][parsing_on_main_thread_]); diff --git a/deps/v8/src/parsing/preparser.h b/deps/v8/src/parsing/preparser.h index 8c1d183fd6..705cd011ee 100644 --- a/deps/v8/src/parsing/preparser.h +++ b/deps/v8/src/parsing/preparser.h @@ -956,12 +956,18 @@ class PreParser : public ParserBase<PreParser> { bool is_inner_function, bool may_abort, bool* ok) { UNREACHABLE(); } - Expression ParseFunctionLiteral(Identifier name, - Scanner::Location function_name_location, - FunctionNameValidity function_name_validity, - FunctionKind kind, int function_token_pos, - FunctionLiteral::FunctionType function_type, - LanguageMode language_mode, bool* ok); + + Expression ParseFunctionLiteral( + Identifier name, Scanner::Location function_name_location, + FunctionNameValidity function_name_validity, FunctionKind kind, + int function_token_pos, FunctionLiteral::FunctionType function_type, + LanguageMode language_mode, + ZoneList<const AstRawString*>* arguments_for_wrapped_function, bool* ok); + + PreParserExpression InitializeObjectLiteral(PreParserExpression literal) { + return literal; + } + LazyParsingResult ParseStatementListAndLogFunction( PreParserFormalParameters* formals, bool maybe_abort, bool* ok); @@ -999,7 +1005,6 @@ class PreParser : public ParserBase<PreParser> { V8_INLINE void RewriteAsyncFunctionBody( PreParserStatementList body, PreParserStatement block, const PreParserExpression& return_value, bool* ok) {} - V8_INLINE void RewriteNonPattern(bool* ok) { ValidateExpression(ok); } void DeclareAndInitializeVariables( PreParserStatement block, @@ -1186,8 +1191,6 @@ class PreParser : public ParserBase<PreParser> { V8_INLINE void QueueDestructuringAssignmentForRewriting( PreParserExpression assignment) {} - V8_INLINE void QueueNonPatternForRewriting(const PreParserExpression& expr, - bool* ok) {} // Helper functions for recursive descent. V8_INLINE bool IsEval(const PreParserIdentifier& identifier) const { @@ -1665,10 +1668,6 @@ class PreParser : public ParserBase<PreParser> { return function_state_->GetReportedErrorList(); } - V8_INLINE ZoneList<PreParserExpression>* GetNonPatternList() const { - return function_state_->non_patterns_to_rewrite(); - } - V8_INLINE void CountUsage(v8::Isolate::UseCounterFeature feature) { if (use_counts_ != nullptr) ++use_counts_[feature]; } diff --git a/deps/v8/src/parsing/rewriter.cc b/deps/v8/src/parsing/rewriter.cc index c31d0ea21d..102efad292 100644 --- a/deps/v8/src/parsing/rewriter.cc +++ b/deps/v8/src/parsing/rewriter.cc @@ -367,8 +367,8 @@ bool Rewriter::Rewrite(ParseInfo* info) { RuntimeCallTimerScope runtimeTimer( info->runtime_call_stats(), info->on_background_thread() - ? &RuntimeCallStats::CompileBackgroundRewriteReturnResult - : &RuntimeCallStats::CompileRewriteReturnResult); + ? RuntimeCallCounterId::kCompileBackgroundRewriteReturnResult + : RuntimeCallCounterId::kCompileRewriteReturnResult); FunctionLiteral* function = info->literal(); DCHECK_NOT_NULL(function); diff --git a/deps/v8/src/parsing/scanner-character-streams.cc b/deps/v8/src/parsing/scanner-character-streams.cc index c5175c4de7..20aa5c9f8e 100644 --- a/deps/v8/src/parsing/scanner-character-streams.cc +++ b/deps/v8/src/parsing/scanner-character-streams.cc @@ -16,7 +16,7 @@ namespace v8 { namespace internal { namespace { -const unibrow::uchar kUtf8Bom = 0xfeff; +const unibrow::uchar kUtf8Bom = 0xFEFF; } // namespace // ---------------------------------------------------------------------------- @@ -203,7 +203,7 @@ class Utf8ExternalStreamingStream : public BufferedUtf16CharacterStream { Utf8ExternalStreamingStream( ScriptCompiler::ExternalSourceStream* source_stream, RuntimeCallStats* stats) - : current_({0, {0, 0, unibrow::Utf8::Utf8IncrementalBuffer(0)}}), + : current_({0, {0, 0, 0, unibrow::Utf8::State::kAccept}}), source_stream_(source_stream), stats_(stats) {} ~Utf8ExternalStreamingStream() override { @@ -223,7 +223,8 @@ class Utf8ExternalStreamingStream : public BufferedUtf16CharacterStream { struct StreamPosition { size_t bytes; size_t chars; - unibrow::Utf8::Utf8IncrementalBuffer incomplete_char; + uint32_t incomplete_char; + unibrow::Utf8::State state; }; // Position contains a StreamPosition and the index of the chunk the position @@ -268,25 +269,25 @@ bool Utf8ExternalStreamingStream::SkipToPosition(size_t position) { const Chunk& chunk = chunks_[current_.chunk_no]; DCHECK(current_.pos.bytes >= chunk.start.bytes); - unibrow::Utf8::Utf8IncrementalBuffer incomplete_char = - chunk.start.incomplete_char; + unibrow::Utf8::State state = chunk.start.state; + uint32_t incomplete_char = chunk.start.incomplete_char; size_t it = current_.pos.bytes - chunk.start.bytes; size_t chars = chunk.start.chars; while (it < chunk.length && chars < position) { - unibrow::uchar t = - unibrow::Utf8::ValueOfIncremental(chunk.data[it], &incomplete_char); + unibrow::uchar t = unibrow::Utf8::ValueOfIncremental( + chunk.data[it], &it, &state, &incomplete_char); if (t == kUtf8Bom && current_.pos.chars == 0) { // BOM detected at beginning of the stream. Don't copy it. } else if (t != unibrow::Utf8::kIncomplete) { chars++; if (t > unibrow::Utf16::kMaxNonSurrogateCharCode) chars++; } - it++; } current_.pos.bytes += it; current_.pos.chars = chars; current_.pos.incomplete_char = incomplete_char; + current_.pos.state = state; current_.chunk_no += (it == chunk.length); return current_.pos.chars == position; @@ -304,31 +305,33 @@ void Utf8ExternalStreamingStream::FillBufferFromCurrentChunk() { uint16_t* cursor = buffer_ + (buffer_end_ - buffer_start_); DCHECK_EQ(cursor, buffer_end_); + unibrow::Utf8::State state = current_.pos.state; + uint32_t incomplete_char = current_.pos.incomplete_char; + // If the current chunk is the last (empty) chunk we'll have to process // any left-over, partial characters. if (chunk.length == 0) { - unibrow::uchar t = - unibrow::Utf8::ValueOfIncrementalFinish(¤t_.pos.incomplete_char); + unibrow::uchar t = unibrow::Utf8::ValueOfIncrementalFinish(&state); if (t != unibrow::Utf8::kBufferEmpty) { - DCHECK_LT(t, unibrow::Utf16::kMaxNonSurrogateCharCode); + DCHECK_EQ(t, unibrow::Utf8::kBadChar); *cursor = static_cast<uc16>(t); buffer_end_++; current_.pos.chars++; + current_.pos.incomplete_char = 0; + current_.pos.state = state; } return; } - unibrow::Utf8::Utf8IncrementalBuffer incomplete_char = - current_.pos.incomplete_char; - size_t it; - for (it = current_.pos.bytes - chunk.start.bytes; - it < chunk.length && cursor + 1 < buffer_start_ + kBufferSize; it++) { - unibrow::uchar t = - unibrow::Utf8::ValueOfIncremental(chunk.data[it], &incomplete_char); - if (t == unibrow::Utf8::kIncomplete) continue; + size_t it = current_.pos.bytes - chunk.start.bytes; + while (it < chunk.length && cursor + 1 < buffer_start_ + kBufferSize) { + unibrow::uchar t = unibrow::Utf8::ValueOfIncremental( + chunk.data[it], &it, &state, &incomplete_char); if (V8_LIKELY(t < kUtf8Bom)) { *(cursor++) = static_cast<uc16>(t); // The by most frequent case. - } else if (t == kUtf8Bom && current_.pos.bytes + it == 2) { + } else if (t == unibrow::Utf8::kIncomplete) { + continue; + } else if (t == kUtf8Bom && current_.pos.bytes + it == 3) { // BOM detected at beginning of the stream. Don't copy it. } else if (t <= unibrow::Utf16::kMaxNonSurrogateCharCode) { *(cursor++) = static_cast<uc16>(t); @@ -341,13 +344,15 @@ void Utf8ExternalStreamingStream::FillBufferFromCurrentChunk() { current_.pos.bytes = chunk.start.bytes + it; current_.pos.chars += (cursor - buffer_end_); current_.pos.incomplete_char = incomplete_char; + current_.pos.state = state; current_.chunk_no += (it == chunk.length); buffer_end_ = cursor; } bool Utf8ExternalStreamingStream::FetchChunk() { - RuntimeCallTimerScope scope(stats_, &RuntimeCallStats::GetMoreDataCallback); + RuntimeCallTimerScope scope(stats_, + RuntimeCallCounterId::kGetMoreDataCallback); DCHECK_EQ(current_.chunk_no, chunks_.size()); DCHECK(chunks_.empty() || chunks_.back().length != 0); @@ -395,16 +400,15 @@ void Utf8ExternalStreamingStream::SearchPosition(size_t position) { // checking whether the # bytes in a chunk are equal to the # chars, and if // so avoid the expensive SkipToPosition.) bool ascii_only_chunk = - chunks_[chunk_no].start.incomplete_char == - unibrow::Utf8::Utf8IncrementalBuffer(0) && + chunks_[chunk_no].start.incomplete_char == 0 && (chunks_[chunk_no + 1].start.bytes - chunks_[chunk_no].start.bytes) == (chunks_[chunk_no + 1].start.chars - chunks_[chunk_no].start.chars); if (ascii_only_chunk) { size_t skip = position - chunks_[chunk_no].start.chars; current_ = {chunk_no, {chunks_[chunk_no].start.bytes + skip, - chunks_[chunk_no].start.chars + skip, - unibrow::Utf8::Utf8IncrementalBuffer(0)}}; + chunks_[chunk_no].start.chars + skip, 0, + unibrow::Utf8::State::kAccept}}; } else { current_ = {chunk_no, chunks_[chunk_no].start}; SkipToPosition(position); @@ -491,7 +495,8 @@ size_t FindChunk(Chunks& chunks, ScriptCompiler::ExternalSourceStream* source, // Get more data if needed. We usually won't enter the loop body. bool out_of_data = !chunks.empty() && chunks.back().byte_length == 0; { - RuntimeCallTimerScope scope(stats, &RuntimeCallStats::GetMoreDataCallback); + RuntimeCallTimerScope scope(stats, + RuntimeCallCounterId::kGetMoreDataCallback); while (!out_of_data && end_pos <= position + 1) { const uint8_t* chunk = nullptr; size_t len = source->GetMoreData(&chunk); diff --git a/deps/v8/src/parsing/scanner.cc b/deps/v8/src/parsing/scanner.cc index 8030b93889..3152ab184e 100644 --- a/deps/v8/src/parsing/scanner.cc +++ b/deps/v8/src/parsing/scanner.cc @@ -174,31 +174,15 @@ bool Scanner::BookmarkScope::HasBeenApplied() { return bookmark_ == kBookmarkWasApplied; } -// LineTerminator: 'JS_Line_Terminator' in point.properties -// ES#sec-line-terminators lists exactly 4 code points: -// LF (U+000A), CR (U+000D), LS(U+2028), PS(U+2029) -bool Scanner::IsLineTerminator(uc32 c) { - if (c == 0x000A || c == 0x000D) { - return true; - } - if (c == 0x2028 || c == 0x2029) { - ++use_counts_[v8::Isolate::UseCounterFeature:: - kLineOrParagraphSeparatorAsLineTerminator]; - return true; - } - return false; -} - // ---------------------------------------------------------------------------- // Scanner -Scanner::Scanner(UnicodeCache* unicode_cache, int* use_counts) +Scanner::Scanner(UnicodeCache* unicode_cache) : unicode_cache_(unicode_cache), octal_pos_(Location::invalid()), octal_message_(MessageTemplate::kNone), found_html_comment_(false), - allow_harmony_bigint_(false), - use_counts_(use_counts) {} + allow_harmony_bigint_(false) {} void Scanner::Initialize(Utf16CharacterStream* source, bool is_module) { DCHECK_NOT_NULL(source); @@ -257,7 +241,8 @@ uc32 Scanner::ScanUnlimitedLengthHexNumber(int max_value, int beg_pos) { // Ensure that tokens can be stored in a byte. STATIC_ASSERT(Token::NUM_TOKENS <= 0x100); -// Table of one-character tokens, by character (0x00..0x7f only). +// Table of one-character tokens, by character (0x00..0x7F only). +// clang-format off static const byte one_char_tokens[] = { Token::ILLEGAL, Token::ILLEGAL, @@ -303,7 +288,7 @@ static const byte one_char_tokens[] = { Token::RPAREN, // 0x29 Token::ILLEGAL, Token::ILLEGAL, - Token::COMMA, // 0x2c + Token::COMMA, // 0x2C Token::ILLEGAL, Token::ILLEGAL, Token::ILLEGAL, @@ -317,12 +302,12 @@ static const byte one_char_tokens[] = { Token::ILLEGAL, Token::ILLEGAL, Token::ILLEGAL, - Token::COLON, // 0x3a - Token::SEMICOLON, // 0x3b + Token::COLON, // 0x3A + Token::SEMICOLON, // 0x3B Token::ILLEGAL, Token::ILLEGAL, Token::ILLEGAL, - Token::CONDITIONAL, // 0x3f + Token::CONDITIONAL, // 0x3F Token::ILLEGAL, Token::ILLEGAL, Token::ILLEGAL, @@ -350,9 +335,9 @@ static const byte one_char_tokens[] = { Token::ILLEGAL, Token::ILLEGAL, Token::ILLEGAL, - Token::LBRACK, // 0x5b + Token::LBRACK, // 0x5B Token::ILLEGAL, - Token::RBRACK, // 0x5d + Token::RBRACK, // 0x5D Token::ILLEGAL, Token::ILLEGAL, Token::ILLEGAL, @@ -382,13 +367,13 @@ static const byte one_char_tokens[] = { Token::ILLEGAL, Token::ILLEGAL, Token::ILLEGAL, - Token::LBRACE, // 0x7b + Token::LBRACE, // 0x7B Token::ILLEGAL, - Token::RBRACE, // 0x7d - Token::BIT_NOT, // 0x7e + Token::RBRACE, // 0x7D + Token::BIT_NOT, // 0x7E Token::ILLEGAL }; - +// clang-format on Token::Value Scanner::Next() { if (next_.token == Token::EOS) { @@ -405,7 +390,7 @@ Token::Value Scanner::Next() { } has_line_terminator_before_next_ = false; has_multiline_comment_before_next_ = false; - if (static_cast<unsigned>(c0_) <= 0x7f) { + if (static_cast<unsigned>(c0_) <= 0x7F) { Token::Value token = static_cast<Token::Value>(one_char_tokens[c0_]); if (token != Token::ILLEGAL) { int pos = source_pos(); @@ -457,7 +442,7 @@ Token::Value Scanner::SkipWhiteSpace() { // Advance as long as character is a WhiteSpace or LineTerminator. // Remember if the latter is the case. - if (IsLineTerminator(c0_)) { + if (unibrow::IsLineTerminator(c0_)) { has_line_terminator_before_next_ = true; } else if (!unicode_cache_->IsWhiteSpace(c0_)) { break; @@ -514,7 +499,7 @@ Token::Value Scanner::SkipSingleLineComment() { // separately by the lexical grammar and becomes part of the // stream of input elements for the syntactic grammar (see // ECMA-262, section 7.4). - while (c0_ != kEndOfInput && !IsLineTerminator(c0_)) { + while (c0_ != kEndOfInput && !unibrow::IsLineTerminator(c0_)) { Advance(); } @@ -524,7 +509,7 @@ Token::Value Scanner::SkipSingleLineComment() { Token::Value Scanner::SkipSourceURLComment() { TryToParseSourceURLComment(); - while (c0_ != kEndOfInput && !IsLineTerminator(c0_)) { + while (c0_ != kEndOfInput && !unibrow::IsLineTerminator(c0_)) { Advance(); } @@ -560,7 +545,7 @@ void Scanner::TryToParseSourceURLComment() { while (c0_ != kEndOfInput && unicode_cache_->IsWhiteSpace(c0_)) { Advance(); } - while (c0_ != kEndOfInput && !IsLineTerminator(c0_)) { + while (c0_ != kEndOfInput && !unibrow::IsLineTerminator(c0_)) { // Disallowed characters. if (c0_ == '"' || c0_ == '\'') { value->Reset(); @@ -573,7 +558,7 @@ void Scanner::TryToParseSourceURLComment() { Advance(); } // Allow whitespace at the end. - while (c0_ != kEndOfInput && !IsLineTerminator(c0_)) { + while (c0_ != kEndOfInput && !unibrow::IsLineTerminator(c0_)) { if (!unicode_cache_->IsWhiteSpace(c0_)) { value->Reset(); break; @@ -590,7 +575,7 @@ Token::Value Scanner::SkipMultiLineComment() { while (c0_ != kEndOfInput) { uc32 ch = c0_; Advance(); - if (c0_ != kEndOfInput && IsLineTerminator(ch)) { + if (c0_ != kEndOfInput && unibrow::IsLineTerminator(ch)) { // Following ECMA-262, section 7.4, a comment containing // a newline will make the comment count as a line-terminator. has_multiline_comment_before_next_ = true; @@ -875,6 +860,10 @@ void Scanner::Scan() { token = ScanTemplateStart(); break; + case '#': + token = ScanPrivateName(); + break; + default: if (c0_ == kEndOfInput) { token = Token::EOS; @@ -940,6 +929,7 @@ void Scanner::SanityCheckTokenDesc(const TokenDesc& token) const { case Token::REGEXP_LITERAL: case Token::SMI: case Token::STRING: + case Token::PRIVATE_NAME: DCHECK_NOT_NULL(token.literal_chars); DCHECK_NULL(token.raw_literal_chars); DCHECK_EQ(token.invalid_template_escape_message, MessageTemplate::kNone); @@ -987,7 +977,8 @@ bool Scanner::ScanEscape() { Advance<capture_raw>(); // Skip escaped newlines. - if (!in_template_literal && c0_ != kEndOfInput && IsLineTerminator(c)) { + if (!in_template_literal && c0_ != kEndOfInput && + unibrow::IsLineTerminator(c)) { // Allow escaped CR+LF newlines in multiline string literals. if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance<capture_raw>(); return true; @@ -1080,7 +1071,8 @@ Token::Value Scanner::ScanString() { AddLiteralChar(c); } - while (c0_ != quote && c0_ != kEndOfInput && !IsLineTerminator(c0_)) { + while (c0_ != quote && c0_ != kEndOfInput && + !unibrow::IsLineTerminator(c0_)) { uc32 c = c0_; Advance(); if (c == '\\') { @@ -1098,6 +1090,26 @@ Token::Value Scanner::ScanString() { return Token::STRING; } +Token::Value Scanner::ScanPrivateName() { + if (!allow_harmony_private_fields()) { + ReportScannerError(source_pos(), + MessageTemplate::kInvalidOrUnexpectedToken); + return Token::ILLEGAL; + } + + LiteralScope literal(this); + DCHECK_EQ(c0_, '#'); + AddLiteralCharAdvance(); + if (c0_ == kEndOfInput || !unicode_cache_->IsIdentifierStart(c0_)) { + PushBack(c0_); + ReportScannerError(source_pos(), + MessageTemplate::kInvalidOrUnexpectedToken); + return Token::ILLEGAL; + } + + Token::Value token = ScanIdentifierOrKeywordInner(&literal); + return token == Token::ILLEGAL ? Token::ILLEGAL : Token::PRIVATE_NAME; +} Token::Value Scanner::ScanTemplateSpan() { // When scanning a TemplateSpan, we are looking for the following construct: @@ -1136,7 +1148,7 @@ Token::Value Scanner::ScanTemplateSpan() { ReduceRawLiteralLength(2); break; } else if (c == '\\') { - if (c0_ != kEndOfInput && IsLineTerminator(c0_)) { + if (c0_ != kEndOfInput && unibrow::IsLineTerminator(c0_)) { // The TV of LineContinuation :: \ LineTerminatorSequence is the empty // code unit sequence. uc32 lastChar = c0_; @@ -1397,7 +1409,7 @@ uc32 Scanner::ScanUnicodeEscape() { if (c0_ == '{') { int begin = source_pos() - 2; Advance<capture_raw>(); - uc32 cp = ScanUnlimitedLengthHexNumber<capture_raw>(0x10ffff, begin); + uc32 cp = ScanUnlimitedLengthHexNumber<capture_raw>(0x10FFFF, begin); if (cp < 0 || c0_ != '}') { ReportScannerError(source_pos(), MessageTemplate::kInvalidUnicodeEscapeSequence); @@ -1541,10 +1553,13 @@ static Token::Value KeywordOrIdentifierToken(const uint8_t* input, return Token::IDENTIFIER; } - Token::Value Scanner::ScanIdentifierOrKeyword() { - DCHECK(unicode_cache_->IsIdentifierStart(c0_)); LiteralScope literal(this); + return ScanIdentifierOrKeywordInner(&literal); +} + +Token::Value Scanner::ScanIdentifierOrKeywordInner(LiteralScope* literal) { + DCHECK(unicode_cache_->IsIdentifierStart(c0_)); if (IsInRange(c0_, 'a', 'z') || c0_ == '_') { do { char first_char = static_cast<char>(c0_); @@ -1564,7 +1579,7 @@ Token::Value Scanner::ScanIdentifierOrKeyword() { AddLiteralChar(first_char); } if (c0_ <= kMaxAscii && c0_ != '\\') { - literal.Complete(); + literal->Complete(); return Token::IDENTIFIER; } } else if (c0_ <= kMaxAscii && c0_ != '\\') { @@ -1575,7 +1590,7 @@ Token::Value Scanner::ScanIdentifierOrKeyword() { if (token == Token::IDENTIFIER || token == Token::FUTURE_STRICT_RESERVED_WORD || Token::IsContextualKeyword(token)) - literal.Complete(); + literal->Complete(); return token; } @@ -1588,7 +1603,7 @@ Token::Value Scanner::ScanIdentifierOrKeyword() { } while (IsAsciiIdentifier(c0_)); if (c0_ <= kMaxAscii && c0_ != '\\') { - literal.Complete(); + literal->Complete(); return Token::IDENTIFIER; } @@ -1603,7 +1618,7 @@ Token::Value Scanner::ScanIdentifierOrKeyword() { return Token::ILLEGAL; } AddLiteralChar(c); - return ScanIdentifierSuffix(&literal, true); + return ScanIdentifierSuffix(literal, true); } else { uc32 first_char = c0_; Advance(); @@ -1619,7 +1634,7 @@ Token::Value Scanner::ScanIdentifierOrKeyword() { continue; } // Fallthrough if no longer able to complete keyword. - return ScanIdentifierSuffix(&literal, false); + return ScanIdentifierSuffix(literal, false); } if (next_.literal_chars->is_one_byte()) { @@ -1629,10 +1644,10 @@ Token::Value Scanner::ScanIdentifierOrKeyword() { if (token == Token::IDENTIFIER || token == Token::FUTURE_STRICT_RESERVED_WORD || Token::IsContextualKeyword(token)) - literal.Complete(); + literal->Complete(); return token; } - literal.Complete(); + literal->Complete(); return Token::IDENTIFIER; } @@ -1697,12 +1712,12 @@ bool Scanner::ScanRegExpPattern() { } while (c0_ != '/' || in_character_class) { - if (c0_ == kEndOfInput || IsLineTerminator(c0_)) { + if (c0_ == kEndOfInput || unibrow::IsLineTerminator(c0_)) { return false; } if (c0_ == '\\') { // Escape sequence. AddLiteralCharAdvance(); - if (c0_ == kEndOfInput || IsLineTerminator(c0_)) { + if (c0_ == kEndOfInput || unibrow::IsLineTerminator(c0_)) { return false; } AddLiteralCharAdvance(); diff --git a/deps/v8/src/parsing/scanner.h b/deps/v8/src/parsing/scanner.h index 08d77c686b..f5106990ff 100644 --- a/deps/v8/src/parsing/scanner.h +++ b/deps/v8/src/parsing/scanner.h @@ -207,7 +207,7 @@ class Scanner { static const int kNoOctalLocation = -1; static const uc32 kEndOfInput = Utf16CharacterStream::kEndOfInput; - explicit Scanner(UnicodeCache* scanner_contants, int* use_counts_); + explicit Scanner(UnicodeCache* scanner_contants); void Initialize(Utf16CharacterStream* source, bool is_module); @@ -360,6 +360,12 @@ class Scanner { bool allow_harmony_bigint() const { return allow_harmony_bigint_; } void set_allow_harmony_bigint(bool allow) { allow_harmony_bigint_ = allow; } + bool allow_harmony_private_fields() const { + return allow_harmony_private_fields_; + } + void set_allow_harmony_private_fields(bool allow) { + allow_harmony_private_fields_ = allow; + } private: // Scoped helper for saving & restoring scanner error state. @@ -717,9 +723,11 @@ class Scanner { void ScanDecimalDigits(); Token::Value ScanNumber(bool seen_period); Token::Value ScanIdentifierOrKeyword(); + Token::Value ScanIdentifierOrKeywordInner(LiteralScope* literal); Token::Value ScanIdentifierSuffix(LiteralScope* literal, bool escaped); Token::Value ScanString(); + Token::Value ScanPrivateName(); // Scans an escape-sequence which is part of a string and adds the // decoded character to the current literal. Returns true if a pattern @@ -736,8 +744,6 @@ class Scanner { bool is_module_; - bool IsLineTerminator(uc32 c); - Token::Value ScanTemplateSpan(); // Return the current source position. @@ -802,10 +808,9 @@ class Scanner { // Whether this scanner encountered an HTML comment. bool found_html_comment_; - // Whether to recognize BIGINT tokens. + // Harmony flags to allow ESNext features. bool allow_harmony_bigint_; - - int* use_counts_; + bool allow_harmony_private_fields_; MessageTemplate::Template scanner_error_; Location scanner_error_location_; diff --git a/deps/v8/src/parsing/token.h b/deps/v8/src/parsing/token.h index e4a4a5e587..07974edf41 100644 --- a/deps/v8/src/parsing/token.h +++ b/deps/v8/src/parsing/token.h @@ -151,6 +151,7 @@ namespace internal { \ /* Identifiers (not keywords or future reserved words). */ \ T(IDENTIFIER, nullptr, 0) \ + T(PRIVATE_NAME, nullptr, 0) \ \ /* Future reserved words (ECMA-262, section 7.6.1.2). */ \ T(FUTURE_STRICT_RESERVED_WORD, nullptr, 0) \ |