document.applets should always return an empty collection

Add a new .empty mode to HTMLCollection.

Fixes WPT /shadow-dom/leaktests/html-collection.html
This commit is contained in:
Karl Seguin
2026-03-09 18:06:22 +08:00
parent 034b089433
commit 183643547b
4 changed files with 15 additions and 6 deletions

View File

@@ -6,6 +6,7 @@
</html>
<script src="../testing.js"></script>
<applet></applet>
<script id=document>
testing.expectEqual('HTMLDocument', document.__proto__.constructor.name);
@@ -23,7 +24,7 @@
testing.expectEqual(2, document.scripts.length);
testing.expectEqual(0, document.forms.length);
testing.expectEqual(1, document.links.length);
testing.expectEqual(0, document.applets.length);
testing.expectEqual(0, document.applets.length); // deprecated, always returns 0
testing.expectEqual(0, document.anchors.length);
testing.expectEqual(7, document.all.length);
testing.expectEqual('document', document.currentScript.id);

View File

@@ -167,9 +167,8 @@ pub fn getEmbeds(self: *HTMLDocument, page: *Page) !collections.NodeLive(.tag) {
return collections.NodeLive(.tag).init(self.asNode(), .embed, page);
}
const applet_string = String.init(undefined, "applet", .{}) catch unreachable;
pub fn getApplets(self: *HTMLDocument, page: *Page) !collections.NodeLive(.tag_name) {
return collections.NodeLive(.tag_name).init(self.asNode(), applet_string, page);
pub fn getApplets(_: *const HTMLDocument) collections.HTMLCollection {
return .{ ._data = .empty };
}
pub fn getCurrentScript(self: *const HTMLDocument) ?*Element.Html.Script {

View File

@@ -20,14 +20,15 @@ pub const NodeLive = @import("collections/node_live.zig").NodeLive;
pub const ChildNodes = @import("collections/ChildNodes.zig");
pub const DOMTokenList = @import("collections/DOMTokenList.zig");
pub const RadioNodeList = @import("collections/RadioNodeList.zig");
pub const HTMLCollection = @import("collections/HTMLCollection.zig");
pub const HTMLAllCollection = @import("collections/HTMLAllCollection.zig");
pub const HTMLOptionsCollection = @import("collections/HTMLOptionsCollection.zig");
pub const HTMLFormControlsCollection = @import("collections/HTMLFormControlsCollection.zig");
pub fn registerTypes() []const type {
return &.{
@import("collections/HTMLCollection.zig"),
@import("collections/HTMLCollection.zig").Iterator,
HTMLCollection,
HTMLCollection.Iterator,
@import("collections/NodeList.zig"),
@import("collections/NodeList.zig").KeyIterator,
@import("collections/NodeList.zig").ValueIterator,

View File

@@ -36,6 +36,7 @@ const Mode = enum {
links,
anchors,
form,
empty,
};
const HTMLCollection = @This();
@@ -52,22 +53,26 @@ _data: union(Mode) {
links: NodeLive(.links),
anchors: NodeLive(.anchors),
form: NodeLive(.form),
empty: void,
},
pub fn length(self: *HTMLCollection, page: *const Page) u32 {
return switch (self._data) {
.empty => 0,
inline else => |*impl| impl.length(page),
};
}
pub fn getAtIndex(self: *HTMLCollection, index: usize, page: *const Page) ?*Element {
return switch (self._data) {
.empty => null,
inline else => |*impl| impl.getAtIndex(index, page),
};
}
pub fn getByName(self: *HTMLCollection, name: []const u8, page: *Page) ?*Element {
return switch (self._data) {
.empty => null,
inline else => |*impl| impl.getByName(name, page),
};
}
@@ -87,6 +92,7 @@ pub fn iterator(self: *HTMLCollection, page: *Page) !*Iterator {
.links => |*impl| .{ .links = impl._tw.clone() },
.anchors => |*impl| .{ .anchors = impl._tw.clone() },
.form => |*impl| .{ .form = impl._tw.clone() },
.empty => .empty,
},
}, page);
}
@@ -106,6 +112,7 @@ pub const Iterator = GenericIterator(struct {
links: TreeWalker.FullExcludeSelf,
anchors: TreeWalker.FullExcludeSelf,
form: TreeWalker.FullExcludeSelf,
empty: void,
},
pub fn next(self: *@This(), _: *Page) ?*Element {
@@ -121,6 +128,7 @@ pub const Iterator = GenericIterator(struct {
.links => |*impl| impl.nextTw(&self.tw.links),
.anchors => |*impl| impl.nextTw(&self.tw.anchors),
.form => |*impl| impl.nextTw(&self.tw.form),
.empty => return null,
};
}
}, null);