diff options
Diffstat (limited to 'deps/v8/src/parsing')
-rw-r--r-- | deps/v8/src/parsing/DIR_METADATA | 11 | ||||
-rw-r--r-- | deps/v8/src/parsing/OWNERS | 2 | ||||
-rw-r--r-- | deps/v8/src/parsing/parse-info.cc | 2 | ||||
-rw-r--r-- | deps/v8/src/parsing/parse-info.h | 2 | ||||
-rw-r--r-- | deps/v8/src/parsing/parser-base.h | 51 | ||||
-rw-r--r-- | deps/v8/src/parsing/parser.cc | 236 | ||||
-rw-r--r-- | deps/v8/src/parsing/parser.h | 16 | ||||
-rw-r--r-- | deps/v8/src/parsing/rewriter.cc | 49 | ||||
-rw-r--r-- | deps/v8/src/parsing/scanner-character-streams.cc | 4 |
9 files changed, 260 insertions, 113 deletions
diff --git a/deps/v8/src/parsing/DIR_METADATA b/deps/v8/src/parsing/DIR_METADATA new file mode 100644 index 0000000000..165380ae4f --- /dev/null +++ b/deps/v8/src/parsing/DIR_METADATA @@ -0,0 +1,11 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +monorail { + component: "Blink>JavaScript>Parser" +}
\ No newline at end of file diff --git a/deps/v8/src/parsing/OWNERS b/deps/v8/src/parsing/OWNERS index 40e6e8b427..9d54af5f2d 100644 --- a/deps/v8/src/parsing/OWNERS +++ b/deps/v8/src/parsing/OWNERS @@ -5,5 +5,3 @@ littledan@chromium.org marja@chromium.org neis@chromium.org verwaest@chromium.org - -# COMPONENT: Blink>JavaScript>Parser diff --git a/deps/v8/src/parsing/parse-info.cc b/deps/v8/src/parsing/parse-info.cc index 5fd685505c..1c2b1b91ed 100644 --- a/deps/v8/src/parsing/parse-info.cc +++ b/deps/v8/src/parsing/parse-info.cc @@ -32,8 +32,6 @@ UnoptimizedCompileFlags::UnoptimizedCompileFlags(Isolate* isolate, set_might_always_opt(FLAG_always_opt || FLAG_prepare_always_opt); set_allow_natives_syntax(FLAG_allow_natives_syntax); set_allow_lazy_compile(FLAG_lazy); - set_allow_harmony_dynamic_import(FLAG_harmony_dynamic_import); - set_allow_harmony_import_meta(FLAG_harmony_import_meta); set_allow_harmony_private_methods(FLAG_harmony_private_methods); set_collect_source_positions(!FLAG_enable_lazy_source_positions || isolate->NeedsDetailedOptimizedCodeLineInfo()); diff --git a/deps/v8/src/parsing/parse-info.h b/deps/v8/src/parsing/parse-info.h index c774f0ae94..d99ddcda89 100644 --- a/deps/v8/src/parsing/parse-info.h +++ b/deps/v8/src/parsing/parse-info.h @@ -60,8 +60,6 @@ class Zone; V(might_always_opt, bool, 1, _) \ V(allow_natives_syntax, bool, 1, _) \ V(allow_lazy_compile, bool, 1, _) \ - V(allow_harmony_dynamic_import, bool, 1, _) \ - V(allow_harmony_import_meta, bool, 1, _) \ V(allow_harmony_private_methods, bool, 1, _) \ V(is_oneshot_iife, bool, 1, _) \ V(collect_source_positions, bool, 1, _) \ diff --git a/deps/v8/src/parsing/parser-base.h b/deps/v8/src/parsing/parser-base.h index 47981c768b..ee54709345 100644 --- a/deps/v8/src/parsing/parser-base.h +++ b/deps/v8/src/parsing/parser-base.h @@ -1853,7 +1853,6 @@ ParserBase<Impl>::ParsePrimaryExpression() { return ParseSuperExpression(is_new); } case Token::IMPORT: - if (!flags().allow_harmony_dynamic_import()) break; return ParseImportExpressions(); case Token::LBRACK: @@ -2989,15 +2988,12 @@ ParserBase<Impl>::ParseCoalesceExpression(ExpressionT expression) { bool first_nullish = true; while (peek() == Token::NULLISH) { SourceRange right_range; - int pos; - ExpressionT y; - { - SourceRangeScope right_range_scope(scanner(), &right_range); - Consume(Token::NULLISH); - pos = peek_position(); - // Parse BitwiseOR or higher. - y = ParseBinaryExpression(6); - } + SourceRangeScope right_range_scope(scanner(), &right_range); + Consume(Token::NULLISH); + int pos = peek_position(); + + // Parse BitwiseOR or higher. + ExpressionT y = ParseBinaryExpression(6); if (first_nullish) { expression = factory()->NewBinaryOperation(Token::NULLISH, expression, y, pos); @@ -3297,7 +3293,6 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) { bool optional_chaining = false; bool is_optional = false; - int optional_link_begin; do { switch (peek()) { case Token::QUESTION_PERIOD: { @@ -3305,16 +3300,10 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) { ReportUnexpectedToken(peek()); return impl()->FailureExpression(); } - // Include the ?. in the source range position. - optional_link_begin = scanner()->peek_location().beg_pos; Consume(Token::QUESTION_PERIOD); is_optional = true; optional_chaining = true; - if (Token::IsPropertyOrCall(peek())) continue; - int pos = position(); - ExpressionT key = ParsePropertyOrPrivatePropertyName(); - result = factory()->NewProperty(result, key, pos, is_optional); - break; + continue; } /* Property */ @@ -3394,7 +3383,14 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) { } default: - // Template literals in/after an Optional Chain not supported: + /* Optional Property */ + if (is_optional) { + DCHECK_EQ(scanner()->current_token(), Token::QUESTION_PERIOD); + int pos = position(); + ExpressionT key = ParsePropertyOrPrivatePropertyName(); + result = factory()->NewProperty(result, key, pos, is_optional); + break; + } if (optional_chaining) { impl()->ReportMessageAt(scanner()->peek_location(), MessageTemplate::kOptionalChainingNoTemplate); @@ -3405,12 +3401,8 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) { result = ParseTemplateLiteral(result, position(), true); break; } - if (is_optional) { - SourceRange chain_link_range(optional_link_begin, end_position()); - impl()->RecordExpressionSourceRange(result, chain_link_range); - is_optional = false; - } - } while (Token::IsPropertyOrCall(peek())); + is_optional = false; + } while (is_optional || Token::IsPropertyOrCall(peek())); if (optional_chaining) return factory()->NewOptionalChain(result); return result; } @@ -3446,10 +3438,7 @@ ParserBase<Impl>::ParseMemberWithPresentNewPrefixesExpression() { if (peek() == Token::SUPER) { const bool is_new = true; result = ParseSuperExpression(is_new); - } else if (flags().allow_harmony_dynamic_import() && - peek() == Token::IMPORT && - (!flags().allow_harmony_import_meta() || - PeekAhead() == Token::LPAREN)) { + } else if (peek() == Token::IMPORT && PeekAhead() == Token::LPAREN) { impl()->ReportMessageAt(scanner()->peek_location(), MessageTemplate::kImportCallNotNewExpression); return impl()->FailureExpression(); @@ -3547,11 +3536,9 @@ ParserBase<Impl>::ParseMemberExpression() { template <typename Impl> typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseImportExpressions() { - DCHECK(flags().allow_harmony_dynamic_import()); - Consume(Token::IMPORT); int pos = position(); - if (flags().allow_harmony_import_meta() && Check(Token::PERIOD)) { + if (Check(Token::PERIOD)) { ExpectContextualKeyword(ast_value_factory()->meta_string(), "import.meta", pos); if (!flags().is_module()) { diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc index b05ae32bba..c65c1dc6b6 100644 --- a/deps/v8/src/parsing/parser.cc +++ b/deps/v8/src/parsing/parser.cc @@ -27,6 +27,7 @@ #include "src/runtime/runtime.h" #include "src/strings/char-predicates-inl.h" #include "src/strings/string-stream.h" +#include "src/strings/unicode-inl.h" #include "src/tracing/trace-event.h" #include "src/zone/zone-list-inl.h" @@ -1033,9 +1034,7 @@ Statement* Parser::ParseModuleItem() { // We must be careful not to parse a dynamic import expression as an import // declaration. Same for import.meta expressions. Token::Value peek_ahead = PeekAhead(); - if ((!flags().allow_harmony_dynamic_import() || - peek_ahead != Token::LPAREN) && - (!flags().allow_harmony_import_meta() || peek_ahead != Token::PERIOD)) { + if (peek_ahead != Token::LPAREN && peek_ahead != Token::PERIOD) { ParseImportDeclaration(); return factory()->EmptyStatement(); } @@ -1071,7 +1070,8 @@ const AstRawString* Parser::ParseModuleSpecifier() { } ZoneChunkList<Parser::ExportClauseData>* Parser::ParseExportClause( - Scanner::Location* reserved_loc) { + Scanner::Location* reserved_loc, + Scanner::Location* string_literal_local_name_loc) { // ExportClause : // '{' '}' // '{' ExportsList '}' @@ -1084,6 +1084,12 @@ ZoneChunkList<Parser::ExportClauseData>* Parser::ParseExportClause( // ExportSpecifier : // IdentifierName // IdentifierName 'as' IdentifierName + // IdentifierName 'as' ModuleExportName + // ModuleExportName + // ModuleExportName 'as' ModuleExportName + // + // ModuleExportName : + // StringLiteral ZoneChunkList<ExportClauseData>* export_data = zone()->New<ZoneChunkList<ExportClauseData>>(zone()); @@ -1091,23 +1097,27 @@ ZoneChunkList<Parser::ExportClauseData>* Parser::ParseExportClause( Token::Value name_tok; while ((name_tok = peek()) != Token::RBRACE) { - // Keep track of the first reserved word encountered in case our - // caller needs to report an error. - if (!reserved_loc->IsValid() && - !Token::IsValidIdentifier(name_tok, LanguageMode::kStrict, false, - flags().is_module())) { + const AstRawString* local_name = ParseExportSpecifierName(); + if (!string_literal_local_name_loc->IsValid() && + name_tok == Token::STRING) { + // Keep track of the first string literal local name exported for error + // reporting. These must be followed by a 'from' clause. + *string_literal_local_name_loc = scanner()->location(); + } else if (!reserved_loc->IsValid() && + !Token::IsValidIdentifier(name_tok, LanguageMode::kStrict, false, + flags().is_module())) { + // Keep track of the first reserved word encountered in case our + // caller needs to report an error. *reserved_loc = scanner()->location(); } - const AstRawString* local_name = ParsePropertyName(); - const AstRawString* export_name = nullptr; + const AstRawString* export_name; Scanner::Location location = scanner()->location(); if (CheckContextualKeyword(ast_value_factory()->as_string())) { - export_name = ParsePropertyName(); + export_name = ParseExportSpecifierName(); // Set the location to the whole "a as b" string, so that it makes sense // both for errors due to "a" and for errors due to "b". location.end_pos = scanner()->location().end_pos; - } - if (export_name == nullptr) { + } else { export_name = local_name; } export_data->push_back({export_name, local_name, location}); @@ -1122,6 +1132,31 @@ ZoneChunkList<Parser::ExportClauseData>* Parser::ParseExportClause( return export_data; } +const AstRawString* Parser::ParseExportSpecifierName() { + Token::Value next = Next(); + + // IdentifierName + if (V8_LIKELY(Token::IsPropertyName(next))) { + return GetSymbol(); + } + + // ModuleExportName + if (next == Token::STRING) { + const AstRawString* export_name = GetSymbol(); + if (V8_LIKELY(export_name->is_one_byte())) return export_name; + if (!unibrow::Utf16::HasUnpairedSurrogate( + reinterpret_cast<const uint16_t*>(export_name->raw_data()), + export_name->length())) { + return export_name; + } + ReportMessage(MessageTemplate::kInvalidModuleExportName); + return EmptyIdentifierString(); + } + + ReportUnexpectedToken(next); + return EmptyIdentifierString(); +} + ZonePtrList<const Parser::NamedImport>* Parser::ParseNamedImports(int pos) { // NamedImports : // '{' '}' @@ -1135,12 +1170,13 @@ ZonePtrList<const Parser::NamedImport>* Parser::ParseNamedImports(int pos) { // ImportSpecifier : // BindingIdentifier // IdentifierName 'as' BindingIdentifier + // ModuleExportName 'as' BindingIdentifier Expect(Token::LBRACE); auto result = zone()->New<ZonePtrList<const NamedImport>>(1, zone()); while (peek() != Token::RBRACE) { - const AstRawString* import_name = ParsePropertyName(); + const AstRawString* import_name = ParseExportSpecifierName(); const AstRawString* local_name = import_name; Scanner::Location location = scanner()->location(); // In the presence of 'as', the left-side of the 'as' can @@ -1174,10 +1210,80 @@ ZonePtrList<const Parser::NamedImport>* Parser::ParseNamedImports(int pos) { return result; } +Parser::ImportAssertions* Parser::ParseImportAssertClause() { + // AssertClause : + // assert '{' '}' + // assert '{' AssertEntries '}' + + // AssertEntries : + // IdentifierName: AssertionKey + // IdentifierName: AssertionKey , AssertEntries + + // AssertionKey : + // IdentifierName + // StringLiteral + + auto import_assertions = zone()->New<ImportAssertions>(zone()); + + if (!FLAG_harmony_import_assertions) { + return import_assertions; + } + + // Assert clause is optional, and cannot be preceded by a LineTerminator. + if (scanner()->HasLineTerminatorBeforeNext() || + !CheckContextualKeyword(ast_value_factory()->assert_string())) { + return import_assertions; + } + + Expect(Token::LBRACE); + + while (peek() != Token::RBRACE) { + const AstRawString* attribute_key = nullptr; + if (Check(Token::STRING)) { + attribute_key = GetSymbol(); + } else { + attribute_key = ParsePropertyName(); + } + + Scanner::Location location = scanner()->location(); + + Expect(Token::COLON); + Expect(Token::STRING); + + const AstRawString* attribute_value = GetSymbol(); + + // Set the location to the whole "key: 'value'"" string, so that it makes + // sense both for errors due to the key and errors due to the value. + location.end_pos = scanner()->location().end_pos; + + auto result = import_assertions->insert(std::make_pair( + attribute_key, std::make_pair(attribute_value, location))); + if (!result.second) { + // It is a syntax error if two AssertEntries have the same key. + ReportMessageAt(location, MessageTemplate::kImportAssertionDuplicateKey, + attribute_key); + break; + } + + if (peek() == Token::RBRACE) break; + if (V8_UNLIKELY(!Check(Token::COMMA))) { + ReportUnexpectedToken(Next()); + break; + } + } + + Expect(Token::RBRACE); + + return import_assertions; +} + void Parser::ParseImportDeclaration() { // ImportDeclaration : // 'import' ImportClause 'from' ModuleSpecifier ';' // 'import' ModuleSpecifier ';' + // 'import' ImportClause 'from' ModuleSpecifier [no LineTerminator here] + // AssertClause ';' + // 'import' ModuleSpecifier [no LineTerminator here] AssertClause';' // // ImportClause : // ImportedDefaultBinding @@ -1198,8 +1304,10 @@ void Parser::ParseImportDeclaration() { if (tok == Token::STRING) { Scanner::Location specifier_loc = scanner()->peek_location(); const AstRawString* module_specifier = ParseModuleSpecifier(); + const ImportAssertions* import_assertions = ParseImportAssertClause(); ExpectSemicolon(); - module()->AddEmptyImport(module_specifier, specifier_loc); + module()->AddEmptyImport(module_specifier, import_assertions, specifier_loc, + zone()); return; } @@ -1242,6 +1350,7 @@ void Parser::ParseImportDeclaration() { ExpectContextualKeyword(ast_value_factory()->from_string()); Scanner::Location specifier_loc = scanner()->peek_location(); const AstRawString* module_specifier = ParseModuleSpecifier(); + const ImportAssertions* import_assertions = ParseImportAssertClause(); ExpectSemicolon(); // Now that we have all the information, we can make the appropriate @@ -1254,24 +1363,26 @@ void Parser::ParseImportDeclaration() { if (module_namespace_binding != nullptr) { module()->AddStarImport(module_namespace_binding, module_specifier, - module_namespace_binding_loc, specifier_loc, - zone()); + import_assertions, module_namespace_binding_loc, + specifier_loc, zone()); } if (import_default_binding != nullptr) { module()->AddImport(ast_value_factory()->default_string(), import_default_binding, module_specifier, - import_default_binding_loc, specifier_loc, zone()); + import_assertions, import_default_binding_loc, + specifier_loc, zone()); } if (named_imports != nullptr) { if (named_imports->length() == 0) { - module()->AddEmptyImport(module_specifier, specifier_loc); + module()->AddEmptyImport(module_specifier, import_assertions, + specifier_loc, zone()); } else { for (const NamedImport* import : *named_imports) { module()->AddImport(import->import_name, import->local_name, - module_specifier, import->location, specifier_loc, - zone()); + module_specifier, import_assertions, + import->location, specifier_loc, zone()); } } } @@ -1354,18 +1465,18 @@ void Parser::ParseExportStar() { int pos = position(); Consume(Token::MUL); - if (!FLAG_harmony_namespace_exports || - !PeekContextualKeyword(ast_value_factory()->as_string())) { + if (!PeekContextualKeyword(ast_value_factory()->as_string())) { // 'export' '*' 'from' ModuleSpecifier ';' Scanner::Location loc = scanner()->location(); ExpectContextualKeyword(ast_value_factory()->from_string()); Scanner::Location specifier_loc = scanner()->peek_location(); const AstRawString* module_specifier = ParseModuleSpecifier(); + const ImportAssertions* import_assertions = ParseImportAssertClause(); ExpectSemicolon(); - module()->AddStarExport(module_specifier, loc, specifier_loc, zone()); + module()->AddStarExport(module_specifier, import_assertions, loc, + specifier_loc, zone()); return; } - if (!FLAG_harmony_namespace_exports) return; // 'export' '*' 'as' IdentifierName 'from' ModuleSpecifier ';' // @@ -1373,9 +1484,14 @@ void Parser::ParseExportStar() { // export * as x from "..."; // ~> // import * as .x from "..."; export {.x as x}; + // + // Note that the desugared internal namespace export name (.x above) will + // never conflict with a string literal export name, as literal string export + // names in local name positions (i.e. left of 'as' or in a clause without + // 'as') are disallowed without a following 'from' clause. ExpectContextualKeyword(ast_value_factory()->as_string()); - const AstRawString* export_name = ParsePropertyName(); + const AstRawString* export_name = ParseExportSpecifierName(); Scanner::Location export_name_loc = scanner()->location(); const AstRawString* local_name = NextInternalNamespaceExportName(); Scanner::Location local_name_loc = Scanner::Location::invalid(); @@ -1385,21 +1501,34 @@ void Parser::ParseExportStar() { ExpectContextualKeyword(ast_value_factory()->from_string()); Scanner::Location specifier_loc = scanner()->peek_location(); const AstRawString* module_specifier = ParseModuleSpecifier(); + const ImportAssertions* import_assertions = ParseImportAssertClause(); ExpectSemicolon(); - module()->AddStarImport(local_name, module_specifier, local_name_loc, - specifier_loc, zone()); + module()->AddStarImport(local_name, module_specifier, import_assertions, + local_name_loc, specifier_loc, zone()); module()->AddExport(local_name, export_name, export_name_loc, zone()); } Statement* Parser::ParseExportDeclaration() { // ExportDeclaration: // 'export' '*' 'from' ModuleSpecifier ';' + // 'export' '*' 'from' ModuleSpecifier [no LineTerminator here] + // AssertClause ';' // 'export' '*' 'as' IdentifierName 'from' ModuleSpecifier ';' + // 'export' '*' 'as' IdentifierName 'from' ModuleSpecifier + // [no LineTerminator here] AssertClause ';' + // 'export' '*' 'as' ModuleExportName 'from' ModuleSpecifier ';' + // 'export' '*' 'as' ModuleExportName 'from' ModuleSpecifier ';' + // [no LineTerminator here] AssertClause ';' // 'export' ExportClause ('from' ModuleSpecifier)? ';' + // 'export' ExportClause ('from' ModuleSpecifier [no LineTerminator here] + // AssertClause)? ';' // 'export' VariableStatement // 'export' Declaration // 'export' 'default' ... (handled in ParseExportDefault) + // + // ModuleExportName : + // StringLiteral Expect(Token::EXPORT); Statement* result = nullptr; @@ -1426,30 +1555,41 @@ Statement* Parser::ParseExportDeclaration() { // encountered, and then throw a SyntaxError if we are in the // non-FromClause case. Scanner::Location reserved_loc = Scanner::Location::invalid(); + Scanner::Location string_literal_local_name_loc = + Scanner::Location::invalid(); ZoneChunkList<ExportClauseData>* export_data = - ParseExportClause(&reserved_loc); - const AstRawString* module_specifier = nullptr; - Scanner::Location specifier_loc; + ParseExportClause(&reserved_loc, &string_literal_local_name_loc); if (CheckContextualKeyword(ast_value_factory()->from_string())) { - specifier_loc = scanner()->peek_location(); - module_specifier = ParseModuleSpecifier(); - } else if (reserved_loc.IsValid()) { - // No FromClause, so reserved words are invalid in ExportClause. - ReportMessageAt(reserved_loc, MessageTemplate::kUnexpectedReserved); - return nullptr; - } - ExpectSemicolon(); - if (module_specifier == nullptr) { - for (const ExportClauseData& data : *export_data) { - module()->AddExport(data.local_name, data.export_name, data.location, - zone()); + Scanner::Location specifier_loc = scanner()->peek_location(); + const AstRawString* module_specifier = ParseModuleSpecifier(); + const ImportAssertions* import_assertions = ParseImportAssertClause(); + ExpectSemicolon(); + + if (export_data->is_empty()) { + module()->AddEmptyImport(module_specifier, import_assertions, + specifier_loc, zone()); + } else { + for (const ExportClauseData& data : *export_data) { + module()->AddExport(data.local_name, data.export_name, + module_specifier, import_assertions, + data.location, specifier_loc, zone()); + } } - } else if (export_data->is_empty()) { - module()->AddEmptyImport(module_specifier, specifier_loc); } else { + if (reserved_loc.IsValid()) { + // No FromClause, so reserved words are invalid in ExportClause. + ReportMessageAt(reserved_loc, MessageTemplate::kUnexpectedReserved); + return nullptr; + } else if (string_literal_local_name_loc.IsValid()) { + ReportMessageAt(string_literal_local_name_loc, + MessageTemplate::kModuleExportNameWithoutFromClause); + return nullptr; + } + + ExpectSemicolon(); + for (const ExportClauseData& data : *export_data) { - module()->AddExport(data.local_name, data.export_name, - module_specifier, data.location, specifier_loc, + module()->AddExport(data.local_name, data.export_name, data.location, zone()); } } diff --git a/deps/v8/src/parsing/parser.h b/deps/v8/src/parsing/parser.h index 8897030a0c..073f517b56 100644 --- a/deps/v8/src/parsing/parser.h +++ b/deps/v8/src/parsing/parser.h @@ -269,7 +269,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { Scanner::Location location; }; ZoneChunkList<ExportClauseData>* ParseExportClause( - Scanner::Location* reserved_loc); + Scanner::Location* reserved_loc, + Scanner::Location* string_literal_local_name_loc); struct NamedImport : public ZoneObject { const AstRawString* import_name; const AstRawString* local_name; @@ -280,7 +281,12 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { local_name(local_name), location(location) {} }; + const AstRawString* ParseExportSpecifierName(); ZonePtrList<const NamedImport>* ParseNamedImports(int pos); + using ImportAssertions = + ZoneMap<const AstRawString*, + std::pair<const AstRawString*, Scanner::Location>>; + ImportAssertions* ParseImportAssertClause(); Statement* BuildInitializationBlock(DeclarationParsingResult* parsing_result); Expression* RewriteReturn(Expression* return_value, int pos); Statement* RewriteSwitchStatement(SwitchStatement* switch_statement, @@ -997,14 +1003,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { node, zone()->New<IterationStatementSourceRanges>(body_range)); } - // Used to record source ranges of expressions associated with optional chain: - V8_INLINE void RecordExpressionSourceRange(Expression* node, - const SourceRange& right_range) { - if (source_range_map_ == nullptr) return; - source_range_map_->Insert(node, - zone()->New<ExpressionSourceRanges>(right_range)); - } - V8_INLINE void RecordSuspendSourceRange(Expression* node, int32_t continuation_position) { if (source_range_map_ == nullptr) return; diff --git a/deps/v8/src/parsing/rewriter.cc b/deps/v8/src/parsing/rewriter.cc index 942acf13f8..36461ee762 100644 --- a/deps/v8/src/parsing/rewriter.cc +++ b/deps/v8/src/parsing/rewriter.cc @@ -246,23 +246,40 @@ void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) { is_set_ = true; Visit(node->finally_block()); node->set_finally_block(replacement_->AsBlock()); - // Save .result value at the beginning of the finally block and restore it - // at the end again: ".backup = .result; ...; .result = .backup" - // This is necessary because the finally block does not normally contribute - // to the completion value. CHECK_NOT_NULL(closure_scope()); - Variable* backup = closure_scope()->NewTemporary( - factory()->ast_value_factory()->dot_result_string()); - Expression* backup_proxy = factory()->NewVariableProxy(backup); - Expression* result_proxy = factory()->NewVariableProxy(result_); - Expression* save = factory()->NewAssignment( - Token::ASSIGN, backup_proxy, result_proxy, kNoSourcePosition); - Expression* restore = factory()->NewAssignment( - Token::ASSIGN, result_proxy, backup_proxy, kNoSourcePosition); - node->finally_block()->statements()->InsertAt( - 0, factory()->NewExpressionStatement(save, kNoSourcePosition), zone()); - node->finally_block()->statements()->Add( - factory()->NewExpressionStatement(restore, kNoSourcePosition), zone()); + if (is_set_) { + // Save .result value at the beginning of the finally block and restore it + // at the end again: ".backup = .result; ...; .result = .backup" This is + // necessary because the finally block does not normally contribute to the + // completion value. + Variable* backup = closure_scope()->NewTemporary( + factory()->ast_value_factory()->dot_result_string()); + Expression* backup_proxy = factory()->NewVariableProxy(backup); + Expression* result_proxy = factory()->NewVariableProxy(result_); + Expression* save = factory()->NewAssignment( + Token::ASSIGN, backup_proxy, result_proxy, kNoSourcePosition); + Expression* restore = factory()->NewAssignment( + Token::ASSIGN, result_proxy, backup_proxy, kNoSourcePosition); + node->finally_block()->statements()->InsertAt( + 0, factory()->NewExpressionStatement(save, kNoSourcePosition), + zone()); + node->finally_block()->statements()->Add( + factory()->NewExpressionStatement(restore, kNoSourcePosition), + zone()); + } else { + // If is_set_ is false, it means the finally block has a 'break' or a + // 'continue' and was not preceded by a statement that assigned to + // .result. Try-finally statements return the abrupt completions from the + // finally block, meaning this case should get an undefined. + // + // Since the finally block will definitely result in an abrupt completion, + // there's no need to save and restore the .result. + Expression* undef = factory()->NewUndefinedLiteral(kNoSourcePosition); + Expression* assignment = SetResult(undef); + node->finally_block()->statements()->InsertAt( + 0, factory()->NewExpressionStatement(assignment, kNoSourcePosition), + zone()); + } // We can't tell whether the finally-block is guaranteed to set .result, so // reset is_set_ before visiting the try-block. is_set_ = false; diff --git a/deps/v8/src/parsing/scanner-character-streams.cc b/deps/v8/src/parsing/scanner-character-streams.cc index 1414b3490b..dde90d910f 100644 --- a/deps/v8/src/parsing/scanner-character-streams.cc +++ b/deps/v8/src/parsing/scanner-character-streams.cc @@ -331,7 +331,7 @@ class UnbufferedCharacterStream : public Utf16CharacterStream { // Provides a unbuffered utf-16 view on the bytes from the underlying // ByteStream. -class RelocatingCharacterStream +class RelocatingCharacterStream final : public UnbufferedCharacterStream<OnHeapStream> { public: template <class... TArgs> @@ -422,7 +422,7 @@ bool BufferedUtf16CharacterStream::ReadBlock() { // TODO(verwaest): Decode utf8 chunks into utf16 chunks on the blink side // instead so we don't need to buffer. -class Utf8ExternalStreamingStream : public BufferedUtf16CharacterStream { +class Utf8ExternalStreamingStream final : public BufferedUtf16CharacterStream { public: Utf8ExternalStreamingStream( ScriptCompiler::ExternalSourceStream* source_stream) |