Skip to content

Commit 1849f4c

Browse files
Merge pull request #544 from lightpanda-io/token_list_iterators
Add missing TokenList APIs
2 parents 66ec087 + 9b4d1d4 commit 1849f4c

File tree

9 files changed

+394
-42
lines changed

9 files changed

+394
-42
lines changed

src/browser/dom/dom.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const DOMException = @import("exceptions.zig").DOMException;
2020
const EventTarget = @import("event_target.zig").EventTarget;
2121
const DOMImplementation = @import("implementation.zig").DOMImplementation;
2222
const NamedNodeMap = @import("namednodemap.zig").NamedNodeMap;
23-
const DOMTokenList = @import("token_list.zig").DOMTokenList;
23+
const DOMTokenList = @import("token_list.zig");
2424
const NodeList = @import("nodelist.zig");
2525
const Node = @import("node.zig");
2626
const MutationObserver = @import("mutation_observer.zig");
@@ -30,7 +30,7 @@ pub const Interfaces = .{
3030
EventTarget,
3131
DOMImplementation,
3232
NamedNodeMap,
33-
DOMTokenList,
33+
DOMTokenList.Interfaces,
3434
NodeList.Interfaces,
3535
Node.Node,
3636
Node.Interfaces,

src/browser/dom/html_collection.zig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const utils = @import("utils.z");
2424
const Element = @import("element.zig").Element;
2525
const Union = @import("element.zig").Union;
2626

27-
const JsObject = @import("../env.zig").JsObject;
27+
const JsThis = @import("../env.zig").JsThis;
2828

2929
const Walker = @import("walker.zig").Walker;
3030
const WalkerDepthFirst = @import("walker.zig").WalkerDepthFirst;
@@ -443,15 +443,15 @@ pub const HTMLCollection = struct {
443443
return null;
444444
}
445445

446-
pub fn postAttach(self: *HTMLCollection, js_obj: JsObject) !void {
446+
pub fn postAttach(self: *HTMLCollection, js_this: JsThis) !void {
447447
const len = try self.get_length();
448448
for (0..len) |i| {
449449
const node = try self.item(@intCast(i)) orelse unreachable;
450450
const e = @as(*parser.Element, @ptrCast(node));
451-
try js_obj.setIndex(@intCast(i), e);
451+
try js_this.setIndex(@intCast(i), e);
452452

453453
if (try item_name(e)) |name| {
454-
try js_obj.set(name, e);
454+
try js_this.set(name, e);
455455
}
456456
}
457457
}

src/browser/dom/mutation_observer.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const parser = @import("../netsurf.zig");
2222
const SessionState = @import("../env.zig").SessionState;
2323

2424
const Env = @import("../env.zig").Env;
25-
const JsObject = @import("../env.zig").JsObject;
25+
const JsThis = @import("../env.zig").JsThis;
2626
const NodeList = @import("nodelist.zig").NodeList;
2727

2828
pub const Interfaces = .{
@@ -184,9 +184,9 @@ pub const MutationRecords = struct {
184184
return null;
185185
};
186186
}
187-
pub fn postAttach(self: *const MutationRecords, js_obj: JsObject) !void {
187+
pub fn postAttach(self: *const MutationRecords, js_this: JsThis) !void {
188188
if (self.first) |mr| {
189-
try js_obj.set("0", mr);
189+
try js_this.set("0", mr);
190190
}
191191
}
192192
};

src/browser/dom/nodelist.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const std = @import("std");
2020

2121
const parser = @import("../netsurf.zig");
2222

23-
const JsObject = @import("../env.zig").JsObject;
23+
const JsThis = @import("../env.zig").JsThis;
2424
const Callback = @import("../env.zig").Callback;
2525
const SessionState = @import("../env.zig").SessionState;
2626

@@ -177,11 +177,11 @@ pub const NodeList = struct {
177177
}
178178

179179
// TODO entries() https://developer.mozilla.org/en-US/docs/Web/API/NodeList/entries
180-
pub fn postAttach(self: *NodeList, js_obj: JsObject) !void {
180+
pub fn postAttach(self: *NodeList, js_this: JsThis) !void {
181181
const len = self.get_length();
182182
for (0..len) |i| {
183183
const node = try self._item(@intCast(i)) orelse unreachable;
184-
try js_obj.setIndex(i, node);
184+
try js_this.setIndex(i, node);
185185
}
186186
}
187187
};

src/browser/dom/token_list.zig

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,22 @@
1919
const std = @import("std");
2020

2121
const parser = @import("../netsurf.zig");
22+
const iterator = @import("../iterator/iterator.zig");
2223

24+
const Callback = @import("../env.zig").Callback;
25+
const JsObject = @import("../env.zig").JsObject;
26+
const SessionState = @import("../env.zig").SessionState;
2327
const DOMException = @import("exceptions.zig").DOMException;
2428

29+
const log = std.log.scoped(.token_list);
30+
31+
pub const Interfaces = .{
32+
DOMTokenList,
33+
DOMTokenListIterable,
34+
TokenListEntriesIterator,
35+
TokenListEntriesIterator.Iterable,
36+
};
37+
2538
// https://dom.spec.whatwg.org/#domtokenlist
2639
pub const DOMTokenList = struct {
2740
pub const Self = parser.TokenList;
@@ -98,7 +111,60 @@ pub const DOMTokenList = struct {
98111
}
99112

100113
pub fn get_value(self: *parser.TokenList) !?[]const u8 {
101-
return try parser.tokenListGetValue(self);
114+
return (try parser.tokenListGetValue(self)) orelse "";
115+
}
116+
117+
pub fn set_value(self: *parser.TokenList, value: []const u8) !void {
118+
return parser.tokenListSetValue(self, value);
119+
}
120+
121+
pub fn _toString(self: *parser.TokenList) ![]const u8 {
122+
return (try get_value(self)) orelse "";
123+
}
124+
125+
pub fn _keys(self: *parser.TokenList) !iterator.U32Iterator {
126+
return .{ .length = try get_length(self) };
127+
}
128+
129+
pub fn _values(self: *parser.TokenList) DOMTokenListIterable {
130+
return DOMTokenListIterable.init(.{ .token_list = self });
131+
}
132+
133+
pub fn _entries(self: *parser.TokenList) TokenListEntriesIterator {
134+
return TokenListEntriesIterator.init(.{ .token_list = self });
135+
}
136+
137+
pub fn _symbol_iterator(self: *parser.TokenList) DOMTokenListIterable {
138+
return _values(self);
139+
}
140+
141+
// TODO handle thisArg
142+
pub fn _forEach(self: *parser.TokenList, cbk: Callback, this_arg: JsObject) !void {
143+
var entries = _entries(self);
144+
while (try entries._next()) |entry| {
145+
var result: Callback.Result = undefined;
146+
cbk.tryCallWithThis(this_arg, .{ entry.@"1", entry.@"0", self }, &result) catch {
147+
log.err("callback error: {s}", .{result.exception});
148+
log.debug("stack:\n{s}", .{result.stack orelse "???"});
149+
};
150+
}
151+
}
152+
};
153+
154+
const DOMTokenListIterable = iterator.Iterable(Iterator, "DOMTokenListIterable");
155+
const TokenListEntriesIterator = iterator.NumericEntries(Iterator, "TokenListEntriesIterator");
156+
157+
pub const Iterator = struct {
158+
index: u32 = 0,
159+
token_list: *parser.TokenList,
160+
161+
// used when wrapped in an iterator.NumericEntries
162+
pub const Error = parser.DOMError;
163+
164+
pub fn _next(self: *Iterator) !?[]const u8 {
165+
const index = self.index;
166+
self.index = index + 1;
167+
return DOMTokenList._item(self.token_list, index);
102168
}
103169
};
104170

@@ -150,4 +216,29 @@ test "Browser.DOM.TokenList" {
150216
.{ "cl4.replace('nok', 'ok')", "true" },
151217
.{ "cl4.value", "empty ok" },
152218
}, .{});
219+
220+
try runner.testCases(&.{
221+
.{ "let cl5 = gs.classList", "undefined" },
222+
.{ "let keys = [...cl5.keys()]", "undefined" },
223+
.{ "keys.length", "2" },
224+
.{ "keys[0]", "0" },
225+
.{ "keys[1]", "1" },
226+
227+
.{ "let values = [...cl5.values()]", "undefined" },
228+
.{ "values.length", "2" },
229+
.{ "values[0]", "empty" },
230+
.{ "values[1]", "ok" },
231+
232+
.{ "let entries = [...cl5.entries()]", "undefined" },
233+
.{ "entries.length", "2" },
234+
.{ "entries[0]", "0,empty" },
235+
.{ "entries[1]", "1,ok" },
236+
}, .{});
237+
238+
try runner.testCases(&.{
239+
.{ "let cl6 = gs.classList", "undefined" },
240+
.{ "cl6.value = 'a b ccc'", "a b ccc" },
241+
.{ "cl6.value", "a b ccc" },
242+
.{ "cl6.toString()", "a b ccc" },
243+
}, .{});
153244
}

src/browser/env.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const Interfaces = generate.Tuple(.{
2121
@import("xmlserializer/xmlserializer.zig").Interfaces,
2222
});
2323

24+
pub const JsThis = Env.JsThis;
2425
pub const JsObject = Env.JsObject;
2526
pub const Callback = Env.Callback;
2627
pub const Env = js.Env(*SessionState, Interfaces{});

0 commit comments

Comments
 (0)