This commit is contained in:
gorhill 2015-10-31 00:55:10 -04:00
parent 43be9f2c22
commit 62a6b5251e
2 changed files with 61 additions and 50 deletions

View File

@ -81,30 +81,6 @@ vAPI.shutdown.add(function() {
/******************************************************************************/ /******************************************************************************/
/******************************************************************************/ /******************************************************************************/
// https://github.com/chrisaljoudi/uBlock/issues/789
// Be sure that specific cosmetic filters are still applied.
// Executed once, then flushed from memory.
(function() {
// Were there specific cosmetic filters?
if ( typeof vAPI.specificHideStyle !== 'object' ) {
return;
}
// Is our style tag still in the DOM? (the guess is whatever parent there
// is, it is in the DOM)
if ( vAPI.specificHideStyle.parentNode !== null ) {
return;
}
// Put it back
var parent = document.head || document.documentElement;
if ( parent ) {
parent.appendChild(vAPI.specificHideStyle);
}
})();
/******************************************************************************/
/******************************************************************************/
// https://github.com/chrisaljoudi/uBlock/issues/7 // https://github.com/chrisaljoudi/uBlock/issues/7
var uBlockCollapser = (function() { var uBlockCollapser = (function() {
@ -310,11 +286,34 @@ var uBlockCollapser = (function() {
return; return;
} }
//console.debug('Starts cosmetic filtering'); //console.debug('Start cosmetic filtering');
//var timer = window.performance || Date; //var timer = window.performance || Date;
//var tStart = timer.now(); //var tStart = timer.now();
// https://github.com/chrisaljoudi/uBlock/issues/789
// https://github.com/gorhill/uBlock/issues/873
// Be sure that our style tags used for cosmetic filtering are still applied.
var checkStyleTags = function() {
var doc = document,
html = doc.documentElement,
head = doc.head,
newParent = html || head;
if ( newParent === null ) {
return;
}
var styles = vAPI.styles || [],
style, oldParent;
for ( var i = 0; i < styles.length; i++ ) {
style = styles[i];
oldParent = style.parentNode;
if ( oldParent !== head && oldParent !== html ) {
newParent.appendChild(style);
}
}
};
checkStyleTags();
var queriedSelectors = {}; var queriedSelectors = {};
var injectedSelectors = {}; var injectedSelectors = {};
var lowGenericSelectors = []; var lowGenericSelectors = [];
@ -428,7 +427,7 @@ var uBlockCollapser = (function() {
var style = document.createElement('style'); var style = document.createElement('style');
// The linefeed before the style block is very important: do no remove! // The linefeed before the style block is very important: do no remove!
style.appendChild(document.createTextNode(selectorStr + '\n{display:none !important;}')); style.appendChild(document.createTextNode(selectorStr + '\n{display:none !important;}'));
var parent = document.body || document.documentElement; var parent = document.head || document.documentElement;
if ( parent ) { if ( parent ) {
parent.appendChild(style); parent.appendChild(style);
vAPI.styles.push(style); vAPI.styles.push(style);
@ -639,15 +638,12 @@ var uBlockCollapser = (function() {
if ( injectedSelectors.hasOwnProperty('{{highHighGenerics}}') ) { if ( injectedSelectors.hasOwnProperty('{{highHighGenerics}}') ) {
return; return;
} }
//var tStart = timer.now(); // When there are too many misses for these highly generic CSS rules,
// we will just give up on looking whether they need to be injected.
if ( document.querySelector(highGenerics.hideHigh) === null ) { if ( document.querySelector(highGenerics.hideHigh) === null ) {
//console.debug('%f: high-high generic test time', timer.now() - tStart);
processHighHighGenericsMisses -= 1; processHighHighGenericsMisses -= 1;
// Too many misses for these nagging highly generic CSS rules,
// so we will just skip them from now on.
if ( processHighHighGenericsMisses === 0 ) { if ( processHighHighGenericsMisses === 0 ) {
injectedSelectors['{{highHighGenerics}}'] = true; injectedSelectors['{{highHighGenerics}}'] = true;
//console.debug('high-high generic: apparently not needed...');
} }
return; return;
} }
@ -783,9 +779,15 @@ var uBlockCollapser = (function() {
// Added node lists will be cumulated here before being processed // Added node lists will be cumulated here before being processed
var addedNodeLists = []; var addedNodeLists = [];
var addedNodeListsTimer = null; var addedNodeListsTimer = null;
var removedNodeListsTimer = null;
var collapser = uBlockCollapser; var collapser = uBlockCollapser;
var treeMutationObservedHandler = function() { // The `cosmeticFiltersActivated` message is required: a new element could
// be matching an already injected but otherwise inactive cosmetic filter.
// This means the already injected cosmetic filter become active (has an
// effect on the document), and thus must be logged if needed.
var addedNodesHandler = function() {
addedNodeListsTimer = null;
var nodeList, iNode, node; var nodeList, iNode, node;
while ( (nodeList = addedNodeLists.pop()) ) { while ( (nodeList = addedNodeLists.pop()) ) {
iNode = nodeList.length; iNode = nodeList.length;
@ -801,51 +803,60 @@ var uBlockCollapser = (function() {
collapser.iframesFromNode(node); collapser.iframesFromNode(node);
} }
} }
addedNodeListsTimer = null;
if ( contextNodes.length !== 0 ) { if ( contextNodes.length !== 0 ) {
idsFromNodeList(selectNodes('[id]')); idsFromNodeList(selectNodes('[id]'));
classesFromNodeList(selectNodes('[class]')); classesFromNodeList(selectNodes('[class]'));
retrieveGenericSelectors(); retrieveGenericSelectors();
// This is required: a new element could be matching an already
// injected but otherwise inactive cosmetic filter. This means
// the already injected cosmetic filter become active (has an
// effect on the document), and thus must be logged if needed.
messager.send({ what: 'cosmeticFiltersActivated' }); messager.send({ what: 'cosmeticFiltersActivated' });
} }
}; };
// https://github.com/gorhill/uBlock/issues/873
// This will ensure our style elements will stay in the DOM.
var removedNodesHandler = function() {
removedNodeListsTimer = null;
checkStyleTags();
};
// https://github.com/chrisaljoudi/uBlock/issues/205 // https://github.com/chrisaljoudi/uBlock/issues/205
// Do not handle added node directly from within mutation observer. // Do not handle added node directly from within mutation observer.
var treeMutationObservedHandlerAsync = function(mutations) { // I arbitrarily chose 100 ms for now: I have to compromise between the
// overhead of processing too few nodes too often and the delay of many
// nodes less often.
var domLayoutChanged = function(mutations) {
var removedNodeLists = false;
var iMutation = mutations.length; var iMutation = mutations.length;
var nodeList; var nodeList, mutation;
while ( iMutation-- ) { while ( iMutation-- ) {
nodeList = mutations[iMutation].addedNodes; mutation = mutations[iMutation];
nodeList = mutation.addedNodes;
if ( nodeList.length !== 0 ) { if ( nodeList.length !== 0 ) {
addedNodeLists.push(nodeList); addedNodeLists.push(nodeList);
} }
if ( mutation.removedNodes.length !== 0 ) {
removedNodeLists = true;
} }
if ( addedNodeListsTimer === null ) { }
// I arbitrarily chose 100 ms for now: if ( addedNodeLists.length !== 0 && addedNodeListsTimer === null ) {
// I have to compromise between the overhead of processing too few addedNodeListsTimer = vAPI.setTimeout(addedNodesHandler, 100);
// nodes too often and the delay of many nodes less often. }
addedNodeListsTimer = vAPI.setTimeout(treeMutationObservedHandler, 100); if ( removedNodeLists && removedNodeListsTimer === null ) {
removedNodeListsTimer = vAPI.setTimeout(removedNodesHandler, 100);
} }
}; };
//console.debug('Starts cosmetic filtering\'s mutations observer'); //console.debug('Starts cosmetic filtering\'s mutations observer');
// https://github.com/gorhill/httpswitchboard/issues/176 // https://github.com/gorhill/httpswitchboard/issues/176
var treeObserver = new MutationObserver(treeMutationObservedHandlerAsync); var domLayoutObserver = new MutationObserver(domLayoutChanged);
treeObserver.observe(document.body, { domLayoutObserver.observe(document.body, {
childList: true, childList: true,
subtree: true subtree: true
}); });
// https://github.com/gorhill/uMatrix/issues/144 // https://github.com/gorhill/uMatrix/issues/144
vAPI.shutdown.add(function() { vAPI.shutdown.add(function() {
treeObserver.disconnect(); domLayoutObserver.disconnect();
if ( addedNodeListsTimer !== null ) { if ( addedNodeListsTimer !== null ) {
clearTimeout(addedNodeListsTimer); clearTimeout(addedNodeListsTimer);
} }

View File

@ -98,7 +98,7 @@ var cosmeticFilters = function(details) {
} }
if ( hide.length !== 0 ) { if ( hide.length !== 0 ) {
var text = hide.join(',\n'); var text = hide.join(',\n');
var style = vAPI.specificHideStyle = document.createElement('style'); var style = document.createElement('style');
// The linefeed before the style block is very important: do not remove! // The linefeed before the style block is very important: do not remove!
style.appendChild(document.createTextNode(text + '\n{display:none !important;}')); style.appendChild(document.createTextNode(text + '\n{display:none !important;}'));
//console.debug('µBlock> "%s" cosmetic filters: injecting %d CSS rules:', details.domain, details.hide.length, hideStyleText); //console.debug('µBlock> "%s" cosmetic filters: injecting %d CSS rules:', details.domain, details.hide.length, hideStyleText);