mirror of https://github.com/gorhill/uBlock.git
fix #3159
This commit is contained in:
parent
9c23e4ab67
commit
374e157b11
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue