From 35c36cc093fd3775d85d9b91cd44e0deebd8b5c1 Mon Sep 17 00:00:00 2001 From: HoJeong Go Date: Fri, 13 Dec 2024 15:20:25 +0900 Subject: [PATCH] feat: merge denyallow and to --- packages/adblocker/src/filters/network.ts | 21 +++++---------------- packages/adblocker/test/parsing.test.ts | 14 +++++++++----- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/packages/adblocker/src/filters/network.ts b/packages/adblocker/src/filters/network.ts index 6cae716f33..035e151940 100644 --- a/packages/adblocker/src/filters/network.ts +++ b/packages/adblocker/src/filters/network.ts @@ -153,7 +153,6 @@ export const enum NETWORK_FILTER_MASK { isHostnameAnchor = 1 << 28, isRedirectRule = 1 << 29, isRedirect = 1 << 30, - isTo = 1 << 31, // IMPORTANT: the mask is now full, no more options can be added // Consider creating a separate fitler type for isReplace if a new // network filter option is needed. @@ -726,6 +725,7 @@ export default class NetworkFilter implements IFilter { // --------------------------------------------------------------------- // // parseOptions // --------------------------------------------------------------------- // + const denyallowEntities: Set = new Set(); for (const rawOption of getFilterOptions(line, optionsIndex + 1, line.length)) { const negation = rawOption[0].charCodeAt(0) === 126; /* '~' */ const option = negation === true ? rawOption[0].slice(1) : rawOption[0]; @@ -734,17 +734,14 @@ export default class NetworkFilter implements IFilter { switch (option) { case 'to': case 'denyallow': { - if (denyallow !== undefined) { - return null; - } let parts = value.split('|'); if (option === 'to') { - mask = setBit(mask, NETWORK_FILTER_MASK.isTo); parts = parts.map((part) => part.charCodeAt(0) === 126 /* '~' */ ? part.slice(1) : `~${part}`, ); } - denyallow = Domains.parse(parts, debug); + parts.forEach((part) => denyallowEntities.add(part)); + denyallow = Domains.parse(Array.from(denyallowEntities), debug); break; } case 'domain': @@ -1536,14 +1533,10 @@ export default class NetworkFilter implements IFilter { } if (this.denyallow !== undefined) { - const optionName = this.isTo() ? 'to' : 'denyallow'; if (this.denyallow.parts !== undefined) { - const parts = this.denyallow.parts.split(','); - options.push( - `${optionName}=${this.isTo() ? parts.map((part) => (part.charCodeAt(0) === 126 /* '~' */ ? part.slice(1) : `~${part}`)).join('|') : parts.join('|')}`, - ); + options.push(`denyallow=${this.denyallow.parts.replace(/,/g, '|')}`); } else { - options.push(`${optionName}=`); + options.push('denyallow='); } } @@ -1834,10 +1827,6 @@ export default class NetworkFilter implements IFilter { return getBit(this.mask, NETWORK_FILTER_MASK.isBadFilter); } - public isTo() { - return getBit(this.mask, NETWORK_FILTER_MASK.isTo); - } - public isUnicode() { return getBit(this.mask, NETWORK_FILTER_MASK.isUnicode); } diff --git a/packages/adblocker/test/parsing.test.ts b/packages/adblocker/test/parsing.test.ts index f06664900a..5149de76c7 100644 --- a/packages/adblocker/test/parsing.test.ts +++ b/packages/adblocker/test/parsing.test.ts @@ -805,12 +805,16 @@ describe('Network filters', () => { }); context('to', () => { - it('fails when both denyallow and to used', () => { - network('||foo.com$denyallow=foo.com,to=bar.com', null); - network('||foo.com$to=foo.com,denyallow=bar.com', null); - }); - it('reverses domains condition', () => { + network('||foo.com$to=foo.com|~bar.com,denyallow=bar.com|~foo.com', { + denyallow: { + hostnames: h(['bar.com']), + entities: undefined, + notHostnames: h(['foo.com']), + notEntities: undefined, + parts: undefined, + }, + }); network('||foo.com$to=bar.com|baz.com', { denyallow: { hostnames: undefined,