11const 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 ;
2+ const DEV = ! [ 'demo.edgepython.com' ] . includes ( location . hostname ) ;
3+ const WASM_SOURCES = DEV
4+ ? [ 'https://demo.edgepython.com/compiler_lib.wasm' ]
5+ : [ './compiler_lib.wasm' ] ;
6+ const FETCH_OPTS = DEV ? { cache : 'no-store' } : undefined ;
67
8+ const CLS = { ok : 'ml-auto text-[#7daf7a]' , err : 'ml-auto text-[#d67f6d]' } ;
9+ const MAX_LINES = 99 ;
710const $ = ( id ) => document . getElementById ( id ) ;
8- const ed = $ ( 'ed' ) , ln = $ ( 'ln' ) , btn = $ ( 'run' ) , term = $ ( 'term' ) , status = $ ( 'status' ) ;
11+ const [ ed , ln , btn , term , statusEl ] = [ 'ed' , 'ln' , 'run' , 'term' , 'status' ] . map ( $ ) ;
912
10- let wasm = null ;
13+ let wasm ;
1114
1215const fmt = ( ms ) => ms < 1000 ? `${ ms . toFixed ( 0 ) } ms` : `${ ( ms / 1000 ) . toFixed ( 2 ) } s` ;
16+ const setStatus = ( text , cls = CLS . ok ) => ( statusEl . textContent = text , statusEl . className = cls ) ;
17+ const time = async ( fn ) => { const t0 = performance . now ( ) ; const r = await fn ( ) ; return [ r , fmt ( performance . now ( ) - t0 ) ] ; } ;
1318
1419const instantiate = async ( url ) => {
15- const res = await fetch ( url ) ;
20+ const res = await fetch ( url , FETCH_OPTS ) ;
1621 if ( ! res . ok ) throw new Error ( `${ url } : HTTP ${ res . status } ` ) ;
1722 try {
1823 return await WebAssembly . instantiateStreaming ( res , { } ) ;
1924 } catch {
20- const bytes = await ( await fetch ( url ) ) . arrayBuffer ( ) ;
21- return WebAssembly . instantiate ( bytes , { } ) ;
25+ return WebAssembly . instantiate ( await ( await fetch ( url , FETCH_OPTS ) ) . arrayBuffer ( ) , { } ) ;
2226 }
2327} ;
2428
2529const loadWasm = async ( ) => {
26- status . textContent = 'loading wasm…' ;
27- const t0 = performance . now ( ) ;
30+ setStatus ( 'loading wasm…' , CLS . ok ) ;
2831 try {
29- const { instance } = await Promise . any ( WASM_SOURCES . map ( instantiate ) ) ;
32+ const [ { instance } , t ] = await time ( ( ) => Promise . any ( WASM_SOURCES . map ( instantiate ) ) ) ;
3033 wasm = instance . exports ;
3134 btn . disabled = false ;
32- status . textContent = `ready (${ fmt ( performance . now ( ) - t0 ) } )` ;
33- status . className = OK ;
35+ setStatus ( `ready (${ t } ${ DEV ? ' · dev' : '' } )` ) ;
3436 } 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` ;
37+ setStatus ( 'load failed' , CLS . err ) ;
38+ term . textContent = `Could not load wasm.\n\n${ err . errors . map ( e => e . message ) . join ( ' | ' ) } ` ;
3839 }
3940} ;
4041
41- const runCode = ( ) => {
42+ const runCode = async ( ) => {
4243 if ( ! wasm ) return ;
4344 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 ) ;
45+ if ( srcBytes . length > SZ ) return void ( term . textContent = `error: source exceeds ${ SZ } bytes` ) ;
46+ const [ out , t ] = await time ( ( ) => {
47+ new Uint8Array ( wasm . memory . buffer ) . set ( srcBytes , wasm . src_ptr ( ) ) ;
48+ const len = wasm . run ( srcBytes . length ) ;
49+ return new TextDecoder ( ) . decode ( new Uint8Array ( wasm . memory . buffer , wasm . out_ptr ( ) , len ) ) ;
50+ } ) ;
5351 term . textContent = out ;
54- status . textContent = `ready (${ elapsed } )` ;
55- status . className = OK ;
52+ setStatus ( `ready (${ t } )` ) ;
5653} ;
5754
5855const sync = ( ) => {
5956 const lines = ed . value . split ( '\n' ) ;
60- if ( lines . length > MAX_LINES ) {
61- ed . value = lines . slice ( 0 , MAX_LINES ) . join ( '\n' ) ;
62- }
57+ if ( lines . length > MAX_LINES ) ed . value = lines . slice ( 0 , MAX_LINES ) . join ( '\n' ) ;
6358 const n = Math . min ( ed . value . split ( '\n' ) . length , MAX_LINES ) ;
6459 ln . textContent = Array . from ( { length : n } , ( _ , i ) => String ( i + 1 ) . padStart ( 2 , '0' ) ) . join ( '\n' ) ;
6560 ln . scrollTop = ed . scrollTop ;
6661} ;
6762
6863btn . addEventListener ( 'click' , runCode ) ;
6964ed . 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- }
65+ if ( ( e . ctrlKey || e . metaKey ) && e . key === 'Enter' ) { e . preventDefault ( ) ; runCode ( ) ; }
66+ else if ( e . key === 'Enter' && ed . value . split ( '\n' ) . length >= MAX_LINES ) e . preventDefault ( ) ;
7667} ) ;
77- ed . oninput = sync ;
78- ed . onscroll = sync ;
68+ ed . oninput = ed . onscroll = sync ;
7969
8070sync ( ) ;
8171loadWasm ( ) ;
0 commit comments