pull/2179/head
Richard Harris 7 years ago
parent e5ec5acd89
commit c3d9647fb0

@ -3,143 +3,143 @@
const importCache = {}; const importCache = {};
function fetchImport(id) { function fetchImport(id) {
return new Promise((fulfil, reject) => { return new Promise((fulfil, reject) => {
curl([`https://bundle.run/${id}`]).then(module => { curl([`https://bundle.run/${id}`]).then(module => {
importCache[id] = module; importCache[id] = module;
fulfil(module); fulfil(module);
}, err => { }, err => {
console.error(err.stack); console.error(err.stack);
reject(new Error(`Error loading ${id} from bundle.run`)); reject(new Error(`Error loading ${id} from bundle.run`));
}); });
}); });
} }
function fetchImports(bundle, progressFunc) { function fetchImports(bundle, progressFunc) {
const missingImports = bundle.imports.filter(x => !importCache[x]); const missingImports = bundle.imports.filter(x => !importCache[x]);
let pendingImports = missingImports.length; let pendingImports = missingImports.length;
if (missingImports.length) { if (missingImports.length) {
let promise = Promise.all( let promise = Promise.all(
missingImports.map(id => fetchImport(id).then(() => { missingImports.map(id => fetchImport(id).then(() => {
pendingImports -= 1; pendingImports -= 1;
if (progressFunc) progressFunc(pendingImports); if (progressFunc) progressFunc(pendingImports);
})) }))
); );
return promise return promise
} else { } else {
return Promise.resolve(); return Promise.resolve();
} }
} }
function handleMessage(ev) { function handleMessage(ev) {
let { action, cmdId } = ev.data; let { action, cmdId } = ev.data;
const sendMessage = (payload) => parent.postMessage( { ...payload }, ev.origin); const sendMessage = (payload) => parent.postMessage( { ...payload }, ev.origin);
const sendReply = (payload) => sendMessage({ ...payload, cmdId }) const sendReply = (payload) => sendMessage({ ...payload, cmdId })
const sendOk = () => sendReply({ action: "cmdOk" }); const sendOk = () => sendReply({ action: "cmdOk" });
const sendError = (message, stack) => sendReply({ action: "cmdError", message, stack }) const sendError = (message, stack) => sendReply({ action: "cmdError", message, stack })
if (action == "eval") { if (action == "eval") {
let { script } = ev.data.args; let { script } = ev.data.args;
try { try {
eval(script); eval(script);
sendOk(); sendOk();
} catch (e) { } catch (e) {
sendError(e.message, e.stack); sendError(e.message, e.stack);
} }
} }
if (action == "bind_props") { if (action == "bind_props") {
let { props } = ev.data.args let { props } = ev.data.args
if (!window.component) { if (!window.component) {
// TODO can this happen? // TODO can this happen?
console.warn('no component to bind to'); console.warn('no component to bind to');
sendOk(); sendOk();
return; return;
} }
try { try {
props.forEach(prop => { props.forEach(prop => {
// TODO should there be a public API for binding? // TODO should there be a public API for binding?
// e.g. `component.$watch(prop, handler)`? // e.g. `component.$watch(prop, handler)`?
// (answer: probably) // (answer: probably)
window.component.$$.bound[prop] = value => { window.component.$$.bound[prop] = value => {
sendMessage({ action:"prop_update", args: { prop, value } }) sendMessage({ action:"prop_update", args: { prop, value } })
}; };
}); });
sendOk(); sendOk();
} catch (e) { } catch (e) {
sendError(e.message, e.stack); sendError(e.message, e.stack);
} }
} }
if (action == "set_prop") { if (action == "set_prop") {
try { try {
if (!window.component) { if (!window.component) {
return; return;
} }
let { prop, value } = ev.data.args; let { prop, value } = ev.data.args;
component[prop] = value; component[prop] = value;
sendOk(); sendOk();
} catch (e) { } catch (e) {
sendError(e.message, e.stack); sendError(e.message, e.stack);
} }
} }
if (action == "catch_clicks") { if (action == "catch_clicks") {
try { try {
let topOrigin = ev.origin; let topOrigin = ev.origin;
document.body.addEventListener('click', event => { document.body.addEventListener('click', event => {
if (event.which !== 1) return; if (event.which !== 1) return;
if (event.metaKey || event.ctrlKey || event.shiftKey) return; if (event.metaKey || event.ctrlKey || event.shiftKey) return;
if (event.defaultPrevented) return; if (event.defaultPrevented) return;
// ensure target is a link // ensure target is a link
let el = event.target; let el = event.target;
while (el && el.nodeName !== 'A') el = el.parentNode; while (el && el.nodeName !== 'A') el = el.parentNode;
if (!el || el.nodeName !== 'A') return; if (!el || el.nodeName !== 'A') return;
if (el.hasAttribute('download') || el.getAttribute('rel') === 'external' || el.target) return; if (el.hasAttribute('download') || el.getAttribute('rel') === 'external' || el.target) return;
event.preventDefault(); event.preventDefault();
if (el.href.startsWith(topOrigin)) { if (el.href.startsWith(topOrigin)) {
const url = new URL(el.href); const url = new URL(el.href);
if (url.hash[0] === '#') { if (url.hash[0] === '#') {
window.location.hash = url.hash; window.location.hash = url.hash;
return; return;
} }
} }
window.open(el.href, '_blank'); window.open(el.href, '_blank');
}); });
sendOk(); sendOk();
} catch(e) { } catch(e) {
sendError(e.message, e.stack); sendError(e.message, e.stack);
} }
} }
if (action == "fetch_imports") { if (action == "fetch_imports") {
let { bundle } = ev.data.args; let { bundle } = ev.data.args;
fetchImports(bundle, (remaining) => { fetchImports(bundle, (remaining) => {
sendMessage({action: "fetch_progress", args: { remaining }}); sendMessage({action: "fetch_progress", args: { remaining }});
}) })
.then(() => { .then(() => {
bundle.imports.forEach(x=> { bundle.imports.forEach(x=> {
const module = importCache[x]; const module = importCache[x];
const name = bundle.importMap.get(x); const name = bundle.importMap.get(x);
window[name] = module; window[name] = module;
}); });
sendOk(); sendOk();
}) })
.catch(e => { .catch(e => {
sendError(e.message, e.stack); sendError(e.message, e.stack);
}) })
} }
} }
window.addEventListener("message", handleMessage, false) window.addEventListener("message", handleMessage, false)

Loading…
Cancel
Save