Source code

Revision control

Copy as Markdown

Other Tools

// Functions available by default in the executor.
'use strict';
let executorStartEvent = null;
function requestExecutor(uuid, startOn) {
if (startOn) {
addEventListener(startOn, (e) => {
executorStartEvent = e;
startExecutor(uuid);
});
} else {
startExecutor(uuid);
}
}
function addScript(url) {
const script = document.createElement('script');
script.src = url;
const promise = new Promise((resolve, reject) => {
script.onload = () => resolve(url);
script.onerror = (e) => reject(e);
});
document.body.appendChild(script);
return promise;
}
/**
* Suspends the executor and executes the function in `fnString` when it has
* suspended. Installs a pageshow handler to resume the executor if the
* document is BFCached. Installs a hashchange handler to detect when the
* navigation did not change documents.
*
* This returns nothing because fn is invoke after waiting for the document to
* be suspended. If we were to return a promise, the executor could not suspend
* until that promise resolved but the promise cannot resolve until the executor
* is suspended. This could be avoided by adding support
* directly in the dispatcher for tasks suspend immediately after execution.
*
* @param {string} fnString A stringified function to be executed.
* @param {any[]} args The arguments to pass to the function.
*/
function executeScriptToNavigate(fnString, args) {
// Only one of these listeners should run.
const controller = new AbortController();
window.addEventListener('pageshow', (event) => {
controller.abort();
executor.resume();
}, {signal: controller.signal, once: true});
window.addEventListener('hashchange', (event) => {
controller.abort();
const oldURLObject = new URL(event.oldURL);
const newURLObject = new URL(event.newURL);
oldURLObject.hash = '';
newURLObject.hash = '';
// If only the hash-fragment changed then the navigation was
// same-document and we should resume the executor.
if (oldURLObject.toString() == newURLObject.toString()) {
executor.resume();
}
}, {signal: controller.signal, once: true});
executor.suspend(() => {
eval(fnString).apply(null, args);
});
}
// If a frameset element exists in the document, return the first one. Otherwise
// create a new one and return that.
function findOrCreateFrameset() {
const framesets = document.getElementsByTagName('frameset');
if (framesets.length > 0) {
return framesets[0];
}
const frameset = document.createElement('frameset');
frameset.cols = '100%';
document.body.append(frameset);
return frameset;
}