1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-10-04 16:47:15 +02:00
This commit is contained in:
gorhill 2017-11-14 15:03:20 -05:00
parent 9c23e4ab67
commit 374e157b11
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
5 changed files with 167 additions and 111 deletions

View File

@ -222,7 +222,11 @@ vAPI.DOMFilterer.prototype = {
vAPI.userStylesheet.add(selectorsStr + '\n{' + declarations + '}');
this.commit();
this.triggerListeners('declarative', selectorsStr);
if ( this.hasListeners() ) {
this.triggerListeners({
declarative: [ [ selectorsStr, declarations ] ]
});
}
if ( declarations !== 'display:none!important;' ) {
this.specificOthers.push({
@ -309,10 +313,14 @@ vAPI.DOMFilterer.prototype = {
this.listeners.splice(pos, 1);
},
triggerListeners: function(type, selectors) {
hasListeners: function() {
return this.listeners.length !== 0;
},
triggerListeners: function(changes) {
var i = this.listeners.length;
while ( i-- ) {
this.listeners[i].onFiltersetChanged(type, selectors);
this.listeners[i].onFiltersetChanged(changes);
}
},
@ -459,37 +467,59 @@ vAPI.DOMFilterer.prototype = {
}
},
getAllDeclarativeSelectors_: function(all) {
var out = [];
getAllSelectors_: function(all) {
var out = {
declarative: []
};
if ( this.specificSimpleHide.size !== 0 ) {
out.push(Array.from(this.specificSimpleHide).join(',\n'));
out.declarative.push([
Array.from(this.specificSimpleHide).join(',\n'),
'display:none!important;'
]);
}
if ( this.specificComplexHide.size !== 0 ) {
out.push(Array.from(this.specificComplexHide).join(',\n'));
out.declarative.push([
Array.from(this.specificComplexHide).join(',\n'),
'display:none!important;'
]);
}
if ( this.genericSimpleHide.size !== 0 ) {
out.push(Array.from(this.genericSimpleHide).join(',\n'));
out.declarative.push([
Array.from(this.genericSimpleHide).join(',\n'),
'display:none!important;'
]);
}
if ( this.genericComplexHide.size !== 0 ) {
out.push(Array.from(this.genericComplexHide).join(',\n'));
out.declarative.push([
Array.from(this.genericComplexHide).join(',\n'),
'display:none!important;'
]);
}
if ( all ) {
out.push('[' + this.hideNodeAttr + ']');
out.declarative.push([
'[' + this.hideNodeAttr + ']',
'display:none!important;'
]);
}
for ( var entry of this.specificOthers ) {
out.push(entry.selectors);
out.declarative.push([ entry.selectors, entry.declarations ]);
}
return out.join(',\n');
return out;
},
getFilteredElementCount: function() {
var selectors = this.getAllDeclarativeSelectors_(true);
var details = this.getAllSelectors_(true);
if ( Array.isArray(details.declarative) === false ) { return 0; }
var selectors = details.declarative.reduce(function(acc, entry) {
acc.push(entry[0]);
return acc;
}, []);
if ( selectors.length === 0 ) { return 0; }
return document.querySelectorAll(selectors).length;
return document.querySelectorAll(selectors.join(',\n')).length;
},
getAllDeclarativeSelectors: function() {
return this.getAllDeclarativeSelectors_();
getAllSelectors: function() {
return this.getAllSelectors_(false);
}
};

View File

@ -80,8 +80,7 @@ vAPI.DOMFilterer.prototype = {
// - Notifying listeners about changed filterset.
commitNow: function() {
this.commitTimer.clear();
var userStylesheet = vAPI.userStylesheet,
addedSelectors = [];
var userStylesheet = vAPI.userStylesheet;
for ( var entry of this.addedCSSRules ) {
if (
this.disabled === false &&
@ -92,13 +91,9 @@ vAPI.DOMFilterer.prototype = {
entry.selectors + '\n{' + entry.declarations + '}'
);
}
addedSelectors.push(entry.selectors);
}
this.addedCSSRules.clear();
userStylesheet.apply();
if ( addedSelectors.length !== 0 ) {
this.triggerListeners('declarative', addedSelectors.join(',\n'));
}
},
commit: function(commitNow) {
@ -133,6 +128,11 @@ vAPI.DOMFilterer.prototype = {
vAPI.userStylesheet.add(selectorsStr + '\n{' + declarations + '}');
}
this.commit();
if ( this.hasListeners() ) {
this.triggerListeners({
declarative: [ [ selectorsStr, declarations ] ]
});
}
},
addListener: function(listener) {
@ -146,10 +146,14 @@ vAPI.DOMFilterer.prototype = {
this.listeners.splice(pos, 1);
},
triggerListeners: function(type, selectors) {
hasListeners: function() {
return this.listeners.length !== 0;
},
triggerListeners: function(changes) {
var i = this.listeners.length;
while ( i-- ) {
this.listeners[i].onFiltersetChanged(type, selectors);
this.listeners[i].onFiltersetChanged(changes);
}
},
@ -196,29 +200,30 @@ vAPI.DOMFilterer.prototype = {
userStylesheet.apply();
},
getAllDeclarativeSelectors_: function(all) {
let selectors = [];
getAllSelectors_: function(all) {
var out = {
declarative: []
};
for ( var entry of this.filterset ) {
if ( all === false && entry.internal ) { continue; }
selectors.push(entry.selectors);
}
var out = selectors.join(',\n');
if ( !all && this.hideNodeAttr !== undefined ) {
out = out.replace('[' + this.hideNodeAttr + ']', '')
.replace(/^,\n|\n,|,\n$/, '');
out.declarative.push([ entry.selectors, entry.declarations ]);
}
return out;
},
getFilteredElementCount: function() {
let selectors = this.getAllDeclarativeSelectors_(true);
return selectors.length !== 0
? document.querySelectorAll(selectors).length
: 0;
let details = this.getAllSelectors_(true);
if ( Array.isArray(details.declarative) === false ) { return 0; }
let selectors = details.declarative.reduce(function(acc, entry) {
acc.push(entry[0]);
return acc;
}, []);
if ( selectors.length === 0 ) { return 0; }
return document.querySelectorAll(selectors.join(',\n')).length;
},
getAllDeclarativeSelectors: function() {
return this.getAllDeclarativeSelectors_(false);
getAllSelectors: function() {
return this.getAllSelectors_(false);
}
};

View File

@ -571,10 +571,11 @@ vAPI.DOMFilterer = (function() {
}
if ( mustCommit === false ) { return; }
this.domFilterer.commit();
this.domFilterer.triggerListeners(
'procedural',
new Map(this.addedSelectors)
);
if ( this.domFilterer.hasListeners() ) {
this.domFilterer.triggerListeners({
procedural: Array.from(this.addedSelectors.values())
});
}
},
commitNow: function() {
@ -696,8 +697,10 @@ vAPI.DOMFilterer = (function() {
return this.proceduralFilterer.createProceduralFilter(o);
};
domFilterer.prototype.getAllProceduralSelectors = function() {
return new Map(this.proceduralFilterer.selectors);
domFilterer.prototype.getAllSelectors = function() {
var out = DOMFiltererBase.prototype.getAllSelectors.call(this);
out.procedural = Array.from(this.proceduralFilterer.selectors.values());
return out;
};
domFilterer.prototype.getAllExceptionSelectors = function() {

View File

@ -149,40 +149,55 @@ var jobQueueTimer = new vAPI.SafeAnimationFrame(function processJobQueue() {
});
var handlers = {
onFiltersetChanged: function(type, selectors) {
onFiltersetChanged: function(changes) {
//console.time('dom logger/filterset changed');
var selector,
sanitized;
if ( type === 'declarative' ) {
var simpleSizeBefore = simple.dict.size,
complexSizeBefore = complex.dict.size;
for ( selector of selectors.split(',\n') ) {
if ( reHasPseudoClass.test(selector) ) {
sanitized = selector.replace(reHasPseudoClass, '');
sanitizedSelectors.set(sanitized, selector);
selector = sanitized;
}
if ( reHasCSSCombinators.test(selector) ) {
complex.dict.add(selector);
complex.str = undefined;
var selector, sanitized, entry,
simpleSizeBefore = simple.dict.size,
complexSizeBefore = complex.dict.size,
logNow = [];
for ( entry of (changes.declarative || []) ) {
for ( selector of entry[0].split(',\n') ) {
if ( entry[1] === 'display:none!important;' ) {
if ( reHasPseudoClass.test(selector) ) {
sanitized = selector.replace(reHasPseudoClass, '');
sanitizedSelectors.set(sanitized, selector);
selector = sanitized;
}
if ( reHasCSSCombinators.test(selector) ) {
complex.dict.add(selector);
complex.str = undefined;
} else {
simple.dict.add(selector);
simple.str = undefined;
}
} else {
simple.dict.add(selector);
simple.str = undefined;
logNow.push(selector + ':style(' + entry[1] + ')');
}
}
if ( simple.dict.size !== simpleSizeBefore ) {
jobQueue.push(DeclarativeSimpleJob.create(document));
}
if ( simple.dict.size !== simpleSizeBefore ) {
jobQueue.push(DeclarativeSimpleJob.create(document));
}
if ( complex.dict.size !== complexSizeBefore ) {
complex.str = Array.from(complex.dict).join(',\n');
jobQueue.push(DeclarativeComplexJob.create());
}
if ( logNow.length !== 0 ) {
vAPI.messaging.send(
'scriptlets',
{
what: 'logCosmeticFilteringData',
frameURL: window.location.href,
frameHostname: window.location.hostname,
matchedSelectors: logNow
}
);
}
if ( Array.isArray(changes.procedural) ) {
for ( selector of changes.procedural ) {
procedural.dict.set(selector.raw, selector);
}
if ( complex.dict.size !== complexSizeBefore ) {
complex.str = Array.from(complex.dict).join(',\n');
jobQueue.push(DeclarativeComplexJob.create());
}
} else if ( type === 'procedural' ) {
for ( selector of selectors ) {
procedural.dict.set(selector[0], selector[1]);
}
if ( selectors.size !== 0 ) {
if ( changes.procedural.size !== 0 ) {
jobQueue.push(ProceduralJob.create());
}
}
@ -193,14 +208,7 @@ var handlers = {
},
onDOMCreated: function() {
handlers.onFiltersetChanged(
'declarative',
vAPI.domFilterer.getAllDeclarativeSelectors()
);
handlers.onFiltersetChanged(
'procedural',
vAPI.domFilterer.getAllProceduralSelectors()
);
handlers.onFiltersetChanged(vAPI.domFilterer.getAllSelectors());
vAPI.domFilterer.addListener(handlers);
},
@ -225,7 +233,6 @@ var handlers = {
jobQueueTimer.start(100);
}
}
};
/******************************************************************************/

View File

@ -693,43 +693,42 @@ var cosmeticFilterMapper = (function() {
var nodesFromStyleTag = function(rootNode) {
var filterMap = roRedNodes,
selectors, selector,
nodes, node,
i, j;
entry, selector, canonical, nodes, node;
var details = vAPI.domFilterer.getAllSelectors();
// Declarative selectors.
selectors = vAPI.domFilterer.getAllDeclarativeSelectors().split(',\n');
i = selectors.length;
while ( i-- ) {
selector = selectors[i];
if ( reHasCSSCombinators.test(selector) ) {
nodes = document.querySelectorAll(selector);
} else {
if (
filterMap.has(rootNode) === false &&
rootNode[matchesFnName](selector)
) {
filterMap.set(rootNode, selector);
for ( entry of (details.declarative || []) ) {
for ( selector of entry[0].split(',\n') ) {
canonical = selector;
if ( entry[1] !== 'display:none!important;' ) {
canonical += ':style(' + entry[1] + ')';
}
nodes = rootNode.querySelectorAll(selector);
}
j = nodes.length;
while ( j-- ) {
node = nodes[j];
if ( filterMap.has(node) === false ) {
filterMap.set(node, selector);
if ( reHasCSSCombinators.test(selector) ) {
nodes = document.querySelectorAll(selector);
} else {
if (
filterMap.has(rootNode) === false &&
rootNode[matchesFnName](selector)
) {
filterMap.set(rootNode, canonical);
}
nodes = rootNode.querySelectorAll(selector);
}
for ( node of nodes ) {
if ( filterMap.has(node) === false ) {
filterMap.set(node, canonical);
}
}
}
}
// Procedural selectors.
selectors = vAPI.domFilterer.getAllProceduralSelectors();
for ( var entry of selectors ) {
nodes = entry[1].exec();
j = nodes.length;
while ( j-- ) {
for ( entry of (details.procedural || []) ) {
nodes = entry.exec();
for ( node of nodes ) {
if ( filterMap.has(node) === false ) {
filterMap.set(node, entry[0]);
filterMap.set(node, entry.raw);
}
}
}
@ -968,6 +967,18 @@ var selectNodes = function(selector, nid) {
/******************************************************************************/
var nodesFromFilter = function(selector) {
var out = [];
for ( var entry of roRedNodes ) {
if ( entry[1] === selector ) {
out.push(entry[0]);
}
}
return out;
};
/******************************************************************************/
var shutdown = function() {
cosmeticFilterMapper.shutdown();
domLayout.shutdown();
@ -1042,7 +1053,7 @@ var onMessage = function(request) {
case 'toggleFilter':
toggleExceptions(
selectNodes(request.filter, request.nid),
nodesFromFilter(request.filter),
request.target
);
highlightElements(true);