Commit 1aa7e197 authored by Daniel Clark's avatar Daniel Clark Committed by Commit Bot

Implement parsing of empty import assertion clause

This is the first change in the process of implementing import
assertions per https://tc39.es/proposal-import-assertions/.

This CR adds support for the empty form of the AssertClause.

Also added is a --harmony-import-assertions flag to enable/disable
import assertions.  For now, the feature is off by default.

The next change will enable the parser to handle a non-empty list
of AssertEntries.

Bug: v8:10958
Change-Id: I0832d89effc27225aa4430605a51690461daf7ad
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2468623Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Commit-Queue: Dan Clark <daniec@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#70545}
parent ebcff9e1
......@@ -211,6 +211,7 @@ class AstBigInt {
F(anonymous_function, "(anonymous function)") \
F(arguments, "arguments") \
F(as, "as") \
F(assert, "assert") \
F(async, "async") \
F(await, "await") \
F(bigint, "bigint") \
......
......@@ -254,7 +254,8 @@ DEFINE_IMPLICATION(harmony_weak_refs_with_cleanup_some, harmony_weak_refs)
V(harmony_regexp_sequence, "RegExp Unicode sequence properties") \
V(harmony_weak_refs_with_cleanup_some, \
"harmony weak references with FinalizationRegistry.prototype.cleanupSome") \
V(harmony_regexp_match_indices, "harmony regexp match indices")
V(harmony_regexp_match_indices, "harmony regexp match indices") \
V(harmony_import_assertions, "harmony import assertions")
#ifdef V8_INTL_SUPPORT
#define HARMONY_INPROGRESS(V) \
......
......@@ -4131,6 +4131,7 @@ EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_import_meta)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_regexp_sequence)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_top_level_await)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_logical_assignment)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_import_assertions)
#ifdef V8_INTL_SUPPORT
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_intl_displaynames_date_types)
......
......@@ -133,6 +133,7 @@
V(_, ArrayBuffer_string, "ArrayBuffer") \
V(_, ArrayIterator_string, "Array Iterator") \
V(_, as_string, "as") \
V(_, assert_string, "assert") \
V(_, async_string, "async") \
V(_, auto_string, "auto") \
V(_, await_string, "await") \
......
......@@ -1174,10 +1174,43 @@ ZonePtrList<const Parser::NamedImport>* Parser::ParseNamedImports(int pos) {
return result;
}
void Parser::ParseImportAssertClause() {
// AssertClause :
// assert '{' '}'
// assert '{' AssertEntries '}'
// AssertEntries :
// IdentifierName: AssertionKey
// IdentifierName: AssertionKey , AssertEntries
// AssertionKey :
// IdentifierName
// StringLiteral
if (!FLAG_harmony_import_assertions) {
return;
}
// Assert clause is optional, and cannot be preceded by a LineTerminator.
if (scanner()->HasLineTerminatorBeforeNext() ||
!CheckContextualKeyword(ast_value_factory()->assert_string())) {
return;
}
Expect(Token::LBRACE);
// TODO(v8:10958) Parse the list of assertions and return the result.
Expect(Token::RBRACE);
}
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,6 +1231,7 @@ void Parser::ParseImportDeclaration() {
if (tok == Token::STRING) {
Scanner::Location specifier_loc = scanner()->peek_location();
const AstRawString* module_specifier = ParseModuleSpecifier();
ParseImportAssertClause();
ExpectSemicolon();
module()->AddEmptyImport(module_specifier, specifier_loc);
return;
......@@ -1242,6 +1276,7 @@ void Parser::ParseImportDeclaration() {
ExpectContextualKeyword(ast_value_factory()->from_string());
Scanner::Location specifier_loc = scanner()->peek_location();
const AstRawString* module_specifier = ParseModuleSpecifier();
ParseImportAssertClause();
ExpectSemicolon();
// Now that we have all the information, we can make the appropriate
......@@ -1361,6 +1396,7 @@ void Parser::ParseExportStar() {
ExpectContextualKeyword(ast_value_factory()->from_string());
Scanner::Location specifier_loc = scanner()->peek_location();
const AstRawString* module_specifier = ParseModuleSpecifier();
ParseImportAssertClause();
ExpectSemicolon();
module()->AddStarExport(module_specifier, loc, specifier_loc, zone());
return;
......@@ -1385,6 +1421,7 @@ void Parser::ParseExportStar() {
ExpectContextualKeyword(ast_value_factory()->from_string());
Scanner::Location specifier_loc = scanner()->peek_location();
const AstRawString* module_specifier = ParseModuleSpecifier();
ParseImportAssertClause();
ExpectSemicolon();
module()->AddStarImport(local_name, module_specifier, local_name_loc,
......@@ -1395,8 +1432,14 @@ void Parser::ParseExportStar() {
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' ExportClause ('from' ModuleSpecifier)? ';'
// 'export' ExportClause ('from' ModuleSpecifier [no LineTerminator here]
// AssertClause)? ';'
// 'export' VariableStatement
// 'export' Declaration
// 'export' 'default' ... (handled in ParseExportDefault)
......@@ -1428,28 +1471,32 @@ Statement* Parser::ParseExportDeclaration() {
Scanner::Location reserved_loc = Scanner::Location::invalid();
ZoneChunkList<ExportClauseData>* export_data =
ParseExportClause(&reserved_loc);
const AstRawString* module_specifier = nullptr;
Scanner::Location specifier_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();
ParseImportAssertClause();
ExpectSemicolon();
if (export_data->is_empty()) {
module()->AddEmptyImport(module_specifier, specifier_loc);
} else {
for (const ExportClauseData& data : *export_data) {
module()->AddExport(data.local_name, data.export_name,
module_specifier, 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;
}
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());
}
}
......
......@@ -281,6 +281,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
location(location) {}
};
ZonePtrList<const NamedImport>* ParseNamedImports(int pos);
void ParseImportAssertClause();
Statement* BuildInitializationBlock(DeclarationParsingResult* parsing_result);
Expression* RewriteReturn(Expression* return_value, int pos);
Statement* RewriteSwitchStatement(SwitchStatement* switch_statement,
......
......@@ -5001,6 +5001,111 @@ TEST(ImportExpressionErrors) {
}
}
TEST(BasicImportAssertionParsing) {
// clang-format off
const char* kSources[] = {
"import { a as b } from 'm.js' assert { };",
"import n from 'n.js' assert { };",
"export { a as b } from 'm.js' assert { };",
"export * from 'm.js' assert { };",
"import 'm.js' assert { };",
"import * as foo from 'bar.js' assert { };",
};
// clang-format on
i::FLAG_harmony_import_assertions = true;
i::Isolate* isolate = CcTest::i_isolate();
i::Factory* factory = isolate->factory();
v8::HandleScope handles(CcTest::isolate());
v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
v8::Context::Scope context_scope(context);
isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
128 * 1024);
for (unsigned i = 0; i < arraysize(kSources); ++i) {
i::Handle<i::String> source =
factory->NewStringFromAsciiChecked(kSources[i]);
// Show that parsing as a module works
{
i::Handle<i::Script> script = factory->NewScript(source);
i::UnoptimizedCompileState compile_state(isolate);
i::UnoptimizedCompileFlags flags =
i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
flags.set_is_module(true);
i::ParseInfo info(isolate, flags, &compile_state);
CHECK_PARSE_PROGRAM(&info, script, isolate);
}
// And that parsing a script does not.
{
i::UnoptimizedCompileState compile_state(isolate);
i::Handle<i::Script> script = factory->NewScript(source);
i::UnoptimizedCompileFlags flags =
i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
i::ParseInfo info(isolate, flags, &compile_state);
CHECK(!i::parsing::ParseProgram(&info, script, isolate,
parsing::ReportStatisticsMode::kYes));
CHECK(info.pending_error_handler()->has_pending_error());
}
}
}
TEST(ImportAssertionParsingErrors) {
// clang-format off
const char* kErrorSources[] = {
"import { a } from 'm.js' assert {;",
"import { a } from 'm.js' assert };",
"import { a } from 'm.js' , assert { };",
"import { a } from 'm.js' assert , { };",
"import { a } from 'm.js' assert { , };",
"import { a } from 'm.js' assert { b };",
"import { a } from 'm.js' assert { 'b' };",
"import { a } from 'm.js' assert { for };",
"import { a } from 'm.js' assert { assert };",
"export { a } assert { };",
"export * assert { };",
"import 'm.js'\n assert { };",
"import 'm.js' \nassert { };",
"import { a } from 'm.js'\n assert { };",
"export * from 'm.js'\n assert { };",
"import { a } from 'm.js' assert { 1: 2 };",
"import { a } from 'm.js' assert { b: c };",
"import { a } from 'm.js' assert { a: 'b', a: 'c' };",
};
// clang-format on
i::FLAG_harmony_import_assertions = true;
i::Isolate* isolate = CcTest::i_isolate();
i::Factory* factory = isolate->factory();
v8::HandleScope handles(CcTest::isolate());
v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
v8::Context::Scope context_scope(context);
isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
128 * 1024);
for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
i::Handle<i::String> source =
factory->NewStringFromAsciiChecked(kErrorSources[i]);
i::Handle<i::Script> script = factory->NewScript(source);
i::UnoptimizedCompileState compile_state(isolate);
i::UnoptimizedCompileFlags flags =
i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script);
flags.set_is_module(true);
i::ParseInfo info(isolate, flags, &compile_state);
CHECK(!i::parsing::ParseProgram(&info, script, isolate,
parsing::ReportStatisticsMode::kYes));
CHECK(info.pending_error_handler()->has_pending_error());
}
}
TEST(SuperCall) {
const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
......
......@@ -298,65 +298,65 @@ KNOWN_MAPS = {
("read_only_space", 0x031b9): (67, "BasicBlockCountersMarkerMap"),
("read_only_space", 0x031fd): (87, "ArrayBoilerplateDescriptionMap"),
("read_only_space", 0x032cd): (99, "InterceptorInfoMap"),
("read_only_space", 0x053c1): (72, "PromiseFulfillReactionJobTaskMap"),
("read_only_space", 0x053e9): (73, "PromiseRejectReactionJobTaskMap"),
("read_only_space", 0x05411): (74, "CallableTaskMap"),
("read_only_space", 0x05439): (75, "CallbackTaskMap"),
("read_only_space", 0x05461): (76, "PromiseResolveThenableJobTaskMap"),
("read_only_space", 0x05489): (79, "FunctionTemplateInfoMap"),
("read_only_space", 0x054b1): (80, "ObjectTemplateInfoMap"),
("read_only_space", 0x054d9): (81, "AccessCheckInfoMap"),
("read_only_space", 0x05501): (82, "AccessorInfoMap"),
("read_only_space", 0x05529): (83, "AccessorPairMap"),
("read_only_space", 0x05551): (84, "AliasedArgumentsEntryMap"),
("read_only_space", 0x05579): (85, "AllocationMementoMap"),
("read_only_space", 0x055a1): (88, "AsmWasmDataMap"),
("read_only_space", 0x055c9): (89, "AsyncGeneratorRequestMap"),
("read_only_space", 0x055f1): (90, "BreakPointMap"),
("read_only_space", 0x05619): (91, "BreakPointInfoMap"),
("read_only_space", 0x05641): (92, "CachedTemplateObjectMap"),
("read_only_space", 0x05669): (94, "ClassPositionsMap"),
("read_only_space", 0x05691): (95, "DebugInfoMap"),
("read_only_space", 0x056b9): (98, "FunctionTemplateRareDataMap"),
("read_only_space", 0x056e1): (100, "InterpreterDataMap"),
("read_only_space", 0x05709): (101, "PromiseCapabilityMap"),
("read_only_space", 0x05731): (102, "PromiseReactionMap"),
("read_only_space", 0x05759): (103, "PropertyDescriptorObjectMap"),
("read_only_space", 0x05781): (104, "PrototypeInfoMap"),
("read_only_space", 0x057a9): (105, "ScriptMap"),
("read_only_space", 0x057d1): (106, "SourceTextModuleInfoEntryMap"),
("read_only_space", 0x057f9): (107, "StackFrameInfoMap"),
("read_only_space", 0x05821): (108, "StackTraceFrameMap"),
("read_only_space", 0x05849): (109, "TemplateObjectDescriptionMap"),
("read_only_space", 0x05871): (110, "Tuple2Map"),
("read_only_space", 0x05899): (111, "WasmCapiFunctionDataMap"),
("read_only_space", 0x058c1): (112, "WasmExceptionTagMap"),
("read_only_space", 0x058e9): (113, "WasmExportedFunctionDataMap"),
("read_only_space", 0x05911): (114, "WasmIndirectFunctionTableMap"),
("read_only_space", 0x05939): (115, "WasmJSFunctionDataMap"),
("read_only_space", 0x05961): (116, "WasmValueMap"),
("read_only_space", 0x05989): (135, "SloppyArgumentsElementsMap"),
("read_only_space", 0x059b1): (172, "OnHeapBasicBlockProfilerDataMap"),
("read_only_space", 0x059d9): (169, "InternalClassMap"),
("read_only_space", 0x05a01): (178, "SmiPairMap"),
("read_only_space", 0x05a29): (177, "SmiBoxMap"),
("read_only_space", 0x05a51): (146, "ExportedSubClassBaseMap"),
("read_only_space", 0x05a79): (147, "ExportedSubClassMap"),
("read_only_space", 0x05aa1): (68, "AbstractInternalClassSubclass1Map"),
("read_only_space", 0x05ac9): (69, "AbstractInternalClassSubclass2Map"),
("read_only_space", 0x05af1): (134, "InternalClassWithSmiElementsMap"),
("read_only_space", 0x05b19): (170, "InternalClassWithStructElementsMap"),
("read_only_space", 0x05b41): (148, "ExportedSubClass2Map"),
("read_only_space", 0x05b69): (179, "SortStateMap"),
("read_only_space", 0x05b91): (86, "AllocationSiteWithWeakNextMap"),
("read_only_space", 0x05bb9): (86, "AllocationSiteWithoutWeakNextMap"),
("read_only_space", 0x05be1): (77, "LoadHandler1Map"),
("read_only_space", 0x05c09): (77, "LoadHandler2Map"),
("read_only_space", 0x05c31): (77, "LoadHandler3Map"),
("read_only_space", 0x05c59): (78, "StoreHandler0Map"),
("read_only_space", 0x05c81): (78, "StoreHandler1Map"),
("read_only_space", 0x05ca9): (78, "StoreHandler2Map"),
("read_only_space", 0x05cd1): (78, "StoreHandler3Map"),
("read_only_space", 0x053d5): (72, "PromiseFulfillReactionJobTaskMap"),
("read_only_space", 0x053fd): (73, "PromiseRejectReactionJobTaskMap"),
("read_only_space", 0x05425): (74, "CallableTaskMap"),
("read_only_space", 0x0544d): (75, "CallbackTaskMap"),
("read_only_space", 0x05475): (76, "PromiseResolveThenableJobTaskMap"),
("read_only_space", 0x0549d): (79, "FunctionTemplateInfoMap"),
("read_only_space", 0x054c5): (80, "ObjectTemplateInfoMap"),
("read_only_space", 0x054ed): (81, "AccessCheckInfoMap"),
("read_only_space", 0x05515): (82, "AccessorInfoMap"),
("read_only_space", 0x0553d): (83, "AccessorPairMap"),
("read_only_space", 0x05565): (84, "AliasedArgumentsEntryMap"),
("read_only_space", 0x0558d): (85, "AllocationMementoMap"),
("read_only_space", 0x055b5): (88, "AsmWasmDataMap"),
("read_only_space", 0x055dd): (89, "AsyncGeneratorRequestMap"),
("read_only_space", 0x05605): (90, "BreakPointMap"),
("read_only_space", 0x0562d): (91, "BreakPointInfoMap"),
("read_only_space", 0x05655): (92, "CachedTemplateObjectMap"),
("read_only_space", 0x0567d): (94, "ClassPositionsMap"),
("read_only_space", 0x056a5): (95, "DebugInfoMap"),
("read_only_space", 0x056cd): (98, "FunctionTemplateRareDataMap"),
("read_only_space", 0x056f5): (100, "InterpreterDataMap"),
("read_only_space", 0x0571d): (101, "PromiseCapabilityMap"),
("read_only_space", 0x05745): (102, "PromiseReactionMap"),
("read_only_space", 0x0576d): (103, "PropertyDescriptorObjectMap"),
("read_only_space", 0x05795): (104, "PrototypeInfoMap"),
("read_only_space", 0x057bd): (105, "ScriptMap"),
("read_only_space", 0x057e5): (106, "SourceTextModuleInfoEntryMap"),
("read_only_space", 0x0580d): (107, "StackFrameInfoMap"),
("read_only_space", 0x05835): (108, "StackTraceFrameMap"),
("read_only_space", 0x0585d): (109, "TemplateObjectDescriptionMap"),
("read_only_space", 0x05885): (110, "Tuple2Map"),
("read_only_space", 0x058ad): (111, "WasmCapiFunctionDataMap"),
("read_only_space", 0x058d5): (112, "WasmExceptionTagMap"),
("read_only_space", 0x058fd): (113, "WasmExportedFunctionDataMap"),
("read_only_space", 0x05925): (114, "WasmIndirectFunctionTableMap"),
("read_only_space", 0x0594d): (115, "WasmJSFunctionDataMap"),
("read_only_space", 0x05975): (116, "WasmValueMap"),
("read_only_space", 0x0599d): (135, "SloppyArgumentsElementsMap"),
("read_only_space", 0x059c5): (172, "OnHeapBasicBlockProfilerDataMap"),
("read_only_space", 0x059ed): (169, "InternalClassMap"),
("read_only_space", 0x05a15): (178, "SmiPairMap"),
("read_only_space", 0x05a3d): (177, "SmiBoxMap"),
("read_only_space", 0x05a65): (146, "ExportedSubClassBaseMap"),
("read_only_space", 0x05a8d): (147, "ExportedSubClassMap"),
("read_only_space", 0x05ab5): (68, "AbstractInternalClassSubclass1Map"),
("read_only_space", 0x05add): (69, "AbstractInternalClassSubclass2Map"),
("read_only_space", 0x05b05): (134, "InternalClassWithSmiElementsMap"),
("read_only_space", 0x05b2d): (170, "InternalClassWithStructElementsMap"),
("read_only_space", 0x05b55): (148, "ExportedSubClass2Map"),
("read_only_space", 0x05b7d): (179, "SortStateMap"),
("read_only_space", 0x05ba5): (86, "AllocationSiteWithWeakNextMap"),
("read_only_space", 0x05bcd): (86, "AllocationSiteWithoutWeakNextMap"),
("read_only_space", 0x05bf5): (77, "LoadHandler1Map"),
("read_only_space", 0x05c1d): (77, "LoadHandler2Map"),
("read_only_space", 0x05c45): (77, "LoadHandler3Map"),
("read_only_space", 0x05c6d): (78, "StoreHandler0Map"),
("read_only_space", 0x05c95): (78, "StoreHandler1Map"),
("read_only_space", 0x05cbd): (78, "StoreHandler2Map"),
("read_only_space", 0x05ce5): (78, "StoreHandler3Map"),
("map_space", 0x02115): (1057, "ExternalMap"),
("map_space", 0x0213d): (1072, "JSMessageObjectMap"),
("map_space", 0x02165): (181, "WasmRttEqrefMap"),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment