From 5178b91fa13b58c1c81ac54923d3f9236af00f4f Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Wed, 16 Feb 2022 12:21:10 -0500 Subject: [PATCH] Revert "Prevent highly generic cosmetic filters from affecting html/body elements" This reverts commit 7c8aec250f03580bbd761810bf5bf26d277683b0. This will be brought back in a future dev cycle. Potentially related issues: - https://github.com/uBlockOrigin/uBlock-issues/issues/1978 - https://github.com/uBlockOrigin/uBlock-issues/issues/1983 --- src/js/contentscript.js | 5 --- src/js/cosmetic-filtering.js | 47 +++++++++++----------------- src/js/scriptlets/cosmetic-logger.js | 6 ++-- src/js/scriptlets/dom-inspector.js | 4 +-- 4 files changed, 23 insertions(+), 39 deletions(-) diff --git a/src/js/contentscript.js b/src/js/contentscript.js index 618ded875..f2dcd1467 100644 --- a/src/js/contentscript.js +++ b/src/js/contentscript.js @@ -676,11 +676,6 @@ vAPI.DOMFilterer = class { getAllExceptionSelectors() { return this.exceptions.join(',\n'); } - - unwrapSelector(s) { - const match = /^:is\((.+)\):not\(html,body\)\/\*hg\*\/$/.exec(s); - return match !== null ? match[1] : s; - } }; /******************************************************************************/ diff --git a/src/js/cosmetic-filtering.js b/src/js/cosmetic-filtering.js index 70448ae94..3634a80ef 100644 --- a/src/js/cosmetic-filtering.js +++ b/src/js/cosmetic-filtering.js @@ -227,11 +227,13 @@ const FilterContainer = function() { this.highlyGeneric.simple = { canonical: 'highGenericHideSimple', dict: new Set(), + str: '', mru: new µb.MRUCache(16) }; this.highlyGeneric.complex = { canonical: 'highGenericHideComplex', dict: new Set(), + str: '', mru: new µb.MRUCache(16) }; @@ -279,16 +281,11 @@ FilterContainer.prototype.reset = function() { // highly generic selectors sets this.highlyGeneric.simple.dict.clear(); + this.highlyGeneric.simple.str = ''; this.highlyGeneric.simple.mru.reset(); this.highlyGeneric.complex.dict.clear(); + this.highlyGeneric.complex.str = ''; this.highlyGeneric.complex.mru.reset(); - - // https://developer.mozilla.org/en-US/docs/Web/CSS/:is#browser_compatibility - // https://developer.mozilla.org/en-US/docs/Web/CSS/:not#browser_compatibility - // Need support for both `:is()` and `:not()` with selector list. - this.cssIs = - vAPI.webextFlavor.soup.has('firefox') && vAPI.webextFlavor.major >= 84 || - vAPI.webextFlavor.soup.has('chromium') && vAPI.webextFlavor.major >= 88; }; /******************************************************************************/ @@ -303,7 +300,9 @@ FilterContainer.prototype.freeze = function() { this.lowlyGeneric.cl.simple.size !== 0 || this.lowlyGeneric.cl.complex.size !== 0; + this.highlyGeneric.simple.str = Array.from(this.highlyGeneric.simple.dict).join(',\n'); this.highlyGeneric.simple.mru.reset(); + this.highlyGeneric.complex.str = Array.from(this.highlyGeneric.complex.dict).join(',\n'); this.highlyGeneric.complex.mru.reset(); this.frozen = true; @@ -707,7 +706,9 @@ FilterContainer.prototype.fromSelfie = function(selfie) { this.lowlyGeneric.cl.simple = new Set(selfie.lowlyGenericSCL); this.lowlyGeneric.cl.complex = new Map(selfie.lowlyGenericCCL); this.highlyGeneric.simple.dict = new Set(selfie.highSimpleGenericHideArray); + this.highlyGeneric.simple.str = selfie.highSimpleGenericHideArray.join(',\n'); this.highlyGeneric.complex.dict = new Set(selfie.highComplexGenericHideArray); + this.highlyGeneric.complex.str = selfie.highComplexGenericHideArray.join(',\n'); this.needDOMSurveyor = selfie.lowlyGenericSID.length !== 0 || selfie.lowlyGenericCID.length !== 0 || @@ -1041,19 +1042,14 @@ FilterContainer.prototype.retrieveSpecificSelectors = function( // indirectly in the mru cache: this is to prevent duplication of the // string in memory, which I have observed occurs when the string is // stored directly as a value in a Map. - // - // https://github.com/uBlockOrigin/uBlock-issues/issues/1692 - // Wrap generic selectors to prevent matching `html` or `body` - // elements. Content script-side code must unwrap those selectors - // before reporting them in a user interface. if ( options.noGenericCosmeticFiltering !== true ) { const exceptionSetHash = out.exceptionFilters.join(); for ( const key in this.highlyGeneric ) { const entry = this.highlyGeneric[key]; - let genericSet = entry.dict; - let cache = entry.mru.lookup(exceptionSetHash); - if ( cache === undefined ) { - cache = { s: '', excepted: [] }; + let str = entry.mru.lookup(exceptionSetHash); + if ( str === undefined ) { + str = { s: entry.str, excepted: [] }; + let genericSet = entry.dict; let hit = false; for ( const exception of exceptionSet ) { if ( (hit = genericSet.has(exception)) ) { break; } @@ -1062,23 +1058,18 @@ FilterContainer.prototype.retrieveSpecificSelectors = function( genericSet = new Set(entry.dict); for ( const exception of exceptionSet ) { if ( genericSet.delete(exception) ) { - cache.excepted.push(exception); + str.excepted.push(exception); } } + str.s = Array.from(genericSet).join(',\n'); } - let genericArr = Array.from(genericSet); - if ( this.cssIs ) { - genericArr = - genericArr.map(a => `:is(${a}):not(html,body)/*hg*/`); - } - cache.s = genericArr.join(',\n'); - entry.mru.add(exceptionSetHash, cache); + entry.mru.add(exceptionSetHash, str); } - if ( cache.excepted.length !== 0 ) { - out.exceptedFilters.push(...cache.excepted); + if ( str.excepted.length !== 0 ) { + out.exceptedFilters.push(...str.excepted); } - if ( cache.s.length !== 0 ) { - injectedHideFilters.push(cache.s); + if ( str.s.length !== 0 ) { + injectedHideFilters.push(str.s); } } } diff --git a/src/js/scriptlets/cosmetic-logger.js b/src/js/scriptlets/cosmetic-logger.js index eae387e66..53a626eed 100644 --- a/src/js/scriptlets/cosmetic-logger.js +++ b/src/js/scriptlets/cosmetic-logger.js @@ -91,7 +91,6 @@ const processDeclarativeSimple = function(node, out) { ) { return; } - const unwrapSelector = vAPI.domFilterer.unwrapSelector; for ( const selector of simpleDeclarativeSet ) { if ( (node === document || safeMatchSelector(selector, node) === false) && @@ -99,7 +98,7 @@ const processDeclarativeSimple = function(node, out) { ) { continue; } - out.push(`##${unwrapSelector(selector)}`); + out.push(`##${selector}`); simpleDeclarativeSet.delete(selector); simpleDeclarativeStr = undefined; loggedSelectors.add(selector); @@ -114,10 +113,9 @@ const processDeclarativeComplex = function(out) { complexDeclarativeStr = safeGroupSelectors(complexDeclarativeSet); } if ( document.querySelector(complexDeclarativeStr) === null ) { return; } - const unwrapSelector = vAPI.domFilterer.unwrapSelector; for ( const selector of complexDeclarativeSet ) { if ( safeQuerySelector(selector) === null ) { continue; } - out.push(`##${unwrapSelector(selector)}`); + out.push(`##${selector}`); complexDeclarativeSet.delete(selector); complexDeclarativeStr = undefined; loggedSelectors.add(selector); diff --git a/src/js/scriptlets/dom-inspector.js b/src/js/scriptlets/dom-inspector.js index 1cdd35423..c1edb90f4 100644 --- a/src/js/scriptlets/dom-inspector.js +++ b/src/js/scriptlets/dom-inspector.js @@ -1,7 +1,7 @@ /******************************************************************************* uBlock Origin - a browser extension to block requests. - Copyright (C) 2015-present Raymond Hill + Copyright (C) 2015-2018 Raymond Hill This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -509,7 +509,7 @@ const cosmeticFilterMapper = (function() { // Declarative selectors. for ( const entry of (details.declarative || []) ) { for ( const selector of entry[0].split(',\n') ) { - let canonical = vAPI.domFilterer.unwrapSelector(selector); + let canonical = selector; let nodes; if ( entry[1] !== vAPI.hideStyle ) { canonical += ':style(' + entry[1] + ')';