Skip to content

Commit 3eb0d57

Browse files
committed
correct element insertation in insertAdjacentHTML
* also DRY since the loop is repeated multiple times.
1 parent 902b8fc commit 3eb0d57

File tree

1 file changed

+34
-35
lines changed

1 file changed

+34
-35
lines changed

src/browser/dom/element.zig

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -242,57 +242,56 @@ pub const Element = struct {
242242
};
243243

244244
// Parse the fragment.
245+
// Should return error.Syntax on fail?
245246
const fragment = try parser.documentParseFragmentFromStr(doc, input);
246247
const fragment_node = parser.documentFragmentToNode(fragment);
247248

248249
// We always get it wrapped like so:
249250
// <html><head></head><body>{ ... }</body></html>
250-
const html = parser.nodeFirstChild(fragment_node) orelse return;
251-
const head = parser.nodeFirstChild(html) orelse return;
252-
const body = parser.nodeNextSibling(head) orelse return;
251+
// None of the following can be null.
252+
const html = parser.nodeFirstChild(fragment_node).?;
253+
const body = parser.nodeLastChild(html).?;
253254

254255
const children = try parser.nodeGetChildNodes(body);
255-
const len = parser.nodeListLength(children);
256256

257-
if (std.mem.eql(u8, position, "beforeend")) {
258-
for (0..len) |_| {
259-
const child = parser.nodeListItem(children, 0) orelse continue;
260-
_ = try parser.nodeInsertBefore(self_node, child, null);
257+
// * `target_node` is `*Node` (where we actually insert),
258+
// * `prev_node` is `?*Node`.
259+
const target_node, const prev_node = blk: {
260+
// Prefer case-sensitive match.
261+
// "beforeend" was the most common case in my tests; we might adjust the order
262+
// depending on which ones websites prefer most.
263+
if (std.mem.eql(u8, position, "beforeend")) {
264+
break :blk .{ self_node, null };
261265
}
262-
} else if (std.mem.eql(u8, position, "afterbegin")) {
263-
const target = parser.nodeFirstChild(self_node) orelse self_node;
264-
for (0..len) |_| {
265-
const child = parser.nodeListItem(children, 0) orelse continue;
266-
_ = try parser.nodeInsertBefore(target, child, null);
267-
}
268-
} else if (std.mem.eql(u8, position, "beforebegin")) {
269-
const parent = parser.nodeParentNode(self_node) orelse {
270-
return error.NoModificationAllowed;
271-
};
272266

273-
// Make sure parent is not Document.
274-
// Should also check for document_fragment and document_type?
275-
if (parser.nodeType(parent) == .document) {
276-
return error.NoModificationAllowed;
267+
if (std.mem.eql(u8, position, "afterbegin")) {
268+
// Get the first child; null indicates there are no children.
269+
const first_child = parser.nodeFirstChild(self_node);
270+
break :blk .{ self_node, first_child };
277271
}
278272

279-
for (0..len) |_| {
280-
const child = parser.nodeListItem(children, 0) orelse continue;
281-
_ = try parser.nodeInsertBefore(parent, child, self_node);
273+
if (std.mem.eql(u8, position, "beforebegin")) {
274+
// The node must have a parent node in order to use this variant.
275+
const parent = parser.nodeParentNode(self_node) orelse return error.NoModificationAllowed;
276+
break :blk .{ parent, self_node };
282277
}
283-
} else if (std.mem.eql(u8, position, "afterend")) {
284-
const parent = parser.nodeParentNode(self_node) orelse {
285-
return error.NoModificationAllowed;
286-
};
287278

288-
if (parser.nodeType(parent) == .document) {
289-
return error.NoModificationAllowed;
279+
if (std.mem.eql(u8, position, "afterend")) {
280+
// The node must have a parent node in order to use this variant.
281+
const parent = parser.nodeParentNode(self_node) orelse return error.NoModificationAllowed;
282+
// Get the next sibling or null; null indicates our node is the only one.
283+
const sibling = parser.nodeNextSibling(self_node);
284+
break :blk .{ parent, sibling };
290285
}
291286

292-
for (0..len) |_| {
293-
const child = parser.nodeListItem(children, 0) orelse continue;
294-
_ = try parser.nodeInsertBefore(parent, child, null);
295-
}
287+
// Thrown if:
288+
// * position is not one of the four listed values.
289+
// * The input is XML that is not well-formed.
290+
return error.Syntax;
291+
};
292+
293+
while (parser.nodeListItem(children, 0)) |child| {
294+
_ = try parser.nodeInsertBefore(target_node, child, prev_node);
296295
}
297296
}
298297

0 commit comments

Comments
 (0)