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 std = @import("std");
const parser = @import("../netsurf.zig"); const parser = @import("../netsurf.zig");
const Env = @import("../env.zig").Env; const Env = @import("../env.zig").Env;
const Node = @import("node.zig").Node;
pub const NodeFilter = struct { pub const NodeFilter = struct {
pub const _FILTER_ACCEPT: u16 = 1; 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. // Verify that we aren't filtering it out.
if (filter) |f| { if (filter) |f| {
const acceptance = try f.call(u16, .{node}); const acceptance = try f.call(u16, .{try Node.toInterface(node)});
return switch (acceptance) { return switch (acceptance) {
NodeFilter._FILTER_ACCEPT => .accept, NodeFilter._FILTER_ACCEPT => .accept,
NodeFilter._FILTER_REJECT => .reject, NodeFilter._FILTER_REJECT => .reject,

View File

@@ -20,9 +20,11 @@ const std = @import("std");
const parser = @import("../netsurf.zig"); const parser = @import("../netsurf.zig");
const Env = @import("../env.zig").Env; const Env = @import("../env.zig").Env;
const NodeFilter = @import("node_filter.zig"); 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 // 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: // For example:
// - nextNode returns the reference node, whereas TreeWalker returns the next node // - nextNode returns the reference node, whereas TreeWalker returns the next node
// - Skip and reject are equivalent for NodeIterator, for TreeWalker they are different // - 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; return self.pointer_before_current;
} }
pub fn get_referenceNode(self: *const NodeIterator) *parser.Node { pub fn get_referenceNode(self: *const NodeIterator) !NodeUnion {
return self.reference_node; return try Node.toInterface(self.reference_node);
} }
pub fn get_root(self: *const NodeIterator) *parser.Node { pub fn get_root(self: *const NodeIterator) !NodeUnion {
return self.root; return try Node.toInterface(self.root);
} }
pub fn get_whatToShow(self: *const NodeIterator) u32 { pub fn get_whatToShow(self: *const NodeIterator) u32 {
return self.what_to_show; 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 if (self.pointer_before_current) { // Unlike TreeWalker, NodeIterator starts at the first node
self.pointer_before_current = false; self.pointer_before_current = false;
if (.accept == try NodeFilter.verify(self.what_to_show, self.filter_func, self.reference_node)) { 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| { if (try self.firstChild(self.reference_node)) |child| {
self.reference_node = child; self.reference_node = child;
return child; return try Node.toInterface(child);
} }
var current = self.reference_node; var current = self.reference_node;
while (current != self.root) { while (current != self.root) {
if (try self.nextSibling(current)) |sibling| { if (try self.nextSibling(current)) |sibling| {
self.reference_node = sibling; self.reference_node = sibling;
return sibling; return try Node.toInterface(sibling);
} }
current = (try parser.nodeParentNode(current)) orelse break; current = (try parser.nodeParentNode(current)) orelse break;
@@ -104,11 +106,11 @@ pub const NodeIterator = struct {
return null; return null;
} }
pub fn _previousNode(self: *NodeIterator) !?*parser.Node { pub fn _previousNode(self: *NodeIterator) !?NodeUnion {
if (!self.pointer_before_current) { if (!self.pointer_before_current) {
self.pointer_before_current = true; self.pointer_before_current = true;
if (.accept == try NodeFilter.verify(self.what_to_show, self.filter_func, self.reference_node)) { 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; if (self.reference_node == self.root) return null;
@@ -122,18 +124,18 @@ pub const NodeIterator = struct {
// Get last child if it has one. // Get last child if it has one.
if (try self.lastChild(current)) |child| { if (try self.lastChild(current)) |child| {
self.reference_node = child; self.reference_node = child;
return child; return try Node.toInterface(child);
} }
// Otherwise, this node is our previous one. // Otherwise, this node is our previous one.
self.reference_node = current; self.reference_node = current;
return current; return try Node.toInterface(current);
}, },
.reject, .skip => { .reject, .skip => {
// Get last child if it has one. // Get last child if it has one.
if (try self.lastChild(current)) |child| { if (try self.lastChild(current)) |child| {
self.reference_node = 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 (current != self.root) {
if (try self.parentNode(current)) |parent| { if (try self.parentNode(current)) |parent| {
self.reference_node = 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 NodeFilter = @import("node_filter.zig");
const Env = @import("../env.zig").Env; const Env = @import("../env.zig").Env;
const Page = @import("../page.zig").Page; 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 // https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker
pub const TreeWalker = struct { pub const TreeWalker = struct {
@@ -55,12 +57,12 @@ pub const TreeWalker = struct {
}; };
} }
pub fn get_root(self: *TreeWalker) *parser.Node { pub fn get_root(self: *TreeWalker) !NodeUnion {
return self.root; return try Node.toInterface(self.root);
} }
pub fn get_currentNode(self: *TreeWalker) *parser.Node { pub fn get_currentNode(self: *TreeWalker) !NodeUnion {
return self.current_node; return try Node.toInterface(self.current_node);
} }
pub fn get_whatToShow(self: *TreeWalker) u32 { 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| { if (try self.firstChild(self.current_node)) |child| {
self.current_node = child; self.current_node = child;
return child; return try Node.toInterface(child);
} }
return null; return null;
} }
pub fn _lastChild(self: *TreeWalker) !?*parser.Node { pub fn _lastChild(self: *TreeWalker) !?NodeUnion {
if (try self.lastChild(self.current_node)) |child| { if (try self.lastChild(self.current_node)) |child| {
self.current_node = child; self.current_node = child;
return child; return try Node.toInterface(child);
} }
return null; return null;
} }
pub fn _nextNode(self: *TreeWalker) !?*parser.Node { pub fn _nextNode(self: *TreeWalker) !?NodeUnion {
if (try self.firstChild(self.current_node)) |child| { if (try self.firstChild(self.current_node)) |child| {
self.current_node = child; self.current_node = child;
return child; return try Node.toInterface(child);
} }
var current = self.current_node; var current = self.current_node;
while (current != self.root) { while (current != self.root) {
if (try self.nextSibling(current)) |sibling| { if (try self.nextSibling(current)) |sibling| {
self.current_node = sibling; self.current_node = sibling;
return sibling; return try Node.toInterface(sibling);
} }
current = (try parser.nodeParentNode(current)) orelse break; current = (try parser.nodeParentNode(current)) orelse break;
@@ -194,25 +196,25 @@ pub const TreeWalker = struct {
return null; return null;
} }
pub fn _nextSibling(self: *TreeWalker) !?*parser.Node { pub fn _nextSibling(self: *TreeWalker) !?NodeUnion {
if (try self.nextSibling(self.current_node)) |sibling| { if (try self.nextSibling(self.current_node)) |sibling| {
self.current_node = sibling; self.current_node = sibling;
return sibling; return try Node.toInterface(sibling);
} }
return null; return null;
} }
pub fn _parentNode(self: *TreeWalker) !?*parser.Node { pub fn _parentNode(self: *TreeWalker) !?NodeUnion {
if (try self.parentNode(self.current_node)) |parent| { if (try self.parentNode(self.current_node)) |parent| {
self.current_node = parent; self.current_node = parent;
return parent; return try Node.toInterface(parent);
} }
return null; return null;
} }
pub fn _previousNode(self: *TreeWalker) !?*parser.Node { pub fn _previousNode(self: *TreeWalker) !?NodeUnion {
if (self.current_node == self.root) return null; if (self.current_node == self.root) return null;
var current = self.current_node; var current = self.current_node;
@@ -224,19 +226,19 @@ pub const TreeWalker = struct {
// Get last child if it has one. // Get last child if it has one.
if (try self.lastChild(current)) |child| { if (try self.lastChild(current)) |child| {
self.current_node = child; self.current_node = child;
return child; return try Node.toInterface(child);
} }
// Otherwise, this node is our previous one. // Otherwise, this node is our previous one.
self.current_node = current; self.current_node = current;
return current; return try Node.toInterface(current);
}, },
.reject => continue, .reject => continue,
.skip => { .skip => {
// Get last child if it has one. // Get last child if it has one.
if (try self.lastChild(current)) |child| { if (try self.lastChild(current)) |child| {
self.current_node = 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 (current != self.root) {
if (try self.parentNode(current)) |parent| { if (try self.parentNode(current)) |parent| {
self.current_node = parent; self.current_node = parent;
return parent; return try Node.toInterface(parent);
} }
} }
return null; return null;
} }
pub fn _previousSibling(self: *TreeWalker) !?*parser.Node { pub fn _previousSibling(self: *TreeWalker) !?NodeUnion {
if (try self.previousSibling(self.current_node)) |sibling| { if (try self.previousSibling(self.current_node)) |sibling| {
self.current_node = sibling; self.current_node = sibling;
return sibling; return try Node.toInterface(sibling);
} }
return null; return null;