mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 23:23:28 +00:00
Merge pull request #954 from lightpanda-io/remove_managed_arraylist
Replace all std.ArrayList with std.ArrayListUnmanaged
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user