1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-11-07 03:12:33 +01:00

this makes shadow DOM work on Firefox

This commit is contained in:
gorhill 2015-07-06 13:53:39 -04:00
parent f1b9e27fdb
commit e3e4d577ee
5 changed files with 47 additions and 53 deletions

View File

@ -453,8 +453,7 @@ var uBlockCollapser = (function() {
} }
// https://github.com/chrisaljoudi/uBlock/issues/158 // https://github.com/chrisaljoudi/uBlock/issues/158
// Using CSSStyleDeclaration.setProperty is more reliable // Using CSSStyleDeclaration.setProperty is more reliable
var template = vAPI.perNodeShadowTemplate; if ( document.body.shadowRoot === undefined ) {
if ( template === null ) {
while ( i-- ) { while ( i-- ) {
elems[i].style.setProperty('display', 'none', 'important'); elems[i].style.setProperty('display', 'none', 'important');
} }
@ -473,7 +472,6 @@ var uBlockCollapser = (function() {
} }
shadow = elem.createShadowRoot(); shadow = elem.createShadowRoot();
shadow.className = sessionId; shadow.className = sessionId;
shadow.appendChild(template.cloneNode(true));
} }
}; };

View File

@ -54,14 +54,6 @@ 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;
})();
/******************************************************************************/ /******************************************************************************/
@ -172,8 +164,7 @@ var hideElements = function(selectors) {
} }
// https://github.com/chrisaljoudi/uBlock/issues/158 // https://github.com/chrisaljoudi/uBlock/issues/158
// Using CSSStyleDeclaration.setProperty is more reliable // Using CSSStyleDeclaration.setProperty is more reliable
var template = vAPI.perNodeShadowTemplate; if ( document.body.shadowRoot === undefined ) {
if ( template === null ) {
while ( i-- ) { while ( i-- ) {
elems[i].style.setProperty('display', 'none', 'important'); elems[i].style.setProperty('display', 'none', 'important');
} }
@ -192,7 +183,6 @@ var hideElements = function(selectors) {
} }
shadow = elem.createShadowRoot(); shadow = elem.createShadowRoot();
shadow.className = sessionId; shadow.className = sessionId;
shadow.appendChild(template.cloneNode(true));
} }
}; };

View File

@ -90,10 +90,9 @@ while ( i-- ) {
} }
continue; continue;
} }
if ( shadow === null || shadow.className !== sessionId ) { if ( shadow !== null && shadow.className === sessionId && shadow.firstElementChild === null ) {
continue; shadow.appendChild(document.createElement('content'));
} }
shadow.children[0].select = '';
} }
/******************************************************************************/ /******************************************************************************/

View File

@ -90,10 +90,9 @@ while ( i-- ) {
} }
continue; continue;
} }
if ( shadow === null || shadow.className !== sessionId ) { if ( shadow !== null && shadow.className === sessionId && shadow.firstElementChild !== null ) {
continue; shadow.removeChild(shadow.firstElementChild);
} }
shadow.children[0].select = selector;
} }
/******************************************************************************/ /******************************************************************************/

View File

