From 74ad9ec8bf8029d416e47be5f0408e02f76284ed Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Mon, 14 Jul 2025 17:01:11 +0800 Subject: [PATCH] Add childElementCount and children to DocumentFragment Also, when shadowRoot is re-attached to an element, clear all existing children (like we're supposed to) --- src/browser/dom/document_fragment.zig | 15 ++++++++++++++- src/browser/dom/element.zig | 2 +- src/browser/dom/shadow_root.zig | 7 +++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/browser/dom/document_fragment.zig b/src/browser/dom/document_fragment.zig index d4d8badd..615eca2a 100644 --- a/src/browser/dom/document_fragment.zig +++ b/src/browser/dom/document_fragment.zig @@ -22,6 +22,7 @@ const Page = @import("../page.zig").Page; const NodeList = @import("nodelist.zig").NodeList; const Element = @import("element.zig").Element; const ElementUnion = @import("element.zig").Union; +const collection = @import("html_collection.zig"); const Node = @import("node.zig").Node; @@ -71,6 +72,15 @@ pub const DocumentFragment = struct { pub fn _querySelectorAll(self: *parser.DocumentFragment, selector: []const u8, page: *Page) !NodeList { return css.querySelectorAll(page.arena, parser.documentFragmentToNode(self), selector); } + + pub fn get_childElementCount(self: *parser.DocumentFragment) !u32 { + var children = try get_children(self); + return children.get_length(); + } + + pub fn get_children(self: *parser.DocumentFragment) !collection.HTMLCollection { + return collection.HTMLCollectionChildren(parser.documentFragmentToNode(self), false); + } }; const testing = @import("../../testing.zig"); @@ -93,10 +103,13 @@ test "Browser.DOM.DocumentFragment" { try runner.testCases(&.{ .{ "let f = document.createDocumentFragment()", null }, .{ "let d = document.createElement('div');", null }, + .{ "d.childElementCount", "0" }, + .{ "d.id = 'x';", null }, .{ "document.getElementById('x') == null;", "true" }, - .{ "f.append(d);", null }, + .{ "f.childElementCount", "1" }, + .{ "f.children[0].id", "x" }, .{ "document.getElementById('x') == null;", "true" }, .{ "document.getElementsByTagName('body')[0].append(f.cloneNode(true));", null }, diff --git a/src/browser/dom/element.zig b/src/browser/dom/element.zig index 753ad707..48cdad0d 100644 --- a/src/browser/dom/element.zig +++ b/src/browser/dom/element.zig @@ -474,7 +474,7 @@ pub const Element = struct { return error.NotSupportedError; } - // TODO: the existing shadow root should be cleared! + try Node.removeChildren(@alignCast(@ptrCast(sr.proto))); return sr; } diff --git a/src/browser/dom/shadow_root.zig b/src/browser/dom/shadow_root.zig index 284e9f6d..45305923 100644 --- a/src/browser/dom/shadow_root.zig +++ b/src/browser/dom/shadow_root.zig @@ -55,6 +55,13 @@ test "Browser.DOM.ShadowRoot" { .{ "div1.shadowRoot == sr1", "true" }, .{ "try { div1.attachShadow({mode: 'closed'}) } catch (e) { e }", "Error: NotSupportedError" }, + + .{ " sr1.append(document.createElement('div'))", null }, + .{ " sr1.append(document.createElement('span'))", null }, + .{ "sr1.childElementCount", "2" }, + // re-attaching clears it + .{ "div1.attachShadow({mode: 'open'}) == sr1", "true" }, + .{ "sr1.childElementCount", "0" }, }, .{}); try runner.testCases(&.{