@@ -194,7 +194,7 @@ pub const Session = struct {
194194 // Use the page_arena for this, which has a more appropriate lifetime
195195 // and which has more retained memory between sessions and pages.
196196 const arena = self .browser .page_arena .allocator ();
197- const body = try self .page .? .fetchData (arena , specifier );
197+ const body = try self .page .? .fetchData (arena , specifier , self . page .? . current_script .? . src );
198198 return self .env .compileModule (body , specifier );
199199 }
200200
@@ -283,6 +283,10 @@ pub const Page = struct {
283283
284284 raw_data : ? []const u8 = null ,
285285
286+ // current_script is the script currently evaluated by the page.
287+ // current_script could by fetch module to resolve module's url to fetch.
288+ current_script : ? * const Script = null ,
289+
286290 fn init (session : * Session ) Page {
287291 return .{
288292 .session = session ,
@@ -546,6 +550,9 @@ pub const Page = struct {
546550 // if no src is present, we evaluate the text source.
547551 // https://html.spec.whatwg.org/multipage/scripting.html#script-processing-model
548552 fn evalScript (self : * Page , s : Script ) ! void {
553+ self .current_script = & s ;
554+ defer self .current_script = null ;
555+
549556 // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-classic-script
550557 const opt_src = try parser .elementGetAttribute (s .element , "src" );
551558 if (opt_src ) | src | {
@@ -590,13 +597,27 @@ pub const Page = struct {
590597 JsErr ,
591598 };
592599
600+ // fetchData returns the data corresponding to the src target.
601+ // It resolves src using the page's uri.
602+ // If a base path is given, src is resolved according to the base first.
593603 // the caller owns the returned string
594- fn fetchData (self : * Page , arena : Allocator , src : []const u8 ) ! []const u8 {
604+ fn fetchData (self : * Page , arena : Allocator , src : []const u8 , base : ? [] const u8 ) ! []const u8 {
595605 log .debug ("starting fetch {s}" , .{src });
596606
597607 var buffer : [1024 ]u8 = undefined ;
598608 var b : []u8 = buffer [0.. ];
599- const u = try std .Uri .resolve_inplace (self .uri , src , & b );
609+
610+ var res_src = src ;
611+
612+ // if a base path is given, we resolve src using base.
613+ if (base ) | _base | {
614+ const dir = std .fs .path .dirname (_base );
615+ if (dir ) | _dir | {
616+ res_src = try std .fs .path .resolve (arena , &.{ _dir , src });
617+ }
618+ }
619+
620+ const u = try std .Uri .resolve_inplace (self .uri , res_src , & b );
600621
601622 var fetchres = try self .session .loader .get (arena , u );
602623 defer fetchres .deinit ();
@@ -624,7 +645,7 @@ pub const Page = struct {
624645 // received.
625646 fn fetchScript (self : * Page , s : Script ) ! void {
626647 const arena = self .arena ;
627- const body = try self .fetchData (arena , s .src );
648+ const body = try self .fetchData (arena , s .src , null );
628649 // TODO: change to &self.session.env when
629650 // https://github.com/lightpanda-io/zig-js-runtime/pull/285 lands
630651 try s .eval (arena , self .session .env , body );
0 commit comments