From 91dfcbef2a9d1a6557b65eedec8b7f11e87adc8e Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Wed, 17 Apr 2024 09:17:49 -0400 Subject: [PATCH] Improve `remove-[attr|class]` scriptlets Related issue: https://github.com/uBlockOrigin/uBlock-issues/issues/3215 --- assets/resources/scriptlets.js | 49 ++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/assets/resources/scriptlets.js b/assets/resources/scriptlets.js index 94f2df3e8..08553ef46 100644 --- a/assets/resources/scriptlets.js +++ b/assets/resources/scriptlets.js @@ -2173,18 +2173,24 @@ builtinScriptlets.push({ fn: removeAttr, dependencies: [ 'run-at.fn', + 'safe-self.fn', ], }); function removeAttr( - token = '', - selector = '', + rawToken = '', + rawSelector = '', behavior = '' ) { - if ( typeof token !== 'string' ) { return; } - if ( token === '' ) { return; } - const tokens = token.split(/\s*\|\s*/); - if ( selector === '' ) { - selector = `[${tokens.join('],[')}]`; + if ( typeof rawToken !== 'string' ) { return; } + if ( rawToken === '' ) { return; } + const safe = safeSelf(); + const logPrefix = safe.makeLogPrefix('remove-attr', rawToken, rawSelector, behavior); + const tokens = rawToken.split(/\s*\|\s*/); + const selector = tokens + .map(a => `${rawSelector}[${CSS.escape(a)}]`) + .join(','); + if ( safe.logLevel > 1 ) { + safe.uboLog(logPrefix, `Target selector:\n\t${selector}`); } let timer; const rmattr = ( ) => { @@ -2193,7 +2199,9 @@ function removeAttr( const nodes = document.querySelectorAll(selector); for ( const node of nodes ) { for ( const attr of tokens ) { + if ( node.hasAttribute(attr) === false ) { continue; } node.removeAttribute(attr); + safe.uboLog(logPrefix, `Removed attribute '${attr}'`); } } } catch(ex) { @@ -2213,7 +2221,7 @@ function removeAttr( } } if ( skip ) { return; } - timer = self.requestIdleCallback(rmattr, { timeout: 17 }); + timer = self.requestIdleCallback(rmattr, { timeout: 67 }); }; const start = ( ) => { rmattr(); @@ -2242,27 +2250,34 @@ builtinScriptlets.push({ world: 'ISOLATED', dependencies: [ 'run-at.fn', + 'safe-self.fn', ], }); function removeClass( - token = '', - selector = '', + rawToken = '', + rawSelector = '', behavior = '' ) { - if ( typeof token !== 'string' ) { return; } - if ( token === '' ) { return; } - const classTokens = token.split(/\s*\|\s*/); - if ( selector === '' ) { - selector = '.' + classTokens.map(a => CSS.escape(a)).join(',.'); + if ( typeof rawToken !== 'string' ) { return; } + if ( rawToken === '' ) { return; } + const safe = safeSelf(); + const logPrefix = safe.makeLogPrefix('remove-class', rawToken, rawSelector, behavior); + const tokens = rawToken.split(/\s*\|\s*/); + const selector = tokens + .map(a => `${rawSelector}.${CSS.escape(a)}`) + .join(','); + if ( safe.logLevel > 1 ) { + safe.uboLog(logPrefix, `Target selector:\n\t${selector}`); } const mustStay = /\bstay\b/.test(behavior); let timer; - const rmclass = function() { + const rmclass = ( ) => { timer = undefined; try { const nodes = document.querySelectorAll(selector); for ( const node of nodes ) { - node.classList.remove(...classTokens); + node.classList.remove(...tokens); + safe.uboLog(logPrefix, 'Removed class(es)'); } } catch(ex) { }