Skip to content

Commit 0c1c264

Browse files
Merge pull request #1274 from lightpanda-io/document-write
implement document.write
2 parents 447ef83 + d8bbaff commit 0c1c264

File tree

3 files changed

+87
-0
lines changed

3 files changed

+87
-0
lines changed

src/browser/dom/document.zig

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,9 +319,67 @@ 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+
_ = try _open(self, page);
345+
346+
const document = parser.documentHTMLToDocument(page.window.document);
347+
const fragment = try parser.documentParseFragmentFromStr(document, str);
348+
const fragment_node = parser.documentFragmentToNode(fragment);
349+
350+
const fragment_html = parser.nodeFirstChild(fragment_node) orelse return;
351+
const fragment_head = parser.nodeFirstChild(fragment_html) orelse return;
352+
const fragment_body = parser.nodeNextSibling(fragment_head) orelse return;
353+
354+
const document_node = parser.documentToNode(document);
355+
const document_html = parser.nodeFirstChild(document_node) orelse return;
356+
const document_head = parser.nodeFirstChild(document_html) orelse return;
357+
const document_body = parser.nodeNextSibling(document_head) orelse return;
358+
359+
{
360+
const children = try parser.nodeGetChildNodes(fragment_head);
361+
// always index 0, because nodeAppendChild moves the node out of
362+
// the nodeList and into the new tree
363+
while (parser.nodeListItem(children, 0)) |child| {
364+
_ = try parser.nodeAppendChild(document_head, child);
365+
}
366+
}
367+
368+
{
369+
const children = try parser.nodeGetChildNodes(fragment_body);
370+
// always index 0, because nodeAppendChild moves the node out of
371+
// the nodeList and into the new tree
372+
while (parser.nodeListItem(children, 0)) |child| {
373+
_ = try parser.nodeAppendChild(document_body, child);
374+
}
375+
}
376+
}
322377
};
323378

324379
const testing = @import("../../testing.zig");
325380
test "Browser: DOM.Document" {
326381
try testing.htmlRunner("dom/document.html");
327382
}
383+
test "Browser: DOM.Document.write" {
384+
try testing.htmlRunner("dom/document_write.html");
385+
}

src/browser/page.zig

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

108+
// Indicates if the page's document is open or close.
109+
// Relates with https://developer.mozilla.org/en-US/docs/Web/API/Document/open
110+
open: bool = false,
111+
108112
const Mode = union(enum) {
109113
pre: void,
110114
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)