| Index: src/api.cc
|
| diff --git a/src/api.cc b/src/api.cc
|
| index a6aa4d257f3635a20881e1529d9fb70042262c78..713ae93fabd85f071605011e6809d792cf1b299b 100644
|
| --- a/src/api.cc
|
| +++ b/src/api.cc
|
| @@ -1884,7 +1884,40 @@ Local<UnboundScript> Script::GetUnboundScript() {
|
| i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared()));
|
| }
|
|
|
| -bool Module::Instantiate(Local<Context> v8_context) {
|
| +int Module::GetModuleRequestsLength() const {
|
| + i::Handle<i::Module> self = Utils::OpenHandle(this);
|
| + i::Isolate* isolate = self->GetIsolate();
|
| + i::Handle<i::SharedFunctionInfo> shared;
|
| + if (self->code()->IsSharedFunctionInfo()) {
|
| + shared = i::handle(i::SharedFunctionInfo::cast(self->code()), isolate);
|
| + } else {
|
| + shared = i::handle(i::JSFunction::cast(self->code())->shared(), isolate);
|
| + }
|
| + return shared->scope_info()
|
| + ->ModuleDescriptorInfo()
|
| + ->module_requests()
|
| + ->length();
|
| +}
|
| +
|
| +Local<String> Module::GetModuleRequest(int i) const {
|
| + CHECK_GE(i, 0);
|
| + i::Handle<i::Module> self = Utils::OpenHandle(this);
|
| + i::Isolate* isolate = self->GetIsolate();
|
| + i::Handle<i::SharedFunctionInfo> shared;
|
| + if (self->code()->IsSharedFunctionInfo()) {
|
| + shared = i::handle(i::SharedFunctionInfo::cast(self->code()), isolate);
|
| + } else {
|
| + shared = i::handle(i::JSFunction::cast(self->code())->shared(), isolate);
|
| + }
|
| + i::Handle<i::FixedArray> module_requests(
|
| + shared->scope_info()->ModuleDescriptorInfo()->module_requests(), isolate);
|
| + CHECK_LT(i, module_requests->length());
|
| + return ToApiHandle<String>(i::handle(module_requests->get(i), isolate));
|
| +}
|
| +
|
| +bool Module::Instantiate(Local<Context> v8_context,
|
| + Module::ResolveCallback callback,
|
| + Local<Value> callback_data) {
|
| i::Handle<i::Module> self = Utils::OpenHandle(this);
|
| i::Isolate* isolate = self->GetIsolate();
|
|
|
| @@ -1899,8 +1932,38 @@ bool Module::Instantiate(Local<Context> v8_context) {
|
| shared, handle(context->native_context(), isolate));
|
| self->set_code(*function);
|
|
|
| - // TODO(adamk): This could fail in the future when Instantiate
|
| - // does linking.
|
| + for (int i = 0, length = GetModuleRequestsLength(); i < length; ++i) {
|
| + Local<Module> import;
|
| + // TODO(adamk): Revisit these failure cases once d8 knows how to
|
| + // persist a module_map across multiple top-level module loads, as
|
| + // the current module is left in a "half-instantiated" state.
|
| + if (!callback(v8_context, GetModuleRequest(i), Utils::ToLocal(self),
|
| + callback_data)
|
| + .ToLocal(&import)) {
|
| + // TODO(adamk): Throw an exception.
|
| + return false;
|
| + }
|
| + if (!import->Instantiate(v8_context, callback, callback_data)) {
|
| + return false;
|
| + }
|
| + self->requested_modules()->set(i, *Utils::OpenHandle(*import));
|
| + }
|
| +
|
| + // TODO(neis): This will create multiple cells for the same local variable if
|
| + // exported under multiple names, which is wrong but cannot be observed at the
|
| + // moment. This will be fixed by doing the full-fledged linking here once we
|
| + // get there.
|
| + i::Handle<i::FixedArray> regular_exports = i::handle(
|
| + shared->scope_info()->ModuleDescriptorInfo()->regular_exports(), isolate);
|
| + for (int i = 0, length = regular_exports->length(); i < length; ++i) {
|
| + i::Handle<i::ModuleInfoEntry> entry =
|
| + i::handle(i::ModuleInfoEntry::cast(regular_exports->get(i)), isolate);
|
| + DCHECK(entry->import_name()->IsUndefined(isolate));
|
| + i::Handle<i::String> export_name =
|
| + handle(i::String::cast(entry->export_name()), isolate);
|
| + i::Module::CreateExport(self, export_name);
|
| + }
|
| +
|
| return true;
|
| }
|
|
|
| @@ -1916,6 +1979,19 @@ MaybeLocal<Value> Module::Evaluate(Local<Context> context) {
|
| // It's an API error to call Evaluate before Instantiate.
|
| CHECK(self->code()->IsJSFunction());
|
|
|
| + // Each module can only be evaluated once.
|
| + if (self->evaluated()) return Undefined(reinterpret_cast<Isolate*>(isolate));
|
| + self->set_evaluated(true);
|
| +
|
| + i::Handle<i::FixedArray> requested_modules(self->requested_modules(),
|
| + isolate);
|
| + for (int i = 0, length = requested_modules->length(); i < length; ++i) {
|
| + i::Handle<i::Module> import(i::Module::cast(requested_modules->get(i)),
|
| + isolate);
|
| + MaybeLocal<Value> maybe_result = Utils::ToLocal(import)->Evaluate(context);
|
| + if (maybe_result.IsEmpty()) return maybe_result;
|
| + }
|
| +
|
| i::Handle<i::JSFunction> function(i::JSFunction::cast(self->code()), isolate);
|
| DCHECK_EQ(i::MODULE_SCOPE, function->shared()->scope_info()->scope_type());
|
| i::Handle<i::Object> receiver = isolate->factory()->undefined_value();
|
| @@ -2049,23 +2125,6 @@ MaybeLocal<Module> ScriptCompiler::CompileModule(Isolate* isolate,
|
|
|
| i::Handle<i::SharedFunctionInfo> shared = Utils::OpenHandle(*unbound);
|
| i::Handle<i::Module> module = i_isolate->factory()->NewModule(shared);
|
| -
|
| - // TODO(neis): This will create multiple cells for the same local variable if
|
| - // exported under multiple names, which is wrong but cannot be observed at the
|
| - // moment. This will be fixed by doing the full-fledged linking here once we
|
| - // get there.
|
| - i::Handle<i::FixedArray> regular_exports =
|
| - i::handle(shared->scope_info()->ModuleDescriptorInfo()->regular_exports(),
|
| - i_isolate);
|
| - for (int i = 0, length = regular_exports->length(); i < length; ++i) {
|
| - i::Handle<i::ModuleInfoEntry> entry =
|
| - i::handle(i::ModuleInfoEntry::cast(regular_exports->get(i)), i_isolate);
|
| - DCHECK(entry->import_name()->IsUndefined(i_isolate));
|
| - i::Handle<i::String> export_name =
|
| - handle(i::String::cast(entry->export_name()), i_isolate);
|
| - i::Module::CreateExport(module, export_name);
|
| - }
|
| -
|
| return ToApiHandle<Module>(module);
|
| }
|
|
|
|
|