diff --git a/src/browser/State.zig b/src/browser/State.zig index 55447923..d594d943 100644 --- a/src/browser/State.zig +++ b/src/browser/State.zig @@ -58,6 +58,8 @@ active_element: ?*parser.Element = null, // default (by returning selectedIndex == 0). explicit_index_set: bool = false, +template_content: ?*parser.DocumentFragment = null, + const ReadyState = enum { loading, interactive, diff --git a/src/browser/dom/document_fragment.zig b/src/browser/dom/document_fragment.zig index 0085ec33..6ed43cac 100644 --- a/src/browser/dom/document_fragment.zig +++ b/src/browser/dom/document_fragment.zig @@ -71,4 +71,17 @@ test "Browser.DOM.DocumentFragment" { .{ "dc1.isEqualNode(dc1)", "true" }, .{ "dc1.isEqualNode(dc2)", "true" }, }, .{}); + + try runner.testCases(&.{ + .{ "let f = document.createDocumentFragment()", null }, + .{ "let d = document.createElement('div');", null }, + .{ "d.id = 'x';", null }, + .{ "document.getElementById('x') == null;", "true" }, + + .{ "f.append(d);", null }, + .{ "document.getElementById('x') == null;", "true" }, + + .{ "document.getElementsByTagName('body')[0].append(f.cloneNode(true));", null }, + .{ "document.getElementById('x') != null;", "true" }, + }, .{}); } diff --git a/src/browser/html/elements.zig b/src/browser/html/elements.zig index 948810a2..28179fee 100644 --- a/src/browser/html/elements.zig +++ b/src/browser/html/elements.zig @@ -1265,6 +1265,16 @@ pub const HTMLTemplateElement = struct { pub fn constructor(page: *Page, js_this: Env.JsThis) !*parser.Element { return constructHtmlElement(page, js_this); } + + pub fn get_content(self: *parser.Template, page: *Page) !*parser.DocumentFragment { + const state = try page.getOrCreateNodeState(@alignCast(@ptrCast(self))); + if (state.template_content) |tc| { + return tc; + } + const tc = try parser.documentCreateDocumentFragment(@ptrCast(page.window.document)); + state.template_content = tc; + return tc; + } }; pub const HTMLTextAreaElement = struct { @@ -1550,7 +1560,8 @@ test "Browser.HTML.Element" { .{ "document.activeElement === focused", "true" }, }, .{}); } -test "Browser.HTML.HtmlInputElement.propeties" { + +test "Browser.HTML.HtmlInputElement.properties" { var runner = try testing.jsRunner(testing.tracking_allocator, .{ .url = "https://lightpanda.io/noslashattheend" }); defer runner.deinit(); var alloc = std.heap.ArenaAllocator.init(runner.app.allocator); @@ -1634,7 +1645,8 @@ test "Browser.HTML.HtmlInputElement.propeties" { .{ "input_value.value", "mango" }, // Still mango }, .{}); } -test "Browser.HTML.HtmlInputElement.propeties.form" { + +test "Browser.HTML.HtmlInputElement.properties.form" { var runner = try testing.jsRunner(testing.tracking_allocator, .{ .html = \\
\\

@@ -1652,6 +1664,21 @@ test "Browser.HTML.HtmlInputElement.propeties.form" { }, .{}); } +test "Browser.HTML.HTMLTemplateElement" { + var runner = try testing.jsRunner(testing.tracking_allocator, .{ .html = "

" }); + defer runner.deinit(); + + try runner.testCases(&.{ + .{ "let t = document.createElement('template')", null }, + .{ "let d = document.createElement('div')", null }, + .{ "d.id = 'abc'", null }, + .{ "t.content.append(d)", null }, + .{ "document.getElementById('abc')", "null" }, + .{ "document.getElementById('c').appendChild(t.content.cloneNode(true))", null }, + .{ "document.getElementById('abc').id", "abc" }, + }, .{}); +} + const Check = struct { input: []const u8, expected: ?[]const u8 = null, // Needed when input != expected