onDOMscriptReady: notify all matching subscribers
This commit is contained in:
parent
32d89e58ea
commit
18b20d13be
|
@ -51,21 +51,21 @@ var loadScript = (() => {
|
||||||
// natively declared <script> elements in html can't have onload= attribute
|
// 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),
|
// 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
|
// so we're using MutationObserver to add onload event listener to the script element to be loaded
|
||||||
window.onDOMscriptReady = (src, timeout = 1000) => {
|
window.onDOMscriptReady = (srcSuffix, timeout = 1000) => {
|
||||||
if (!subscribers) {
|
if (!subscribers) {
|
||||||
subscribers = new Map();
|
subscribers = new Map();
|
||||||
observer = new MutationObserver(observe);
|
observer = new MutationObserver(observe);
|
||||||
observer.observe(document.head, {childList: true});
|
observer.observe(document.head, {childList: true});
|
||||||
}
|
}
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const listeners = subscribers.get(src);
|
const listeners = subscribers.get(srcSuffix);
|
||||||
if (listeners) {
|
if (listeners) {
|
||||||
listeners.push(resolve);
|
listeners.push(resolve);
|
||||||
} else {
|
} else {
|
||||||
subscribers.set(src, [resolve]);
|
subscribers.set(srcSuffix, [resolve]);
|
||||||
}
|
}
|
||||||
// no need to clear the timer since a resolved Promise won't reject anymore
|
// a resolved Promise won't reject anymore
|
||||||
setTimeout(reject, timeout);
|
setTimeout(() => emptyAfterCleanup(srcSuffix) + reject(), timeout);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -82,22 +82,33 @@ var loadScript = (() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSubscribersForSrc(src) {
|
function getSubscribersForSrc(src) {
|
||||||
for (const [subscribedSrc, listeners] of subscribers.entries()) {
|
for (const [suffix, listeners] of subscribers.entries()) {
|
||||||
if (src.endsWith(subscribedSrc)) {
|
if (src.endsWith(suffix)) {
|
||||||
return {subscribedSrc, listeners};
|
return {suffix, listeners};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function notifySubscribers(event) {
|
function notifySubscribers(event) {
|
||||||
this.removeEventListener('load', notifySubscribers);
|
this.removeEventListener('load', notifySubscribers);
|
||||||
const {subscribedSrc, listeners = []} = getSubscribersForSrc(this.src) || {};
|
for (let data; (data = getSubscribersForSrc(this.src));) {
|
||||||
listeners.forEach(fn => fn(event));
|
data.listeners.forEach(fn => fn(event));
|
||||||
subscribers.delete(subscribedSrc);
|
if (emptyAfterCleanup(data.suffix)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function emptyAfterCleanup(suffix) {
|
||||||
|
if (!subscribers) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
subscribers.delete(suffix);
|
||||||
if (!subscribers.size) {
|
if (!subscribers.size) {
|
||||||
observer.disconnect();
|
observer.disconnect();
|
||||||
observer = null;
|
observer = null;
|
||||||
subscribers = null;
|
subscribers = null;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user