Commit 9135859a authored by legendecas's avatar legendecas Committed by V8 LUCI CQ

[ShadowRealm] Implement ShadowRealm.prototype.importValue

As per https://tc39.es/ecma262/#sec-hostimportmoduledynamically defined,
referencingScriptOrModule in HostImportModuleDynamically can be a Script
Record, a Module Record, or null.
So to https://tc39.es/proposal-shadowrealm/#sec-shadowrealmimportvalue,
the HostImportModuleDynamicallyCallback is been invoked with a `null`
resource_name. This may not be considered a breaking change as the
parameter resource_name is defined as Local<Value>.

Updates d8's DoHostImportModuleDynamically to handle null resource_name,
and resolve the dynamically imported specifier relative to the executing
script's origin. In this way, we have to set ModuleEmbedderData.origin
even if the JavaScript source to be evaluated is Script. Also, a
ModuleEmbedderData is created for each ShadowRealm to separate their
module maps from the initiator context's.

Bug: v8:11989
Change-Id: If70fb140657da4f2dd92eedfcc4515211602aa46
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3522883Reviewed-by: 's avatarShu-yu Guo <syg@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Commit-Queue: Chengzhong Wu <legendecas@gmail.com>
Cr-Commit-Position: refs/heads/main@{#80118}
parent 9ad39743
...@@ -872,7 +872,11 @@ namespace internal { ...@@ -872,7 +872,11 @@ namespace internal {
CPP(ShadowRealmConstructor) \ CPP(ShadowRealmConstructor) \
TFS(ShadowRealmGetWrappedValue, kCreationContext, kTargetContext, kValue) \ TFS(ShadowRealmGetWrappedValue, kCreationContext, kTargetContext, kValue) \
CPP(ShadowRealmPrototypeEvaluate) \ CPP(ShadowRealmPrototypeEvaluate) \
CPP(ShadowRealmPrototypeImportValue) \ TFJ(ShadowRealmPrototypeImportValue, kJSArgcReceiverSlots + 2, kReceiver, \
kSpecifier, kExportName) \
TFJ(ShadowRealmImportValueFulfilled, kJSArgcReceiverSlots + 1, kReceiver, \
kExports) \
TFJ(ShadowRealmImportValueRejected, kDontAdaptArgumentsSentinel) \
\ \
/* SharedArrayBuffer */ \ /* SharedArrayBuffer */ \
CPP(SharedArrayBufferPrototypeGetByteLength) \ CPP(SharedArrayBufferPrototypeGetByteLength) \
......
...@@ -216,11 +216,5 @@ BUILTIN(ShadowRealmPrototypeEvaluate) { ...@@ -216,11 +216,5 @@ BUILTIN(ShadowRealmPrototypeEvaluate) {
return *wrapped_result; return *wrapped_result;
} }
// https://tc39.es/proposal-shadowrealm/#sec-shadowrealm.prototype.importvalue
BUILTIN(ShadowRealmPrototypeImportValue) {
HandleScope scope(isolate);
return ReadOnlyRoots(isolate).undefined_value();
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#include "src/builtins/builtins.h" #include "src/builtins/builtins.h"
#include "src/codegen/code-stub-assembler.h" #include "src/codegen/code-stub-assembler.h"
#include "src/objects/descriptor-array.h" #include "src/objects/descriptor-array.h"
#include "src/objects/js-shadow-realms.h"
#include "src/objects/module.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -15,11 +17,27 @@ class ShadowRealmBuiltinsAssembler : public CodeStubAssembler { ...@@ -15,11 +17,27 @@ class ShadowRealmBuiltinsAssembler : public CodeStubAssembler {
explicit ShadowRealmBuiltinsAssembler(compiler::CodeAssemblerState* state) explicit ShadowRealmBuiltinsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {} : CodeStubAssembler(state) {}
enum ImportValueFulfilledFunctionContextSlot {
kEvalContextSlot = Context::MIN_CONTEXT_SLOTS,
kSpecifierSlot,
kExportNameSlot,
kContextLength,
};
protected: protected:
TNode<JSObject> AllocateJSWrappedFunction(TNode<Context> context, TNode<JSObject> AllocateJSWrappedFunction(TNode<Context> context,
TNode<Object> target); TNode<Object> target);
void CheckAccessor(TNode<DescriptorArray> array, TNode<IntPtrT> index, void CheckAccessor(TNode<DescriptorArray> array, TNode<IntPtrT> index,
TNode<Name> name, Label* bailout); TNode<Name> name, Label* bailout);
TNode<Object> ImportValue(TNode<NativeContext> caller_context,
TNode<NativeContext> eval_context,
TNode<String> specifier, TNode<String> export_name);
TNode<Context> CreateImportValueFulfilledFunctionContext(
TNode<NativeContext> caller_context, TNode<NativeContext> eval_context,
TNode<String> specifier, TNode<String> export_name);
TNode<JSFunction> AllocateImportValueFulfilledFunction(
TNode<NativeContext> caller_context, TNode<NativeContext> eval_context,
TNode<String> specifier, TNode<String> export_name);
}; };
TNode<JSObject> ShadowRealmBuiltinsAssembler::AllocateJSWrappedFunction( TNode<JSObject> ShadowRealmBuiltinsAssembler::AllocateJSWrappedFunction(
...@@ -35,6 +53,40 @@ TNode<JSObject> ShadowRealmBuiltinsAssembler::AllocateJSWrappedFunction( ...@@ -35,6 +53,40 @@ TNode<JSObject> ShadowRealmBuiltinsAssembler::AllocateJSWrappedFunction(
return wrapped; return wrapped;
} }
TNode<Context>
ShadowRealmBuiltinsAssembler::CreateImportValueFulfilledFunctionContext(
TNode<NativeContext> caller_context, TNode<NativeContext> eval_context,
TNode<String> specifier, TNode<String> export_name) {
const TNode<Context> context = AllocateSyntheticFunctionContext(
caller_context, ImportValueFulfilledFunctionContextSlot::kContextLength);
StoreContextElementNoWriteBarrier(
context, ImportValueFulfilledFunctionContextSlot::kEvalContextSlot,
eval_context);
StoreContextElementNoWriteBarrier(
context, ImportValueFulfilledFunctionContextSlot::kSpecifierSlot,
specifier);
StoreContextElementNoWriteBarrier(
context, ImportValueFulfilledFunctionContextSlot::kExportNameSlot,
export_name);
return context;
}
TNode<JSFunction>
ShadowRealmBuiltinsAssembler::AllocateImportValueFulfilledFunction(
TNode<NativeContext> caller_context, TNode<NativeContext> eval_context,
TNode<String> specifier, TNode<String> export_name) {
const TNode<Context> function_context =
CreateImportValueFulfilledFunctionContext(caller_context, eval_context,
specifier, export_name);
const TNode<Map> function_map = CAST(LoadContextElement(
caller_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX));
const TNode<SharedFunctionInfo> info =
ShadowRealmImportValueFulfilledSFIConstant();
return AllocateFunctionWithMapAndContext(function_map, info,
function_context);
}
void ShadowRealmBuiltinsAssembler::CheckAccessor(TNode<DescriptorArray> array, void ShadowRealmBuiltinsAssembler::CheckAccessor(TNode<DescriptorArray> array,
TNode<IntPtrT> index, TNode<IntPtrT> index,
TNode<Name> name, TNode<Name> name,
...@@ -244,5 +296,131 @@ TF_BUILTIN(CallWrappedFunction, ShadowRealmBuiltinsAssembler) { ...@@ -244,5 +296,131 @@ TF_BUILTIN(CallWrappedFunction, ShadowRealmBuiltinsAssembler) {
Unreachable(); Unreachable();
} }
// https://tc39.es/proposal-shadowrealm/#sec-shadowrealm.prototype.importvalue
TF_BUILTIN(ShadowRealmPrototypeImportValue, ShadowRealmBuiltinsAssembler) {
const char* const kMethodName = "ShadowRealm.prototype.importValue";
TNode<Context> context = Parameter<Context>(Descriptor::kContext);
// 1. Let O be this value.
TNode<Object> O = Parameter<Object>(Descriptor::kReceiver);
// 2. Perform ? ValidateShadowRealmObject(O).
ThrowIfNotInstanceType(context, O, JS_SHADOW_REALM_TYPE, kMethodName);
// 3. Let specifierString be ? ToString(specifier).
TNode<Object> specifier = Parameter<Object>(Descriptor::kSpecifier);
TNode<String> specifier_string = ToString_Inline(context, specifier);
// 4. Let exportNameString be ? ToString(exportName).
TNode<Object> export_name = Parameter<Object>(Descriptor::kExportName);
TNode<String> export_name_string = ToString_Inline(context, export_name);
// 5. Let callerRealm be the current Realm Record.
TNode<NativeContext> caller_context = LoadNativeContext(context);
// 6. Let evalRealm be O.[[ShadowRealm]].
// 7. Let evalContext be O.[[ExecutionContext]].
TNode<NativeContext> eval_context =
CAST(LoadObjectField(CAST(O), JSShadowRealm::kNativeContextOffset));
// 8. Return ? ShadowRealmImportValue(specifierString, exportNameString,
// callerRealm, evalRealm, evalContext).
TNode<Object> result = ImportValue(caller_context, eval_context,
specifier_string, export_name_string);
Return(result);
}
// https://tc39.es/proposal-shadowrealm/#sec-shadowrealmimportvalue
TNode<Object> ShadowRealmBuiltinsAssembler::ImportValue(
TNode<NativeContext> caller_context, TNode<NativeContext> eval_context,
TNode<String> specifier, TNode<String> export_name) {
// 1. Assert: evalContext is an execution context associated to a ShadowRealm
// instance's [[ExecutionContext]].
// 2. Let innerCapability be ! NewPromiseCapability(%Promise%).
// 3. Let runningContext be the running execution context.
// 4. If runningContext is not already suspended, suspend runningContext.
// 5. Push evalContext onto the execution context stack; evalContext is now
// the running execution context.
// 6. Perform ! HostImportModuleDynamically(null, specifierString,
// innerCapability).
// 7. Suspend evalContext and remove it from the execution context stack.
// 8. Resume the context that is now on the top of the execution context stack
// as the running execution context.
TNode<Object> inner_capability =
CallRuntime(Runtime::kShadowRealmImportValue, eval_context, specifier);
// 9. Let steps be the steps of an ExportGetter function as described below.
// 10. Let onFulfilled be ! CreateBuiltinFunction(steps, 1, "", «
// [[ExportNameString]] », callerRealm).
// 11. Set onFulfilled.[[ExportNameString]] to exportNameString.
TNode<JSFunction> on_fulfilled = AllocateImportValueFulfilledFunction(
caller_context, eval_context, specifier, export_name);
TNode<JSFunction> on_rejected = CAST(LoadContextElement(
caller_context, Context::SHADOW_REALM_IMPORT_VALUE_REJECTED_INDEX));
// 12. Let promiseCapability be ! NewPromiseCapability(%Promise%).
TNode<JSPromise> promise = NewJSPromise(caller_context);
// 13. Return ! PerformPromiseThen(innerCapability.[[Promise]], onFulfilled,
// callerRealm.[[Intrinsics]].[[%ThrowTypeError%]], promiseCapability).
return CallBuiltin(Builtin::kPerformPromiseThen, caller_context,
inner_capability, on_fulfilled, on_rejected, promise);
}
// ExportGetter of
// https://tc39.es/proposal-shadowrealm/#sec-shadowrealmimportvalue
TF_BUILTIN(ShadowRealmImportValueFulfilled, ShadowRealmBuiltinsAssembler) {
// An ExportGetter function is an anonymous built-in function with a
// [[ExportNameString]] internal slot. When an ExportGetter function is called
// with argument exports, it performs the following steps:
// 8. Let realm be f.[[Realm]].
TNode<Context> context = Parameter<Context>(Descriptor::kContext);
TNode<Context> eval_context = CAST(LoadContextElement(
context, ImportValueFulfilledFunctionContextSlot::kEvalContextSlot));
Label get_export_exception(this, Label::kDeferred);
// 2. Let f be the active function object.
// 3. Let string be f.[[ExportNameString]].
// 4. Assert: Type(string) is String.
TNode<String> export_name_string = CAST(LoadContextElement(
context, ImportValueFulfilledFunctionContextSlot::kExportNameSlot));
// 1. Assert: exports is a module namespace exotic object.
TNode<JSModuleNamespace> exports =
Parameter<JSModuleNamespace>(Descriptor::kExports);
// 5. Let hasOwn be ? HasOwnProperty(exports, string).
// 6. If hasOwn is false, throw a TypeError exception.
// 7. Let value be ? Get(exports, string).
// The only exceptions thrown by Runtime::kGetModuleNamespaceExport are
// either the export is not found or the module is not initialized.
TVARIABLE(Object, var_exception);
TNode<Object> value;
{
compiler::ScopedExceptionHandler handler(this, &get_export_exception,
&var_exception);
value = CallRuntime(Runtime::kGetModuleNamespaceExport, eval_context,
exports, export_name_string);
}
// 9. Return ? GetWrappedValue(realm, value).
TNode<NativeContext> caller_context = LoadNativeContext(context);
TNode<Object> wrapped_result =
CallBuiltin(Builtin::kShadowRealmGetWrappedValue, caller_context,
caller_context, eval_context, value);
Return(wrapped_result);
BIND(&get_export_exception);
{
TNode<String> specifier_string = CAST(LoadContextElement(
context, ImportValueFulfilledFunctionContextSlot::kSpecifierSlot));
ThrowTypeError(context, MessageTemplate::kUnresolvableExport,
specifier_string, export_name_string);
}
}
TF_BUILTIN(ShadowRealmImportValueRejected, ShadowRealmBuiltinsAssembler) {
TNode<Context> context = Parameter<Context>(Descriptor::kContext);
// TODO(v8:11989): provide a non-observable inspection on the
// pending_exception to the newly created TypeError.
// https://github.com/tc39/proposal-shadowrealm/issues/353
ThrowTypeError(context, MessageTemplate::kImportShadowRealmRejected);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -6520,6 +6520,10 @@ TNode<BoolT> CodeStubAssembler::IsJSStringIterator(TNode<HeapObject> object) { ...@@ -6520,6 +6520,10 @@ TNode<BoolT> CodeStubAssembler::IsJSStringIterator(TNode<HeapObject> object) {
return HasInstanceType(object, JS_STRING_ITERATOR_TYPE); return HasInstanceType(object, JS_STRING_ITERATOR_TYPE);
} }
TNode<BoolT> CodeStubAssembler::IsJSShadowRealm(TNode<HeapObject> object) {
return HasInstanceType(object, JS_SHADOW_REALM_TYPE);
}
TNode<BoolT> CodeStubAssembler::IsJSRegExpStringIterator( TNode<BoolT> CodeStubAssembler::IsJSRegExpStringIterator(
TNode<HeapObject> object) { TNode<HeapObject> object) {
return HasInstanceType(object, JS_REG_EXP_STRING_ITERATOR_TYPE); return HasInstanceType(object, JS_REG_EXP_STRING_ITERATOR_TYPE);
......
...@@ -111,6 +111,9 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol }; ...@@ -111,6 +111,9 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
V(ProxyRevokeSharedFun, proxy_revoke_shared_fun, ProxyRevokeSharedFun) \ V(ProxyRevokeSharedFun, proxy_revoke_shared_fun, ProxyRevokeSharedFun) \
V(RegExpSpeciesProtector, regexp_species_protector, RegExpSpeciesProtector) \ V(RegExpSpeciesProtector, regexp_species_protector, RegExpSpeciesProtector) \
V(SetIteratorProtector, set_iterator_protector, SetIteratorProtector) \ V(SetIteratorProtector, set_iterator_protector, SetIteratorProtector) \
V(ShadowRealmImportValueFulfilledSFI, \
shadow_realm_import_value_fulfilled_sfi, \
ShadowRealmImportValueFulfilledSFI) \
V(SingleCharacterStringCache, single_character_string_cache, \ V(SingleCharacterStringCache, single_character_string_cache, \
SingleCharacterStringCache) \ SingleCharacterStringCache) \
V(StringIteratorProtector, string_iterator_protector, \ V(StringIteratorProtector, string_iterator_protector, \
...@@ -2582,6 +2585,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -2582,6 +2585,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<BoolT> IsJSPromise(TNode<HeapObject> object); TNode<BoolT> IsJSPromise(TNode<HeapObject> object);
TNode<BoolT> IsJSProxy(TNode<HeapObject> object); TNode<BoolT> IsJSProxy(TNode<HeapObject> object);
TNode<BoolT> IsJSStringIterator(TNode<HeapObject> object); TNode<BoolT> IsJSStringIterator(TNode<HeapObject> object);
TNode<BoolT> IsJSShadowRealm(TNode<HeapObject> object);
TNode<BoolT> IsJSRegExpStringIterator(TNode<HeapObject> object); TNode<BoolT> IsJSRegExpStringIterator(TNode<HeapObject> object);
TNode<BoolT> IsJSReceiverInstanceType(TNode<Int32T> instance_type); TNode<BoolT> IsJSReceiverInstanceType(TNode<Int32T> instance_type);
TNode<BoolT> IsJSReceiverMap(TNode<Map> map); TNode<BoolT> IsJSReceiverMap(TNode<Map> map);
......
...@@ -105,6 +105,7 @@ namespace internal { ...@@ -105,6 +105,7 @@ namespace internal {
T(ImportOutsideModule, "Cannot use import statement outside a module") \ T(ImportOutsideModule, "Cannot use import statement outside a module") \
T(ImportMetaOutsideModule, "Cannot use 'import.meta' outside a module") \ T(ImportMetaOutsideModule, "Cannot use 'import.meta' outside a module") \
T(ImportMissingSpecifier, "import() requires a specifier") \ T(ImportMissingSpecifier, "import() requires a specifier") \
T(ImportShadowRealmRejected, "Cannot import in the ShadowRealm") \
T(IncompatibleMethodReceiver, "Method % called on incompatible receiver %") \ T(IncompatibleMethodReceiver, "Method % called on incompatible receiver %") \
T(InstanceofNonobjectProto, \ T(InstanceofNonobjectProto, \
"Function has non-object prototype '%' in instanceof check") \ "Function has non-object prototype '%' in instanceof check") \
......
...@@ -653,6 +653,100 @@ namespace { ...@@ -653,6 +653,100 @@ namespace {
const int kHostDefinedOptionsLength = 2; const int kHostDefinedOptionsLength = 2;
const uint32_t kHostDefinedOptionsMagicConstant = 0xF1F2F3F0; const uint32_t kHostDefinedOptionsMagicConstant = 0xF1F2F3F0;
std::string ToSTLString(Isolate* isolate, Local<String> v8_str) {
String::Utf8Value utf8(isolate, v8_str);
// Should not be able to fail since the input is a String.
CHECK(*utf8);
return *utf8;
}
// Per-context Module data, allowing sharing of module maps
// across top-level module loads.
class ModuleEmbedderData {
private:
class ModuleGlobalHash {
public:
explicit ModuleGlobalHash(Isolate* isolate) : isolate_(isolate) {}
size_t operator()(const Global<Module>& module) const {
return module.Get(isolate_)->GetIdentityHash();
}
private:
Isolate* isolate_;
};
public:
explicit ModuleEmbedderData(Isolate* isolate)
: module_to_specifier_map(10, ModuleGlobalHash(isolate)),
json_module_to_parsed_json_map(
10, module_to_specifier_map.hash_function()) {}
static ModuleType ModuleTypeFromImportAssertions(
Local<Context> context, Local<FixedArray> 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<String> v8_assertion_key =
import_assertions->Get(context, i).As<v8::String>();
std::string assertion_key = ToSTLString(isolate, v8_assertion_key);
if (assertion_key == "type") {
Local<String> v8_assertion_value =
import_assertions->Get(context, i + 1).As<String>();
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, module type) pair to Module.
std::map<std::pair<std::string, ModuleType>, Global<Module>> module_map;
// Map from Module to its URL as defined in the ScriptOrigin
std::unordered_map<Global<Module>, std::string, ModuleGlobalHash>
module_to_specifier_map;
// Map from JSON Module to its parsed content, for use in module
// JSONModuleEvaluationSteps
std::unordered_map<Global<Module>, Global<Value>, ModuleGlobalHash>
json_module_to_parsed_json_map;
// Origin location used for resolving modules when referrer is null.
std::string origin;
};
enum { kModuleEmbedderDataIndex, kInspectorClientIndex };
std::shared_ptr<ModuleEmbedderData> InitializeModuleEmbedderData(
Local<Context> context) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
const size_t kModuleEmbedderDataEstimate = 4 * 1024; // module map.
i::Handle<i::Managed<ModuleEmbedderData>> module_data_managed =
i::Managed<ModuleEmbedderData>::Allocate(
i_isolate, kModuleEmbedderDataEstimate, context->GetIsolate());
v8::Local<v8::Value> module_data = Utils::ToLocal(module_data_managed);
context->SetEmbedderData(kModuleEmbedderDataIndex, module_data);
return module_data_managed->get();
}
std::shared_ptr<ModuleEmbedderData> GetModuleDataFromContext(
Local<Context> context) {
v8::Local<v8::Value> module_data =
context->GetEmbedderData(kModuleEmbedderDataIndex);
i::Handle<i::Managed<ModuleEmbedderData>> module_data_managed =
i::Handle<i::Managed<ModuleEmbedderData>>::cast(
Utils::OpenHandle<Value, i::Object>(module_data));
return module_data_managed->get();
}
ScriptOrigin CreateScriptOrigin(Isolate* isolate, Local<String> resource_name, ScriptOrigin CreateScriptOrigin(Isolate* isolate, Local<String> resource_name,
v8::ScriptType type) { v8::ScriptType type) {
Local<PrimitiveArray> options = Local<PrimitiveArray> options =
...@@ -741,6 +835,10 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source, ...@@ -741,6 +835,10 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
ScriptOrigin origin = ScriptOrigin origin =
CreateScriptOrigin(isolate, name, ScriptType::kClassic); CreateScriptOrigin(isolate, name, ScriptType::kClassic);
std::shared_ptr<ModuleEmbedderData> module_data =
GetModuleDataFromContext(realm);
module_data->origin = ToSTLString(isolate, name);
for (int i = 1; i < options.repeat_compile; ++i) { for (int i = 1; i < options.repeat_compile; ++i) {
HandleScope handle_scope_for_compiling(isolate); HandleScope handle_scope_for_compiling(isolate);
if (CompileString<Script>(isolate, context, source, origin).IsEmpty()) { if (CompileString<Script>(isolate, context, source, origin).IsEmpty()) {
...@@ -844,13 +942,6 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source, ...@@ -844,13 +942,6 @@ bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
namespace { namespace {
std::string ToSTLString(Isolate* isolate, Local<String> v8_str) {
String::Utf8Value utf8(isolate, v8_str);
// Should not be able to fail since the input is a String.
CHECK(*utf8);
return *utf8;
}
bool IsAbsolutePath(const std::string& path) { bool IsAbsolutePath(const std::string& path) {
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
// This is an incorrect approximation, but should // This is an incorrect approximation, but should
...@@ -919,98 +1010,23 @@ std::string NormalizePath(const std::string& path, ...@@ -919,98 +1010,23 @@ std::string NormalizePath(const std::string& path,
return os.str(); return os.str();
} }
// Per-context Module data, allowing sharing of module maps
// across top-level module loads.
class ModuleEmbedderData {
private:
class ModuleGlobalHash {
public:
explicit ModuleGlobalHash(Isolate* isolate) : isolate_(isolate) {}
size_t operator()(const Global<Module>& module) const {
return module.Get(isolate_)->GetIdentityHash();
}
private:
Isolate* isolate_;
};
public:
explicit ModuleEmbedderData(Isolate* isolate)
: module_to_specifier_map(10, ModuleGlobalHash(isolate)),
json_module_to_parsed_json_map(10, ModuleGlobalHash(isolate)) {}
static ModuleType ModuleTypeFromImportAssertions(
Local<Context> context, Local<FixedArray> 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<String> v8_assertion_key =
import_assertions->Get(context, i).As<v8::String>();
std::string assertion_key = ToSTLString(isolate, v8_assertion_key);
if (assertion_key == "type") {
Local<String> v8_assertion_value =
import_assertions->Get(context, i + 1).As<String>();
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, module type) pair to Module.
std::map<std::pair<std::string, ModuleType>, Global<Module>> module_map;
// Map from Module to its URL as defined in the ScriptOrigin
std::unordered_map<Global<Module>, std::string, ModuleGlobalHash>
module_to_specifier_map;
// Map from JSON Module to its parsed content, for use in module
// JSONModuleEvaluationSteps
std::unordered_map<Global<Module>, Global<Value>, ModuleGlobalHash>
json_module_to_parsed_json_map;
};
enum { kModuleEmbedderDataIndex, kInspectorClientIndex };
void InitializeModuleEmbedderData(Local<Context> context) {
context->SetAlignedPointerInEmbedderData(
kModuleEmbedderDataIndex, new ModuleEmbedderData(context->GetIsolate()));
}
ModuleEmbedderData* GetModuleDataFromContext(Local<Context> context) {
return static_cast<ModuleEmbedderData*>(
context->GetAlignedPointerFromEmbedderData(kModuleEmbedderDataIndex));
}
void DisposeModuleEmbedderData(Local<Context> context) {
delete GetModuleDataFromContext(context);
context->SetAlignedPointerInEmbedderData(kModuleEmbedderDataIndex, nullptr);
}
MaybeLocal<Module> ResolveModuleCallback(Local<Context> context, MaybeLocal<Module> ResolveModuleCallback(Local<Context> context,
Local<String> specifier, Local<String> specifier,
Local<FixedArray> import_assertions, Local<FixedArray> import_assertions,
Local<Module> referrer) { Local<Module> referrer) {
Isolate* isolate = context->GetIsolate(); Isolate* isolate = context->GetIsolate();
ModuleEmbedderData* d = GetModuleDataFromContext(context); std::shared_ptr<ModuleEmbedderData> module_data =
auto specifier_it = GetModuleDataFromContext(context);
d->module_to_specifier_map.find(Global<Module>(isolate, referrer)); auto specifier_it = module_data->module_to_specifier_map.find(
CHECK(specifier_it != d->module_to_specifier_map.end()); Global<Module>(isolate, referrer));
CHECK(specifier_it != module_data->module_to_specifier_map.end());
std::string absolute_path = NormalizePath(ToSTLString(isolate, specifier), std::string absolute_path = NormalizePath(ToSTLString(isolate, specifier),
DirName(specifier_it->second)); DirName(specifier_it->second));
ModuleType module_type = ModuleEmbedderData::ModuleTypeFromImportAssertions( ModuleType module_type = ModuleEmbedderData::ModuleTypeFromImportAssertions(
context, import_assertions, true); context, import_assertions, true);
auto module_it = auto module_it =
d->module_map.find(std::make_pair(absolute_path, module_type)); module_data->module_map.find(std::make_pair(absolute_path, module_type));
CHECK(module_it != d->module_map.end()); CHECK(module_it != module_data->module_map.end());
return module_it->second.Get(isolate); return module_it->second.Get(isolate);
} }
...@@ -1032,13 +1048,14 @@ MaybeLocal<Module> Shell::FetchModuleTree(Local<Module> referrer, ...@@ -1032,13 +1048,14 @@ MaybeLocal<Module> Shell::FetchModuleTree(Local<Module> referrer,
} }
} }
ModuleEmbedderData* d = GetModuleDataFromContext(context); std::shared_ptr<ModuleEmbedderData> module_data =
GetModuleDataFromContext(context);
if (source_text.IsEmpty()) { if (source_text.IsEmpty()) {
std::string msg = "d8: Error reading module from " + file_name; std::string msg = "d8: Error reading module from " + file_name;
if (!referrer.IsEmpty()) { if (!referrer.IsEmpty()) {
auto specifier_it = auto specifier_it = module_data->module_to_specifier_map.find(
d->module_to_specifier_map.find(Global<Module>(isolate, referrer)); Global<Module>(isolate, referrer));
CHECK(specifier_it != d->module_to_specifier_map.end()); CHECK(specifier_it != module_data->module_to_specifier_map.end());
msg += "\n imported by " + specifier_it->second; msg += "\n imported by " + specifier_it->second;
} }
isolate->ThrowError( isolate->ThrowError(
...@@ -1074,7 +1091,7 @@ MaybeLocal<Module> Shell::FetchModuleTree(Local<Module> referrer, ...@@ -1074,7 +1091,7 @@ MaybeLocal<Module> Shell::FetchModuleTree(Local<Module> referrer,
String::NewFromUtf8(isolate, file_name.c_str()).ToLocalChecked(), String::NewFromUtf8(isolate, file_name.c_str()).ToLocalChecked(),
export_names, Shell::JSONModuleEvaluationSteps); export_names, Shell::JSONModuleEvaluationSteps);
CHECK(d->json_module_to_parsed_json_map CHECK(module_data->json_module_to_parsed_json_map
.insert(std::make_pair(Global<Module>(isolate, module), .insert(std::make_pair(Global<Module>(isolate, module),
Global<Value>(isolate, parsed_json))) Global<Value>(isolate, parsed_json)))
.second); .second);
...@@ -1082,11 +1099,11 @@ MaybeLocal<Module> Shell::FetchModuleTree(Local<Module> referrer, ...@@ -1082,11 +1099,11 @@ MaybeLocal<Module> Shell::FetchModuleTree(Local<Module> referrer,
UNREACHABLE(); UNREACHABLE();
} }
CHECK(d->module_map CHECK(module_data->module_map
.insert(std::make_pair(std::make_pair(file_name, module_type), .insert(std::make_pair(std::make_pair(file_name, module_type),
Global<Module>(isolate, module))) Global<Module>(isolate, module)))
.second); .second);
CHECK(d->module_to_specifier_map CHECK(module_data->module_to_specifier_map
.insert(std::make_pair(Global<Module>(isolate, module), file_name)) .insert(std::make_pair(Global<Module>(isolate, module), file_name))
.second); .second);
...@@ -1109,7 +1126,7 @@ MaybeLocal<Module> Shell::FetchModuleTree(Local<Module> referrer, ...@@ -1109,7 +1126,7 @@ MaybeLocal<Module> Shell::FetchModuleTree(Local<Module> referrer,
return MaybeLocal<Module>(); return MaybeLocal<Module>();
} }
if (d->module_map.count( if (module_data->module_map.count(
std::make_pair(absolute_path, request_module_type))) { std::make_pair(absolute_path, request_module_type))) {
continue; continue;
} }
...@@ -1127,10 +1144,11 @@ MaybeLocal<Value> Shell::JSONModuleEvaluationSteps(Local<Context> context, ...@@ -1127,10 +1144,11 @@ MaybeLocal<Value> Shell::JSONModuleEvaluationSteps(Local<Context> context,
Local<Module> module) { Local<Module> module) {
Isolate* isolate = context->GetIsolate(); Isolate* isolate = context->GetIsolate();
ModuleEmbedderData* d = GetModuleDataFromContext(context); std::shared_ptr<ModuleEmbedderData> module_data =
auto json_value_it = GetModuleDataFromContext(context);
d->json_module_to_parsed_json_map.find(Global<Module>(isolate, module)); auto json_value_it = module_data->json_module_to_parsed_json_map.find(
CHECK(json_value_it != d->json_module_to_parsed_json_map.end()); Global<Module>(isolate, module));
CHECK(json_value_it != module_data->json_module_to_parsed_json_map.end());
Local<Value> json_value = json_value_it->second.Get(isolate); Local<Value> json_value = json_value_it->second.Get(isolate);
TryCatch try_catch(isolate); TryCatch try_catch(isolate);
...@@ -1151,11 +1169,12 @@ MaybeLocal<Value> Shell::JSONModuleEvaluationSteps(Local<Context> context, ...@@ -1151,11 +1169,12 @@ MaybeLocal<Value> Shell::JSONModuleEvaluationSteps(Local<Context> context,
} }
struct DynamicImportData { struct DynamicImportData {
DynamicImportData(Isolate* isolate_, Local<String> referrer_, DynamicImportData(Isolate* isolate_, Local<Context> context_,
Local<String> specifier_, Local<Value> referrer_, Local<String> specifier_,
Local<FixedArray> import_assertions_, Local<FixedArray> import_assertions_,
Local<Promise::Resolver> resolver_) Local<Promise::Resolver> resolver_)
: isolate(isolate_) { : isolate(isolate_) {
context.Reset(isolate, context_);
referrer.Reset(isolate, referrer_); referrer.Reset(isolate, referrer_);
specifier.Reset(isolate, specifier_); specifier.Reset(isolate, specifier_);
import_assertions.Reset(isolate, import_assertions_); import_assertions.Reset(isolate, import_assertions_);
...@@ -1163,7 +1182,10 @@ struct DynamicImportData { ...@@ -1163,7 +1182,10 @@ struct DynamicImportData {
} }
Isolate* isolate; Isolate* isolate;
Global<String> referrer; // The initiating context. It can be the Realm created by d8, or the context
// created by ShadowRealm built-in.
Global<Context> context;
Global<Value> referrer;
Global<String> specifier; Global<String> specifier;
Global<FixedArray> import_assertions; Global<FixedArray> import_assertions;
Global<Promise::Resolver> resolver; Global<Promise::Resolver> resolver;
...@@ -1235,7 +1257,8 @@ MaybeLocal<Promise> Shell::HostImportModuleDynamically( ...@@ -1235,7 +1257,8 @@ MaybeLocal<Promise> Shell::HostImportModuleDynamically(
Local<Promise::Resolver> resolver; Local<Promise::Resolver> resolver;
if (!maybe_resolver.ToLocal(&resolver)) return MaybeLocal<Promise>(); if (!maybe_resolver.ToLocal(&resolver)) return MaybeLocal<Promise>();
if (!IsValidHostDefinedOptions(context, host_defined_options, if (!resource_name->IsNull() &&
!IsValidHostDefinedOptions(context, host_defined_options,
resource_name)) { resource_name)) {
resolver resolver
->Reject(context, v8::Exception::TypeError(String::NewFromUtf8Literal( ->Reject(context, v8::Exception::TypeError(String::NewFromUtf8Literal(
...@@ -1243,7 +1266,7 @@ MaybeLocal<Promise> Shell::HostImportModuleDynamically( ...@@ -1243,7 +1266,7 @@ MaybeLocal<Promise> Shell::HostImportModuleDynamically(
.ToChecked(); .ToChecked();
} else { } else {
DynamicImportData* data = DynamicImportData* data =
new DynamicImportData(isolate, resource_name.As<String>(), specifier, new DynamicImportData(isolate, context, resource_name, specifier,
import_assertions, resolver); import_assertions, resolver);
PerIsolateData::Get(isolate)->AddDynamicImportData(data); PerIsolateData::Get(isolate)->AddDynamicImportData(data);
isolate->EnqueueMicrotask(Shell::DoHostImportModuleDynamically, data); isolate->EnqueueMicrotask(Shell::DoHostImportModuleDynamically, data);
...@@ -1257,10 +1280,11 @@ void Shell::HostInitializeImportMetaObject(Local<Context> context, ...@@ -1257,10 +1280,11 @@ void Shell::HostInitializeImportMetaObject(Local<Context> context,
Isolate* isolate = context->GetIsolate(); Isolate* isolate = context->GetIsolate();
HandleScope handle_scope(isolate); HandleScope handle_scope(isolate);
ModuleEmbedderData* d = GetModuleDataFromContext(context); std::shared_ptr<ModuleEmbedderData> module_data =
auto specifier_it = GetModuleDataFromContext(context);
d->module_to_specifier_map.find(Global<Module>(isolate, module)); auto specifier_it = module_data->module_to_specifier_map.find(
CHECK(specifier_it != d->module_to_specifier_map.end()); Global<Module>(isolate, module));
CHECK(specifier_it != module_data->module_to_specifier_map.end());
Local<String> url_key = Local<String> url_key =
String::NewFromUtf8Literal(isolate, "url", NewStringType::kInternalized); String::NewFromUtf8Literal(isolate, "url", NewStringType::kInternalized);
...@@ -1271,7 +1295,14 @@ void Shell::HostInitializeImportMetaObject(Local<Context> context, ...@@ -1271,7 +1295,14 @@ void Shell::HostInitializeImportMetaObject(Local<Context> context,
MaybeLocal<Context> Shell::HostCreateShadowRealmContext( MaybeLocal<Context> Shell::HostCreateShadowRealmContext(
Local<Context> initiator_context) { Local<Context> initiator_context) {
return v8::Context::New(initiator_context->GetIsolate()); Local<Context> context = v8::Context::New(initiator_context->GetIsolate());
std::shared_ptr<ModuleEmbedderData> shadow_realm_data =
InitializeModuleEmbedderData(context);
std::shared_ptr<ModuleEmbedderData> initiator_data =
GetModuleDataFromContext(initiator_context);
shadow_realm_data->origin = initiator_data->origin;
return context;
} }
void Shell::DoHostImportModuleDynamically(void* import_data) { void Shell::DoHostImportModuleDynamically(void* import_data) {
...@@ -1281,16 +1312,16 @@ void Shell::DoHostImportModuleDynamically(void* import_data) { ...@@ -1281,16 +1312,16 @@ void Shell::DoHostImportModuleDynamically(void* import_data) {
Isolate* isolate(import_data_->isolate); Isolate* isolate(import_data_->isolate);
HandleScope handle_scope(isolate); HandleScope handle_scope(isolate);
Local<String> referrer(import_data_->referrer.Get(isolate)); Local<Context> realm = import_data_->context.Get(isolate);
Local<Value> referrer(import_data_->referrer.Get(isolate));
Local<String> specifier(import_data_->specifier.Get(isolate)); Local<String> specifier(import_data_->specifier.Get(isolate));
Local<FixedArray> import_assertions( Local<FixedArray> import_assertions(
import_data_->import_assertions.Get(isolate)); import_data_->import_assertions.Get(isolate));
Local<Promise::Resolver> resolver(import_data_->resolver.Get(isolate)); Local<Promise::Resolver> resolver(import_data_->resolver.Get(isolate));
PerIsolateData* data = PerIsolateData::Get(isolate); PerIsolateData* data = PerIsolateData::Get(isolate);
PerIsolateData::Get(isolate)->DeleteDynamicImportData(import_data_); data->DeleteDynamicImportData(import_data_);
Local<Context> realm = data->realms_[data->realm_current_].Get(isolate);
Context::Scope context_scope(realm); Context::Scope context_scope(realm);
ModuleType module_type = ModuleEmbedderData::ModuleTypeFromImportAssertions( ModuleType module_type = ModuleEmbedderData::ModuleTypeFromImportAssertions(
...@@ -1306,17 +1337,21 @@ void Shell::DoHostImportModuleDynamically(void* import_data) { ...@@ -1306,17 +1337,21 @@ void Shell::DoHostImportModuleDynamically(void* import_data) {
return; return;
} }
std::string source_url = ToSTLString(isolate, referrer); std::shared_ptr<ModuleEmbedderData> module_data =
GetModuleDataFromContext(realm);
std::string source_url = referrer->IsNull()
? module_data->origin
: ToSTLString(isolate, referrer.As<String>());
std::string dir_name = std::string dir_name =
DirName(NormalizePath(source_url, GetWorkingDirectory())); DirName(NormalizePath(source_url, GetWorkingDirectory()));
std::string file_name = ToSTLString(isolate, specifier); std::string file_name = ToSTLString(isolate, specifier);
std::string absolute_path = NormalizePath(file_name, dir_name); std::string absolute_path = NormalizePath(file_name, dir_name);
ModuleEmbedderData* d = GetModuleDataFromContext(realm);
Local<Module> root_module; Local<Module> root_module;
auto module_it = auto module_it =
d->module_map.find(std::make_pair(absolute_path, module_type)); module_data->module_map.find(std::make_pair(absolute_path, module_type));
if (module_it != d->module_map.end()) { if (module_it != module_data->module_map.end()) {
root_module = module_it->second.Get(isolate); root_module = module_it->second.Get(isolate);
} else if (!FetchModuleTree(Local<Module>(), realm, absolute_path, } else if (!FetchModuleTree(Local<Module>(), realm, absolute_path,
module_type) module_type)
...@@ -1374,11 +1409,12 @@ bool Shell::ExecuteModule(Isolate* isolate, const char* file_name) { ...@@ -1374,11 +1409,12 @@ bool Shell::ExecuteModule(Isolate* isolate, const char* file_name) {
// isolate->ReportPendingMessages(). // isolate->ReportPendingMessages().
TryCatch try_catch(isolate); TryCatch try_catch(isolate);
ModuleEmbedderData* d = GetModuleDataFromContext(realm); std::shared_ptr<ModuleEmbedderData> module_data =
GetModuleDataFromContext(realm);
Local<Module> root_module; Local<Module> root_module;
auto module_it = d->module_map.find( auto module_it = module_data->module_map.find(
std::make_pair(absolute_path, ModuleType::kJavaScript)); std::make_pair(absolute_path, ModuleType::kJavaScript));
if (module_it != d->module_map.end()) { if (module_it != module_data->module_map.end()) {
root_module = module_it->second.Get(isolate); root_module = module_it->second.Get(isolate);
} else if (!FetchModuleTree(Local<Module>(), realm, absolute_path, } else if (!FetchModuleTree(Local<Module>(), realm, absolute_path,
ModuleType::kJavaScript) ModuleType::kJavaScript)
...@@ -1388,6 +1424,8 @@ bool Shell::ExecuteModule(Isolate* isolate, const char* file_name) { ...@@ -1388,6 +1424,8 @@ bool Shell::ExecuteModule(Isolate* isolate, const char* file_name) {
return false; return false;
} }
module_data->origin = absolute_path;
MaybeLocal<Value> maybe_result; MaybeLocal<Value> maybe_result;
if (root_module->InstantiateModule(realm, ResolveModuleCallback) if (root_module->InstantiateModule(realm, ResolveModuleCallback)
.FromMaybe(false)) { .FromMaybe(false)) {
...@@ -1616,14 +1654,7 @@ PerIsolateData::RealmScope::RealmScope(PerIsolateData* data) : data_(data) { ...@@ -1616,14 +1654,7 @@ PerIsolateData::RealmScope::RealmScope(PerIsolateData* data) : data_(data) {
} }
PerIsolateData::RealmScope::~RealmScope() { PerIsolateData::RealmScope::~RealmScope() {
// Drop realms to avoid keeping them alive. We don't dispose the // Drop realms to avoid keeping them alive.
// module embedder data for the first realm here, but instead do
// it in RunShell or in RunMain, if not running in interactive mode
for (int i = 1; i < data_->realm_count_; ++i) {
Global<Context>& realm = data_->realms_[i];
if (realm.IsEmpty()) continue;
DisposeModuleEmbedderData(realm.Get(data_->isolate_));
}
data_->realm_count_ = 0; data_->realm_count_ = 0;
delete[] data_->realms_; delete[] data_->realms_;
} }
...@@ -1805,7 +1836,6 @@ void Shell::DisposeRealm(const v8::FunctionCallbackInfo<v8::Value>& args, ...@@ -1805,7 +1836,6 @@ void Shell::DisposeRealm(const v8::FunctionCallbackInfo<v8::Value>& args,
Isolate* isolate = args.GetIsolate(); Isolate* isolate = args.GetIsolate();
PerIsolateData* data = PerIsolateData::Get(isolate); PerIsolateData* data = PerIsolateData::Get(isolate);
Local<Context> context = data->realms_[index].Get(isolate); Local<Context> context = data->realms_[index].Get(isolate);
DisposeModuleEmbedderData(context);
data->realms_[index].Reset(); data->realms_[index].Reset();
// ContextDisposedNotification expects the disposed context to be entered. // ContextDisposedNotification expects the disposed context to be entered.
v8::Context::Scope scope(context); v8::Context::Scope scope(context);
...@@ -3715,9 +3745,6 @@ void Shell::RunShell(Isolate* isolate) { ...@@ -3715,9 +3745,6 @@ void Shell::RunShell(Isolate* isolate) {
kProcessMessageQueue); kProcessMessageQueue);
} }
printf("\n"); printf("\n");
// We need to explicitly clean up the module embedder data for
// the interative shell context.
DisposeModuleEmbedderData(context);
} }
class InspectorFrontend final : public v8_inspector::V8Inspector::Channel { class InspectorFrontend final : public v8_inspector::V8Inspector::Channel {
...@@ -4031,7 +4058,6 @@ void SourceGroup::ExecuteInThread() { ...@@ -4031,7 +4058,6 @@ void SourceGroup::ExecuteInThread() {
Execute(isolate); Execute(isolate);
Shell::CompleteMessageLoop(isolate); Shell::CompleteMessageLoop(isolate);
} }
DisposeModuleEmbedderData(context);
} }
Shell::CollectGarbage(isolate); Shell::CollectGarbage(isolate);
} }
...@@ -4306,7 +4332,6 @@ void Worker::ExecuteInThread() { ...@@ -4306,7 +4332,6 @@ void Worker::ExecuteInThread() {
} }
} }
} }
DisposeModuleEmbedderData(context);
} }
Shell::CollectGarbage(isolate_); Shell::CollectGarbage(isolate_);
} }
...@@ -4707,9 +4732,6 @@ int Shell::RunMain(Isolate* isolate, bool last_run) { ...@@ -4707,9 +4732,6 @@ int Shell::RunMain(Isolate* isolate, bool last_run) {
if (!options.isolate_sources[0].Execute(isolate)) success = false; if (!options.isolate_sources[0].Execute(isolate)) success = false;
if (!CompleteMessageLoop(isolate)) success = false; if (!CompleteMessageLoop(isolate)) success = false;
} }
if (!use_existing_context) {
DisposeModuleEmbedderData(context);
}
WriteLcovData(isolate, options.lcov_file); WriteLcovData(isolate, options.lcov_file);
if (last_run && i::FLAG_stress_snapshot) { if (last_run && i::FLAG_stress_snapshot) {
static constexpr bool kClearRecompilableData = true; static constexpr bool kClearRecompilableData = true;
......
...@@ -4655,7 +4655,7 @@ MaybeHandle<JSPromise> NewRejectedPromise(Isolate* isolate, ...@@ -4655,7 +4655,7 @@ MaybeHandle<JSPromise> NewRejectedPromise(Isolate* isolate,
} // namespace } // namespace
MaybeHandle<JSPromise> Isolate::RunHostImportModuleDynamicallyCallback( MaybeHandle<JSPromise> Isolate::RunHostImportModuleDynamicallyCallback(
Handle<Script> referrer, Handle<Object> specifier, MaybeHandle<Script> maybe_referrer, Handle<Object> specifier,
MaybeHandle<Object> maybe_import_assertions_argument) { MaybeHandle<Object> maybe_import_assertions_argument) {
v8::Local<v8::Context> api_context = v8::Local<v8::Context> api_context =
v8::Utils::ToLocal(Handle<Context>::cast(native_context())); v8::Utils::ToLocal(Handle<Context>::cast(native_context()));
...@@ -4684,13 +4684,23 @@ MaybeHandle<JSPromise> Isolate::RunHostImportModuleDynamicallyCallback( ...@@ -4684,13 +4684,23 @@ MaybeHandle<JSPromise> Isolate::RunHostImportModuleDynamicallyCallback(
clear_pending_exception(); clear_pending_exception();
return NewRejectedPromise(this, api_context, exception); return NewRejectedPromise(this, api_context, exception);
} }
Handle<FixedArray> host_defined_options;
Handle<Object> resource_name;
if (maybe_referrer.is_null()) {
host_defined_options = factory()->empty_fixed_array();
resource_name = factory()->null_value();
} else {
Handle<Script> referrer = maybe_referrer.ToHandleChecked();
host_defined_options = handle(referrer->host_defined_options(), this);
resource_name = handle(referrer->name(), this);
}
if (host_import_module_dynamically_callback_) { if (host_import_module_dynamically_callback_) {
ASSIGN_RETURN_ON_SCHEDULED_EXCEPTION_VALUE( ASSIGN_RETURN_ON_SCHEDULED_EXCEPTION_VALUE(
this, promise, this, promise,
host_import_module_dynamically_callback_( host_import_module_dynamically_callback_(
api_context, api_context, v8::Utils::ToLocal(host_defined_options),
v8::Utils::ToLocal(handle(referrer->host_defined_options(), this)), v8::Utils::ToLocal(resource_name),
v8::Utils::ToLocal(handle(referrer->name(), this)),
v8::Utils::ToLocal(specifier_str), v8::Utils::ToLocal(specifier_str),
ToApiHandle<v8::FixedArray>(import_assertions_array)), ToApiHandle<v8::FixedArray>(import_assertions_array)),
MaybeHandle<JSPromise>()); MaybeHandle<JSPromise>());
...@@ -4698,9 +4708,8 @@ MaybeHandle<JSPromise> Isolate::RunHostImportModuleDynamicallyCallback( ...@@ -4698,9 +4708,8 @@ MaybeHandle<JSPromise> Isolate::RunHostImportModuleDynamicallyCallback(
// TODO(cbruni, v8:12302): Avoid creating tempory ScriptOrModule objects. // TODO(cbruni, v8:12302): Avoid creating tempory ScriptOrModule objects.
auto script_or_module = i::Handle<i::ScriptOrModule>::cast( auto script_or_module = i::Handle<i::ScriptOrModule>::cast(
this->factory()->NewStruct(i::SCRIPT_OR_MODULE_TYPE)); this->factory()->NewStruct(i::SCRIPT_OR_MODULE_TYPE));
script_or_module->set_resource_name(referrer->name()); script_or_module->set_resource_name(*resource_name);
script_or_module->set_host_defined_options( script_or_module->set_host_defined_options(*host_defined_options);
referrer->host_defined_options());
ASSIGN_RETURN_ON_SCHEDULED_EXCEPTION_VALUE( ASSIGN_RETURN_ON_SCHEDULED_EXCEPTION_VALUE(
this, promise, this, promise,
host_import_module_dynamically_with_import_assertions_callback_( host_import_module_dynamically_with_import_assertions_callback_(
......
...@@ -1762,7 +1762,7 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory { ...@@ -1762,7 +1762,7 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
void SetHostImportModuleDynamicallyCallback( void SetHostImportModuleDynamicallyCallback(
HostImportModuleDynamicallyCallback callback); HostImportModuleDynamicallyCallback callback);
MaybeHandle<JSPromise> RunHostImportModuleDynamicallyCallback( MaybeHandle<JSPromise> RunHostImportModuleDynamicallyCallback(
Handle<Script> referrer, Handle<Object> specifier, MaybeHandle<Script> maybe_referrer, Handle<Object> specifier,
MaybeHandle<Object> maybe_import_assertions_argument); MaybeHandle<Object> maybe_import_assertions_argument);
void SetHostInitializeImportMetaObjectCallback( void SetHostInitializeImportMetaObjectCallback(
......
...@@ -1067,6 +1067,13 @@ void Heap::CreateInitialObjects() { ...@@ -1067,6 +1067,13 @@ void Heap::CreateInitialObjects() {
CreateSharedFunctionInfo(isolate_, Builtin::kProxyRevoke, 0); CreateSharedFunctionInfo(isolate_, Builtin::kProxyRevoke, 0);
set_proxy_revoke_shared_fun(*info); set_proxy_revoke_shared_fun(*info);
} }
// ShadowRealm:
{
Handle<SharedFunctionInfo> info = CreateSharedFunctionInfo(
isolate_, Builtin::kShadowRealmImportValueFulfilled, 0);
set_shadow_realm_import_value_fulfilled_sfi(*info);
}
} }
void Heap::CreateInternalAccessorInfoObjects() { void Heap::CreateInternalAccessorInfoObjects() {
......
...@@ -4554,6 +4554,17 @@ void Genesis::InitializeGlobal_harmony_shadow_realm() { ...@@ -4554,6 +4554,17 @@ void Genesis::InitializeGlobal_harmony_shadow_realm() {
native_context()->set_wrapped_function_map(*map); native_context()->set_wrapped_function_map(*map);
} }
// Internal steps of ShadowRealmImportValue
{
Handle<JSFunction> shadow_realm_import_value_rejected =
SimpleCreateFunction(isolate(), factory->empty_string(),
Builtin::kShadowRealmImportValueRejected, 1,
false);
shadow_realm_import_value_rejected->shared().set_native(false);
native_context()->set_shadow_realm_import_value_rejected(
*shadow_realm_import_value_rejected);
}
} }
void Genesis::InitializeGlobal_harmony_struct() { void Genesis::InitializeGlobal_harmony_struct() {
......
...@@ -353,6 +353,8 @@ enum ContextLookupFlags { ...@@ -353,6 +353,8 @@ enum ContextLookupFlags {
V(SET_ADD_INDEX, JSFunction, set_add) \ V(SET_ADD_INDEX, JSFunction, set_add) \
V(SET_DELETE_INDEX, JSFunction, set_delete) \ V(SET_DELETE_INDEX, JSFunction, set_delete) \
V(SET_HAS_INDEX, JSFunction, set_has) \ V(SET_HAS_INDEX, JSFunction, set_has) \
V(SHADOW_REALM_IMPORT_VALUE_REJECTED_INDEX, JSFunction, \
shadow_realm_import_value_rejected) \
V(SYNTAX_ERROR_FUNCTION_INDEX, JSFunction, syntax_error_function) \ V(SYNTAX_ERROR_FUNCTION_INDEX, JSFunction, syntax_error_function) \
V(TYPE_ERROR_FUNCTION_INDEX, JSFunction, type_error_function) \ V(TYPE_ERROR_FUNCTION_INDEX, JSFunction, type_error_function) \
V(URI_ERROR_FUNCTION_INDEX, JSFunction, uri_error_function) \ V(URI_ERROR_FUNCTION_INDEX, JSFunction, uri_error_function) \
......
...@@ -367,6 +367,11 @@ Handle<JSModuleNamespace> Module::GetModuleNamespace(Isolate* isolate, ...@@ -367,6 +367,11 @@ Handle<JSModuleNamespace> Module::GetModuleNamespace(Isolate* isolate,
return ns; return ns;
} }
bool JSModuleNamespace::HasExport(Isolate* isolate, Handle<String> name) {
Handle<Object> object(module().exports().Lookup(name), isolate);
return !object->IsTheHole(isolate);
}
MaybeHandle<Object> JSModuleNamespace::GetExport(Isolate* isolate, MaybeHandle<Object> JSModuleNamespace::GetExport(Isolate* isolate,
Handle<String> name) { Handle<String> name) {
Handle<Object> object(module().exports().Lookup(name), isolate); Handle<Object> object(module().exports().Lookup(name), isolate);
......
...@@ -147,6 +147,8 @@ class JSModuleNamespace ...@@ -147,6 +147,8 @@ class JSModuleNamespace
V8_WARN_UNUSED_RESULT MaybeHandle<Object> GetExport(Isolate* isolate, V8_WARN_UNUSED_RESULT MaybeHandle<Object> GetExport(Isolate* isolate,
Handle<String> name); Handle<String> name);
bool HasExport(Isolate* isolate, Handle<String> name);
// Return the (constant) property attributes for the referenced property, // Return the (constant) property attributes for the referenced property,
// which is assumed to correspond to an export. If the export is // which is assumed to correspond to an export. If the export is
// uninitialized, schedule an exception and return Nothing. // uninitialized, schedule an exception and return Nothing.
......
...@@ -292,7 +292,9 @@ class Symbol; ...@@ -292,7 +292,9 @@ class Symbol;
PromiseThrowerFinallySharedFun) \ PromiseThrowerFinallySharedFun) \
V(SharedFunctionInfo, promise_value_thunk_finally_shared_fun, \ V(SharedFunctionInfo, promise_value_thunk_finally_shared_fun, \
PromiseValueThunkFinallySharedFun) \ PromiseValueThunkFinallySharedFun) \
V(SharedFunctionInfo, proxy_revoke_shared_fun, ProxyRevokeSharedFun) V(SharedFunctionInfo, proxy_revoke_shared_fun, ProxyRevokeSharedFun) \
V(SharedFunctionInfo, shadow_realm_import_value_fulfilled_sfi, \
ShadowRealmImportValueFulfilledSFI)
// These root references can be updated by the mutator. // These root references can be updated by the mutator.
#define STRONG_MUTABLE_MOVABLE_ROOT_LIST(V) \ #define STRONG_MUTABLE_MOVABLE_ROOT_LIST(V) \
......
...@@ -59,5 +59,17 @@ RUNTIME_FUNCTION(Runtime_GetImportMetaObject) { ...@@ -59,5 +59,17 @@ RUNTIME_FUNCTION(Runtime_GetImportMetaObject) {
SourceTextModule::GetImportMeta(isolate, module)); SourceTextModule::GetImportMeta(isolate, module));
} }
RUNTIME_FUNCTION(Runtime_GetModuleNamespaceExport) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
Handle<JSModuleNamespace> module_namespace = args.at<JSModuleNamespace>(0);
Handle<String> name = args.at<String>(1);
if (!module_namespace->HasExport(isolate, name)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
}
RETURN_RESULT_OR_FAILURE(isolate, module_namespace->GetExport(isolate, name));
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -18,5 +18,27 @@ RUNTIME_FUNCTION(Runtime_ShadowRealmWrappedFunctionCreate) { ...@@ -18,5 +18,27 @@ RUNTIME_FUNCTION(Runtime_ShadowRealmWrappedFunctionCreate) {
isolate, JSWrappedFunction::Create(isolate, native_context, value)); isolate, JSWrappedFunction::Create(isolate, native_context, value));
} }
// https://tc39.es/proposal-shadowrealm/#sec-shadowrealm.prototype.importvalue
RUNTIME_FUNCTION(Runtime_ShadowRealmImportValue) {
DCHECK_EQ(1, args.length());
HandleScope scope(isolate);
Handle<String> specifier = args.at<String>(0);
Handle<JSPromise> inner_capability;
MaybeHandle<Object> import_assertions;
MaybeHandle<Script> referrer;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, inner_capability,
isolate->RunHostImportModuleDynamicallyCallback(referrer, specifier,
import_assertions));
// Check that the promise is created in the eval_context.
DCHECK(
inner_capability->GetCreationContext().ToHandleChecked().is_identical_to(
isolate->native_context()));
return *inner_capability;
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -277,7 +277,8 @@ namespace internal { ...@@ -277,7 +277,8 @@ namespace internal {
#define FOR_EACH_INTRINSIC_MODULE(F, I) \ #define FOR_EACH_INTRINSIC_MODULE(F, I) \
F(DynamicImportCall, -1 /* [2, 3] */, 1) \ F(DynamicImportCall, -1 /* [2, 3] */, 1) \
I(GetImportMetaObject, 0, 1) \ I(GetImportMetaObject, 0, 1) \
F(GetModuleNamespace, 1, 1) F(GetModuleNamespace, 1, 1) \
F(GetModuleNamespaceExport, 2, 1)
#define FOR_EACH_INTRINSIC_NUMBERS(F, I) \ #define FOR_EACH_INTRINSIC_NUMBERS(F, I) \
F(ArrayBufferMaxByteLength, 0, 1) \ F(ArrayBufferMaxByteLength, 0, 1) \
...@@ -440,7 +441,8 @@ namespace internal { ...@@ -440,7 +441,8 @@ namespace internal {
F(ThrowConstAssignError, 0, 1) F(ThrowConstAssignError, 0, 1)
#define FOR_EACH_INTRINSIC_SHADOW_REALM(F, I) \ #define FOR_EACH_INTRINSIC_SHADOW_REALM(F, I) \
F(ShadowRealmWrappedFunctionCreate, 2, 1) F(ShadowRealmWrappedFunctionCreate, 2, 1) \
F(ShadowRealmImportValue, 1, 1)
#define FOR_EACH_INTRINSIC_STRINGS(F, I) \ #define FOR_EACH_INTRINSIC_STRINGS(F, I) \
F(FlattenString, 1, 1) \ F(FlattenString, 1, 1) \
......
...@@ -83,7 +83,7 @@ bytecodes: [ ...@@ -83,7 +83,7 @@ bytecodes: [
/* 48 E> */ B(DefineKeyedOwnProperty), R(this), R(0), U8(0), /* 48 E> */ B(DefineKeyedOwnProperty), R(this), R(0), U8(0),
/* 53 S> */ B(LdaImmutableCurrentContextSlot), U8(3), /* 53 S> */ B(LdaImmutableCurrentContextSlot), U8(3),
/* 58 E> */ B(GetKeyedProperty), R(this), U8(2), /* 58 E> */ B(GetKeyedProperty), R(this), U8(2),
B(Wide), B(LdaSmi), I16(297), B(Wide), B(LdaSmi), I16(298),
B(Star2), B(Star2),
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star3), B(Star3),
...@@ -115,7 +115,7 @@ bytecodes: [ ...@@ -115,7 +115,7 @@ bytecodes: [
/* 41 E> */ B(DefineKeyedOwnProperty), R(this), R(0), U8(0), /* 41 E> */ B(DefineKeyedOwnProperty), R(this), R(0), U8(0),
/* 46 S> */ B(LdaImmutableCurrentContextSlot), U8(3), /* 46 S> */ B(LdaImmutableCurrentContextSlot), U8(3),
/* 51 E> */ B(GetKeyedProperty), R(this), U8(2), /* 51 E> */ B(GetKeyedProperty), R(this), U8(2),
B(Wide), B(LdaSmi), I16(296), B(Wide), B(LdaSmi), I16(297),
B(Star2), B(Star2),
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star3), B(Star3),
...@@ -149,7 +149,7 @@ bytecodes: [ ...@@ -149,7 +149,7 @@ bytecodes: [
B(Star2), B(Star2),
B(LdaImmutableCurrentContextSlot), U8(3), B(LdaImmutableCurrentContextSlot), U8(3),
/* 58 E> */ B(GetKeyedProperty), R(this), U8(2), /* 58 E> */ B(GetKeyedProperty), R(this), U8(2),
B(Wide), B(LdaSmi), I16(297), B(Wide), B(LdaSmi), I16(298),
B(Star3), B(Star3),
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star4), B(Star4),
...@@ -181,7 +181,7 @@ bytecodes: [ ...@@ -181,7 +181,7 @@ bytecodes: [
/* 41 E> */ B(DefineKeyedOwnProperty), R(this), R(0), U8(0), /* 41 E> */ B(DefineKeyedOwnProperty), R(this), R(0), U8(0),
/* 46 S> */ B(LdaImmutableCurrentContextSlot), U8(3), /* 46 S> */ B(LdaImmutableCurrentContextSlot), U8(3),
/* 51 E> */ B(GetKeyedProperty), R(this), U8(2), /* 51 E> */ B(GetKeyedProperty), R(this), U8(2),
B(Wide), B(LdaSmi), I16(296), B(Wide), B(LdaSmi), I16(297),
B(Star2), B(Star2),
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star3), B(Star3),
......
...@@ -58,7 +58,7 @@ bytecodes: [ ...@@ -58,7 +58,7 @@ bytecodes: [
B(Star2), B(Star2),
B(LdaImmutableCurrentContextSlot), U8(3), B(LdaImmutableCurrentContextSlot), U8(3),
/* 54 E> */ B(GetKeyedProperty), R(this), U8(2), /* 54 E> */ B(GetKeyedProperty), R(this), U8(2),
B(Wide), B(LdaSmi), I16(295), B(Wide), B(LdaSmi), I16(296),
B(Star3), B(Star3),
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star4), B(Star4),
...@@ -91,7 +91,7 @@ bytecodes: [ ...@@ -91,7 +91,7 @@ bytecodes: [
/* 44 E> */ B(DefineKeyedOwnProperty), R(this), R(0), U8(0), /* 44 E> */ B(DefineKeyedOwnProperty), R(this), R(0), U8(0),
/* 49 S> */ B(LdaImmutableCurrentContextSlot), U8(3), /* 49 S> */ B(LdaImmutableCurrentContextSlot), U8(3),
/* 54 E> */ B(GetKeyedProperty), R(this), U8(2), /* 54 E> */ B(GetKeyedProperty), R(this), U8(2),
B(Wide), B(LdaSmi), I16(295), B(Wide), B(LdaSmi), I16(296),
B(Star2), B(Star2),
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star3), B(Star3),
......
...@@ -24,7 +24,7 @@ bytecodes: [ ...@@ -24,7 +24,7 @@ bytecodes: [
B(TestReferenceEqual), R(this), B(TestReferenceEqual), R(this),
B(Mov), R(this), R(1), B(Mov), R(this), R(1),
B(JumpIfTrue), U8(16), B(JumpIfTrue), U8(16),
B(Wide), B(LdaSmi), I16(289), B(Wide), B(LdaSmi), I16(290),
B(Star2), B(Star2),
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star3), B(Star3),
...@@ -61,13 +61,13 @@ bytecodes: [ ...@@ -61,13 +61,13 @@ bytecodes: [
B(TestReferenceEqual), R(this), B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0), B(Mov), R(this), R(0),
B(JumpIfTrue), U8(16), B(JumpIfTrue), U8(16),
B(Wide), B(LdaSmi), I16(289), B(Wide), B(LdaSmi), I16(290),
B(Star2), B(Star2),
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star3), B(Star3),
/* 61 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(2), U8(2), /* 61 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(2), U8(2),
B(Throw), B(Throw),
B(Wide), B(LdaSmi), I16(295), B(Wide), B(LdaSmi), I16(296),
B(Star2), B(Star2),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star3), B(Star3),
...@@ -99,13 +99,13 @@ bytecodes: [ ...@@ -99,13 +99,13 @@ bytecodes: [
B(TestReferenceEqual), R(this), B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0), B(Mov), R(this), R(0),
B(JumpIfTrue), U8(16), B(JumpIfTrue), U8(16),
B(Wide), B(LdaSmi), I16(289), B(Wide), B(LdaSmi), I16(290),
B(Star1), B(Star1),
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star2), B(Star2),
/* 61 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(1), U8(2), /* 61 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(1), U8(2),
B(Throw), B(Throw),
B(Wide), B(LdaSmi), I16(295), B(Wide), B(LdaSmi), I16(296),
B(Star1), B(Star1),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star2), B(Star2),
...@@ -145,7 +145,7 @@ bytecodes: [ ...@@ -145,7 +145,7 @@ bytecodes: [
B(TestReferenceEqual), R(this), B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0), B(Mov), R(this), R(0),
B(JumpIfTrue), U8(16), B(JumpIfTrue), U8(16),
B(Wide), B(LdaSmi), I16(289), B(Wide), B(LdaSmi), I16(290),
B(Star2), B(Star2),
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star3), B(Star3),
...@@ -167,7 +167,7 @@ bytecodes: [ ...@@ -167,7 +167,7 @@ bytecodes: [
B(TestReferenceEqual), R(this), B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0), B(Mov), R(this), R(0),
B(JumpIfTrue), U8(16), B(JumpIfTrue), U8(16),
B(Wide), B(LdaSmi), I16(289), B(Wide), B(LdaSmi), I16(290),
B(Star3), B(Star3),
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star4), B(Star4),
...@@ -182,7 +182,7 @@ bytecodes: [ ...@@ -182,7 +182,7 @@ bytecodes: [
B(TestReferenceEqual), R(this), B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0), B(Mov), R(this), R(0),
B(JumpIfTrue), U8(16), B(JumpIfTrue), U8(16),
B(Wide), B(LdaSmi), I16(289), B(Wide), B(LdaSmi), I16(290),
B(Star2), B(Star2),
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star3), B(Star3),
...@@ -216,13 +216,13 @@ bytecodes: [ ...@@ -216,13 +216,13 @@ bytecodes: [
B(TestReferenceEqual), R(this), B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0), B(Mov), R(this), R(0),
B(JumpIfTrue), U8(16), B(JumpIfTrue), U8(16),
B(Wide), B(LdaSmi), I16(289), B(Wide), B(LdaSmi), I16(290),
B(Star1), B(Star1),
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star2), B(Star2),
/* 65 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(1), U8(2), /* 65 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(1), U8(2),
B(Throw), B(Throw),
B(Wide), B(LdaSmi), I16(297), B(Wide), B(LdaSmi), I16(298),
B(Star1), B(Star1),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star2), B(Star2),
...@@ -253,13 +253,13 @@ bytecodes: [ ...@@ -253,13 +253,13 @@ bytecodes: [
B(TestReferenceEqual), R(this), B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0), B(Mov), R(this), R(0),
B(JumpIfTrue), U8(16), B(JumpIfTrue), U8(16),
B(Wide), B(LdaSmi), I16(289), B(Wide), B(LdaSmi), I16(290),
B(Star1), B(Star1),
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star2), B(Star2),
/* 58 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(1), U8(2), /* 58 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(1), U8(2),
B(Throw), B(Throw),
B(Wide), B(LdaSmi), I16(296), B(Wide), B(LdaSmi), I16(297),
B(Star1), B(Star1),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star2), B(Star2),
...@@ -292,13 +292,13 @@ bytecodes: [ ...@@ -292,13 +292,13 @@ bytecodes: [
B(TestReferenceEqual), R(this), B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0), B(Mov), R(this), R(0),
B(JumpIfTrue), U8(16), B(JumpIfTrue), U8(16),
B(Wide), B(LdaSmi), I16(289), B(Wide), B(LdaSmi), I16(290),
B(Star2), B(Star2),
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star3), B(Star3),
/* 65 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(2), U8(2), /* 65 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(2), U8(2),
B(Throw), B(Throw),
B(Wide), B(LdaSmi), I16(297), B(Wide), B(LdaSmi), I16(298),
B(Star2), B(Star2),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star3), B(Star3),
...@@ -327,7 +327,7 @@ bytecode array length: 19 ...@@ -327,7 +327,7 @@ bytecode array length: 19
bytecodes: [ bytecodes: [
/* 46 S> */ B(LdaImmutableCurrentContextSlot), U8(3), /* 46 S> */ B(LdaImmutableCurrentContextSlot), U8(3),
/* 51 E> */ B(GetKeyedProperty), R(this), U8(0), /* 51 E> */ B(GetKeyedProperty), R(this), U8(0),
B(Wide), B(LdaSmi), I16(296), B(Wide), B(LdaSmi), I16(297),
B(Star1), B(Star1),
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star2), B(Star2),
......
// Copyright 2022 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-shadow-realm --allow-natives-syntax
var shadowRealm = new ShadowRealm();
globalThis.foobar = 'outer-scope';
{
const promise = shadowRealm.importValue('./shadowrealm-skip-1.mjs', 'func');
// Promise is created in caller realm.
assertInstanceof(promise, Promise);
assertPromiseResult(promise.then(func => {
// Check that side-effects in the ShadowRealm not propagated to the caller.
assertEquals(globalThis.foobar, 'outer-scope');
// Check that the func is created in the current Realm.
assertEquals(typeof func, 'function');
assertTrue(func instanceof Function);
// Should return the inner global value.
assertEquals(func(), 'inner-scope');
}));
}
{
const promise = shadowRealm.importValue('./shadowrealm-skip-1.mjs', 'foo');
// Promise is created in caller realm.
assertInstanceof(promise, Promise);
assertPromiseResult(promise.then(foo => {
assertEquals(foo, 'bar');
}));
}
{
const promise = shadowRealm.importValue('./shadowrealm-skip-1.mjs', 'obj');
// Promise is created in caller realm.
assertInstanceof(promise, Promise);
assertThrowsAsync(promise, TypeError, "[object Object] is not a function");
}
{
const promise = shadowRealm.importValue('./shadowrealm-skip-1.mjs', 'not_exists');
// Promise is created in caller realm.
assertInstanceof(promise, Promise);
assertThrowsAsync(promise, TypeError, "The requested module './shadowrealm-skip-1.mjs' does not provide an export named 'not_exists'");
}
{
const promise = shadowRealm.importValue('./shadowrealm-skip-not-found.mjs', 'foo');
// Promise is created in caller realm.
assertInstanceof(promise, Promise);
assertThrowsAsync(promise, TypeError, 'Cannot import in the ShadowRealm');
}
{
const promise = shadowRealm.importValue('./shadowrealm-skip-2-throw.mjs', 'foo');
// Promise is created in caller realm.
assertInstanceof(promise, Promise);
assertThrowsAsync(promise, TypeError, 'Cannot import in the ShadowRealm');
}
// Invalid args
assertThrows(() => ShadowRealm.prototype.importValue.call(1, '', ''), TypeError, 'Method ShadowRealm.prototype.importValue called on incompatible receiver 1')
assertThrows(() => ShadowRealm.prototype.importValue.call({}, '', ''), TypeError, 'Method ShadowRealm.prototype.importValue called on incompatible receiver #<Object>')
export const foo = 'bar';
export const obj = {};
export const func = function () {
return globalThis.foobar;
};
// Generates side-effects to the globalThis.
globalThis.foobar = 'inner-scope';
export const foo = 'bar';
throw new Error('foobar');
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
# tested standalone. # tested standalone.
'modules-skip*': [SKIP], 'modules-skip*': [SKIP],
'harmony/modules-skip*': [SKIP], 'harmony/modules-skip*': [SKIP],
'harmony/shadowrealm-skip*': [SKIP],
'regress/modules-skip*': [SKIP], 'regress/modules-skip*': [SKIP],
'wasm/exceptions-utils': [SKIP], 'wasm/exceptions-utils': [SKIP],
'wasm/wasm-module-builder': [SKIP], 'wasm/wasm-module-builder': [SKIP],
......
...@@ -2985,13 +2985,6 @@ ...@@ -2985,13 +2985,6 @@
# https://bugs.chromium.org/p/v8/issues/detail?id=11989 # https://bugs.chromium.org/p/v8/issues/detail?id=11989
'built-ins/ShadowRealm/prototype/evaluate/globalthis-ordinary-object': [FAIL], 'built-ins/ShadowRealm/prototype/evaluate/globalthis-ordinary-object': [FAIL],
'built-ins/ShadowRealm/prototype/importValue/exportName-tostring': [FAIL],
'built-ins/ShadowRealm/prototype/importValue/import-value': [FAIL],
'built-ins/ShadowRealm/prototype/importValue/specifier-tostring': [FAIL],
'built-ins/ShadowRealm/prototype/importValue/throws-if-import-value-does-not-exist': [FAIL],
'built-ins/ShadowRealm/prototype/importValue/throws-typeerror-import-syntax-error': [FAIL],
'built-ins/ShadowRealm/prototype/importValue/throws-typeerror-import-throws': [FAIL],
'built-ins/ShadowRealm/prototype/importValue/validates-realm-object': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=12085 # https://bugs.chromium.org/p/v8/issues/detail?id=12085
'language/statements/class/subclass/derived-class-return-override-catch-finally': [FAIL], 'language/statements/class/subclass/derived-class-return-override-catch-finally': [FAIL],
......
...@@ -538,27 +538,28 @@ KNOWN_OBJECTS = { ...@@ -538,27 +538,28 @@ KNOWN_OBJECTS = {
("old_space", 0x04b39): "StringSplitCache", ("old_space", 0x04b39): "StringSplitCache",
("old_space", 0x04f41): "RegExpMultipleCache", ("old_space", 0x04f41): "RegExpMultipleCache",
("old_space", 0x05349): "BuiltinsConstantsTable", ("old_space", 0x05349): "BuiltinsConstantsTable",
("old_space", 0x05775): "AsyncFunctionAwaitRejectSharedFun", ("old_space", 0x05779): "AsyncFunctionAwaitRejectSharedFun",
("old_space", 0x05799): "AsyncFunctionAwaitResolveSharedFun", ("old_space", 0x0579d): "AsyncFunctionAwaitResolveSharedFun",
("old_space", 0x057bd): "AsyncGeneratorAwaitRejectSharedFun", ("old_space", 0x057c1): "AsyncGeneratorAwaitRejectSharedFun",
("old_space", 0x057e1): "AsyncGeneratorAwaitResolveSharedFun", ("old_space", 0x057e5): "AsyncGeneratorAwaitResolveSharedFun",
("old_space", 0x05805): "AsyncGeneratorYieldResolveSharedFun", ("old_space", 0x05809): "AsyncGeneratorYieldResolveSharedFun",
("old_space", 0x05829): "AsyncGeneratorReturnResolveSharedFun", ("old_space", 0x0582d): "AsyncGeneratorReturnResolveSharedFun",
("old_space", 0x0584d): "AsyncGeneratorReturnClosedRejectSharedFun", ("old_space", 0x05851): "AsyncGeneratorReturnClosedRejectSharedFun",
("old_space", 0x05871): "AsyncGeneratorReturnClosedResolveSharedFun", ("old_space", 0x05875): "AsyncGeneratorReturnClosedResolveSharedFun",
("old_space", 0x05895): "AsyncIteratorValueUnwrapSharedFun", ("old_space", 0x05899): "AsyncIteratorValueUnwrapSharedFun",
("old_space", 0x058b9): "PromiseAllResolveElementSharedFun", ("old_space", 0x058bd): "PromiseAllResolveElementSharedFun",
("old_space", 0x058dd): "PromiseAllSettledResolveElementSharedFun", ("old_space", 0x058e1): "PromiseAllSettledResolveElementSharedFun",
("old_space", 0x05901): "PromiseAllSettledRejectElementSharedFun", ("old_space", 0x05905): "PromiseAllSettledRejectElementSharedFun",
("old_space", 0x05925): "PromiseAnyRejectElementSharedFun", ("old_space", 0x05929): "PromiseAnyRejectElementSharedFun",
("old_space", 0x05949): "PromiseCapabilityDefaultRejectSharedFun", ("old_space", 0x0594d): "PromiseCapabilityDefaultRejectSharedFun",
("old_space", 0x0596d): "PromiseCapabilityDefaultResolveSharedFun", ("old_space", 0x05971): "PromiseCapabilityDefaultResolveSharedFun",
("old_space", 0x05991): "PromiseCatchFinallySharedFun", ("old_space", 0x05995): "PromiseCatchFinallySharedFun",
("old_space", 0x059b5): "PromiseGetCapabilitiesExecutorSharedFun", ("old_space", 0x059b9): "PromiseGetCapabilitiesExecutorSharedFun",
("old_space", 0x059d9): "PromiseThenFinallySharedFun", ("old_space", 0x059dd): "PromiseThenFinallySharedFun",
("old_space", 0x059fd): "PromiseThrowerFinallySharedFun", ("old_space", 0x05a01): "PromiseThrowerFinallySharedFun",
("old_space", 0x05a21): "PromiseValueThunkFinallySharedFun", ("old_space", 0x05a25): "PromiseValueThunkFinallySharedFun",
("old_space", 0x05a45): "ProxyRevokeSharedFun", ("old_space", 0x05a49): "ProxyRevokeSharedFun",
("old_space", 0x05a6d): "ShadowRealmImportValueFulfilledSFI",
} }
# Lower 32 bits of first page addresses for various heap spaces. # Lower 32 bits of first page addresses for various heap spaces.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment