import '@casual-simulation/aux-vm/globalThis-polyfill' ; import { Message } from 'comlink/dist/umd/protocol' ; import { Observable } from 'rxjs' ; param iframeWindow export function setupChannel ( iframeWindow ) { const channel = new MessageChannel ( ) ; iframeWindow . postMessage ( { type : 'init_port' , port : channel . port2 , } , '*' , [ channel . port2 ] ) ; return channel ; } param origin export function listenForChannels ( origin ? ) { return new Observable ( ( observer ) => { let listener = ( msg ) => { if ( msg . data . type === 'init_port' ) { if ( ! origin || msg . origin === origin ) { observer . next ( msg . data . port ) ; } } } ; globalThis . addEventListener ( 'message' , listener ) ; return ( ) => { globalThis . removeEventListener ( 'message' , listener ) ; } ; } ) ; } param origin export function listenForChannel ( origin ? ) { return new Promise < MessagePort > ( ( resolve ) => { let listener = ( msg ) => { if ( msg . data . type === 'init_port' ) { if ( ! origin || msg . origin === origin ) { globalThis . removeEventListener ( 'message' , listener ) ; resolve ( msg . data . port ) ; } } } ; globalThis . addEventListener ( 'message' , listener ) ; } ) ; } export function waitForLoad ( iframe ) { return new Promise < void > ( ( resolve ) => { let listener = ( ) => { iframe . removeEventListener ( 'load' , listener ) ; resolve ( ) ; } ; iframe . addEventListener ( 'load' , listener ) ; } ) ; } param iframeWindow param id param source export function loadScript ( iframeWindow , id , source ) { return new Promise < void > ( ( resolve , reject ) => { const listener = ( message ) => { if ( message . source !== iframeWindow ) { return ; } if ( message . data . type === 'script_loaded' && message . data . id === id ) { globalThis . removeEventListener ( 'message' , listener ) ; resolve ( ) ; } } ; globalThis . addEventListener ( 'message' , listener ) ; iframeWindow . postMessage ( { type : 'load_script' , id , source , } , '*' ) ; } ) ; } param iframeWindow param id param port export function injectPort ( iframeWindow , id , port ) { return new Promise < void > ( ( resolve , reject ) => { const listener = ( message ) => { if ( message . source !== iframeWindow ) { return ; } if ( message . data . type === 'port_injected' && message . data . id === id ) { globalThis . removeEventListener ( 'message' , listener ) ; resolve ( ) ; } } ; globalThis . addEventListener ( 'message' , listener ) ; iframeWindow . postMessage ( { type : 'inject_port' , id , port , } , '*' , [ port ] ) ; } ) ; } param iframeWindow param id param text param element export function loadText ( iframeWindow , id , text , element ) { return new Promise < void > ( ( resolve , reject ) => { const listener = ( message ) => { if ( message . source !== iframeWindow ) { return ; } if ( message . data . type === 'text_loaded' && message . data . id === id ) { globalThis . removeEventListener ( 'message' , listener ) ; resolve ( ) ; } } ; globalThis . addEventListener ( 'message' , listener ) ; iframeWindow . postMessage ( { type : 'load_text' , id , text , element , } , '*' ) ; } ) ; } param iframeWindow export function reload ( iframeWindow ) { const promise = waitForLoad ( iframeWindow ) ; iframeWindow . contentWindow . postMessage ( { type : 'reload' , } , '*' ) ; return promise ; } param options param properties export async function setupCustomIframe ( options , properties ? ) { const origin = options . vmOrigin || location . origin ; const iframeUrl = new URL ( '/aux-vm-iframe.html' , origin ) . href ; const iframe = document . createElement ( 'iframe' ) ; iframe . src = iframeUrl ; iframe . style . display = 'none' ; if ( properties ) { for ( let key in properties ) { ( < any > iframe ) [ key ] = ( < any > properties ) [ key ] ; } } let promise = waitForLoad ( iframe ) ; document . body . insertBefore ( iframe , document . body . firstChild ) ; await promise ; return iframe ; }