|
19 | 19 | const std = @import("std"); |
20 | 20 |
|
21 | 21 | const parser = @import("../netsurf.zig"); |
| 22 | +const iterator = @import("../iterator/iterator.zig"); |
22 | 23 |
|
| 24 | +const Callback = @import("../env.zig").Callback; |
| 25 | +const JsObject = @import("../env.zig").JsObject; |
| 26 | +const SessionState = @import("../env.zig").SessionState; |
23 | 27 | const DOMException = @import("exceptions.zig").DOMException; |
24 | 28 |
|
| 29 | +const log = std.log.scoped(.token_list); |
| 30 | + |
| 31 | +pub const Interfaces = .{ |
| 32 | + DOMTokenList, |
| 33 | + DOMTokenListIterable, |
| 34 | + TokenListEntriesIterator, |
| 35 | + TokenListEntriesIterator.Iterable, |
| 36 | +}; |
| 37 | + |
25 | 38 | // https://dom.spec.whatwg.org/#domtokenlist |
26 | 39 | pub const DOMTokenList = struct { |
27 | 40 | pub const Self = parser.TokenList; |
@@ -98,7 +111,60 @@ pub const DOMTokenList = struct { |
98 | 111 | } |
99 | 112 |
|
100 | 113 | 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); |
102 | 168 | } |
103 | 169 | }; |
104 | 170 |
|
@@ -150,4 +216,29 @@ test "Browser.DOM.TokenList" { |
150 | 216 | .{ "cl4.replace('nok', 'ok')", "true" }, |
151 | 217 | .{ "cl4.value", "empty ok" }, |
152 | 218 | }, .{}); |
| 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 | + }, .{}); |
153 | 244 | } |
0 commit comments