code wiki / _hdl_build / nx_js_render_gate.nx
nx_js_render_gate.nx source
↩ module page · 78 lines · 4961 B
1// nx_js_render_gate.nx -- gate for R-JS-DOMWRITE: the sovereign JS engine now BUILDS rendered content.
2// Drives js_render_page (parse->tree, run inline scripts in tree mode, serialize). Proves DOM-write
3// (getElementById().innerHTML= / .textContent=) actually mutates what renders. 0=GREEN/1=RED.
4import "nx_syscalls.nx"
5import "nx_js_eval.nx"
6
7func r_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
8func r_pn(v: i64) -> i64 {
9 var m: i64 = v
10 if m < 0 { r_p("-\x00" as *u8); m = 0 - m }
11 let t: *u8 = sys_mmap(24); var k: i64 = 0
12 if m == 0 { t[0] = 48 as u8; k = 1 } else { while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } }
13 let o: *u8 = sys_mmap(24); var j: i64 = 0
14 while j < k { o[j] = t[k - 1 - j]; j = j + 1 }
15 sys_write(1, o, k); return 0
16}
17func r_clen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
18func r_contains(buf: *u8, blen: i64, needle: *u8) -> i64 {
19 let nl: i64 = r_clen(needle)
20 if nl == 0 { return 1 }
21 var i: i64 = 0
22 while (i + nl) <= blen {
23 var j: i64 = 0; var ok: i64 = 1
24 while j < nl { if (buf[i + j] & 0xff) != (needle[j] & 0xff) { ok = 0; j = nl } else { j = j + 1 } }
25 if ok == 1 { return 1 }
26 i = i + 1
27 }
28 return 0
29}
30func chk(cond: i64, name: *u8, pp: *i64, tp: *i64) -> i64 {
31 tp[0] = tp[0] + 1; r_p(name)
32 if cond == 1 { pp[0] = pp[0] + 1; r_p(" ok\n\x00" as *u8) } else { r_p(" FAIL\n\x00" as *u8) }
33 return 0
34}
35
36func main() -> i64 {
37 let pp: *i64 = sys_mmap(8) as *i64; pp[0] = 0
38 let tp: *i64 = sys_mmap(8) as *i64; tp[0] = 0
39 let out: *u8 = sys_mmap(131072)
40
41 // R1: a script BUILDS content via innerHTML -> renders into the serialized DOM (the core win)
42 let page1: *u8 = "<html><body><div id=\"app\">old</div><script>document.getElementById('app').innerHTML='<p>built by JS</p>';</script></body></html>\x00" as *u8
43 let n1: i64 = js_render_page(page1, r_clen(page1), out, 131072)
44 chk(r_contains(out, n1, "<p>built by JS</p>\x00" as *u8), "R1 innerHTML builds DOM\x00" as *u8, pp, tp)
45 chk(r_contains(out, n1, ">old<\x00" as *u8) == 0, "R1b old content replaced\x00" as *u8, pp, tp)
46
47 // R2: textContent= mutation renders
48 let page2: *u8 = "<html><body><span id=\"s\">x</span><script>document.getElementById('s').textContent='ZZZ';</script></body></html>\x00" as *u8
49 let n2: i64 = js_render_page(page2, r_clen(page2), out, 131072)
50 chk(r_contains(out, n2, "ZZZ\x00" as *u8), "R2 textContent= renders\x00" as *u8, pp, tp)
51
52 // R3: no-script page still round-trips unchanged (control)
53 let page3: *u8 = "<html><body><h1>Hello</h1></body></html>\x00" as *u8
54 let n3: i64 = js_render_page(page3, r_clen(page3), out, 131072)
55 chk(r_contains(out, n3, "<h1>Hello</h1>\x00" as *u8), "R3 no-script round-trip\x00" as *u8, pp, tp)
56
57 // R4: missing-id getElementById is null -> assigning throws inside script, page unharmed (neg control)
58 let page4: *u8 = "<html><body><div id=\"keep\">stay</div><script>var e=document.getElementById('absent'); if(e){ e.textContent='X'; }</script></body></html>\x00" as *u8
59 let n4: i64 = js_render_page(page4, r_clen(page4), out, 131072)
60 chk(r_contains(out, n4, "stay\x00" as *u8), "R4 missing-id safe\x00" as *u8, pp, tp)
61
62 // R5: a script BUILDS a node via createElement + setAttribute + appendChild (the React-style pattern)
63 let page5: *u8 = "<html><body><div id=\"box\"></div><script>var d=document.createElement('p');d.textContent='made by createElement';d.setAttribute('class','built');document.getElementById('box').appendChild(d);</script></body></html>\x00" as *u8
64 let n5: i64 = js_render_page(page5, r_clen(page5), out, 131072)
65 chk(r_contains(out, n5, "made by createElement\x00" as *u8), "R5 createElement+appendChild builds\x00" as *u8, pp, tp)
66 chk(r_contains(out, n5, "class=\"built\"\x00" as *u8), "R5b setAttribute on built node\x00" as *u8, pp, tp)
67
68 // R6: querySelectorAll('.class').length + querySelector('tag').setAttribute, rendered
69 let page6: *u8 = "<html><body><ul><li class=\"it\">A</li><li class=\"it\">B</li><li>C</li></ul><div id=\"out\"></div><script>var n=document.querySelectorAll('.it').length;document.getElementById('out').textContent='count='+n;document.querySelector('li').setAttribute('data-first','yes');</script></body></html>\x00" as *u8
70 let n6: i64 = js_render_page(page6, r_clen(page6), out, 131072)
71 chk(r_contains(out, n6, "count=2\x00" as *u8), "R6 querySelectorAll .length\x00" as *u8, pp, tp)
72 chk(r_contains(out, n6, "data-first=\"yes\"\x00" as *u8), "R6b querySelector+setAttribute\x00" as *u8, pp, tp)
73
74 r_p("JSRENDERGATE pass=\x00" as *u8); r_pn(pp[0]); r_p("/\x00" as *u8); r_pn(tp[0]); r_p("\n\x00" as *u8)
75 if pp[0] == tp[0] { r_p("JSRENDERGATE verdict=GREEN\n\x00" as *u8); return 0 }
76 r_p("JSRENDERGATE verdict=RED\n\x00" as *u8)
77 return 1
78}