Last active
October 5, 2020 07:12
-
-
Save disco0/6bb36689412f8fcd064d1537de106fdc to your computer and use it in GitHub Desktop.
Browser Extension window.onload workaround
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(() => { | |
let subscribers, observer; | |
// natively declared <script> elements in html can't have onload= attribute | |
// due to the default extension CSP that forbids inline code (and we don't want to relax it), | |
// so we're using MutationObserver to add onload event listener to the script element to be loaded | |
window.onDOMscriptReady = (srcSuffix, timeout = 1000) => | |
{ | |
if (!subscribers) | |
{ | |
subscribers = new Map(); | |
observer = new MutationObserver(observe); | |
observer.observe(document.head, { childList: true }); | |
} | |
return new Promise((resolve, reject) => | |
{ | |
const listeners = subscribers.get(srcSuffix); | |
if (listeners) | |
listeners.push(resolve); | |
else | |
subscribers.set(srcSuffix, [resolve]); | |
// a resolved Promise won't reject anymore | |
setTimeout(() => { | |
emptyAfterCleanup(srcSuffix); | |
reject(new Error('Timeout')); | |
}, timeout); | |
}); | |
}; | |
return; | |
function observe(mutations) { | |
for (const { addedNodes } of mutations) { | |
for (const n of addedNodes) { | |
if (n.src && getSubscribersForSrc(n.src)) { | |
n.addEventListener('load', notifySubscribers); | |
} | |
} | |
} | |
} | |
function getSubscribersForSrc(src) { | |
for (const [suffix, listeners] of subscribers.entries()) { | |
if (src.endsWith(suffix)) { | |
return { suffix, listeners }; | |
} | |
} | |
} | |
function notifySubscribers(event) { | |
this.removeEventListener('load', notifySubscribers); | |
for (let data; (data = getSubscribersForSrc(this.src));) { | |
data.listeners.forEach(fn => fn(event)); | |
if (emptyAfterCleanup(data.suffix)) { | |
return; | |
} | |
} | |
} | |
function emptyAfterCleanup(suffix) { | |
if (!subscribers) { | |
return true; | |
} | |
subscribers.delete(suffix); | |
if (!subscribers.size) { | |
observer.disconnect(); | |
observer = null; | |
subscribers = null; | |
return true; | |
} | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment