From 23c8616ba52d3173506888bd0cf16d5d7d2753fb Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Wed, 11 Feb 2026 21:20:16 +0800 Subject: [PATCH] Passes all test for WPT dom/nodes/Node-properties.htm Documents created via DOMImplementation should not inherit the page.URL. Add textContent for DocumentFragment Fix creteElement for XML namespace when not explicitly specified --- src/browser/webapi/DOMImplementation.zig | 2 ++ src/browser/webapi/Document.zig | 9 +++++---- src/browser/webapi/Node.zig | 8 +++----- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/browser/webapi/DOMImplementation.zig b/src/browser/webapi/DOMImplementation.zig index 82405cdd..f0f9247c 100644 --- a/src/browser/webapi/DOMImplementation.zig +++ b/src/browser/webapi/DOMImplementation.zig @@ -34,6 +34,7 @@ pub fn createDocumentType(_: *const DOMImplementation, qualified_name: []const u pub fn createHTMLDocument(_: *const DOMImplementation, title: ?[]const u8, page: *Page) !*Document { const document = (try page._factory.document(Node.Document.HTMLDocument{ ._proto = undefined })).asDocument(); document._ready_state = .complete; + document._url = "about:blank"; { const doctype = try page._factory.node(DocumentType{ @@ -67,6 +68,7 @@ pub fn createHTMLDocument(_: *const DOMImplementation, title: ?[]const u8, page: pub fn createDocument(_: *const DOMImplementation, namespace_: ?[]const u8, qualified_name: ?[]const u8, doctype: ?*DocumentType, page: *Page) !*Document { // Create XML Document const document = (try page._factory.document(Node.Document.XMLDocument{ ._proto = undefined })).asDocument(); + document._url = "about:blank"; // Append doctype if provided if (doctype) |dt| { diff --git a/src/browser/webapi/Document.zig b/src/browser/webapi/Document.zig index 18102a98..f52fad65 100644 --- a/src/browser/webapi/Document.zig +++ b/src/browser/webapi/Document.zig @@ -44,6 +44,7 @@ const Document = @This(); _type: Type, _proto: *Node, _location: ?*Location = null, +_url: ?[:0]const u8 = null, // URL for documents created via DOMImplementation (about:blank) _ready_state: ReadyState = .loading, _current_script: ?*Element.Html.Script = null, _elements_by_id: std.StringHashMapUnmanaged(*Element) = .empty, @@ -105,8 +106,8 @@ pub fn asEventTarget(self: *Document) *@import("EventTarget.zig") { return self._proto.asEventTarget(); } -pub fn getURL(_: *const Document, page: *const Page) [:0]const u8 { - return page.url; +pub fn getURL(self: *const Document, page: *const Page) [:0]const u8 { + return self._url orelse page.url; } pub fn getContentType(self: *const Document) []const u8 { @@ -131,8 +132,8 @@ pub fn createElement(self: *Document, name: []const u8, options_: ?CreateElement if (self._type == .html) { break :blk .{ .html, std.ascii.lowerString(&page.buf, name) }; } - // Generic and XML documents create XML elements - break :blk .{ .xml, name }; + // Generic and XML documents create elements with null namespace + break :blk .{ .null, name }; }; // HTML documents are case-insensitive - lowercase the tag name diff --git a/src/browser/webapi/Node.zig b/src/browser/webapi/Node.zig index bcf0ac1b..418b6ae6 100644 --- a/src/browser/webapi/Node.zig +++ b/src/browser/webapi/Node.zig @@ -255,7 +255,7 @@ pub fn childNodes(self: *const Node, page: *Page) !*collections.ChildNodes { pub fn getTextContent(self: *Node, writer: *std.Io.Writer) error{WriteFailed}!void { switch (self._type) { - .element => { + .element, .document_fragment => { var it = self.childrenIterator(); while (it.next()) |child| { // ignore comments and processing instructions. @@ -268,7 +268,6 @@ pub fn getTextContent(self: *Node, writer: *std.Io.Writer) error{WriteFailed}!vo .cdata => |c| try writer.writeAll(c.getData()), .document => {}, .document_type => {}, - .document_fragment => {}, .attribute => |attr| try writer.writeAll(attr._value.str()), } } @@ -912,16 +911,15 @@ pub const JsApi = struct { fn _textContext(self: *Node, page: *const Page) !?[]const u8 { // cdata and attributes can return value directly, avoiding the copy switch (self._type) { - .element => |el| { + .element, .document_fragment => { var buf = std.Io.Writer.Allocating.init(page.call_arena); - try el.asNode().getTextContent(&buf.writer); + try self.getTextContent(&buf.writer); return buf.written(); }, .cdata => |cdata| return cdata.getData(), .attribute => |attr| return attr._value.str(), .document => return null, .document_type => return null, - .document_fragment => return null, } }