nodelist: implement iterators

This commit is contained in:
Pierre Tachoire
2024-09-25 09:37:14 +02:00
parent 30679d18ee
commit aefab86501
5 changed files with 140 additions and 5 deletions

View File

@@ -26,6 +26,7 @@ const Events = @import("events/event.zig");
const XHR = @import("xhr/xhr.zig");
const Storage = @import("storage/storage.zig");
const URL = @import("url/url.zig");
const Iterators = @import("iterator/iterator.zig");
pub const HTMLDocument = @import("html/document.zig").HTMLDocument;
@@ -38,6 +39,7 @@ pub const Interfaces = generate.Tuple(.{
XHR.Interfaces,
Storage.Interfaces,
URL.Interfaces,
Iterators.Interfaces,
});
pub const UserContext = @import("user_context.zig").UserContext;

View File

@@ -435,7 +435,11 @@ pub fn testExecFn(
.{ .src = "document.querySelector(':root').nodeName", .ex = "HTML" },
.{ .src = "document.querySelectorAll('p').length", .ex = "2" },
.{ .src = "document.querySelectorAll('.ok').item(0).id", .ex = "link" },
.{ .src =
\\Array.from(document.querySelectorAll('#content > p#para-empty'))
\\.map(row => row.querySelector('span').textContent)
\\.length;
, .ex = "1" },
};
try checkCases(js_env, &querySelector);

View File

@@ -23,7 +23,7 @@ const EventTarget = @import("event_target.zig").EventTarget;
const DOMImplementation = @import("implementation.zig").DOMImplementation;
const NamedNodeMap = @import("namednodemap.zig").NamedNodeMap;
const DOMTokenList = @import("token_list.zig").DOMTokenList;
const NodeList = @import("nodelist.zig").NodeList;
const NodeList = @import("nodelist.zig");
const Nod = @import("node.zig");
const MutationObserver = @import("mutation_observer.zig");
@@ -33,7 +33,7 @@ pub const Interfaces = generate.Tuple(.{
DOMImplementation,
NamedNodeMap,
DOMTokenList,
NodeList,
NodeList.Interfaces,
Nod.Node,
Nod.Interfaces,
MutationObserver.Interfaces,

View File

@@ -25,14 +25,78 @@ const Callback = jsruntime.Callback;
const CallbackResult = jsruntime.CallbackResult;
const Case = jsruntime.test_utils.Case;
const checkCases = jsruntime.test_utils.checkCases;
const generate = @import("../generate.zig");
const NodeUnion = @import("node.zig").Union;
const Node = @import("node.zig").Node;
const U32Iterator = @import("../iterator/iterator.zig").U32Iterator;
const log = std.log.scoped(.nodelist);
const DOMException = @import("exceptions.zig").DOMException;
pub const Interfaces = generate.Tuple(.{
NodeListIterator,
NodeList,
});
pub const NodeListIterator = struct {
pub const mem_guarantied = true;
coll: *NodeList,
index: u32 = 0,
pub const Return = struct {
value: ?NodeUnion,
done: bool,
};
pub fn _next(self: *NodeListIterator) !Return {
const e = try self.coll._item(self.index);
if (e == null) {
return Return{
.value = null,
.done = true,
};
}
self.index += 1;
return Return{
.value = e,
.done = false,
};
}
};
pub const NodeListEntriesIterator = struct {
pub const mem_guarantied = true;
coll: *NodeList,
index: u32 = 0,
pub const Return = struct {
value: ?NodeUnion,
done: bool,
};
pub fn _next(self: *NodeListEntriesIterator) !Return {
const e = try self.coll._item(self.index);
if (e == null) {
return Return{
.value = null,
.done = true,
};
}
self.index += 1;
return Return{
.value = e,
.done = false,
};
}
};
// Nodelist is implemented in pure Zig b/c libdom's NodeList doesn't allow to
// append nodes.
// WEB IDL https://dom.spec.whatwg.org/#nodelist
@@ -91,9 +155,38 @@ pub const NodeList = struct {
}
}
// TODO _symbol_iterator
pub fn _keys(self: *NodeList) U32Iterator {
log.debug("keys", .{});
return .{
.length = self.get_length(),
};
}
// TODO implement postAttach
pub fn _values(self: *NodeList) NodeListIterator {
log.debug("values", .{});
return .{
.coll = self,
};
}
pub fn _symbol_iterator(self: *NodeList) NodeListIterator {
log.debug("symbol", .{});
return self._values();
}
// TODO entries() https://developer.mozilla.org/en-US/docs/Web/API/NodeList/entries
pub fn postAttach(self: *NodeList, alloc: std.mem.Allocator, js_obj: jsruntime.JSObject) !void {
const ln = self.get_length();
var i: u32 = 0;
while (i < ln) {
defer i += 1;
const k = try std.fmt.allocPrint(alloc, "{d}", .{i});
const node = try self._item(i) orelse unreachable;
try js_obj.set(k, node);
}
}
};
// Tests
@@ -106,6 +199,7 @@ pub fn testExecFn(
var childnodes = [_]Case{
.{ .src = "let list = document.getElementById('content').childNodes", .ex = "undefined" },
.{ .src = "list.length", .ex = "9" },
.{ .src = "list[0].__proto__.constructor.name", .ex = "Text" },
.{ .src =
\\let i = 0;
\\list.forEach(function (n, idx) {

35
src/iterator/iterator.zig Normal file
View File

@@ -0,0 +1,35 @@
const std = @import("std");
const generate = @import("../generate.zig");
pub const Interfaces = generate.Tuple(.{
U32Iterator,
});
pub const U32Iterator = struct {
pub const mem_guarantied = true;
length: u32,
index: u32 = 0,
pub const Return = struct {
value: u32,
done: bool,
};
pub fn _next(self: *U32Iterator) !Return {
const i = self.index;
if (i >= self.length) {
return Return{
.value = 0,
.done = true,
};
}
self.index += 1;
return Return{
.value = i,
.done = false,
};
}
};