From 9c22f6a5bfc732dae10ca281de87d3225eec891b Mon Sep 17 00:00:00 2001 From: Richard Harris Date: Sat, 2 Mar 2019 18:42:41 -0500 Subject: [PATCH] simplify viewer --- site/src/components/Repl/Output/Viewer.svelte | 218 +++++------------- site/src/components/Repl/Output/replProxy.js | 13 +- 2 files changed, 68 insertions(+), 163 deletions(-) diff --git a/site/src/components/Repl/Output/Viewer.svelte b/site/src/components/Repl/Output/Viewer.svelte index b9b0e60070..ee67222938 100644 --- a/site/src/components/Repl/Output/Viewer.svelte +++ b/site/src/components/Repl/Output/Viewer.svelte @@ -12,188 +12,94 @@ export let error; // TODO should this be exposed as a prop? export function setProp(prop, value) { - if (!replProxy) return; - replProxy.setProp(prop, value); + if (!proxy) return; + proxy.setProp(prop, value); } - let hasComponent = false; - let iframe; - let pendingImports = 0; + let pending_imports = 0; let pending = false; - let replProxy = null; + let proxy = null; - let createComponent; - let init; + let ready = false; onMount(() => { - replProxy = new ReplProxy(iframe); - - iframe.addEventListener('load', () => { - replProxy.onPropUpdate = (prop, value) => { + proxy = new ReplProxy(iframe, { + onPropUpdate: (prop, value) => { dispatch('binding', { prop, value }); values.update(values => Object.assign({}, values, { [prop]: value })); - }; + }, - replProxy.onFetchProgress = (progress) => { - pendingImports = progress + onFetchProgress: progress => { + pending_imports = progress; } + }); - replProxy.handleLinks(); - - let promise = null; - let updating = false; + iframe.addEventListener('load', () => { + proxy.handleLinks(); + ready = true; + }); - let toDestroy = null; + return () => { + proxy.eval(`if (window.component) window.component.\$destroy();`) + proxy.destroy(); + } + }); - const init = () => { - if ($bundle.error) return; + let current_token; - const removeStyles = () => { - replProxy.eval(` - const styles = document.querySelectorAll('style.svelte'); - let i = styles.length; - while (i--) styles[i].parentNode.removeChild(styles[i]); - `) - }; + async function apply_bundle($bundle) { + if (!$bundle || $bundle.error) return; - const destroyComponent = () => { - replProxy.eval(`if (window.component) - window.component.\$destroy(); - window.component = null`); - }; + const token = current_token = {}; - const ready = () => { - error = null; + try { + await proxy.fetchImports($bundle.imports, $bundle.import_map); + if (token !== current_token) return; - if (toDestroy) { - removeStyles(); - destroyComponent(); - toDestroy = null; - } + await proxy.eval(` + const styles = document.querySelectorAll('style.svelte'); + let i = styles.length; + while (i--) styles[i].parentNode.removeChild(styles[i]); + `) - if ($bundle.ssr) { // this only gets generated if component uses lifecycle hooks - pending = true; - createHtml(); - } else { - pending = false; - createComponent(); + await proxy.eval(`${$bundle.dom.code} + if (window.component) { + try { + window.component.$destroy(); + } catch (err) { + console.error(err); } } - 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) { - try { - window.component.$destroy(); - } catch (err) { - console.error(err); - } - } - - document.body.innerHTML = ''; - window.location.hash = ''; - window._svelteTransitionManager = null; - - window.component = new SvelteComponent({ - target: document.body, - props: ${JSON.stringify($values)} - }); - `) - .then(()=> { - replProxy.bindProps(props); - }) - .catch(e => { - // TODO show in UI - hasComponent = false; - - const loc = getLocationFromStack(e.stack, $bundle.dom.map); - if (loc) { - e.filename = loc.source; - e.loc = { line: loc.line, column: loc.column }; - } - - 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; - }); - } - - run = () => { - pending = false; - - // TODO do we need to clear out SSR HTML? - createComponent(); - props_handler = props => { - replProxy.bindProps(props) - }; - replProxy.bindProps(props); - }; + document.body.innerHTML = ''; + window.location.hash = ''; + window._svelteTransitionManager = null; + + window.component = new SvelteComponent({ + target: document.body, + props: ${JSON.stringify($values)} + }); + `); + + await proxy.bindProps(props); + } catch (e) { + const loc = getLocationFromStack(e.stack, $bundle.dom.map); + if (loc) { + e.filename = loc.source; + e.loc = { line: loc.line, column: loc.column }; } - bundle_handler = $bundle => { - if (!$bundle) return; // TODO can this ever happen? - if (promise) promise.cancel(); - - toDestroy = hasComponent; - hasComponent = false; - - init(); - }; - }); + console.error(e); - return () => replProxy.destroy(); - }); - - function noop(){} - let run = noop; - let bundle_handler = noop; - let props_handler = noop; + error = e; + } + } - $: bundle_handler($bundle); - $: props_handler(props); + $: if (ready) apply_bundle($bundle);
-