fix callback crash with Node.Union
Some checks failed
e2e-test / zig build release (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
e2e-test / cdp-and-hyperfine-bench (push) Has been cancelled
e2e-test / perf-fmt (push) Has been cancelled
zig-test / zig build dev (push) Has been cancelled
zig-test / browser fetch (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled

This commit is contained in:
sjorsdonkers
2025-07-10 10:26:44 +02:00
committed by Sjors
parent a8b72c1d5f
commit 49a97dbb66
3 changed files with 43 additions and 38 deletions

View File

@@ -19,6 +19,7 @@
const std = @import("std");
const parser = @import("../netsurf.zig");
const Env = @import("../env.zig").Env;
const Node = @import("node.zig").Node;
pub const NodeFilter = struct {
pub const _FILTER_ACCEPT: u16 = 1;
@@ -63,7 +64,7 @@ pub fn verify(what_to_show: u32, filter: ?Env.Function, node: *parser.Node) !Ver
// Verify that we aren't filtering it out.
if (filter) |f| {
const acceptance = try f.call(u16, .{node});
const acceptance = try f.call(u16, .{try Node.toInterface(node)});
return switch (acceptance) {
NodeFilter._FILTER_ACCEPT => .accept,
NodeFilter._FILTER_REJECT => .reject,

View File

@@ -20,9 +20,11 @@ const std = @import("std");
const parser = @import("../netsurf.zig");
const Env = @import("../env.zig").Env;
const NodeFilter = @import("node_filter.zig");
const Node = @import("node.zig").Node;
const NodeUnion = @import("node.zig").Union;
// https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator
// While this is similar to TreeWalker it has it's own implementation as there are several suttle differences
// While this is similar to TreeWalker it has its own implementation as there are several subtle differences
// For example:
// - nextNode returns the reference node, whereas TreeWalker returns the next node
// - Skip and reject are equivalent for NodeIterator, for TreeWalker they are different
@@ -66,36 +68,36 @@ pub const NodeIterator = struct {
return self.pointer_before_current;
}
pub fn get_referenceNode(self: *const NodeIterator) *parser.Node {
return self.reference_node;
pub fn get_referenceNode(self: *const NodeIterator) !NodeUnion {
return try Node.toInterface(self.reference_node);
}
pub fn get_root(self: *const NodeIterator) *parser.Node {
return self.root;
pub fn get_root(self: *const NodeIterator) !NodeUnion {
return try Node.toInterface(self.root);
}
pub fn get_whatToShow(self: *const NodeIterator) u32 {
return self.what_to_show;
}
pub fn _nextNode(self: *NodeIterator) !?*parser.Node {
pub fn _nextNode(self: *NodeIterator) !?NodeUnion {
if (self.pointer_before_current) { // Unlike TreeWalker, NodeIterator starts at the first node
self.pointer_before_current = false;
if (.accept == try NodeFilter.verify(self.what_to_show, self.filter_func, self.reference_node)) {
return self.reference_node;
return try Node.toInterface(self.reference_node);
}
}
if (try self.firstChild(self.reference_node)) |child| {
self.reference_node = child;
return child;
return try Node.toInterface(child);
}
var current = self.reference_node;
while (current != self.root) {
if (try self.nextSibling(current)) |sibling| {
self.reference_node = sibling;
return sibling;
return try Node.toInterface(sibling);
}
current = (try parser.nodeParentNode(current)) orelse break;
@@ -104,11 +106,11 @@ pub const NodeIterator = struct {
return null;
}
pub fn _previousNode(self: *NodeIterator) !?*parser.Node {
pub fn _previousNode(self: *NodeIterator) !?NodeUnion {
if (!self.pointer_before_current) {
self.pointer_before_current = true;
if (.accept == try NodeFilter.verify(self.what_to_show, self.filter_func, self.reference_node)) {
return self.reference_node; // Still need to verify as last may be first as well
return try Node.toInterface(self.reference_node); // Still need to verify as last may be first as well
}
}
if (self.reference_node == self.root) return null;
@@ -122,18 +124,18 @@ pub const NodeIterator = struct {
// Get last child if it has one.
if (try self.lastChild(current)) |child| {
self.reference_node = child;
return child;
return try Node.toInterface(child);
}
// Otherwise, this node is our previous one.
self.reference_node = current;
return current;
return try Node.toInterface(current);
},
.reject, .skip => {
// Get last child if it has one.
if (try self.lastChild(current)) |child| {
self.reference_node = child;
return child;
return try Node.toInterface(child);
}
},
}
@@ -142,7 +144,7 @@ pub const NodeIterator = struct {
if (current != self.root) {
if (try self.parentNode(current)) |parent| {
self.reference_node = parent;
return parent;
return try Node.toInterface(parent);
}
}

View File

@@ -22,6 +22,8 @@ const parser = @import("../netsurf.zig");
const NodeFilter = @import("node_filter.zig");
const Env = @import("../env.zig").Env;
const Page = @import("../page.zig").Page;
const Node = @import("node.zig").Node;
const NodeUnion = @import("node.zig").Union;
// https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker
pub const TreeWalker = struct {
@@ -55,12 +57,12 @@ pub const TreeWalker = struct {
};
}
pub fn get_root(self: *TreeWalker) *parser.Node {
return self.root;
pub fn get_root(self: *TreeWalker) !NodeUnion {
return try Node.toInterface(self.root);
}
pub fn get_currentNode(self: *TreeWalker) *parser.Node {
return self.current_node;
pub fn get_currentNode(self: *TreeWalker) !NodeUnion {
return try Node.toInterface(self.current_node);
}
pub fn get_whatToShow(self: *TreeWalker) u32 {
@@ -157,35 +159,35 @@ pub const TreeWalker = struct {
}
}
pub fn _firstChild(self: *TreeWalker) !?*parser.Node {
pub fn _firstChild(self: *TreeWalker) !?NodeUnion {
if (try self.firstChild(self.current_node)) |child| {
self.current_node = child;
return child;
return try Node.toInterface(child);
}
return null;
}
pub fn _lastChild(self: *TreeWalker) !?*parser.Node {
pub fn _lastChild(self: *TreeWalker) !?NodeUnion {
if (try self.lastChild(self.current_node)) |child| {
self.current_node = child;
return child;
return try Node.toInterface(child);
}
return null;
}
pub fn _nextNode(self: *TreeWalker) !?*parser.Node {
pub fn _nextNode(self: *TreeWalker) !?NodeUnion {
if (try self.firstChild(self.current_node)) |child| {
self.current_node = child;
return child;
return try Node.toInterface(child);
}
var current = self.current_node;
while (current != self.root) {
if (try self.nextSibling(current)) |sibling| {
self.current_node = sibling;
return sibling;
return try Node.toInterface(sibling);
}
current = (try parser.nodeParentNode(current)) orelse break;
@@ -194,25 +196,25 @@ pub const TreeWalker = struct {
return null;
}
pub fn _nextSibling(self: *TreeWalker) !?*parser.Node {
pub fn _nextSibling(self: *TreeWalker) !?NodeUnion {
if (try self.nextSibling(self.current_node)) |sibling| {
self.current_node = sibling;
return sibling;
return try Node.toInterface(sibling);
}
return null;
}
pub fn _parentNode(self: *TreeWalker) !?*parser.Node {
pub fn _parentNode(self: *TreeWalker) !?NodeUnion {
if (try self.parentNode(self.current_node)) |parent| {
self.current_node = parent;
return parent;
return try Node.toInterface(parent);
}
return null;
}
pub fn _previousNode(self: *TreeWalker) !?*parser.Node {
pub fn _previousNode(self: *TreeWalker) !?NodeUnion {
if (self.current_node == self.root) return null;
var current = self.current_node;
@@ -224,19 +226,19 @@ pub const TreeWalker = struct {
// Get last child if it has one.
if (try self.lastChild(current)) |child| {
self.current_node = child;
return child;
return try Node.toInterface(child);
}
// Otherwise, this node is our previous one.
self.current_node = current;
return current;
return try Node.toInterface(current);
},
.reject => continue,
.skip => {
// Get last child if it has one.
if (try self.lastChild(current)) |child| {
self.current_node = child;
return child;
return try Node.toInterface(child);
}
},
}
@@ -245,17 +247,17 @@ pub const TreeWalker = struct {
if (current != self.root) {
if (try self.parentNode(current)) |parent| {
self.current_node = parent;
return parent;
return try Node.toInterface(parent);
}
}
return null;
}
pub fn _previousSibling(self: *TreeWalker) !?*parser.Node {
pub fn _previousSibling(self: *TreeWalker) !?NodeUnion {
if (try self.previousSibling(self.current_node)) |sibling| {
self.current_node = sibling;
return sibling;
return try Node.toInterface(sibling);
}
return null;