From 2ac63b69858b27c8643977f146e89233583880cc Mon Sep 17 00:00:00 2001 From: sjorsdonkers <72333389+sjorsdonkers@users.noreply.github.com> Date: Fri, 18 Apr 2025 11:53:53 +0200 Subject: [PATCH 1/3] describeNode --- src/cdp/domains/dom.zig | 33 +++++++++++++++++++++++++++++++++ src/cdp/testing.zig | 29 +++++++++++++++++++++++++---- src/runtime/js.zig | 13 +++++++++++++ 3 files changed, 71 insertions(+), 4 deletions(-) diff --git a/src/cdp/domains/dom.zig b/src/cdp/domains/dom.zig index e85ee7fe..396cf530 100644 --- a/src/cdp/domains/dom.zig +++ b/src/cdp/domains/dom.zig @@ -30,6 +30,7 @@ pub fn processMessage(cmd: anytype) !void { getSearchResults, discardSearchResults, resolveNode, + describeNode, }, cmd.input.action) orelse return error.UnknownMethod; switch (action) { @@ -39,6 +40,7 @@ pub fn processMessage(cmd: anytype) !void { .getSearchResults => return getSearchResults(cmd), .discardSearchResults => return discardSearchResults(cmd), .resolveNode => return resolveNode(cmd), + .describeNode => return describeNode(cmd), } } @@ -151,6 +153,37 @@ fn resolveNode(cmd: anytype) !void { } }, .{}); } +fn describeNode(cmd: anytype) !void { + const params = (try cmd.params(struct { + nodeId: ?Node.Id = null, + backendNodeId: ?Node.Id = null, + objectId: ?[]const u8 = null, + depth: u32 = 1, + pierce: bool = false, + })) orelse return error.InvalidParams; + if (params.backendNodeId != null or params.depth != 1 or params.pierce) { + return error.NotYetImplementedParams; + } + + const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; + + if (params.nodeId != null) { + const node = bc.node_registry.lookup_by_id.get(params.nodeId.?) orelse return error.NodeNotFound; + return cmd.sendResult(.{ .node = bc.nodeWriter(node, .{}) }, .{}); + } else if (params.objectId != null) { + + // Retrieve the object from which ever context it is in. + const js_value = try bc.session.inspector.getValueByObjectId(cmd.arena, bc.session.executor, params.objectId.?); + const entry = js_value.taggedAnyOpaque() orelse return error.ObjectIdIsNotANode; + const subtype = entry.subtype orelse return error.ObjectIdIsNotANode; + if (subtype != .node) return error.ObjectIdIsNotANode; + + const node = try bc.node_registry.register(@ptrCast(entry.ptr)); + return cmd.sendResult(.{ .node = bc.nodeWriter(node, .{}) }, .{}); + } + return error.MissingParams; +} + const testing = @import("../testing.zig"); test "cdp.dom: getSearchResults unknown search id" { diff --git a/src/cdp/testing.zig b/src/cdp/testing.zig index 1ca67c03..22fc9e8e 100644 --- a/src/cdp/testing.zig +++ b/src/cdp/testing.zig @@ -55,13 +55,13 @@ const Browser = struct { if (self.session != null) { return error.MockBrowserSessionAlreadyExists; } - const arena = self.arena.allocator(); + const executor = arena.create(Executor) catch unreachable; self.session = try arena.create(Session); self.session.?.* = .{ .page = null, .arena = arena, - .executor = .{}, + .executor = executor, .inspector = .{}, }; return self.session.?; @@ -78,7 +78,7 @@ const Browser = struct { const Session = struct { page: ?Page = null, arena: Allocator, - executor: Executor, + executor: *Executor, inspector: Inspector, pub fn currentPage(self: *Session) ?*Page { @@ -112,7 +112,7 @@ const Executor = struct {}; const Inspector = struct { pub fn getRemoteObject( self: *const Inspector, - executor: Executor, + executor: *Executor, group: []const u8, value: anytype, ) !RemoteObject { @@ -122,6 +122,27 @@ const Inspector = struct { _ = value; return RemoteObject{}; } + pub fn getValueByObjectId(self: Inspector, alloc: std.mem.Allocator, executor: *const Executor, object_id: []const u8) !Value { + _ = self; + _ = alloc; + _ = executor; + _ = object_id; + return .{}; + } +}; +const Value = struct { + pub fn taggedAnyOpaque(self: Value) ?*TaggedAnyOpaque { + _ = self; + return null; + } +}; +const TaggedAnyOpaque = struct { + ptr: *anyopaque, + subtype: ?SubType = .node, +}; + +const SubType = enum { + node, }; const RemoteObject = struct { diff --git a/src/runtime/js.zig b/src/runtime/js.zig index 5d52536c..a42df1c7 100644 --- a/src/runtime/js.zig +++ b/src/runtime/js.zig @@ -1369,6 +1369,15 @@ pub fn Env(comptime S: type, comptime types: anytype) type { generate_preview, ); } + + // Gets a value by object ID regardless of which context it is in. + // unwrapping the object also tells us the context, for now we assume it is always the default one. + // The executor argument is likely to change to somthing to allow us to find the right Executer with the given context + pub fn getValueByObjectId(self: Inspector, allocator: std.mem.Allocator, executor: *const Executor, object_id: []const u8) !Value { + const unwrapped = try self.session.unwrapObject(allocator, object_id); + // std.debug.assert(executor.context.handle == unwrapped.context.handle); + return .{ .value = unwrapped.value, .executor = executor }; // The values context and groupId are not used here + } }; pub const RemoteObject = v8.RemoteObject; @@ -1382,6 +1391,10 @@ pub fn Env(comptime S: type, comptime types: anytype) type { const executor = self.executor; return valueToString(allocator, self.value, executor.isolate, executor.context); } + + pub fn taggedAnyOpaque(self: Value) ?*TaggedAnyOpaque { + return getTaggedAnyOpaque(self.value); + } }; // Reverses the mapZigInstanceToJs, making sure that our TaggedAnyOpaque From 5026c4880561a644c443a1be984412eaec3e4a6d Mon Sep 17 00:00:00 2001 From: sjorsdonkers <72333389+sjorsdonkers@users.noreply.github.com> Date: Fri, 18 Apr 2025 17:40:54 +0200 Subject: [PATCH 2/3] Update zig-v8 to v0.1.18 --- .github/actions/install/action.yml | 2 +- Dockerfile | 6 +----- build.zig.zon | 4 ++-- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/actions/install/action.yml b/.github/actions/install/action.yml index bfe8fa40..ac34cffb 100644 --- a/.github/actions/install/action.yml +++ b/.github/actions/install/action.yml @@ -17,7 +17,7 @@ inputs: zig-v8: description: 'zig v8 version to install' required: false - default: 'v0.1.17' + default: 'v0.1.18' v8: description: 'v8 version to install' required: false diff --git a/Dockerfile b/Dockerfile index 539dfdc6..e3c23039 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ ARG ZIG=0.14.0 ARG ZIG_MINISIG=RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U ARG ARCH=x86_64 ARG V8=11.1.134 -ARG ZIG_V8=v0.1.16 +ARG ZIG_V8=v0.1.18 RUN apt-get update -yq && \ apt-get install -yq xz-utils \ @@ -51,10 +51,6 @@ WORKDIR /browser RUN git submodule init && \ git submodule update --recursive -RUN cd vendor/zig-js-runtime && \ - git submodule init && \ - git submodule update --recursive - RUN make install-libiconv && \ make install-netsurf && \ make install-mimalloc diff --git a/build.zig.zon b/build.zig.zon index 757b2e28..d4f5d74d 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -13,8 +13,8 @@ .hash = "tigerbeetle_io-0.0.0-ViLgxpyRBAB5BMfIcj3KMXfbJzwARs9uSl8aRy2OXULd", }, .v8 = .{ - .url = "https://github.com/karlseguin/zig-v8-fork/archive/e5f1c0c9f1ed147617427f22cdaf11df4ab60b79.tar.gz", - .hash = "v8-0.0.0-xddH61vYIACI2pT1t-dUbXm18cHAKy-KWT_Qft4sBwam", + .url = "https://github.com/lightpanda-io/zig-v8-fork/archive/5790c80fcd12dec64e596f6f66f09de567020e8a.tar.gz", + .hash = "v8-0.0.0-xddH66roIAAdXNJpBKN_NO8zBz2H8b9moUzshBCfns2p", }, //.v8 = .{ .path = "../zig-v8-fork" }, //.tigerbeetle_io = .{ .path = "../tigerbeetle-io" }, From a698ff8309429b2e9c480c150ea1441817fb4d5c Mon Sep 17 00:00:00 2001 From: sjorsdonkers <72333389+sjorsdonkers@users.noreply.github.com> Date: Tue, 22 Apr 2025 13:48:13 +0200 Subject: [PATCH 3/3] describeNode feedback --- src/cdp/domains/dom.zig | 12 ++++-------- src/cdp/testing.zig | 20 ++------------------ src/runtime/js.zig | 14 +++++--------- 3 files changed, 11 insertions(+), 35 deletions(-) diff --git a/src/cdp/domains/dom.zig b/src/cdp/domains/dom.zig index 396cf530..a51a4059 100644 --- a/src/cdp/domains/dom.zig +++ b/src/cdp/domains/dom.zig @@ -170,15 +170,11 @@ fn describeNode(cmd: anytype) !void { if (params.nodeId != null) { const node = bc.node_registry.lookup_by_id.get(params.nodeId.?) orelse return error.NodeNotFound; return cmd.sendResult(.{ .node = bc.nodeWriter(node, .{}) }, .{}); - } else if (params.objectId != null) { - + } + if (params.objectId != null) { // Retrieve the object from which ever context it is in. - const js_value = try bc.session.inspector.getValueByObjectId(cmd.arena, bc.session.executor, params.objectId.?); - const entry = js_value.taggedAnyOpaque() orelse return error.ObjectIdIsNotANode; - const subtype = entry.subtype orelse return error.ObjectIdIsNotANode; - if (subtype != .node) return error.ObjectIdIsNotANode; - - const node = try bc.node_registry.register(@ptrCast(entry.ptr)); + const parser_node = try bc.session.inspector.getNodePtr(cmd.arena, params.objectId.?); + const node = try bc.node_registry.register(@ptrCast(parser_node)); return cmd.sendResult(.{ .node = bc.nodeWriter(node, .{}) }, .{}); } return error.MissingParams; diff --git a/src/cdp/testing.zig b/src/cdp/testing.zig index 22fc9e8e..b702b923 100644 --- a/src/cdp/testing.zig +++ b/src/cdp/testing.zig @@ -122,28 +122,12 @@ const Inspector = struct { _ = value; return RemoteObject{}; } - pub fn getValueByObjectId(self: Inspector, alloc: std.mem.Allocator, executor: *const Executor, object_id: []const u8) !Value { + pub fn getNodePtr(self: Inspector, alloc: std.mem.Allocator, object_id: []const u8) !?*anyopaque { _ = self; - _ = alloc; - _ = executor; _ = object_id; - return .{}; + return try alloc.create(i32); } }; -const Value = struct { - pub fn taggedAnyOpaque(self: Value) ?*TaggedAnyOpaque { - _ = self; - return null; - } -}; -const TaggedAnyOpaque = struct { - ptr: *anyopaque, - subtype: ?SubType = .node, -}; - -const SubType = enum { - node, -}; const RemoteObject = struct { pub fn deinit(self: RemoteObject) void { diff --git a/src/runtime/js.zig b/src/runtime/js.zig index a42df1c7..81639704 100644 --- a/src/runtime/js.zig +++ b/src/runtime/js.zig @@ -1371,12 +1371,12 @@ pub fn Env(comptime S: type, comptime types: anytype) type { } // Gets a value by object ID regardless of which context it is in. - // unwrapping the object also tells us the context, for now we assume it is always the default one. - // The executor argument is likely to change to somthing to allow us to find the right Executer with the given context - pub fn getValueByObjectId(self: Inspector, allocator: std.mem.Allocator, executor: *const Executor, object_id: []const u8) !Value { + pub fn getNodePtr(self: *const Inspector, allocator: Allocator, object_id: []const u8) !?*anyopaque { const unwrapped = try self.session.unwrapObject(allocator, object_id); - // std.debug.assert(executor.context.handle == unwrapped.context.handle); - return .{ .value = unwrapped.value, .executor = executor }; // The values context and groupId are not used here + // The values context and groupId are not used here + const toa = getTaggedAnyOpaque(unwrapped.value) orelse return null; + if (toa.subtype == null or toa.subtype != .node) return error.ObjectIdIsNotANode; + return toa.ptr; } }; @@ -1391,10 +1391,6 @@ pub fn Env(comptime S: type, comptime types: anytype) type { const executor = self.executor; return valueToString(allocator, self.value, executor.isolate, executor.context); } - - pub fn taggedAnyOpaque(self: Value) ?*TaggedAnyOpaque { - return getTaggedAnyOpaque(self.value); - } }; // Reverses the mapZigInstanceToJs, making sure that our TaggedAnyOpaque