nx_wasmfit.nx source
↩ module page · 109 lines · 6510 B
1// nx_wasmfit.nx -- THE ONE RULER FOR "CAN THIS MODULE'S FRAMEBUFFER EXIST IN THE MEMORY IT DECLARES".
2//
3// WHY IT IS A LIBRARY AND NOT A CHECK INSIDE AN EMITTER. On 2026-08-14 /craft shipped BLACK TWICE: its
4// framebuffer had outgrown the module's own declared linear memory (needed 22,022,528 bytes against
5// 192 pages = 12,582,912), so every browser frame trapped with "index out of bounds". The guard that
6// now refuses that was written INSIDE nx_game_page_emit's gpe_build_s, whose header claimed "every
7// wasm page in the estate is built through this function -- one guard here covers all of them".
8//
9// THAT CLAIM WAS FALSE, AND MEASURED SO ON 2026-08-15. nx_wasmpage_census walked all 62,906 shipped
10// html pages: 25 carry an embedded wasm module, and only 9 come from gpe_build_s. The other 16 --
11// pong, racing, td, city, shmup, explorer, adventure, voxelworld, sudoku and the rest -- are emitted
12// by organs that each hand-pasted their own copy of the same blit shim and none of the guard.
13// ★★★★★★A GUARD PLACED IN "THE" SHARED PATH IS ONLY AS BROAD AS THE CLAIM THAT THE PATH IS SHARED,
14// AND THAT CLAIM IS A MEASUREMENT NOBODY TOOK. The census took it and the answer was 9 of 25.
15//
16// So the ruler moves DOWN here, where any emitter can reach it, and gpe_build_s becomes one of its
17// callers rather than its owner. ★EXTEND THE INCUMBENT, NEVER ADD A SECOND RULER: the arithmetic below
18// is gpe_build_s's, moved rather than re-typed, so there is exactly one definition of "fits" in the
19// estate and no opportunity for two of them to drift.
20//
21// It asks the ARTIFACT, never a constant typed in another file: wm_parse reads the module's own memory
22// section, and fb_off/ww/hh are the module's own accessors. With no init() the quality slot is zero,
23// which clamps to the FINEST setting, so ww/hh report the worst case the adaptive controller can ever
24// reach -- exactly the case that has to fit. Cheap by construction: three accessor calls and no
25// render, so it costs nothing per emit and there is no reason for any caller to skip it.
26// license_tier: ORIGINAL
27import "nx_syscalls.nx"
28import "nx_wasm_vm.nx"
29
30const WF_PROCEED: i64 = 0
31const WF_REFUSE: i64 = 1
32
33// ⚠THIS FORMATTER IS A KNOWN DUPLICATE AND IS NAMED AS ONE. The estate's clean implementation is
34// gv_puts/gv_num in nx_gate_verdict (measured balanced by nx_mmapbal), and both other organs written
35// alongside this one now simply delegate to it. This lib deliberately does NOT, because it is imported
36// by every wasm-page EMITTER and pulling the gate framework into each of them to print digits is a
37// worse trade than one small local copy. So the copy stays, BALANCED via the singleton-getter idiom
38// that nx_mmapbal recognises as an owning allocation.
39// ★★★★★OWED, AND STATED RATHER THAN LEFT SILENT: the estate has several integer formatters
40// (gv_num, gpe_pn, g_pn, wf_num). Converging them needs a leaf-level print lib that carries no gate
41// dependency; that is a campaign, not this edit, and pretending otherwise would be the duplicate-ruler
42// defect with a comment on top.
43const WF_NUMBUF: i64 = 32
44func wf_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
45static WF_NUM_B: i64
46func wf_num_b() -> *u8 { if WF_NUM_B == 0 { WF_NUM_B = sys_mmap(WF_NUMBUF) as i64 } return WF_NUM_B as *u8 }
47static WF_NUM_T: i64
48func wf_num_t() -> *u8 { if WF_NUM_T == 0 { WF_NUM_T = sys_mmap(WF_NUMBUF) as i64 } return WF_NUM_T as *u8 }
49func wf_num(v: i64) -> i64 {
50 let b: *u8 = wf_num_b()
51 var n: i64 = 0
52 var x: i64 = v
53 if x == 0 { b[0] = 48 as u8; n = 1 } else {
54 if x < 0 { wf_puts("-" as *u8); x = 0 - x }
55 let t: *u8 = wf_num_t()
56 var m: i64 = 0
57 while x > 0 { t[m] = (48 + (x % 10)) as u8; x = x / 10; m = m + 1 }
58 while m > 0 { m = m - 1; b[n] = t[m]; n = n + 1 }
59 }
60 sys_write(1, b, n)
61 return 0
62}
63
64// THE CONTRACT IS DELIBERATELY BINARY: WF_PROCEED or WF_REFUSE, because the caller's decision is
65// binary and a three-valued return invites `if wf_guard(...) != 0 { refuse }`, which would refuse
66// every module that simply has no framebuffer to check. ★A RETURN CODE THAT MAKES THE WRONG USAGE THE
67// NATURAL ONE IS A DEFECT IN THE CONTRACT, NOT IN THE CALLER. The distinction between "fits" and
68// "nothing to check" is not lost -- it is PRINTED, named, with the numbers beside it.
69// `who` names the calling emitter so a refusal in a build log says which page was not built.
70func wf_guard(wasm: *u8, wn: i64, who: *u8) -> i64 {
71 let m: *WasmMod = wm_new(wasm, wn)
72 if wm_parse(m) != 0 {
73 wf_puts("WASMFIT-REFUSE [" as *u8); wf_puts(who)
74 wf_puts("]: the wasm does not parse -- no page built\n" as *u8)
75 return WF_REFUSE
76 }
77 let fo: i64 = wm_find_export(m, "fb_off" as *u8)
78 let fw: i64 = wm_find_export(m, "ww" as *u8)
79 let fh: i64 = wm_find_export(m, "hh" as *u8)
80 if fo < 0 { return wf_nosurface(who) }
81 if fw < 0 { return wf_nosurface(who) }
82 if fh < 0 { return wf_nosurface(who) }
83
84 let off: i64 = wm_run(m, "fb_off" as *u8, 0,0,0,0,0, 0)
85 let w: i64 = wm_run(m, "ww" as *u8, 0,0,0,0,0, 0)
86 let h: i64 = wm_run(m, "hh" as *u8, 0,0,0,0,0, 0)
87 let need: i64 = off + w*h*8
88 wf_puts(" wasmfit [" as *u8); wf_puts(who); wf_puts("]: framebuffer " as *u8)
89 wf_num(w); wf_puts("x" as *u8); wf_num(h)
90 wf_puts(" at " as *u8); wf_num(off); wf_puts(" needs " as *u8); wf_num(need)
91 wf_puts(" of " as *u8); wf_num(m.mem_bytes); wf_puts(" declared\n" as *u8)
92 if need > m.mem_bytes {
93 wf_puts("WASMFIT-REFUSE [" as *u8); wf_puts(who)
94 wf_puts("]: the framebuffer does not fit the module's own linear memory -- a browser\n" as *u8)
95 wf_puts("traps with 'index out of bounds' on the first frame and the page renders NOTHING.\n" as *u8)
96 wf_puts("Raise the module's declared memory or lower its render ceiling; no page built.\n" as *u8)
97 return WF_REFUSE
98 }
99 return WF_PROCEED
100}
101
102// A module with no ww/hh/fb_off has no framebuffer, so the fit question does not APPLY to it -- this
103// is "not applicable", not "could not look", and acquitting is correct. It still announces, because a
104// guard that passes in silence is indistinguishable from one that was never called.
105func wf_nosurface(who: *u8) -> i64 {
106 wf_puts(" wasmfit [" as *u8); wf_puts(who)
107 wf_puts("]: module exposes no ww/hh/fb_off surface -- no framebuffer to bound\n" as *u8)
108 return WF_PROCEED
109}