Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 35 additions & 12 deletions src/browser/browser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -184,17 +184,18 @@ pub const Session = struct {
_ = referrer;

const self: *Session = @ptrCast(@alignCast(ctx));

if (self.page == null) {
return error.NoPage;
}
const page = &(self.page orelse return error.NoPage);

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

Expand Down Expand Up @@ -283,6 +284,10 @@ pub const Page = struct {

raw_data: ?[]const u8 = null,

// current_script is the script currently evaluated by the page.
// current_script could by fetch module to resolve module's url to fetch.
current_script: ?*const Script = null,

fn init(session: *Session) Page {
return .{
.session = session,
Expand Down Expand Up @@ -504,7 +509,7 @@ pub const Page = struct {
// > page.
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#notes
try parser.documentHTMLSetCurrentScript(html_doc, @ptrCast(e));
self.evalScript(script) catch |err| log.warn("evaljs: {any}", .{err});
self.evalScript(&script) catch |err| log.warn("evaljs: {any}", .{err});
try parser.documentHTMLSetCurrentScript(html_doc, null);
}

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

Expand All @@ -545,7 +550,10 @@ pub const Page = struct {
// evalScript evaluates the src in priority.
// if no src is present, we evaluate the text source.
// https://html.spec.whatwg.org/multipage/scripting.html#script-processing-model
fn evalScript(self: *Page, s: Script) !void {
fn evalScript(self: *Page, s: *const Script) !void {
self.current_script = s;
defer self.current_script = null;

// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-classic-script
const opt_src = try parser.elementGetAttribute(s.element, "src");
if (opt_src) |src| {
Expand Down Expand Up @@ -590,13 +598,27 @@ pub const Page = struct {
JsErr,
};

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

var buffer: [1024]u8 = undefined;
var b: []u8 = buffer[0..];
const u = try std.Uri.resolve_inplace(self.uri, src, &b);

var res_src = src;

// if a base path is given, we resolve src using base.
if (base) |_base| {
const dir = std.fs.path.dirname(_base);
if (dir) |_dir| {
res_src = try std.fs.path.resolve(arena, &.{ _dir, src });
}
}

const u = try std.Uri.resolve_inplace(self.uri, res_src, &b);

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

// fetchScript senf a GET request to the src and execute the script
// received.
fn fetchScript(self: *Page, s: Script) !void {
fn fetchScript(self: *const Page, s: *const Script) !void {
const arena = self.arena;
const body = try self.fetchData(arena, s.src);

const body = try self.fetchData(arena, s.src, null);
// TODO: change to &self.session.env when
// https://github.com/lightpanda-io/zig-js-runtime/pull/285 lands
try s.eval(arena, self.session.env, body);
Expand Down