Skip to content

Commit 1cfbf60

Browse files
committed
browser: fix module URL resolution
1 parent 48d01c0 commit 1cfbf60

File tree

1 file changed

+25
-4
lines changed

1 file changed

+25
-4
lines changed

src/browser/browser.zig

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)