code wiki / _hdl_build / nx_js_promise_gate.nx

nx_js_promise_gate.nx source

↩ module page · 65 lines · 4972 B

1import "nx_gate_gn.nx" 2import "nx_gate_base.nx" 3// nx_js_promise_gate.nx -- proves the R-JS-PROMISE rung: Promise.resolve/reject + .then/.catch execute 4// their callbacks with the settled value, CHAIN (then's return resolves the next), propagate REJECTION, 5// ADOPT a returned promise, and schedule as MICROtasks (so .then runs before setTimeout, after sync). 6// Uses js_run_source_read: run -> drain the event loop -> read a global -> assert. license_tier: ORIGINAL 7import "nx_js_eval.nx" 8 9func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 10" as *u8); return ok } 11func gsl(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 12 13func gr_str(label: *u8, src: *u8, rn: *u8, want: *u8) -> i64 { 14 let out: *i64 = sys_mmap(16) as *i64 15 let rc: i64 = js_run_source_read(src, gsl(src), rn, out) 16 gw(" "); gw(label); gw(": " as *u8) 17 if rc != 0 { gw("FAIL (eval rc=1)\n" as *u8); return 0 } 18 if out[0] != VAL_STR { gw("FAIL (not a string)\n" as *u8); return 0 } 19 let rec: *i64 = (out[1]) as *i64 20 let wl: i64 = gsl(want) 21 if ev_str_len(rec) != wl { gw("FAIL (len; got '" as *u8); sys_write(1, ev_str_bytes(rec), ev_str_len(rec)); gw("')\n" as *u8); return 0 } 22 let rb: *u8 = ev_str_bytes(rec) 23 var i: i64 = 0 24 while i < wl { if (rb[i] & 0xff) != (want[i] & 0xff) { gw("FAIL (got '" as *u8); sys_write(1, rb, wl); gw("' want '" as *u8); gw(want); gw("')\n" as *u8); return 0 } i = i + 1 } 25 gw("ok ('" as *u8); gw(want); gw("')\n" as *u8); return 1 26} 27func gr_num(label: *u8, src: *u8, rn: *u8, want: i64) -> i64 { 28 let out: *i64 = sys_mmap(16) as *i64 29 let rc: i64 = js_run_source_read(src, gsl(src), rn, out) 30 gw(" "); gw(label); gw(": " as *u8) 31 if rc != 0 { gw("FAIL (eval rc=1)\n" as *u8); return 0 } 32 if out[0] != VAL_NUM { gw("FAIL (not a number, tag="); gn(out[0]); gw(")\n" as *u8); return 0 } 33 if out[1] != want { gw("FAIL (got "); gn(out[1]); gw(" want "); gn(want); gw(")\n" as *u8); return 0 } 34 gw("ok ("); gn(want); gw(")\n" as *u8); return 1 35} 36 37func main(argc: i64, argv: *i64) -> i64 { 38 gw("=== nx_js_promise_gate: Promise resolve/reject/then/catch + microtask order ===\n" as *u8) 39 var pass: i64 = 0 40 var tot: i64 = 0 41 // T0 .then handler receives the resolved value. 42 tot = tot + 1; pass = pass + gr_num("T0 resolve.then(v) gets value" as *u8, "var x=0;Promise.resolve(7).then(function(v){x=v;});" as *u8, "x" as *u8, 7) 43 // T1 CHAINING: each .then's return resolves the next. 44 tot = tot + 1; pass = pass + gr_num("T1 chain then->then (+1)" as *u8, "var x=0;Promise.resolve(1).then(function(v){return v+1;}).then(function(v){x=v;});" as *u8, "x" as *u8, 2) 45 // T2 MICROTASK: synchronous code runs before the .then callback -> 'SP'. 46 tot = tot + 1; pass = pass + gr_str("T2 sync before then = SP" as *u8, "var log='';Promise.resolve(0).then(function(){log=log+'P';});log=log+'S';" as *u8, "log" as *u8, "SP" as *u8) 47 // T3 MICRO before MACRO: a .then runs before a setTimeout -> 'SPT'. 48 tot = tot + 1; pass = pass + gr_str("T3 then before setTimeout = SPT" as *u8, "var log='';setTimeout(function(){log=log+'T';},0);Promise.resolve(0).then(function(){log=log+'P';});log=log+'S';" as *u8, "log" as *u8, "SPT" as *u8) 49 // T4 .catch handles a rejection. 50 tot = tot + 1; pass = pass + gr_num("T4 reject.catch(e) gets reason" as *u8, "var x=0;Promise.reject(5).catch(function(e){x=e;});" as *u8, "x" as *u8, 5) 51 // T5 rejection PASSES THROUGH a .then with no onRejected -> the later .catch sees it. 52 tot = tot + 1; pass = pass + gr_num("T5 reject skips then, hits catch" as *u8, "var x=0;Promise.reject(9).then(function(v){x=1;}).catch(function(e){x=e;});" as *u8, "x" as *u8, 9) 53 // T6 ADOPTION: a .then that RETURNS a promise -> the next .then waits for it. 54 tot = tot + 1; pass = pass + gr_num("T6 then returns a promise (adopt)" as *u8, "var x=0;Promise.resolve(1).then(function(v){return Promise.resolve(v+10);}).then(function(v){x=v;});" as *u8, "x" as *u8, 11) 55 // T7 then(onF,onR): on rejection onF is SKIPPED, onR runs. 56 tot = tot + 1; pass = pass + gr_num("T7 then(onF,onR) picks onR" as *u8, "var x=0;Promise.reject(3).then(function(v){x=100;},function(e){x=e;});" as *u8, "x" as *u8, 3) 57 // T8 two .then on the SAME promise both fire. 58 tot = tot + 1; pass = pass + gr_num("T8 two then on one promise" as *u8, "var s=0;var p=Promise.resolve(5);p.then(function(v){s=s+v;});p.then(function(v){s=s+v;});" as *u8, "s" as *u8, 10) 59 // T9 LIAR-KILL: a fulfill handler must NOT run on a rejected promise (x stays 0). 60 tot = tot + 1; pass = pass + gr_num("T9 liar-kill (onF skipped on reject)" as *u8, "var x=0;Promise.reject(1).then(function(v){x=42;});" as *u8, "x" as *u8, 0) 61 62 gw("=== "); gn(pass); gw("/"); gn(tot); gw(" "); if pass == tot { gw("GREEN ===\n" as *u8) } else { gw("RED ===\n" as *u8) } 63 if pass == tot { return 0 } 64 return 1 65}