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.
This commit is contained in:
Karl Seguin
2025-08-12 17:12:20 +08:00
parent a504f051e7
commit 3ef4ba6b8b

View File

@@ -180,11 +180,35 @@ pub const Node = struct {
}
pub fn get_isConnected(self: *parser.Node) !bool {
// TODO: handle Shadow DOM
if (try parser.nodeType(self) == .document) {
var node = self;
while (true) {
const node_type = try parser.nodeType(node);
if (node_type == .document) {
return true;
}
return try Node.get_parentNode(self) != null;
if (try parser.nodeParentNode(node)) |parent| {
// didn't find a document, but node has a parent, let's see
// if it's connected;
node = parent;
continue;
}
if (node_type != .document_fragment) {
// doesn't have a parent and isn't a document_fragment
// can't be connected
return false;
}
if (parser.documentFragmentGetHost(@ptrCast(node))) |host| {
// node doesn't have a parent, but it's a document fragment
// with a host. The host is like the parent, but we only want to
// traverse up (or down) to it in specific cases, like isConnected.
node = host;
continue;
}
return false;
}
}
// Read/Write attributes
@@ -652,7 +676,13 @@ test "Browser.DOM.node" {
try runner.testCases(&.{
.{ "content.isConnected", "true" },
.{ "document.isConnected", "true" },
.{ "document.createElement('div').isConnected", "false" },
.{ "const connDiv = document.createElement('div')", null },
.{ "connDiv.isConnected", "false" },
.{ "const connParentDiv = document.createElement('div')", null },
.{ "connParentDiv.appendChild(connDiv)", null },
.{ "connDiv.isConnected", "false" },
.{ "content.appendChild(connParentDiv)", null },
.{ "connDiv.isConnected", "true" },
}, .{});
try runner.testCases(&.{