Skip to content

Commit 97d414a

Browse files
committed
Fixing TreeWalker Filtering
1 parent 38c6fa9 commit 97d414a

File tree

1 file changed

+158
-52
lines changed

1 file changed

+158
-52
lines changed

src/browser/dom/tree_walker.zig

Lines changed: 158 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const parser = @import("../netsurf.zig");
2121

2222
const NodeFilter = @import("node_filter.zig").NodeFilter;
2323
const Env = @import("../env.zig").Env;
24+
const SessionState = @import("../env.zig").SessionState;
2425

2526
// https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker
2627
pub const TreeWalker = struct {
@@ -29,8 +30,6 @@ pub const TreeWalker = struct {
2930
what_to_show: u32,
3031
filter: ?Env.Function,
3132

32-
depth: usize,
33-
3433
pub const TreeWalkerOpts = union(enum) {
3534
function: Env.Function,
3635
object: struct { acceptNode: Env.Function },
@@ -51,14 +50,17 @@ pub const TreeWalker = struct {
5150
.current_node = node,
5251
.what_to_show = what_to_show orelse NodeFilter._SHOW_ALL,
5352
.filter = filter_func,
54-
.depth = 0,
5553
};
5654
}
5755

58-
fn verify_what_to_show(self: *const TreeWalker, node: *parser.Node) !bool {
56+
const VerifyResult = enum { accept, skip, reject };
57+
58+
fn verify(self: *const TreeWalker, node: *parser.Node) !VerifyResult {
5959
const node_type = try parser.nodeType(node);
6060
const what_to_show = self.what_to_show;
61-
return switch (node_type) {
61+
62+
// Verify that we can show this node type.
63+
if (!switch (node_type) {
6264
.attribute => what_to_show & NodeFilter._SHOW_ATTRIBUTE != 0,
6365
.cdata_section => what_to_show & NodeFilter._SHOW_CDATA_SECTION != 0,
6466
.comment => what_to_show & NodeFilter._SHOW_COMMENT != 0,
@@ -71,17 +73,18 @@ pub const TreeWalker = struct {
7173
.notation => what_to_show & NodeFilter._SHOW_NOTATION != 0,
7274
.processing_instruction => what_to_show & NodeFilter._SHOW_PROCESSING_INSTRUCTION != 0,
7375
.text => what_to_show & NodeFilter._SHOW_TEXT != 0,
74-
};
75-
}
76+
}) return .reject;
7677

77-
fn verify_filter(self: *const TreeWalker, node: *parser.Node) !bool {
78+
// Verify that we aren't filtering it out.
7879
if (self.filter) |f| {
7980
const filter = try f.call(u32, .{node});
8081
return switch (filter) {
81-
NodeFilter._FILTER_ACCEPT => true,
82-
else => false,
82+
NodeFilter._FILTER_ACCEPT => .accept,
83+
NodeFilter._FILTER_REJECT => .reject,
84+
NodeFilter._FILTER_SKIP => .skip,
85+
else => .reject,
8386
};
84-
} else return true;
87+
} else return .accept;
8588
}
8689

8790
pub fn get_root(self: *TreeWalker) *parser.Node {
@@ -100,88 +103,191 @@ pub const TreeWalker = struct {
100103
return self.filter;
101104
}
102105

103-
pub fn _firstChild(self: *TreeWalker) !?*parser.Node {
104-
const children = try parser.nodeGetChildNodes(self.current_node);
106+
pub fn set_currentNode(self: *TreeWalker, node: *parser.Node) !void {
107+
self.current_node = node;
108+
}
109+
110+
fn firstChild(self: *const TreeWalker, node: *parser.Node) !?*parser.Node {
111+
const children = try parser.nodeGetChildNodes(node);
105112
const child_count = try parser.nodeListLength(children);
106113

107114
for (0..child_count) |i| {
108115
const index: u32 = @intCast(i);
109116
const child = (try parser.nodeListItem(children, index)) orelse return null;
110117

111-
if (!try self.verify_what_to_show(child)) continue;
112-
if (!try self.verify_filter(child)) continue;
113-
114-
self.depth += 1;
115-
self.current_node = child;
116-
return child;
118+
switch (try self.verify(child)) {
119+
.accept => return child,
120+
.reject => continue,
121+
.skip => if (try self.firstChild(child)) |gchild| return gchild,
122+
}
117123
}
118124

119125
return null;
120126
}
121127

122-
pub fn _lastChild(self: *TreeWalker) !?*parser.Node {
123-
const children = try parser.nodeGetChildNodes(self.current_node);
128+
fn lastChild(self: *const TreeWalker, node: *parser.Node) !?*parser.Node {
129+
const children = try parser.nodeGetChildNodes(node);
124130
const child_count = try parser.nodeListLength(children);
125131

126-
for (0..child_count) |i| {
127-
const index: u32 = @intCast(child_count - 1 - i);
132+
var index: u32 = child_count;
133+
while (index > 0) {
134+
index -= 1;
128135
const child = (try parser.nodeListItem(children, index)) orelse return null;
129136

130-
if (!try self.verify_what_to_show(child)) continue;
131-
if (!try self.verify_filter(child)) continue;
137+
switch (try self.verify(child)) {
138+
.accept => return child,
139+
.reject => continue,
140+
.skip => if (try self.lastChild(child)) |gchild| return gchild,
141+
}
142+
}
143+
144+
return null;
145+
}
146+
147+
fn nextSibling(self: *const TreeWalker, node: *parser.Node) !?*parser.Node {
148+
var current = node;
132149

133-
self.depth += 1;
150+
while (true) {
151+
current = (try parser.nodeNextSibling(current)) orelse return null;
152+
153+
switch (try self.verify(current)) {
154+
.accept => return current,
155+
.skip, .reject => continue,
156+
}
157+
}
158+
159+
return null;
160+
}
161+
162+
fn previousSibling(self: *const TreeWalker, node: *parser.Node) !?*parser.Node {
163+
var current = node;
164+
165+
while (true) {
166+
current = (try parser.nodePreviousSibling(current)) orelse return null;
167+
168+
switch (try self.verify(current)) {
169+
.accept => return current,
170+
.skip, .reject => continue,
171+
}
172+
}
173+
174+
return null;
175+
}
176+
177+
fn parentNode(self: *const TreeWalker, node: *parser.Node) !?*parser.Node {
178+
if (self.root == node) return null;
179+
180+
var current = node;
181+
while (true) {
182+
if (current == self.root) return null;
183+
current = (try parser.nodeParentNode(current)) orelse return null;
184+
185+
switch (try self.verify(current)) {
186+
.accept => return current,
187+
.reject, .skip => continue,
188+
}
189+
}
190+
}
191+
192+
pub fn _firstChild(self: *TreeWalker) !?*parser.Node {
193+
if (try self.firstChild(self.current_node)) |child| {
134194
self.current_node = child;
135195
return child;
136196
}
137197

138198
return null;
139199
}
140200

141-
pub fn _nextNode(self: *TreeWalker) !?*parser.Node {
142-
return self._firstChild();
201+
pub fn _lastChild(self: *TreeWalker) !?*parser.Node {
202+
if (try self.lastChild(self.current_node)) |child| {
203+
self.current_node = child;
204+
return child;
205+
}
206+
207+
return null;
143208
}
144209

145-
pub fn _nextSibling(self: *TreeWalker) !?*parser.Node {
210+
pub fn _nextNode(self: *TreeWalker) !?*parser.Node {
211+
if (try self.firstChild(self.current_node)) |child| {
212+
self.current_node = child;
213+
return child;
214+
}
215+
146216
var current = self.current_node;
217+
while (current != self.root) {
218+
if (try self.nextSibling(current)) |sibling| {
219+
self.current_node = sibling;
220+
return sibling;
221+
}
147222

148-
while (true) {
149-
current = (try parser.nodeNextSibling(current)) orelse return null;
150-
if (!try self.verify_what_to_show(current)) continue;
151-
if (!try self.verify_filter(current)) continue;
152-
break;
223+
current = (try parser.nodeParentNode(current)) orelse break;
153224
}
154225

155-
return current;
226+
return null;
156227
}
157228

158-
pub fn _parentNode(self: *TreeWalker) !?*parser.Node {
159-
if (self.depth == 0) return null;
229+
pub fn _nextSibling(self: *TreeWalker) !?*parser.Node {
230+
if (try self.nextSibling(self.current_node)) |sibling| {
231+
self.current_node = sibling;
232+
return sibling;
233+
}
160234

161-
const parent = (try parser.nodeParentNode(self.current_node)) orelse return null;
235+
return null;
236+
}
162237

163-
if (!try self.verify_what_to_show(parent)) return null;
164-
if (!try self.verify_filter(parent)) return null;
238+
pub fn _parentNode(self: *TreeWalker) !?*parser.Node {
239+
if (try self.parentNode(self.current_node)) |parent| {
240+
self.current_node = parent;
241+
return parent;
242+
}
165243

166-
self.depth -= 1;
167-
self.current_node = parent;
168-
return parent;
244+
return null;
169245
}
170246

171247
pub fn _previousNode(self: *TreeWalker) !?*parser.Node {
172-
return self._parentNode();
248+
var current = self.current_node;
249+
while (try parser.nodePreviousSibling(current)) |previous| {
250+
current = previous;
251+
252+
switch (try self.verify(current)) {
253+
.accept => {
254+
// Get last child if it has one.
255+
if (try self.lastChild(current)) |child| {
256+
self.current_node = child;
257+
return child;
258+
}
259+
260+
// Otherwise, this node is our previous one.
261+
self.current_node = current;
262+
return current;
263+
},
264+
.reject => continue,
265+
.skip => {
266+
// Get last child if it has one.
267+
if (try self.lastChild(current)) |child| {
268+
self.current_node = child;
269+
return child;
270+
}
271+
},
272+
}
273+
}
274+
275+
if (current != self.root) {
276+
if (try self.parentNode(current)) |parent| {
277+
self.current_node = parent;
278+
return parent;
279+
}
280+
}
281+
282+
return null;
173283
}
174284

175285
pub fn _previousSibling(self: *TreeWalker) !?*parser.Node {
176-
var current = self.current_node;
177-
178-
while (true) {
179-
current = (try parser.nodePreviousSibling(current)) orelse return null;
180-
if (!try self.verify_what_to_show(current)) continue;
181-
if (!try self.verify_filter(current)) continue;
182-
break;
286+
if (try self.previousSibling(self.current_node)) |sibling| {
287+
self.current_node = sibling;
288+
return sibling;
183289
}
184290

185-
return current;
291+
return null;
186292
}
187293
};

0 commit comments

Comments
 (0)