code wiki / _hdl_build / nx_js_fetch_gate.nx
nx_js_fetch_gate.nx source
↩ module page · 63 lines · 4765 B
1import "nx_gate_gn.nx"
2import "nx_gate_base.nx"
3// nx_js_fetch_gate.nx -- proves the R-JS-FETCH rung: fetch() returns a Promise<Response>; a data: URL
4// resolves inline; Response has .status/.ok and .text() (a Promise); the SPA pattern
5// fetch(u).then(r=>r.text()).then(t=>...) hydrates; a non-data URL rejects -> .catch; JSON via
6// JSON.parse(text). Uses js_run_source_read (run -> drain -> read a global). 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, tag="); gn(out[0]); gw(")\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("')\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_fetch_gate: fetch() -> Promise<Response> -> .text()/.status ===\n" as *u8)
39 var pass: i64 = 0
40 var tot: i64 = 0
41 // T0 fetch(data:).then(r=>r.status) = 200
42 tot = tot + 1; pass = pass + gr_num("T0 fetch data: -> status 200" as *u8, "var x=0;fetch('data:,hi').then(function(r){x=r.status;});" as *u8, "x" as *u8, 200)
43 // T1 THE SPA PATTERN: fetch(u).then(r=>r.text()).then(t=>use t)
44 tot = tot + 1; pass = pass + gr_str("T1 fetch->text->then (SPA)" as *u8, "var log='';fetch('data:,hello').then(function(r){return r.text();}).then(function(t){log=t;});" as *u8, "log" as *u8, "hello" as *u8)
45 // T2 Response.ok is true for a 2xx
46 tot = tot + 1; pass = pass + gr_num("T2 response.ok on 200" as *u8, "var x=0;fetch('data:,y').then(function(r){if(r.ok){x=1;}});" as *u8, "x" as *u8, 1)
47 // T3 fetch is ASYNC (microtask): sync runs before the .then -> 'SF'
48 tot = tot + 1; pass = pass + gr_str("T3 sync before fetch.then = SF" as *u8, "var log='';fetch('data:,z').then(function(r){log=log+'F';});log=log+'S';" as *u8, "log" as *u8, "SF" as *u8)
49 // T4 a non-data URL PENDS (the pending-fetch model): without a consumer to service it, neither .then
50 // nor .catch fires in a single drain -> x stays its initial value. (nx_js_pending_fetch_gate proves the
51 // service->resolve->hydrate path.)
52 tot = tot + 1; pass = pass + gr_num("T4 http URL pends (no resolve w/o consumer)" as *u8, "var x=7;fetch('http://api/x').then(function(r){x=1;}).catch(function(e){x=2;});" as *u8, "x" as *u8, 7)
53 // T5 JSON via JSON.parse(text) -- body has a comma, proving data: takes everything after the FIRST comma
54 tot = tot + 1; pass = pass + gr_num("T5 fetch->text->JSON.parse" as *u8, "var x=0;fetch('data:,{\x22a\x22:1,\x22b\x22:2}').then(function(r){return r.text();}).then(function(t){x=JSON.parse(t).b;});" as *u8, "x" as *u8, 2)
55 // T6 LIAR-KILL: a resolved fetch must take .then, NOT .catch (x=1 from then, never 42 from catch)
56 tot = tot + 1; pass = pass + gr_num("T6 liar-kill (data: fulfils, not rejects)" as *u8, "var x=0;fetch('data:,ok').then(function(r){x=1;}).catch(function(e){x=42;});" as *u8, "x" as *u8, 1)
57 // T7 response.json() -> parsed object (the canonical fetch(u).then(r=>r.json()).then(data=>..) pattern)
58 tot = tot + 1; pass = pass + gr_num("T7 fetch->json()->obj" as *u8, "var x=0;fetch('data:,{\x22n\x22:5,\x22m\x22:9}').then(function(r){return r.json();}).then(function(j){x=j.m;});" as *u8, "x" as *u8, 9)
59
60 gw("=== "); gn(pass); gw("/"); gn(tot); gw(" "); if pass == tot { gw("GREEN ===\n" as *u8) } else { gw("RED ===\n" as *u8) }
61 if pass == tot { return 0 }
62 return 1
63}