Skip to content

Commit 671dbcf

Browse files
Merge pull request #470 from lightpanda-io/resove-module
browser: fix module URL resolution
2 parents 3608165 + 087a7b5 commit 671dbcf

File tree

1 file changed

+35
-12
lines changed

1 file changed

+35
-12
lines changed

src/browser/browser.zig

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -184,17 +184,18 @@ pub const Session = struct {
184184
_ = referrer;
185185

186186
const self: *Session = @ptrCast(@alignCast(ctx));
187-
188-
if (self.page == null) {
189-
return error.NoPage;
190-
}
187+
const page = &(self.page orelse return error.NoPage);
191188

192189
log.debug("fetch module: specifier: {s}", .{specifier});
193190
// fetchModule is called within the context of processing a page.
194191
// Use the page_arena for this, which has a more appropriate lifetime
195192
// and which has more retained memory between sessions and pages.
196193
const arena = self.browser.page_arena.allocator();
197-
const body = try self.page.?.fetchData(arena, specifier);
194+
const body = try page.fetchData(
195+
arena,
196+
specifier,
197+
if (page.current_script) |s| s.src else null,
198+
);
198199
return self.env.compileModule(body, specifier);
199200
}
200201

@@ -283,6 +284,10 @@ pub const Page = struct {
283284

284285
raw_data: ?[]const u8 = null,
285286

287+
// current_script is the script currently evaluated by the page.
288+
// current_script could by fetch module to resolve module's url to fetch.
289+
current_script: ?*const Script = null,
290+
286291
fn init(session: *Session) Page {
287292
return .{
288293
.session = session,
@@ -504,7 +509,7 @@ pub const Page = struct {
504509
// > page.
505510
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#notes
506511
try parser.documentHTMLSetCurrentScript(html_doc, @ptrCast(e));
507-
self.evalScript(script) catch |err| log.warn("evaljs: {any}", .{err});
512+
self.evalScript(&script) catch |err| log.warn("evaljs: {any}", .{err});
508513
try parser.documentHTMLSetCurrentScript(html_doc, null);
509514
}
510515

@@ -523,7 +528,7 @@ pub const Page = struct {
523528
// eval async scripts.
524529
for (sasync.items) |s| {
525530
try parser.documentHTMLSetCurrentScript(html_doc, @ptrCast(s.element));
526-
self.evalScript(s) catch |err| log.warn("evaljs: {any}", .{err});
531+
self.evalScript(&s) catch |err| log.warn("evaljs: {any}", .{err});
527532
try parser.documentHTMLSetCurrentScript(html_doc, null);
528533
}
529534

@@ -545,7 +550,10 @@ pub const Page = struct {
545550
// evalScript evaluates the src in priority.
546551
// if no src is present, we evaluate the text source.
547552
// https://html.spec.whatwg.org/multipage/scripting.html#script-processing-model
548-
fn evalScript(self: *Page, s: Script) !void {
553+
fn evalScript(self: *Page, s: *const Script) !void {
554+
self.current_script = s;
555+
defer self.current_script = null;
556+
549557
// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-classic-script
550558
const opt_src = try parser.elementGetAttribute(s.element, "src");
551559
if (opt_src) |src| {
@@ -590,13 +598,27 @@ pub const Page = struct {
590598
JsErr,
591599
};
592600

601+
// fetchData returns the data corresponding to the src target.
602+
// It resolves src using the page's uri.
603+
// If a base path is given, src is resolved according to the base first.
593604
// the caller owns the returned string
594-
fn fetchData(self: *Page, arena: Allocator, src: []const u8) ![]const u8 {
605+
fn fetchData(self: *const Page, arena: Allocator, src: []const u8, base: ?[]const u8) ![]const u8 {
595606
log.debug("starting fetch {s}", .{src});
596607

597608
var buffer: [1024]u8 = undefined;
598609
var b: []u8 = buffer[0..];
599-
const u = try std.Uri.resolve_inplace(self.uri, src, &b);
610+
611+
var res_src = src;
612+
613+
// if a base path is given, we resolve src using base.
614+
if (base) |_base| {
615+
const dir = std.fs.path.dirname(_base);
616+
if (dir) |_dir| {
617+
res_src = try std.fs.path.resolve(arena, &.{ _dir, src });
618+
}
619+
}
620+
621+
const u = try std.Uri.resolve_inplace(self.uri, res_src, &b);
600622

601623
var fetchres = try self.session.loader.get(arena, u);
602624
defer fetchres.deinit();
@@ -622,9 +644,10 @@ pub const Page = struct {
622644

623645
// fetchScript senf a GET request to the src and execute the script
624646
// received.
625-
fn fetchScript(self: *Page, s: Script) !void {
647+
fn fetchScript(self: *const Page, s: *const Script) !void {
626648
const arena = self.arena;
627-
const body = try self.fetchData(arena, s.src);
649+
650+
const body = try self.fetchData(arena, s.src, null);
628651
// TODO: change to &self.session.env when
629652
// https://github.com/lightpanda-io/zig-js-runtime/pull/285 lands
630653
try s.eval(arena, self.session.env, body);

0 commit comments

Comments
 (0)