Merge pull request #276 from lightpanda-io/compare-position

node: implement node.compareDocumentPosition
This commit is contained in:
Pierre Tachoire
2024-10-17 15:06:47 +02:00
committed by GitHub
3 changed files with 73 additions and 11 deletions

View File

@@ -29,7 +29,6 @@ const Node = @import("node.zig").Node;
const NodeList = @import("nodelist.zig").NodeList; const NodeList = @import("nodelist.zig").NodeList;
const NodeUnion = @import("node.zig").Union; const NodeUnion = @import("node.zig").Union;
const Walker = @import("walker.zig").WalkerDepthFirst;
const collection = @import("html_collection.zig"); const collection = @import("html_collection.zig");
const css = @import("css.zig"); const css = @import("css.zig");

View File

@@ -40,6 +40,7 @@ const DocumentType = @import("document_type.zig").DocumentType;
const DocumentFragment = @import("document_fragment.zig").DocumentFragment; const DocumentFragment = @import("document_fragment.zig").DocumentFragment;
const HTMLCollection = @import("html_collection.zig").HTMLCollection; const HTMLCollection = @import("html_collection.zig").HTMLCollection;
const HTMLCollectionIterator = @import("html_collection.zig").HTMLCollectionIterator; const HTMLCollectionIterator = @import("html_collection.zig").HTMLCollectionIterator;
const Walker = @import("walker.zig").WalkerDepthFirst;
// HTML // HTML
const HTML = @import("../html/html.zig"); const HTML = @import("../html/html.zig");
@@ -195,21 +196,68 @@ pub const Node = struct {
return try Node.toInterface(clone); return try Node.toInterface(clone);
} }
pub fn _compareDocumentPosition(self: *parser.Node, other: *parser.Node) void { pub fn _compareDocumentPosition(self: *parser.Node, other: *parser.Node) !u32 {
// TODO if (self == other) return 0;
_ = other;
_ = self; const docself = try parser.nodeOwnerDocument(self);
std.log.err("Not implemented {s}", .{"node.compareDocumentPosition()"}); 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 { pub fn _contains(self: *parser.Node, other: *parser.Node) !bool {
return try parser.nodeContains(self, other); return try parser.nodeContains(self, other);
} }
pub fn _getRootNode(self: *parser.Node) void { pub fn _getRootNode(self: *parser.Node) !?HTMLElem.Union {
// TODO // TODO return thiss shadow-including root if options["composed"] is true
_ = self; const res = try parser.nodeOwnerDocument(self);
std.log.err("Not implemented {s}", .{"node.getRootNode()"}); if (res == null) {
return null;
}
return try HTMLElem.toInterface(HTMLElem.Union, @as(*parser.Element, @ptrCast(res.?)));
} }
pub fn _hasChildNodes(self: *parser.Node) !bool { pub fn _hasChildNodes(self: *parser.Node) !bool {
@@ -384,6 +432,21 @@ pub fn testExecFn(
; ;
try runScript(js_env, alloc, trim_and_replace, "proto_test"); 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 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{ var first_child = [_]Case{
// for next test cases // for next test cases
.{ .src = "let content = document.getElementById('content')", .ex = "undefined" }, .{ .src = "let content = document.getElementById('content')", .ex = "undefined" },

View File

@@ -1794,7 +1794,7 @@ pub fn documentFragmentBodyChildren(doc: *DocumentFragment) !?*NodeList {
// Document Position // Document Position
pub const DocumentPosition = enum(u2) { pub const DocumentPosition = enum(u32) {
disconnected = c.DOM_DOCUMENT_POSITION_DISCONNECTED, disconnected = c.DOM_DOCUMENT_POSITION_DISCONNECTED,
preceding = c.DOM_DOCUMENT_POSITION_PRECEDING, preceding = c.DOM_DOCUMENT_POSITION_PRECEDING,
following = c.DOM_DOCUMENT_POSITION_FOLLOWING, following = c.DOM_DOCUMENT_POSITION_FOLLOWING,