simplify viewer

pull/2179/head
Richard Harris 7 years ago
parent 68bc5ee8b5
commit 9c22f6a5bf

@ -12,107 +12,61 @@
export let error; // TODO should this be exposed as a prop? export let error; // TODO should this be exposed as a prop?
export function setProp(prop, value) { export function setProp(prop, value) {
if (!replProxy) return; if (!proxy) return;
replProxy.setProp(prop, value); proxy.setProp(prop, value);
} }
let hasComponent = false;
let iframe; let iframe;
let pendingImports = 0; let pending_imports = 0;
let pending = false; let pending = false;
let replProxy = null; let proxy = null;
let createComponent; let ready = false;
let init;
onMount(() => { onMount(() => {
replProxy = new ReplProxy(iframe); proxy = new ReplProxy(iframe, {
onPropUpdate: (prop, value) => {
iframe.addEventListener('load', () => {
replProxy.onPropUpdate = (prop, value) => {
dispatch('binding', { prop, value }); dispatch('binding', { prop, value });
values.update(values => Object.assign({}, values, { values.update(values => Object.assign({}, values, {
[prop]: value [prop]: value
})); }));
}; },
replProxy.onFetchProgress = (progress) => { onFetchProgress: progress => {
pendingImports = progress pending_imports = progress;
} }
});
replProxy.handleLinks(); iframe.addEventListener('load', () => {
proxy.handleLinks();
ready = true;
});
let promise = null; return () => {
let updating = false; proxy.eval(`if (window.component) window.component.\$destroy();`)
proxy.destroy();
}
});
let current_token;
let toDestroy = null; async function apply_bundle($bundle) {
if (!$bundle || $bundle.error) return;
const init = () => { const token = current_token = {};
if ($bundle.error) return;
try {
await proxy.fetchImports($bundle.imports, $bundle.import_map);
if (token !== current_token) return;
const removeStyles = () => { await proxy.eval(`
replProxy.eval(`
const styles = document.querySelectorAll('style.svelte'); const styles = document.querySelectorAll('style.svelte');
let i = styles.length; let i = styles.length;
while (i--) styles[i].parentNode.removeChild(styles[i]); while (i--) styles[i].parentNode.removeChild(styles[i]);
`) `)
};
const destroyComponent = () => { await proxy.eval(`${$bundle.dom.code}
replProxy.eval(`if (window.component)
window.component.\$destroy();
window.component = null`);
};
const ready = () => {
error = null;
if (toDestroy) {
removeStyles();
destroyComponent();
toDestroy = null;
}
if ($bundle.ssr) { // this only gets generated if component uses lifecycle hooks
pending = true;
createHtml();
} else {
pending = false;
createComponent();
}
}
const createHtml = () => {
replProxy.eval(`${$bundle.ssr.code}
var rendered = SvelteComponent.render(${JSON.stringify($values)});
if (rendered.css.code) {
var style = document.createElement('style');
style.className = 'svelte';
style.textContent = rendered.css.code;
document.head.appendChild(style);
}
document.body.innerHTML = rendered.html;
`)
.catch( e => {
const loc = getLocationFromStack(e.stack, $bundle.ssr.map);
if (loc) {
e.filename = loc.source;
e.start = { line: loc.line, column: loc.column };
}
error = e;
});
};
const createComponent = () => {
// remove leftover styles from SSR renderer
if ($bundle.ssr) removeStyles();
replProxy.eval(`${$bundle.dom.code}
if (window.component) { if (window.component) {
try { try {
window.component.$destroy(); window.component.$destroy();
@ -129,71 +83,23 @@
target: document.body, target: document.body,
props: ${JSON.stringify($values)} props: ${JSON.stringify($values)}
}); });
`) `);
.then(()=> {
replProxy.bindProps(props);
})
.catch(e => {
// TODO show in UI
hasComponent = false;
await proxy.bindProps(props);
} catch (e) {
const loc = getLocationFromStack(e.stack, $bundle.dom.map); const loc = getLocationFromStack(e.stack, $bundle.dom.map);
if (loc) { if (loc) {
e.filename = loc.source; e.filename = loc.source;
e.loc = { line: loc.line, column: loc.column }; e.loc = { line: loc.line, column: loc.column };
} }
error = e; console.error(e);
});
};
// Download the imports (sets them on iframe window when complete)
{
let cancelled = false;
promise = replProxy.fetchImports($bundle.imports, $bundle.import_map);
promise.cancel = () => { cancelled = true };
promise.then(() => {
if (cancelled) return;
ready()
}).catch(e => {
if (cancelled) return;
error = e; error = e;
});
} }
run = () => {
pending = false;
// TODO do we need to clear out SSR HTML?
createComponent();
props_handler = props => {
replProxy.bindProps(props)
};
replProxy.bindProps(props);
};
} }
bundle_handler = $bundle => { $: if (ready) apply_bundle($bundle);
if (!$bundle) return; // TODO can this ever happen?
if (promise) promise.cancel();
toDestroy = hasComponent;
hasComponent = false;
init();
};
});
return () => replProxy.destroy();
});
function noop(){}
let run = noop;
let bundle_handler = noop;
let props_handler = noop;
$: bundle_handler($bundle);
$: props_handler(props);
</script> </script>
<style> <style>
@ -245,7 +151,7 @@
</style> </style>
<div class="iframe-container"> <div class="iframe-container">
<iframe title="Result" bind:this={iframe} sandbox="allow-popups-to-escape-sandbox allow-scripts allow-popups allow-forms allow-pointer-lock allow-top-navigation allow-modals" class="{error || pending || pendingImports ? 'greyed-out' : ''}" srcdoc=' <iframe title="Result" bind:this={iframe} sandbox="allow-popups-to-escape-sandbox allow-scripts allow-popups allow-forms allow-pointer-lock allow-top-navigation allow-modals" class="{error || pending || pending_imports ? 'greyed-out' : ''}" srcdoc='
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
@ -264,8 +170,8 @@
<Message kind="error" details={error}/> <Message kind="error" details={error}/>
{:else if !$bundle} {:else if !$bundle}
<Message kind="info">loading Svelte compiler...</Message> <Message kind="info">loading Svelte compiler...</Message>
{:else if pendingImports} {:else if pending_imports}
<Message kind="info">loading {pendingImports} {pendingImports === 1 ? 'dependency' : 'dependencies'} from <Message kind="info">loading {pending_imports} {pending_imports === 1 ? 'dependency' : 'dependencies'} from
https://bundle.run</Message> https://bundle.run</Message>
{/if} {/if}
</div> </div>

@ -1,10 +1,11 @@
export default class ReplProxy { export default class ReplProxy {
constructor(iframe) { constructor(iframe, handlers) {
this.iframe = iframe; this.iframe = iframe;
this.handlers = handlers;
this.cmdId = 1; this.cmdId = 1;
this.pendingCmds = new Map(); this.pendingCmds = new Map();
this.onPropUpdate = null;
this.onFetchProgress = null;
this.handle_event = (ev) => this.handleReplMessage(ev); this.handle_event = (ev) => this.handleReplMessage(ev);
window.addEventListener("message", this.handle_event, false); window.addEventListener("message", this.handle_event, false);
} }
@ -57,13 +58,11 @@ export default class ReplProxy {
if (action == "prop_update") { if (action == "prop_update") {
let { prop, value } = ev.data.args; let { prop, value } = ev.data.args;
if (this.onPropUpdate) this.handlers.onPropUpdate(prop, value)
this.onPropUpdate(prop, value)
} }
if (action == "fetch_progress") { if (action == "fetch_progress") {
if (this.onFetchProgress) this.handlers.onFetchProgress(ev.data.args.remaining)
this.onFetchProgress(ev.data.args.remaining)
} }
} }

Loading…
Cancel
Save