Skip to content

Commit 8d81ee9

Browse files
Feat: Refactor for demo.
1 parent 32ba9ef commit 8d81ee9

2 files changed

Lines changed: 93 additions & 74 deletions

File tree

demo/index.html

Lines changed: 12 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
<!DOCTYPE html>
2+
23
<html lang="es">
4+
35
<head>
6+
47
<meta charset="UTF-8">
58
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6-
<title>Edge Python Code Edior</title>
9+
10+
<title>Edge Python Demo</title>
11+
712
<script src="https://cdn.tailwindcss.com"></script>
13+
<script type="module" src="./main.js" defer></script>
14+
815
<link rel="icon" type="image/svg" href="icon.svg">
16+
917
<style>
1018
.no-scrollbar::-webkit-scrollbar { display: none; }
1119
.no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
@@ -15,7 +23,9 @@
1523
line-height: 1.625;
1624
}
1725
</style>
26+
1827
</head>
28+
1929
<body class="bg-[#161616] text-[#ffffff] h-screen flex flex-col p-4 gap-4 overflow-hidden">
2030

2131
<div class="w-full bg-[#222222] border border-[#2d2d2d] rounded-md flex flex-col flex-[70] basis-0 overflow-hidden">
@@ -55,78 +65,6 @@
5565
<div id="term" class="code-font text-sm p-3 text-[#c2c2c2] flex-1 overflow-y-auto no-scrollbar whitespace-pre-wrap"></div>
5666
</div>
5767

58-
<script>
59-
const SZ = 1 << 20;
60-
61-
const ed = document.getElementById('ed');
62-
const ln = document.getElementById('ln');
63-
const btn = document.getElementById('run');
64-
const term = document.getElementById('term');
65-
const status = document.getElementById('status');
66-
67-
let wasm = null;
68-
69-
async function loadWasm() {
70-
try {
71-
status.textContent = 'loading wasm…';
72-
const res = await fetch('./compiler_lib.wasm');
73-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
74-
const { instance } = await WebAssembly.instantiateStreaming(res, {});
75-
wasm = instance.exports;
76-
btn.disabled = false;
77-
status.textContent = 'ready';
78-
status.className = 'ml-auto text-emerald-500';
79-
} catch (e) {
80-
status.textContent = `load failed: ${e.message}`;
81-
status.className = 'ml-auto text-red-500';
82-
}
83-
}
84-
85-
function runCode() {
86-
if (!wasm) return;
87-
const srcBytes = new TextEncoder().encode(ed.value);
88-
if (srcBytes.length > SZ) {
89-
term.textContent = `error: source exceeds ${SZ} bytes`;
90-
return;
91-
}
92-
const mem = new Uint8Array(wasm.memory.buffer);
93-
mem.set(srcBytes, wasm.src_ptr());
94-
const outLen = wasm.run(srcBytes.length);
95-
const outView = new Uint8Array(wasm.memory.buffer, wasm.out_ptr(), outLen);
96-
term.textContent = new TextDecoder().decode(outView);
97-
}
98-
99-
btn.addEventListener('click', runCode);
100-
101-
ed.addEventListener('keydown', (e) => {
102-
if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
103-
e.preventDefault();
104-
runCode();
105-
return;
106-
}
107-
if (e.key === 'Enter' && ed.value.split('\n').length >= 99) {
108-
e.preventDefault();
109-
}
110-
});
111-
112-
const sync = () => {
113-
let lines = ed.value.split('\n');
114-
if (lines.length > 99) {
115-
ed.value = lines.slice(0, 99).join('\n');
116-
lines = ed.value.split('\n');
117-
}
118-
ln.textContent = Array.from({length: lines.length}, (_, i) =>
119-
String(i + 1).padStart(2, '0')
120-
).join('\n');
121-
ln.scrollTop = ed.scrollTop;
122-
};
123-
124-
ed.oninput = sync;
125-
ed.onscroll = sync;
126-
127-
sync();
128-
loadWasm();
129-
</script>
130-
13168
</body>
69+
13270
</html>

demo/main.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
const SZ = 1 << 20;
2+
const WASM_SOURCES = ['./compiler_lib.wasm', 'https://demo.edgepython.com/compiler_lib.wasm'];
3+
const OK = 'ml-auto text-[#7daf7a]';
4+
const ERR = 'ml-auto text-[#d67f6d]';
5+
const MAX_LINES = 99;
6+
7+
const $ = (id) => document.getElementById(id);
8+
const ed = $('ed'), ln = $('ln'), btn = $('run'), term = $('term'), status = $('status');
9+
10+
let wasm = null;
11+
12+
const fmt = (ms) => ms < 1000 ? `${ms.toFixed(0)}ms` : `${(ms / 1000).toFixed(2)}s`;
13+
14+
const instantiate = async (url) => {
15+
const res = await fetch(url);
16+
if (!res.ok) throw new Error(`${url}: HTTP ${res.status}`);
17+
try {
18+
return await WebAssembly.instantiateStreaming(res, {});
19+
} catch {
20+
const bytes = await (await fetch(url)).arrayBuffer();
21+
return WebAssembly.instantiate(bytes, {});
22+
}
23+
};
24+
25+
const loadWasm = async () => {
26+
status.textContent = 'loading wasm…';
27+
const t0 = performance.now();
28+
try {
29+
const { instance } = await Promise.any(WASM_SOURCES.map(instantiate));
30+
wasm = instance.exports;
31+
btn.disabled = false;
32+
status.textContent = `ready (${fmt(performance.now() - t0)})`;
33+
status.className = OK;
34+
} catch (err) {
35+
status.textContent = 'load failed';
36+
status.className = ERR;
37+
term.textContent = `Could not load wasm.\n\n${err.errors.map(e => e.message).join(' | ')}\n\nFor local development:\n cd demo/ && make dev`;
38+
}
39+
};
40+
41+
const runCode = () => {
42+
if (!wasm) return;
43+
const srcBytes = new TextEncoder().encode(ed.value);
44+
if (srcBytes.length > SZ) {
45+
term.textContent = `error: source exceeds ${SZ} bytes`;
46+
return;
47+
}
48+
const t0 = performance.now();
49+
new Uint8Array(wasm.memory.buffer).set(srcBytes, wasm.src_ptr());
50+
const outLen = wasm.run(srcBytes.length);
51+
const out = new TextDecoder().decode(new Uint8Array(wasm.memory.buffer, wasm.out_ptr(), outLen));
52+
const elapsed = fmt(performance.now() - t0);
53+
term.textContent = out;
54+
status.textContent = `ready (${elapsed})`;
55+
status.className = OK;
56+
};
57+
58+
const sync = () => {
59+
const lines = ed.value.split('\n');
60+
if (lines.length > MAX_LINES) {
61+
ed.value = lines.slice(0, MAX_LINES).join('\n');
62+
}
63+
const n = Math.min(ed.value.split('\n').length, MAX_LINES);
64+
ln.textContent = Array.from({ length: n }, (_, i) => String(i + 1).padStart(2, '0')).join('\n');
65+
ln.scrollTop = ed.scrollTop;
66+
};
67+
68+
btn.addEventListener('click', runCode);
69+
ed.addEventListener('keydown', (e) => {
70+
if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
71+
e.preventDefault();
72+
runCode();
73+
} else if (e.key === 'Enter' && ed.value.split('\n').length >= MAX_LINES) {
74+
e.preventDefault();
75+
}
76+
});
77+
ed.oninput = sync;
78+
ed.onscroll = sync;
79+
80+
sync();
81+
loadWasm();

0 commit comments

Comments
 (0)