diff --git a/src/browser/browser.zig b/src/browser/browser.zig index 42c705b1..d09b9d95 100644 --- a/src/browser/browser.zig +++ b/src/browser/browser.zig @@ -49,29 +49,33 @@ const log = std.log.scoped(.browser); // A browser contains only one session. // TODO allow multiple sessions per browser. 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 // doesn't use it directly... _ = vm; - return Browser{ - .session = try Session.init(alloc, loop, "about:blank"), - }; + try Session.init(&self.session, alloc, loop, uri); } pub fn deinit(self: *Browser) void { 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 = try Session.init(alloc, loop, "about:blank"); + try Session.init(&self.session, alloc, loop, uri); } pub fn currentSession(self: *Browser) *Session { - return self.session; + return &self.session; } }; @@ -99,13 +103,12 @@ pub const Session = struct { window: Window, // TODO move the shed to the browser? storageShed: storage.Shed, - page: ?*Page = null, + _page: ?Page = null, httpClient: HttpClient, jstypes: [Types.len]usize = undefined, - fn init(alloc: std.mem.Allocator, loop: *Loop, uri: []const u8) !*Session { - var self = try alloc.create(Session); + fn init(self: *Session, alloc: std.mem.Allocator, loop: *Loop, uri: []const u8) !void { self.* = Session{ .uri = uri, .alloc = alloc, @@ -116,15 +119,13 @@ pub const Session = struct { .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 }; try self.env.load(&self.jstypes); - - return self; } fn deinit(self: *Session) void { - if (self.page) |page| page.end(); + if (self._page) |*p| p.end(); if (self.inspector) |inspector| { inspector.deinit(self.alloc); @@ -136,7 +137,6 @@ pub const Session = struct { self.httpClient.deinit(); self.loader.deinit(); self.storageShed.deinit(); - self.alloc.destroy(self); } pub fn initInspector( @@ -158,8 +158,17 @@ pub const Session = struct { } } - pub fn createPage(self: *Session) !Page { - return Page.init(self.alloc, self); + pub fn createPage(self: *Session) !void { + 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, fn init( + self: *Page, alloc: std.mem.Allocator, session: *Session, - ) !Page { - if (session.page != null) return error.SessionPageExists; - var page = Page{ + ) void { + self.* = .{ .arena = std.heap.ArenaAllocator.init(alloc), .session = session, }; - session.page = &page; - return page; } // reset js env and mem arena. diff --git a/src/cdp/page.zig b/src/cdp/page.zig index ae59c85d..a76b4e7f 100644 --- a/src/cdp/page.zig +++ b/src/cdp/page.zig @@ -281,7 +281,7 @@ fn navigate( try sendEvent(alloc, ctx, "Runtime.executionContextsCleared", void, {}, msg.sessionID); // Launch navigate - var p = try ctx.browser.currentSession().createPage(); + try ctx.browser.session.createPage(); ctx.state.executionContextId += 1; const auxData = try std.fmt.allocPrint( alloc, @@ -290,7 +290,7 @@ fn navigate( .{ctx.state.frameID}, ); defer alloc.free(auxData); - _ = try p.navigate(params.url, auxData); + try ctx.browser.session.page().navigate(params.url, auxData); // Events diff --git a/src/main.zig b/src/main.zig index fc486afb..08745b30 100644 --- a/src/main.zig +++ b/src/main.zig @@ -224,18 +224,10 @@ pub fn main() !void { defer srv.close(); std.log.info("Listening on: {s}:{d}...", .{ host, port }); - // create v8 vm - const vm = jsruntime.VM.init(); - defer vm.deinit(); - // loop var loop = try jsruntime.Loop.init(arena.allocator()); defer loop.deinit(); - // browser - var browser = try Browser.init(arena.allocator(), &loop, vm); - defer browser.deinit(); - // 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)); } diff --git a/src/main_get.zig b/src/main_get.zig index 8368dd47..2814c077 100644 --- a/src/main_get.zig +++ b/src/main_get.zig @@ -83,18 +83,18 @@ pub fn main() !void { var loop = try jsruntime.Loop.init(allocator); defer loop.deinit(); - var browser = try Browser.init(allocator, &loop, vm); + var browser = Browser{}; + try Browser.init(&browser, allocator, &loop, vm); defer browser.deinit(); - var page = try browser.currentSession().createPage(); - defer page.deinit(); + try browser.session.createPage(); - try page.navigate(url, null); - defer page.end(); + try browser.session.page().navigate(url, null); + defer browser.session.page().end(); - try page.wait(); + try browser.session.page().wait(); if (dump) { - try page.dump(std.io.getStdOut()); + try browser.session.page().dump(std.io.getStdOut()); } } diff --git a/src/server.zig b/src/server.zig index 4f925b2b..e2eece71 100644 --- a/src/server.zig +++ b/src/server.zig @@ -249,12 +249,12 @@ pub const Ctx = struct { // allocator of the current session inline fn alloc(self: *Ctx) std.mem.Allocator { - return self.browser.currentSession().alloc; + return self.browser.session.alloc; } // JS env of the current session inline fn env(self: Ctx) jsruntime.Env { - return self.browser.currentSession().env; + return self.browser.session.env; } // actions @@ -300,7 +300,7 @@ pub const Ctx = struct { fn newSession(self: *Ctx) !void { try self.browser.newSession(self.alloc(), self.loop); - try self.browser.currentSession().initInspector( + try self.browser.session.initInspector( self, Ctx.onInspectorResp, Ctx.onInspectorNotif, @@ -398,12 +398,21 @@ pub fn sendSync(ctx: *Ctx, msg: []const u8) !void { // ------ pub fn listen( - browser: *Browser, + alloc: std.mem.Allocator, loop: *jsruntime.Loop, server_socket: std.posix.socket_t, timeout: u64, ) 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 var read_buf: [BufReadSize]u8 = undefined; var msg_buf = try MsgBuffer.init(loop.alloc, BufReadSize * 256); // 256KB @@ -417,7 +426,7 @@ pub fn listen( // for accepting connections and receving messages var ctx = Ctx{ .loop = loop, - .browser = browser, + .browser = &browser, .sessionNew = true, .read_buf = &read_buf, .msg_buf = &msg_buf, @@ -426,7 +435,7 @@ pub fn listen( .conn_completion = &conn_completion, .timeout_completion = &timeout_completion, }; - try browser.currentSession().initInspector( + try browser.session.initInspector( &ctx, Ctx.onInspectorResp, Ctx.onInspectorNotif,