| Add a WebAssembly backend for the example 728acaa nandithebull 7h ago | 1 | // Headless check of the wasm build: same contract as the native library. |
| 2 | // node tool/test_wasm.mjs [out.bin] |
| 3 | // With an argument, writes the raw RGBA frame there so it can be diffed |
| 4 | // against the native kernel (tool/test_wasm_parity.sh). |
| 5 | import { createRequire } from 'node:module'; |
| 6 | import { writeFileSync } from 'node:fs'; |
| 7 | |
| 8 | const require = createRequire(import.meta.url); |
| Replace V with Nim 472eb49 nandithebull 7h ago | 9 | const createNimFlutterModule = require('../example/web/nimflutter.js'); |
| 10 | const M = await createNimFlutterModule(); |
| Add a WebAssembly backend for the example 728acaa nandithebull 7h ago | 11 | |
| 12 | let failures = 0; |
| 13 | const check = (name, ok, detail = '') => { |
| 14 | console.log(`${ok ? 'ok ' : 'FAIL'} ${name}${detail ? ` — ${detail}` : ''}`); |
| 15 | if (!ok) failures++; |
| 16 | }; |
| 17 | |
| Replace V with Nim 472eb49 nandithebull 7h ago | 18 | M.ccall('nf_init', null, [], []); |
| 19 | check('nf_add', M.ccall('nf_add', 'number', ['number', 'number'], [20, 22]) === 42); |
| Add a WebAssembly backend for the example 728acaa nandithebull 7h ago | 20 | |
| Replace V with Nim 472eb49 nandithebull 7h ago | 21 | // nf_greet returns a Nim-allocated string the caller must release. |
| Add a WebAssembly backend for the example 728acaa nandithebull 7h ago | 22 | const namePtr = M._malloc(16); |
| 23 | M.stringToUTF8('wasm', namePtr, 16); |
| Replace V with Nim 472eb49 nandithebull 7h ago | 24 | const resPtr = M.ccall('nf_greet', 'number', ['number'], [namePtr]); |
| Add a WebAssembly backend for the example 728acaa nandithebull 7h ago | 25 | const greeting = M.UTF8ToString(resPtr); |
| Replace V with Nim 472eb49 nandithebull 7h ago | 26 | M.ccall('nf_free', null, ['number'], [resPtr]); |
| Add a WebAssembly backend for the example 728acaa nandithebull 7h ago | 27 | M._free(namePtr); |
| Replace V with Nim 472eb49 nandithebull 7h ago | 28 | check('nf_greet', greeting === 'Hello, wasm, from Nim!', greeting); |
| Add a WebAssembly backend for the example 728acaa nandithebull 7h ago | 29 | |
| 30 | const W = 240, H = 180, ITER = 300, BYTES = W * H * 4; |
| 31 | const buf = M._malloc(BYTES); |
| 32 | |
| 33 | const fill = (len, y0, y1) => { |
| 34 | M.HEAPU8.fill(0, buf, buf + BYTES); |
| 35 | M.ccall( |
| Replace V with Nim 472eb49 nandithebull 7h ago | 36 | 'nf_mandelbrot', |
| Add a WebAssembly backend for the example 728acaa nandithebull 7h ago | 37 | null, |
| 38 | ['number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number'], |
| 39 | [buf, len, W, H, -0.5, 0.0, 3.0, ITER, y0, y1], |
| 40 | ); |
| 41 | return M.HEAPU8.slice(buf, buf + BYTES); |
| 42 | }; |
| 43 | |
| 44 | const frame = fill(BYTES, 0, H); |
| 45 | check('every pixel has alpha', frame.every((v, i) => i % 4 !== 3 || v === 255)); |
| 46 | check('frame is a fractal, not a flat fill', new Set(frame).size > 8); |
| 47 | |
| 48 | // size_t is 32-bit on wasm32 — the guard has to hold there too. |
| 49 | check('undersized buf_len writes nothing', fill(BYTES - 1, 0, H).every((v) => v === 0)); |
| 50 | check('zero buf_len writes nothing', fill(0, 0, H).every((v) => v === 0)); |
| 51 | check('inverted band writes nothing', fill(BYTES, 10, 2).every((v) => v === 0)); |
| 52 | |
| 53 | // Band split must reassemble into the identical frame. |
| 54 | const top = fill(BYTES, 0, H / 2).slice(0, (BYTES / 2)); |
| 55 | const bottom = fill(BYTES, H / 2, H).slice(0, (BYTES / 2)); |
| 56 | const joined = new Uint8Array(BYTES); |
| 57 | joined.set(top, 0); |
| 58 | joined.set(bottom, BYTES / 2); |
| 59 | check('band split matches a single-shot render', joined.every((v, i) => v === frame[i])); |
| 60 | |
| 61 | M._free(buf); |
| 62 | |
| 63 | if (process.argv[2]) { |
| 64 | writeFileSync(process.argv[2], Buffer.from(frame)); |
| 65 | console.log(`wrote ${process.argv[2]} (${frame.length} bytes)`); |
| 66 | } |
| 67 | process.exit(failures === 0 ? 0 : 1); |