From 16fd730e95eac2754e876aafc0b7efe587b30001 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sun, 22 Oct 2023 13:18:21 +0200 Subject: [PATCH] deps: V8: cherry-pick a0fd3209dda8 Original commit message: [import-attributes] Implement import attributes, with `assert` fallback In the past six months, the old import assertions proposal has been renamed to "import attributes" with the follwing major changes: 1. the keyword is now `with` instead of `assert` 2. unknown assertions cause an error rather than being ignored To preserve backward compatibility with existing applications that use `assert`, implementations _can_ keep it around as a fallback for both the static and dynamic forms. Additionally, the proposal has some minor changes that came up during the stage 3 reviews: 3. dynamic import first reads all the attributes, and then verifies that they are all strings 4. there is no need for a `[no LineTerminator here]` restriction before the `with` keyword 5. static import syntax allows any `LiteralPropertyName` as attribute keys, to align with every other syntax using key-value pairs The new syntax is enabled by a new `--harmony-import-attributes` flag, disabled by default. However, the new behavioral changes also apply to the old syntax that is under the `--harmony-import-assertions` flag. This patch does implements (1), (3), (4) and (5). Handling of unknown import assertions was not implemented directly in V8, but delegated to embedders. As such, it will be implemented separately in d8 and Chromium. To simplify the review, this patch doesn't migrate usage of the term "assertions" to "attributes". There are many variables and internal functions that could be easily renamed as soon as this patch landes. There is one usage in the public API (`ModuleRequest::GetImportAssertions`) that will probably need to be aliased and then removed following the same process as for other API breaking changes. Bug: v8:13856 Change-Id: I78b167348d898887332c5ca7468bc5d58cd9b1ca Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4632799 Commit-Queue: Shu-yu Guo Reviewed-by: Adam Klein Cr-Commit-Position: refs/heads/main@{#89110} Refs: https://github.com/v8/v8/commit/159c82c5e6392e78b9bba7161b1bed6e23758984 Refs: https://github.com/v8/v8/commit/a0fd3209dda8527d7da810abe231df27fffe789e PR-URL: https://github.com/nodejs/node/pull/50183 Reviewed-By: Geoffrey Booth --- common.gypi | 2 +- deps/v8/include/v8-script.h | 7 +- deps/v8/src/execution/isolate.cc | 48 +++- deps/v8/src/flags/flag-definitions.h | 1 + deps/v8/src/init/bootstrapper.cc | 1 + deps/v8/src/init/heap-symbols.h | 1 + deps/v8/src/parsing/parser-base.h | 4 +- deps/v8/src/parsing/parser.cc | 39 +-- deps/v8/src/roots/static-roots.h | 146 +++++------ .../harmony/modules-import-attributes-1.mjs | 9 + .../harmony/modules-import-attributes-2.mjs | 9 + .../harmony/modules-import-attributes-3.mjs | 9 + .../harmony/modules-import-attributes-4.mjs | 9 + .../modules-import-attributes-dynamic-1.mjs | 12 + .../modules-import-attributes-dynamic-10.mjs | 19 ++ .../modules-import-attributes-dynamic-11.mjs | 19 ++ .../modules-import-attributes-dynamic-12.mjs | 26 ++ .../modules-import-attributes-dynamic-13.mjs | 26 ++ .../modules-import-attributes-dynamic-2.mjs | 13 + .../modules-import-attributes-dynamic-3.mjs | 13 + .../modules-import-attributes-dynamic-4.mjs | 14 ++ .../modules-import-attributes-dynamic-5.mjs | 12 + .../modules-import-attributes-dynamic-6.mjs | 18 ++ .../modules-import-attributes-dynamic-7.mjs | 63 +++++ .../modules-import-attributes-dynamic-8.mjs | 13 + .../modules-import-attributes-dynamic-9.mjs | 13 + ...tributes-dynamic-assertions-fallback-1.mjs | 15 ++ ...tributes-dynamic-assertions-fallback-2.mjs | 15 ++ .../test/unittests/parser/parsing-unittest.cc | 229 ++++++++++++++++++ 29 files changed, 698 insertions(+), 107 deletions(-) create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-1.mjs create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-2.mjs create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-3.mjs create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-4.mjs create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-1.mjs create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-10.mjs create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-11.mjs create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-12.mjs create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-13.mjs create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-2.mjs create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-3.mjs create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-4.mjs create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-5.mjs create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-6.mjs create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-7.mjs create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-8.mjs create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-9.mjs create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-assertions-fallback-1.mjs create mode 100644 deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-assertions-fallback-2.mjs diff --git a/common.gypi b/common.gypi index 4c856c0912260c..dd79c43462bec9 100644 --- a/common.gypi +++ b/common.gypi @@ -36,7 +36,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.17', + 'v8_embedder_string': '-node.18', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/include/v8-script.h b/deps/v8/include/v8-script.h index 4a8ccab7e28d1d..f15d148b28d85c 100644 --- a/deps/v8/include/v8-script.h +++ b/deps/v8/include/v8-script.h @@ -142,10 +142,9 @@ class V8_EXPORT ModuleRequest : public Data { * * All assertions present in the module request will be supplied in this * list, regardless of whether they are supported by the host. Per - * https://tc39.es/proposal-import-assertions/#sec-hostgetsupportedimportassertions, - * hosts are expected to ignore assertions that they do not support (as - * opposed to, for example, triggering an error if an unsupported assertion is - * present). + * https://tc39.es/proposal-import-attributes/#sec-hostgetsupportedimportattributes, + * hosts are expected to throw for assertions that they do not support (as + * opposed to, for example, ignoring them). */ Local GetImportAssertions() const; diff --git a/deps/v8/src/execution/isolate.cc b/deps/v8/src/execution/isolate.cc index 06c707da96ca34..1c63f0c56bf719 100644 --- a/deps/v8/src/execution/isolate.cc +++ b/deps/v8/src/execution/isolate.cc @@ -5156,7 +5156,8 @@ MaybeHandle Isolate::GetImportAssertionsFromArgument( // The parser shouldn't have allowed the second argument to import() if // the flag wasn't enabled. - DCHECK(v8_flags.harmony_import_assertions); + DCHECK(v8_flags.harmony_import_assertions || + v8_flags.harmony_import_attributes); if (!import_assertions_argument->IsJSReceiver()) { this->Throw( @@ -5166,18 +5167,35 @@ MaybeHandle Isolate::GetImportAssertionsFromArgument( Handle import_assertions_argument_receiver = Handle::cast(import_assertions_argument); - Handle key = factory()->assert_string(); Handle import_assertions_object; - if (!JSReceiver::GetProperty(this, import_assertions_argument_receiver, key) - .ToHandle(&import_assertions_object)) { - // This can happen if the property has a getter function that throws - // an error. - return MaybeHandle(); + + if (v8_flags.harmony_import_attributes) { + Handle with_key = factory()->with_string(); + if (!JSReceiver::GetProperty(this, import_assertions_argument_receiver, + with_key) + .ToHandle(&import_assertions_object)) { + // This can happen if the property has a getter function that throws + // an error. + return MaybeHandle(); + } } - // If there is no 'assert' option in the options bag, it's not an error. Just - // do the import() as if no assertions were provided. + if (v8_flags.harmony_import_assertions && + (!v8_flags.harmony_import_attributes || + import_assertions_object->IsUndefined())) { + Handle assert_key = factory()->assert_string(); + if (!JSReceiver::GetProperty(this, import_assertions_argument_receiver, + assert_key) + .ToHandle(&import_assertions_object)) { + // This can happen if the property has a getter function that throws + // an error. + return MaybeHandle(); + } + } + + // If there is no 'with' or 'assert' option in the options bag, it's not an + // error. Just do the import() as if no assertions were provided. if (import_assertions_object->IsUndefined()) return import_assertions_array; if (!import_assertions_object->IsJSReceiver()) { @@ -5199,6 +5217,8 @@ MaybeHandle Isolate::GetImportAssertionsFromArgument( return MaybeHandle(); } + bool has_non_string_attribute = false; + // The assertions will be passed to the host in the form: [key1, // value1, key2, value2, ...]. constexpr size_t kAssertionEntrySizeForDynamicImport = 2; @@ -5216,9 +5236,7 @@ MaybeHandle Isolate::GetImportAssertionsFromArgument( } if (!assertion_value->IsString()) { - this->Throw(*factory()->NewTypeError( - MessageTemplate::kNonStringImportAssertionValue)); - return MaybeHandle(); + has_non_string_attribute = true; } import_assertions_array->set((i * kAssertionEntrySizeForDynamicImport), @@ -5227,6 +5245,12 @@ MaybeHandle Isolate::GetImportAssertionsFromArgument( *assertion_value); } + if (has_non_string_attribute) { + this->Throw(*factory()->NewTypeError( + MessageTemplate::kNonStringImportAssertionValue)); + return MaybeHandle(); + } + return import_assertions_array; } diff --git a/deps/v8/src/flags/flag-definitions.h b/deps/v8/src/flags/flag-definitions.h index 8a3ab897c67e98..1bb489833b81f8 100644 --- a/deps/v8/src/flags/flag-definitions.h +++ b/deps/v8/src/flags/flag-definitions.h @@ -235,6 +235,7 @@ DEFINE_BOOL(harmony_shipping, true, "enable all shipped harmony features") // Features that are still work in progress (behind individual flags). #define HARMONY_INPROGRESS_BASE(V) \ + V(harmony_import_attributes, "harmony import attributes") \ V(harmony_weak_refs_with_cleanup_some, \ "harmony weak references with FinalizationRegistry.prototype.cleanupSome") \ V(harmony_temporal, "Temporal") \ diff --git a/deps/v8/src/init/bootstrapper.cc b/deps/v8/src/init/bootstrapper.cc index 69d01ff33902aa..c468c502e703df 100644 --- a/deps/v8/src/init/bootstrapper.cc +++ b/deps/v8/src/init/bootstrapper.cc @@ -4523,6 +4523,7 @@ void Genesis::InitializeConsole(Handle extras_binding) { void Genesis::InitializeGlobal_##id() {} EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_import_assertions) +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_import_attributes) EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_symbol_as_weakmap_key) EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_rab_gsab_transfer) diff --git a/deps/v8/src/init/heap-symbols.h b/deps/v8/src/init/heap-symbols.h index 5388b88d4e7599..1ca46fdc81faa4 100644 --- a/deps/v8/src/init/heap-symbols.h +++ b/deps/v8/src/init/heap-symbols.h @@ -462,6 +462,7 @@ V(_, week_string, "week") \ V(_, weeks_string, "weeks") \ V(_, weekOfYear_string, "weekOfYear") \ + V(_, with_string, "with") \ V(_, word_string, "word") \ V(_, yearMonthFromFields_string, "yearMonthFromFields") \ V(_, year_string, "year") \ diff --git a/deps/v8/src/parsing/parser-base.h b/deps/v8/src/parsing/parser-base.h index ff5af7dfec9204..cfba92d7e884b8 100644 --- a/deps/v8/src/parsing/parser-base.h +++ b/deps/v8/src/parsing/parser-base.h @@ -3774,7 +3774,9 @@ ParserBase::ParseImportExpressions() { AcceptINScope scope(this, true); ExpressionT specifier = ParseAssignmentExpressionCoverGrammar(); - if (v8_flags.harmony_import_assertions && Check(Token::COMMA)) { + if ((v8_flags.harmony_import_assertions || + v8_flags.harmony_import_attributes) && + Check(Token::COMMA)) { if (Check(Token::RPAREN)) { // A trailing comma allowed after the specifier. return factory()->NewImportCallExpression(specifier, pos); diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc index 6886e037ac2f97..336d88b2ea195b 100644 --- a/deps/v8/src/parsing/parser.cc +++ b/deps/v8/src/parsing/parser.cc @@ -1344,27 +1344,28 @@ ZonePtrList* Parser::ParseNamedImports(int pos) { } ImportAssertions* Parser::ParseImportAssertClause() { - // AssertClause : - // assert '{' '}' - // assert '{' AssertEntries '}' + // WithClause : + // with '{' '}' + // with '{' WithEntries ','? '}' - // AssertEntries : - // IdentifierName: AssertionKey - // IdentifierName: AssertionKey , AssertEntries + // WithEntries : + // LiteralPropertyName + // LiteralPropertyName ':' StringLiteral , WithEntries - // AssertionKey : - // IdentifierName - // StringLiteral + // (DEPRECATED) + // AssertClause : + // assert '{' '}' + // assert '{' WithEntries ','? '}' auto import_assertions = zone()->New(zone()); - if (!v8_flags.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())) { + if (v8_flags.harmony_import_attributes && Check(Token::WITH)) { + // 'with' keyword consumed + } else if (v8_flags.harmony_import_assertions && + !scanner()->HasLineTerminatorBeforeNext() && + CheckContextualKeyword(ast_value_factory()->assert_string())) { + // 'assert' keyword consumed + } else { return import_assertions; } @@ -1372,8 +1373,12 @@ ImportAssertions* Parser::ParseImportAssertClause() { while (peek() != Token::RBRACE) { const AstRawString* attribute_key = nullptr; - if (Check(Token::STRING)) { + if (Check(Token::STRING) || Check(Token::SMI)) { attribute_key = GetSymbol(); + } else if (Check(Token::NUMBER)) { + attribute_key = GetNumberAsSymbol(); + } else if (Check(Token::BIGINT)) { + attribute_key = GetBigIntAsSymbol(); } else { attribute_key = ParsePropertyName(); } diff --git a/deps/v8/src/roots/static-roots.h b/deps/v8/src/roots/static-roots.h index df53f43736888f..16729572de88fc 100644 --- a/deps/v8/src/roots/static-roots.h +++ b/deps/v8/src/roots/static-roots.h @@ -693,82 +693,83 @@ struct StaticReadOnlyRoot { static constexpr Tagged_t kweek_string = 0x5a55; static constexpr Tagged_t kweeks_string = 0x5a65; static constexpr Tagged_t kweekOfYear_string = 0x5a79; - static constexpr Tagged_t kword_string = 0x5a91; - static constexpr Tagged_t kyearMonthFromFields_string = 0x5aa1; - static constexpr Tagged_t kyear_string = 0x5ac1; - static constexpr Tagged_t kyears_string = 0x5ad1; - static constexpr Tagged_t kUninitializedValue = 0x5af5; - static constexpr Tagged_t kArgumentsMarker = 0x5b2d; - static constexpr Tagged_t kTerminationException = 0x5b65; - static constexpr Tagged_t kException = 0x5ba5; - static constexpr Tagged_t kOptimizedOut = 0x5bc1; - static constexpr Tagged_t kStaleRegister = 0x5bf9; - static constexpr Tagged_t kSelfReferenceMarker = 0x5c31; - static constexpr Tagged_t kBasicBlockCountersMarker = 0x5c71; - static constexpr Tagged_t karray_buffer_wasm_memory_symbol = 0x5cb5; - static constexpr Tagged_t kcall_site_info_symbol = 0x5cc5; - static constexpr Tagged_t kconsole_context_id_symbol = 0x5cd5; - static constexpr Tagged_t kconsole_context_name_symbol = 0x5ce5; - static constexpr Tagged_t kclass_fields_symbol = 0x5cf5; - static constexpr Tagged_t kclass_positions_symbol = 0x5d05; - static constexpr Tagged_t kerror_end_pos_symbol = 0x5d15; - static constexpr Tagged_t kerror_script_symbol = 0x5d25; - static constexpr Tagged_t kerror_stack_symbol = 0x5d35; - static constexpr Tagged_t kerror_start_pos_symbol = 0x5d45; - static constexpr Tagged_t kfrozen_symbol = 0x5d55; - static constexpr Tagged_t kinterpreter_trampoline_symbol = 0x5d65; - static constexpr Tagged_t knative_context_index_symbol = 0x5d75; - static constexpr Tagged_t knonextensible_symbol = 0x5d85; - static constexpr Tagged_t kpromise_debug_marker_symbol = 0x5d95; - static constexpr Tagged_t kpromise_debug_message_symbol = 0x5da5; - static constexpr Tagged_t kpromise_forwarding_handler_symbol = 0x5db5; - static constexpr Tagged_t kpromise_handled_by_symbol = 0x5dc5; - static constexpr Tagged_t kpromise_awaited_by_symbol = 0x5dd5; - static constexpr Tagged_t kregexp_result_names_symbol = 0x5de5; - static constexpr Tagged_t kregexp_result_regexp_input_symbol = 0x5df5; - static constexpr Tagged_t kregexp_result_regexp_last_index_symbol = 0x5e05; - static constexpr Tagged_t ksealed_symbol = 0x5e15; - static constexpr Tagged_t kstrict_function_transition_symbol = 0x5e25; + static constexpr Tagged_t kwith_string = 0x5a91; + static constexpr Tagged_t kword_string = 0x5aa1; + static constexpr Tagged_t kyearMonthFromFields_string = 0x5ab1; + static constexpr Tagged_t kyear_string = 0x5ad1; + static constexpr Tagged_t kyears_string = 0x5ae1; + static constexpr Tagged_t kUninitializedValue = 0x5b05; + static constexpr Tagged_t kArgumentsMarker = 0x5b3d; + static constexpr Tagged_t kTerminationException = 0x5b75; + static constexpr Tagged_t kException = 0x5bb5; + static constexpr Tagged_t kOptimizedOut = 0x5bd1; + static constexpr Tagged_t kStaleRegister = 0x5c09; + static constexpr Tagged_t kSelfReferenceMarker = 0x5c41; + static constexpr Tagged_t kBasicBlockCountersMarker = 0x5c81; + static constexpr Tagged_t karray_buffer_wasm_memory_symbol = 0x5cc5; + static constexpr Tagged_t kcall_site_info_symbol = 0x5cd5; + static constexpr Tagged_t kconsole_context_id_symbol = 0x5ce5; + static constexpr Tagged_t kconsole_context_name_symbol = 0x5cf5; + static constexpr Tagged_t kclass_fields_symbol = 0x5d05; + static constexpr Tagged_t kclass_positions_symbol = 0x5d15; + static constexpr Tagged_t kerror_end_pos_symbol = 0x5d25; + static constexpr Tagged_t kerror_script_symbol = 0x5d35; + static constexpr Tagged_t kerror_stack_symbol = 0x5d45; + static constexpr Tagged_t kerror_start_pos_symbol = 0x5d55; + static constexpr Tagged_t kfrozen_symbol = 0x5d65; + static constexpr Tagged_t kinterpreter_trampoline_symbol = 0x5d75; + static constexpr Tagged_t knative_context_index_symbol = 0x5d85; + static constexpr Tagged_t knonextensible_symbol = 0x5d95; + static constexpr Tagged_t kpromise_debug_marker_symbol = 0x5da5; + static constexpr Tagged_t kpromise_debug_message_symbol = 0x5db5; + static constexpr Tagged_t kpromise_forwarding_handler_symbol = 0x5dc5; + static constexpr Tagged_t kpromise_handled_by_symbol = 0x5dd5; + static constexpr Tagged_t kpromise_awaited_by_symbol = 0x5de5; + static constexpr Tagged_t kregexp_result_names_symbol = 0x5df5; + static constexpr Tagged_t kregexp_result_regexp_input_symbol = 0x5e05; + static constexpr Tagged_t kregexp_result_regexp_last_index_symbol = 0x5e15; + static constexpr Tagged_t ksealed_symbol = 0x5e25; + static constexpr Tagged_t kstrict_function_transition_symbol = 0x5e35; static constexpr Tagged_t ktemplate_literal_function_literal_id_symbol = - 0x5e35; - static constexpr Tagged_t ktemplate_literal_slot_id_symbol = 0x5e45; - static constexpr Tagged_t kwasm_exception_tag_symbol = 0x5e55; - static constexpr Tagged_t kwasm_exception_values_symbol = 0x5e65; - static constexpr Tagged_t kwasm_uncatchable_symbol = 0x5e75; - static constexpr Tagged_t kwasm_wrapped_object_symbol = 0x5e85; - static constexpr Tagged_t kwasm_debug_proxy_cache_symbol = 0x5e95; - static constexpr Tagged_t kwasm_debug_proxy_names_symbol = 0x5ea5; - static constexpr Tagged_t kasync_iterator_symbol = 0x5eb5; - static constexpr Tagged_t kintl_fallback_symbol = 0x5ee5; - static constexpr Tagged_t kmatch_all_symbol = 0x5f1d; - static constexpr Tagged_t kmatch_symbol = 0x5f49; - static constexpr Tagged_t ksearch_symbol = 0x5f71; - static constexpr Tagged_t ksplit_symbol = 0x5f9d; - static constexpr Tagged_t kto_primitive_symbol = 0x5fc5; - static constexpr Tagged_t kunscopables_symbol = 0x5ff5; - static constexpr Tagged_t khas_instance_symbol = 0x6025; - static constexpr Tagged_t kto_string_tag_symbol = 0x6055; - static constexpr Tagged_t kconstructor_string = 0x60ad; - static constexpr Tagged_t knext_string = 0x60c5; - static constexpr Tagged_t kresolve_string = 0x60d5; - static constexpr Tagged_t kthen_string = 0x60e9; - static constexpr Tagged_t kiterator_symbol = 0x60f9; - static constexpr Tagged_t kreplace_symbol = 0x6109; - static constexpr Tagged_t kspecies_symbol = 0x6119; - static constexpr Tagged_t kis_concat_spreadable_symbol = 0x6129; - static constexpr Tagged_t kEmptySlowElementDictionary = 0x6139; - static constexpr Tagged_t kEmptySymbolTable = 0x615d; - static constexpr Tagged_t kEmptyOrderedHashMap = 0x6179; - static constexpr Tagged_t kEmptyOrderedHashSet = 0x618d; - static constexpr Tagged_t kEmptyFeedbackMetadata = 0x61a1; - static constexpr Tagged_t kGlobalThisBindingScopeInfo = 0x61ad; - static constexpr Tagged_t kEmptyFunctionScopeInfo = 0x61cd; - static constexpr Tagged_t kNativeScopeInfo = 0x61f1; - static constexpr Tagged_t kShadowRealmScopeInfo = 0x6209; + 0x5e45; + static constexpr Tagged_t ktemplate_literal_slot_id_symbol = 0x5e55; + static constexpr Tagged_t kwasm_exception_tag_symbol = 0x5e65; + static constexpr Tagged_t kwasm_exception_values_symbol = 0x5e75; + static constexpr Tagged_t kwasm_uncatchable_symbol = 0x5e85; + static constexpr Tagged_t kwasm_wrapped_object_symbol = 0x5e95; + static constexpr Tagged_t kwasm_debug_proxy_cache_symbol = 0x5ea5; + static constexpr Tagged_t kwasm_debug_proxy_names_symbol = 0x5eb5; + static constexpr Tagged_t kasync_iterator_symbol = 0x5ec5; + static constexpr Tagged_t kintl_fallback_symbol = 0x5ef5; + static constexpr Tagged_t kmatch_all_symbol = 0x5f2d; + static constexpr Tagged_t kmatch_symbol = 0x5f59; + static constexpr Tagged_t ksearch_symbol = 0x5f81; + static constexpr Tagged_t ksplit_symbol = 0x5fad; + static constexpr Tagged_t kto_primitive_symbol = 0x5fd5; + static constexpr Tagged_t kunscopables_symbol = 0x6005; + static constexpr Tagged_t khas_instance_symbol = 0x6035; + static constexpr Tagged_t kto_string_tag_symbol = 0x6065; + static constexpr Tagged_t kconstructor_string = 0x60bd; + static constexpr Tagged_t knext_string = 0x60d5; + static constexpr Tagged_t kresolve_string = 0x60e5; + static constexpr Tagged_t kthen_string = 0x60f9; + static constexpr Tagged_t kiterator_symbol = 0x6109; + static constexpr Tagged_t kreplace_symbol = 0x6119; + static constexpr Tagged_t kspecies_symbol = 0x6129; + static constexpr Tagged_t kis_concat_spreadable_symbol = 0x6139; + static constexpr Tagged_t kEmptySlowElementDictionary = 0x6149; + static constexpr Tagged_t kEmptySymbolTable = 0x616d; + static constexpr Tagged_t kEmptyOrderedHashMap = 0x6189; + static constexpr Tagged_t kEmptyOrderedHashSet = 0x619d; + static constexpr Tagged_t kEmptyFeedbackMetadata = 0x61b1; + static constexpr Tagged_t kGlobalThisBindingScopeInfo = 0x61bd; + static constexpr Tagged_t kEmptyFunctionScopeInfo = 0x61dd; + static constexpr Tagged_t kNativeScopeInfo = 0x6201; + static constexpr Tagged_t kShadowRealmScopeInfo = 0x6219; static constexpr Tagged_t kWasmNull = 0xfffd; }; -static constexpr std::array StaticReadOnlyRootsPointerTable = { +static constexpr std::array StaticReadOnlyRootsPointerTable = { StaticReadOnlyRoot::kFreeSpaceMap, StaticReadOnlyRoot::kOnePointerFillerMap, StaticReadOnlyRoot::kTwoPointerFillerMap, @@ -1365,6 +1366,7 @@ static constexpr std::array StaticReadOnlyRootsPointerTable = { StaticReadOnlyRoot::kweek_string, StaticReadOnlyRoot::kweeks_string, StaticReadOnlyRoot::kweekOfYear_string, + StaticReadOnlyRoot::kwith_string, StaticReadOnlyRoot::kword_string, StaticReadOnlyRoot::kyearMonthFromFields_string, StaticReadOnlyRoot::kyear_string, diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-1.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-1.mjs new file mode 100644 index 00000000000000..3cf6bac870b80f --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-1.mjs @@ -0,0 +1,9 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-import-attributes + +import { life } from 'modules-skip-1.mjs' with { }; + +assertEquals(42, life()); diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-2.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-2.mjs new file mode 100644 index 00000000000000..63f5859ca0f1d0 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-2.mjs @@ -0,0 +1,9 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-import-attributes + +import json from 'modules-skip-1.json' with { type: 'json' }; + +assertEquals(42, json.life); diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-3.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-3.mjs new file mode 100644 index 00000000000000..34db1852367c19 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-3.mjs @@ -0,0 +1,9 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-import-attributes + +import {life} from 'modules-skip-imports-json-1.mjs'; + +assertEquals(42, life()); diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-4.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-4.mjs new file mode 100644 index 00000000000000..66bdc11c359ed4 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-4.mjs @@ -0,0 +1,9 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-import-attributes + +import json from 'modules-skip-1.json' with { type: 'json', notARealAssertion: 'value'}; + +assertEquals(42, json.life); diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-1.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-1.mjs new file mode 100644 index 00000000000000..644fc96a6e2111 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-1.mjs @@ -0,0 +1,12 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --harmony-import-attributes + +var life; +import('modules-skip-1.mjs', { }).then(namespace => life = namespace.life()); + +%PerformMicrotaskCheckpoint(); + +assertEquals(42, life); diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-10.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-10.mjs new file mode 100644 index 00000000000000..972fbed24bfff2 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-10.mjs @@ -0,0 +1,19 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --harmony-import-attributes + +var result1; +var result2; +import('modules-skip-1.json', { get with() { throw 'bad \'with\' getter!'; } }).then( + () => assertUnreachable('Should have failed due to throwing getter'), + error => result1 = error); +import('modules-skip-1.json', { with: { get assertionKey() { throw 'bad \'assertionKey\' getter!'; } } }).then( + () => assertUnreachable('Should have failed due to throwing getter'), + error => result2 = error); + +%PerformMicrotaskCheckpoint(); + +assertEquals('bad \'with\' getter!', result1); +assertEquals('bad \'assertionKey\' getter!', result2); \ No newline at end of file diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-11.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-11.mjs new file mode 100644 index 00000000000000..c39a5f9d4e2e06 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-11.mjs @@ -0,0 +1,19 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --harmony-import-attributes --harmony-top-level-await + +var life1; +var life2; +import('modules-skip-1.json', { with: { type: 'json' } }).then( + namespace => life1 = namespace.default.life); + +// Try loading the same module a second time. +import('modules-skip-1.json', { with: { type: 'json' } }).then( + namespace => life2 = namespace.default.life); + +%PerformMicrotaskCheckpoint(); + +assertEquals(42, life1); +assertEquals(42, life2); diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-12.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-12.mjs new file mode 100644 index 00000000000000..1d8fb21a502237 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-12.mjs @@ -0,0 +1,26 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --harmony-import-attributes + +let result1; +let result2; + +let badAssertProxy1 = new Proxy({}, { ownKeys() { throw "bad ownKeys!"; } }); +import('./modules-skip-1.mjs', { with: badAssertProxy1 }).then( + () => assertUnreachable('Should have failed due to throwing ownKeys'), + error => result1 = error); + +let badAssertProxy2 = new Proxy( + {foo: "bar"}, + { getOwnPropertyDescriptor() { throw "bad getOwnPropertyDescriptor!"; } }); +import('./modules-skip-1.mjs', { with: badAssertProxy2 }).then( + () => assertUnreachable( + 'Should have failed due to throwing getOwnPropertyDescriptor'), + error => result2 = error); + +%PerformMicrotaskCheckpoint(); + +assertEquals('bad ownKeys!', result1); +assertEquals('bad getOwnPropertyDescriptor!', result2); \ No newline at end of file diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-13.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-13.mjs new file mode 100644 index 00000000000000..6e23c07c281db1 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-13.mjs @@ -0,0 +1,26 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --harmony-import-attributes + +let getters = 0; +let result; + +import('./modules-skip-1.mjs', { with: { + get attr1() { + getters++; + return {}; + }, + get attr2() { + getters++; + return {}; + }, +} }).then( + () => assertUnreachable('Should have failed due to invalid attributes values'), + error => result = error); + +%PerformMicrotaskCheckpoint(); + +assertEquals(2, getters); +assertInstanceof(result, TypeError); diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-2.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-2.mjs new file mode 100644 index 00000000000000..b8e59fb0bfe9c3 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-2.mjs @@ -0,0 +1,13 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --harmony-import-attributes + +var life; +import('modules-skip-1.mjs', { with: { } }).then( + namespace => life = namespace.life()); + +%PerformMicrotaskCheckpoint(); + +assertEquals(42, life); diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-3.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-3.mjs new file mode 100644 index 00000000000000..da570eb2836edd --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-3.mjs @@ -0,0 +1,13 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --harmony-import-attributes + +var life; +import('modules-skip-1.json', { with: { type: 'json' } }).then( + namespace => life = namespace.default.life); + +%PerformMicrotaskCheckpoint(); + +assertEquals(42, life); diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-4.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-4.mjs new file mode 100644 index 00000000000000..fff6fe2bbef84c --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-4.mjs @@ -0,0 +1,14 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --harmony-import-attributes + +var result; +import('modules-skip-1.json', { with: { type: 'notARealType' } }).then( + () => assertUnreachable('Should have failed due to bad module type'), + error => result = error.message); + +%PerformMicrotaskCheckpoint(); + +assertEquals('Invalid module type was asserted', result); diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-5.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-5.mjs new file mode 100644 index 00000000000000..cdb1567c330764 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-5.mjs @@ -0,0 +1,12 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --harmony-import-attributes + +var life; +import('modules-skip-imports-json-1.mjs',).then(namespace => life = namespace.life()); + +%PerformMicrotaskCheckpoint(); + +assertEquals(42, life); diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-6.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-6.mjs new file mode 100644 index 00000000000000..ad84e3edd5ffe1 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-6.mjs @@ -0,0 +1,18 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --harmony-import-attributes + +var life; +import('modules-skip-1.json', { with: { type: 'json', notARealAssertion: 'value' } }).then( + namespace => life = namespace.default.life); + +var life2; +import('modules-skip-1.json', { with: { 0: 'value', type: 'json' } }).then( + namespace => life2 = namespace.default.life); + +%PerformMicrotaskCheckpoint(); + +assertEquals(42, life); +assertEquals(42, life2); diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-7.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-7.mjs new file mode 100644 index 00000000000000..530d833cce5a4d --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-7.mjs @@ -0,0 +1,63 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --harmony-import-attributes + +var result1; +var result2; +var result3; +var result4; +var result5; +var result6; +var result7; +var result8; +var result9; +var result10; +import('modules-skip-1.json', null).then( + () => assertUnreachable('Should have failed due to non-object parameter'), + error => result1 = error.message); +import('modules-skip-1.json', 7).then( + () => assertUnreachable('Should have failed due to non-object parameter'), + error => result2 = error.message); +import('modules-skip-1.json', 'string').then( + () => assertUnreachable('Should have failed due to non-object parameter'), + error => result3 = error.message); +import('modules-skip-1.json', { with: null}).then( + () => assertUnreachable('Should have failed due to bad with object'), + error => result4 = error.message); +import('modules-skip-1.json', { with: 7}).then( + () => assertUnreachable('Should have failed due to bad with object'), + error => result5 = error.message); +import('modules-skip-1.json', { with: 'string'}).then( + () => assertUnreachable('Should have failed due to bad with object'), + error => result6 = error.message); +import('modules-skip-1.json', { with: { a: null }}).then( + () => assertUnreachable('Should have failed due to bad with object'), + error => result7 = error.message); +import('modules-skip-1.json', { with: { a: undefined }}).then( + () => assertUnreachable('Should have failed due to bad assertion value'), + error => result8 = error.message); +import('modules-skip-1.json', { with: { a: 7 }}).then( + () => assertUnreachable('Should have failed due to bad assertion value'), + error => result9 = error.message); + import('modules-skip-1.json', { with: { a: { } }}).then( + () => assertUnreachable('Should have failed due to bad assertion value'), + error => result10 = error.message); + +%PerformMicrotaskCheckpoint(); + +const argumentNotObjectError = 'The second argument to import() must be an object'; +const assertOptionNotObjectError = 'The \'assert\' option must be an object'; +const assertionValueNotStringError = 'Import assertion value must be a string'; + +assertEquals(argumentNotObjectError, result1); +assertEquals(argumentNotObjectError, result2); +assertEquals(argumentNotObjectError, result3); +assertEquals(assertOptionNotObjectError, result4); +assertEquals(assertOptionNotObjectError, result5); +assertEquals(assertOptionNotObjectError, result6); +assertEquals(assertionValueNotStringError, result7); +assertEquals(assertionValueNotStringError, result8); +assertEquals(assertionValueNotStringError, result9); +assertEquals(assertionValueNotStringError, result10); diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-8.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-8.mjs new file mode 100644 index 00000000000000..74a4504e253d6a --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-8.mjs @@ -0,0 +1,13 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --harmony-import-attributes + +var life; +import('modules-skip-1.mjs', undefined).then( + namespace => life = namespace.life()); + +%PerformMicrotaskCheckpoint(); + +assertEquals(42, life); diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-9.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-9.mjs new file mode 100644 index 00000000000000..1b56c70df61682 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-9.mjs @@ -0,0 +1,13 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --harmony-import-attributes + +var life; +import('modules-skip-1.mjs', { with: undefined }).then( + namespace => life = namespace.life()); + +%PerformMicrotaskCheckpoint(); + +assertEquals(42, life); diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-assertions-fallback-1.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-assertions-fallback-1.mjs new file mode 100644 index 00000000000000..3faaf0dccea1c9 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-assertions-fallback-1.mjs @@ -0,0 +1,15 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --harmony-import-attributes --harmony-import-assertions + +var life; +import('modules-skip-1.mjs', { + with: {}, + get assert() { throw 'Should not read assert'; } +}).then(namespace => life = namespace.life()); + +%PerformMicrotaskCheckpoint(); + +assertEquals(42, life); diff --git a/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-assertions-fallback-2.mjs b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-assertions-fallback-2.mjs new file mode 100644 index 00000000000000..4c83d2fbd716cc --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/modules-import-attributes-dynamic-assertions-fallback-2.mjs @@ -0,0 +1,15 @@ +// Copyright 2021 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --harmony-import-attributes --harmony-import-assertions + +var life; +import('modules-skip-1.json', { + with: undefined, + assert: { type: 'json' } +}).then(namespace => life = namespace.default.life); + +%PerformMicrotaskCheckpoint(); + +assertEquals(42, life); diff --git a/deps/v8/test/unittests/parser/parsing-unittest.cc b/deps/v8/test/unittests/parser/parsing-unittest.cc index 9048d7f1faf674..24e178e2ca5eb6 100644 --- a/deps/v8/test/unittests/parser/parsing-unittest.cc +++ b/deps/v8/test/unittests/parser/parsing-unittest.cc @@ -4876,6 +4876,11 @@ TEST_F(ParsingTest, BasicImportAssertionParsing) { "import { a as b } from 'm.js' assert { \nc: 'd'};", "import { a as b } from 'm.js' assert { c:\n 'd'};", "import { a as b } from 'm.js' assert { c:'d'\n};", + + "import { a as b } from 'm.js' assert { 0: 'b', };", + "import { a as b } from 'm.js' assert { 0n: 'b', };", + "import { a as b } from 'm.js' assert { '0': 'b', };", + "import { a as b } from 'm.js' assert { 0.0: 'b', };", }; // clang-format on @@ -4943,10 +4948,234 @@ TEST_F(ParsingTest, ImportAssertionParsingErrors) { "import { a } from 'm.js' assert { , b: c };", "import { a } from 'm.js' assert { a: 'b', a: 'c' };", "import { a } from 'm.js' assert { a: 'b', 'a': 'c' };", + + "import { a } from 'm.js' assert { 0: 'b', '0': 'c' };", + "import { a } from 'm.js' assert { 0n: 'b', '0': 'c' };", + "import { a } from 'm.js' assert { 0: 'b', 0n: 'c' };", + "import { a } from 'm.js' assert { 0: 'b', 0.0: 'c' };", + "import { a } from 'm.js' assert { '0': 'b', 0n: 'c' };", + + "import 'm.js' with { a: 'b' };" + }; + // clang-format on + + i::v8_flags.harmony_import_assertions = true; + i::Isolate* isolate = i_isolate(); + i::Factory* factory = isolate->factory(); + + isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() - + 128 * 1024); + + for (unsigned i = 0; i < arraysize(kErrorSources); ++i) { + i::Handle source = + factory->NewStringFromAsciiChecked(kErrorSources[i]); + + i::Handle script = factory->NewScript(source); + i::UnoptimizedCompileState compile_state; + i::ReusableUnoptimizedCompileState reusable_state(isolate); + i::UnoptimizedCompileFlags flags = + i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script); + flags.set_is_module(true); + i::ParseInfo info(isolate, flags, &compile_state, &reusable_state); + CHECK(!i::parsing::ParseProgram(&info, script, isolate, + parsing::ReportStatisticsMode::kYes)); + CHECK(info.pending_error_handler()->has_pending_error()); + } +} + +TEST_F(ParsingTest, BasicImportAttributesParsing) { + // clang-format off + const char* kSources[] = { + "import { a as b } from 'm.js' with { };", + "import n from 'n.js' with { };", + "export { a as b } from 'm.js' with { };", + "export * from 'm.js' with { };", + "import 'm.js' with { };", + "import * as foo from 'bar.js' with { };", + + "import { a as b } from 'm.js' with { a: 'b' };", + "import { a as b } from 'm.js' with { c: 'd' };", + "import { a as b } from 'm.js' with { 'c': 'd' };", + "import { a as b } from 'm.js' with { a: 'b', 'c': 'd', e: 'f' };", + "import { a as b } from 'm.js' with { 'c': 'd', };", + "import n from 'n.js' with { 'c': 'd' };", + "export { a as b } from 'm.js' with { 'c': 'd' };", + "export * from 'm.js' with { 'c': 'd' };", + "import 'm.js' with { 'c': 'd' };", + "import * as foo from 'bar.js' with { 'c': 'd' };", + + "import { a as b } from 'm.js' with { \nc: 'd'};", + "import { a as b } from 'm.js' with { c:\n 'd'};", + "import { a as b } from 'm.js' with { c:'d'\n};", + + "import { a as b } from 'm.js' with { 0: 'b', };", + "import { a as b } from 'm.js' with { 0n: 'b', };", + "import { a as b } from 'm.js' with { '0': 'b', };", + "import { a as b } from 'm.js' with { 0.0: 'b', };", + + "import 'm.js'\n with { };", + "import 'm.js' \nwith { };", + "import { a } from 'm.js'\n with { };", + "export * from 'm.js'\n with { };" + }; + // clang-format on + + i::v8_flags.harmony_import_attributes = true; + i::Isolate* isolate = i_isolate(); + i::Factory* factory = isolate->factory(); + + isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() - + 128 * 1024); + + for (unsigned i = 0; i < arraysize(kSources); ++i) { + i::Handle source = + factory->NewStringFromAsciiChecked(kSources[i]); + + // Show that parsing as a module works + { + i::Handle script = factory->NewScript(source); + i::UnoptimizedCompileState compile_state; + i::ReusableUnoptimizedCompileState reusable_state(isolate); + i::UnoptimizedCompileFlags flags = + i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script); + flags.set_is_module(true); + i::ParseInfo info(isolate, flags, &compile_state, &reusable_state); + CHECK_PARSE_PROGRAM(&info, script, isolate); + } + + // And that parsing a script does not. + { + i::UnoptimizedCompileState compile_state; + i::ReusableUnoptimizedCompileState reusable_state(isolate); + i::Handle script = factory->NewScript(source); + i::UnoptimizedCompileFlags flags = + i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script); + i::ParseInfo info(isolate, flags, &compile_state, &reusable_state); + CHECK(!i::parsing::ParseProgram(&info, script, isolate, + parsing::ReportStatisticsMode::kYes)); + CHECK(info.pending_error_handler()->has_pending_error()); + } + } +} + +TEST_F(ParsingTest, ImportAttributesParsingErrors) { + // clang-format off + const char* kErrorSources[] = { + "import { a } from 'm.js' with {;", + "import { a } from 'm.js' with };", + "import { a } from 'm.js' , with { };", + "import { a } from 'm.js' with , { };", + "import { a } from 'm.js' with { , };", + "import { a } from 'm.js' with { b };", + "import { a } from 'm.js' with { 'b' };", + "import { a } from 'm.js' with { for };", + "import { a } from 'm.js' with { with };", + "export { a } with { };", + "export * with { };", + + "import { a } from 'm.js' with { 1: 2 };", + "import { a } from 'm.js' with { b: c };", + "import { a } from 'm.js' with { 'b': c };", + "import { a } from 'm.js' with { , b: c };", + "import { a } from 'm.js' with { a: 'b', a: 'c' };", + "import { a } from 'm.js' with { a: 'b', 'a': 'c' };", + + "import { a } from 'm.js' with { 0: 'b', '0': 'c' };", + "import { a } from 'm.js' with { 0n: 'b', '0': 'c' };", + "import { a } from 'm.js' with { 0: 'b', 0n: 'c' };", + "import { a } from 'm.js' with { 0: 'b', 0.0: 'c' };", + "import { a } from 'm.js' with { '0': 'b', 0n: 'c' };", + + "import 'm.js' assert { a: 'b' };" + }; + // clang-format on + + i::v8_flags.harmony_import_assertions = false; + i::v8_flags.harmony_import_attributes = true; + i::Isolate* isolate = i_isolate(); + i::Factory* factory = isolate->factory(); + + isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() - + 128 * 1024); + + for (unsigned i = 0; i < arraysize(kErrorSources); ++i) { + i::Handle source = + factory->NewStringFromAsciiChecked(kErrorSources[i]); + + i::Handle script = factory->NewScript(source); + i::UnoptimizedCompileState compile_state; + i::ReusableUnoptimizedCompileState reusable_state(isolate); + i::UnoptimizedCompileFlags flags = + i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script); + flags.set_is_module(true); + i::ParseInfo info(isolate, flags, &compile_state, &reusable_state); + CHECK(!i::parsing::ParseProgram(&info, script, isolate, + parsing::ReportStatisticsMode::kYes)); + CHECK(info.pending_error_handler()->has_pending_error()); + } +} + +TEST_F(ParsingTest, BasicImportAttributesAndAssertionsParsing) { + // clang-format off + const char* kSources[] = { + "import { a } from 'm.js' assert { };", + "import { a } from 'm.js' with { };", + "import { a } from 'm.js'\n with { };", + }; + // clang-format on + + i::v8_flags.harmony_import_assertions = true; + i::v8_flags.harmony_import_attributes = true; + i::Isolate* isolate = i_isolate(); + i::Factory* factory = isolate->factory(); + + isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() - + 128 * 1024); + + for (unsigned i = 0; i < arraysize(kSources); ++i) { + i::Handle source = + factory->NewStringFromAsciiChecked(kSources[i]); + + // Show that parsing as a module works + { + i::Handle script = factory->NewScript(source); + i::UnoptimizedCompileState compile_state; + i::ReusableUnoptimizedCompileState reusable_state(isolate); + i::UnoptimizedCompileFlags flags = + i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script); + flags.set_is_module(true); + i::ParseInfo info(isolate, flags, &compile_state, &reusable_state); + CHECK_PARSE_PROGRAM(&info, script, isolate); + } + + // And that parsing a script does not. + { + i::UnoptimizedCompileState compile_state; + i::ReusableUnoptimizedCompileState reusable_state(isolate); + i::Handle script = factory->NewScript(source); + i::UnoptimizedCompileFlags flags = + i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script); + i::ParseInfo info(isolate, flags, &compile_state, &reusable_state); + CHECK(!i::parsing::ParseProgram(&info, script, isolate, + parsing::ReportStatisticsMode::kYes)); + CHECK(info.pending_error_handler()->has_pending_error()); + } + } +} + +TEST_F(ParsingTest, ImportAttributesAndAssertionsParsingErrors) { + // clang-format off + const char* kErrorSources[] = { + "import { a } from 'm.js'\n assert { };", + "import { a } from 'm.js' with { } assert { };", + "import { a } from 'm.js' with assert { };", + "import { a } from 'm.js' assert { } with { };", + "import { a } from 'm.js' assert with { };", }; // clang-format on i::v8_flags.harmony_import_assertions = true; + i::v8_flags.harmony_import_attributes = true; i::Isolate* isolate = i_isolate(); i::Factory* factory = isolate->factory();