Skip to content

Commit 6d4966e

Browse files
committed
implement document.write
1 parent 7c97620 commit 6d4966e

File tree

3 files changed

+88
-0
lines changed

3 files changed

+88
-0
lines changed

src/browser/dom/document.zig

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,9 +319,68 @@ pub const Document = struct {
319319
log.debug(.web_api, "not implemented", .{ .feature = "Document hasFocus" });
320320
return true;
321321
}
322+
323+
pub fn _open(_: *parser.Document, page: *Page) !*parser.DocumentHTML {
324+
if (page.open) {
325+
return page.window.document;
326+
}
327+
328+
// This implementation is invalid.
329+
// According to MDN, we should cleanup registered listeners.
330+
// So we sould cleanup previous DOM memory.
331+
// But this implementation is more simple for now.
332+
const html_doc = try parser.documentHTMLParseFromStr("");
333+
try page.setDocument(html_doc);
334+
page.open = true;
335+
336+
return page.window.document;
337+
}
338+
339+
pub fn _close(_: *parser.Document, page: *Page) !void {
340+
page.open = false;
341+
}
342+
343+
pub fn _write(self: *parser.Document, str: []const u8, page: *Page) !void {
344+
if (!page.open) {
345+
_ = try _open(self, page);
346+
}
347+
const document = parser.documentHTMLToDocument(page.window.document);
348+
const fragment = try parser.documentParseFragmentFromStr(document, str);
349+
const fragment_node = parser.documentFragmentToNode(fragment);
350+
351+
const fragment_html = parser.nodeFirstChild(fragment_node) orelse return;
352+
const fragment_head = parser.nodeFirstChild(fragment_html) orelse return;
353+
const fragment_body = parser.nodeNextSibling(fragment_head) orelse return;
354+
355+
const document_node = parser.documentToNode(document);
356+
const document_html = parser.nodeFirstChild(document_node) orelse return;
357+
const document_head = parser.nodeFirstChild(document_html) orelse return;
358+
const document_body = parser.nodeNextSibling(document_head) orelse return;
359+
360+
{
361+
const children = try parser.nodeGetChildNodes(fragment_head);
362+
// always index 0, because nodeAppendChild moves the node out of
363+
// the nodeList and into the new tree
364+
while (parser.nodeListItem(children, 0)) |child| {
365+
_ = try parser.nodeAppendChild(document_head, child);
366+
}
367+
}
368+
369+
{
370+
const children = try parser.nodeGetChildNodes(fragment_body);
371+
// always index 0, because nodeAppendChild moves the node out of
372+
// the nodeList and into the new tree
373+
while (parser.nodeListItem(children, 0)) |child| {
374+
_ = try parser.nodeAppendChild(document_body, child);
375+
}
376+
}
377+
}
322378
};
323379

324380
const testing = @import("../../testing.zig");
325381
test "Browser: DOM.Document" {
326382
try testing.htmlRunner("dom/document.html");
327383
}
384+
test "Browser: DOM.Document.write" {
385+
try testing.htmlRunner("dom/document_write.html");
386+
}

src/browser/page.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ pub const Page = struct {
103103
notified_network_idle: IdleNotification = .init,
104104
notified_network_almost_idle: IdleNotification = .init,
105105

106+
// Indicates if the page's document is open or close.
107+
// Relates with https://developer.mozilla.org/en-US/docs/Web/API/Document/open
108+
open: bool = false,
109+
106110
const Mode = union(enum) {
107111
pre: void,
108112
err: anyerror,

src/tests/dom/document_write.html

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<!DOCTYPE html>
2+
<script src="../testing.js"></script>
3+
4+
<div id="content">
5+
<a id="a1" href="foo" class="ok">OK</a>
6+
<p id="p1" class="ok empty">
7+
<span id="s1"></span>
8+
</p>
9+
<p id="p2"> And</p>
10+
</div>
11+
12+
13+
<script id=document_write>
14+
document.open();
15+
document.write("<p id=ok>Hello world!</p>");
16+
document.write("<p>I am a fish</p>");
17+
document.write("<p>The number is 42</p>");
18+
document.close();
19+
20+
const ok = document.getElementById("ok");
21+
testing.expectEqual('Hello world!', ok.innerText);
22+
23+
const content = document.firstElementChild.innerHTML;
24+
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);
25+
</script>

0 commit comments

Comments
 (0)