Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 26 additions & 16 deletions src/ui/widgets/EmbeddedDisplay/scripts/scriptExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import log from "loglevel";
import { v4 as uuidv4 } from "uuid";

let iFrameSandboxScriptRunner: HTMLIFrameElement | null = null;
let iFrameSandboxReady = false;

export interface ScriptResponse {
functionReturnValue: any;
Expand Down Expand Up @@ -88,32 +89,29 @@ const buildSandboxIframe = async (): Promise<HTMLIFrameElement> => {
iFrameSandboxScriptRunner.style.display = "none";
iFrameSandboxScriptRunner.id = "script-runner-iframe";

// This adds an event listen to recieve the IFRAME_READY message, that is sent by the iFrame when it is ready to run scripts.
// This adds an event listen to receive the IFRAME_READY message, that is sent by the iFrame when it is ready to run scripts.
const onMessage = (event: MessageEvent) => {
if (event.data === "IFRAME_READY") {
log.debug(
`The script runner iframe has started the following messeage was recievd: ${event.data}`
);
if (
event.data === "IFRAME_READY" &&
event.source === iFrameSandboxScriptRunner?.contentWindow
) {
log.debug("The script runner iframe has started");
iFrameSandboxReady = true;
window.removeEventListener("message", onMessage);
resolve(iFrameSandboxScriptRunner as HTMLIFrameElement);
}
};

window.addEventListener("message", onMessage);

iFrameSandboxScriptRunner.onload = () => {
if (!iFrameSandboxScriptRunner) {
return;
}
iFrameSandboxScriptRunner.srcdoc = iFrameScriptExecutionHandlerCode;
};

document.body.appendChild(iFrameSandboxScriptRunner);

setTimeout(() => {
window.removeEventListener("message", onMessage);
reject(new Error("The creation of a script execution iframe timed out"));
}, 1000);

iFrameSandboxScriptRunner.srcdoc = iFrameScriptExecutionHandlerCode;

document.body.appendChild(iFrameSandboxScriptRunner);
});
};

Expand All @@ -133,14 +131,26 @@ export const executeDynamicScriptInSandbox = async (
await buildSandboxIframe();
}

if (!iFrameSandboxReady) {
// The iFrame sandbox is still starting up, this can happen on app startup.
// We don't want to block, so log and return an empty response.
log.warn(
"The Iframe sandbox is starting up, dynamic script execution skipped on this occasion."
);
return {
functionReturnValue: "",
widgetProps: {}
};
}

if (!iFrameSandboxScriptRunner?.contentWindow) {
throw new Error("Iframe content window not available");
}

return new Promise<any>((resolve, reject) => {
const id = uuidv4();

// Define a message handler to recieve the responses from the IFrame.
// Define a message handler to receive the responses from the IFrame.
const messageHandler = (event: MessageEvent) => {
if (
event.data?.id === id &&
Expand All @@ -149,7 +159,7 @@ export const executeDynamicScriptInSandbox = async (
) {
window.removeEventListener("message", messageHandler);
if (!event.data?.error) {
// Sucess return the response data.
// Success return the response data.
resolve({
functionReturnValue: event.data?.functionReturnValue,
widgetProps: event.data?.widgetProps
Expand Down
Loading