Skip to content
Merged
Show file tree
Hide file tree
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
3 changes: 1 addition & 2 deletions src/browser/browser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ pub const Browser = struct {
http_client: *http.Client,
session_pool: SessionPool,
page_arena: std.heap.ArenaAllocator,
pub const EnvType = Env;

const SessionPool = std.heap.MemoryPool(Session);

Expand Down Expand Up @@ -97,7 +96,7 @@ pub const Browser = struct {
return session;
}

fn closeSession(self: *Browser) void {
pub fn closeSession(self: *Browser) void {
if (self.session) |session| {
session.deinit();
self.session_pool.destroy(session);
Expand Down
12 changes: 6 additions & 6 deletions src/cdp/cdp.zig
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ const Allocator = std.mem.Allocator;
const json = std.json;

const App = @import("../app.zig").App;
const Env = @import("../browser/env.zig").Env;
const asUint = @import("../str/parser.zig").asUint;
const Browser = @import("../browser/browser.zig").Browser;
const Session = @import("../browser/browser.zig").Session;
const Incrementing = @import("../id.zig").Incrementing;
const Notification = @import("../notification.zig").Notification;

Expand All @@ -32,8 +35,6 @@ pub const LOADER_ID = "LOADERID24DD2FD56CF1EF33C965C79C";

pub const CDP = CDPT(struct {
const Client = *@import("../server.zig").Client;
const Browser = @import("../browser/browser.zig").Browser;
const Session = @import("../browser/browser.zig").Session;
});

const SessionIdGen = Incrementing(u32, "SID");
Expand Down Expand Up @@ -69,8 +70,6 @@ pub fn CDPT(comptime TypeProvider: type) type {
message_arena: std.heap.ArenaAllocator,

const Self = @This();
pub const Browser = TypeProvider.Browser;
pub const Session = TypeProvider.Session;

pub fn init(app: *App, client: TypeProvider.Client) !Self {
const allocator = app.allocator;
Expand Down Expand Up @@ -247,6 +246,7 @@ pub fn CDPT(comptime TypeProvider: type) type {
return false;
}
bc.deinit();
self.browser.closeSession();
self.browser_context_pool.destroy(bc);
self.browser_context = null;
return true;
Expand Down Expand Up @@ -282,7 +282,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
// all intents and purpose, from CDP's point of view our Browser and
// our Session more or less maps to a BrowserContext. THIS HAS ZERO
// RELATION TO SESSION_ID
session: *CDP_T.Session,
session: *Session,

// Points to the session arena
arena: Allocator,
Expand All @@ -309,7 +309,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
node_registry: Node.Registry,
node_search_list: Node.Search.List,

isolated_world: ?IsolatedWorld(CDP_T.Browser.EnvType),
isolated_world: ?IsolatedWorld(Env),

const Self = @This();

Expand Down
2 changes: 1 addition & 1 deletion src/cdp/domains/target.zig
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ test "cdp.target: createTarget" {
try testing.expectEqual(true, bc.target_id != null);
try testing.expectEqual(
\\{"isDefault":true,"type":"default","frameId":"TID-1"}
, bc.session.page.?.aux_data);
, bc.session.aux_data);

try ctx.expectSentResult(.{ .targetId = bc.target_id.? }, .{ .id = 10 });
try ctx.expectSentEvent("Target.targetCreated", .{ .targetInfo = .{ .url = "about:blank", .title = "about:blank", .attached = false, .type = "page", .canAccessOpener = false, .browserContextId = "BID-9", .targetId = bc.target_id.? } }, .{});
Expand Down
211 changes: 11 additions & 200 deletions src/cdp/testing.zig
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
const std = @import("std");
const json = std.json;
const Allocator = std.mem.Allocator;
const ArenaAllocator = std.heap.ArenaAllocator;

const Testing = @This();

Expand All @@ -36,196 +37,6 @@ pub const expectEqualSlices = base.expectEqualSlices;

pub const Document = @import("../testing.zig").Document;

const Browser = struct {
session: ?*Session = null,
arena: std.heap.ArenaAllocator,
env: Env,
pub const EnvType = Env;

pub fn init(app: *App) !Browser {
return .{
.arena = std.heap.ArenaAllocator.init(app.allocator),
.env = Env{},
};
}

pub fn deinit(self: *Browser) void {
self.arena.deinit();
}

pub fn newSession(self: *Browser, ctx: anytype) !*Session {
_ = ctx;
if (self.session != null) {
return error.MockBrowserSessionAlreadyExists;
}
const arena = self.arena.allocator();
const executor = arena.create(Env.Executor) catch unreachable;
self.session = try arena.create(Session);
self.session.?.* = .{
.page = null,
.arena = self.arena,
.executor = executor,
.inspector = .{},
.state = 0,
};
return self.session.?;
}

pub fn hasSession(self: *const Browser, session_id: []const u8) bool {
const session = self.session orelse return false;
return std.mem.eql(u8, session.id, session_id);
}

pub fn runMicrotasks(_: *const Browser) void {}
};

const Session = struct {
page: ?Page = null,
arena: std.heap.ArenaAllocator,
executor: *Env.Executor,
inspector: Inspector,
state: i32,

pub fn currentPage(self: *Session) ?*Page {
return &(self.page orelse return null);
}

pub fn createPage(self: *Session, aux_data: ?[]const u8) !*Page {
if (self.page != null) {
return error.MockBrowserPageAlreadyExists;
}
self.page = .{
.session = self,
.url = URL.parse("https://lightpanda.io/", null) catch unreachable,
.aux_data = try self.arena.allocator().dupe(u8, aux_data orelse ""),
};
return &self.page.?;
}

pub fn removePage(self: *Session) void {
self.page = null;
}

pub fn callInspector(self: *Session, msg: []const u8) void {
_ = self;
_ = msg;
}
};

const Env = struct {
pub const Executor = MockExecutor;
pub fn startExecutor(self: *Env, comptime Global: type, state: anytype, module_loader: anytype, kind: anytype) !*Executor {
_ = self;
_ = Global;
_ = state;
_ = module_loader;
_ = kind;
return error.MockExecutor;
}
pub fn stopExecutor(self: *Env, executor: *Executor) void {
_ = self;
_ = executor;
}
};
const MockExecutor = struct {
context: Context,

pub fn startScope(self: *MockExecutor, global: anytype) !void {
_ = self;
_ = global;
}
pub fn endScope(self: *MockExecutor) void {
_ = self;
}
};
const Context = struct {
pub fn debugContextId(self: Context) i32 {
_ = self;
return 0;
}
};

const Inspector = struct {
pub fn getRemoteObject(
self: *const Inspector,
executor: *Env.Executor,
group: []const u8,
value: anytype,
) !RemoteObject {
_ = self;
_ = executor;
_ = group;
_ = value;
return RemoteObject{};
}
pub fn getNodePtr(self: Inspector, alloc: std.mem.Allocator, object_id: []const u8) !?*anyopaque {
_ = self;
_ = object_id;
return try alloc.create(i32);
}
pub fn contextCreated(
self: *const Inspector,
executor: *const Env.Executor,
name: []const u8,
origin: []const u8,
aux_data: ?[]const u8,
is_default_context: bool,
) void {
_ = self;
_ = executor;
_ = name;
_ = origin;
_ = aux_data;
_ = is_default_context;
}
};

const RemoteObject = struct {
pub fn deinit(self: RemoteObject) void {
_ = self;
}
pub fn getType(self: RemoteObject, alloc: std.mem.Allocator) ![:0]const u8 {
_ = self;
_ = alloc;
return "TheType";
}
pub fn getSubtype(self: RemoteObject, alloc: std.mem.Allocator) ![:0]const u8 {
_ = self;
_ = alloc;
return "TheSubtype";
}
pub fn getClassName(self: RemoteObject, alloc: std.mem.Allocator) ![:0]const u8 {
_ = self;
_ = alloc;
return "TheClassName";
}
pub fn getDescription(self: RemoteObject, alloc: std.mem.Allocator) ![:0]const u8 {
_ = self;
_ = alloc;
return "TheDescription";
}
pub fn getObjectId(self: RemoteObject, alloc: std.mem.Allocator) ![:0]const u8 {
_ = self;
_ = alloc;
return "TheObjectId";
}
};

const Page = struct {
session: *Session,
url: ?URL = null,
aux_data: []const u8 = "",
doc: ?*parser.Document = null,

pub fn navigate(_: *Page, url: URL, opts: anytype) !void {
_ = url;
_ = opts;
}

const MouseEvent = @import("../browser/browser.zig").Page.MouseEvent;
pub fn mouseEvent(_: *Page, _: MouseEvent) !void {}
};

const Client = struct {
allocator: Allocator,
sent: std.ArrayListUnmanaged(json.Value) = .{},
Expand All @@ -246,19 +57,22 @@ const Client = struct {
const value = try json.parseFromSliceLeaky(json.Value, self.allocator, serialized, .{});
try self.sent.append(self.allocator, value);
}

pub fn sendJSONRaw(self: *Client, _: ArenaAllocator, buf: std.ArrayListUnmanaged(u8)) !void {
const value = try json.parseFromSliceLeaky(json.Value, self.allocator, buf.items, .{});
try self.sent.append(self.allocator, value);
}
};

const TestCDP = main.CDPT(struct {
pub const Browser = Testing.Browser;
pub const Session = Testing.Session;
pub const Client = *Testing.Client;
});

const TestContext = struct {
app: *App,
client: ?Client = null,
cdp_: ?TestCDP = null,
arena: std.heap.ArenaAllocator,
arena: ArenaAllocator,

pub fn deinit(self: *TestContext) void {
if (self.cdp_) |*c| {
Expand All @@ -273,7 +87,7 @@ const TestContext = struct {
self.client = Client.init(self.arena.allocator());
// Don't use the arena here. We want to detect leaks in CDP.
// The arena is only for test-specific stuff
self.cdp_ = try TestCDP.init(self.app, &self.client.?);
self.cdp_ = TestCDP.init(self.app, &self.client.?) catch unreachable;
}
return &self.cdp_.?;
}
Expand All @@ -286,11 +100,8 @@ const TestContext = struct {
};
pub fn loadBrowserContext(self: *TestContext, opts: BrowserContextOpts) !*main.BrowserContext(TestCDP) {
var c = self.cdp();
c.browser.session = null;

if (c.browser_context) |bc| {
bc.deinit();
c.browser_context = null;
_ = c.disposeBrowserContext(bc.id);
}

_ = try c.createBrowserContext();
Expand Down Expand Up @@ -410,7 +221,7 @@ const TestContext = struct {
pub fn context() TestContext {
return .{
.app = App.init(std.testing.allocator, .{ .run_mode = .serve }) catch unreachable,
.arena = std.heap.ArenaAllocator.init(std.testing.allocator),
.arena = ArenaAllocator.init(std.testing.allocator),
};
}

Expand All @@ -420,7 +231,7 @@ pub fn context() TestContext {
// json and check if the two are equal.
// Except serializing to JSON isn't deterministic.
// So we serialize the JSON then we deserialize to json.Value. And then we can
// compare our anytype expection with the json.Value that we captured
// compare our anytype expectation with the json.Value that we captured

fn compareExpectedToSent(expected: []const u8, actual: json.Value) !bool {
const expected_value = try std.json.parseFromSlice(json.Value, std.testing.allocator, expected, .{});
Expand Down
Loading