Remove heap allocation for Session

And adapt to similar changes on zig-js-runtime for Env

Signed-off-by: Francis Bouvier <francis@lightpanda.io>
This commit is contained in:
Francis Bouvier
2024-10-15 15:52:48 +02:00
parent efca71510a
commit ea9af210f9
5 changed files with 55 additions and 47 deletions

View File

@@ -49,29 +49,33 @@ const log = std.log.scoped(.browser);
// A browser contains only one session. // A browser contains only one session.
// TODO allow multiple sessions per browser. // TODO allow multiple sessions per browser.
pub const Browser = struct { pub const Browser = struct {
session: *Session, session: Session = undefined,
pub fn init(alloc: std.mem.Allocator, loop: *Loop, vm: jsruntime.VM) !Browser { const uri = "about:blank";
pub fn init(self: *Browser, alloc: std.mem.Allocator, loop: *Loop, vm: jsruntime.VM) !void {
// We want to ensure the caller initialised a VM, but the browser // We want to ensure the caller initialised a VM, but the browser
// doesn't use it directly... // doesn't use it directly...
_ = vm; _ = vm;
return Browser{ try Session.init(&self.session, alloc, loop, uri);
.session = try Session.init(alloc, loop, "about:blank"),
};
} }
pub fn deinit(self: *Browser) void { pub fn deinit(self: *Browser) void {
self.session.deinit(); self.session.deinit();
} }
pub fn newSession(self: *Browser, alloc: std.mem.Allocator, loop: *jsruntime.Loop) !void { pub fn newSession(
self: *Browser,
alloc: std.mem.Allocator,
loop: *jsruntime.Loop,
) !void {
self.session.deinit(); self.session.deinit();
self.session = try Session.init(alloc, loop, "about:blank"); try Session.init(&self.session, alloc, loop, uri);
} }
pub fn currentSession(self: *Browser) *Session { pub fn currentSession(self: *Browser) *Session {
return self.session; return &self.session;
} }
}; };
@@ -99,13 +103,12 @@ pub const Session = struct {
window: Window, window: Window,
// TODO move the shed to the browser? // TODO move the shed to the browser?
storageShed: storage.Shed, storageShed: storage.Shed,
page: ?*Page = null, _page: ?Page = null,
httpClient: HttpClient, httpClient: HttpClient,
jstypes: [Types.len]usize = undefined, jstypes: [Types.len]usize = undefined,
fn init(alloc: std.mem.Allocator, loop: *Loop, uri: []const u8) !*Session { fn init(self: *Session, alloc: std.mem.Allocator, loop: *Loop, uri: []const u8) !void {
var self = try alloc.create(Session);
self.* = Session{ self.* = Session{
.uri = uri, .uri = uri,
.alloc = alloc, .alloc = alloc,
@@ -116,15 +119,13 @@ pub const Session = struct {
.httpClient = undefined, .httpClient = undefined,
}; };
self.env = try Env.init(self.arena.allocator(), loop, null); Env.init(&self.env, self.arena.allocator(), loop, null);
self.httpClient = .{ .allocator = alloc, .loop = loop }; self.httpClient = .{ .allocator = alloc, .loop = loop };
try self.env.load(&self.jstypes); try self.env.load(&self.jstypes);
return self;
} }
fn deinit(self: *Session) void { fn deinit(self: *Session) void {
if (self.page) |page| page.end(); if (self._page) |*p| p.end();
if (self.inspector) |inspector| { if (self.inspector) |inspector| {
inspector.deinit(self.alloc); inspector.deinit(self.alloc);
@@ -136,7 +137,6 @@ pub const Session = struct {
self.httpClient.deinit(); self.httpClient.deinit();
self.loader.deinit(); self.loader.deinit();
self.storageShed.deinit(); self.storageShed.deinit();
self.alloc.destroy(self);
} }
pub fn initInspector( pub fn initInspector(
@@ -158,8 +158,17 @@ pub const Session = struct {
} }
} }
pub fn createPage(self: *Session) !Page { pub fn createPage(self: *Session) !void {
return Page.init(self.alloc, self); if (self._page != null) return error.SessionPageExists;
const p: Page = undefined;
self._page = p;
Page.init(&self._page.?, self.alloc, self);
}
// shortcut
pub fn page(self: *Session) *Page {
if (self._page) |*p| return p;
@panic("No Page on this session");
} }
}; };
@@ -181,16 +190,14 @@ pub const Page = struct {
raw_data: ?[]const u8 = null, raw_data: ?[]const u8 = null,
fn init( fn init(
self: *Page,
alloc: std.mem.Allocator, alloc: std.mem.Allocator,
session: *Session, session: *Session,
) !Page { ) void {
if (session.page != null) return error.SessionPageExists; self.* = .{
var page = Page{
.arena = std.heap.ArenaAllocator.init(alloc), .arena = std.heap.ArenaAllocator.init(alloc),
.session = session, .session = session,
}; };
session.page = &page;
return page;
} }
// reset js env and mem arena. // reset js env and mem arena.

View File

@@ -281,7 +281,7 @@ fn navigate(
try sendEvent(alloc, ctx, "Runtime.executionContextsCleared", void, {}, msg.sessionID); try sendEvent(alloc, ctx, "Runtime.executionContextsCleared", void, {}, msg.sessionID);
// Launch navigate // Launch navigate
var p = try ctx.browser.currentSession().createPage(); try ctx.browser.session.createPage();
ctx.state.executionContextId += 1; ctx.state.executionContextId += 1;
const auxData = try std.fmt.allocPrint( const auxData = try std.fmt.allocPrint(
alloc, alloc,
@@ -290,7 +290,7 @@ fn navigate(
.{ctx.state.frameID}, .{ctx.state.frameID},
); );
defer alloc.free(auxData); defer alloc.free(auxData);
_ = try p.navigate(params.url, auxData); try ctx.browser.session.page().navigate(params.url, auxData);
// Events // Events

View File

@@ -224,18 +224,10 @@ pub fn main() !void {
defer srv.close(); defer srv.close();
std.log.info("Listening on: {s}:{d}...", .{ host, port }); std.log.info("Listening on: {s}:{d}...", .{ host, port });
// create v8 vm
const vm = jsruntime.VM.init();
defer vm.deinit();
// loop // loop
var loop = try jsruntime.Loop.init(arena.allocator()); var loop = try jsruntime.Loop.init(arena.allocator());
defer loop.deinit(); defer loop.deinit();
// browser
var browser = try Browser.init(arena.allocator(), &loop, vm);
defer browser.deinit();
// listen // listen
try server.listen(&browser, &loop, srv.sockfd.?, std.time.ns_per_s * @as(u64, timeout)); try server.listen(arena.allocator(), &loop, srv.sockfd.?, std.time.ns_per_s * @as(u64, timeout));
} }

View File

@@ -83,18 +83,18 @@ pub fn main() !void {
var loop = try jsruntime.Loop.init(allocator); var loop = try jsruntime.Loop.init(allocator);
defer loop.deinit(); defer loop.deinit();
var browser = try Browser.init(allocator, &loop, vm); var browser = Browser{};
try Browser.init(&browser, allocator, &loop, vm);
defer browser.deinit(); defer browser.deinit();
var page = try browser.currentSession().createPage(); try browser.session.createPage();
defer page.deinit();
try page.navigate(url, null); try browser.session.page().navigate(url, null);
defer page.end(); defer browser.session.page().end();
try page.wait(); try browser.session.page().wait();
if (dump) { if (dump) {
try page.dump(std.io.getStdOut()); try browser.session.page().dump(std.io.getStdOut());
} }
} }

View File

@@ -249,12 +249,12 @@ pub const Ctx = struct {
// allocator of the current session // allocator of the current session
inline fn alloc(self: *Ctx) std.mem.Allocator { inline fn alloc(self: *Ctx) std.mem.Allocator {
return self.browser.currentSession().alloc; return self.browser.session.alloc;
} }
// JS env of the current session // JS env of the current session
inline fn env(self: Ctx) jsruntime.Env { inline fn env(self: Ctx) jsruntime.Env {
return self.browser.currentSession().env; return self.browser.session.env;
} }
// actions // actions
@@ -300,7 +300,7 @@ pub const Ctx = struct {
fn newSession(self: *Ctx) !void { fn newSession(self: *Ctx) !void {
try self.browser.newSession(self.alloc(), self.loop); try self.browser.newSession(self.alloc(), self.loop);
try self.browser.currentSession().initInspector( try self.browser.session.initInspector(
self, self,
Ctx.onInspectorResp, Ctx.onInspectorResp,
Ctx.onInspectorNotif, Ctx.onInspectorNotif,
@@ -398,12 +398,21 @@ pub fn sendSync(ctx: *Ctx, msg: []const u8) !void {
// ------ // ------
pub fn listen( pub fn listen(
browser: *Browser, alloc: std.mem.Allocator,
loop: *jsruntime.Loop, loop: *jsruntime.Loop,
server_socket: std.posix.socket_t, server_socket: std.posix.socket_t,
timeout: u64, timeout: u64,
) anyerror!void { ) anyerror!void {
// create v8 vm
const vm = jsruntime.VM.init();
defer vm.deinit();
// browser
var browser: Browser = undefined;
try Browser.init(&browser, alloc, loop, vm);
defer browser.deinit();
// create buffers // create buffers
var read_buf: [BufReadSize]u8 = undefined; var read_buf: [BufReadSize]u8 = undefined;
var msg_buf = try MsgBuffer.init(loop.alloc, BufReadSize * 256); // 256KB var msg_buf = try MsgBuffer.init(loop.alloc, BufReadSize * 256); // 256KB
@@ -417,7 +426,7 @@ pub fn listen(
// for accepting connections and receving messages // for accepting connections and receving messages
var ctx = Ctx{ var ctx = Ctx{
.loop = loop, .loop = loop,
.browser = browser, .browser = &browser,
.sessionNew = true, .sessionNew = true,
.read_buf = &read_buf, .read_buf = &read_buf,
.msg_buf = &msg_buf, .msg_buf = &msg_buf,
@@ -426,7 +435,7 @@ pub fn listen(
.conn_completion = &conn_completion, .conn_completion = &conn_completion,
.timeout_completion = &timeout_completion, .timeout_completion = &timeout_completion,
}; };
try browser.currentSession().initInspector( try browser.session.initInspector(
&ctx, &ctx,
Ctx.onInspectorResp, Ctx.onInspectorResp,
Ctx.onInspectorNotif, Ctx.onInspectorNotif,