diff --git a/DEPS b/DEPS index cfd0904e0613..adbb482a9502 100644 --- a/DEPS +++ b/DEPS @@ -88,15 +88,15 @@ vars = { deps = { 'build': - Var('chromium_url') + '/chromium/src/build.git' + '@' + '710b42c08be2d80bf25542805e0d3b4d40a35d3e', + Var('chromium_url') + '/chromium/src/build.git' + '@' + '32fd3b2e52a86bcbaceedbd39dd8bdde93aaf4bf', 'third_party/depot_tools': - Var('chromium_url') + '/chromium/tools/depot_tools.git' + '@' + '07bd252238b7ba84f7039dc55ce03b37e475489c', + Var('chromium_url') + '/chromium/tools/depot_tools.git' + '@' + '1076f38947e6e13964741cd6547da31a2ccc7a1d', 'third_party/icu': Var('chromium_url') + '/chromium/deps/icu.git' + '@' + '899e18383fd732b47e6978db2b960a1b2a80179b', 'third_party/instrumented_libraries': Var('chromium_url') + '/chromium/src/third_party/instrumented_libraries.git' + '@' + '4d3867052d35b2171f2edbb3466fa8f7e2d11319', 'buildtools': - Var('chromium_url') + '/chromium/src/buildtools.git' + '@' + '13547b97dad2cdf1b3726b07b2563b921068a018', + Var('chromium_url') + '/chromium/src/buildtools.git' + '@' + '450b6b6103ec59640e957959356dae00c2f418b0', 'buildtools/clang_format/script': Var('chromium_url') + '/chromium/llvm-project/cfe/tools/clang-format.git' + '@' + '96636aa0e9f047f17447f2d45a094d0b59ed7917', 'buildtools/linux64': { @@ -206,7 +206,7 @@ deps = { 'third_party/markupsafe': Var('chromium_url') + '/chromium/src/third_party/markupsafe.git' + '@' + '0944e71f4b2cb9a871bcbe353f95e889b64a611a', 'tools/swarming_client': - Var('chromium_url') + '/infra/luci/client-py.git' + '@' + '1a072711d4388c62e02480fabc26c68c24494be9', + Var('chromium_url') + '/infra/luci/client-py.git' + '@' + 'a32a1607f6093d338f756c7e7c7b4333b0c50c9c', 'test/benchmarks/data': Var('chromium_url') + '/v8/deps/third_party/benchmarks.git' + '@' + '05d7188267b4560491ff9155c5ee13e207ecd65f', 'test/mozilla/data': diff --git a/include/v8.h b/include/v8.h index 20d03920f585..f292758e8f93 100644 --- a/include/v8.h +++ b/include/v8.h @@ -6136,9 +6136,10 @@ class V8_EXPORT RegExp : public Object { kUnicode = 1 << 4, kDotAll = 1 << 5, kLinear = 1 << 6, + kHasIndices = 1 << 7, }; - static constexpr int kFlagCount = 7; + static constexpr int kFlagCount = 8; /** * Creates a regular expression from the given pattern string and @@ -7435,7 +7436,7 @@ using CallCompletedCallback = void (*)(Isolate*); * The specifier is the name of the module that should be imported. * * The embedder must compile, instantiate, evaluate the Module, and - * obtain it's namespace object. + * obtain its namespace object. * * The Promise returned from this function is forwarded to userland * JavaScript. The embedder must resolve this promise with the module @@ -7444,9 +7445,43 @@ using CallCompletedCallback = void (*)(Isolate*); * fails (e.g. due to stack overflow), the embedder must propagate * that exception by returning an empty MaybeLocal. */ -using HostImportModuleDynamicallyCallback = MaybeLocal (*)( - Local context, Local referrer, - Local specifier); +using HostImportModuleDynamicallyCallback V8_DEPRECATE_SOON( + "Use HostImportModuleDynamicallyWithImportAssertionsCallback instead") = + MaybeLocal (*)(Local context, + Local referrer, + Local specifier); + +/** + * HostImportModuleDynamicallyWithImportAssertionsCallback is called when we + * require the embedder to load a module. This is used as part of the dynamic + * import syntax. + * + * The referrer contains metadata about the script/module that calls + * import. + * + * The specifier is the name of the module that should be imported. + * + * The import_assertions are import assertions for this request in the form: + * [key1, value1, key2, value2, ...] where the keys and values are of type + * v8::String. Note, unlike the FixedArray passed to ResolveModuleCallback and + * returned from ModuleRequest::GetImportAssertions(), this array does not + * contain the source Locations of the assertions. + * + * The embedder must compile, instantiate, evaluate the Module, and + * obtain its namespace object. + * + * The Promise returned from this function is forwarded to userland + * JavaScript. The embedder must resolve this promise with the module + * namespace object. In case of an exception, the embedder must reject + * this promise with the exception. If the promise creation itself + * fails (e.g. due to stack overflow), the embedder must propagate + * that exception by returning an empty MaybeLocal. + */ +using HostImportModuleDynamicallyWithImportAssertionsCallback = + MaybeLocal (*)(Local context, + Local referrer, + Local specifier, + Local import_assertions); /** * HostInitializeImportMetaObjectCallback is called the first time import.meta @@ -8776,9 +8811,19 @@ class V8_EXPORT Isolate { * This specifies the callback called by the upcoming dynamic * import() language feature to load modules. */ + V8_DEPRECATE_SOON( + "Use the version of SetHostImportModuleDynamicallyCallback that takes a " + "HostImportModuleDynamicallyWithImportAssertionsCallback instead") void SetHostImportModuleDynamicallyCallback( HostImportModuleDynamicallyCallback callback); + /** + * This specifies the callback called by the upcoming dynamic + * import() language feature to load modules. + */ + void SetHostImportModuleDynamicallyCallback( + HostImportModuleDynamicallyWithImportAssertionsCallback callback); + /** * This specifies the callback called by the upcoming import.meta * language feature to retrieve host-defined meta data for a module. diff --git a/src/api/api.cc b/src/api/api.cc index a964fec27602..3656bc689df8 100644 --- a/src/api/api.cc +++ b/src/api/api.cc @@ -7032,6 +7032,7 @@ REGEXP_FLAG_ASSERT_EQ(kIgnoreCase); REGEXP_FLAG_ASSERT_EQ(kMultiline); REGEXP_FLAG_ASSERT_EQ(kSticky); REGEXP_FLAG_ASSERT_EQ(kUnicode); +REGEXP_FLAG_ASSERT_EQ(kHasIndices); REGEXP_FLAG_ASSERT_EQ(kLinear); #undef REGEXP_FLAG_ASSERT_EQ @@ -8652,7 +8653,13 @@ void Isolate::SetAbortOnUncaughtExceptionCallback( } void Isolate::SetHostImportModuleDynamicallyCallback( - HostImportModuleDynamicallyCallback callback) { + i::Isolate::DeprecatedHostImportModuleDynamicallyCallback callback) { + i::Isolate* isolate = reinterpret_cast(this); + isolate->SetHostImportModuleDynamicallyCallback(callback); +} + +void Isolate::SetHostImportModuleDynamicallyCallback( + HostImportModuleDynamicallyWithImportAssertionsCallback callback) { i::Isolate* isolate = reinterpret_cast(this); isolate->SetHostImportModuleDynamicallyCallback(callback); } diff --git a/src/ast/prettyprinter.cc b/src/ast/prettyprinter.cc index 9cd64700c6ce..c3dae452c581 100644 --- a/src/ast/prettyprinter.cc +++ b/src/ast/prettyprinter.cc @@ -256,6 +256,7 @@ void CallPrinter::VisitRegExpLiteral(RegExpLiteral* node) { Print("/"); PrintLiteral(node->pattern(), false); Print("/"); + if (node->flags() & RegExp::kHasIndices) Print("d"); if (node->flags() & RegExp::kGlobal) Print("g"); if (node->flags() & RegExp::kIgnoreCase) Print("i"); if (node->flags() & RegExp::kLinear) Print("l"); @@ -1156,6 +1157,7 @@ void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) { PrintLiteralIndented("PATTERN", node->raw_pattern(), false); int i = 0; EmbeddedVector buf; + if (node->flags() & RegExp::kHasIndices) buf[i++] = 'd'; if (node->flags() & RegExp::kGlobal) buf[i++] = 'g'; if (node->flags() & RegExp::kIgnoreCase) buf[i++] = 'i'; if (node->flags() & RegExp::kLinear) buf[i++] = 'l'; diff --git a/src/builtins/accessors.cc b/src/builtins/accessors.cc index b4c4b3f83c2a..53256725a04a 100644 --- a/src/builtins/accessors.cc +++ b/src/builtins/accessors.cc @@ -842,32 +842,5 @@ Handle Accessors::MakeErrorStackInfo(Isolate* isolate) { &ErrorStackGetter, &ErrorStackSetter); } -// -// Accessors::RegExpResultIndices -// - -void Accessors::RegExpResultIndicesGetter( - v8::Local key, const v8::PropertyCallbackInfo& info) { - i::Isolate* isolate = reinterpret_cast(info.GetIsolate()); - HandleScope scope(isolate); - Handle regexp_result( - Handle::cast(Utils::OpenHandle(*info.Holder()))); - MaybeHandle maybe_indices( - JSRegExpResult::GetAndCacheIndices(isolate, regexp_result)); - Handle indices; - if (!maybe_indices.ToHandle(&indices)) { - isolate->OptionalRescheduleException(false); - Handle result = isolate->factory()->undefined_value(); - info.GetReturnValue().Set(Utils::ToLocal(result)); - } else { - info.GetReturnValue().Set(Utils::ToLocal(indices)); - } -} - -Handle Accessors::MakeRegExpResultIndicesInfo(Isolate* isolate) { - return MakeAccessor(isolate, isolate->factory()->indices_string(), - &RegExpResultIndicesGetter, nullptr); -} - } // namespace internal } // namespace v8 diff --git a/src/builtins/accessors.h b/src/builtins/accessors.h index 7bc8075e55ab..0148b8e3d18f 100644 --- a/src/builtins/accessors.h +++ b/src/builtins/accessors.h @@ -44,8 +44,6 @@ class JavaScriptFrame; kHasSideEffectToReceiver) \ V(_, function_prototype, FunctionPrototype, kHasNoSideEffect, \ kHasSideEffectToReceiver) \ - V(_, regexp_result_indices, RegExpResultIndices, kHasSideEffectToReceiver, \ - kHasSideEffectToReceiver) \ V(_, string_length, StringLength, kHasNoSideEffect, kHasSideEffectToReceiver) #define ACCESSOR_SETTER_LIST(V) \ diff --git a/src/builtins/builtins-regexp-gen.cc b/src/builtins/builtins-regexp-gen.cc index 0deb7528f0a4..de088ad2ace1 100644 --- a/src/builtins/builtins-regexp-gen.cc +++ b/src/builtins/builtins-regexp-gen.cc @@ -88,31 +88,52 @@ TNode RegExpBuiltinsAssembler::LoadCodeObjectEntry(TNode code) { TNode RegExpBuiltinsAssembler::AllocateRegExpResult( TNode context, TNode length, TNode index, TNode input, TNode regexp, TNode last_index, - TNode* elements_out) { + TNode has_indices, TNode* elements_out) { CSA_ASSERT(this, SmiLessThanOrEqual( length, SmiConstant(JSArray::kMaxFastArrayLength))); CSA_ASSERT(this, SmiGreaterThan(length, SmiConstant(0))); // Allocate. + Label result_has_indices(this), allocated(this); const ElementsKind elements_kind = PACKED_ELEMENTS; - TNode map = CAST(LoadContextElement(LoadNativeContext(context), - Context::REGEXP_RESULT_MAP_INDEX)); base::Optional> no_gc_site = base::nullopt; TNode length_intptr = SmiUntag(length); + // Note: The returned `var_elements` may be in young large object space, but + // `var_array` is guaranteed to be in new space so we could skip write + // barriers below. + TVARIABLE(JSArray, var_array); + TVARIABLE(FixedArrayBase, var_elements); - // Note: The returned `elements` may be in young large object space, but - // `array` is guaranteed to be in new space so we could skip write barriers - // below. - TNode array; - TNode elements; - std::tie(array, elements) = AllocateUninitializedJSArrayWithElements( - elements_kind, map, length, no_gc_site, length_intptr, - kAllowLargeObjectAllocation, JSRegExpResult::kSize); + GotoIf(has_indices, &result_has_indices); + { + TNode map = CAST(LoadContextElement(LoadNativeContext(context), + Context::REGEXP_RESULT_MAP_INDEX)); + std::tie(var_array, var_elements) = + AllocateUninitializedJSArrayWithElements( + elements_kind, map, length, no_gc_site, length_intptr, + kAllowLargeObjectAllocation, JSRegExpResult::kSize); + Goto(&allocated); + } + + BIND(&result_has_indices); + { + TNode map = + CAST(LoadContextElement(LoadNativeContext(context), + Context::REGEXP_RESULT_WITH_INDICES_MAP_INDEX)); + std::tie(var_array, var_elements) = + AllocateUninitializedJSArrayWithElements( + elements_kind, map, length, no_gc_site, length_intptr, + kAllowLargeObjectAllocation, JSRegExpResultWithIndices::kSize); + Goto(&allocated); + } + + BIND(&allocated); // Finish result initialization. - TNode result = UncheckedCast(array); + TNode result = + UncheckedCast(var_array.value()); // Load undefined value once here to avoid multiple LoadRoots. TNode undefined_value = UncheckedCast( @@ -127,10 +148,6 @@ TNode RegExpBuiltinsAssembler::AllocateRegExpResult( StoreObjectFieldNoWriteBarrier(result, JSRegExpResult::kNamesOffset, undefined_value); - // Stash regexp in order to re-execute and build JSRegExpResultIndices lazily - // when the 'indices' property is accessed. - StoreObjectField(result, JSRegExpResult::kCachedIndicesOrRegexpOffset, - regexp); StoreObjectField(result, JSRegExpResult::kRegexpInputOffset, input); // If non-smi last_index then store an SmiZero instead. @@ -142,12 +159,25 @@ TNode RegExpBuiltinsAssembler::AllocateRegExpResult( last_index_smi); } + Label finish_initialization(this); + GotoIfNot(has_indices, &finish_initialization); + { + static_assert( + std::is_base_of::value, + "JSRegExpResultWithIndices is a subclass of JSRegExpResult"); + StoreObjectFieldNoWriteBarrier( + result, JSRegExpResultWithIndices::kIndicesOffset, undefined_value); + Goto(&finish_initialization); + } + + BIND(&finish_initialization); + // Finish elements initialization. - FillFixedArrayWithValue(elements_kind, elements, IntPtrZero(), length_intptr, - RootIndex::kUndefinedValue); + FillFixedArrayWithValue(elements_kind, var_elements.value(), IntPtrZero(), + length_intptr, RootIndex::kUndefinedValue); - if (elements_out) *elements_out = CAST(elements); + if (elements_out) *elements_out = CAST(var_elements.value()); return result; } @@ -185,7 +215,7 @@ TNode RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( TNode context, TNode regexp, TNode match_info, TNode string, TNode last_index) { - Label named_captures(this), out(this); + Label named_captures(this), maybe_build_indices(this), out(this); TNode num_indices = SmiUntag(CAST(UnsafeLoadFixedArrayElement( match_info, RegExpMatchInfo::kNumberOfCapturesIndex))); @@ -201,15 +231,19 @@ TNode RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( TNode first = CAST(CallBuiltin(Builtins::kSubString, context, string, start, end)); + // Load flags and check if the result object needs to have indices. + const TNode flags = + CAST(LoadObjectField(regexp, JSRegExp::kFlagsOffset)); + const TNode has_indices = IsSetSmi(flags, JSRegExp::kHasIndices); TNode result_elements; TNode result = AllocateRegExpResult(context, num_results, start, string, regexp, - last_index, &result_elements); + last_index, has_indices, &result_elements); UnsafeStoreFixedArrayElement(result_elements, 0, first); // If no captures exist we can skip named capture handling as well. - GotoIf(SmiEqual(num_results, SmiConstant(1)), &out); + GotoIf(SmiEqual(num_results, SmiConstant(1)), &maybe_build_indices); // Store all remaining captures. TNode limit = IntPtrAdd( @@ -273,7 +307,7 @@ TNode RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( // index at odd indices. TNode maybe_names = LoadFixedArrayElement(data, JSRegExp::kIrregexpCaptureNameMapIndex); - GotoIf(TaggedEqual(maybe_names, SmiZero()), &out); + GotoIf(TaggedEqual(maybe_names, SmiZero()), &maybe_build_indices); // One or more named captures exist, add a property for each one. @@ -343,8 +377,8 @@ TNode RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( } var_i = i_plus_2; - Branch(IntPtrGreaterThanOrEqual(var_i.value(), names_length), &out, - &loop); + Branch(IntPtrGreaterThanOrEqual(var_i.value(), names_length), + &maybe_build_indices, &loop); if (!V8_DICT_MODE_PROTOTYPES_BOOL) { // TODO(v8:11167) make unconditional once OrderedNameDictionary @@ -358,6 +392,22 @@ TNode RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( } } + // Build indices if needed (i.e. if the /d flag is present) after named + // capture groups are processed. + BIND(&maybe_build_indices); + GotoIfNot(has_indices, &out); + { + const TNode maybe_names = + LoadObjectField(result, JSRegExpResultWithIndices::kNamesOffset); + const TNode indices = + UncheckedCast( + CallRuntime(Runtime::kRegExpBuildIndices, context, regexp, + match_info, maybe_names)); + StoreObjectField(result, JSRegExpResultWithIndices::kIndicesOffset, + indices); + Goto(&out); + } + BIND(&out); return result; } @@ -836,8 +886,20 @@ void RegExpBuiltinsAssembler::BranchIfRegExpResult(const TNode context, const TNode initial_regexp_result_map = LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX); + Label maybe_result_with_indices(this); Branch(TaggedEqual(map, initial_regexp_result_map), if_isunmodified, - if_ismodified); + &maybe_result_with_indices); + BIND(&maybe_result_with_indices); + { + static_assert( + std::is_base_of::value, + "JSRegExpResultWithIndices is a subclass of JSRegExpResult"); + const TNode initial_regexp_result_with_indices_map = + LoadContextElement(native_context, + Context::REGEXP_RESULT_WITH_INDICES_MAP_INDEX); + Branch(TaggedEqual(map, initial_regexp_result_with_indices_map), + if_isunmodified, if_ismodified); + } } // Fast path stub for ATOM regexps. String matching is done by StringIndexOf, @@ -945,6 +1007,7 @@ TNode RegExpBuiltinsAssembler::FlagsGetter(TNode context, BIND(&next); \ } while (false) + CASE_FOR_FLAG(JSRegExp::kHasIndices); CASE_FOR_FLAG(JSRegExp::kGlobal); CASE_FOR_FLAG(JSRegExp::kIgnoreCase); CASE_FOR_FLAG(JSRegExp::kLinear); @@ -981,35 +1044,38 @@ TNode RegExpBuiltinsAssembler::FlagsGetter(TNode context, CASE_FOR_FLAG("sticky", JSRegExp::kSticky); #undef CASE_FOR_FLAG - { - Label next(this); - - // Check the runtime value of FLAG_enable_experimental_regexp_engine - // first. - TNode flag_value = UncheckedCast( - Load(MachineType::Uint8(), - ExternalConstant( - ExternalReference:: - address_of_enable_experimental_regexp_engine()))); - GotoIf(Word32Equal(Word32And(flag_value, Int32Constant(0xFF)), - Int32Constant(0)), - &next); +#define CASE_FOR_FLAG(NAME, V8_FLAG_EXTERN_REF, FLAG) \ + do { \ + Label next(this); \ + TNode flag_value = UncheckedCast( \ + Load(MachineType::Uint8(), ExternalConstant(V8_FLAG_EXTERN_REF))); \ + GotoIf(Word32Equal(Word32And(flag_value, Int32Constant(0xFF)), \ + Int32Constant(0)), \ + &next); \ + const TNode flag = GetProperty( \ + context, regexp, isolate->factory()->InternalizeUtf8String(NAME)); \ + Label if_isflagset(this); \ + BranchIfToBooleanIsTrue(flag, &if_isflagset, &next); \ + BIND(&if_isflagset); \ + var_length = Uint32Add(var_length.value(), Uint32Constant(1)); \ + var_flags = Signed(WordOr(var_flags.value(), IntPtrConstant(FLAG))); \ + Goto(&next); \ + BIND(&next); \ + } while (false) - const TNode flag = GetProperty( - context, regexp, isolate->factory()->InternalizeUtf8String("linear")); - Label if_isflagset(this); - BranchIfToBooleanIsTrue(flag, &if_isflagset, &next); - BIND(&if_isflagset); - var_length = Uint32Add(var_length.value(), Uint32Constant(1)); - var_flags = - Signed(WordOr(var_flags.value(), IntPtrConstant(JSRegExp::kLinear))); - Goto(&next); - BIND(&next); - } + CASE_FOR_FLAG( + "hasIndices", + ExternalReference::address_of_harmony_regexp_match_indices_flag(), + JSRegExp::kHasIndices); + CASE_FOR_FLAG( + "linear", + ExternalReference::address_of_enable_experimental_regexp_engine(), + JSRegExp::kLinear); +#undef CASE_FOR_FLAG } - // Allocate a string of the required length and fill it with the corresponding - // char for each set flag. + // Allocate a string of the required length and fill it with the + // corresponding char for each set flag. { const TNode result = AllocateSeqOneByteString(var_length.value()); @@ -1029,6 +1095,7 @@ TNode RegExpBuiltinsAssembler::FlagsGetter(TNode context, BIND(&next); \ } while (false) + CASE_FOR_FLAG(JSRegExp::kHasIndices, 'd'); CASE_FOR_FLAG(JSRegExp::kGlobal, 'g'); CASE_FOR_FLAG(JSRegExp::kIgnoreCase, 'i'); CASE_FOR_FLAG(JSRegExp::kLinear, 'l'); @@ -1283,6 +1350,9 @@ TNode RegExpBuiltinsAssembler::SlowFlagGetter(TNode context, case JSRegExp::kUnicode: name = isolate()->factory()->unicode_string(); break; + case JSRegExp::kHasIndices: + name = isolate()->factory()->has_indices_string(); + break; case JSRegExp::kLinear: name = isolate()->factory()->linear_string(); break; diff --git a/src/builtins/builtins-regexp-gen.h b/src/builtins/builtins-regexp-gen.h index 273e31559915..2f3d9a2051a2 100644 --- a/src/builtins/builtins-regexp-gen.h +++ b/src/builtins/builtins-regexp-gen.h @@ -22,13 +22,14 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler { TNode LoadCodeObjectEntry(TNode code); - // Allocate a RegExpResult with the given length (the number of captures, - // including the match itself), index (the index where the match starts), - // and input string. + // Allocate either a JSRegExpResult or a JSRegExpResultWithIndices (depending + // on has_indices) with the given length (the number of captures, including + // the match itself), index (the index where the match starts), and input + // string. TNode AllocateRegExpResult( TNode context, TNode length, TNode index, TNode input, TNode regexp, TNode last_index, - TNode* elements_out = nullptr); + TNode has_indices, TNode* elements_out = nullptr); TNode FastLoadLastIndexBeforeSmiCheck(TNode regexp); TNode FastLoadLastIndex(TNode regexp) { diff --git a/src/builtins/regexp.tq b/src/builtins/regexp.tq index fc07f471df59..9fb1215e2ec3 100644 --- a/src/builtins/regexp.tq +++ b/src/builtins/regexp.tq @@ -51,8 +51,8 @@ transitioning macro RegExpExec(implicit context: Context)( } extern macro RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( - implicit context: Context)( - JSRegExp, RegExpMatchInfo, String, Number): JSRegExpResult; + implicit context: Context)(JSRegExp, RegExpMatchInfo, String, Number): + JSRegExpResult|JSRegExpResultWithIndices; const kGlobalOrSticky: constexpr int31 generates 'JSRegExp::kGlobal | JSRegExp::kSticky'; @@ -185,6 +185,7 @@ extern enum Flag constexpr 'JSRegExp::Flag' { kSticky, kUnicode, kDotAll, + kHasIndices, kLinear } @@ -243,6 +244,13 @@ transitioning javascript builtin RegExpPrototypeMultilineGetter( 'RegExp.prototype.multiline'); } +transitioning javascript builtin RegExpPrototypeHasIndicesGetter( + js-implicit context: NativeContext, receiver: JSAny)(): JSAny { + return FlagGetter( + receiver, Flag::kHasIndices, kNoCounterFlagGetter, + 'RegExp.prototype.hasIndices'); +} + transitioning javascript builtin RegExpPrototypeLinearGetter( js-implicit context: NativeContext, receiver: JSAny)(): JSAny { return FlagGetter( diff --git a/src/codegen/external-reference.cc b/src/codegen/external-reference.cc index 3a1f1af7403f..08eaadd4243f 100644 --- a/src/codegen/external-reference.cc +++ b/src/codegen/external-reference.cc @@ -462,6 +462,11 @@ ExternalReference ExternalReference::address_of_builtin_subclassing_flag() { return ExternalReference(&FLAG_builtin_subclassing); } +ExternalReference +ExternalReference::address_of_harmony_regexp_match_indices_flag() { + return ExternalReference(&FLAG_harmony_regexp_match_indices); +} + ExternalReference ExternalReference::address_of_runtime_stats_flag() { return ExternalReference(&TracingFlags::runtime_stats); } diff --git a/src/codegen/external-reference.h b/src/codegen/external-reference.h index c1c10419e606..79f6ce5e1be8 100644 --- a/src/codegen/external-reference.h +++ b/src/codegen/external-reference.h @@ -99,16 +99,18 @@ class StatsCounter; #define EXTERNAL_REFERENCE_LIST(V) \ V(abort_with_reason, "abort_with_reason") \ + V(address_of_builtin_subclassing_flag, "FLAG_builtin_subclassing") \ V(address_of_double_abs_constant, "double_absolute_constant") \ V(address_of_double_neg_constant, "double_negate_constant") \ V(address_of_enable_experimental_regexp_engine, \ "address_of_enable_experimental_regexp_engine") \ V(address_of_float_abs_constant, "float_absolute_constant") \ V(address_of_float_neg_constant, "float_negate_constant") \ + V(address_of_harmony_regexp_match_indices_flag, \ + "FLAG_harmony_regexp_match_indices") \ V(address_of_min_int, "LDoubleConstant::min_int") \ V(address_of_mock_arraybuffer_allocator_flag, \ "FLAG_mock_arraybuffer_allocator") \ - V(address_of_builtin_subclassing_flag, "FLAG_builtin_subclassing") \ V(address_of_one_half, "LDoubleConstant::one_half") \ V(address_of_runtime_stats_flag, "TracingFlags::runtime_stats") \ V(address_of_the_hole_nan, "the_hole_nan") \ diff --git a/src/common/message-template.h b/src/common/message-template.h index 8394c6c5364c..11a9baca32f1 100644 --- a/src/common/message-template.h +++ b/src/common/message-template.h @@ -125,10 +125,14 @@ namespace internal { T(NonCoercibleWithProperty, \ "Cannot destructure property '%' of '%' as it is %.") \ T(NonExtensibleProto, "% is not extensible") \ + T(NonObjectAssertOption, "The 'assert' option must be an object") \ T(NonObjectInInstanceOfCheck, \ "Right-hand side of 'instanceof' is not an object") \ T(NonObjectPropertyLoad, "Cannot read property '%' of %") \ T(NonObjectPropertyStore, "Cannot set property '%' of %") \ + T(NonObjectImportArgument, \ + "The second argument to import() must be an object") \ + T(NonStringImportAssertionValue, "Import assertion value must be a string") \ T(NoSetterInCallback, "Cannot set property % of % which has only a getter") \ T(NotAnIterator, "% is not an iterator") \ T(NotAPromise, "% is not a promise") \ diff --git a/src/compiler/backend/arm/code-generator-arm.cc b/src/compiler/backend/arm/code-generator-arm.cc index d54343027757..d894a65d433b 100644 --- a/src/compiler/backend/arm/code-generator-arm.cc +++ b/src/compiler/backend/arm/code-generator-arm.cc @@ -3220,7 +3220,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( __ vrev16(Neon8, i.OutputSimd128Register(), i.InputSimd128Register(0)); break; } - case kArmV128AnyTrue: { + case kArmV32x4AnyTrue: + case kArmV16x8AnyTrue: + case kArmV8x16AnyTrue: { const QwNeonRegister& src = i.InputSimd128Register(0); UseScratchRegisterScope temps(tasm()); DwVfpRegister scratch = temps.AcquireD(); diff --git a/src/compiler/backend/arm/instruction-codes-arm.h b/src/compiler/backend/arm/instruction-codes-arm.h index 591a5e0a1722..b5a77a1a10cb 100644 --- a/src/compiler/backend/arm/instruction-codes-arm.h +++ b/src/compiler/backend/arm/instruction-codes-arm.h @@ -327,9 +327,11 @@ namespace compiler { V(ArmS8x8Reverse) \ V(ArmS8x4Reverse) \ V(ArmS8x2Reverse) \ + V(ArmV32x4AnyTrue) \ V(ArmV32x4AllTrue) \ + V(ArmV16x8AnyTrue) \ V(ArmV16x8AllTrue) \ - V(ArmV128AnyTrue) \ + V(ArmV8x16AnyTrue) \ V(ArmV8x16AllTrue) \ V(ArmS128Load8Splat) \ V(ArmS128Load16Splat) \ diff --git a/src/compiler/backend/arm/instruction-scheduler-arm.cc b/src/compiler/backend/arm/instruction-scheduler-arm.cc index 9168e16bde8f..8b52a18482b4 100644 --- a/src/compiler/backend/arm/instruction-scheduler-arm.cc +++ b/src/compiler/backend/arm/instruction-scheduler-arm.cc @@ -307,9 +307,11 @@ int InstructionScheduler::GetTargetInstructionFlags( case kArmS8x8Reverse: case kArmS8x4Reverse: case kArmS8x2Reverse: + case kArmV32x4AnyTrue: case kArmV32x4AllTrue: + case kArmV16x8AnyTrue: case kArmV16x8AllTrue: - case kArmV128AnyTrue: + case kArmV8x16AnyTrue: case kArmV8x16AllTrue: return kNoOpcodeFlags; diff --git a/src/compiler/backend/arm/instruction-selector-arm.cc b/src/compiler/backend/arm/instruction-selector-arm.cc index b3c06887e39a..78a458083dd4 100644 --- a/src/compiler/backend/arm/instruction-selector-arm.cc +++ b/src/compiler/backend/arm/instruction-selector-arm.cc @@ -2596,9 +2596,11 @@ void InstructionSelector::VisitWord32AtomicPairCompareExchange(Node* node) { V(I8x16Abs, kArmI8x16Abs) \ V(I8x16Popcnt, kArmVcnt) \ V(S128Not, kArmS128Not) \ + V(V32x4AnyTrue, kArmV32x4AnyTrue) \ V(V32x4AllTrue, kArmV32x4AllTrue) \ + V(V16x8AnyTrue, kArmV16x8AnyTrue) \ V(V16x8AllTrue, kArmV16x8AllTrue) \ - V(V128AnyTrue, kArmV128AnyTrue) \ + V(V8x16AnyTrue, kArmV8x16AnyTrue) \ V(V8x16AllTrue, kArmV8x16AllTrue) #define SIMD_SHIFT_OP_LIST(V) \ diff --git a/src/compiler/backend/arm64/instruction-selector-arm64.cc b/src/compiler/backend/arm64/instruction-selector-arm64.cc index bc8a29354876..7979ee697eed 100644 --- a/src/compiler/backend/arm64/instruction-selector-arm64.cc +++ b/src/compiler/backend/arm64/instruction-selector-arm64.cc @@ -3423,9 +3423,11 @@ void InstructionSelector::VisitInt64AbsWithOverflow(Node* node) { V(I8x16Abs, kArm64I8x16Abs) \ V(I8x16BitMask, kArm64I8x16BitMask) \ V(S128Not, kArm64S128Not) \ + V(V32x4AnyTrue, kArm64V128AnyTrue) \ V(V32x4AllTrue, kArm64V32x4AllTrue) \ + V(V16x8AnyTrue, kArm64V128AnyTrue) \ V(V16x8AllTrue, kArm64V16x8AllTrue) \ - V(V128AnyTrue, kArm64V128AnyTrue) \ + V(V8x16AnyTrue, kArm64V128AnyTrue) \ V(V8x16AllTrue, kArm64V8x16AllTrue) #define SIMD_SHIFT_OP_LIST(V) \ diff --git a/src/compiler/backend/ia32/instruction-selector-ia32.cc b/src/compiler/backend/ia32/instruction-selector-ia32.cc index e1ad1e7d0303..8e1fcc6c5776 100644 --- a/src/compiler/backend/ia32/instruction-selector-ia32.cc +++ b/src/compiler/backend/ia32/instruction-selector-ia32.cc @@ -2336,6 +2336,11 @@ void InstructionSelector::VisitWord32AtomicPairCompareExchange(Node* node) { V(I8x16BitMask) \ V(S128Not) +#define SIMD_ANYTRUE_LIST(V) \ + V(V32x4AnyTrue) \ + V(V16x8AnyTrue) \ + V(V8x16AnyTrue) + #define SIMD_ALLTRUE_LIST(V) \ V(V32x4AllTrue) \ V(V16x8AllTrue) \ @@ -2633,12 +2638,17 @@ SIMD_UNOP_LIST(VISIT_SIMD_UNOP) #undef VISIT_SIMD_UNOP #undef SIMD_UNOP_LIST -void InstructionSelector::VisitV128AnyTrue(Node* node) { - IA32OperandGenerator g(this); - InstructionOperand temps[] = {g.TempRegister()}; - Emit(kIA32S128AnyTrue, g.DefineAsRegister(node), - g.UseRegister(node->InputAt(0)), arraysize(temps), temps); -} +// The implementation of AnyTrue is the same for all shapes. +#define VISIT_SIMD_ANYTRUE(Opcode) \ + void InstructionSelector::Visit##Opcode(Node* node) { \ + IA32OperandGenerator g(this); \ + InstructionOperand temps[] = {g.TempRegister()}; \ + Emit(kIA32S128AnyTrue, g.DefineAsRegister(node), \ + g.UseRegister(node->InputAt(0)), arraysize(temps), temps); \ + } +SIMD_ANYTRUE_LIST(VISIT_SIMD_ANYTRUE) +#undef VISIT_SIMD_ANYTRUE +#undef SIMD_ANYTRUE_LIST #define VISIT_SIMD_ALLTRUE(Opcode) \ void InstructionSelector::Visit##Opcode(Node* node) { \ diff --git a/src/compiler/backend/instruction-selector.cc b/src/compiler/backend/instruction-selector.cc index 3b35b0072985..6aa7326e3aa7 100644 --- a/src/compiler/backend/instruction-selector.cc +++ b/src/compiler/backend/instruction-selector.cc @@ -2306,12 +2306,16 @@ void InstructionSelector::VisitNode(Node* node) { return MarkAsSimd128(node), VisitI8x16Swizzle(node); case IrOpcode::kI8x16Shuffle: return MarkAsSimd128(node), VisitI8x16Shuffle(node); + case IrOpcode::kV32x4AnyTrue: + return MarkAsWord32(node), VisitV32x4AnyTrue(node); case IrOpcode::kV32x4AllTrue: return MarkAsWord32(node), VisitV32x4AllTrue(node); + case IrOpcode::kV16x8AnyTrue: + return MarkAsWord32(node), VisitV16x8AnyTrue(node); case IrOpcode::kV16x8AllTrue: return MarkAsWord32(node), VisitV16x8AllTrue(node); - case IrOpcode::kV128AnyTrue: - return MarkAsWord32(node), VisitV128AnyTrue(node); + case IrOpcode::kV8x16AnyTrue: + return MarkAsWord32(node), VisitV8x16AnyTrue(node); case IrOpcode::kV8x16AllTrue: return MarkAsWord32(node), VisitV8x16AllTrue(node); default: diff --git a/src/compiler/backend/x64/code-generator-x64.cc b/src/compiler/backend/x64/code-generator-x64.cc index bba7fe2e11d8..aefeb783ef0d 100644 --- a/src/compiler/backend/x64/code-generator-x64.cc +++ b/src/compiler/backend/x64/code-generator-x64.cc @@ -4227,7 +4227,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( __ Por(dst, kScratchDoubleReg); break; } - case kX64V128AnyTrue: { + case kX64V32x4AnyTrue: + case kX64V16x8AnyTrue: + case kX64V8x16AnyTrue: { Register dst = i.OutputRegister(); XMMRegister src = i.InputSimd128Register(0); diff --git a/src/compiler/backend/x64/instruction-codes-x64.h b/src/compiler/backend/x64/instruction-codes-x64.h index 805f6f883541..b2d168b86055 100644 --- a/src/compiler/backend/x64/instruction-codes-x64.h +++ b/src/compiler/backend/x64/instruction-codes-x64.h @@ -389,9 +389,11 @@ namespace compiler { V(X64S8x8Reverse) \ V(X64S8x4Reverse) \ V(X64S8x2Reverse) \ + V(X64V32x4AnyTrue) \ V(X64V32x4AllTrue) \ + V(X64V16x8AnyTrue) \ V(X64V16x8AllTrue) \ - V(X64V128AnyTrue) \ + V(X64V8x16AnyTrue) \ V(X64V8x16AllTrue) \ V(X64Prefetch) \ V(X64PrefetchNta) \ diff --git a/src/compiler/backend/x64/instruction-scheduler-x64.cc b/src/compiler/backend/x64/instruction-scheduler-x64.cc index d73080cc4f05..89c7681b0e38 100644 --- a/src/compiler/backend/x64/instruction-scheduler-x64.cc +++ b/src/compiler/backend/x64/instruction-scheduler-x64.cc @@ -317,7 +317,9 @@ int InstructionScheduler::GetTargetInstructionFlags( case kX64S128Zero: case kX64S128AllOnes: case kX64S128AndNot: + case kX64V32x4AnyTrue: case kX64V32x4AllTrue: + case kX64V16x8AnyTrue: case kX64V16x8AllTrue: case kX64I8x16Swizzle: case kX64I8x16Shuffle: @@ -349,7 +351,7 @@ int InstructionScheduler::GetTargetInstructionFlags( case kX64S8x8Reverse: case kX64S8x4Reverse: case kX64S8x2Reverse: - case kX64V128AnyTrue: + case kX64V8x16AnyTrue: case kX64V8x16AllTrue: return (instr->addressing_mode() == kMode_None) ? kNoOpcodeFlags diff --git a/src/compiler/backend/x64/instruction-selector-x64.cc b/src/compiler/backend/x64/instruction-selector-x64.cc index 57d06f01e2f1..57c6afa1cc85 100644 --- a/src/compiler/backend/x64/instruction-selector-x64.cc +++ b/src/compiler/backend/x64/instruction-selector-x64.cc @@ -2977,6 +2977,11 @@ VISIT_ATOMIC_BINOP(Xor) V(I8x16Shl) \ V(I8x16ShrU) +#define SIMD_ANYTRUE_LIST(V) \ + V(V32x4AnyTrue) \ + V(V16x8AnyTrue) \ + V(V8x16AnyTrue) + #define SIMD_ALLTRUE_LIST(V) \ V(V32x4AllTrue) \ V(V16x8AllTrue) \ @@ -3167,11 +3172,15 @@ SIMD_BINOP_ONE_TEMP_LIST(VISIT_SIMD_BINOP_ONE_TEMP) #undef VISIT_SIMD_BINOP_ONE_TEMP #undef SIMD_BINOP_ONE_TEMP_LIST -void InstructionSelector::VisitV128AnyTrue(Node* node) { - X64OperandGenerator g(this); - Emit(kX64V128AnyTrue, g.DefineAsRegister(node), - g.UseUniqueRegister(node->InputAt(0))); -} +#define VISIT_SIMD_ANYTRUE(Opcode) \ + void InstructionSelector::Visit##Opcode(Node* node) { \ + X64OperandGenerator g(this); \ + Emit(kX64##Opcode, g.DefineAsRegister(node), \ + g.UseUniqueRegister(node->InputAt(0))); \ + } +SIMD_ANYTRUE_LIST(VISIT_SIMD_ANYTRUE) +#undef VISIT_SIMD_ANYTRUE +#undef SIMD_ANYTRUE_LIST #define VISIT_SIMD_ALLTRUE(Opcode) \ void InstructionSelector::Visit##Opcode(Node* node) { \ diff --git a/src/compiler/machine-operator.cc b/src/compiler/machine-operator.cc index 5b24af57f941..d94cf350c3a8 100644 --- a/src/compiler/machine-operator.cc +++ b/src/compiler/machine-operator.cc @@ -548,9 +548,11 @@ ShiftKind ShiftKindOf(Operator const* op) { V(S128Not, Operator::kNoProperties, 1, 0, 1) \ V(S128Select, Operator::kNoProperties, 3, 0, 1) \ V(S128AndNot, Operator::kNoProperties, 2, 0, 1) \ + V(V32x4AnyTrue, Operator::kNoProperties, 1, 0, 1) \ V(V32x4AllTrue, Operator::kNoProperties, 1, 0, 1) \ + V(V16x8AnyTrue, Operator::kNoProperties, 1, 0, 1) \ V(V16x8AllTrue, Operator::kNoProperties, 1, 0, 1) \ - V(V128AnyTrue, Operator::kNoProperties, 1, 0, 1) \ + V(V8x16AnyTrue, Operator::kNoProperties, 1, 0, 1) \ V(V8x16AllTrue, Operator::kNoProperties, 1, 0, 1) \ V(I8x16Swizzle, Operator::kNoProperties, 2, 0, 1) diff --git a/src/compiler/machine-operator.h b/src/compiler/machine-operator.h index 946a412d74a6..8b0597a55b9e 100644 --- a/src/compiler/machine-operator.h +++ b/src/compiler/machine-operator.h @@ -819,9 +819,11 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final const Operator* I8x16Swizzle(); const Operator* I8x16Shuffle(const uint8_t shuffle[16]); + const Operator* V32x4AnyTrue(); const Operator* V32x4AllTrue(); + const Operator* V16x8AnyTrue(); const Operator* V16x8AllTrue(); - const Operator* V128AnyTrue(); + const Operator* V8x16AnyTrue(); const Operator* V8x16AllTrue(); // load [base + index] diff --git a/src/compiler/opcodes.h b/src/compiler/opcodes.h index e90ee3ae6483..9a511106fd22 100644 --- a/src/compiler/opcodes.h +++ b/src/compiler/opcodes.h @@ -978,9 +978,11 @@ V(S128AndNot) \ V(I8x16Swizzle) \ V(I8x16Shuffle) \ + V(V32x4AnyTrue) \ V(V32x4AllTrue) \ + V(V16x8AnyTrue) \ V(V16x8AllTrue) \ - V(V128AnyTrue) \ + V(V8x16AnyTrue) \ V(V8x16AllTrue) \ V(LoadTransform) \ V(PrefetchTemporal) \ diff --git a/src/compiler/simd-scalar-lowering.cc b/src/compiler/simd-scalar-lowering.cc index f8408af063eb..f9bf22f8be56 100644 --- a/src/compiler/simd-scalar-lowering.cc +++ b/src/compiler/simd-scalar-lowering.cc @@ -166,9 +166,11 @@ void SimdScalarLowering::LowerGraph() { V(S128Not) \ V(S128AndNot) \ V(S128Select) \ + V(V32x4AnyTrue) \ V(V32x4AllTrue) \ + V(V16x8AnyTrue) \ V(V16x8AllTrue) \ - V(V128AnyTrue) \ + V(V8x16AnyTrue) \ V(V8x16AllTrue) \ V(I32x4BitMask) \ V(I32x4ExtMulLowI16x8S) \ @@ -2218,7 +2220,9 @@ void SimdScalarLowering::LowerNode(Node* node) { ReplaceNode(node, rep_node, 16); break; } - case IrOpcode::kV128AnyTrue: { + case IrOpcode::kV32x4AnyTrue: + case IrOpcode::kV16x8AnyTrue: + case IrOpcode::kV8x16AnyTrue: { DCHECK_EQ(1, node->InputCount()); // AnyTrue always returns a I32x4, and can work with inputs of any shape, // but we still need GetReplacementsWithType if input is float. diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc index cb2475a0f1f1..e7162303eff2 100644 --- a/src/compiler/wasm-compiler.cc +++ b/src/compiler/wasm-compiler.cc @@ -5211,12 +5211,16 @@ Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, Node* const* inputs) { case wasm::kExprS128AndNot: return graph()->NewNode(mcgraph()->machine()->S128AndNot(), inputs[0], inputs[1]); + case wasm::kExprV32x4AnyTrue: + return graph()->NewNode(mcgraph()->machine()->V32x4AnyTrue(), inputs[0]); case wasm::kExprV32x4AllTrue: return graph()->NewNode(mcgraph()->machine()->V32x4AllTrue(), inputs[0]); + case wasm::kExprV16x8AnyTrue: + return graph()->NewNode(mcgraph()->machine()->V16x8AnyTrue(), inputs[0]); case wasm::kExprV16x8AllTrue: return graph()->NewNode(mcgraph()->machine()->V16x8AllTrue(), inputs[0]); - case wasm::kExprV128AnyTrue: - return graph()->NewNode(mcgraph()->machine()->V128AnyTrue(), inputs[0]); + case wasm::kExprV8x16AnyTrue: + return graph()->NewNode(mcgraph()->machine()->V8x16AnyTrue(), inputs[0]); case wasm::kExprV8x16AllTrue: return graph()->NewNode(mcgraph()->machine()->V8x16AllTrue(), inputs[0]); case wasm::kExprI8x16Swizzle: diff --git a/src/d8/d8.cc b/src/d8/d8.cc index 84f1628cd7fd..b9932415c343 100644 --- a/src/d8/d8.cc +++ b/src/d8/d8.cc @@ -839,13 +839,46 @@ class ModuleEmbedderData { public: explicit ModuleEmbedderData(Isolate* isolate) - : module_to_specifier_map(10, ModuleGlobalHash(isolate)) {} + : module_to_specifier_map(10, ModuleGlobalHash(isolate)), + json_module_to_parsed_json_map(10, ModuleGlobalHash(isolate)) {} + + static ModuleType ModuleTypeFromImportAssertions( + Local context, Local import_assertions, + bool hasPositions) { + Isolate* isolate = context->GetIsolate(); + const int kV8AssertionEntrySize = hasPositions ? 3 : 2; + for (int i = 0; i < import_assertions->Length(); + i += kV8AssertionEntrySize) { + Local v8_assertion_key = + import_assertions->Get(context, i).As(); + std::string assertion_key = ToSTLString(isolate, v8_assertion_key); + + if (assertion_key == "type") { + Local v8_assertion_value = + import_assertions->Get(context, i + 1).As(); + std::string assertion_value = ToSTLString(isolate, v8_assertion_value); + if (assertion_value == "json") { + return ModuleType::kJSON; + } else { + // JSON is currently the only supported non-JS type + return ModuleType::kInvalid; + } + } + } + + // If no type is asserted, default to JS. + return ModuleType::kJavaScript; + } - // Map from normalized module specifier to Module. - std::unordered_map> specifier_to_module_map; + // Map from (normalized module specifier, module type) pair to Module. + std::map, Global> module_map; // Map from Module to its URL as defined in the ScriptOrigin std::unordered_map, std::string, ModuleGlobalHash> module_to_specifier_map; + // Map from JSON Module to its parsed content, for use in module + // JSONModuleEvaluationSteps + std::unordered_map, Global, ModuleGlobalHash> + json_module_to_parsed_json_map; }; enum { kModuleEmbedderDataIndex, kInspectorClientIndex }; @@ -869,7 +902,6 @@ MaybeLocal ResolveModuleCallback(Local context, Local specifier, Local import_assertions, Local referrer) { - // TODO(v8:11189) Consider JSON modules support in d8. Isolate* isolate = context->GetIsolate(); ModuleEmbedderData* d = GetModuleDataFromContext(context); auto specifier_it = @@ -877,8 +909,11 @@ MaybeLocal ResolveModuleCallback(Local context, CHECK(specifier_it != d->module_to_specifier_map.end()); std::string absolute_path = NormalizePath(ToSTLString(isolate, specifier), DirName(specifier_it->second)); - auto module_it = d->specifier_to_module_map.find(absolute_path); - CHECK(module_it != d->specifier_to_module_map.end()); + ModuleType module_type = ModuleEmbedderData::ModuleTypeFromImportAssertions( + context, import_assertions, true); + auto module_it = + d->module_map.find(std::make_pair(absolute_path, module_type)); + CHECK(module_it != d->module_map.end()); return module_it->second.Get(isolate); } @@ -886,7 +921,8 @@ MaybeLocal ResolveModuleCallback(Local context, MaybeLocal Shell::FetchModuleTree(Local referrer, Local context, - const std::string& file_name) { + const std::string& file_name, + ModuleType module_type) { DCHECK(IsAbsolutePath(file_name)); Isolate* isolate = context->GetIsolate(); Local source_text = ReadFile(isolate, file_name.c_str()); @@ -914,16 +950,39 @@ MaybeLocal Shell::FetchModuleTree(Local referrer, ScriptOrigin origin( isolate, String::NewFromUtf8(isolate, file_name.c_str()).ToLocalChecked(), 0, 0, false, -1, Local(), false, false, true); - ScriptCompiler::Source source(source_text, origin); Local module; - if (!CompileString(isolate, context, source_text, origin) - .ToLocal(&module)) { - return MaybeLocal(); + if (module_type == ModuleType::kJavaScript) { + ScriptCompiler::Source source(source_text, origin); + if (!CompileString(isolate, context, source_text, origin) + .ToLocal(&module)) { + return MaybeLocal(); + } + } else if (module_type == ModuleType::kJSON) { + Local parsed_json; + if (!v8::JSON::Parse(context, source_text).ToLocal(&parsed_json)) { + return MaybeLocal(); + } + + std::vector> export_names{ + String::NewFromUtf8(isolate, "default").ToLocalChecked()}; + + module = v8::Module::CreateSyntheticModule( + isolate, + String::NewFromUtf8(isolate, file_name.c_str()).ToLocalChecked(), + export_names, Shell::JSONModuleEvaluationSteps); + + CHECK(d->json_module_to_parsed_json_map + .insert(std::make_pair(Global(isolate, module), + Global(isolate, parsed_json))) + .second); + } else { + UNREACHABLE(); } - CHECK(d->specifier_to_module_map - .insert(std::make_pair(file_name, Global(isolate, module))) + CHECK(d->module_map + .insert(std::make_pair(std::make_pair(file_name, module_type), + Global(isolate, module))) .second); CHECK(d->module_to_specifier_map .insert(std::make_pair(Global(isolate, module), file_name)) @@ -938,8 +997,23 @@ MaybeLocal Shell::FetchModuleTree(Local referrer, Local name = module_request->GetSpecifier(); std::string absolute_path = NormalizePath(ToSTLString(isolate, name), dir_name); - if (d->specifier_to_module_map.count(absolute_path)) continue; - if (FetchModuleTree(module, context, absolute_path).IsEmpty()) { + Local import_assertions = module_request->GetImportAssertions(); + ModuleType request_module_type = + ModuleEmbedderData::ModuleTypeFromImportAssertions( + context, import_assertions, true); + + if (request_module_type == ModuleType::kInvalid) { + Throw(isolate, "Invalid module type was asserted"); + return MaybeLocal(); + } + + if (d->module_map.count( + std::make_pair(absolute_path, request_module_type))) { + continue; + } + + if (FetchModuleTree(module, context, absolute_path, request_module_type) + .IsEmpty()) { return MaybeLocal(); } } @@ -947,19 +1021,53 @@ MaybeLocal Shell::FetchModuleTree(Local referrer, return module; } +MaybeLocal Shell::JSONModuleEvaluationSteps(Local context, + Local module) { + Isolate* isolate = context->GetIsolate(); + + ModuleEmbedderData* d = GetModuleDataFromContext(context); + auto json_value_it = + d->json_module_to_parsed_json_map.find(Global(isolate, module)); + CHECK(json_value_it != d->json_module_to_parsed_json_map.end()); + Local json_value = json_value_it->second.Get(isolate); + + TryCatch try_catch(isolate); + Maybe result = module->SetSyntheticModuleExport( + isolate, + String::NewFromUtf8Literal(isolate, "default", + NewStringType::kInternalized), + json_value); + + // Setting the default export should never fail. + CHECK(!try_catch.HasCaught()); + CHECK(!result.IsNothing() && result.FromJust()); + + if (i::FLAG_harmony_top_level_await) { + Local resolver = + Promise::Resolver::New(context).ToLocalChecked(); + resolver->Resolve(context, Undefined(isolate)).ToChecked(); + return resolver->GetPromise(); + } + + return Undefined(isolate); +} + struct DynamicImportData { DynamicImportData(Isolate* isolate_, Local referrer_, Local specifier_, + Local import_assertions_, Local resolver_) : isolate(isolate_) { referrer.Reset(isolate, referrer_); specifier.Reset(isolate, specifier_); + import_assertions.Reset(isolate, import_assertions_); resolver.Reset(isolate, resolver_); } Isolate* isolate; Global referrer; Global specifier; + Global import_assertions; Global resolver; }; @@ -1020,15 +1128,16 @@ void Shell::ModuleResolutionFailureCallback( MaybeLocal Shell::HostImportModuleDynamically( Local context, Local referrer, - Local specifier) { + Local specifier, Local import_assertions) { Isolate* isolate = context->GetIsolate(); MaybeLocal maybe_resolver = Promise::Resolver::New(context); Local resolver; if (maybe_resolver.ToLocal(&resolver)) { - DynamicImportData* data = new DynamicImportData( - isolate, referrer->GetResourceName().As(), specifier, resolver); + DynamicImportData* data = + new DynamicImportData(isolate, referrer->GetResourceName().As(), + specifier, import_assertions, resolver); PerIsolateData::Get(isolate)->AddDynamicImportData(data); isolate->EnqueueMicrotask(Shell::DoHostImportModuleDynamically, data); return resolver->GetPromise(); @@ -1064,6 +1173,8 @@ void Shell::DoHostImportModuleDynamically(void* import_data) { Local referrer(import_data_->referrer.Get(isolate)); Local specifier(import_data_->specifier.Get(isolate)); + Local import_assertions( + import_data_->import_assertions.Get(isolate)); Local resolver(import_data_->resolver.Get(isolate)); PerIsolateData* data = PerIsolateData::Get(isolate); @@ -1072,21 +1183,33 @@ void Shell::DoHostImportModuleDynamically(void* import_data) { Local realm = data->realms_[data->realm_current_].Get(isolate); Context::Scope context_scope(realm); + ModuleType module_type = ModuleEmbedderData::ModuleTypeFromImportAssertions( + realm, import_assertions, false); + + TryCatch try_catch(isolate); + try_catch.SetVerbose(true); + + if (module_type == ModuleType::kInvalid) { + Throw(isolate, "Invalid module type was asserted"); + CHECK(try_catch.HasCaught()); + resolver->Reject(realm, try_catch.Exception()).ToChecked(); + return; + } + std::string source_url = ToSTLString(isolate, referrer); std::string dir_name = DirName(NormalizePath(source_url, GetWorkingDirectory())); std::string file_name = ToSTLString(isolate, specifier); std::string absolute_path = NormalizePath(file_name, dir_name); - TryCatch try_catch(isolate); - try_catch.SetVerbose(true); - ModuleEmbedderData* d = GetModuleDataFromContext(realm); Local root_module; - auto module_it = d->specifier_to_module_map.find(absolute_path); - if (module_it != d->specifier_to_module_map.end()) { + auto module_it = + d->module_map.find(std::make_pair(absolute_path, module_type)); + if (module_it != d->module_map.end()) { root_module = module_it->second.Get(isolate); - } else if (!FetchModuleTree(Local(), realm, absolute_path) + } else if (!FetchModuleTree(Local(), realm, absolute_path, + module_type) .ToLocal(&root_module)) { CHECK(try_catch.HasCaught()); resolver->Reject(realm, try_catch.Exception()).ToChecked(); @@ -1154,7 +1277,8 @@ bool Shell::ExecuteModule(Isolate* isolate, const char* file_name) { Local root_module; - if (!FetchModuleTree(Local(), realm, absolute_path) + if (!FetchModuleTree(Local(), realm, absolute_path, + ModuleType::kJavaScript) .ToLocal(&root_module)) { CHECK(try_catch.HasCaught()); ReportException(isolate, &try_catch); diff --git a/src/d8/d8.h b/src/d8/d8.h index a6a1037cff1c..a9f6f3bc8b86 100644 --- a/src/d8/d8.h +++ b/src/d8/d8.h @@ -26,6 +26,8 @@ namespace v8 { class D8Console; +enum class ModuleType { kJavaScript, kJSON, kInvalid }; + namespace internal { class CancelableTaskManager; } // namespace internal @@ -534,7 +536,7 @@ class Shell : public i::AllStatic { static void RemoveDirectory(const v8::FunctionCallbackInfo& args); static MaybeLocal HostImportModuleDynamically( Local context, Local referrer, - Local specifier); + Local specifier, Local import_assertions); static void ModuleResolutionSuccessCallback( const v8::FunctionCallbackInfo& info); static void ModuleResolutionFailureCallback( @@ -630,7 +632,11 @@ class Shell : public i::AllStatic { int index); static MaybeLocal FetchModuleTree(v8::Local origin_module, v8::Local context, - const std::string& file_name); + const std::string& file_name, + ModuleType module_type); + + static MaybeLocal JSONModuleEvaluationSteps(Local context, + Local module); template static MaybeLocal CompileString(Isolate* isolate, Local context, diff --git a/src/debug/debug-evaluate.cc b/src/debug/debug-evaluate.cc index 77683fde1ef0..b8d377ce84f5 100644 --- a/src/debug/debug-evaluate.cc +++ b/src/debug/debug-evaluate.cc @@ -843,6 +843,7 @@ DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtins::Name id) { case Builtins::kRegExpPrototypeSplit: case Builtins::kRegExpPrototypeFlagsGetter: case Builtins::kRegExpPrototypeGlobalGetter: + case Builtins::kRegExpPrototypeHasIndicesGetter: case Builtins::kRegExpPrototypeIgnoreCaseGetter: case Builtins::kRegExpPrototypeMatchAll: case Builtins::kRegExpPrototypeMultilineGetter: diff --git a/src/execution/isolate.cc b/src/execution/isolate.cc index 3869231aeb9a..fc6d252e110e 100644 --- a/src/execution/isolate.cc +++ b/src/execution/isolate.cc @@ -4153,11 +4153,17 @@ MaybeHandle NewRejectedPromise(Isolate* isolate, } // namespace MaybeHandle Isolate::RunHostImportModuleDynamicallyCallback( - Handle