From 59ece79d147447532c1ba578b4d24c2d42115aca Mon Sep 17 00:00:00 2001 From: Jonathan Kingston Date: Wed, 3 Nov 2021 11:22:43 +0000 Subject: [PATCH] Move to using mutation observing to reduce page overhead (#985) --- Core/contentblocker.js | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/Core/contentblocker.js b/Core/contentblocker.js index b558aedc7c..59dd5098a7 100644 --- a/Core/contentblocker.js +++ b/Core/contentblocker.js @@ -537,6 +537,7 @@ _utf8_encode : function (string) { // public function shouldBlock(trackerUrl, type) { + seenUrls.add(trackerUrl) let startTime = performance.now() if (!blockingEnabled) { @@ -589,14 +590,18 @@ _utf8_encode : function (string) { return false } + const seenUrls = new Set() + function hasNotSeen(url) { + return !seenUrls.has(url) + } + function processPage() { - [].slice.apply(document.scripts).forEach(function(el) { + [...document.scripts].filter(hasNotSeen).forEach((el) => { if (shouldBlock(el.src, 'SCRIPT')) { duckduckgoDebugMessaging.log("blocking load") } - }); - [].slice.apply(document.images).forEach(function(el) { + [...document.images].filter(hasNotSeen).forEach((el) => { // If the image's natural width is zero, then it has not loaded so we // can assume that it may have been blocked. if (el.naturalWidth === 0) { @@ -605,25 +610,34 @@ _utf8_encode : function (string) { } } }); - [].slice.apply(document.querySelectorAll('link')).forEach(function(el) { + [...document.querySelectorAll('link')].filter(hasNotSeen).forEach((el) => { if (shouldBlock(el.href, 'LINK')) { duckduckgoDebugMessaging.log("blocking load") } }); - [].slice.apply(document.querySelectorAll('iframe')).forEach(function(el) { - if (shouldBlock(el.src, 'IFRAME')) { - duckduckgoDebugMessaging.log("blocking load") - } + [...document.querySelectorAll('iframe')].filter(hasNotSeen).forEach((el) => { + if (shouldBlock(el.src, 'IFRAME')) { + duckduckgoDebugMessaging.log("blocking load") + } }); - scheduleProcessPage() } - - var interval = 1 - function scheduleProcessPage() { - interval *= 2 - setTimeout(processPage, interval * 1000) + + function debounce(func, wait) { + let timeout + return function () { + clearTimeout(timeout) + timeout = setTimeout(() => { + func.apply(this, arguments) + }, wait) + } } + const observer = new MutationObserver(debounce((mutations, o) => { + processPage() + }, 100)) + const rootElement = document.body || document.documentElement + observer.observe(rootElement, { childList: true, subtree: true }); + // Init (function() {