more context stuff

pull/2179/head
Richard Harris 7 years ago
parent 8c9cc8bf2a
commit 53653c1c7c

@ -5,14 +5,10 @@
import { decode } from 'sourcemap-codec'; import { decode } from 'sourcemap-codec';
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
const { values, navigate } = getContext('REPL'); const { bundle, values, navigate } = getContext('REPL');
export let bundle;
export let dom;
export let ssr;
export let props; export let props;
export let sourceError; export let error; // TODO should this be exposed as a prop?
export let error;
export function setProp(prop, value) { export function setProp(prop, value) {
if (!replProxy) return; if (!replProxy) return;
@ -21,13 +17,12 @@
let hasComponent = false; let hasComponent = false;
const refs = {}; let iframe;
let pendingImports = 0; let pendingImports = 0;
let pending = false; let pending = false;
let replProxy = null; let replProxy = null;
const namespaceSpecifier = /\*\s+as\s+(\w+)/; const namespaceSpecifier = /\*\s+as\s+(\w+)/;
const namedSpecifiers = /\{(.+)\}/; const namedSpecifiers = /\{(.+)\}/;
@ -73,10 +68,9 @@
} }
}); });
onMount(() => { onMount(() => {
replProxy = new ReplProxy(refs.child); replProxy = new ReplProxy(iframe);
refs.child.addEventListener('load', () => {
iframe.addEventListener('load', () => {
replProxy.onPropUpdate = (prop, value) => { replProxy.onPropUpdate = (prop, value) => {
dispatch('binding', { prop, value }); dispatch('binding', { prop, value });
values.update(values => Object.assign({}, values, { values.update(values => Object.assign({}, values, {
@ -96,7 +90,7 @@
let toDestroy = null; let toDestroy = null;
const init = () => { const init = () => {
if (sourceError) return; if ($bundle.error) return;
const removeStyles = () => { const removeStyles = () => {
replProxy.eval(` replProxy.eval(`
@ -121,7 +115,7 @@
toDestroy = null; toDestroy = null;
} }
if (ssr) { // this only gets generated if component uses lifecycle hooks if ($bundle.ssr) { // this only gets generated if component uses lifecycle hooks
pending = true; pending = true;
createHtml(); createHtml();
} else { } else {
@ -131,7 +125,7 @@
} }
const createHtml = () => { const createHtml = () => {
replProxy.eval(`${ssr.code} replProxy.eval(`${$bundle.ssr.code}
var rendered = SvelteComponent.render(${JSON.stringify($values)}); var rendered = SvelteComponent.render(${JSON.stringify($values)});
if (rendered.css.code) { if (rendered.css.code) {
@ -144,7 +138,7 @@
document.body.innerHTML = rendered.html; document.body.innerHTML = rendered.html;
`) `)
.catch( e => { .catch( e => {
const loc = getLocationFromStack(e.stack, ssr.map); const loc = getLocationFromStack(e.stack, $bundle.ssr.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 };
@ -156,9 +150,9 @@
const createComponent = () => { const createComponent = () => {
// remove leftover styles from SSR renderer // remove leftover styles from SSR renderer
if (ssr) removeStyles(); if ($bundle.ssr) removeStyles();
replProxy.eval(`${dom.code} replProxy.eval(`${$bundle.dom.code}
if (window.component) { if (window.component) {
try { try {
window.component.$destroy(); window.component.$destroy();
@ -183,7 +177,7 @@
// TODO show in UI // TODO show in UI
hasComponent = false; hasComponent = false;
const loc = getLocationFromStack(e.stack, 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 };
@ -196,7 +190,7 @@
// Download the imports (sets them on iframe window when complete) // Download the imports (sets them on iframe window when complete)
{ {
let cancelled = false; let cancelled = false;
promise = replProxy.fetchImports(bundle); promise = replProxy.fetchImports($bundle.imports, $bundle.import_map);
promise.cancel = () => { cancelled = true }; promise.cancel = () => { cancelled = true };
promise.then(() => { promise.then(() => {
if (cancelled) return; if (cancelled) return;
@ -219,8 +213,8 @@
}; };
} }
bundle_handler = bundle => { bundle_handler = $bundle => {
if (!bundle) return; // TODO can this ever happen? if (!$bundle) return; // TODO can this ever happen?
if (promise) promise.cancel(); if (promise) promise.cancel();
toDestroy = hasComponent; toDestroy = hasComponent;
@ -228,8 +222,6 @@
init(); init();
}; };
}); });
}); });
@ -238,7 +230,7 @@
let bundle_handler = noop; let bundle_handler = noop;
let props_handler = noop; let props_handler = noop;
$: bundle_handler(bundle); $: bundle_handler($bundle);
$: props_handler(props); $: props_handler(props);
</script> </script>
@ -292,7 +284,7 @@
</style> </style>
<div class="iframe-container"> <div class="iframe-container">
<iframe title="Result" bind:this={refs.child} 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 || pendingImports ? 'greyed-out' : ''}" srcdoc='
<!doctype html> <!doctype html>
<html> <html>
<head> <head>

@ -6,16 +6,11 @@
import PropEditor from './PropEditor.svelte'; import PropEditor from './PropEditor.svelte';
import CodeMirror from '../CodeMirror.svelte'; import CodeMirror from '../CodeMirror.svelte';
const { values } = getContext('REPL'); const { bundle, values } = getContext('REPL');
export let bundle;
export let js; export let js;
export let css; export let css;
export let dom;
export let ssr;
export let props; export let props;
export let json5;
export let sourceError;
export let sourceErrorLoc; export let sourceErrorLoc;
export let runtimeError; export let runtimeError;
export let compile_options; export let compile_options;
@ -121,14 +116,10 @@
{#if view === 'result'} {#if view === 'result'}
<SplitPane type="vertical" pos={67} fixed={!show_props} fixed_pos={100}> <SplitPane type="vertical" pos={67} fixed={!show_props} fixed_pos={100}>
<div slot="a"> <div slot="a">
{#if bundle} {#if $bundle}
<Viewer <Viewer
bind:this={viewer} bind:this={viewer}
{bundle}
{dom}
{ssr}
{props} {props}
{sourceError}
bind:error={runtimeError} bind:error={runtimeError}
on:binding="{e => setPropFromViewer(e.detail.prop, e.detail.value)}" on:binding="{e => setPropFromViewer(e.detail.prop, e.detail.value)}"
/> />

@ -83,7 +83,7 @@ export default class ReplProxy {
return this.iframeCommand("catch_clicks", {}); return this.iframeCommand("catch_clicks", {});
} }
fetchImports(bundle) { fetchImports(imports, import_map) {
return this.iframeCommand("fetch_imports", { bundle }) return this.iframeCommand("fetch_imports", { imports, import_map })
} }
} }

@ -23,20 +23,26 @@
version; // workaround version; // workaround
return { return {
imports: bundle && bundle.imports || [], imports,
components: $components, components: $components,
values: $values values: $values
}; };
} }
export function update(app) {
// TODO
}
const components = writable([]); const components = writable([]);
const values = writable({}); const values = writable({});
const selected = writable(null); const selected = writable(null);
const bundle = writable(null);
setContext('REPL', { setContext('REPL', {
components, components,
values, values,
selected, selected,
bundle,
navigate: item => { navigate: item => {
const match = /^(.+)\.(\w+)$/.exec(item.filename); const match = /^(.+)\.(\w+)$/.exec(item.filename);
@ -78,7 +84,8 @@
let workers; let workers;
let bundle = null; let imports = null;
let import_map = null;
let dom; let dom;
let ssr; let ssr;
let sourceError = null; let sourceError = null;
@ -119,7 +126,8 @@
workers.bundler.postMessage({ type: 'init', version }); workers.bundler.postMessage({ type: 'init', version });
workers.bundler.onmessage = event => { workers.bundler.onmessage = event => {
({ bundle, dom, ssr, warnings, error: sourceError } = event.data); bundle.set(event.data);
({ imports, import_map, dom, ssr, warnings, error: sourceError } = event.data);
if (sourceError) console.error(sourceError); if (sourceError) console.error(sourceError);
runtimeError = null; runtimeError = null;
}; };
@ -284,11 +292,7 @@
{version} {version}
{js} {js}
{css} {css}
{bundle}
{ssr}
{dom}
{props} {props}
{sourceError}
{runtimeError} {runtimeError}
{embedded} {embedded}
{show_props} {show_props}

@ -14,8 +14,8 @@ function fetchImport(id) {
}); });
} }
function fetchImports(bundle, progressFunc) { function fetchImports(imports, progressFunc) {
const missingImports = bundle.imports.filter(x => !importCache[x]); const missingImports = imports.filter(x => !importCache[x]);
let pendingImports = missingImports.length; let pendingImports = missingImports.length;
if (missingImports.length) { if (missingImports.length) {
@ -124,14 +124,14 @@ function handleMessage(ev) {
if (action == "fetch_imports") { if (action == "fetch_imports") {
let { bundle } = ev.data.args; let { imports, import_map } = ev.data.args;
fetchImports(bundle, (remaining) => { fetchImports(imports, (remaining) => {
sendMessage({action: "fetch_progress", args: { remaining }}); sendMessage({action: "fetch_progress", args: { remaining }});
}) })
.then(() => { .then(() => {
bundle.imports.forEach(x=> { imports.forEach(x=> {
const module = importCache[x]; const module = importCache[x];
const name = bundle.importMap.get(x); const name = import_map.get(x);
window[name] = module; window[name] = module;
}); });
sendOk(); sendOk();

@ -147,6 +147,7 @@ async function bundle(components) {
lookup[path] = component; lookup[path] = component;
}); });
const import_map = new Map();
let dom; let dom;
let error; let error;
@ -164,14 +165,13 @@ async function bundle(components) {
cached.dom = dom.cache; cached.dom = dom.cache;
let uid = 1; let uid = 1;
const importMap = new Map();
const domResult = await dom.bundle.generate({ const dom_result = await dom.bundle.generate({
format: 'iife', format: 'iife',
name: 'SvelteComponent', name: 'SvelteComponent',
globals: id => { globals: id => {
const name = `import_${uid++}`; const name = `import_${uid++}`;
importMap.set(id, name); import_map.set(id, name);
return name; return name;
}, },
sourcemap: true sourcemap: true
@ -192,22 +192,20 @@ async function bundle(components) {
if (token !== currentToken) return; if (token !== currentToken) return;
const ssrResult = ssr const ssr_result = ssr
? await ssr.bundle.generate({ ? await ssr.bundle.generate({
format: 'iife', format: 'iife',
name: 'SvelteComponent', name: 'SvelteComponent',
globals: id => importMap.get(id), globals: id => import_map.get(id),
sourcemap: true sourcemap: true
}) })
: null; : null;
return { return {
bundle: {
imports: dom.bundle.imports, imports: dom.bundle.imports,
importMap import_map,
}, dom: dom_result,
dom: domResult, ssr: ssr_result,
ssr: ssrResult,
warnings: dom.warnings, warnings: dom.warnings,
error: null error: null
}; };
@ -216,7 +214,8 @@ async function bundle(components) {
delete e.toString; delete e.toString;
return { return {
bundle: null, imports: [],
import_map,
dom: null, dom: null,
ssr: null, ssr: null,
warnings: dom.warnings, warnings: dom.warnings,

Loading…
Cancel
Save