micro-optimize pseudoclass parsing, add :modal

This commit is contained in:
Karl Seguin
2025-11-20 22:01:14 +08:00
parent 57aa267f24
commit 302b9f9dd7
3 changed files with 28 additions and 23 deletions

View File

@@ -499,6 +499,7 @@ fn attributeContainsWord(value: []const u8, word: []const u8) bool {
fn matchesPseudoClass(el: *Node.Element, pseudo: Selector.PseudoClass) bool {
switch (pseudo) {
.modal => return false,
.first_child => return isFirstChild(el),
.last_child => return isLastChild(el),
.only_child => return isFirstChild(el) and isLastChild(el),

View File

@@ -398,29 +398,25 @@ fn pseudoClass(self: *Parser, arena: Allocator, page: *Page) !Selector.PseudoCla
return error.UnknownPseudoClass;
}
// Simple pseudo-classes without arguments
if (std.mem.eql(u8, name, "first-child")) {
return .first_child;
}
if (std.mem.eql(u8, name, "last-child")) {
return .last_child;
}
if (std.mem.eql(u8, name, "only-child")) {
return .only_child;
}
if (std.mem.eql(u8, name, "first-of-type")) {
return .first_of_type;
}
if (std.mem.eql(u8, name, "last-of-type")) {
return .last_of_type;
}
if (std.mem.eql(u8, name, "only-of-type")) {
return .only_of_type;
switch (name.len) {
5 => {
if (fastEql(name, "modal")) return .modal;
},
10 => {
if (fastEql(name, "only-child")) return .only_child;
if (fastEql(name, "last-child")) return .last_child;
},
11 => {
if (fastEql(name, "first-child")) return .first_child;
},
12 => {
if (fastEql(name, "only-of-type")) return .only_of_type;
if (fastEql(name, "last-of-type")) return .last_of_type;
},
13 => {
if (fastEql(name, "first-of-type")) return .first_of_type;
},
else => {},
}
return error.UnknownPseudoClass;
@@ -801,6 +797,13 @@ fn asUint(comptime string: anytype) std.meta.Int(
return @bitCast(@as(*const [byteLength]u8, string).*);
}
fn fastEql(a: []const u8, comptime b: []const u8) bool {
for (a, b) |a_byte, b_byte| {
if (a_byte != b_byte) return false;
}
return true;
}
const testing = @import("../../../testing.zig");
test "Selector: Parser.ID" {
{

View File

@@ -131,6 +131,7 @@ pub const AttributeMatcher = union(enum) {
};
pub const PseudoClass = union(enum) {
modal,
first_child,
last_child,
only_child,