From bf697f344a55a7adbf5d4f9a201dba4669e339af Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Mon, 30 Sep 2019 18:21:24 -0400 Subject: [PATCH] Log procedural cosmetic exception filters Related issue: - https://github.com/gorhill/uBlock/issues/127 Procedural cosmetic exception filters were the last class of cosmetic exception filters not being reported in the logger; this commit fixes this. Additionally, ensure that a single DOM listener can't prevent other listeners from being processed by throwing an exception. Such approach would have prevented regression leading to emergency release 1.22.4: - https://github.com/gorhill/uBlock/releases/tag/1.22.4 --- src/js/contentscript.js | 11 +++++++---- src/js/scriptlets/cosmetic-logger.js | 20 +++++++++++++++++--- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/js/contentscript.js b/src/js/contentscript.js index 42b83e25f..7ed08c7d2 100644 --- a/src/js/contentscript.js +++ b/src/js/contentscript.js @@ -267,7 +267,7 @@ vAPI.SafeAnimationFrame.prototype = { /******************************************************************************/ /******************************************************************************/ -vAPI.domWatcher = (function() { +vAPI.domWatcher = (( ) => { const addedNodeLists = []; const removedNodeLists = []; @@ -311,7 +311,8 @@ vAPI.domWatcher = (function() { //console.timeEnd('dom watcher/safe observer handler'); if ( addedNodes.length === 0 && removedNodes === false ) { return; } for ( const listener of getListenerIterator() ) { - listener.onDOMChanged(addedNodes, removedNodes); + try { listener.onDOMChanged(addedNodes, removedNodes); } + catch (ex) { } } addedNodes.length = 0; removedNodes = false; @@ -373,7 +374,8 @@ vAPI.domWatcher = (function() { listeners.push(listener); listenerIteratorDirty = true; if ( domIsReady !== true ) { return; } - listener.onDOMCreated(); + try { listener.onDOMCreated(); } + catch (ex) { } startMutationObserver(); }; @@ -401,7 +403,8 @@ vAPI.domWatcher = (function() { const start = function() { domIsReady = true; for ( const listener of getListenerIterator() ) { - listener.onDOMCreated(); + try { listener.onDOMCreated(); } + catch (ex) { } } startMutationObserver(); }; diff --git a/src/js/scriptlets/cosmetic-logger.js b/src/js/scriptlets/cosmetic-logger.js index 1120c68d4..e8be4fc4a 100644 --- a/src/js/scriptlets/cosmetic-logger.js +++ b/src/js/scriptlets/cosmetic-logger.js @@ -46,6 +46,7 @@ let declarativeStyleStr; const proceduralDict = new Map(); const exceptionDict = new Map(); let exceptionStr; +const proceduralExceptionDict = new Map(); const nodesToProcess = new Set(); const loggedSelectors = new Set(); @@ -172,6 +173,17 @@ const processExceptions = function(out) { /******************************************************************************/ +const processProceduralExceptions = function(out) { + if ( proceduralExceptionDict.size === 0 ) { return; } + for ( const exception of proceduralExceptionDict.values() ) { + if ( exception.test() === false ) { continue; } + out.push(`#@#${exception.raw}`); + proceduralExceptionDict.delete(exception.raw); + } +}; + +/******************************************************************************/ + const processTimer = new vAPI.SafeAnimationFrame(( ) => { //console.time('dom logger/scanning for matches'); processTimer.clear(); @@ -193,6 +205,7 @@ const processTimer = new vAPI.SafeAnimationFrame(( ) => { processDeclarativeStyle(toLog); processProcedural(toLog); processExceptions(toLog); + processProceduralExceptions(toLog); nodesToProcess.clear(); @@ -268,9 +281,10 @@ const handlers = { exceptionDict.set(details.style[0], details.raw); continue; } - // TODO: - // Handling of procedural cosmetic exception filters - // not implemented. + proceduralExceptionDict.set( + details.raw, + vAPI.domFilterer.createProceduralFilter(details) + ); } exceptionStr = undefined; }