implement document.write

This commit is contained in:
Pierre Tachoire
2025-12-13 14:05:05 +01:00
parent 7c976209cc
commit 6d4966e83d
3 changed files with 88 additions and 0 deletions

View File

@@ -319,9 +319,68 @@ pub const Document = struct {
log.debug(.web_api, "not implemented", .{ .feature = "Document hasFocus" });
return true;
}
pub fn _open(_: *parser.Document, page: *Page) !*parser.DocumentHTML {
if (page.open) {
return page.window.document;
}
// This implementation is invalid.
// According to MDN, we should cleanup registered listeners.
// So we sould cleanup previous DOM memory.
// But this implementation is more simple for now.
const html_doc = try parser.documentHTMLParseFromStr("");
try page.setDocument(html_doc);
page.open = true;
return page.window.document;
}
pub fn _close(_: *parser.Document, page: *Page) !void {
page.open = false;
}
pub fn _write(self: *parser.Document, str: []const u8, page: *Page) !void {
if (!page.open) {
_ = try _open(self, page);
}
const document = parser.documentHTMLToDocument(page.window.document);
const fragment = try parser.documentParseFragmentFromStr(document, str);
const fragment_node = parser.documentFragmentToNode(fragment);
const fragment_html = parser.nodeFirstChild(fragment_node) orelse return;
const fragment_head = parser.nodeFirstChild(fragment_html) orelse return;
const fragment_body = parser.nodeNextSibling(fragment_head) orelse return;
const document_node = parser.documentToNode(document);
const document_html = parser.nodeFirstChild(document_node) orelse return;
const document_head = parser.nodeFirstChild(document_html) orelse return;
const document_body = parser.nodeNextSibling(document_head) orelse return;
{
const children = try parser.nodeGetChildNodes(fragment_head);
// always index 0, because nodeAppendChild moves the node out of
// the nodeList and into the new tree
while (parser.nodeListItem(children, 0)) |child| {
_ = try parser.nodeAppendChild(document_head, child);
}
}
{
const children = try parser.nodeGetChildNodes(fragment_body);
// always index 0, because nodeAppendChild moves the node out of
// the nodeList and into the new tree
while (parser.nodeListItem(children, 0)) |child| {
_ = try parser.nodeAppendChild(document_body, child);
}
}
}
};
const testing = @import("../../testing.zig");
test "Browser: DOM.Document" {
try testing.htmlRunner("dom/document.html");
}
test "Browser: DOM.Document.write" {
try testing.htmlRunner("dom/document_write.html");
}

View File

@@ -103,6 +103,10 @@ pub const Page = struct {
notified_network_idle: IdleNotification = .init,
notified_network_almost_idle: IdleNotification = .init,
// Indicates if the page's document is open or close.
// Relates with https://developer.mozilla.org/en-US/docs/Web/API/Document/open
open: bool = false,
const Mode = union(enum) {
pre: void,
err: anyerror,

View File

@@ -0,0 +1,25 @@
<!DOCTYPE html>
<script src="../testing.js"></script>
<div id="content">
<a id="a1" href="foo" class="ok">OK</a>
<p id="p1" class="ok empty">
<span id="s1"></span>
</p>
<p id="p2"> And</p>
</div>
<script id=document_write>
document.open();
document.write("<p id=ok>Hello world!</p>");
document.write("<p>I am a fish</p>");
document.write("<p>The number is 42</p>");
document.close();
const ok = document.getElementById("ok");
testing.expectEqual('Hello world!', ok.innerText);
const content = document.firstElementChild.innerHTML;
testing.expectEqual('<head></head><body><p id="ok">Hello world!</p><p>I am a fish</p><p>The number is 42</p></body>', content);
</script>