@@ -2,6 +2,7 @@ import log from "loglevel";
22import { v4 as uuidv4 } from "uuid" ;
33
44let iFrameSandboxScriptRunner : HTMLIFrameElement | null = null ;
5+ let iFrameSandboxReady = false ;
56
67export 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