mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-10-04 10:24:56 -04:00
Engine: look through an optional stretch when reading a branch's ends
An alternation or a repeat keeps only whether its text may start and end with a token character, and read that off one marker. An optional non-token stretch there (`\/?x`) was taken as a definite non-token, so `\/ads(\/?x|\/y)` was filed under "ads" while `/adsx` carries no such token. What follows the stretch answers now.
This commit is contained in:
1 parent
433ca9b747
commit
06f7f6f295
2 files changed
+31
-2
No files matched your search
@@ -665,6 +665,19 @@ test "adblock.AdBlocker: the regex rules from EasyList" {
|
||||
try expectVerdict(&blocker, .none, "https://x.com/ABCD.js", "x.com", script);
|
||||
}
|
||||
|
||||
test "adblock.AdBlocker: a regex is found under every token it may match" {
|
||||
var blocker: AdBlocker = try .init(testing.allocator);
|
||||
defer blocker.deinit();
|
||||
|
||||
try testLoad(&blocker,
|
||||
\\/\/ads(\/?x|\/y)/$script
|
||||
);
|
||||
try expectVerdict(&blocker, .blocked, "https://example.com/adsx", "example.com", script);
|
||||
try expectVerdict(&blocker, .blocked, "https://example.com/ads/x", "example.com", script);
|
||||
try expectVerdict(&blocker, .blocked, "https://example.com/ads/y", "example.com", script);
|
||||
try expectVerdict(&blocker, .none, "https://example.com/ads/z", "example.com", script);
|
||||
}
|
||||
|
||||
test "adblock.AdBlocker: $badfilter removes a regex rule" {
|
||||
var blocker: AdBlocker = try .init(testing.allocator);
|
||||
defer blocker.deinit();
|
||||
|
||||
@@ -637,12 +637,25 @@ const RegexShape = struct {
|
||||
return c == maybe_token or c == maybe_token_optional or isTokenChar(c);
|
||||
}
|
||||
|
||||
/// Whether what `s` matches could start with a token character. An
|
||||
/// optional non-token stretch may be absent, so whatever follows it
|
||||
/// answers instead.
|
||||
fn startsTokenish(s: []const u8) bool {
|
||||
return s.len != 0 and isTokenish(s[0]);
|
||||
for (s) |c| {
|
||||
if (isTokenish(c)) return true;
|
||||
if (c != not_token_optional) return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn endsTokenish(s: []const u8) bool {
|
||||
return s.len != 0 and isTokenish(s[s.len - 1]);
|
||||
var i = s.len;
|
||||
while (i > 0) {
|
||||
i -= 1;
|
||||
if (isTokenish(s[i])) return true;
|
||||
if (s[i] != not_token_optional) return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -693,6 +706,9 @@ test "adblock.Engine: regex filters yield the tokens every match carries" {
|
||||
// An optional stretch may vanish and glue its neighbours: "adsbanner".
|
||||
tokens = try tokensOf(arena, "/\\/ads\\/?banner\\//", &buf);
|
||||
try testing.expectEqual(0, tokens.len);
|
||||
// ... also from inside a group: "adsx" is a match.
|
||||
tokens = try tokensOf(arena, "/\\/ads(\\/?x|\\/y)/", &buf);
|
||||
try testing.expectEqual(0, tokens.len);
|
||||
// A repeat is not the literal it repeats.
|
||||
tokens = try tokensOf(arena, "/\\/ab+c\\//", &buf);
|
||||
try testing.expectEqual(0, tokens.len);
|
||||
|
||||
Reference in new issue
Block a user