Don't assume `document.documentElement` is non-null (#3857)

* Fix uBlockOrigin/uBlock-issues#1756

This PR fixes uBlockOrigin/uBlock-issues#1756.

* fix dom-inspector.js

* more explicit if statements

* these changes should also be safe
This commit is contained in:
Eli Grey 2021-10-14 06:08:08 -07:00 committed by GitHub
parent ebd8ab6037
commit 1285f78e05
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 20 deletions

View File

@ -788,7 +788,7 @@
rmattr(); rmattr();
if ( /\bstay\b/.test(behavior) === false ) { return; } if ( /\bstay\b/.test(behavior) === false ) { return; }
const observer = new MutationObserver(mutationHandler); const observer = new MutationObserver(mutationHandler);
observer.observe(document.documentElement, { observer.observe(document, {
attributes: true, attributes: true,
attributeFilter: tokens, attributeFilter: tokens,
childList: true, childList: true,
@ -847,7 +847,7 @@
rmclass(); rmclass();
if ( /\bstay\b/.test(behavior) === false ) { return; } if ( /\bstay\b/.test(behavior) === false ) { return; }
const observer = new MutationObserver(mutationHandler); const observer = new MutationObserver(mutationHandler);
observer.observe(document.documentElement, { observer.observe(document, {
attributes: true, attributes: true,
attributeFilter: [ 'class' ], attributeFilter: [ 'class' ],
childList: true, childList: true,
@ -1555,7 +1555,7 @@
asyncTimer = window.requestAnimationFrame(cleanVideo); asyncTimer = window.requestAnimationFrame(cleanVideo);
}; };
var observer = new MutationObserver(cleanVideoAsync); var observer = new MutationObserver(cleanVideoAsync);
observer.observe(document.documentElement, { childList: true, subtree: true }); observer.observe(document, { childList: true, subtree: true });
})(); })();

View File

@ -393,7 +393,7 @@ vAPI.SafeAnimationFrame = class {
const startMutationObserver = function() { const startMutationObserver = function() {
if ( domLayoutObserver !== undefined ) { return; } if ( domLayoutObserver !== undefined ) { return; }
domLayoutObserver = new MutationObserver(observerHandler); domLayoutObserver = new MutationObserver(observerHandler);
domLayoutObserver.observe(document.documentElement, { domLayoutObserver.observe(document, {
//attributeFilter: [ 'class', 'id' ], //attributeFilter: [ 'class', 'id' ],
//attributes: true, //attributes: true,
childList: true, childList: true,
@ -469,7 +469,7 @@ vAPI.injectScriptlet = function(doc, text) {
try { try {
script = doc.createElement('script'); script = doc.createElement('script');
script.appendChild(doc.createTextNode(text)); script.appendChild(doc.createTextNode(text));
(doc.head || doc.documentElement).appendChild(script); (doc.head || doc.documentElement || doc).appendChild(script);
} catch (ex) { } catch (ex) {
} }
if ( script ) { if ( script ) {
@ -1171,10 +1171,14 @@ vAPI.DOMFilterer = class {
// Look-up safe-only selectors to mitigate probability of // Look-up safe-only selectors to mitigate probability of
// html/body elements of erroneously being targeted. // html/body elements of erroneously being targeted.
const ids = [], classes = []; const ids = [], classes = [];
if (document.documentElement !== null) {
idFromNode(document.documentElement, ids); idFromNode(document.documentElement, ids);
idFromNode(document.body, ids);
classesFromNode(document.documentElement, classes); classesFromNode(document.documentElement, classes);
}
if (document.body !== null) {
idFromNode(document.body, ids);
classesFromNode(document.body, classes); classesFromNode(document.body, classes);
}
if ( ids.length !== 0 || classes.length !== 0 ) { if ( ids.length !== 0 || classes.length !== 0 ) {
messaging.send('contentscript', { messaging.send('contentscript', {
what: 'retrieveGenericCosmeticSelectors', what: 'retrieveGenericCosmeticSelectors',

View File

@ -247,7 +247,7 @@ const domLayout = (function() {
const getLayoutData = function() { const getLayoutData = function() {
var layout = []; var layout = [];
var stack = []; var stack = [];
var node = document.documentElement; var node = document;
var domNode; var domNode;
var lvl = 0; var lvl = 0;
@ -264,6 +264,7 @@ const domLayout = (function() {
continue; continue;
} }
// sibling // sibling
if (node instanceof Element) {
if ( node.nextElementSibling === null ) { if ( node.nextElementSibling === null ) {
do { do {
node = stack.pop(); node = stack.pop();
@ -274,6 +275,7 @@ const domLayout = (function() {
} }
node = node.nextElementSibling; node = node.nextElementSibling;
} }
}
return layout; return layout;
}; };
@ -547,7 +549,9 @@ const cosmeticFilterMapper = (function() {
const reset = function() { const reset = function() {
roRedNodes.clear(); roRedNodes.clear();
if (document.documentElement !== null) {
incremental(document.documentElement); incremental(document.documentElement);
}
}; };
const shutdown = function() { const shutdown = function() {
@ -812,7 +816,7 @@ const shutdown = function() {
domLayout.shutdown(); domLayout.shutdown();
vAPI.MessagingConnection.disconnectFrom(loggerConnectionId); vAPI.MessagingConnection.disconnectFrom(loggerConnectionId);
window.removeEventListener('scroll', onScrolled, true); window.removeEventListener('scroll', onScrolled, true);
document.documentElement.removeChild(pickerRoot); pickerRoot.remove();
pickerRoot = svgRoot = null; pickerRoot = svgRoot = null;
}; };
@ -977,7 +981,7 @@ pickerRoot.style.cssText = [
].join(' !important;\n'); ].join(' !important;\n');
pickerRoot.addEventListener('load', ev => { bootstrap(ev); }); pickerRoot.addEventListener('load', ev => { bootstrap(ev); });
document.documentElement.appendChild(pickerRoot); (document.documentElement || document).appendChild(pickerRoot);
/******************************************************************************/ /******************************************************************************/