summaryrefslogtreecommitdiff
path: root/js/src/builtin/ModuleObject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/builtin/ModuleObject.cpp')
-rw-r--r--js/src/builtin/ModuleObject.cpp102
1 files changed, 102 insertions, 0 deletions
diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp
index 760fb9c04d..e40ba110b8 100644
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -5,6 +5,7 @@
#include "builtin/ModuleObject.h"
+#include "builtin/Promise.h"
#include "builtin/SelfHostingDefines.h"
#include "frontend/ParseNode.h"
#include "frontend/SharedContext.h"
@@ -1030,6 +1031,22 @@ ModuleObject::Evaluate(JSContext* cx, HandleModuleObject self)
return InvokeSelfHostedMethod(cx, self, cx->names().ModuleEvaluate);
}
+/* static */ ModuleNamespaceObject*
+ModuleObject::GetOrCreateModuleNamespace(JSContext* cx, HandleModuleObject self)
+{
+ FixedInvokeArgs<1> args(cx);
+ args[0].setObject(*self);
+
+ RootedValue result(cx);
+ if (!CallSelfHostedFunction(cx, cx->names().GetModuleNamespace, UndefinedHandleValue, args,
+ &result))
+ {
+ return nullptr;
+ }
+
+ return &result.toObject().as<ModuleNamespaceObject>();
+}
+
DEFINE_GETTER_FUNCTIONS(ModuleObject, namespace_, NamespaceSlot)
DEFINE_GETTER_FUNCTIONS(ModuleObject, status, StatusSlot)
DEFINE_GETTER_FUNCTIONS(ModuleObject, evaluationError, EvaluationErrorSlot)
@@ -1519,3 +1536,88 @@ js::GetOrCreateModuleMetaObject(JSContext* cx, HandleObject moduleArg)
return metaObject;
}
+
+JSObject*
+js::CallModuleResolveHook(JSContext* cx, HandleValue referencingPrivate, HandleString specifier)
+{
+ JS::ModuleResolveHook moduleResolveHook = cx->runtime()->moduleResolveHook;
+ if (!moduleResolveHook) {
+ JS_ReportErrorASCII(cx, "Module resolve hook not set");
+ return nullptr;
+ }
+
+ RootedObject result(cx, moduleResolveHook(cx, referencingPrivate, specifier));
+ if (!result) {
+ return nullptr;
+ }
+
+ if (!result->is<ModuleObject>()) {
+ JS_ReportErrorASCII(cx, "Module resolve hook did not return Module object");
+ return nullptr;
+ }
+
+ return result;
+}
+
+JSObject*
+js::StartDynamicModuleImport(JSContext* cx, HandleValue referencingPrivate, HandleValue specifierArg)
+{
+ RootedObject promiseConstructor(cx, JS::GetPromiseConstructor(cx));
+ if (!promiseConstructor) {
+ return nullptr;
+ }
+
+ RootedObject promiseObject(cx, JS::NewPromiseObject(cx, nullptr));
+ if (!promiseObject) {
+ return nullptr;
+ }
+
+ Handle<PromiseObject*> promise = promiseObject.as<PromiseObject>();
+
+ RootedString specifier(cx, ToString(cx, specifierArg));
+ if (!specifier) {
+ if (!RejectPromiseWithPendingError(cx, promise))
+ return nullptr;
+ return promise;
+ }
+
+ JS::ModuleDynamicImportHook importHook = cx->runtime()->moduleDynamicImportHook;
+ MOZ_ASSERT(importHook);
+ if (!importHook(cx, referencingPrivate, specifier, promise)) {
+ if (!RejectPromiseWithPendingError(cx, promise))
+ return nullptr;
+ return promise;
+ }
+
+ return promise;
+}
+
+bool
+js::FinishDynamicModuleImport(JSContext* cx, HandleValue referencingPrivate, HandleString specifier,
+ HandleObject promiseArg)
+{
+ Handle<PromiseObject*> promise = promiseArg.as<PromiseObject>();
+
+ if (cx->isExceptionPending()) {
+ return RejectPromiseWithPendingError(cx, promise);
+ }
+
+ RootedObject result(cx, CallModuleResolveHook(cx, referencingPrivate, specifier));
+ if (!result) {
+ return RejectPromiseWithPendingError(cx, promise);
+ }
+
+ RootedModuleObject module(cx, &result->as<ModuleObject>());
+ if (module->status() != MODULE_STATUS_EVALUATED) {
+ JS_ReportErrorASCII(cx, "Unevaluated or errored module returned by module resolve hook");
+ return RejectPromiseWithPendingError(cx, promise);
+ }
+
+ RootedObject ns(cx, ModuleObject::GetOrCreateModuleNamespace(cx, module));
+ if (!ns) {
+ return RejectPromiseWithPendingError(cx, promise);
+ }
+
+ RootedValue value(cx, ObjectValue(*ns));
+ return PromiseObject::resolve(cx, promise, value);
+}