Merge pull request #1324 from lightpanda-io/elements_by_name_nodelist

getElementsByName now returns a NodeList rather than an HTMLCollection
This commit is contained in:
Karl Seguin
2026-01-07 10:41:54 +08:00
committed by GitHub
4 changed files with 16 additions and 8 deletions

View File

@@ -411,7 +411,7 @@ fn attachClass(comptime JsApi: type, isolate: v8.Isolate, template: v8.FunctionT
}, },
bridge.Function => { bridge.Function => {
const function_template = v8.FunctionTemplate.initCallback(isolate, value.func); const function_template = v8.FunctionTemplate.initCallback(isolate, value.func);
const js_name: v8.Name = v8.String.initUtf8(isolate, name).toName(); const js_name = v8.String.initUtf8(isolate, name).toName();
if (value.static) { if (value.static) {
template.set(js_name, function_template, v8.PropertyAttribute.None); template.set(js_name, function_template, v8.PropertyAttribute.None);
} else { } else {
@@ -460,6 +460,12 @@ fn attachClass(comptime JsApi: type, isolate: v8.Isolate, template: v8.FunctionT
instance_template.markAsUndetectable(); instance_template.markAsUndetectable();
instance_template.setCallAsFunctionHandler(JsApi.Meta.callable.func); instance_template.setCallAsFunctionHandler(JsApi.Meta.callable.func);
} }
if (@hasDecl(JsApi.Meta, "name")) {
const js_name = v8.Symbol.getToStringTag(isolate).toName();
const instance_template = template.getInstanceTemplate();
instance_template.set(js_name, v8.String.initUtf8(isolate, JsApi.Meta.name), v8.PropertyAttribute.ReadOnly + v8.PropertyAttribute.DontDelete);
}
} }
fn protoIndexLookup(comptime JsApi: type) ?bridge.JsApiLookup.BackingInt { fn protoIndexLookup(comptime JsApi: type) ?bridge.JsApiLookup.BackingInt {

View File

@@ -28,7 +28,6 @@ const Mode = enum {
tag, tag,
tag_name, tag_name,
class_name, class_name,
name,
all_elements, all_elements,
child_elements, child_elements,
child_tag, child_tag,
@@ -44,7 +43,6 @@ _data: union(Mode) {
tag: NodeLive(.tag), tag: NodeLive(.tag),
tag_name: NodeLive(.tag_name), tag_name: NodeLive(.tag_name),
class_name: NodeLive(.class_name), class_name: NodeLive(.class_name),
name: NodeLive(.name),
all_elements: NodeLive(.all_elements), all_elements: NodeLive(.all_elements),
child_elements: NodeLive(.child_elements), child_elements: NodeLive(.child_elements),
child_tag: NodeLive(.child_tag), child_tag: NodeLive(.child_tag),
@@ -79,7 +77,6 @@ pub fn iterator(self: *HTMLCollection, page: *Page) !*Iterator {
.tag => |*impl| .{ .tag = impl._tw.clone() }, .tag => |*impl| .{ .tag = impl._tw.clone() },
.tag_name => |*impl| .{ .tag_name = impl._tw.clone() }, .tag_name => |*impl| .{ .tag_name = impl._tw.clone() },
.class_name => |*impl| .{ .class_name = impl._tw.clone() }, .class_name => |*impl| .{ .class_name = impl._tw.clone() },
.name => |*impl| .{ .name = impl._tw.clone() },
.all_elements => |*impl| .{ .all_elements = impl._tw.clone() }, .all_elements => |*impl| .{ .all_elements = impl._tw.clone() },
.child_elements => |*impl| .{ .child_elements = impl._tw.clone() }, .child_elements => |*impl| .{ .child_elements = impl._tw.clone() },
.child_tag => |*impl| .{ .child_tag = impl._tw.clone() }, .child_tag => |*impl| .{ .child_tag = impl._tw.clone() },
@@ -98,7 +95,6 @@ pub const Iterator = GenericIterator(struct {
tag: TreeWalker.FullExcludeSelf, tag: TreeWalker.FullExcludeSelf,
tag_name: TreeWalker.FullExcludeSelf, tag_name: TreeWalker.FullExcludeSelf,
class_name: TreeWalker.FullExcludeSelf, class_name: TreeWalker.FullExcludeSelf,
name: TreeWalker.FullExcludeSelf,
all_elements: TreeWalker.FullExcludeSelf, all_elements: TreeWalker.FullExcludeSelf,
child_elements: TreeWalker.Children, child_elements: TreeWalker.Children,
child_tag: TreeWalker.Children, child_tag: TreeWalker.Children,
@@ -113,7 +109,6 @@ pub const Iterator = GenericIterator(struct {
.tag => |*impl| impl.nextTw(&self.tw.tag), .tag => |*impl| impl.nextTw(&self.tw.tag),
.tag_name => |*impl| impl.nextTw(&self.tw.tag_name), .tag_name => |*impl| impl.nextTw(&self.tw.tag_name),
.class_name => |*impl| impl.nextTw(&self.tw.class_name), .class_name => |*impl| impl.nextTw(&self.tw.class_name),
.name => |*impl| impl.nextTw(&self.tw.name),
.all_elements => |*impl| impl.nextTw(&self.tw.all_elements), .all_elements => |*impl| impl.nextTw(&self.tw.all_elements),
.child_elements => |*impl| impl.nextTw(&self.tw.child_elements), .child_elements => |*impl| impl.nextTw(&self.tw.child_elements),
.child_tag => |*impl| impl.nextTw(&self.tw.child_tag), .child_tag => |*impl| impl.nextTw(&self.tw.child_tag),

View File

@@ -26,11 +26,13 @@ const Node = @import("../Node.zig");
const ChildNodes = @import("ChildNodes.zig"); const ChildNodes = @import("ChildNodes.zig");
const RadioNodeList = @import("RadioNodeList.zig"); const RadioNodeList = @import("RadioNodeList.zig");
const SelectorList = @import("../selector/List.zig"); const SelectorList = @import("../selector/List.zig");
const NodeLive = @import("node_live.zig").NodeLive;
const Mode = enum { const Mode = enum {
child_nodes, child_nodes,
selector_list, selector_list,
radio_node_list, radio_node_list,
name,
}; };
const NodeList = @This(); const NodeList = @This();
@@ -39,6 +41,7 @@ data: union(Mode) {
child_nodes: *ChildNodes, child_nodes: *ChildNodes,
selector_list: *SelectorList, selector_list: *SelectorList,
radio_node_list: *RadioNodeList, radio_node_list: *RadioNodeList,
name: NodeLive(.name),
}, },
pub fn length(self: *NodeList, page: *Page) !u32 { pub fn length(self: *NodeList, page: *Page) !u32 {
@@ -46,6 +49,7 @@ pub fn length(self: *NodeList, page: *Page) !u32 {
.child_nodes => |impl| impl.length(page), .child_nodes => |impl| impl.length(page),
.selector_list => |impl| @intCast(impl.getLength()), .selector_list => |impl| @intCast(impl.getLength()),
.radio_node_list => |impl| impl.getLength(), .radio_node_list => |impl| impl.getLength(),
.name => |*impl| impl.length(page),
}; };
} }
@@ -54,6 +58,7 @@ pub fn getAtIndex(self: *NodeList, index: usize, page: *Page) !?*Node {
.child_nodes => |impl| impl.getAtIndex(index, page), .child_nodes => |impl| impl.getAtIndex(index, page),
.selector_list => |impl| impl.getAtIndex(index), .selector_list => |impl| impl.getAtIndex(index),
.radio_node_list => |impl| impl.getAtIndex(index, page), .radio_node_list => |impl| impl.getAtIndex(index, page),
.name => |*impl| if (impl.getAtIndex(index, page)) |el| el.asNode() else null,
}; };
} }

View File

@@ -320,12 +320,14 @@ pub fn NodeLive(comptime mode: Mode) type {
} }
const HTMLCollection = @import("HTMLCollection.zig"); const HTMLCollection = @import("HTMLCollection.zig");
pub fn runtimeGenericWrap(self: Self, page: *Page) !*HTMLCollection { const NodeList = @import("NodeList.zig");
pub fn runtimeGenericWrap(self: Self, page: *Page) !if (mode == .name) *NodeList else *HTMLCollection {
const collection = switch (mode) { const collection = switch (mode) {
.name => return page._factory.create(NodeList{ .data = .{ .name = self } }),
.tag => HTMLCollection{ ._data = .{ .tag = self } }, .tag => HTMLCollection{ ._data = .{ .tag = self } },
.tag_name => HTMLCollection{ ._data = .{ .tag_name = self } }, .tag_name => HTMLCollection{ ._data = .{ .tag_name = self } },
.class_name => HTMLCollection{ ._data = .{ .class_name = self } }, .class_name => HTMLCollection{ ._data = .{ .class_name = self } },
.name => HTMLCollection{ ._data = .{ .name = self } },
.all_elements => HTMLCollection{ ._data = .{ .all_elements = self } }, .all_elements => HTMLCollection{ ._data = .{ .all_elements = self } },
.child_elements => HTMLCollection{ ._data = .{ .child_elements = self } }, .child_elements => HTMLCollection{ ._data = .{ .child_elements = self } },
.child_tag => HTMLCollection{ ._data = .{ .child_tag = self } }, .child_tag => HTMLCollection{ ._data = .{ .child_tag = self } },