@@ -29,6 +29,7 @@ const Mime = @import("mime.zig");
2929const jsruntime = @import ("jsruntime" );
3030const Loop = jsruntime .Loop ;
3131const Env = jsruntime .Env ;
32+ const Module = jsruntime .Module ;
3233
3334const apiweb = @import ("../apiweb.zig" );
3435
@@ -125,6 +126,21 @@ pub const Session = struct {
125126 try self .env .load (& self .jstypes );
126127 }
127128
129+ fn fetchModule (ctx : * anyopaque , referrer : ? jsruntime.Module , specifier : []const u8 ) ! jsruntime.Module {
130+ _ = referrer ;
131+
132+ const self : * Session = @ptrCast (@alignCast (ctx ));
133+
134+ if (self .page == null ) return error .NoPage ;
135+
136+ log .debug ("fetch module: specifier: {s}" , .{specifier });
137+ const alloc = self .arena .allocator ();
138+ const body = try self .page .? .fetchData (alloc , specifier );
139+ defer alloc .free (body );
140+
141+ return self .env .compileModule (body , specifier );
142+ }
143+
128144 fn deinit (self : * Session ) void {
129145 if (self .page ) | * p | p .end ();
130146
@@ -362,6 +378,9 @@ pub const Page = struct {
362378 log .debug ("start js env" , .{});
363379 try self .session .env .start ();
364380
381+ // register the module loader
382+ try self .session .env .setModuleLoadFn (self .session , Session .fetchModule );
383+
365384 // load polyfills
366385 try polyfill .load (alloc , self .session .env );
367386
@@ -530,33 +549,39 @@ pub const Page = struct {
530549 JsErr ,
531550 };
532551
533- // fetchScript senf a GET request to the src and execute the script
534- // received.
535- fn fetchScript (self : * Page , s : Script ) ! void {
536- const alloc = self .arena .allocator ();
537-
538- log .debug ("starting fetch script {s}" , .{s .src });
552+ // the caller owns the returned string
553+ fn fetchData (self : * Page , alloc : std.mem.Allocator , src : []const u8 ) ! []const u8 {
554+ log .debug ("starting fetch {s}" , .{src });
539555
540556 var buffer : [1024 ]u8 = undefined ;
541557 var b : []u8 = buffer [0.. ];
542- const u = try std .Uri .resolve_inplace (self .uri , s . src , & b );
558+ const u = try std .Uri .resolve_inplace (self .uri , src , & b );
543559
544560 var fetchres = try self .session .loader .get (alloc , u );
545561 defer fetchres .deinit ();
546562
547563 const resp = fetchres .req .response ;
548564
549- log .info ("fetch script {any}: {d}" , .{ u , resp .status });
565+ log .info ("fetch {any}: {d}" , .{ u , resp .status });
550566
551567 if (resp .status != .ok ) return FetchError .BadStatusCode ;
552568
553569 // TODO check content-type
554570 const body = try fetchres .req .reader ().readAllAlloc (alloc , 16 * 1024 * 1024 );
555- defer alloc .free (body );
556571
557572 // check no body
558573 if (body .len == 0 ) return FetchError .NoBody ;
559574
575+ return body ;
576+ }
577+
578+ // fetchScript senf a GET request to the src and execute the script
579+ // received.
580+ fn fetchScript (self : * Page , s : Script ) ! void {
581+ const alloc = self .arena .allocator ();
582+ const body = try self .fetchData (alloc , s .src );
583+ defer alloc .free (body );
584+
560585 try s .eval (alloc , self .session .env , body );
561586 }
562587
0 commit comments