@@ -24,10 +24,12 @@ IN THE SOFTWARE.
24
24
#include < stdlib.h>
25
25
#include < string.h>
26
26
#include < string>
27
+ #include < map>
27
28
28
29
#include " binding.h"
29
30
#include " libplatform/libplatform.h"
30
31
#include " v8.h"
32
+ #include " _cgo_export.h"
31
33
32
34
using namespace v8 ;
33
35
@@ -37,6 +39,7 @@ struct worker_s {
37
39
std::string last_exception;
38
40
Persistent<Function> recv;
39
41
Persistent<Context> context;
42
+ std::map<std::string, Eternal<Module>> modules;
40
43
};
41
44
42
45
// Extracts a C string from a V8 Utf8Value.
@@ -90,6 +93,30 @@ void ExitOnPromiseRejectCallback(PromiseRejectMessage promise_reject_message) {
90
93
exit (1 );
91
94
}
92
95
96
+ MaybeLocal<Module> ResolveCallback (Local<Context> context,
97
+ Local<String> specifier,
98
+ Local<Module> referrer) {
99
+ auto isolate = Isolate::GetCurrent ();
100
+ worker* w = (worker*)isolate->GetData (0 );
101
+
102
+ HandleScope handle_scope (isolate);
103
+
104
+ String::Utf8Value str (specifier);
105
+ const char * moduleName = *str;
106
+
107
+ if (w->modules .count (moduleName) == 0 ) {
108
+ std::string out;
109
+ out.append (" Module (" );
110
+ out.append (moduleName);
111
+ out.append (" ) has not been loaded" );
112
+ out.append (" \n " );
113
+ w->last_exception = out;
114
+ return MaybeLocal<Module>();
115
+ }
116
+
117
+ return w->modules [moduleName].Get (isolate);
118
+ }
119
+
93
120
// Exception details will be appended to the first argument.
94
121
std::string ExceptionString (worker* w, TryCatch* try_catch) {
95
122
std::string out;
@@ -151,7 +178,6 @@ std::string ExceptionString(worker* w, TryCatch* try_catch) {
151
178
}
152
179
153
180
extern " C" {
154
- #include " _cgo_export.h"
155
181
156
182
const char * worker_version () { return V8::GetVersion (); }
157
183
@@ -197,6 +223,90 @@ int worker_load(worker* w, char* name_s, char* source_s) {
197
223
return 0 ;
198
224
}
199
225
226
+ int worker_load_module (worker* w, char * name_s, char * source_s, int callback_index) {
227
+ Locker locker (w->isolate );
228
+ Isolate::Scope isolate_scope (w->isolate );
229
+ HandleScope handle_scope (w->isolate );
230
+
231
+ Local<Context> context = Local<Context>::New (w->isolate , w->context );
232
+ Context::Scope context_scope (context);
233
+
234
+ TryCatch try_catch (w->isolate );
235
+
236
+ Local<String> name = String::NewFromUtf8 (w->isolate , name_s);
237
+ Local<String> source_text = String::NewFromUtf8 (w->isolate , source_s);
238
+
239
+ Local<Integer> line_offset = Integer::New (w->isolate , 0 );
240
+ Local<Integer> column_offset = Integer::New (w->isolate , 0 );
241
+ Local<Boolean > is_cross_origin = True (w->isolate );
242
+ Local<Integer> script_id = Local<Integer>();
243
+ Local<Value> source_map_url = Local<Value>();
244
+ Local<Boolean > is_opaque = False (w->isolate );
245
+ Local<Boolean > is_wasm = False (w->isolate );
246
+ Local<Boolean > is_module = True (w->isolate );
247
+
248
+ ScriptOrigin origin (name, line_offset, column_offset, is_cross_origin,
249
+ script_id, source_map_url, is_opaque, is_wasm, is_module);
250
+
251
+ ScriptCompiler::Source source (source_text, origin);
252
+ Local<Module> module;
253
+
254
+ if (!ScriptCompiler::CompileModule (w->isolate , &source).ToLocal (&module)) {
255
+ assert (try_catch.HasCaught ());
256
+ w->last_exception = ExceptionString (w, &try_catch);
257
+ return 1 ;
258
+ }
259
+
260
+ for (int i = 0 ; i < module->GetModuleRequestsLength (); i++) {
261
+ Local<String> dependency = module->GetModuleRequest (i);
262
+ String::Utf8Value str (dependency);
263
+ char * dependencySpecifier = *str;
264
+
265
+ // If we've already loaded the module, skip resolving it.
266
+ // TODO: Is there ever a time when the specifier would be the same
267
+ // but would need to be resolved again?
268
+ if (w->modules .count (dependencySpecifier) != 0 ) {
269
+ continue ;
270
+ }
271
+
272
+ int ret = ResolveModule (dependencySpecifier, name_s, callback_index);
273
+ if (ret != 0 ) {
274
+ // TODO: Use module->GetModuleRequestLocation() to get source locations
275
+ std::string out;
276
+ out.append (" Module (" );
277
+ out.append (dependencySpecifier);
278
+ out.append (" ) has not been loaded" );
279
+ out.append (" \n " );
280
+ w->last_exception = out;
281
+ return ret;
282
+ }
283
+ }
284
+
285
+ Eternal<Module> persModule (w->isolate , module);
286
+ w->modules [name_s] = persModule;
287
+
288
+ Maybe<bool > ok = module->InstantiateModule (context, ResolveCallback);
289
+
290
+ if (!ok.FromMaybe (false )) {
291
+ // TODO: I'm not sure if this is needed
292
+ if (try_catch.HasCaught ()) {
293
+ assert (try_catch.HasCaught ());
294
+ w->last_exception = ExceptionString (w, &try_catch);
295
+ }
296
+ return 2 ;
297
+ }
298
+
299
+ MaybeLocal<Value> result = module->Evaluate (context);
300
+
301
+ if (result.IsEmpty ()) {
302
+ assert (try_catch.HasCaught ());
303
+ w->last_exception = ExceptionString (w, &try_catch);
304
+ return 2 ;
305
+ }
306
+
307
+ return 0 ;
308
+ }
309
+
200
310
void Print (const FunctionCallbackInfo<Value>& args) {
201
311
bool first = true ;
202
312
for (int i = 0 ; i < args.Length (); i++) {
0 commit comments