Skip to content

Commit 0c016c9

Browse files
committed
Fix Node.isConnected
The previous implementation just checked if a node had a parent. But it should check the node has a document ancestor: ``` const d1 = document.createElement('div'); document.createElement('div').appendChild(d1); d1.isConnected ``` should be `false`. In addition to this fix, also added support for DocumentFragments which are part of the ShadowRoot. This, like events, is one of those apis that DOES break the ShadowRoot isolation.
1 parent 6a2dd11 commit 0c016c9

File tree

2 files changed

+38
-8
lines changed

2 files changed

+38
-8
lines changed

src/browser/dom/node.zig

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,35 @@ pub const Node = struct {
180180
}
181181

182182
pub fn get_isConnected(self: *parser.Node) !bool {
183-
// TODO: handle Shadow DOM
184-
if (try parser.nodeType(self) == .document) {
185-
return true;
183+
var node = self;
184+
while (true) {
185+
const node_type = try parser.nodeType(node);
186+
if (node_type == .document) {
187+
return true;
188+
}
189+
190+
if (try parser.nodeParentNode(node)) |parent| {
191+
// didn't find a document, but node has a parent, let's see
192+
// if it's connected;
193+
node = parent;
194+
continue;
195+
}
196+
197+
if (node_type != .document_fragment) {
198+
// doesn't have a parent and isn't a document_fragment
199+
// can't be connected
200+
return false;
201+
}
202+
203+
if (parser.documentFragmentGetHost(@ptrCast(node))) |host| {
204+
// node doesn't have a parent, but it's a document fragment
205+
// with a host. The host is like the parent, but we only want to
206+
// traverse up (or down) to it in specific cases, like isConnected.
207+
node = host;
208+
continue;
209+
}
210+
return false;
186211
}
187-
return try Node.get_parentNode(self) != null;
188212
}
189213

190214
// Read/Write attributes
@@ -652,7 +676,13 @@ test "Browser.DOM.node" {
652676
try runner.testCases(&.{
653677
.{ "content.isConnected", "true" },
654678
.{ "document.isConnected", "true" },
655-
.{ "document.createElement('div').isConnected", "false" },
679+
.{ "const connDiv = document.createElement('div')", null },
680+
.{ "connDiv.isConnected", "false" },
681+
.{ "const connParentDiv = document.createElement('div')", null },
682+
.{ "connParentDiv.appendChild(connDiv)", null },
683+
.{ "connDiv.isConnected", "false" },
684+
.{ "content.appendChild(connParentDiv)", null },
685+
.{ "connDiv.isConnected", "true" },
656686
}, .{});
657687

658688
try runner.testCases(&.{

src/browser/dom/shadow_root.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ const testing = @import("../../testing.zig");
6262
test "Browser.DOM.ShadowRoot" {
6363
defer testing.reset();
6464

65-
var runner = try testing.jsRunner(testing.tracking_allocator, .{ .html =
65+
var runner = try testing.jsRunner(testing.tracking_allocator, .{ .html =
6666
\\ <div id=conflict>nope</div>
6767
});
6868
defer runner.deinit();
@@ -94,8 +94,8 @@ test "Browser.DOM.ShadowRoot" {
9494
try runner.testCases(&.{
9595
.{ "sr2.getElementById('conflict')", "null" },
9696
.{ "const n1 = document.createElement('div')", null },
97-
.{ "n1.id = 'conflict'", null},
98-
.{ "sr2.append(n1)", null},
97+
.{ "n1.id = 'conflict'", null },
98+
.{ "sr2.append(n1)", null },
9999
.{ "sr2.getElementById('conflict') == n1", "true" },
100100
}, .{});
101101

0 commit comments

Comments
 (0)