@ -154,6 +154,7 @@ var pickerRoot = null;
var highlightedElementLists = [ [], [], [] ]; var highlightedElementLists = [ [], [], [] ];
var nodeToIdMap = new WeakMap(); // No need to iterate var nodeToIdMap = new WeakMap(); // No need to iterate
var nodeToCosmeticFilterMap = new WeakMap();
var toggledNodes = new Map(); var toggledNodes = new Map();
/******************************************************************************/ /******************************************************************************/
@ -192,31 +193,6 @@ var domLayout = (function() {
return nid; return nid;
}; };
// Collect all nodes which are directly affected by cosmetic filters: these
// will be reported in the layout data.
// TODO: take into account cosmetic filters added after the map is build.
var nodeToCosmeticFilterMap = (function() {
var out = new WeakMap();
var styleTags = vAPI.styles || [];
var i = styleTags.length;
var selectors, styleText, j, selector, nodes, k;
while ( i-- ) {
styleText = styleTags[i].textContent;
selectors = styleText.slice(0, styleText.lastIndexOf('\n')).split(/,\n/);
j = selectors.length;
while ( j-- ) {
selector = selectors[j];
nodes = document.querySelectorAll(selector);
k = nodes.length;
while ( k-- ) {
out.set(nodes[k], selector);
}
}
}
return out;
})();
var selectorFromNode = function(node) { var selectorFromNode = function(node) {
var str, attr, pos, sw, i; var str, attr, pos, sw, i;
var tag = node.localName; var tag = node.localName;
@ -708,6 +684,29 @@ var cosmeticFilterFromTarget = function(nid, coarseSelector) {
/******************************************************************************/ /******************************************************************************/
var cosmeticFilterMapFromStyleTag = function(styleTag) {
var filterMap = nodeToCosmeticFilterMap;
var styleText = styleTag.textContent;
var selectors = styleText.slice(0, styleText.lastIndexOf('\n')).split(/,\n/);
var i = selectors.length;
var selector, nodes, j, node;
while ( i-- ) {
selector = selectors[i];
nodes = document.querySelectorAll(selector);
j = nodes.length;
while ( j-- ) {
node = nodes[j];
filterMap.set(node, selector);
// Not all target nodes have necessarily been force-hidden,
// do it now so that the inspector does not unhide these
// nodes.
hideNode(node);
}
}
};
/******************************************************************************/
var elementsFromSelector = function(selector, context) { var elementsFromSelector = function(selector, context) {
if ( !context ) { if ( !context ) {
context = document; context = document;
@ -772,7 +771,7 @@ var highlightElements = function(scrollTo) {
svgRoot.children[i+1].setAttribute('d', islands.join('') || 'M0 0'); svgRoot.children[i+1].setAttribute('d', islands.join('') || 'M0 0');
} }
svgRoot.children[0].setAttribute('d', ocean.join('')); svgRoot.firstElementChild.setAttribute('d', ocean.join(''));
if ( !scrollTo ) { if ( !scrollTo ) {
return; return;
@ -926,8 +925,8 @@ var showNode = function(node, v1, v2) {
} else { } else {
node.style.setProperty('display', v1, v2); node.style.setProperty('display', v1, v2);
} }
} else if ( shadow !== null && shadow.className === sessionId ) { } else if ( shadow !== null && shadow.className === sessionId && shadow.firstElementChild === null ) {
shadow.children[0].select = ''; shadow.appendChild(document.createElement('content'));
} }
}; };
@ -940,26 +939,35 @@ var hideNode = function(node) {
return; return;
} }
if ( shadow !== null && shadow.className === sessionId ) { if ( shadow !== null && shadow.className === sessionId ) {
shadow.children[0].select = '#' + sessionId; if ( shadow.firstElementChild !== null ) {
shadow.removeChild(shadow.firstElementChild);
}
return; return;
} }
// not all node can be shadowed // not all nodes can be shadowed
try { try {
shadow = node.createShadowRoot(); shadow = node.createShadowRoot();
} catch (ex) { } catch (ex) {
return; return;
} }
shadow.className = sessionId; shadow.className = sessionId;
shadow.appendChild(vAPI.perNodeShadowTemplate.cloneNode(true));
}; };
/******************************************************************************/ /******************************************************************************/
var toggleStylesVisibility = function(state) { var toggleStylesVisibility = function(state) {
var styleTags = vAPI.styles || []; var styleTags = vAPI.styles || [];
var i = styleTags.length, sheet; var styleTag, sheet;
var i = styleTags.length;
while ( i-- ) { while ( i-- ) {
sheet = styleTags[i].sheet; styleTag = styleTags[i];
// Collect all nodes which are directly affected by cosmetic filters: these
// will be reported in the layout data.
// TODO: take into account cosmetic filters added after the map is build.
if ( state === false ) {
cosmeticFilterMapFromStyleTag(styleTag);
}
sheet = styleTag.sheet;
if ( sheet !== null ) { if ( sheet !== null ) {
sheet.disabled = !state; sheet.disabled = !state;
} }