mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-07 03:12:33 +01:00
#435: using shadow nodes instead of modifying directly nodes' style attr
This commit is contained in:
parent
c11421d574
commit
febb18147a
@ -446,13 +446,35 @@ var uBlockCollapser = (function() {
|
|||||||
if ( document.body === null ) {
|
if ( document.body === null ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/158
|
|
||||||
// Using CSSStyleDeclaration.setProperty is more reliable
|
|
||||||
var elems = document.querySelectorAll(selectors);
|
var elems = document.querySelectorAll(selectors);
|
||||||
var i = elems.length;
|
var i = elems.length;
|
||||||
|
if ( i === 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// https://github.com/chrisaljoudi/uBlock/issues/158
|
||||||
|
// Using CSSStyleDeclaration.setProperty is more reliable
|
||||||
|
var template = vAPI.perNodeShadowTemplate;
|
||||||
|
if ( template === null ) {
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
elems[i].style.setProperty('display', 'none', 'important');
|
elems[i].style.setProperty('display', 'none', 'important');
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// https://github.com/gorhill/uBlock/issues/435
|
||||||
|
// Using shadow content so that we do not have to modify style
|
||||||
|
// attribute.
|
||||||
|
var sessionId = vAPI.sessionId;
|
||||||
|
var elem, shadow;
|
||||||
|
while ( i-- ) {
|
||||||
|
elem = elems[i];
|
||||||
|
shadow = elem.shadowRoot;
|
||||||
|
if ( shadow !== null && shadow.className === sessionId ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
shadow = elem.createShadowRoot();
|
||||||
|
shadow.className = sessionId;
|
||||||
|
shadow.appendChild(template.cloneNode(true));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extract and return the staged nodes which (may) match the selectors.
|
// Extract and return the staged nodes which (may) match the selectors.
|
||||||
|
@ -54,6 +54,14 @@ if ( vAPI.contentscriptStartInjected ) {
|
|||||||
}
|
}
|
||||||
vAPI.contentscriptStartInjected = true;
|
vAPI.contentscriptStartInjected = true;
|
||||||
vAPI.styles = vAPI.styles || [];
|
vAPI.styles = vAPI.styles || [];
|
||||||
|
vAPI.perNodeShadowTemplate = (function() {
|
||||||
|
if ( typeof document.documentElement.createShadowRoot !== 'function' ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var content = document.createElement('content');
|
||||||
|
content.select = '#' + vAPI.sessionId;
|
||||||
|
return content;
|
||||||
|
})();
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
@ -157,13 +165,35 @@ var hideElements = function(selectors) {
|
|||||||
if ( document.body === null ) {
|
if ( document.body === null ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/158
|
|
||||||
// Using CSSStyleDeclaration.setProperty is more reliable
|
|
||||||
var elems = document.querySelectorAll(selectors);
|
var elems = document.querySelectorAll(selectors);
|
||||||
var i = elems.length;
|
var i = elems.length;
|
||||||
|
if ( i === 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// https://github.com/chrisaljoudi/uBlock/issues/158
|
||||||
|
// Using CSSStyleDeclaration.setProperty is more reliable
|
||||||
|
var template = vAPI.perNodeShadowTemplate;
|
||||||
|
if ( template === null ) {
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
elems[i].style.setProperty('display', 'none', 'important');
|
elems[i].style.setProperty('display', 'none', 'important');
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// https://github.com/gorhill/uBlock/issues/435
|
||||||
|
// Using shadow content so that we do not have to modify style
|
||||||
|
// attribute.
|
||||||
|
var sessionId = vAPI.sessionId;
|
||||||
|
var elem, shadow;
|
||||||
|
while ( i-- ) {
|
||||||
|
elem = elems[i];
|
||||||
|
shadow = elem.shadowRoot;
|
||||||
|
if ( shadow !== null && shadow.className === sessionId ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
shadow = elem.createShadowRoot();
|
||||||
|
shadow.className = sessionId;
|
||||||
|
shadow.appendChild(template.cloneNode(true));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var url = window.location.href;
|
var url = window.location.href;
|
||||||
|
@ -29,8 +29,11 @@
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var showdomButton = uDom.nodeFromId('showdom');
|
||||||
|
|
||||||
// Don't bother if the browser is not modern enough.
|
// Don't bother if the browser is not modern enough.
|
||||||
if ( typeof Map === undefined || typeof WeakMap === undefined ) {
|
if ( typeof Map === undefined || typeof WeakMap === undefined ) {
|
||||||
|
showdomButton.classList.add('disabled');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +47,6 @@ var inspectedURL = '';
|
|||||||
var inspectedHostname = '';
|
var inspectedHostname = '';
|
||||||
var pollTimer = null;
|
var pollTimer = null;
|
||||||
var fingerprint = null;
|
var fingerprint = null;
|
||||||
var showdomButton = uDom.nodeFromId('showdom');
|
|
||||||
var inspector = uDom.nodeFromId('domInspector');
|
var inspector = uDom.nodeFromId('domInspector');
|
||||||
var domTree = uDom.nodeFromId('domTree');
|
var domTree = uDom.nodeFromId('domTree');
|
||||||
var tabSelector = uDom.nodeFromId('pageSelector');
|
var tabSelector = uDom.nodeFromId('pageSelector');
|
||||||
|
@ -49,6 +49,8 @@ if ( Array.isArray(styles) === false ) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sessionId = vAPI.sessionId;
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// Remove all cosmetic filtering-related styles from the DOM
|
// Remove all cosmetic filtering-related styles from the DOM
|
||||||
@ -60,15 +62,12 @@ var style, i;
|
|||||||
i = styles.length;
|
i = styles.length;
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
style = styles[i];
|
style = styles[i];
|
||||||
if ( style.parentElement === null ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
style.parentElement.removeChild(style);
|
|
||||||
selectors.push(style.textContent.replace(reProperties, ''));
|
selectors.push(style.textContent.replace(reProperties, ''));
|
||||||
|
if ( style.sheet !== null ) {
|
||||||
|
style.sheet.disabled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove `display: none !important` attribute
|
|
||||||
|
|
||||||
if ( selectors.length === 0 ) {
|
if ( selectors.length === 0 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -78,13 +77,23 @@ try {
|
|||||||
elems = document.querySelectorAll(selectors.join(','));
|
elems = document.querySelectorAll(selectors.join(','));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
i = elems.length;
|
i = elems.length;
|
||||||
|
|
||||||
|
var elem, shadow;
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
style = elems[i].style;
|
elem = elems[i];
|
||||||
|
shadow = elem.shadowRoot;
|
||||||
|
if ( shadow === undefined ) {
|
||||||
|
style = elem.style;
|
||||||
if ( typeof style === 'object' || typeof style.removeProperty === 'function' ) {
|
if ( typeof style === 'object' || typeof style.removeProperty === 'function' ) {
|
||||||
style.removeProperty('display');
|
style.removeProperty('display');
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( shadow === null || shadow.className !== sessionId ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
shadow.children[0].select = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -49,6 +49,8 @@ if ( Array.isArray(styles) === false ) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sessionId = vAPI.sessionId;
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// Insert all cosmetic filtering-related style tags in the DOM
|
// Insert all cosmetic filtering-related style tags in the DOM
|
||||||
@ -56,23 +58,16 @@ if ( Array.isArray(styles) === false ) {
|
|||||||
var selectors = [];
|
var selectors = [];
|
||||||
var reProperties = /\s*\{[^}]+\}\s*/;
|
var reProperties = /\s*\{[^}]+\}\s*/;
|
||||||
var style, i;
|
var style, i;
|
||||||
var parent = document.head || document.body || document.documentElement;
|
|
||||||
|
|
||||||
i = styles.length;
|
i = styles.length;
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
style = styles[i];
|
style = styles[i];
|
||||||
if ( style.parentElement !== null ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ( parent === null ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
selectors.push(style.textContent.replace(reProperties, ''));
|
selectors.push(style.textContent.replace(reProperties, ''));
|
||||||
parent.appendChild(style);
|
if ( style.sheet !== null ) {
|
||||||
|
style.sheet.disabled = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add `display: none !important` attribute
|
|
||||||
|
|
||||||
if ( selectors.length === 0 ) {
|
if ( selectors.length === 0 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -83,12 +78,22 @@ try {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var elem, shadow, selector = '#' + sessionId;
|
||||||
i = elems.length;
|
i = elems.length;
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
|
elem = elems[i];
|
||||||
|
shadow = elem.shadowRoot;
|
||||||
|
if ( shadow === undefined ) {
|
||||||
style = elems[i].style;
|
style = elems[i].style;
|
||||||
if ( typeof style === 'object' || typeof style.removeProperty === 'function' ) {
|
if ( typeof style === 'object' || typeof style.removeProperty === 'function' ) {
|
||||||
style.setProperty('display', 'none', 'important');
|
style.setProperty('display', 'none', 'important');
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( shadow === null || shadow.className !== sessionId ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
shadow.children[0].select = selector;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -42,7 +42,9 @@ if ( typeof vAPI !== 'object' ) {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
if ( document.querySelector('iframe.dom-inspector.' + vAPI.sessionId) !== null ) {
|
var sessionId = vAPI.sessionId;
|
||||||
|
|
||||||
|
if ( document.querySelector('iframe.dom-inspector.' + sessionId) !== null ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +161,7 @@ var toggledNodes = new Map();
|
|||||||
// Some kind of fingerprint for the DOM, without incurring too much overhead.
|
// Some kind of fingerprint for the DOM, without incurring too much overhead.
|
||||||
|
|
||||||
var domFingerprint = function() {
|
var domFingerprint = function() {
|
||||||
return vAPI.sessionId;
|
return sessionId;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -274,7 +276,7 @@ var domLayout = (function() {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// skip uBlock's own nodes
|
// skip uBlock's own nodes
|
||||||
if ( node.classList.contains(vAPI.sessionId) ) {
|
if ( node.classList.contains(sessionId) ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if ( level === 0 && localName === 'body' ) {
|
if ( level === 0 && localName === 'body' ) {
|
||||||
@ -807,14 +809,14 @@ var onScrolled = function() {
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var resetToggledNodes = function() {
|
var resetToggledNodes = function() {
|
||||||
var value;
|
var details;
|
||||||
// Chromium does not support destructuring as of v43.
|
// Chromium does not support destructuring as of v43.
|
||||||
for ( var node of toggledNodes.keys() ) {
|
for ( var node of toggledNodes.keys() ) {
|
||||||
value = toggledNodes.get(node);
|
details = toggledNodes.get(node);
|
||||||
if ( value !== null ) {
|
if ( details.show ) {
|
||||||
node.style.removeProperty('display');
|
showNode(node, details.v1, details.v2);
|
||||||
} else {
|
} else {
|
||||||
node.style.setProperty('display', value);
|
hideNode(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
toggledNodes.clear();
|
toggledNodes.clear();
|
||||||
@ -845,6 +847,7 @@ var selectNodes = function(selector, nid) {
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var shutdown = function() {
|
var shutdown = function() {
|
||||||
|
toggleStylesVisibility(true);
|
||||||
resetToggledNodes();
|
resetToggledNodes();
|
||||||
domLayout.shutdown();
|
domLayout.shutdown();
|
||||||
localMessager.removeAllListeners();
|
localMessager.removeAllListeners();
|
||||||
@ -869,32 +872,38 @@ var toggleNodes = function(nodes, originalState, targetState) {
|
|||||||
if ( i === 0 ) {
|
if ( i === 0 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var node, value;
|
var node, details;
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
node = nodes[i];
|
node = nodes[i];
|
||||||
if ( originalState ) { // any, ?
|
// originally visible node
|
||||||
if ( targetState ) { // any, any
|
if ( originalState ) {
|
||||||
value = toggledNodes.get(node);
|
// unhide visible node
|
||||||
if ( value === undefined ) {
|
if ( targetState ) {
|
||||||
continue;
|
details = toggledNodes.get(node) || {};
|
||||||
}
|
showNode(node, details.v1, details.v2);
|
||||||
if ( value !== null ) {
|
|
||||||
node.style.removeProperty('display');
|
|
||||||
} else {
|
|
||||||
node.style.setProperty('display', value);
|
|
||||||
}
|
|
||||||
toggledNodes.delete(node);
|
toggledNodes.delete(node);
|
||||||
} else { // any, hidden
|
|
||||||
toggledNodes.set(node, node.style.getPropertyValue('display') || null);
|
|
||||||
node.style.setProperty('display', 'none');
|
|
||||||
}
|
}
|
||||||
} else { // hidden, ?
|
// hide visible node
|
||||||
if ( targetState ) { // hidden, any
|
else {
|
||||||
toggledNodes.set(node, 'none');
|
toggledNodes.set(node, {
|
||||||
node.style.setProperty('display', 'initial', 'important');
|
show: true,
|
||||||
} else { // hidden, hidden
|
v1: node.style.getPropertyValue('display') || '',
|
||||||
|
v2: node.style.getPropertyPriority('display') || ''
|
||||||
|
});
|
||||||
|
hideNode(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// originally hidden node
|
||||||
|
else {
|
||||||
|
// show hidden node
|
||||||
|
if ( targetState ) {
|
||||||
|
toggledNodes.set(node, { show: false });
|
||||||
|
showNode(node, 'initial', 'important');
|
||||||
|
}
|
||||||
|
// hide hidden node
|
||||||
|
else {
|
||||||
|
hideNode(node);
|
||||||
toggledNodes.delete(node);
|
toggledNodes.delete(node);
|
||||||
node.style.setProperty('display', 'none', 'important');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -902,6 +911,56 @@ var toggleNodes = function(nodes, originalState, targetState) {
|
|||||||
|
|
||||||
// https://www.youtube.com/watch?v=L5jRewnxSBY
|
// https://www.youtube.com/watch?v=L5jRewnxSBY
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var showNode = function(node, v1, v2) {
|
||||||
|
var shadow = node.shadowRoot;
|
||||||
|
if ( shadow === undefined ) {
|
||||||
|
if ( !v1 ) {
|
||||||
|
node.style.removeProperty('display');
|
||||||
|
} else {
|
||||||
|
node.style.setProperty('display', v1, v2);
|
||||||
|
}
|
||||||
|
} else if ( shadow !== null && shadow.className === sessionId ) {
|
||||||
|
shadow.children[0].select = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var hideNode = function(node) {
|
||||||
|
var shadow = node.shadowRoot;
|
||||||
|
if ( shadow === undefined ) {
|
||||||
|
node.style.setProperty('display', 'none', 'important');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( shadow !== null && shadow.className === sessionId ) {
|
||||||
|
shadow.children[0].select = '#' + sessionId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// not all node can be shadowed
|
||||||
|
try {
|
||||||
|
shadow = node.createShadowRoot();
|
||||||
|
} catch (ex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
shadow.className = sessionId;
|
||||||
|
shadow.appendChild(vAPI.perNodeShadowTemplate.cloneNode(true));
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var toggleStylesVisibility = function(state) {
|
||||||
|
var styleTags = vAPI.styles || [];
|
||||||
|
var i = styleTags.length, sheet;
|
||||||
|
while ( i-- ) {
|
||||||
|
sheet = styleTags[i].sheet;
|
||||||
|
if ( sheet !== null ) {
|
||||||
|
sheet.disabled = !state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
@ -978,7 +1037,7 @@ var onMessage = function(request) {
|
|||||||
// Install DOM inspector widget
|
// Install DOM inspector widget
|
||||||
|
|
||||||
pickerRoot = document.createElement('iframe');
|
pickerRoot = document.createElement('iframe');
|
||||||
pickerRoot.classList.add(vAPI.sessionId);
|
pickerRoot.classList.add(sessionId);
|
||||||
pickerRoot.classList.add('dom-inspector');
|
pickerRoot.classList.add('dom-inspector');
|
||||||
pickerRoot.style.cssText = [
|
pickerRoot.style.cssText = [
|
||||||
'background: transparent',
|
'background: transparent',
|
||||||
@ -1048,6 +1107,7 @@ pickerRoot.onload = function() {
|
|||||||
window.addEventListener('scroll', onScrolled, true);
|
window.addEventListener('scroll', onScrolled, true);
|
||||||
|
|
||||||
highlightElements();
|
highlightElements();
|
||||||
|
toggleStylesVisibility(false);
|
||||||
|
|
||||||
localMessager.addListener(onMessage);
|
localMessager.addListener(onMessage);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user