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
This commit is contained in:
Karl Seguin
2026-02-11 21:20:16 +08:00
parent 77aa2241dc
commit 23c8616ba5
3 changed files with 10 additions and 9 deletions

View File

@@ -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| {

View File

@@ -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

View File

@@ -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,
}
}