From b64f7d013dcde373902fb3d609b7ce44931f4ccc Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 17 Oct 2024 13:17:59 +0200 Subject: [PATCH 1/2] node: implement node.compareDocumentPosition --- src/dom/document.zig | 1 - src/dom/node.zig | 65 +++++++++++++++++++++++++++++++++++++---- src/netsurf/netsurf.zig | 2 +- 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/src/dom/document.zig b/src/dom/document.zig index 11b29016..0b8d0cd8 100644 --- a/src/dom/document.zig +++ b/src/dom/document.zig @@ -29,7 +29,6 @@ const Node = @import("node.zig").Node; const NodeList = @import("nodelist.zig").NodeList; const NodeUnion = @import("node.zig").Union; -const Walker = @import("walker.zig").WalkerDepthFirst; const collection = @import("html_collection.zig"); const css = @import("css.zig"); diff --git a/src/dom/node.zig b/src/dom/node.zig index f5f0ade2..6c5ac8c4 100644 --- a/src/dom/node.zig +++ b/src/dom/node.zig @@ -40,6 +40,7 @@ const DocumentType = @import("document_type.zig").DocumentType; const DocumentFragment = @import("document_fragment.zig").DocumentFragment; const HTMLCollection = @import("html_collection.zig").HTMLCollection; const HTMLCollectionIterator = @import("html_collection.zig").HTMLCollectionIterator; +const Walker = @import("walker.zig").WalkerDepthFirst; // HTML const HTML = @import("../html/html.zig"); @@ -195,11 +196,55 @@ pub const Node = struct { return try Node.toInterface(clone); } - pub fn _compareDocumentPosition(self: *parser.Node, other: *parser.Node) void { - // TODO - _ = other; - _ = self; - std.log.err("Not implemented {s}", .{"node.compareDocumentPosition()"}); + pub fn _compareDocumentPosition(self: *parser.Node, other: *parser.Node) !u32 { + if (self == other) return 0; + + const docself = try parser.nodeOwnerDocument(self); + const docother = try parser.nodeOwnerDocument(other); + + // Both are in different document. + if (docself == null or docother == null or docother.? != docself.?) { + return @intFromEnum(parser.DocumentPosition.disconnected); + } + + // TODO Both are in a different trees in the same document. + + const w = Walker{}; + var next: ?*parser.Node = null; + + // Is other a descendant of self? + while (true) { + next = try w.get_next(self, next) orelse break; + if (other == next) { + return @intFromEnum(parser.DocumentPosition.following) + + @intFromEnum(parser.DocumentPosition.contained_by); + } + } + + // Is self a descendant of other? + next = null; + while (true) { + next = try w.get_next(other, next) orelse break; + if (self == next) { + return @intFromEnum(parser.DocumentPosition.contains) + + @intFromEnum(parser.DocumentPosition.preceding); + } + } + + next = null; + while (true) { + next = try w.get_next(parser.documentToNode(docself.?), next) orelse break; + if (other == next) { + // other precedes self. + return @intFromEnum(parser.DocumentPosition.preceding); + } + if (self == next) { + // other follows self. + return @intFromEnum(parser.DocumentPosition.following); + } + } + + return 0; } pub fn _contains(self: *parser.Node, other: *parser.Node) !bool { @@ -384,6 +429,16 @@ pub fn testExecFn( ; try runScript(js_env, alloc, trim_and_replace, "proto_test"); + var node_compare_document_position = [_]Case{ + .{ .src = "document.body.compareDocumentPosition(document.firstChild); ", .ex = "10" }, + .{ .src = "document.getElementById(\"para-empty\").compareDocumentPosition(document.getElementById(\"content\"));", .ex = "10" }, + .{ .src = "document.getElementById(\"content\").compareDocumentPosition(document.getElementById(\"para-empty\"));", .ex = "20" }, + .{ .src = "document.getElementById(\"link\").compareDocumentPosition(document.getElementById(\"link\"));", .ex = "0" }, + .{ .src = "document.getElementById(\"para-empty\").compareDocumentPosition(document.getElementById(\"link\"));", .ex = "2" }, + .{ .src = "document.getElementById(\"link\").compareDocumentPosition(document.getElementById(\"para-empty\"));", .ex = "4" }, + }; + try checkCases(js_env, &node_compare_document_position); + var first_child = [_]Case{ // for next test cases .{ .src = "let content = document.getElementById('content')", .ex = "undefined" }, diff --git a/src/netsurf/netsurf.zig b/src/netsurf/netsurf.zig index 322bb4b3..a3560d25 100644 --- a/src/netsurf/netsurf.zig +++ b/src/netsurf/netsurf.zig @@ -1794,7 +1794,7 @@ pub fn documentFragmentBodyChildren(doc: *DocumentFragment) !?*NodeList { // Document Position -pub const DocumentPosition = enum(u2) { +pub const DocumentPosition = enum(u32) { disconnected = c.DOM_DOCUMENT_POSITION_DISCONNECTED, preceding = c.DOM_DOCUMENT_POSITION_PRECEDING, following = c.DOM_DOCUMENT_POSITION_FOLLOWING, From 8dc757ddf30e17628cdd7222cb967307e722649d Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 17 Oct 2024 14:43:58 +0200 Subject: [PATCH 2/2] node: implement getRootNode --- src/dom/node.zig | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/dom/node.zig b/src/dom/node.zig index 6c5ac8c4..05c47d74 100644 --- a/src/dom/node.zig +++ b/src/dom/node.zig @@ -251,10 +251,13 @@ pub const Node = struct { return try parser.nodeContains(self, other); } - pub fn _getRootNode(self: *parser.Node) void { - // TODO - _ = self; - std.log.err("Not implemented {s}", .{"node.getRootNode()"}); + pub fn _getRootNode(self: *parser.Node) !?HTMLElem.Union { + // TODO return this’s shadow-including root if options["composed"] is true + const res = try parser.nodeOwnerDocument(self); + if (res == null) { + return null; + } + return try HTMLElem.toInterface(HTMLElem.Union, @as(*parser.Element, @ptrCast(res.?))); } pub fn _hasChildNodes(self: *parser.Node) !bool { @@ -439,6 +442,11 @@ pub fn testExecFn( }; try checkCases(js_env, &node_compare_document_position); + var get_root_node = [_]Case{ + .{ .src = "document.getElementById('content').getRootNode().__proto__.constructor.name", .ex = "HTMLDocument" }, + }; + try checkCases(js_env, &get_root_node); + var first_child = [_]Case{ // for next test cases .{ .src = "let content = document.getElementById('content')", .ex = "undefined" },