re-enable CDP node registry

This commit is contained in:
Karl Seguin
2025-12-09 11:50:33 +08:00
parent 49c0e95664
commit 9132bc2375
13 changed files with 653 additions and 624 deletions

View File

@@ -1276,7 +1276,7 @@ fn createHtmlElementT(self: *Page, comptime E: type, namespace: Element.Namespac
const node = element.asNode(); const node = element.asNode();
if (@hasDecl(E, "Build") and @hasDecl(E.Build, "created")) { if (@hasDecl(E, "Build") and @hasDecl(E.Build, "created")) {
@call(.auto, @field(E.Build, "created"), .{ node, self }) catch |err| { @call(.auto, @field(E.Build, "created"), .{ node, self }) catch |err| {
log.err(.page, "build.created", .{ .tag = node.getNodeName(self), .err = err }); log.err(.page, "build.created", .{ .tag = node.getNodeName(&self.buf), .err = err });
return err; return err;
}; };
} }

View File

@@ -0,0 +1 @@
<a id=a1>link1</a><div id=d2><p>other</p></div>

View File

@@ -0,0 +1 @@
<a id=a1></a><a id=a2></a>

View File

@@ -0,0 +1 @@
<a id=a1></a><div id=d2><a id=a2></a></div>

View File

@@ -225,6 +225,15 @@ pub fn getNamespaceURI(self: *const Element) []const u8 {
return self._namespace.toUri(); return self._namespace.toUri();
} }
pub fn getLocalName(self: *Element) []const u8 {
const name = self.getTagNameLower();
if (std.mem.indexOfPos(u8, name, 0, ":")) |pos| {
return name[pos + 1 ..];
}
return name;
}
// innerText represents the **rendered** text content of a node and its // innerText represents the **rendered** text content of a node and its
// descendants. // descendants.
pub fn getInnerText(self: *Element, writer: *std.Io.Writer) !void { pub fn getInnerText(self: *Element, writer: *std.Io.Writer) !void {
@@ -1091,16 +1100,7 @@ pub const JsApi = struct {
return null; return null;
} }
pub const localName = bridge.accessor(_localName, null, .{}); pub const localName = bridge.accessor(Element.getLocalName, null, .{});
fn _localName(self: *Element) []const u8 {
const name = self.getTagNameLower();
if (std.mem.indexOfPos(u8, name, 0, ":")) |pos| {
return name[pos + 1 ..];
}
return name;
}
pub const id = bridge.accessor(Element.getId, Element.setId, .{}); pub const id = bridge.accessor(Element.getId, Element.setId, .{});
pub const className = bridge.accessor(Element.getClassName, Element.setClassName, .{}); pub const className = bridge.accessor(Element.getClassName, Element.setClassName, .{});
pub const classList = bridge.accessor(Element.getClassList, null, .{}); pub const classList = bridge.accessor(Element.getClassList, null, .{});

View File

@@ -98,7 +98,6 @@ pub const JsApi = struct {
pub const name = "Navigator"; pub const name = "Navigator";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
// ZIGDOM (currently no optimization for empty types)
pub const empty_with_no_proto = true; pub const empty_with_no_proto = true;
}; };

View File

