Commit 9d72d08a authored by Daniel Clark's avatar Daniel Clark Committed by Commit Bot

[modules] Add ResolveModuleCallback that takes import assertions

This change completes the necessary API changes for import assertions
discussed in
https://docs.google.com/document/d/1yuXgNHSbTAPubT1Mg0JXp5uTrfirkvO1g5cHHCe-LmY.

The old ResolveCallback is deprecated and replaced with a
ResolveModuleCallback that includes import assertions.  Until
ResolveCallback is removed, InstantiateModule and associated functions
are modified to accept both types of callback, using the new one if it
was supplied and the old one otherwise.  An alternative that I chose not
to go with would be to just duplicate InstantiateModule and associated
functions for both callback types.

SyntheticModule::PrepareInstantiate's callback parameter was unused so I
removed it.

Bug: v8:10958
Change-Id: I8e9fbaf9c2853b076b13da02473fbbe039b9db57
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2551919Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Commit-Queue: Dan Clark <daniec@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#71506}
parent d35aaf74
...@@ -1628,9 +1628,13 @@ class V8_EXPORT Module : public Data { ...@@ -1628,9 +1628,13 @@ class V8_EXPORT Module : public Data {
*/ */
int GetIdentityHash() const; int GetIdentityHash() const;
V8_DEPRECATE_SOON("Use ResolveModuleCallback")
typedef MaybeLocal<Module> (*ResolveCallback)(Local<Context> context, typedef MaybeLocal<Module> (*ResolveCallback)(Local<Context> context,
Local<String> specifier, Local<String> specifier,
Local<Module> referrer); Local<Module> referrer);
typedef MaybeLocal<Module> (*ResolveModuleCallback)(
Local<Context> context, Local<String> specifier,
Local<FixedArray> import_assertions, Local<Module> referrer);
/** /**
* Instantiates the module and its dependencies. * Instantiates the module and its dependencies.
...@@ -1639,8 +1643,13 @@ class V8_EXPORT Module : public Data { ...@@ -1639,8 +1643,13 @@ class V8_EXPORT Module : public Data {
* instantiation. (In the case where the callback throws an exception, that * instantiation. (In the case where the callback throws an exception, that
* exception is propagated.) * exception is propagated.)
*/ */
V8_DEPRECATE_SOON(
"Use the version of InstantiateModule that takes a ResolveModuleCallback "
"parameter")
V8_WARN_UNUSED_RESULT Maybe<bool> InstantiateModule(Local<Context> context, V8_WARN_UNUSED_RESULT Maybe<bool> InstantiateModule(Local<Context> context,
ResolveCallback callback); ResolveCallback callback);
V8_WARN_UNUSED_RESULT Maybe<bool> InstantiateModule(
Local<Context> context, ResolveModuleCallback callback);
/** /**
* Evaluates the module and its dependencies. * Evaluates the module and its dependencies.
......
...@@ -104,7 +104,8 @@ MAKE_TO_LOCAL(ToLocal, BigInt, BigInt) ...@@ -104,7 +104,8 @@ MAKE_TO_LOCAL(ToLocal, BigInt, BigInt)
MAKE_TO_LOCAL(ExternalToLocal, JSObject, External) MAKE_TO_LOCAL(ExternalToLocal, JSObject, External)
MAKE_TO_LOCAL(CallableToLocal, JSReceiver, Function) MAKE_TO_LOCAL(CallableToLocal, JSReceiver, Function)
MAKE_TO_LOCAL(ToLocalPrimitive, Object, Primitive) MAKE_TO_LOCAL(ToLocalPrimitive, Object, Primitive)
MAKE_TO_LOCAL(ToLocal, FixedArray, PrimitiveArray) MAKE_TO_LOCAL(FixedArrayToLocal, FixedArray, FixedArray)
MAKE_TO_LOCAL(PrimitiveArrayToLocal, FixedArray, PrimitiveArray)
MAKE_TO_LOCAL(ScriptOrModuleToLocal, Script, ScriptOrModule) MAKE_TO_LOCAL(ScriptOrModuleToLocal, Script, ScriptOrModule)
#undef MAKE_TO_LOCAL_TYPED_ARRAY #undef MAKE_TO_LOCAL_TYPED_ARRAY
......
...@@ -380,7 +380,7 @@ static ScriptOrigin GetScriptOriginForScript(i::Isolate* isolate, ...@@ -380,7 +380,7 @@ static ScriptOrigin GetScriptOriginForScript(i::Isolate* isolate,
script->column_offset(), options.IsSharedCrossOrigin(), script->id(), script->column_offset(), options.IsSharedCrossOrigin(), script->id(),
Utils::ToLocal(source_map_url), options.IsOpaque(), Utils::ToLocal(source_map_url), options.IsOpaque(),
script->type() == i::Script::TYPE_WASM, options.IsModule(), script->type() == i::Script::TYPE_WASM, options.IsModule(),
Utils::ToLocal(host_defined_options)); Utils::PrimitiveArrayToLocal(host_defined_options));
return origin; return origin;
} }
...@@ -2396,10 +2396,23 @@ int Module::GetIdentityHash() const { return Utils::OpenHandle(this)->hash(); } ...@@ -2396,10 +2396,23 @@ int Module::GetIdentityHash() const { return Utils::OpenHandle(this)->hash(); }
Maybe<bool> Module::InstantiateModule(Local<Context> context, Maybe<bool> Module::InstantiateModule(Local<Context> context,
Module::ResolveCallback callback) { Module::ResolveCallback callback) {
auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate()); auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
ENTER_V8(isolate, context, Module, InstantiateModule, Nothing<bool>(),
i::HandleScope);
ResolveModuleCallback callback_with_import_assertions = nullptr;
has_pending_exception =
!i::Module::Instantiate(isolate, Utils::OpenHandle(this), context,
callback_with_import_assertions, callback);
RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
return Just(true);
}
Maybe<bool> Module::InstantiateModule(Local<Context> context,
Module::ResolveModuleCallback callback) {
auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
ENTER_V8(isolate, context, Module, InstantiateModule, Nothing<bool>(), ENTER_V8(isolate, context, Module, InstantiateModule, Nothing<bool>(),
i::HandleScope); i::HandleScope);
has_pending_exception = !i::Module::Instantiate( has_pending_exception = !i::Module::Instantiate(
isolate, Utils::OpenHandle(this), context, callback); isolate, Utils::OpenHandle(this), context, callback, nullptr);
RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
return Just(true); return Just(true);
} }
......
...@@ -242,7 +242,9 @@ class Utils { ...@@ -242,7 +242,9 @@ class Utils {
v8::internal::Handle<v8::internal::JSReceiver> obj); v8::internal::Handle<v8::internal::JSReceiver> obj);
static inline Local<Primitive> ToLocalPrimitive( static inline Local<Primitive> ToLocalPrimitive(
v8::internal::Handle<v8::internal::Object> obj); v8::internal::Handle<v8::internal::Object> obj);
static inline Local<PrimitiveArray> ToLocal( static inline Local<FixedArray> FixedArrayToLocal(
v8::internal::Handle<v8::internal::FixedArray> obj);
static inline Local<PrimitiveArray> PrimitiveArrayToLocal(
v8::internal::Handle<v8::internal::FixedArray> obj); v8::internal::Handle<v8::internal::FixedArray> obj);
static inline Local<ScriptOrModule> ScriptOrModuleToLocal( static inline Local<ScriptOrModule> ScriptOrModuleToLocal(
v8::internal::Handle<v8::internal::Script> obj); v8::internal::Handle<v8::internal::Script> obj);
......
...@@ -869,7 +869,9 @@ void DisposeModuleEmbedderData(Local<Context> context) { ...@@ -869,7 +869,9 @@ void DisposeModuleEmbedderData(Local<Context> context) {
MaybeLocal<Module> ResolveModuleCallback(Local<Context> context, MaybeLocal<Module> ResolveModuleCallback(Local<Context> context,
Local<String> specifier, Local<String> specifier,
Local<FixedArray> import_assertions,
Local<Module> referrer) { Local<Module> referrer) {
// TODO(v8:11189) Consider JSON modules support in d8.
Isolate* isolate = context->GetIsolate(); Isolate* isolate = context->GetIsolate();
ModuleEmbedderData* d = GetModuleDataFromContext(context); ModuleEmbedderData* d = GetModuleDataFromContext(context);
auto specifier_it = auto specifier_it =
......
...@@ -174,14 +174,16 @@ MaybeHandle<Cell> Module::ResolveExport(Isolate* isolate, Handle<Module> module, ...@@ -174,14 +174,16 @@ MaybeHandle<Cell> Module::ResolveExport(Isolate* isolate, Handle<Module> module,
} }
} }
bool Module::Instantiate(Isolate* isolate, Handle<Module> module, bool Module::Instantiate(
v8::Local<v8::Context> context, Isolate* isolate, Handle<Module> module, v8::Local<v8::Context> context,
v8::Module::ResolveCallback callback) { v8::Module::ResolveModuleCallback callback,
DeprecatedResolveCallback callback_without_import_assertions) {
#ifdef DEBUG #ifdef DEBUG
PrintStatusMessage(*module, "Instantiating module "); PrintStatusMessage(*module, "Instantiating module ");
#endif // DEBUG #endif // DEBUG
if (!PrepareInstantiate(isolate, module, context, callback)) { if (!PrepareInstantiate(isolate, module, context, callback,
callback_without_import_assertions)) {
ResetGraph(isolate, module); ResetGraph(isolate, module);
DCHECK_EQ(module->status(), kUninstantiated); DCHECK_EQ(module->status(), kUninstantiated);
return false; return false;
...@@ -200,9 +202,10 @@ bool Module::Instantiate(Isolate* isolate, Handle<Module> module, ...@@ -200,9 +202,10 @@ bool Module::Instantiate(Isolate* isolate, Handle<Module> module,
return true; return true;
} }
bool Module::PrepareInstantiate(Isolate* isolate, Handle<Module> module, bool Module::PrepareInstantiate(
v8::Local<v8::Context> context, Isolate* isolate, Handle<Module> module, v8::Local<v8::Context> context,
v8::Module::ResolveCallback callback) { v8::Module::ResolveModuleCallback callback,
DeprecatedResolveCallback callback_without_import_assertions) {
DCHECK_NE(module->status(), kEvaluating); DCHECK_NE(module->status(), kEvaluating);
DCHECK_NE(module->status(), kInstantiating); DCHECK_NE(module->status(), kInstantiating);
if (module->status() >= kPreInstantiating) return true; if (module->status() >= kPreInstantiating) return true;
...@@ -211,10 +214,11 @@ bool Module::PrepareInstantiate(Isolate* isolate, Handle<Module> module, ...@@ -211,10 +214,11 @@ bool Module::PrepareInstantiate(Isolate* isolate, Handle<Module> module,
if (module->IsSourceTextModule()) { if (module->IsSourceTextModule()) {
return SourceTextModule::PrepareInstantiate( return SourceTextModule::PrepareInstantiate(
isolate, Handle<SourceTextModule>::cast(module), context, callback); isolate, Handle<SourceTextModule>::cast(module), context, callback,
callback_without_import_assertions);
} else { } else {
return SyntheticModule::PrepareInstantiate( return SyntheticModule::PrepareInstantiate(
isolate, Handle<SyntheticModule>::cast(module), context, callback); isolate, Handle<SyntheticModule>::cast(module), context);
} }
} }
......
...@@ -69,13 +69,24 @@ class Module : public HeapObject { ...@@ -69,13 +69,24 @@ class Module : public HeapObject {
// i.e. has a top-level await. // i.e. has a top-level await.
V8_WARN_UNUSED_RESULT bool IsGraphAsync(Isolate* isolate) const; V8_WARN_UNUSED_RESULT bool IsGraphAsync(Isolate* isolate) const;
// While deprecating v8::ResolveCallback in v8.h we still need to support the
// version of the API that uses it, but we can't directly reference the
// deprecated version because of the enusing build warnings. So, we declare
// this matching typedef for temporary internal use.
// TODO(v8:10958) Delete this typedef and all references to it once
// v8::ResolveCallback is removed.
typedef MaybeLocal<v8::Module> (*DeprecatedResolveCallback)(
Local<v8::Context> context, Local<v8::String> specifier,
Local<v8::Module> referrer);
// Implementation of spec operation ModuleDeclarationInstantiation. // Implementation of spec operation ModuleDeclarationInstantiation.
// Returns false if an exception occurred during instantiation, true // Returns false if an exception occurred during instantiation, true
// otherwise. (In the case where the callback throws an exception, that // otherwise. (In the case where the callback throws an exception, that
// exception is propagated.) // exception is propagated.)
static V8_WARN_UNUSED_RESULT bool Instantiate( static V8_WARN_UNUSED_RESULT bool Instantiate(
Isolate* isolate, Handle<Module> module, v8::Local<v8::Context> context, Isolate* isolate, Handle<Module> module, v8::Local<v8::Context> context,
v8::Module::ResolveCallback callback); v8::Module::ResolveModuleCallback callback,
DeprecatedResolveCallback callback_without_import_assertions);
// Implementation of spec operation ModuleEvaluation. // Implementation of spec operation ModuleEvaluation.
static V8_WARN_UNUSED_RESULT MaybeHandle<Object> Evaluate( static V8_WARN_UNUSED_RESULT MaybeHandle<Object> Evaluate(
...@@ -114,7 +125,8 @@ class Module : public HeapObject { ...@@ -114,7 +125,8 @@ class Module : public HeapObject {
static V8_WARN_UNUSED_RESULT bool PrepareInstantiate( static V8_WARN_UNUSED_RESULT bool PrepareInstantiate(
Isolate* isolate, Handle<Module> module, v8::Local<v8::Context> context, Isolate* isolate, Handle<Module> module, v8::Local<v8::Context> context,
v8::Module::ResolveCallback callback); v8::Module::ResolveModuleCallback callback,
DeprecatedResolveCallback callback_without_import_assertions);
static V8_WARN_UNUSED_RESULT bool FinishInstantiate( static V8_WARN_UNUSED_RESULT bool FinishInstantiate(
Isolate* isolate, Handle<Module> module, Isolate* isolate, Handle<Module> module,
ZoneForwardList<Handle<SourceTextModule>>* stack, unsigned* dfs_index, ZoneForwardList<Handle<SourceTextModule>>* stack, unsigned* dfs_index,
......
...@@ -312,7 +312,9 @@ MaybeHandle<Cell> SourceTextModule::ResolveExportUsingStarExports( ...@@ -312,7 +312,9 @@ MaybeHandle<Cell> SourceTextModule::ResolveExportUsingStarExports(
bool SourceTextModule::PrepareInstantiate( bool SourceTextModule::PrepareInstantiate(
Isolate* isolate, Handle<SourceTextModule> module, Isolate* isolate, Handle<SourceTextModule> module,
v8::Local<v8::Context> context, v8::Module::ResolveCallback callback) { v8::Local<v8::Context> context, v8::Module::ResolveModuleCallback callback,
Module::DeprecatedResolveCallback callback_without_import_assertions) {
DCHECK_EQ(callback != nullptr, callback_without_import_assertions == nullptr);
// Obtain requested modules. // Obtain requested modules.
Handle<SourceTextModuleInfo> module_info(module->info(), isolate); Handle<SourceTextModuleInfo> module_info(module->info(), isolate);
Handle<FixedArray> module_requests(module_info->module_requests(), isolate); Handle<FixedArray> module_requests(module_info->module_requests(), isolate);
...@@ -321,14 +323,26 @@ bool SourceTextModule::PrepareInstantiate( ...@@ -321,14 +323,26 @@ bool SourceTextModule::PrepareInstantiate(
Handle<ModuleRequest> module_request( Handle<ModuleRequest> module_request(
ModuleRequest::cast(module_requests->get(i)), isolate); ModuleRequest::cast(module_requests->get(i)), isolate);
Handle<String> specifier(module_request->specifier(), isolate); Handle<String> specifier(module_request->specifier(), isolate);
// TODO(v8:10958) Pass import assertions to the callback
v8::Local<v8::Module> api_requested_module; v8::Local<v8::Module> api_requested_module;
if (callback) {
Handle<FixedArray> import_assertions(module_request->import_assertions(),
isolate);
if (!callback(context, v8::Utils::ToLocal(specifier), if (!callback(context, v8::Utils::ToLocal(specifier),
v8::Utils::FixedArrayToLocal(import_assertions),
v8::Utils::ToLocal(Handle<Module>::cast(module)))
.ToLocal(&api_requested_module)) {
isolate->PromoteScheduledException();
return false;
}
} else {
if (!callback_without_import_assertions(
context, v8::Utils::ToLocal(specifier),
v8::Utils::ToLocal(Handle<Module>::cast(module))) v8::Utils::ToLocal(Handle<Module>::cast(module)))
.ToLocal(&api_requested_module)) { .ToLocal(&api_requested_module)) {
isolate->PromoteScheduledException(); isolate->PromoteScheduledException();
return false; return false;
} }
}
Handle<Module> requested_module = Utils::OpenHandle(*api_requested_module); Handle<Module> requested_module = Utils::OpenHandle(*api_requested_module);
requested_modules->set(i, *requested_module); requested_modules->set(i, *requested_module);
} }
...@@ -338,7 +352,8 @@ bool SourceTextModule::PrepareInstantiate( ...@@ -338,7 +352,8 @@ bool SourceTextModule::PrepareInstantiate(
Handle<Module> requested_module(Module::cast(requested_modules->get(i)), Handle<Module> requested_module(Module::cast(requested_modules->get(i)),
isolate); isolate);
if (!Module::PrepareInstantiate(isolate, requested_module, context, if (!Module::PrepareInstantiate(isolate, requested_module, context,
callback)) { callback,
callback_without_import_assertions)) {
return false; return false;
} }
} }
......
...@@ -138,7 +138,9 @@ class SourceTextModule ...@@ -138,7 +138,9 @@ class SourceTextModule
static V8_WARN_UNUSED_RESULT bool PrepareInstantiate( static V8_WARN_UNUSED_RESULT bool PrepareInstantiate(
Isolate* isolate, Handle<SourceTextModule> module, Isolate* isolate, Handle<SourceTextModule> module,
v8::Local<v8::Context> context, v8::Module::ResolveCallback callback); v8::Local<v8::Context> context,
v8::Module::ResolveModuleCallback callback,
Module::DeprecatedResolveCallback callback_without_import_assertions);
static V8_WARN_UNUSED_RESULT bool FinishInstantiate( static V8_WARN_UNUSED_RESULT bool FinishInstantiate(
Isolate* isolate, Handle<SourceTextModule> module, Isolate* isolate, Handle<SourceTextModule> module,
ZoneForwardList<Handle<SourceTextModule>>* stack, unsigned* dfs_index, ZoneForwardList<Handle<SourceTextModule>>* stack, unsigned* dfs_index,
......
...@@ -70,8 +70,7 @@ MaybeHandle<Cell> SyntheticModule::ResolveExport( ...@@ -70,8 +70,7 @@ MaybeHandle<Cell> SyntheticModule::ResolveExport(
// https://heycam.github.io/webidl/#smr-instantiate // https://heycam.github.io/webidl/#smr-instantiate
bool SyntheticModule::PrepareInstantiate(Isolate* isolate, bool SyntheticModule::PrepareInstantiate(Isolate* isolate,
Handle<SyntheticModule> module, Handle<SyntheticModule> module,
v8::Local<v8::Context> context, v8::Local<v8::Context> context) {
v8::Module::ResolveCallback callback) {
Handle<ObjectHashTable> exports(module->exports(), isolate); Handle<ObjectHashTable> exports(module->exports(), isolate);
Handle<FixedArray> export_names(module->export_names(), isolate); Handle<FixedArray> export_names(module->export_names(), isolate);
// Spec step 7: For each export_name in module->export_names... // Spec step 7: For each export_name in module->export_names...
......
...@@ -56,7 +56,7 @@ class SyntheticModule ...@@ -56,7 +56,7 @@ class SyntheticModule
static V8_WARN_UNUSED_RESULT bool PrepareInstantiate( static V8_WARN_UNUSED_RESULT bool PrepareInstantiate(
Isolate* isolate, Handle<SyntheticModule> module, Isolate* isolate, Handle<SyntheticModule> module,
v8::Local<v8::Context> context, v8::Module::ResolveCallback callback); v8::Local<v8::Context> context);
static V8_WARN_UNUSED_RESULT bool FinishInstantiate( static V8_WARN_UNUSED_RESULT bool FinishInstantiate(
Isolate* isolate, Handle<SyntheticModule> module); Isolate* isolate, Handle<SyntheticModule> module);
......
...@@ -82,6 +82,7 @@ using ::v8::Boolean; ...@@ -82,6 +82,7 @@ using ::v8::Boolean;
using ::v8::BooleanObject; using ::v8::BooleanObject;
using ::v8::Context; using ::v8::Context;
using ::v8::Extension; using ::v8::Extension;
using ::v8::FixedArray;
using ::v8::Function; using ::v8::Function;
using ::v8::FunctionTemplate; using ::v8::FunctionTemplate;
using ::v8::HandleScope; using ::v8::HandleScope;
...@@ -23525,6 +23526,11 @@ class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream { ...@@ -23525,6 +23526,11 @@ class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
unsigned index_; unsigned index_;
}; };
v8::MaybeLocal<Module> UnexpectedModuleResolveCallback(
Local<Context> context, Local<String> specifier,
Local<FixedArray> import_assertions, Local<Module> referrer) {
CHECK_WITH_MSG(false, "Unexpected call to resolve callback");
}
// Helper function for running streaming tests. // Helper function for running streaming tests.
void RunStreamingTest(const char** chunks, i::ScriptType type, void RunStreamingTest(const char** chunks, i::ScriptType type,
...@@ -23577,7 +23583,10 @@ void RunStreamingTest(const char** chunks, i::ScriptType type, ...@@ -23577,7 +23583,10 @@ void RunStreamingTest(const char** chunks, i::ScriptType type,
env.local(), &source, v8_str(full_source), origin); env.local(), &source, v8_str(full_source), origin);
if (expected_success) { if (expected_success) {
v8::Local<v8::Module> module = maybe_module.ToLocalChecked(); v8::Local<v8::Module> module = maybe_module.ToLocalChecked();
CHECK(module->InstantiateModule(env.local(), nullptr).FromJust()); CHECK(
module
->InstantiateModule(env.local(), UnexpectedModuleResolveCallback)
.FromJust());
CHECK_EQ(Module::kInstantiated, module->GetStatus()); CHECK_EQ(Module::kInstantiated, module->GetStatus());
v8::Local<Value> result = module->Evaluate(env.local()).ToLocalChecked(); v8::Local<Value> result = module->Evaluate(env.local()).ToLocalChecked();
CHECK_EQ(Module::kEvaluated, module->GetStatus()); CHECK_EQ(Module::kEvaluated, module->GetStatus());
...@@ -24038,12 +24047,6 @@ TEST(CodeCache) { ...@@ -24038,12 +24047,6 @@ TEST(CodeCache) {
isolate2->Dispose(); isolate2->Dispose();
} }
v8::MaybeLocal<Module> UnexpectedModuleResolveCallback(Local<Context> context,
Local<String> specifier,
Local<Module> referrer) {
CHECK_WITH_MSG(false, "Unexpected call to resolve callback");
}
v8::MaybeLocal<Value> UnexpectedSyntheticModuleEvaluationStepsCallback( v8::MaybeLocal<Value> UnexpectedSyntheticModuleEvaluationStepsCallback(
Local<Context> context, Local<Module> module) { Local<Context> context, Local<Module> module) {
CHECK_WITH_MSG(false, "Unexpected call to synthetic module re callback"); CHECK_WITH_MSG(false, "Unexpected call to synthetic module re callback");
...@@ -24126,9 +24129,9 @@ Local<Module> CompileAndInstantiateModuleFromCache( ...@@ -24126,9 +24129,9 @@ Local<Module> CompileAndInstantiateModuleFromCache(
} // namespace } // namespace
v8::MaybeLocal<Module> SyntheticModuleResolveCallback(Local<Context> context, v8::MaybeLocal<Module> SyntheticModuleResolveCallback(
Local<String> specifier, Local<Context> context, Local<String> specifier,
Local<Module> referrer) { Local<FixedArray> import_assertions, Local<Module> referrer) {
std::vector<v8::Local<v8::String>> export_names{v8_str("test_export")}; std::vector<v8::Local<v8::String>> export_names{v8_str("test_export")};
Local<Module> module = CreateAndInstantiateSyntheticModule( Local<Module> module = CreateAndInstantiateSyntheticModule(
context->GetIsolate(), context->GetIsolate(),
...@@ -24138,7 +24141,8 @@ v8::MaybeLocal<Module> SyntheticModuleResolveCallback(Local<Context> context, ...@@ -24138,7 +24141,8 @@ v8::MaybeLocal<Module> SyntheticModuleResolveCallback(Local<Context> context,
} }
v8::MaybeLocal<Module> SyntheticModuleThatThrowsDuringEvaluateResolveCallback( v8::MaybeLocal<Module> SyntheticModuleThatThrowsDuringEvaluateResolveCallback(
Local<Context> context, Local<String> specifier, Local<Module> referrer) { Local<Context> context, Local<String> specifier,
Local<FixedArray> import_assertions, Local<Module> referrer) {
std::vector<v8::Local<v8::String>> export_names{v8_str("test_export")}; std::vector<v8::Local<v8::String>> export_names{v8_str("test_export")};
Local<Module> module = CreateAndInstantiateSyntheticModule( Local<Module> module = CreateAndInstantiateSyntheticModule(
context->GetIsolate(), context->GetIsolate(),
...@@ -35,7 +35,9 @@ static Local<Module> dep1; ...@@ -35,7 +35,9 @@ static Local<Module> dep1;
static Local<Module> dep2; static Local<Module> dep2;
MaybeLocal<Module> ResolveCallback(Local<Context> context, MaybeLocal<Module> ResolveCallback(Local<Context> context,
Local<String> specifier, Local<String> specifier,
Local<FixedArray> import_assertions,
Local<Module> referrer) { Local<Module> referrer) {
CHECK_EQ(0, import_assertions->Length());
Isolate* isolate = CcTest::isolate(); Isolate* isolate = CcTest::isolate();
if (specifier->StrictEquals(v8_str("./dep1.js"))) { if (specifier->StrictEquals(v8_str("./dep1.js"))) {
return dep1; return dep1;
...@@ -131,7 +133,46 @@ TEST(ModuleInstantiationFailures1) { ...@@ -131,7 +133,46 @@ TEST(ModuleInstantiationFailures1) {
i::FLAG_harmony_top_level_await = prev_top_level_await; i::FLAG_harmony_top_level_await = prev_top_level_await;
} }
TEST(ModuleInstantiationFailures1WithImportAssertions) { static Local<Module> fooModule;
static Local<Module> barModule;
MaybeLocal<Module> ResolveCallbackWithImportAssertions(
Local<Context> context, Local<String> specifier,
Local<FixedArray> import_assertions, Local<Module> referrer) {
Isolate* isolate = CcTest::isolate();
LocalContext env;
if (specifier->StrictEquals(v8_str("./foo.js"))) {
CHECK_EQ(0, import_assertions->Length());
return fooModule;
} else if (specifier->StrictEquals(v8_str("./bar.js"))) {
CHECK_EQ(3, import_assertions->Length());
Local<String> assertion_key =
import_assertions->Get(env.local(), 0).As<Value>().As<String>();
CHECK(v8_str("a")->StrictEquals(assertion_key));
Local<String> assertion_value =
import_assertions->Get(env.local(), 1).As<Value>().As<String>();
CHECK(v8_str("b")->StrictEquals(assertion_value));
Local<Data> assertion_source_offset_object =
import_assertions->Get(env.local(), 2);
Local<Int32> assertion_source_offset_int32 =
assertion_source_offset_object.As<Value>()
->ToInt32(context)
.ToLocalChecked();
int32_t assertion_source_offset = assertion_source_offset_int32->Value();
CHECK_EQ(65, assertion_source_offset);
Location loc = referrer->SourceOffsetToLocation(assertion_source_offset);
CHECK_EQ(1, loc.GetLineNumber());
CHECK_EQ(35, loc.GetColumnNumber());
return barModule;
} else {
isolate->ThrowException(v8_str("boom"));
return MaybeLocal<Module>();
}
}
TEST(ModuleInstantiationWithImportAssertions) {
bool prev_top_level_await = i::FLAG_harmony_top_level_await; bool prev_top_level_await = i::FLAG_harmony_top_level_await;
bool prev_import_assertions = i::FLAG_harmony_import_assertions; bool prev_import_assertions = i::FLAG_harmony_import_assertions;
i::FLAG_harmony_import_assertions = true; i::FLAG_harmony_import_assertions = true;
...@@ -194,16 +235,40 @@ TEST(ModuleInstantiationFailures1WithImportAssertions) { ...@@ -194,16 +235,40 @@ TEST(ModuleInstantiationFailures1WithImportAssertions) {
CHECK_EQ(35, loc.GetColumnNumber()); CHECK_EQ(35, loc.GetColumnNumber());
} }
// Instantiation should fail. // foo.js
{ {
v8::TryCatch inner_try_catch(isolate); Local<String> source_text = v8_str("Object.expando = 40");
CHECK( ScriptOrigin origin = ModuleOrigin(v8_str("foo.js"), CcTest::isolate());
module->InstantiateModule(env.local(), ResolveCallback).IsNothing()); ScriptCompiler::Source source(source_text, origin);
CHECK(inner_try_catch.HasCaught()); fooModule =
CHECK(inner_try_catch.Exception()->StrictEquals(v8_str("boom"))); ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
CHECK_EQ(Module::kUninstantiated, module->GetStatus());
} }
// bar.js
{
Local<String> source_text = v8_str("Object.expando += 2");
ScriptOrigin origin = ModuleOrigin(v8_str("bar.js"), CcTest::isolate());
ScriptCompiler::Source source(source_text, origin);
barModule =
ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
}
CHECK(module
->InstantiateModule(env.local(),
ResolveCallbackWithImportAssertions)
.FromJust());
CHECK_EQ(Module::kInstantiated, module->GetStatus());
MaybeLocal<Value> result = module->Evaluate(env.local());
CHECK_EQ(Module::kEvaluated, module->GetStatus());
if (i::FLAG_harmony_top_level_await) {
Local<Promise> promise = Local<Promise>::Cast(result.ToLocalChecked());
CHECK_EQ(promise->State(), v8::Promise::kFulfilled);
CHECK(promise->Result()->IsUndefined());
} else {
CHECK(!result.IsEmpty());
ExpectInt32("Object.expando", 42);
}
CHECK(!try_catch.HasCaught()); CHECK(!try_catch.HasCaught());
} }
i::FLAG_harmony_top_level_await = prev_top_level_await; i::FLAG_harmony_top_level_await = prev_top_level_await;
...@@ -296,7 +361,9 @@ TEST(ModuleInstantiationFailures2) { ...@@ -296,7 +361,9 @@ TEST(ModuleInstantiationFailures2) {
} }
static MaybeLocal<Module> CompileSpecifierAsModuleResolveCallback( static MaybeLocal<Module> CompileSpecifierAsModuleResolveCallback(
Local<Context> context, Local<String> specifier, Local<Module> referrer) { Local<Context> context, Local<String> specifier,
Local<FixedArray> import_assertions, Local<Module> referrer) {
CHECK_EQ(0, import_assertions->Length());
ScriptOrigin origin = ModuleOrigin(v8_str("module.js"), CcTest::isolate()); ScriptOrigin origin = ModuleOrigin(v8_str("module.js"), CcTest::isolate());
ScriptCompiler::Source source(specifier, origin); ScriptCompiler::Source source(specifier, origin);
return ScriptCompiler::CompileModule(CcTest::isolate(), &source) return ScriptCompiler::CompileModule(CcTest::isolate(), &source)
...@@ -417,7 +484,9 @@ TEST(ModuleEvaluationError1) { ...@@ -417,7 +484,9 @@ TEST(ModuleEvaluationError1) {
static Local<Module> failure_module; static Local<Module> failure_module;
static Local<Module> dependent_module; static Local<Module> dependent_module;
MaybeLocal<Module> ResolveCallbackForModuleEvaluationError2( MaybeLocal<Module> ResolveCallbackForModuleEvaluationError2(
Local<Context> context, Local<String> specifier, Local<Module> referrer) { Local<Context> context, Local<String> specifier,
Local<FixedArray> import_assertions, Local<Module> referrer) {
CHECK_EQ(0, import_assertions->Length());
if (specifier->StrictEquals(v8_str("./failure.js"))) { if (specifier->StrictEquals(v8_str("./failure.js"))) {
return failure_module; return failure_module;
} else { } else {
...@@ -1087,7 +1156,9 @@ static Local<Module> cycle_self_module; ...@@ -1087,7 +1156,9 @@ static Local<Module> cycle_self_module;
static Local<Module> cycle_one_module; static Local<Module> cycle_one_module;
static Local<Module> cycle_two_module; static Local<Module> cycle_two_module;
MaybeLocal<Module> ResolveCallbackForIsGraphAsyncTopLevelAwait( MaybeLocal<Module> ResolveCallbackForIsGraphAsyncTopLevelAwait(
Local<Context> context, Local<String> specifier, Local<Module> referrer) { Local<Context> context, Local<String> specifier,
Local<FixedArray> import_assertions, Local<Module> referrer) {
CHECK_EQ(0, import_assertions->Length());
if (specifier->StrictEquals(v8_str("./async_leaf.js"))) { if (specifier->StrictEquals(v8_str("./async_leaf.js"))) {
return async_leaf_module; return async_leaf_module;
} else if (specifier->StrictEquals(v8_str("./sync_leaf.js"))) { } else if (specifier->StrictEquals(v8_str("./sync_leaf.js"))) {
......
...@@ -129,7 +129,9 @@ void IsolateData::RegisterModule(v8::Local<v8::Context> context, ...@@ -129,7 +129,9 @@ void IsolateData::RegisterModule(v8::Local<v8::Context> context,
// static // static
v8::MaybeLocal<v8::Module> IsolateData::ModuleResolveCallback( v8::MaybeLocal<v8::Module> IsolateData::ModuleResolveCallback(
v8::Local<v8::Context> context, v8::Local<v8::String> specifier, v8::Local<v8::Context> context, v8::Local<v8::String> specifier,
v8::Local<v8::FixedArray> import_assertions,
v8::Local<v8::Module> referrer) { v8::Local<v8::Module> referrer) {
// TODO(v8:11189) Consider JSON modules support in the InspectorClient
IsolateData* data = IsolateData::FromContext(context); IsolateData* data = IsolateData::FromContext(context);
std::string str = *v8::String::Utf8Value(data->isolate(), specifier); std::string str = *v8::String::Utf8Value(data->isolate(), specifier);
return data->modules_[ToVector(data->isolate(), specifier)].Get( return data->modules_[ToVector(data->isolate(), specifier)].Get(
......
...@@ -100,6 +100,7 @@ class IsolateData : public v8_inspector::V8InspectorClient { ...@@ -100,6 +100,7 @@ class IsolateData : public v8_inspector::V8InspectorClient {
private: private:
static v8::MaybeLocal<v8::Module> ModuleResolveCallback( static v8::MaybeLocal<v8::Module> ModuleResolveCallback(
v8::Local<v8::Context> context, v8::Local<v8::String> specifier, v8::Local<v8::Context> context, v8::Local<v8::String> specifier,
v8::Local<v8::FixedArray> import_assertions,
v8::Local<v8::Module> referrer); v8::Local<v8::Module> referrer);
static void MessageHandler(v8::Local<v8::Message> message, static void MessageHandler(v8::Local<v8::Message> message,
v8::Local<v8::Value> exception); v8::Local<v8::Value> exception);
......
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