Merge pull request #954 from lightpanda-io/remove_managed_arraylist

Replace all std.ArrayList with std.ArrayListUnmanaged
This commit is contained in:
Pierre Tachoire
2025-08-20 08:55:03 +02:00
committed by GitHub
8 changed files with 144 additions and 122 deletions

View File

@@ -20,18 +20,23 @@ const std = @import("std");
const css = @import("css.zig"); const css = @import("css.zig");
const Node = @import("libdom.zig").Node; const Node = @import("libdom.zig").Node;
const parser = @import("../netsurf.zig"); const parser = @import("../netsurf.zig");
const Allocator = std.mem.Allocator;
const Matcher = struct { const Matcher = struct {
const Nodes = std.ArrayList(Node); const Nodes = std.ArrayListUnmanaged(Node);
nodes: Nodes, nodes: Nodes,
allocator: Allocator,
fn init(alloc: std.mem.Allocator) Matcher { fn init(allocator: Allocator) Matcher {
return .{ .nodes = Nodes.init(alloc) }; return .{
.nodes = .empty,
.allocator = allocator,
};
} }
fn deinit(m: *Matcher) void { fn deinit(m: *Matcher) void {
m.nodes.deinit(); m.nodes.deinit(m.allocator);
} }
fn reset(m: *Matcher) void { fn reset(m: *Matcher) void {
@@ -39,7 +44,7 @@ const Matcher = struct {
} }
pub fn match(m: *Matcher, n: Node) !void { pub fn match(m: *Matcher, n: Node) !void {
try m.nodes.append(n); try m.nodes.append(m.allocator, n);
} }
}; };

View File

@@ -84,16 +84,20 @@ pub const Node = struct {
}; };
const Matcher = struct { const Matcher = struct {
const Nodes = std.ArrayList(*const Node); const Nodes = std.ArrayListUnmanaged(*const Node);
nodes: Nodes, nodes: Nodes,
allocator: Allocator,
fn init(alloc: std.mem.Allocator) Matcher { fn init(allocator: Allocator) Matcher {
return .{ .nodes = Nodes.init(alloc) }; return .{
.nodes = .empty,
.allocator = allocator,
};
} }
fn deinit(m: *Matcher) void { fn deinit(m: *Matcher) void {
m.nodes.deinit(); m.nodes.deinit(self.allocator);
} }
fn reset(m: *Matcher) void { fn reset(m: *Matcher) void {
@@ -101,7 +105,7 @@ const Matcher = struct {
} }
pub fn match(m: *Matcher, n: *const Node) !void { pub fn match(m: *Matcher, n: *const Node) !void {
try m.nodes.append(n); try m.nodes.append(self.allocator, n);
} }
}; };

View File

@@ -22,6 +22,7 @@
// see https://github.com/andybalholm/cascadia/blob/master/parser.go // see https://github.com/andybalholm/cascadia/blob/master/parser.go
const std = @import("std"); const std = @import("std");
const ascii = std.ascii; const ascii = std.ascii;
const Allocator = std.mem.Allocator;
const selector = @import("selector.zig"); const selector = @import("selector.zig");
const Selector = selector.Selector; const Selector = selector.Selector;
@@ -77,8 +78,8 @@ pub const Parser = struct {
opts: ParseOptions, opts: ParseOptions,
pub fn parse(p: *Parser, alloc: std.mem.Allocator) ParseError!Selector { pub fn parse(p: *Parser, allocator: Allocator) ParseError!Selector {
return p.parseSelectorGroup(alloc); return p.parseSelectorGroup(allocator);
} }
// skipWhitespace consumes whitespace characters and comments. // skipWhitespace consumes whitespace characters and comments.
@@ -115,13 +116,13 @@ pub const Parser = struct {
// parseSimpleSelectorSequence parses a selector sequence that applies to // parseSimpleSelectorSequence parses a selector sequence that applies to
// a single element. // a single element.
fn parseSimpleSelectorSequence(p: *Parser, alloc: std.mem.Allocator) ParseError!Selector { fn parseSimpleSelectorSequence(p: *Parser, allocator: Allocator) ParseError!Selector {
if (p.i >= p.s.len) { if (p.i >= p.s.len) {
return ParseError.ExpectedSelector; return ParseError.ExpectedSelector;
} }
var buf = std.ArrayList(Selector).init(alloc); var buf: std.ArrayListUnmanaged(Selector) = .empty;
defer buf.deinit(); defer buf.deinit(allocator);
switch (p.s[p.i]) { switch (p.s[p.i]) {
'*' => { '*' => {
@@ -138,20 +139,20 @@ pub const Parser = struct {
// There's no type selector. Wait to process the other till the // There's no type selector. Wait to process the other till the
// main loop. // main loop.
}, },
else => try buf.append(try p.parseTypeSelector(alloc)), else => try buf.append(allocator, try p.parseTypeSelector(allocator)),
} }
var pseudo_elt: ?PseudoClass = null; var pseudo_elt: ?PseudoClass = null;
loop: while (p.i < p.s.len) { loop: while (p.i < p.s.len) {
var ns: Selector = switch (p.s[p.i]) { var ns: Selector = switch (p.s[p.i]) {
'#' => try p.parseIDSelector(alloc), '#' => try p.parseIDSelector(allocator),
'.' => try p.parseClassSelector(alloc), '.' => try p.parseClassSelector(allocator),
'[' => try p.parseAttributeSelector(alloc), '[' => try p.parseAttributeSelector(allocator),
':' => try p.parsePseudoclassSelector(alloc), ':' => try p.parsePseudoclassSelector(allocator),
else => break :loop, else => break :loop,
}; };
errdefer ns.deinit(alloc); errdefer ns.deinit(allocator);
// From https://drafts.csswg.org/selectors-3/#pseudo-elements : // From https://drafts.csswg.org/selectors-3/#pseudo-elements :
// "Only one pseudo-element may appear per selector, and if present // "Only one pseudo-element may appear per selector, and if present
@@ -165,28 +166,32 @@ pub const Parser = struct {
if (!p.opts.accept_pseudo_elts) return ParseError.PseudoElementDisabled; if (!p.opts.accept_pseudo_elts) return ParseError.PseudoElementDisabled;
pseudo_elt = e; pseudo_elt = e;
ns.deinit(alloc); ns.deinit(allocator);
}, },
else => { else => {
if (pseudo_elt != null) return ParseError.PseudoElementNotAtSelectorEnd; if (pseudo_elt != null) return ParseError.PseudoElementNotAtSelectorEnd;
try buf.append(ns); try buf.append(allocator, ns);
}, },
} }
} }
// no need wrap the selectors in compoundSelector // no need wrap the selectors in compoundSelector
if (buf.items.len == 1 and pseudo_elt == null) return buf.items[0]; if (buf.items.len == 1 and pseudo_elt == null) {
return buf.items[0];
}
return .{ .compound = .{ .selectors = try buf.toOwnedSlice(), .pseudo_elt = pseudo_elt } }; return .{
.compound = .{ .selectors = try buf.toOwnedSlice(allocator), .pseudo_elt = pseudo_elt },
};
} }
// parseTypeSelector parses a type selector (one that matches by tag name). // parseTypeSelector parses a type selector (one that matches by tag name).
fn parseTypeSelector(p: *Parser, alloc: std.mem.Allocator) ParseError!Selector { fn parseTypeSelector(p: *Parser, allocator: Allocator) ParseError!Selector {
var buf = std.ArrayList(u8).init(alloc); var buf: std.ArrayListUnmanaged(u8) = .empty;
defer buf.deinit(); defer buf.deinit(allocator);
try p.parseIdentifier(buf.writer()); try p.parseIdentifier(buf.writer(allocator));
return .{ .tag = try buf.toOwnedSlice() }; return .{ .tag = try buf.toOwnedSlice(allocator) };
} }
// parseIdentifier parses an identifier. // parseIdentifier parses an identifier.
@@ -314,47 +319,47 @@ pub const Parser = struct {
} }
// parseIDSelector parses a selector that matches by id attribute. // parseIDSelector parses a selector that matches by id attribute.
fn parseIDSelector(p: *Parser, alloc: std.mem.Allocator) ParseError!Selector { fn parseIDSelector(p: *Parser, allocator: Allocator) ParseError!Selector {
if (p.i >= p.s.len) return ParseError.ExpectedIDSelector; if (p.i >= p.s.len) return ParseError.ExpectedIDSelector;
if (p.s[p.i] != '#') return ParseError.ExpectedIDSelector; if (p.s[p.i] != '#') return ParseError.ExpectedIDSelector;
p.i += 1; p.i += 1;
var buf = std.ArrayList(u8).init(alloc); var buf: std.ArrayListUnmanaged(u8) = .empty;
defer buf.deinit(); defer buf.deinit(allocator);
try p.parseName(buf.writer()); try p.parseName(buf.writer(allocator));
return .{ .id = try buf.toOwnedSlice() }; return .{ .id = try buf.toOwnedSlice(allocator) };
} }
// parseClassSelector parses a selector that matches by class attribute. // parseClassSelector parses a selector that matches by class attribute.
fn parseClassSelector(p: *Parser, alloc: std.mem.Allocator) ParseError!Selector { fn parseClassSelector(p: *Parser, allocator: Allocator) ParseError!Selector {
if (p.i >= p.s.len) return ParseError.ExpectedClassSelector; if (p.i >= p.s.len) return ParseError.ExpectedClassSelector;
if (p.s[p.i] != '.') return ParseError.ExpectedClassSelector; if (p.s[p.i] != '.') return ParseError.ExpectedClassSelector;
p.i += 1; p.i += 1;
var buf = std.ArrayList(u8).init(alloc); var buf: std.ArrayListUnmanaged(u8) = .empty;
defer buf.deinit(); defer buf.deinit(allocator);
try p.parseIdentifier(buf.writer()); try p.parseIdentifier(buf.writer(allocator));
return .{ .class = try buf.toOwnedSlice() }; return .{ .class = try buf.toOwnedSlice(allocator) };
} }
// parseAttributeSelector parses a selector that matches by attribute value. // parseAttributeSelector parses a selector that matches by attribute value.
fn parseAttributeSelector(p: *Parser, alloc: std.mem.Allocator) ParseError!Selector { fn parseAttributeSelector(p: *Parser, allocator: Allocator) ParseError!Selector {
if (p.i >= p.s.len) return ParseError.ExpectedAttributeSelector; if (p.i >= p.s.len) return ParseError.ExpectedAttributeSelector;
if (p.s[p.i] != '[') return ParseError.ExpectedAttributeSelector; if (p.s[p.i] != '[') return ParseError.ExpectedAttributeSelector;
p.i += 1; p.i += 1;
_ = p.skipWhitespace(); _ = p.skipWhitespace();
var buf = std.ArrayList(u8).init(alloc); var buf: std.ArrayListUnmanaged(u8) = .empty;
defer buf.deinit(); defer buf.deinit(allocator);
try p.parseIdentifier(buf.writer()); try p.parseIdentifier(buf.writer(allocator));
const key = try buf.toOwnedSlice(); const key = try buf.toOwnedSlice(allocator);
errdefer alloc.free(key); errdefer allocator.free(key);
lowerstr(key); lowerstr(key);
@@ -377,12 +382,12 @@ pub const Parser = struct {
var is_val: bool = undefined; var is_val: bool = undefined;
if (op == .regexp) { if (op == .regexp) {
is_val = false; is_val = false;
try p.parseRegex(buf.writer()); try p.parseRegex(buf.writer(allocator));
} else { } else {
is_val = true; is_val = true;
switch (p.s[p.i]) { switch (p.s[p.i]) {
'\'', '"' => try p.parseString(buf.writer()), '\'', '"' => try p.parseString(buf.writer(allocator)),
else => try p.parseIdentifier(buf.writer()), else => try p.parseIdentifier(buf.writer(allocator)),
} }
} }
@@ -404,8 +409,8 @@ pub const Parser = struct {
return .{ .attribute = .{ return .{ .attribute = .{
.key = key, .key = key,
.val = if (is_val) try buf.toOwnedSlice() else null, .val = if (is_val) try buf.toOwnedSlice(allocator) else null,
.regexp = if (!is_val) try buf.toOwnedSlice() else null, .regexp = if (!is_val) try buf.toOwnedSlice(allocator) else null,
.op = op, .op = op,
.ci = ci, .ci = ci,
} }; } };
@@ -498,7 +503,7 @@ pub const Parser = struct {
// parsePseudoclassSelector parses a pseudoclass selector like :not(p) or a pseudo-element // parsePseudoclassSelector parses a pseudoclass selector like :not(p) or a pseudo-element
// For backwards compatibility, both ':' and '::' prefix are allowed for pseudo-elements. // For backwards compatibility, both ':' and '::' prefix are allowed for pseudo-elements.
// https://drafts.csswg.org/selectors-3/#pseudo-elements // https://drafts.csswg.org/selectors-3/#pseudo-elements
fn parsePseudoclassSelector(p: *Parser, alloc: std.mem.Allocator) ParseError!Selector { fn parsePseudoclassSelector(p: *Parser, allocator: Allocator) ParseError!Selector {
if (p.i >= p.s.len) return ParseError.ExpectedPseudoClassSelector; if (p.i >= p.s.len) return ParseError.ExpectedPseudoClassSelector;
if (p.s[p.i] != ':') return ParseError.ExpectedPseudoClassSelector; if (p.s[p.i] != ':') return ParseError.ExpectedPseudoClassSelector;
@@ -511,10 +516,10 @@ pub const Parser = struct {
p.i += 1; p.i += 1;
} }
var buf = std.ArrayList(u8).init(alloc); var buf: std.ArrayListUnmanaged(u8) = .empty;
defer buf.deinit(); defer buf.deinit(allocator);
try p.parseIdentifier(buf.writer()); try p.parseIdentifier(buf.writer(allocator));
const pseudo_class = try PseudoClass.parse(buf.items); const pseudo_class = try PseudoClass.parse(buf.items);
@@ -527,11 +532,11 @@ pub const Parser = struct {
.not, .has, .haschild => { .not, .has, .haschild => {
if (!p.consumeParenthesis()) return ParseError.ExpectedParenthesis; if (!p.consumeParenthesis()) return ParseError.ExpectedParenthesis;
const sel = try p.parseSelectorGroup(alloc); const sel = try p.parseSelectorGroup(allocator);
if (!p.consumeClosingParenthesis()) return ParseError.ExpectedParenthesisClose; if (!p.consumeClosingParenthesis()) return ParseError.ExpectedParenthesisClose;
const s = try alloc.create(Selector); const s = try allocator.create(Selector);
errdefer alloc.destroy(s); errdefer allocator.destroy(s);
s.* = sel; s.* = sel;
return .{ .pseudo_class_relative = .{ .pseudo_class = pseudo_class, .match = s } }; return .{ .pseudo_class_relative = .{ .pseudo_class = pseudo_class, .match = s } };
@@ -541,16 +546,16 @@ pub const Parser = struct {
if (p.i == p.s.len) return ParseError.UnmatchParenthesis; if (p.i == p.s.len) return ParseError.UnmatchParenthesis;
switch (p.s[p.i]) { switch (p.s[p.i]) {
'\'', '"' => try p.parseString(buf.writer()), '\'', '"' => try p.parseString(buf.writer(allocator)),
else => try p.parseString(buf.writer()), else => try p.parseString(buf.writer(allocator)),
} }
_ = p.skipWhitespace(); _ = p.skipWhitespace();
if (p.i >= p.s.len) return ParseError.InvalidPseudoClass; if (p.i >= p.s.len) return ParseError.InvalidPseudoClass;
if (!p.consumeClosingParenthesis()) return ParseError.ExpectedParenthesisClose; if (!p.consumeClosingParenthesis()) return ParseError.ExpectedParenthesisClose;
const val = try buf.toOwnedSlice(); const val = try buf.toOwnedSlice(allocator);
errdefer alloc.free(val); errdefer allocator.free(val);
lowerstr(val); lowerstr(val);
@@ -559,15 +564,15 @@ pub const Parser = struct {
.matches, .matchesown => { .matches, .matchesown => {
if (!p.consumeParenthesis()) return ParseError.ExpectedParenthesis; if (!p.consumeParenthesis()) return ParseError.ExpectedParenthesis;
try p.parseRegex(buf.writer()); try p.parseRegex(buf.writer(allocator));
if (p.i >= p.s.len) return ParseError.InvalidPseudoClassSelector; if (p.i >= p.s.len) return ParseError.InvalidPseudoClassSelector;
if (!p.consumeClosingParenthesis()) return ParseError.ExpectedParenthesisClose; if (!p.consumeClosingParenthesis()) return ParseError.ExpectedParenthesisClose;
return .{ .pseudo_class_regexp = .{ .own = pseudo_class == .matchesown, .regexp = try buf.toOwnedSlice() } }; return .{ .pseudo_class_regexp = .{ .own = pseudo_class == .matchesown, .regexp = try buf.toOwnedSlice(allocator) } };
}, },
.nth_child, .nth_last_child, .nth_of_type, .nth_last_of_type => { .nth_child, .nth_last_child, .nth_of_type, .nth_last_of_type => {
if (!p.consumeParenthesis()) return ParseError.ExpectedParenthesis; if (!p.consumeParenthesis()) return ParseError.ExpectedParenthesis;
const nth = try p.parseNth(alloc); const nth = try p.parseNth(allocator);
if (!p.consumeClosingParenthesis()) return ParseError.ExpectedParenthesisClose; if (!p.consumeClosingParenthesis()) return ParseError.ExpectedParenthesisClose;
const last = pseudo_class == .nth_last_child or pseudo_class == .nth_last_of_type; const last = pseudo_class == .nth_last_child or pseudo_class == .nth_last_of_type;
@@ -587,14 +592,14 @@ pub const Parser = struct {
if (!p.consumeParenthesis()) return ParseError.ExpectedParenthesis; if (!p.consumeParenthesis()) return ParseError.ExpectedParenthesis;
if (p.i == p.s.len) return ParseError.UnmatchParenthesis; if (p.i == p.s.len) return ParseError.UnmatchParenthesis;
try p.parseIdentifier(buf.writer()); try p.parseIdentifier(buf.writer(allocator));
_ = p.skipWhitespace(); _ = p.skipWhitespace();
if (p.i >= p.s.len) return ParseError.InvalidPseudoClass; if (p.i >= p.s.len) return ParseError.InvalidPseudoClass;
if (!p.consumeClosingParenthesis()) return ParseError.ExpectedParenthesisClose; if (!p.consumeClosingParenthesis()) return ParseError.ExpectedParenthesisClose;
const val = try buf.toOwnedSlice(); const val = try buf.toOwnedSlice(allocator);
errdefer alloc.free(val); errdefer allocator.free(val);
lowerstr(val); lowerstr(val);
return .{ .pseudo_class_lang = val }; return .{ .pseudo_class_lang = val };
@@ -622,30 +627,32 @@ pub const Parser = struct {
} }
// parseSelectorGroup parses a group of selectors, separated by commas. // parseSelectorGroup parses a group of selectors, separated by commas.
fn parseSelectorGroup(p: *Parser, alloc: std.mem.Allocator) ParseError!Selector { fn parseSelectorGroup(p: *Parser, allocator: Allocator) ParseError!Selector {
const s = try p.parseSelector(alloc); const s = try p.parseSelector(allocator);
var buf = std.ArrayList(Selector).init(alloc); var buf: std.ArrayListUnmanaged(Selector) = .empty;
defer buf.deinit(); defer buf.deinit(allocator);
try buf.append(s); try buf.append(allocator, s);
while (p.i < p.s.len) { while (p.i < p.s.len) {
if (p.s[p.i] != ',') break; if (p.s[p.i] != ',') break;
p.i += 1; p.i += 1;
const ss = try p.parseSelector(alloc); const ss = try p.parseSelector(allocator);
try buf.append(ss); try buf.append(allocator, ss);
} }
if (buf.items.len == 1) return buf.items[0]; if (buf.items.len == 1) {
return buf.items[0];
}
return .{ .group = try buf.toOwnedSlice() }; return .{ .group = try buf.toOwnedSlice(allocator) };
} }
// parseSelector parses a selector that may include combinators. // parseSelector parses a selector that may include combinators.
fn parseSelector(p: *Parser, alloc: std.mem.Allocator) ParseError!Selector { fn parseSelector(p: *Parser, allocator: Allocator) ParseError!Selector {
_ = p.skipWhitespace(); _ = p.skipWhitespace();
var s = try p.parseSimpleSelectorSequence(alloc); var s = try p.parseSimpleSelectorSequence(allocator);
while (true) { while (true) {
var combinator: Combinator = .empty; var combinator: Combinator = .empty;
@@ -673,17 +680,21 @@ pub const Parser = struct {
return s; return s;
} }
const c = try p.parseSimpleSelectorSequence(alloc); const c = try p.parseSimpleSelectorSequence(allocator);
const first = try alloc.create(Selector); const first = try allocator.create(Selector);
errdefer alloc.destroy(first); errdefer allocator.destroy(first);
first.* = s; first.* = s;
const second = try alloc.create(Selector); const second = try allocator.create(Selector);
errdefer alloc.destroy(second); errdefer allocator.destroy(second);
second.* = c; second.* = c;
s = Selector{ .combined = .{ .first = first, .second = second, .combinator = combinator } }; s = Selector{ .combined = .{
.first = first,
.second = second,
.combinator = combinator,
} };
} }
return s; return s;
@@ -776,7 +787,7 @@ pub const Parser = struct {
} }
// parseNth parses the argument for :nth-child (normally of the form an+b). // parseNth parses the argument for :nth-child (normally of the form an+b).
fn parseNth(p: *Parser, alloc: std.mem.Allocator) ParseError![2]isize { fn parseNth(p: *Parser, allocator: Allocator) ParseError![2]isize {
// initial state // initial state
if (p.i >= p.s.len) return ParseError.ExpectedNthExpression; if (p.i >= p.s.len) return ParseError.ExpectedNthExpression;
return switch (p.s[p.i]) { return switch (p.s[p.i]) {
@@ -794,10 +805,10 @@ pub const Parser = struct {
return p.parseNthReadN(1); return p.parseNthReadN(1);
}, },
'o', 'O', 'e', 'E' => { 'o', 'O', 'e', 'E' => {
var buf = std.ArrayList(u8).init(alloc); var buf: std.ArrayListUnmanaged(u8) = .empty;
defer buf.deinit(); defer buf.deinit(allocator);
try p.parseName(buf.writer()); try p.parseName(buf.writer(allocator));
if (std.ascii.eqlIgnoreCase("odd", buf.items)) return .{ 2, 1 }; if (std.ascii.eqlIgnoreCase("odd", buf.items)) return .{ 2, 1 };
if (std.ascii.eqlIgnoreCase("even", buf.items)) return .{ 2, 0 }; if (std.ascii.eqlIgnoreCase("even", buf.items)) return .{ 2, 0 };
@@ -873,7 +884,7 @@ test "parser.skipWhitespace" {
} }
test "parser.parseIdentifier" { test "parser.parseIdentifier" {
const alloc = std.testing.allocator; const allocator = std.testing.allocator;
const testcases = [_]struct { const testcases = [_]struct {
s: []const u8, // given value s: []const u8, // given value
@@ -889,14 +900,14 @@ test "parser.parseIdentifier" {
.{ .s = "a\\\"b", .exp = "a\"b" }, .{ .s = "a\\\"b", .exp = "a\"b" },
}; };
var buf = std.ArrayList(u8).init(alloc); var buf: std.ArrayListUnmanaged(u8) = .empty;
defer buf.deinit(); defer buf.deinit(allocator);
for (testcases) |tc| { for (testcases) |tc| {
buf.clearRetainingCapacity(); buf.clearRetainingCapacity();
var p = Parser{ .s = tc.s, .opts = .{} }; var p = Parser{ .s = tc.s, .opts = .{} };
p.parseIdentifier(buf.writer()) catch |e| { p.parseIdentifier(buf.writer(allocator)) catch |e| {
// if error was expected, continue. // if error was expected, continue.
if (tc.err) continue; if (tc.err) continue;
@@ -911,7 +922,7 @@ test "parser.parseIdentifier" {
} }
test "parser.parseString" { test "parser.parseString" {
const alloc = std.testing.allocator; const allocator = std.testing.allocator;
const testcases = [_]struct { const testcases = [_]struct {
s: []const u8, // given value s: []const u8, // given value
@@ -930,14 +941,14 @@ test "parser.parseString" {
.{ .s = "\"hello world\"", .exp = "hello world" }, .{ .s = "\"hello world\"", .exp = "hello world" },
}; };
var buf = std.ArrayList(u8).init(alloc); var buf: std.ArrayListUnmanaged(u8) = .empty;
defer buf.deinit(); defer buf.deinit(allocator);
for (testcases) |tc| { for (testcases) |tc| {
buf.clearRetainingCapacity(); buf.clearRetainingCapacity();
var p = Parser{ .s = tc.s, .opts = .{} }; var p = Parser{ .s = tc.s, .opts = .{} };
p.parseString(buf.writer()) catch |e| { p.parseString(buf.writer(allocator)) catch |e| {
// if error was expected, continue. // if error was expected, continue.
if (tc.err) continue; if (tc.err) continue;
@@ -954,7 +965,7 @@ test "parser.parseString" {
test "parser.parse" { test "parser.parse" {
var arena = std.heap.ArenaAllocator.init(std.testing.allocator); var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
defer arena.deinit(); defer arena.deinit();
const alloc = arena.allocator(); const allocator = arena.allocator();
const testcases = [_]struct { const testcases = [_]struct {
s: []const u8, // given value s: []const u8, // given value
@@ -970,7 +981,7 @@ test "parser.parse" {
for (testcases) |tc| { for (testcases) |tc| {
var p = Parser{ .s = tc.s, .opts = .{} }; var p = Parser{ .s = tc.s, .opts = .{} };
const sel = p.parse(alloc) catch |e| { const sel = p.parse(allocator) catch |e| {
// if error was expected, continue. // if error was expected, continue.
if (tc.err) continue; if (tc.err) continue;

View File

@@ -137,14 +137,14 @@ pub const Element = struct {
} }
pub fn get_innerHTML(self: *parser.Element, page: *Page) ![]const u8 { pub fn get_innerHTML(self: *parser.Element, page: *Page) ![]const u8 {
var buf = std.ArrayList(u8).init(page.call_arena); var buf: std.ArrayListUnmanaged(u8) = .empty;
try dump.writeChildren(parser.elementToNode(self), .{}, buf.writer()); try dump.writeChildren(parser.elementToNode(self), .{}, buf.writer(page.call_arena));
return buf.items; return buf.items;
} }
pub fn get_outerHTML(self: *parser.Element, page: *Page) ![]const u8 { pub fn get_outerHTML(self: *parser.Element, page: *Page) ![]const u8 {
var buf = std.ArrayList(u8).init(page.call_arena); var buf: std.ArrayListUnmanaged(u8) = .empty;
try dump.writeNode(parser.elementToNode(self), .{}, buf.writer()); try dump.writeNode(parser.elementToNode(self), .{}, buf.writer(page.call_arena));
return buf.items; return buf.items;
} }

View File

@@ -60,8 +60,8 @@ pub const ShadowRoot = struct {
} }
pub fn get_innerHTML(self: *ShadowRoot, page: *Page) ![]const u8 { pub fn get_innerHTML(self: *ShadowRoot, page: *Page) ![]const u8 {
var buf = std.ArrayList(u8).init(page.call_arena); var buf: std.ArrayListUnmanaged(u8) = .empty;
try dump.writeChildren(parser.documentFragmentToNode(self.proto), .{}, buf.writer()); try dump.writeChildren(parser.documentFragmentToNode(self.proto), .{}, buf.writer(page.call_arena));
return buf.items; return buf.items;
} }

View File

@@ -358,10 +358,12 @@ pub const Cookie = struct {
if (domain.len > 0) { if (domain.len > 0) {
const no_leading_dot = if (domain[0] == '.') domain[1..] else domain; const no_leading_dot = if (domain[0] == '.') domain[1..] else domain;
var list = std.ArrayList(u8).init(arena); var list: std.ArrayListUnmanaged(u8) = .empty;
try list.ensureTotalCapacity(no_leading_dot.len + 1); // Expect no precents needed try list.ensureTotalCapacity(arena, no_leading_dot.len + 1); // Expect no precents needed
list.appendAssumeCapacity('.'); list.appendAssumeCapacity('.');
try std.Uri.Component.percentEncode(list.writer(), no_leading_dot, isHostChar); try std.Uri.Component.percentEncode(list.writer(
arena,
), no_leading_dot, isHostChar);
var owned_domain: []u8 = list.items; // @memory retains memory used before growing var owned_domain: []u8 = list.items; // @memory retains memory used before growing
_ = toLower(owned_domain); _ = toLower(owned_domain);
@@ -385,9 +387,9 @@ pub const Cookie = struct {
pub fn percentEncode(arena: Allocator, component: std.Uri.Component, comptime isValidChar: fn (u8) bool) ![]u8 { pub fn percentEncode(arena: Allocator, component: std.Uri.Component, comptime isValidChar: fn (u8) bool) ![]u8 {
switch (component) { switch (component) {
.raw => |str| { .raw => |str| {
var list = std.ArrayList(u8).init(arena); var list: std.ArrayListUnmanaged(u8) = .empty;
try list.ensureTotalCapacity(str.len); // Expect no precents needed try list.ensureTotalCapacity(arena, str.len); // Expect no precents needed
try std.Uri.Component.percentEncode(list.writer(), str, isValidChar); try std.Uri.Component.percentEncode(list.writer(arena), str, isValidChar);
return list.items; // @memory retains memory used before growing return list.items; // @memory retains memory used before growing
}, },
.percent_encoded => |str| { .percent_encoded => |str| {
@@ -591,7 +593,7 @@ test "Jar: add" {
test "Jar: forRequest" { test "Jar: forRequest" {
const expectCookies = struct { const expectCookies = struct {
fn expect(expected: []const u8, jar: *Jar, target_uri: Uri, opts: LookupOpts) !void { fn expect(expected: []const u8, jar: *Jar, target_uri: Uri, opts: LookupOpts) !void {
var arr: std.ArrayListUnmanaged(u8) = .{}; var arr: std.ArrayListUnmanaged(u8) = .empty;
defer arr.deinit(testing.allocator); defer arr.deinit(testing.allocator);
try jar.forRequest(&target_uri, arr.writer(testing.allocator), opts); try jar.forRequest(&target_uri, arr.writer(testing.allocator), opts);
try testing.expectEqual(expected, arr.items); try testing.expectEqual(expected, arr.items);

View File

@@ -114,7 +114,7 @@ pub const URL = struct {
} }
pub fn get_origin(self: *URL, page: *Page) ![]const u8 { pub fn get_origin(self: *URL, page: *Page) ![]const u8 {
var buf = std.ArrayList(u8).init(page.arena); var buf: std.ArrayListUnmanaged(u8) = .empty;
try self.uri.writeToStream(.{ try self.uri.writeToStream(.{
.scheme = true, .scheme = true,
.authentication = false, .authentication = false,
@@ -122,7 +122,7 @@ pub const URL = struct {
.path = false, .path = false,
.query = false, .query = false,
.fragment = false, .fragment = false,
}, buf.writer()); }, buf.writer(page.arena));
return buf.items; return buf.items;
} }
@@ -174,7 +174,7 @@ pub const URL = struct {
} }
pub fn get_host(self: *URL, page: *Page) ![]const u8 { pub fn get_host(self: *URL, page: *Page) ![]const u8 {
var buf = std.ArrayList(u8).init(page.arena); var buf: std.ArrayListUnmanaged(u8) = .empty;
try self.uri.writeToStream(.{ try self.uri.writeToStream(.{
.scheme = false, .scheme = false,
@@ -183,7 +183,7 @@ pub const URL = struct {
.path = false, .path = false,
.query = false, .query = false,
.fragment = false, .fragment = false,
}, buf.writer()); }, buf.writer(page.arena));
return buf.items; return buf.items;
} }
@@ -195,8 +195,8 @@ pub const URL = struct {
const arena = page.arena; const arena = page.arena;
if (self.uri.port == null) return try arena.dupe(u8, ""); if (self.uri.port == null) return try arena.dupe(u8, "");
var buf = std.ArrayList(u8).init(arena); var buf: std.ArrayListUnmanaged(u8) = .empty;
try std.fmt.formatInt(self.uri.port.?, 10, .lower, .{}, buf.writer()); try std.fmt.formatInt(self.uri.port.?, 10, .lower, .{}, buf.writer(arena));
return buf.items; return buf.items;
} }

View File

@@ -34,11 +34,11 @@ pub const XMLSerializer = struct {
} }
pub fn _serializeToString(_: *const XMLSerializer, root: *parser.Node, page: *Page) ![]const u8 { pub fn _serializeToString(_: *const XMLSerializer, root: *parser.Node, page: *Page) ![]const u8 {
var buf = std.ArrayList(u8).init(page.arena); var buf: std.ArrayListUnmanaged(u8) = .empty;
switch (try parser.nodeType(root)) { switch (try parser.nodeType(root)) {
.document => try dump.writeHTML(@as(*parser.Document, @ptrCast(root)), .{}, buf.writer()), .document => try dump.writeHTML(@as(*parser.Document, @ptrCast(root)), .{}, buf.writer(page.call_arena)),
.document_type => try dump.writeDocType(@as(*parser.DocumentType, @ptrCast(root)), buf.writer()), .document_type => try dump.writeDocType(@as(*parser.DocumentType, @ptrCast(root)), buf.writer(page.call_arena)),
else => try dump.writeNode(root, .{}, buf.writer()), else => try dump.writeNode(root, .{}, buf.writer(page.call_arena)),
} }
return buf.items; return buf.items;
} }