// Copyright (C) 2023-2026 Lightpanda (Selecy SAS) // // Francis Bouvier // Pierre Tachoire // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . const std = @import("std"); const lp = @import("lightpanda"); const Frame = @import("../browser/Frame.zig"); const DOMNode = @import("../browser/webapi/Node.zig"); const Label = @import("../browser/webapi/element/html/Label.zig"); const Node = @import("Node.zig"); const log = lp.log; const jsonStringify = std.json.Stringify; const AXNode = @This(); // Max bytes retained in the name-resolution scratch arena across resets. // Anything beyond is freed back to the backing allocator. const scratch_retain_limit = 64 * 1024; // Need a custom writer, because we can't just serialize the node as-is. // Sometimes we want to serializ the node without children, sometimes with just // its direct children, and sometimes the entire tree. // (For now, we only support direct children) pub const Writer = struct { root: *const Node, registry: *Node.Registry, frame: *Frame, visibility_cache: *DOMNode.Element.VisibilityCache, label_index: *Label.LabelByForIndex, temp_arena: std.mem.Allocator, // When null, emit the full AX tree (getFullAXTree). When set, walk the // subtree visiting all nodes (including AX-ignored ones, per the // queryAXTree spec) and emit only nodes whose role + accessible name // match the filter, in a flat shape. filter: ?Filter = null, pub const Filter = struct { role: ?[]const u8 = null, accessible_name: ?[]const u8 = null, }; pub const Opts = struct { filter: ?Filter = null, }; const ResolvedRole = struct { role: []const u8, // Non-null when the current node is a