@@ -256,9 +256,9 @@ pub fn setTextContent(self: *Node, data: []const u8, page: *Page) !void {
} }
} }
pub fn getNodeName(self: *const Node, page: *Page) []const u8 { pub fn getNodeName(self: *const Node, buf: []u8) []const u8 {
return switch (self._type) { return switch (self._type) {
.element => |el| el.getTagNameSpec(&page.buf), .element => |el| el.getTagNameSpec(buf),
.cdata => |cd| switch (cd._type) { .cdata => |cd| switch (cd._type) {
.text => "#text", .text => "#text",
.cdata_section => "#cdata-section", .cdata_section => "#cdata-section",
@@ -271,7 +271,7 @@ pub fn getNodeName(self: *const Node, page: *Page) []const u8 {
}; };
} }
pub fn nodeType(self: *const Node) u8 { pub fn getNodeType(self: *const Node) u8 {
return switch (self._type) { return switch (self._type) {
.element => 1, .element => 1,
.attribute => 2, .attribute => 2,
@@ -491,6 +491,13 @@ pub fn childrenIterator(self: *Node) NodeIterator {
}; };
} }
pub fn getChildrenCount(self: *Node) usize {
return switch (self._type) {
.element, .document, .document_fragment => self.getLength(),
.document_type, .attribute, .cdata => return 0,
};
}
pub fn getLength(self: *Node) u32 { pub fn getLength(self: *Node) u32 {
switch (self._type) { switch (self._type) {
.cdata => |cdata| { .cdata => |cdata| {
@@ -770,8 +777,12 @@ pub const JsApi = struct {
pub const DOCUMENT_POSITION_CONTAINED_BY = bridge.property(0x10); pub const DOCUMENT_POSITION_CONTAINED_BY = bridge.property(0x10);
pub const DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = bridge.property(0x20); pub const DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = bridge.property(0x20);
pub const nodeName = bridge.accessor(Node.getNodeName, null, .{}); pub const nodeName = bridge.accessor(struct{
pub const nodeType = bridge.accessor(Node.nodeType, null, .{}); fn wrap(self: *const Node, page: *Page) []const u8 {
return self.getNodeName(&page.buf);
}
}.wrap, null, .{});
pub const nodeType = bridge.accessor(Node.getNodeType, null, .{});
pub const textContent = bridge.accessor(_textContext, Node.setTextContent, .{}); pub const textContent = bridge.accessor(_textContext, Node.setTextContent, .{});
fn _textContext(self: *Node, page: *const Page) !?[]const u8 { fn _textContext(self: *Node, page: *const Page) !?[]const u8 {

View File

@@ -72,7 +72,7 @@ pub fn shouldShow(node: *const Node, what_to_show: u32) bool {
// TODO: Test this mapping thoroughly! // TODO: Test this mapping thoroughly!
// nodeType values (1=ELEMENT, 3=TEXT, 9=DOCUMENT, etc.) need to map to // nodeType values (1=ELEMENT, 3=TEXT, 9=DOCUMENT, etc.) need to map to
// SHOW_* bitmask positions (0x1, 0x4, 0x100, etc.) // SHOW_* bitmask positions (0x1, 0x4, 0x100, etc.)
const node_type_value = node.nodeType(); const node_type_value = node.getNodeType();
const bit_position = node_type_value - 1; const bit_position = node_type_value - 1;
const node_type_bit: u32 = @as(u32, 1) << @intCast(bit_position); const node_type_bit: u32 = @as(u32, 1) << @intCast(bit_position);
return (what_to_show & node_type_bit) != 0; return (what_to_show & node_type_bit) != 0;

View File

@@ -42,7 +42,6 @@ _resolver: js.PersistentPromiseResolver,
pub const Input = Request.Input; pub const Input = Request.Input;
pub const InitOpts = Request.InitOpts; pub const InitOpts = Request.InitOpts;
// @ZIGDOM just enough to get campfire demo working
pub fn init(input: Input, options: ?InitOpts, page: *Page) !js.Promise { pub fn init(input: Input, options: ?InitOpts, page: *Page) !js.Promise {
const request = try Request.init(input, options, page); const request = try Request.init(input, options, page);

File diff suppressed because it is too large Load Diff

View File

@@ -287,8 +287,7 @@ pub fn CDPT(comptime TypeProvider: type) type {
} }
pub fn BrowserContext(comptime CDP_T: type) type { pub fn BrowserContext(comptime CDP_T: type) type {
// @ZIGMOD const Node = @import("Node.zig");
// const Node = @import("Node.zig");
return struct { return struct {
id: []const u8, id: []const u8,
@@ -328,9 +327,8 @@ pub fn BrowserContext(comptime CDP_T: type) type {
security_origin: []const u8, security_origin: []const u8,
page_life_cycle_events: bool, page_life_cycle_events: bool,
secure_context_type: []const u8, secure_context_type: []const u8,
// @ZIGDOM node_registry: Node.Registry,
// node_registry: Node.Registry, node_search_list: Node.Search.List,
// node_search_list: Node.Search.List,
inspector: js.Inspector, inspector: js.Inspector,
isolated_worlds: std.ArrayListUnmanaged(IsolatedWorld), isolated_worlds: std.ArrayListUnmanaged(IsolatedWorld),
@@ -363,9 +361,8 @@ pub fn BrowserContext(comptime CDP_T: type) type {
const inspector = try cdp.browser.env.newInspector(arena, self); const inspector = try cdp.browser.env.newInspector(arena, self);
// @ZIGDOM var registry = Node.Registry.init(allocator);
// var registry = Node.Registry.init(allocator); errdefer registry.deinit();
// errdefer registry.deinit();
self.* = .{ self.* = .{
.id = id, .id = id,
@@ -378,9 +375,8 @@ pub fn BrowserContext(comptime CDP_T: type) type {
.secure_context_type = "Secure", // TODO = enum .secure_context_type = "Secure", // TODO = enum
.loader_id = LOADER_ID, .loader_id = LOADER_ID,
.page_life_cycle_events = false, // TODO; Target based value .page_life_cycle_events = false, // TODO; Target based value
// @ZIGDOM .node_registry = registry,
// .node_registry = registry, .node_search_list = undefined,
// .node_search_list = undefined,
.isolated_worlds = .empty, .isolated_worlds = .empty,
.inspector = inspector, .inspector = inspector,
.notification_arena = cdp.notification_arena.allocator(), .notification_arena = cdp.notification_arena.allocator(),
@@ -388,8 +384,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
.captured_responses = .empty, .captured_responses = .empty,
.log_interceptor = LogInterceptor(Self).init(allocator, self), .log_interceptor = LogInterceptor(Self).init(allocator, self),
}; };
// ZIGDOM self.node_search_list = Node.Search.List.init(allocator, &self.node_registry);
// self.node_search_list = Node.Search.List.init(allocator, &self.node_registry);
errdefer self.deinit(); errdefer self.deinit();
try cdp.browser.notification.register(.page_remove, self, onPageRemove); try cdp.browser.notification.register(.page_remove, self, onPageRemove);
@@ -424,9 +419,8 @@ pub fn BrowserContext(comptime CDP_T: type) type {
world.deinit(); world.deinit();
} }
self.isolated_worlds.clearRetainingCapacity(); self.isolated_worlds.clearRetainingCapacity();
// @ZIGDOM self.node_registry.deinit();
// self.node_registry.deinit(); self.node_search_list.deinit();
// self.node_search_list.deinit();
self.cdp.browser.notification.unregisterAll(self); self.cdp.browser.notification.unregisterAll(self);
if (self.http_proxy_changed) { if (self.http_proxy_changed) {
@@ -440,10 +434,8 @@ pub fn BrowserContext(comptime CDP_T: type) type {
} }
pub fn reset(self: *Self) void { pub fn reset(self: *Self) void {
// @ZIGDOM self.node_registry.reset();
_ = self; self.node_search_list.reset();
// self.node_registry.reset();
// self.node_search_list.reset();
} }
pub fn createIsolatedWorld(self: *Self, world_name: []const u8, grant_universal_access: bool) !*IsolatedWorld { pub fn createIsolatedWorld(self: *Self, world_name: []const u8, grant_universal_access: bool) !*IsolatedWorld {
@@ -462,15 +454,14 @@ pub fn BrowserContext(comptime CDP_T: type) type {
return world; return world;
} }
// @ZIGDOM pub fn nodeWriter(self: *Self, root: *const Node, opts: Node.Writer.Opts) Node.Writer {
// pub fn nodeWriter(self: *Self, root: *const Node, opts: Node.Writer.Opts) Node.Writer { return .{
// return .{ .root = root,
// .root = root, .depth = opts.depth,
// .depth = opts.depth, .exclude_root = opts.exclude_root,
// .exclude_root = opts.exclude_root, .registry = &self.node_registry,
// .registry = &self.node_registry, };
// }; }
// }
pub fn getURL(self: *const Self) ?[:0]const u8 { pub fn getURL(self: *const Self) ?[:0]const u8 {
const page = self.session.currentPage() orelse return null; const page = self.session.currentPage() orelse return null;

View File

@@ -32,8 +32,7 @@ pub const expect = std.testing.expect;
pub const expectEqual = base.expectEqual; pub const expectEqual = base.expectEqual;
pub const expectError = base.expectError; pub const expectError = base.expectError;
pub const expectEqualSlices = base.expectEqualSlices; pub const expectEqualSlices = base.expectEqualSlices;
pub const pageTest = base.pageTest;
pub const Document = @import("../testing.zig").Document;
const Client = struct { const Client = struct {
allocator: Allocator, allocator: Allocator,

View File

@@ -40,6 +40,7 @@ const App = @import("App.zig");
const js = @import("browser/js/js.zig"); const js = @import("browser/js/js.zig");
const Browser = @import("browser/Browser.zig"); const Browser = @import("browser/Browser.zig");
const Session = @import("browser/Session.zig"); const Session = @import("browser/Session.zig");
const Page = @import("browser/Page.zig");
// Merged std.testing.expectEqual and std.testing.expectString // Merged std.testing.expectEqual and std.testing.expectString
// can be useful when testing fields of an anytype an you don't know // can be useful when testing fields of an anytype an you don't know
@@ -415,6 +416,27 @@ fn runWebApiTest(test_file: [:0]const u8) !void {
}; };
} }
// Used by a few CDP tests - wouldn't be sad to see this go.
pub fn pageTest(comptime test_file: []const u8) !*Page {
const page = try test_session.createPage();
errdefer test_session.removePage();
const url = try std.fmt.allocPrintSentinel(
arena_allocator,
"http://127.0.0.1:9582/{s}{s}",
.{ WEB_API_TEST_ROOT, test_file },
0,
);
try page.navigate(url, .{});
test_session.fetchWait(2000);
page._session.browser.runMicrotasks();
page._session.browser.runMessageLoop();
return page;
}
test { test {
std.testing.refAllDecls(@This()); std.testing.refAllDecls(@This());
} }