22#include < string>
33
44#include < jsapi.h>
5+ #include < jsfriendapi.h>
56
67#include < js/CompilationAndEvaluation.h>
8+ #include < js/Initialization.h>
79#include < js/Modules.h>
810#include < js/SourceText.h>
911
@@ -76,6 +78,13 @@ static JSObject* ExampleResolveHook(JSContext* cx,
7678 }
7779 }
7880
81+ if (filename == u" b" ) {
82+ mod = CompileExampleModule (cx, " b" , " export const C2 = 2;" );
83+ if (!mod) {
84+ return nullptr ;
85+ }
86+ }
87+
7988 // Register result in table.
8089 if (mod) {
8190 moduleRegistry.emplace (filename, JS::PersistentRootedObject (cx, mod));
@@ -86,7 +95,43 @@ static JSObject* ExampleResolveHook(JSContext* cx,
8695 return nullptr ;
8796}
8897
98+ // Callback for embedding to implement an asynchronous dynamic import. This must
99+ // do the same thing as the module resolve hook, but also link and evaluate the
100+ // module, and it must always call JS::FinishDynamicModuleImport when done.
101+ static bool ExampleDynamicImportHook (JSContext* cx,
102+ JS ::Handle<JS ::Value> referencingPrivate,
103+ JS ::Handle<JSObject*> moduleRequest,
104+ JS ::Handle<JSObject*> promise) {
105+ JS ::Rooted<JSObject*> mod{
106+ cx, ExampleResolveHook (cx, referencingPrivate, moduleRequest)};
107+ if (!mod || !JS::ModuleLink (cx, mod)) {
108+ return JS::FinishDynamicModuleImport (cx, nullptr , referencingPrivate,
109+ moduleRequest, promise);
110+ }
111+
112+ JS ::Rooted<JS ::Value> rval{cx};
113+ if (!JS::ModuleEvaluate (cx, mod, &rval)) {
114+ return JS::FinishDynamicModuleImport (cx, nullptr , referencingPrivate,
115+ moduleRequest, promise);
116+ }
117+ if (rval.isObject ()) {
118+ JS ::Rooted<JSObject*> evaluationPromise{cx, &rval.toObject ()};
119+ return JS::FinishDynamicModuleImport (
120+ cx, evaluationPromise, referencingPrivate, moduleRequest, promise);
121+ }
122+ return JS::FinishDynamicModuleImport (cx, nullptr , referencingPrivate,
123+ moduleRequest, promise);
124+ }
125+
89126static bool ModuleExample (JSContext* cx) {
127+ // In order to use dynamic imports, we need a job queue. We can use the
128+ // default SpiderMonkey job queue for this example, but a more sophisticated
129+ // embedding would use a custom job queue to schedule its own tasks.
130+ if (!js::UseInternalJobQueues (cx)) return false ;
131+
132+ // We must instantiate self-hosting *after* setting up job queue.
133+ if (!JS::InitSelfHostedCode (cx)) return false ;
134+
90135 JS ::RootedObject global (cx, boilerplate::CreateGlobal (cx));
91136 if (!global) {
92137 return false ;
@@ -95,11 +140,17 @@ static bool ModuleExample(JSContext* cx) {
95140 JSAutoRealm ar (cx, global);
96141
97142 // Register a hook in order to provide modules
98- JS::SetModuleResolveHook (JS_GetRuntime (cx), ExampleResolveHook);
143+ JSRuntime* rt = JS_GetRuntime (cx);
144+ JS::SetModuleResolveHook (rt, ExampleResolveHook);
145+ JS::SetModuleDynamicImportHook (rt, ExampleDynamicImportHook);
99146
100147 // Compile the top module.
101- JS ::RootedObject mod (
102- cx, CompileExampleModule (cx, " top" , " import {C1} from 'a';" ));
148+ static const char top_module_source[] = R"js(
149+ import {C1} from 'a';
150+ const {C2} = await import('b');
151+ )js" ;
152+ JS ::Rooted<JSObject*> mod{cx,
153+ CompileExampleModule (cx, " top" , top_module_source)};
103154 if (!mod) {
104155 boilerplate::ReportAndClearException (cx);
105156 return false ;
@@ -120,11 +171,22 @@ static bool ModuleExample(JSContext* cx) {
120171 return false ;
121172 }
122173
174+ js::RunJobs (cx);
175+ if (rval.isObject ()) {
176+ JS ::Rooted<JSObject*> evaluationPromise{cx, &rval.toObject ()};
177+ if (!JS::ThrowOnModuleEvaluationFailure (
178+ cx, evaluationPromise,
179+ JS ::ModuleErrorBehaviour::ThrowModuleErrorsSync)) {
180+ boilerplate::ReportAndClearException (cx);
181+ return false ;
182+ }
183+ }
184+
123185 return true ;
124186}
125187
126188int main (int argc, const char * argv[]) {
127- if (!boilerplate::RunExample (ModuleExample)) {
189+ if (!boilerplate::RunExample (ModuleExample, /* initSelfHosting = */ false )) {
128190 return 1 ;
129191 }
130192 return 0 ;
0 commit comments