protect own style elements (100 times max to avoid deadlocks)
fixes #252
This commit is contained in:
parent
5d905c2952
commit
8a1908b760
|
@ -224,8 +224,12 @@ function applyStyles(styles) {
|
||||||
for (const id in styles) {
|
for (const id in styles) {
|
||||||
applySections(id, styles[id].map(section => section.code).join('\n'));
|
applySections(id, styles[id].map(section => section.code).join('\n'));
|
||||||
}
|
}
|
||||||
initDocRewriteObserver();
|
if (!isOwnPage && !docRewriteObserver && styleElements.size) {
|
||||||
initDocRootObserver();
|
initDocRewriteObserver();
|
||||||
|
}
|
||||||
|
if (!docRootObserver && styleElements.size) {
|
||||||
|
initDocRootObserver();
|
||||||
|
}
|
||||||
if (retiredStyleTimers.size) {
|
if (retiredStyleTimers.size) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
for (const [id, timer] of retiredStyleTimers.entries()) {
|
for (const [id, timer] of retiredStyleTimers.entries()) {
|
||||||
|
@ -290,9 +294,6 @@ function replaceAll(newStyles) {
|
||||||
|
|
||||||
|
|
||||||
function initDocRewriteObserver() {
|
function initDocRewriteObserver() {
|
||||||
if (isOwnPage || docRewriteObserver || !styleElements.size) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// re-add styles if we detect documentElement being recreated
|
// re-add styles if we detect documentElement being recreated
|
||||||
const reinjectStyles = () => {
|
const reinjectStyles = () => {
|
||||||
if (!styleElements) {
|
if (!styleElements) {
|
||||||
|
@ -327,36 +328,57 @@ function initDocRewriteObserver() {
|
||||||
|
|
||||||
|
|
||||||
function initDocRootObserver() {
|
function initDocRootObserver() {
|
||||||
if (!styleElements.size || document.body || docRootObserver) {
|
let lastRestorationTime = 0;
|
||||||
return;
|
let restorationCounter = 0;
|
||||||
|
|
||||||
|
docRootObserver = new MutationObserver(findMisplacedStyles);
|
||||||
|
connectObserver();
|
||||||
|
|
||||||
|
function connectObserver() {
|
||||||
|
docRootObserver.observe(ROOT, {childList: true});
|
||||||
}
|
}
|
||||||
// wait for BODY and move all style elements after it
|
|
||||||
docRootObserver = new MutationObserver(() => {
|
function findMisplacedStyles() {
|
||||||
let expectedPrevSibling = document.body || document.head;
|
let expectedPrevSibling = document.body || document.head;
|
||||||
if (!expectedPrevSibling) {
|
if (!expectedPrevSibling) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
docRootObserver.disconnect();
|
const list = [];
|
||||||
for (const el of styleElements.values()) {
|
for (const el of styleElements.values()) {
|
||||||
if (el.previousElementSibling !== expectedPrevSibling) {
|
if (el.previousElementSibling !== expectedPrevSibling) {
|
||||||
ROOT.insertBefore(el, expectedPrevSibling.nextSibling);
|
list.push({el, before: expectedPrevSibling.nextSibling});
|
||||||
if (el.disabled !== disableAll) {
|
|
||||||
// moving an element resets its 'disabled' state
|
|
||||||
el.disabled = disableAll;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
expectedPrevSibling = el;
|
expectedPrevSibling = el;
|
||||||
}
|
}
|
||||||
if (document.body) {
|
if (list.length && !restorationLimitExceeded()) {
|
||||||
docRootObserver = null;
|
restoreMisplacedStyles(list);
|
||||||
} else {
|
|
||||||
docRootObserver.connect();
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
docRootObserver.connect = () => {
|
|
||||||
docRootObserver.observe(ROOT, {childList: true});
|
function restoreMisplacedStyles(list) {
|
||||||
};
|
docRootObserver.disconnect();
|
||||||
docRootObserver.connect();
|
for (const {el, before} of list) {
|
||||||
|
ROOT.insertBefore(el, before);
|
||||||
|
if (el.disabled !== disableAll) {
|
||||||
|
// moving an element resets its 'disabled' state
|
||||||
|
el.disabled = disableAll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connectObserver();
|
||||||
|
}
|
||||||
|
|
||||||
|
function restorationLimitExceeded() {
|
||||||
|
const t = performance.now();
|
||||||
|
if (t - lastRestorationTime > 1000) {
|
||||||
|
restorationCounter = 0;
|
||||||
|
}
|
||||||
|
lastRestorationTime = t;
|
||||||
|
if (++restorationCounter > 100) {
|
||||||
|
console.error('Stylus stopped restoring userstyle elements after 100 failed attempts.\n' +
|
||||||
|
'Please report on https://github.com/openstyles/stylus/issues');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user