From 518e0aa07a8de46374011b1ef4d035a4c4496c24 Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Wed, 7 Jan 2026 11:43:55 +0800 Subject: [PATCH] add outerHTML setter --- src/browser/Page.zig | 6 +++--- src/browser/tests/element/outer.html | 21 +++++++++++++++++++++ src/browser/webapi/Document.zig | 18 +++++++++++++++--- src/browser/webapi/Element.zig | 16 +++++++++++++++- 4 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 src/browser/tests/element/outer.html diff --git a/src/browser/Page.zig b/src/browser/Page.zig index 8df24ec4..f2cab39b 100644 --- a/src/browser/Page.zig +++ b/src/browser/Page.zig @@ -2172,9 +2172,9 @@ pub fn appendAllChildren(self: *Page, parent: *Node, target: *Node) !void { } } -pub fn insertAllChildrenBefore(self: *Page, fragment: *Node, target: *Node, ref_node: *Node) !void { +pub fn insertAllChildrenBefore(self: *Page, fragment: *Node, parent: *Node, ref_node: *Node) !void { self.domChanged(); - const dest_connected = target.isConnected(); + const dest_connected = parent.isConnected(); var it = fragment.childrenIterator(); while (it.next()) |child| { @@ -2182,7 +2182,7 @@ pub fn insertAllChildrenBefore(self: *Page, fragment: *Node, target: *Node, ref_ const child_was_connected = child.isConnected(); self.removeNode(fragment, child, .{ .will_be_reconnected = dest_connected }); try self.insertNodeRelative( - target, + parent, child, .{ .before = ref_node }, .{ .child_already_connected = child_was_connected }, diff --git a/src/browser/tests/element/outer.html b/src/browser/tests/element/outer.html new file mode 100644 index 00000000..354b383a --- /dev/null +++ b/src/browser/tests/element/outer.html @@ -0,0 +1,21 @@ + + +
hello world
+ + diff --git a/src/browser/webapi/Document.zig b/src/browser/webapi/Document.zig index 8dafc21f..8b6c9e76 100644 --- a/src/browser/webapi/Document.zig +++ b/src/browser/webapi/Document.zig @@ -163,8 +163,10 @@ pub fn createAttributeNS(_: *const Document, namespace: []const u8, name: []cons }); } -pub fn getElementById(self: *const Document, id_: ?[]const u8) ?*Element { - const id = id_ orelse return null; +pub fn getElementById(self: *const Document, id: []const u8) ?*Element { + if (id.len == 0) { + return null; + } return self._elements_by_id.get(id); } @@ -685,7 +687,17 @@ pub const JsApi = struct { pub const createEvent = bridge.function(Document.createEvent, .{ .dom_exception = true }); pub const createTreeWalker = bridge.function(Document.createTreeWalker, .{}); pub const createNodeIterator = bridge.function(Document.createNodeIterator, .{}); - pub const getElementById = bridge.function(Document.getElementById, .{}); + pub const getElementById = bridge.function(_getElementById, .{}); + fn _getElementById(self: *const Document, value_: ?js.Value) !?*Element { + const value = value_ orelse return null; + if (value.isNull()) { + return self.getElementById("null"); + } + if (value.isUndefined()) { + return self.getElementById("undefined"); + } + return self.getElementById(try value.toZig([]const u8)); + } pub const querySelector = bridge.function(Document.querySelector, .{ .dom_exception = true }); pub const querySelectorAll = bridge.function(Document.querySelectorAll, .{ .dom_exception = true }); pub const getElementsByTagName = bridge.function(Document.getElementsByTagName, .{}); diff --git a/src/browser/webapi/Element.zig b/src/browser/webapi/Element.zig index 98bbbf7b..d6badbec 100644 --- a/src/browser/webapi/Element.zig +++ b/src/browser/webapi/Element.zig @@ -317,6 +317,20 @@ pub fn getOuterHTML(self: *Element, writer: *std.Io.Writer, page: *Page) !void { return dump.deep(self.asNode(), .{ .shadow = .skip }, writer, page); } +pub fn setOuterHTML(self: *Element, html: []const u8, page: *Page) !void { + const node = self.asNode(); + const parent = node._parent orelse return; + + page.domChanged(); + if (html.len > 0) { + const fragment = (try Node.DocumentFragment.init(page)).asNode(); + try page.parseHtmlAsChildren(fragment, html); + try page.insertAllChildrenBefore(fragment, parent, node); + } + + page.removeNode(parent, node, .{ .will_be_reconnected = false }); +} + pub fn getInnerHTML(self: *Element, writer: *std.Io.Writer, page: *Page) !void { const dump = @import("../dump.zig"); return dump.children(self.asNode(), .{ .shadow = .skip }, writer, page); @@ -1220,7 +1234,7 @@ pub const JsApi = struct { return buf.written(); } - pub const outerHTML = bridge.accessor(_outerHTML, null, .{}); + pub const outerHTML = bridge.accessor(_outerHTML, Element.setOuterHTML, .{}); fn _outerHTML(self: *Element, page: *Page) ![]const u8 { var buf = std.Io.Writer.Allocating.init(page.call_arena); try self.getOuterHTML(&buf.writer, page);