forked from sveltejs/svelte
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrepl-runner.js
105 lines (90 loc) · 2.66 KB
/
repl-runner.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
(function() {
const import_cache = {};
function fetch_import(id) {
return new Promise((fulfil, reject) => {
curl([`https://bundle.run/${id}`]).then(module => {
import_cache[id] = module;
fulfil(module);
}, err => {
console.error(err.stack);
reject(new Error(`Error loading ${id} from bundle.run`));
});
});
}
function fetch_imports(imports, progress_func) {
const missing_imports = imports.filter(x => !import_cache[x]);
let pending_imports = missing_imports.length;
if (missing_imports.length) {
let promise = Promise.all(
missing_imports.map(id => fetch_import(id).then(() => {
pending_imports -= 1;
if (progress_func) progress_func(pending_imports);
}))
);
return promise;
} else {
return Promise.resolve();
}
}
function handle_message(ev) {
let { action, cmd_id } = ev.data;
const send_message = (payload) => parent.postMessage( { ...payload }, ev.origin);
const send_reply = (payload) => send_message({ ...payload, cmd_id });
const send_ok = () => send_reply({ action: 'cmd_ok' });
const send_error = (message, stack) => send_reply({ action: 'cmd_error', message, stack });
if (action === 'eval') {
try {
const { script } = ev.data.args;
eval(script);
send_ok();
} catch (e) {
send_error(e.message, e.stack);
}
}
if (action === 'catch_clicks') {
try {
const top_origin = ev.origin;
document.body.addEventListener('click', event => {
if (event.which !== 1) return;
if (event.metaKey || event.ctrlKey || event.shiftKey) return;
if (event.defaultPrevented) return;
// ensure target is a link
let el = event.target;
while (el && el.nodeName !== 'A') el = el.parentNode;
if (!el || el.nodeName !== 'A') return;
if (el.hasAttribute('download') || el.getAttribute('rel') === 'external' || el.target) return;
event.preventDefault();
if (el.href.startsWith(top_origin)) {
const url = new URL(el.href);
if (url.hash[0] === '#') {
window.location.hash = url.hash;
return;
}
}
window.open(el.href, '_blank');
});
send_ok();
} catch(e) {
send_error(e.message, e.stack);
}
}
if (action === 'fetch_imports') {
const { imports, import_map } = ev.data.args;
fetch_imports(imports, (remaining) => {
send_message({action: 'fetch_progress', args: { remaining }});
})
.then(() => {
imports.forEach(x=> {
const module = import_cache[x];
const name = import_map.get(x);
window[name] = module;
});
send_ok();
})
.catch(e => {
send_error(e.message, e.stack);
});
}
}
window.addEventListener('message', handle_message, false);
})();