nx_js_conformance.nx source
↩ module page · 233 lines · 17198 B
1// nx_js_conformance.nx -- WB-JS-001 conformance HARNESS (test262-lite, no-wave
2// MEASUREMENT, not a pass/fail gate). Composes the sovereign engine READ-ONLY
3// (imports nx_js_eval -> js_run_source) and runs a categorized battery of real JS
4// programs, asserting evaluated VALUES + expected ERRORS. Prints a per-category
5// capability map + an overall conformance permil -- the honest measure of what the
6// engine does today and what's still gapped (drives the next eval rungs).
7//
8// This is a SEPARATE organ (does NOT edit nx_js_eval) so it can ride the engine
9// while the evaluator is authored independently. Each case is a real spec behavior;
10// FAILs are NAMED, never hidden -- the score is the truth, not a wave. license_tier: ORIGINAL
11import "nx_js_eval.nx"
12import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
13
14func jc_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
15// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
16// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
17// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
18// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
19func jc_putn(v: i64) -> i64 { nxi_out(v); return 0 }
20func jc_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
21
22// ---- assertion primitives over js_run_source ----
23func jc_num(s: *u8, want: i64) -> i64 {
24 let out: *i64 = sys_mmap(16) as *i64
25 if js_run_source(s, jc_slen(s), out) != 0 { return 0 }
26 if out[0] != VAL_NUM { return 0 }
27 if out[1] != want { return 0 }
28 return 1
29}
30func jc_bool(s: *u8, want: i64) -> i64 {
31 let out: *i64 = sys_mmap(16) as *i64
32 if js_run_source(s, jc_slen(s), out) != 0 { return 0 }
33 if out[0] != VAL_BOOL { return 0 }
34 if out[1] != want { return 0 }
35 return 1
36}
37func jc_str(s: *u8, want: *u8) -> i64 {
38 let out: *i64 = sys_mmap(16) as *i64
39 if js_run_source(s, jc_slen(s), out) != 0 { return 0 }
40 if out[0] != VAL_STR { return 0 }
41 let rec: *i64 = (out[1]) as *i64
42 let en: i64 = jc_slen(want)
43 if ev_str_len(rec) != en { return 0 }
44 let rb: *u8 = ev_str_bytes(rec)
45 var i: i64 = 0
46 while i < en { if (rb[i] & 0xff) != (want[i] & 0xff) { return 0 } i = i + 1 }
47 return 1
48}
49func jc_err(s: *u8) -> i64 {
50 let out: *i64 = sys_mmap(16) as *i64
51 if js_run_source(s, jc_slen(s), out) == 1 { return 1 }
52 return 0
53}
54
55// run a single case, print PASS/FAIL with the label, return 1/0 to tally.
56func jc_case(ok: i64, label: *u8) -> i64 {
57 if ok == 1 { jc_puts(" ok " as *u8) } else { jc_puts(" FAIL " as *u8) }
58 jc_puts(label); jc_puts("\n" as *u8)
59 return ok
60}
61
62func main() -> i64 {
63 var pass: i64 = 0
64 var tot: i64 = 0
65 jc_puts("nx_js_conformance (WB-JS-001 test262-lite, no-wave measurement)\n" as *u8)
66
67 // ---- arithmetic ----
68 jc_puts(" [arithmetic]\n" as *u8)
69 pass = pass + jc_case(jc_num("2+2\x00" as *u8, 4), "2+2=4\x00" as *u8); tot=tot+1
70 pass = pass + jc_case(jc_num("10-3\x00" as *u8, 7), "10-3=7\x00" as *u8); tot=tot+1
71 pass = pass + jc_case(jc_num("4*5\x00" as *u8, 20), "4*5=20\x00" as *u8); tot=tot+1
72 pass = pass + jc_case(jc_num("20/4\x00" as *u8, 5), "20/4=5\x00" as *u8); tot=tot+1
73 pass = pass + jc_case(jc_num("17%5\x00" as *u8, 2), "17%5=2\x00" as *u8); tot=tot+1
74
75 // ---- precedence / associativity ----
76 jc_puts(" [precedence]\n" as *u8)
77 pass = pass + jc_case(jc_num("1+2*3\x00" as *u8, 7), "1+2*3=7\x00" as *u8); tot=tot+1
78 pass = pass + jc_case(jc_num("(1+2)*3\x00" as *u8, 9), "(1+2)*3=9\x00" as *u8); tot=tot+1
79 pass = pass + jc_case(jc_num("10-2-3\x00" as *u8, 5), "10-2-3=5 (left-assoc)\x00" as *u8); tot=tot+1
80 pass = pass + jc_case(jc_num("2+3*4-1\x00" as *u8, 13), "2+3*4-1=13\x00" as *u8); tot=tot+1
81
82 // ---- comparison / equality ----
83 jc_puts(" [comparison]\n" as *u8)
84 pass = pass + jc_case(jc_bool("2<3\x00" as *u8, 1), "2<3=true\x00" as *u8); tot=tot+1
85 pass = pass + jc_case(jc_bool("3<2\x00" as *u8, 0), "3<2=false\x00" as *u8); tot=tot+1
86 pass = pass + jc_case(jc_bool("5<=5\x00" as *u8, 1), "5<=5=true\x00" as *u8); tot=tot+1
87 pass = pass + jc_case(jc_bool("3==3\x00" as *u8, 1), "3==3=true\x00" as *u8); tot=tot+1
88 pass = pass + jc_case(jc_bool("2===2\x00" as *u8, 1), "2===2=true\x00" as *u8); tot=tot+1
89 pass = pass + jc_case(jc_bool("2!==3\x00" as *u8, 1), "2!==3=true\x00" as *u8); tot=tot+1
90
91 // ---- logical / truthiness ----
92 jc_puts(" [logical]\n" as *u8)
93 pass = pass + jc_case(jc_num("1&&2\x00" as *u8, 2), "1&&2=2 (operand)\x00" as *u8); tot=tot+1
94 pass = pass + jc_case(jc_num("0||5\x00" as *u8, 5), "0||5=5\x00" as *u8); tot=tot+1
95 pass = pass + jc_case(jc_num("0&&9\x00" as *u8, 0), "0&&9=0\x00" as *u8); tot=tot+1
96 pass = pass + jc_case(jc_bool("!0\x00" as *u8, 1), "!0=true\x00" as *u8); tot=tot+1
97 pass = pass + jc_case(jc_bool("!!5\x00" as *u8, 1), "!!5=true\x00" as *u8); tot=tot+1
98
99 // ---- strings ----
100 jc_puts(" [strings]\n" as *u8)
101 pass = pass + jc_case(jc_str("'ab'+'cd'\x00" as *u8, "abcd\x00" as *u8), "'ab'+'cd'='abcd'\x00" as *u8); tot=tot+1
102 pass = pass + jc_case(jc_str("'x'+'y'+'z'\x00" as *u8, "xyz\x00" as *u8), "'x'+'y'+'z'='xyz'\x00" as *u8); tot=tot+1
103 pass = pass + jc_case(jc_str("'n='+5\x00" as *u8, "n=5\x00" as *u8), "'n='+5='n=5' (coerce)\x00" as *u8); tot=tot+1
104 pass = pass + jc_case(jc_bool("'a'=='a'\x00" as *u8, 1), "'a'=='a'=true\x00" as *u8); tot=tot+1
105 pass = pass + jc_case(jc_bool("'a'=='b'\x00" as *u8, 0), "'a'=='b'=false\x00" as *u8); tot=tot+1
106
107 // ---- variables / assignment ----
108 jc_puts(" [variables]\n" as *u8)
109 pass = pass + jc_case(jc_num("var x=5; x+1\x00" as *u8, 6), "var x=5;x+1=6\x00" as *u8); tot=tot+1
110 pass = pass + jc_case(jc_num("var x=5; x=x+10; x\x00" as *u8, 15), "reassign x=15\x00" as *u8); tot=tot+1
111 pass = pass + jc_case(jc_num("var a=1; var b=2; a+b\x00" as *u8, 3), "two vars a+b=3\x00" as *u8); tot=tot+1
112
113 // ---- control flow ----
114 jc_puts(" [control-flow]\n" as *u8)
115 pass = pass + jc_case(jc_num("var x=10; if(x>5)x=1; else x=0; x\x00" as *u8, 1), "if-true branch\x00" as *u8); tot=tot+1
116 pass = pass + jc_case(jc_num("var x=2; if(x>5)x=1; else x=0; x\x00" as *u8, 0), "if-else branch\x00" as *u8); tot=tot+1
117 pass = pass + jc_case(jc_num("var s=0; var i=1; while(i<=5){s=s+i;i=i+1;} s\x00" as *u8, 15), "while sum 1..5=15\x00" as *u8); tot=tot+1
118
119 // ---- functions / recursion / closures ----
120 jc_puts(" [functions]\n" as *u8)
121 pass = pass + jc_case(jc_num("function add(a,b){return a+b;} add(2,3)\x00" as *u8, 5), "add(2,3)=5\x00" as *u8); tot=tot+1
122 pass = pass + jc_case(jc_num("function fac(n){if(n<=1){return 1;} return n*fac(n-1);} fac(5)\x00" as *u8, 120), "fac(5)=120\x00" as *u8); tot=tot+1
123 pass = pass + jc_case(jc_num("function fib(n){if(n<2){return n;} return fib(n-1)+fib(n-2);} fib(10)\x00" as *u8, 55), "fib(10)=55\x00" as *u8); tot=tot+1
124 pass = pass + jc_case(jc_num("function o(){var x=10; function i(){return x;} return i();} o()\x00" as *u8, 10), "nested fn closes over local=10\x00" as *u8); tot=tot+1
125
126 // ---- objects / arrays (probes the NEXT rung; FAIL here = honest named-open) ----
127 jc_puts(" [objects/arrays]\n" as *u8)
128 pass = pass + jc_case(jc_num("var o={x:10}; o.x\x00" as *u8, 10), "object literal + member read {x:10}.x=10\x00" as *u8); tot=tot+1
129 pass = pass + jc_case(jc_num("var o={}; o.a=5; o.a\x00" as *u8, 5), "object member assign o.a=5\x00" as *u8); tot=tot+1
130 pass = pass + jc_case(jc_num("var a=[10,20,30]; a[1]\x00" as *u8, 20), "array literal + index a[1]=20\x00" as *u8); tot=tot+1
131 pass = pass + jc_case(jc_num("[1,2,3,4].length\x00" as *u8, 4), "array .length=4\x00" as *u8); tot=tot+1
132 pass = pass + jc_case(jc_num("'hello'.length\x00" as *u8, 5), "string .length=5\x00" as *u8); tot=tot+1
133
134 // ---- extended control flow (for / do-while / break / continue) ----
135 jc_puts(" [control-flow-ext]\n" as *u8)
136 pass = pass + jc_case(jc_num("var s=0; for(var i=0;i<5;i=i+1){s=s+i;} s\x00" as *u8, 10), "for loop sum 0..4 = 10\x00" as *u8); tot=tot+1
137 pass = pass + jc_case(jc_num("var i=0; var s=0; do{s=s+i;i=i+1;}while(i<3); s\x00" as *u8, 3), "do-while sum 0..2 = 3\x00" as *u8); tot=tot+1
138 pass = pass + jc_case(jc_num("var s=0; var i=0; while(i<10){if(i==3)break; s=s+i; i=i+1;} s\x00" as *u8, 3), "break at i==3 -> 0+1+2=3\x00" as *u8); tot=tot+1
139 pass = pass + jc_case(jc_num("var s=0; var i=0; while(i<5){i=i+1; if(i==3)continue; s=s+i;} s\x00" as *u8, 12), "continue skip 3 -> 1+2+4+5=12\x00" as *u8); tot=tot+1
140
141 // ---- extended operators (ternary / compound assign) ----
142 jc_puts(" [operators-ext]\n" as *u8)
143 pass = pass + jc_case(jc_num("var x=5; x>3?100:200\x00" as *u8, 100), "ternary true -> 100\x00" as *u8); tot=tot+1
144 pass = pass + jc_case(jc_num("var x=2; x>3?100:200\x00" as *u8, 200), "ternary false -> 200\x00" as *u8); tot=tot+1
145 pass = pass + jc_case(jc_num("var x=10; x+=5; x\x00" as *u8, 15), "compound += -> 15\x00" as *u8); tot=tot+1
146 pass = pass + jc_case(jc_num("var x=10; x-=3; x\x00" as *u8, 7), "compound -= -> 7\x00" as *u8); tot=tot+1
147 pass = pass + jc_case(jc_num("var x=4; x*=3; x\x00" as *u8, 12), "compound *= -> 12\x00" as *u8); tot=tot+1
148
149 // ---- R-JS-UPDATE (rung 5a): ++/-- prefix/postfix on ident/member/index ----
150 jc_puts(" [update-ops]\n" as *u8)
151 pass = pass + jc_case(jc_num("var i=5; i++; i\x00" as *u8, 6), "i++ -> 6\x00" as *u8); tot=tot+1
152 pass = pass + jc_case(jc_num("var i=5; var j=i++; j*10+i\x00" as *u8, 56), "postfix returns OLD (56)\x00" as *u8); tot=tot+1
153 pass = pass + jc_case(jc_num("var i=5; var j=++i; j*10+i\x00" as *u8, 66), "prefix returns NEW (66)\x00" as *u8); tot=tot+1
154 pass = pass + jc_case(jc_num("var s=0; for(var i=0;i<5;i++){s+=i;} s\x00" as *u8, 10), "for(...;i++) sum=10\x00" as *u8); tot=tot+1
155 pass = pass + jc_case(jc_num("var o={n:1}; o.n++; o.n\x00" as *u8, 2), "o.n++ -> 2\x00" as *u8); tot=tot+1
156 pass = pass + jc_case(jc_num("var a=[7]; a[0]--; a[0]\x00" as *u8, 6), "a[0]-- -> 6\x00" as *u8); tot=tot+1
157
158 // ---- R-JS-F64 / P8 (real-JS IEEE-double number model): non-exact div -> double; /0 -> Inf/NaN ----
159 jc_puts(" [numbers-f64]\n" as *u8)
160 pass = pass + jc_case(jc_str("''+7/2\x00" as *u8, "3.5\x00" as *u8), "7/2 = 3.5 (not int 3)\x00" as *u8); tot=tot+1
161 pass = pass + jc_case(jc_num("6/2\x00" as *u8, 3), "6/2 = 3 (exact stays int)\x00" as *u8); tot=tot+1
162 pass = pass + jc_case(jc_str("''+1/0\x00" as *u8, "Infinity\x00" as *u8), "1/0 = Infinity (not error)\x00" as *u8); tot=tot+1
163 pass = pass + jc_case(jc_str("''+(0-1/0)\x00" as *u8, "-Infinity\x00" as *u8), "-1/0 = -Infinity\x00" as *u8); tot=tot+1
164 pass = pass + jc_case(jc_str("''+0/0\x00" as *u8, "NaN\x00" as *u8), "0/0 = NaN\x00" as *u8); tot=tot+1
165 pass = pass + jc_case(jc_str("''+5%0\x00" as *u8, "NaN\x00" as *u8), "5%0 = NaN\x00" as *u8); tot=tot+1
166 pass = pass + jc_case(jc_num("7%3\x00" as *u8, 1), "7%3 = 1 (int mod exact)\x00" as *u8); tot=tot+1
167 pass = pass + jc_case(jc_str("''+1/4\x00" as *u8, "0.25\x00" as *u8), "1/4 = 0.25\x00" as *u8); tot=tot+1
168
169 // ---- OCTANE-ENABLING FEATURES (2026-07-08): bitwise, radix literals, multi-var, prototypes, ctors ----
170 jc_puts(" [bitwise]\n" as *u8)
171 pass = pass + jc_case(jc_num("5&3\x00" as *u8, 1), "5&3 = 1\x00" as *u8); tot=tot+1
172 pass = pass + jc_case(jc_num("5|2\x00" as *u8, 7), "5|2 = 7\x00" as *u8); tot=tot+1
173 pass = pass + jc_case(jc_num("5^3\x00" as *u8, 6), "5^3 = 6\x00" as *u8); tot=tot+1
174 pass = pass + jc_case(jc_num("~5\x00" as *u8, 0 - 6), "~5 = -6\x00" as *u8); tot=tot+1
175 pass = pass + jc_case(jc_num("1<<4\x00" as *u8, 16), "1<<4 = 16\x00" as *u8); tot=tot+1
176 pass = pass + jc_case(jc_num("255>>2\x00" as *u8, 63), "255>>2 = 63\x00" as *u8); tot=tot+1
177 pass = pass + jc_case(jc_num("13>>1^53256\x00" as *u8, 53262), "richards idle: 13>>1^0xD008\x00" as *u8); tot=tot+1
178 jc_puts(" [radix literals]\n" as *u8)
179 pass = pass + jc_case(jc_num("0xFF\x00" as *u8, 255), "0xFF = 255\x00" as *u8); tot=tot+1
180 pass = pass + jc_case(jc_num("0xD008\x00" as *u8, 53256), "0xD008 = 53256\x00" as *u8); tot=tot+1
181 pass = pass + jc_case(jc_num("0o17\x00" as *u8, 15), "0o17 = 15\x00" as *u8); tot=tot+1
182 pass = pass + jc_case(jc_num("0b1011\x00" as *u8, 11), "0b1011 = 11\x00" as *u8); tot=tot+1
183 jc_puts(" [multi-declarator var]\n" as *u8)
184 pass = pass + jc_case(jc_num("var a=1,b=2,c=3; a+b+c\x00" as *u8, 6), "var a=1,b=2,c=3 -> 6\x00" as *u8); tot=tot+1
185 pass = pass + jc_case(jc_num("var p, q=5; (p==undefined?100:0)+q\x00" as *u8, 105), "var p,q=5 (p undefined)\x00" as *u8); tot=tot+1
186 jc_puts(" [prototype OOP]\n" as *u8)
187 pass = pass + jc_case(jc_num("function F(){this.x=5;}F.prototype.g=function(){return this.x*2;};new F().g()\x00" as *u8, 10), "prototype method + new\x00" as *u8); tot=tot+1
188 pass = pass + jc_case(jc_num("function A(){}A.prototype.k=9;var a=new A();a.k\x00" as *u8, 9), "inherited data property\x00" as *u8); tot=tot+1
189 jc_puts(" [native constructors]\n" as *u8)
190 pass = pass + jc_case(jc_num("new Array(4).length\x00" as *u8, 4), "new Array(4).length = 4\x00" as *u8); tot=tot+1
191 pass = pass + jc_case(jc_num("new Array(7,8,9).length\x00" as *u8, 3), "new Array(7,8,9).length = 3\x00" as *u8); tot=tot+1
192 pass = pass + jc_case(jc_str("var e=new Error('boom'); e.message\x00" as *u8, "boom\x00" as *u8), "new Error(msg).message\x00" as *u8); tot=tot+1
193
194 // ---- R-JS-TRY (rung 5b): try/catch/finally + throw ----
195 jc_puts(" [try-catch]\n" as *u8)
196 pass = pass + jc_case(jc_num("var r=0; try{throw 5;}catch(e){r=e;} r\x00" as *u8, 5), "throw value caught -> 5\x00" as *u8); tot=tot+1
197 pass = pass + jc_case(jc_num("var r=0; try{var o={}; o.nope();}catch(e){r=7;} r\x00" as *u8, 7), "runtime error caught -> 7\x00" as *u8); tot=tot+1
198 pass = pass + jc_case(jc_str("var r=''; try{r=r+'t';}finally{r=r+'f';} r\x00" as *u8, "tf\x00" as *u8), "finally runs on normal path\x00" as *u8); tot=tot+1
199 pass = pass + jc_case(jc_str("var g=''; function f(){try{return 'A';}finally{g=g+'F';}} f()+g\x00" as *u8, "AF\x00" as *u8), "return runs finally -> AF\x00" as *u8); tot=tot+1
200 pass = pass + jc_case(jc_num("var r=0; try{try{throw 1;}catch(e){throw 2;}}catch(e2){r=e2;} r\x00" as *u8, 2), "nested rethrow -> outer catch\x00" as *u8); tot=tot+1
201
202 // ---- REAL-WORLD SHAPE: hydration-style image extraction (array of objects -> URL list).
203 // This is EXACTLY the compute google-images JS hydration does: walk a data array,
204 // filter, and build the result. If it runs, the engine is READY for the extraction
205 // half of google-images -- only the DOM/fetch DATA-binding (native fns) remains. ----
206 jc_puts(" [hydration-shape]\n" as *u8)
207 pass = pass + jc_case(jc_str("var data=[{src:'img1',ok:1},{src:'img2',ok:0},{src:'img3',ok:1}]; var r=''; for(var i=0;i<data.length;i=i+1){ if(data[i].ok==1){ r=r+data[i].src+','; } } r\x00" as *u8, "img1,img3,\x00" as *u8), "extract valid image URLs from data-array (array<-obj, index, member, filter, concat)\x00" as *u8); tot=tot+1
208 pass = pass + jc_case(jc_num("var a=[3,1,4,1,5,9,2,6]; var mx=0; for(var i=0;i<a.length;i=i+1){ if(a[i]>mx){mx=a[i];} } mx\x00" as *u8, 9), "scan array for max = 9\x00" as *u8); tot=tot+1
209
210 // ---- error / tamper (must be ReferenceError-class, not silent) ----
211 jc_puts(" [errors]\n" as *u8)
212 pass = pass + jc_case(jc_err("y+1\x00" as *u8), "undeclared READ y -> error\x00" as *u8); tot=tot+1
213 pass = pass + jc_case(jc_num("z=5; z\x00" as *u8, 5), "assign-to-undeclared -> NON-STRICT auto-global (V8: z=5, NOT error)\x00" as *u8); tot=tot+1
214 pass = pass + jc_case(jc_err("1+\x00" as *u8), "parse '1+' -> error\x00" as *u8); tot=tot+1
215 pass = pass + jc_case(jc_err("(1+2\x00" as *u8), "unclosed paren -> error\x00" as *u8); tot=tot+1
216
217 // ---- report ----
218 var permil: i64 = 0
219 if tot > 0 { permil = pass * 1000 / tot }
220 jc_puts("---- conformance: passed " as *u8); jc_putn(pass); jc_puts(" / " as *u8); jc_putn(tot)
221 jc_puts(" = " as *u8); jc_putn(permil); jc_puts(" permil\n" as *u8)
222 let lfd: i64 = sys_openat_append("knowledge/status/js_engine.log\x00" as *u8, 0x1a4)
223 if lfd >= 0 {
224 sys_write(lfd, "WB-JS-CONFORMANCE harness=nx_js_conformance pass=" as *u8, 49)
225 let bb: *u8=sys_mmap(28); var m: i64=pass; var k: i64=0; if m==0{bb[0]=48;k=1}; while m>0{bb[k]=48+(m%10);m=m/10;k=k+1}; var z: i64=0; let rv: *u8=sys_mmap(28); while z<k{rv[z]=bb[k-1-z];z=z+1}; sys_write(lfd, rv, k)
226 sys_write(lfd, "/\x00" as *u8, 1)
227 let cc: *u8=sys_mmap(28); var m2: i64=tot; var k2: i64=0; if m2==0{cc[0]=48;k2=1}; while m2>0{cc[k2]=48+(m2%10);m2=m2/10;k2=k2+1}; var z2: i64=0; let rv2: *u8=sys_mmap(28); while z2<k2{rv2[z2]=cc[k2-1-z2];z2=z2+1}; sys_write(lfd, rv2, k2)
228 sys_write(lfd, " (measured, no-wave)\n" as *u8, 21)
229 sys_close(lfd)
230 }
231 sys_exit(0)
232 return 0
233}