Add CDP Node Registry

This expands on the existing CDP node work used in  DOM.search. It introduces
a node registry to track all nodes returned to the client and give lookups to
get a node from a Id or a *parser.node.

Eventually, the goal is to have the Registry emit the DOM.setChildNodes event
whenever necessary, as well as support many of the missing DOM actions.

Added tests to existing search handlers. Reworked search a little bit to avoid
some unnecessary allocations and to hook it into the registry.

The generated Node is currently incomplete. The parentId is missing, the
children are missing. Also, we still need to associate the v8 ObjectId to the
node.

Finally, I moved all action handlers into a nested "domain" folder.
This commit is contained in:
Karl Seguin
2025-03-28 18:25:51 +08:00
parent 82e67b7550
commit be9e953971
19 changed files with 663 additions and 325 deletions

View File

@@ -17,7 +17,6 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
const std = @import("std");
const json = std.json;
const Allocator = std.mem.Allocator;
@@ -27,9 +26,13 @@ const main = @import("cdp.zig");
const parser = @import("netsurf");
const App = @import("../app.zig").App;
pub const expectEqual = std.testing.expectEqual;
pub const expectError = std.testing.expectError;
pub const expectString = std.testing.expectEqualStrings;
pub const allocator = @import("../testing.zig").allocator;
pub const expectEqual = @import("../testing.zig").expectEqual;
pub const expectError = @import("../testing.zig").expectError;
pub const expectEqualSlices = @import("../testing.zig").expectEqualSlices;
pub const Document = @import("../testing.zig").Document;
const Browser = struct {
session: ?*Session = null,
@@ -51,11 +54,11 @@ const Browser = struct {
return error.MockBrowserSessionAlreadyExists;
}
const allocator = self.arena.allocator();
self.session = try allocator.create(Session);
const arena = self.arena.allocator();
self.session = try arena.create(Session);
self.session.?.* = .{
.page = null,
.allocator = allocator,
.arena = arena,
};
return self.session.?;
}
@@ -70,7 +73,7 @@ const Browser = struct {
const Session = struct {
page: ?Page = null,
allocator: Allocator,
arena: Allocator,
pub fn currentPage(self: *Session) ?*Page {
return &(self.page orelse return null);
@@ -82,7 +85,7 @@ const Session = struct {
}
self.page = .{
.session = self,
.aux_data = try self.allocator.dupe(u8, aux_data orelse ""),
.aux_data = try self.arena.dupe(u8, aux_data orelse ""),
};
return &self.page.?;
}
@@ -114,9 +117,9 @@ const Client = struct {
sent: std.ArrayListUnmanaged(json.Value) = .{},
serialized: std.ArrayListUnmanaged([]const u8) = .{},
fn init(allocator: Allocator) Client {
fn init(alloc: Allocator) Client {
return .{
.allocator = allocator,
.allocator = alloc,
};
}
@@ -165,6 +168,7 @@ const TestContext = struct {
id: ?[]const u8 = null,
target_id: ?[]const u8 = null,
session_id: ?[]const u8 = null,
html: ?[]const u8 = null,
};
pub fn loadBrowserContext(self: *TestContext, opts: BrowserContextOpts) !*main.BrowserContext(TestCDP) {
var c = self.cdp();
@@ -189,6 +193,13 @@ const TestContext = struct {
if (opts.session_id) |sid| {
bc.session_id = sid;
}
if (opts.html) |html| {
parser.deinit();
try parser.init();
const page = try bc.session.createPage(null);
page.doc = (try Document.init(html)).doc;
}
return bc;
}