You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte/site/src/components/Repl/Output/ReplProxy.js

75 lines
1.7 KiB

let uid = 1;
export default class ReplProxy {
constructor(iframe, handlers) {
this.iframe = iframe;
this.handlers = handlers;
this.pending_cmds = new Map();
this.handle_event = e => this.handle_repl_message(e);
window.addEventListener('message', this.handle_event, false);
}
destroy() {
window.removeEventListener('message', this.handle_event);
}
iframe_command(action, args) {
return new Promise((resolve, reject) => {
const cmd_id = uid++;
this.pending_cmds.set(cmd_id, { resolve, reject });
this.iframe.contentWindow.postMessage({ action, cmd_id, args }, '*');
});
}
handle_command_message(cmd_data) {
let action = cmd_data.action;
let id = cmd_data.cmd_id;
let handler = this.pending_cmds.get(id);
if (handler) {
this.pending_cmds.delete(id);
if (action === 'cmd_error') {
let { message, stack } = cmd_data;
let e = new Error(message);
e.stack = stack;
handler.reject(e)
}
if (action === 'cmd_ok') {
handler.resolve(cmd_data.args)
}
} else {
console.error('command not found', id, cmd_data, [...this.pending_cmds.keys()]);
}
}
handle_repl_message(event) {
if (event.source !== this.iframe.contentWindow) return;
const { action, args } = event.data;
if (action === 'cmd_error' || action === 'cmd_ok') {
this.handle_command_message(event.data);
}
if (action === 'fetch_progress') {
this.handlers.on_fetch_progress(args.remaining)
}
}
eval(script) {
return this.iframe_command('eval', { script });
}
handle_links() {
return this.iframe_command('catch_clicks', {});
}
fetch_imports(imports, import_map) {
return this.iframe_command('fetch_imports', { imports, import_map })
}
}