[modules] Disallow throwing in import.meta callback

... via a comment in the API and a CHECK in
Isolate::RunHostInitializeImportMetaObjectCallback.

Also restructure things a little bit such that
this function really just runs the callback and
doesn't deal with module internals. Memoization
now happens in the SourceTextModule class.

Bug: v8:7044
Change-Id: I5b850ae629c3638c4b30dfdeaa996642a33d14dc
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2190413
Reviewed-by: Sathya Gunasekaran  <gsathya@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Auto-Submit: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67682}
This commit is contained in:
Georg Neis 2020-05-08 10:36:36 +02:00 committed by Commit Bot
parent b1a0dd8503
commit 5bf4772878
6 changed files with 31 additions and 19 deletions

View File

@ -7219,7 +7219,8 @@ typedef MaybeLocal<Promise> (*HostImportModuleDynamicallyCallback)(
/**
* HostInitializeImportMetaObjectCallback is called the first time import.meta
* is accessed for a module. Subsequent access will reuse the same value.
* is accessed for a module. Subsequent access will reuse the same value. The
* callback must not throw.
*
* The method combines two implementation-defined abstract operations into one:
* HostGetImportMetaProperties and HostFinalizeImportMeta.

View File

@ -3952,19 +3952,17 @@ void Isolate::SetHostImportModuleDynamicallyCallback(
Handle<JSObject> Isolate::RunHostInitializeImportMetaObjectCallback(
Handle<SourceTextModule> module) {
Handle<HeapObject> host_meta(module->import_meta(), this);
if (host_meta->IsTheHole(this)) {
host_meta = factory()->NewJSObjectWithNullProto();
if (host_initialize_import_meta_object_callback_ != nullptr) {
v8::Local<v8::Context> api_context =
v8::Utils::ToLocal(Handle<Context>(native_context()));
host_initialize_import_meta_object_callback_(
api_context, Utils::ToLocal(Handle<Module>::cast(module)),
v8::Local<v8::Object>::Cast(v8::Utils::ToLocal(host_meta)));
}
module->set_import_meta(*host_meta);
CHECK(module->import_meta().IsTheHole(this));
Handle<JSObject> import_meta = factory()->NewJSObjectWithNullProto();
if (host_initialize_import_meta_object_callback_ != nullptr) {
v8::Local<v8::Context> api_context =
v8::Utils::ToLocal(Handle<Context>(native_context()));
host_initialize_import_meta_object_callback_(
api_context, Utils::ToLocal(Handle<Module>::cast(module)),
v8::Local<v8::Object>::Cast(v8::Utils::ToLocal(import_meta)));
CHECK(!has_scheduled_exception());
}
return Handle<JSObject>::cast(host_meta);
return import_meta;
}
void Isolate::SetHostInitializeImportMetaObjectCallback(

View File

@ -583,6 +583,16 @@ Handle<JSModuleNamespace> SourceTextModule::GetModuleNamespace(
return Module::GetModuleNamespace(isolate, requested_module);
}
Handle<JSObject> SourceTextModule::GetImportMeta(
Isolate* isolate, Handle<SourceTextModule> module) {
Handle<HeapObject> import_meta(module->import_meta(), isolate);
if (import_meta->IsTheHole(isolate)) {
import_meta = isolate->RunHostInitializeImportMetaObjectCallback(module);
module->set_import_meta(*import_meta);
}
return Handle<JSObject>::cast(import_meta);
}
MaybeHandle<Object> SourceTextModule::EvaluateMaybeAsync(
Isolate* isolate, Handle<SourceTextModule> module) {
// In the event of errored evaluation, return a rejected promise.

View File

@ -59,6 +59,11 @@ class SourceTextModule
static Handle<JSModuleNamespace> GetModuleNamespace(
Isolate* isolate, Handle<SourceTextModule> module, int module_request);
// Get the import.meta object of [module]. If it doesn't exist yet, it is
// created and passed to the embedder callback for initialization.
V8_EXPORT_PRIVATE static Handle<JSObject> GetImportMeta(
Isolate* isolate, Handle<SourceTextModule> module);
using BodyDescriptor =
SubclassBodyDescriptor<Module::BodyDescriptor,
FixedBodyDescriptor<kCodeOffset, kSize, kSize>>;

View File

@ -41,7 +41,7 @@ RUNTIME_FUNCTION(Runtime_GetImportMetaObject) {
HandleScope scope(isolate);
DCHECK_EQ(0, args.length());
Handle<SourceTextModule> module(isolate->context().module(), isolate);
return *isolate->RunHostInitializeImportMetaObjectCallback(module);
return *SourceTextModule::GetImportMeta(isolate, module);
}
} // namespace internal

View File

@ -25760,7 +25760,6 @@ void HostInitializeImportMetaObjectCallbackStatic(Local<Context> context,
Local<Module> module,
Local<Object> meta) {
CHECK(!module.IsEmpty());
meta->CreateDataProperty(context, v8_str("foo"), v8_str("bar")).ToChecked();
}
@ -25784,10 +25783,9 @@ TEST(ImportMeta) {
v8::ScriptCompiler::Source source(source_text, origin);
Local<Module> module =
v8::ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
i::Handle<i::Object> meta =
i_isolate->RunHostInitializeImportMetaObjectCallback(
i::Handle<i::SourceTextModule>::cast(v8::Utils::OpenHandle(*module)));
CHECK(meta->IsJSObject());
i::Handle<i::JSObject> meta = i::SourceTextModule::GetImportMeta(
i_isolate,
i::Handle<i::SourceTextModule>::cast(v8::Utils::OpenHandle(*module)));
Local<Object> meta_obj = Local<Object>::Cast(v8::Utils::ToLocal(meta));
CHECK(meta_obj->Get(context.local(), v8_str("foo"))
.ToLocalChecked()