summaryrefslogtreecommitdiff
path: root/deps/v8/src/parsing
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/parsing')
-rw-r--r--deps/v8/src/parsing/DIR_METADATA11
-rw-r--r--deps/v8/src/parsing/OWNERS2
-rw-r--r--deps/v8/src/parsing/parse-info.cc2
-rw-r--r--deps/v8/src/parsing/parse-info.h2
-rw-r--r--deps/v8/src/parsing/parser-base.h51
-rw-r--r--deps/v8/src/parsing/parser.cc236
-rw-r--r--deps/v8/src/parsing/parser.h16
-rw-r--r--deps/v8/src/parsing/rewriter.cc49
-rw-r--r--deps/v8/src/parsing/scanner-character-streams.cc4
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)