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();
if (@hasDecl(E, "Build") and @hasDecl(E.Build, "created")) {
@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;
};
}

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();
}
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
// descendants.
pub fn getInnerText(self: *Element, writer: *std.Io.Writer) !void {
@@ -1091,16 +1100,7 @@ pub const JsApi = struct {
return null;
}
pub const localName = bridge.accessor(_localName, 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 localName = bridge.accessor(Element.getLocalName, null, .{});
pub const id = bridge.accessor(Element.getId, Element.setId, .{});
pub const className = bridge.accessor(Element.getClassName, Element.setClassName, .{});
pub const classList = bridge.accessor(Element.getClassList, null, .{});

View File

@@ -98,7 +98,6 @@ pub const JsApi = struct {
pub const name = "Navigator";
pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined;
// ZIGDOM (currently no optimization for empty types)
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) {
.element => |el| el.getTagNameSpec(&page.buf),
.element => |el| el.getTagNameSpec(buf),
.cdata => |cd| switch (cd._type) {
.text => "#text",
.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) {
.element => 1,
.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 {
switch (self._type) {
.cdata => |cdata| {
@@ -770,8 +777,12 @@ pub const JsApi = struct {
pub const DOCUMENT_POSITION_CONTAINED_BY = bridge.property(0x10);
pub const DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = bridge.property(0x20);
pub const nodeName = bridge.accessor(Node.getNodeName, null, .{});
pub const nodeType = bridge.accessor(Node.nodeType, null, .{});
pub const nodeName = bridge.accessor(struct{
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, .{});
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!
// nodeType values (1=ELEMENT, 3=TEXT, 9=DOCUMENT, etc.) need to map to
// 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 node_type_bit: u32 = @as(u32, 1) << @intCast(bit_position);
return (what_to_show & node_type_bit) != 0;

View File

@@ -42,7 +42,6 @@ _resolver: js.PersistentPromiseResolver,
pub const Input = Request.Input;
pub const InitOpts = Request.InitOpts;
// @ZIGDOM just enough to get campfire demo working
pub fn init(input: Input, options: ?InitOpts, page: *Page) !js.Promise {
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 {
// @ZIGMOD
// const Node = @import("Node.zig");
const Node = @import("Node.zig");
return struct {
id: []const u8,
@@ -328,9 +327,8 @@ pub fn BrowserContext(comptime CDP_T: type) type {
security_origin: []const u8,
page_life_cycle_events: bool,
secure_context_type: []const u8,
// @ZIGDOM
// node_registry: Node.Registry,
// node_search_list: Node.Search.List,
node_registry: Node.Registry,
node_search_list: Node.Search.List,
inspector: js.Inspector,
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);
// @ZIGDOM
// var registry = Node.Registry.init(allocator);
// errdefer registry.deinit();
var registry = Node.Registry.init(allocator);
errdefer registry.deinit();
self.* = .{
.id = id,
@@ -378,9 +375,8 @@ pub fn BrowserContext(comptime CDP_T: type) type {
.secure_context_type = "Secure", // TODO = enum
.loader_id = LOADER_ID,
.page_life_cycle_events = false, // TODO; Target based value
// @ZIGDOM
// .node_registry = registry,
// .node_search_list = undefined,
.node_registry = registry,
.node_search_list = undefined,
.isolated_worlds = .empty,
.inspector = inspector,
.notification_arena = cdp.notification_arena.allocator(),
@@ -388,8 +384,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
.captured_responses = .empty,
.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();
try cdp.browser.notification.register(.page_remove, self, onPageRemove);
@@ -424,9 +419,8 @@ pub fn BrowserContext(comptime CDP_T: type) type {
world.deinit();
}
self.isolated_worlds.clearRetainingCapacity();
// @ZIGDOM
// self.node_registry.deinit();
// self.node_search_list.deinit();
self.node_registry.deinit();
self.node_search_list.deinit();
self.cdp.browser.notification.unregisterAll(self);
if (self.http_proxy_changed) {
@@ -440,10 +434,8 @@ pub fn BrowserContext(comptime CDP_T: type) type {
}
pub fn reset(self: *Self) void {
// @ZIGDOM
_ = self;
// self.node_registry.reset();
// 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 {
@@ -462,15 +454,14 @@ pub fn BrowserContext(comptime CDP_T: type) type {
return world;
}
// @ZIGDOM
// pub fn nodeWriter(self: *Self, root: *const Node, opts: Node.Writer.Opts) Node.Writer {
// return .{
// .root = root,
// .depth = opts.depth,
// .exclude_root = opts.exclude_root,
// .registry = &self.node_registry,
// };
// }
pub fn nodeWriter(self: *Self, root: *const Node, opts: Node.Writer.Opts) Node.Writer {
return .{
.root = root,
.depth = opts.depth,
.exclude_root = opts.exclude_root,
.registry = &self.node_registry,
};
}
pub fn getURL(self: *const Self) ?[:0]const u8 {
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 expectError = base.expectError;
pub const expectEqualSlices = base.expectEqualSlices;
pub const Document = @import("../testing.zig").Document;
pub const pageTest = base.pageTest;
const Client = struct {
allocator: Allocator,

View File

@@ -40,6 +40,7 @@ const App = @import("App.zig");
const js = @import("browser/js/js.zig");
const Browser = @import("browser/Browser.zig");
const Session = @import("browser/Session.zig");
const Page = @import("browser/Page.zig");
// Merged std.testing.expectEqual and std.testing.expectString
// 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 {
std.testing.refAllDecls(@This());
}