Skip to content

Commit d12ba29

Browse files
authored
Merge pull request #141 from DiamondLightSource/fix-dynamic-script-timeouts
Fix dynamic script timeouts
2 parents 811eba5 + 71aa71a commit d12ba29

File tree

1 file changed

+26
-16
lines changed

1 file changed

+26
-16
lines changed

src/ui/widgets/EmbeddedDisplay/scripts/scriptExecutor.ts

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import log from "loglevel";
22
import { v4 as uuidv4 } from "uuid";
33

44
let iFrameSandboxScriptRunner: HTMLIFrameElement | null = null;
5+
let iFrameSandboxReady = false;
56

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

91-
// This adds an event listen to recieve the IFRAME_READY message, that is sent by the iFrame when it is ready to run scripts.
92+
// This adds an event listen to receive the IFRAME_READY message, that is sent by the iFrame when it is ready to run scripts.
9293
const onMessage = (event: MessageEvent) => {
93-
if (event.data === "IFRAME_READY") {
94-
log.debug(
95-
`The script runner iframe has started the following messeage was recievd: ${event.data}`
96-
);
94+
if (
95+
event.data === "IFRAME_READY" &&
96+
event.source === iFrameSandboxScriptRunner?.contentWindow
97+
) {
98+
log.debug("The script runner iframe has started");
99+
iFrameSandboxReady = true;
97100
window.removeEventListener("message", onMessage);
98101
resolve(iFrameSandboxScriptRunner as HTMLIFrameElement);
99102
}
100103
};
101104

102105
window.addEventListener("message", onMessage);
103106

104-
iFrameSandboxScriptRunner.onload = () => {
105-
if (!iFrameSandboxScriptRunner) {
106-
return;
107-
}
108-
iFrameSandboxScriptRunner.srcdoc = iFrameScriptExecutionHandlerCode;
109-
};
110-
111-
document.body.appendChild(iFrameSandboxScriptRunner);
112-
113107
setTimeout(() => {
114108
window.removeEventListener("message", onMessage);
115109
reject(new Error("The creation of a script execution iframe timed out"));
116110
}, 1000);
111+
112+
iFrameSandboxScriptRunner.srcdoc = iFrameScriptExecutionHandlerCode;
113+
114+
document.body.appendChild(iFrameSandboxScriptRunner);
117115
});
118116
};
119117

@@ -133,14 +131,26 @@ export const executeDynamicScriptInSandbox = async (
133131
await buildSandboxIframe();
134132
}
135133

134+
if (!iFrameSandboxReady) {
135+
// The iFrame sandbox is still starting up, this can happen on app startup.
136+
// We don't want to block, so log and return an empty response.
137+
log.warn(
138+
"The Iframe sandbox is starting up, dynamic script execution skipped on this occasion."
139+
);
140+
return {
141+
functionReturnValue: "",
142+
widgetProps: {}
143+
};
144+
}
145+
136146
if (!iFrameSandboxScriptRunner?.contentWindow) {
137147
throw new Error("Iframe content window not available");
138148
}
139149

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

143-
// Define a message handler to recieve the responses from the IFrame.
153+
// Define a message handler to receive the responses from the IFrame.
144154
const messageHandler = (event: MessageEvent) => {
145155
if (
146156
event.data?.id === id &&
@@ -149,7 +159,7 @@ export const executeDynamicScriptInSandbox = async (
149159
) {
150160
window.removeEventListener("message", messageHandler);
151161
if (!event.data?.error) {
152-
// Sucess return the response data.
162+
// Success return the response data.
153163
resolve({
154164
functionReturnValue: event.data?.functionReturnValue,
155165
widgetProps: event.data?.widgetProps

0 commit comments

Comments
 (0)