code wiki / (root) / nx_layout_example_com_real_test.nx

nx_layout_example_com_real_test.nx source

↩ module page · 229 lines · 9234 B

1// nx_layout_example_com_real_test.nx -- lay out the REAL example.com 2// HTML page (528 bytes) fetched through bits-up TLS 1.3 + cert chain 3// + chunked-transfer dechunk. 4// 5// Reads /tmp/example_com.html (dropped by nx_https_get_live_real_ca), 6// streams it through nx_layout_from_dom, and reports the resulting 7// LayoutBox tree shape: count, max depth, presence of canonical 8// nodes (html/head/body/h1/p/a). Does NOT yet compute geometry -- 9// the goal here is to prove the substrate's HTML→DOM→layout-tree 10// path consumes a real-world page without segfaulting or stalling. 11// 12// expect_exit: 0. 13// license_tier: ORIGINAL 14 15import "nx_syscalls.nx" 16import "nx_layout_box.nx" 17import "nx_layout_from_dom.nx" 18import "nx_layout_block.nx" 19import "nx_css_apply.nx" 20 21func dump_dec(l0: i64, l1: i64, v: i64) -> i64 { 22 let lab: *u8 = sys_mmap(8) 23 lab[0]=l0 as u8; lab[1]=l1 as u8; lab[2]=0x3D 24 sys_write(2, lab, 3) 25 var av: i64 = v 26 if av < 0 { 27 let neg: *u8 = sys_mmap(8); neg[0]=0x2D; sys_write(2, neg, 1) 28 av = 0 - av 29 } 30 let buf: *u8 = sys_mmap(16) 31 var pos: i64 = 0 32 if av == 0 { buf[0]=0x30; pos = 1 } 33 var x: i64 = av 34 while x > 0 { 35 buf[pos] = (0x30 + (x % 10)) as u8 36 x = x / 10; pos = pos + 1 37 } 38 let out: *u8 = sys_mmap(16); var oi: i64 = 0 39 while oi < pos { out[oi] = buf[pos - 1 - oi]; oi = oi + 1 } 40 sys_write(2, out, pos) 41 let nl: *u8 = sys_mmap(8); nl[0]=0x0A; sys_write(2, nl, 1) 42 return 0 43} 44 45// Walk the tree DFS, reporting max depth. 46func max_depth(tree: *LayoutTree, idx: i64, d: i64) -> i64 { 47 if idx < 0 { return d } 48 let b: *LayoutBox = ((tree.boxes as i64) + idx * NX_LAYOUT_BOX_BYTES) as *LayoutBox 49 var best: i64 = d 50 var child: i64 = b.first_child_idx 51 while child >= 0 { 52 let dc: i64 = max_depth(tree, child, d + 1) 53 if dc > best { best = dc } 54 let cb: *LayoutBox = ((tree.boxes as i64) + child * NX_LAYOUT_BOX_BYTES) as *LayoutBox 55 child = cb.next_sibling_idx 56 } 57 return best 58} 59 60func main() -> i64 { 61 let path: *u8 = "/tmp/example_com.html\x00" 62 let len_p: *i64 = sys_mmap(16) as *i64 63 let html: *u8 = sys_read_file(path, len_p) 64 let html_len: i64 = *len_p 65 if html_len <= 0 { return 1 } 66 dump_dec(0x48, 0x4C, html_len) // "HL=" html length 67 68 // Allocate LayoutTree + LayoutBox arena 69 let boxes: *LayoutBox = (sys_mmap(NX_LAYOUT_BOX_BYTES * 512 + 16)) as *LayoutBox 70 let tree_raw: *u8 = sys_mmap(64) 71 let tree: *LayoutTree = tree_raw as *LayoutTree 72 nx_layout_tree_init(tree, boxes, 512) 73 74 // Stack arena (depth 64) 75 let stack_raw: *u8 = sys_mmap(NX_LAYOUT_FROM_DOM_STACK_BYTES + 8) 76 let stk: *LayoutFromDomStack = stack_raw as *LayoutFromDomStack 77 let stk_indices: *i64 = (sys_mmap(8 * 64)) as *i64 78 nx_layout_from_dom_stack_init(stk, stk_indices, 64) 79 80 let rc: i64 = nx_layout_from_dom(html, html_len, tree, stk) 81 dump_dec(0x52, 0x43, rc) // "RC=" build verdict 82 if rc != 0 { return 2 } 83 84 dump_dec(0x4E, 0x42, tree.count) // "NB=" box count 85 86 let depth: i64 = max_depth(tree, 0, 0) 87 dump_dec(0x44, 0x50, depth) // "DP=" max depth 88 89 // Box-kind histogram: BLOCK / INLINE / TEXT 90 var blocks: i64 = 0 91 var inlines: i64 = 0 92 var texts: i64 = 0 93 var anons: i64 = 0 94 var i: i64 = 0 95 while i < tree.count { 96 let b: *LayoutBox = ((tree.boxes as i64) + i * NX_LAYOUT_BOX_BYTES) as *LayoutBox 97 if b.kind == NX_LAYOUT_BOX_BLOCK { blocks = blocks + 1 } 98 if b.kind == NX_LAYOUT_BOX_INLINE { inlines = inlines + 1 } 99 if b.kind == NX_LAYOUT_BOX_TEXT { texts = texts + 1 } 100 if b.kind == NX_LAYOUT_BOX_ANONYMOUS { anons = anons + 1 } 101 i = i + 1 102 } 103 dump_dec(0x42, 0x4C, blocks) // "BL=" blocks 104 dump_dec(0x49, 0x4E, inlines) // "IN=" inlines 105 dump_dec(0x54, 0x58, texts) // "TX=" texts 106 dump_dec(0x41, 0x4E, anons) // "AN=" anonymous 107 108 // ---- Run nx_layout_block with EMPTY cascade ----------------------- 109 // Goal: prove default block-flow layout computes valid pixel 110 // geometry for every box. No CSS rules => every block fills 111 // viewport width; heights stack via normal flow. Real CSS 112 // cascade integration is a separate arc. 113 let prop_buf: *u8 = sys_mmap(256) 114 let table: *LayoutPropTable = (sys_mmap(NX_LAYOUT_PROP_TABLE_BYTES)) as *LayoutPropTable 115 nx_layout_prop_table_init(table, prop_buf) 116 117 let resolve: *CssResolveCtx = (sys_mmap(NX_CSS_RESOLVE_CTX_BYTES)) as *CssResolveCtx 118 resolve.root_font_size_px = 16 119 resolve.parent_font_size_px = 16 120 resolve.parent_dimension_px = 800 121 122 let ctx: *LayoutCtx = (sys_mmap(NX_LAYOUT_CTX_BYTES)) as *LayoutCtx 123 nx_layout_ctx_init(ctx, tree, 0 as *CssComputedDecl, 0, html, 800, resolve) 124 125 let outer_h: i64 = nx_layout_block_layout(ctx, table, 0) 126 dump_dec(0x4F, 0x48, outer_h) // "OH=" outer height of root 127 128 // ---- Tree dump: one line per box -------------------------------- 129 // Format: IDX:PAR:KIND e.g. " 0:-1:BLOCK" 130 // Kind printed as a short tag (BL/IN/TX/AN/UN). 131 sys_write(1, "---- tree dump (idx:parent:kind) ----\n" as *u8, 38) 132 i = 0 133 while i < tree.count { 134 let b: *LayoutBox = ((tree.boxes as i64) + i * NX_LAYOUT_BOX_BYTES) as *LayoutBox 135 // idx (3-digit decimal) 136 let line: *u8 = sys_mmap(32) 137 line[0] = (0x30 + ((i / 100) % 10)) as u8 138 line[1] = (0x30 + ((i / 10) % 10)) as u8 139 line[2] = (0x30 + (i % 10)) as u8 140 line[3] = 0x3A 141 // parent (i64; print sign + up to 3 digits) 142 var par: i64 = b.parent_idx 143 var pi: i64 = 4 144 if par < 0 { 145 line[pi] = 0x2D 146 pi = pi + 1 147 par = 0 - par 148 } 149 line[pi] = (0x30 + ((par / 100) % 10)) as u8 150 line[pi + 1] = (0x30 + ((par / 10) % 10)) as u8 151 line[pi + 2] = (0x30 + (par % 10)) as u8 152 line[pi + 3] = 0x3A 153 pi = pi + 4 154 if b.kind == NX_LAYOUT_BOX_BLOCK { line[pi]=0x42; line[pi+1]=0x4C } // BL 155 if b.kind == NX_LAYOUT_BOX_INLINE { line[pi]=0x49; line[pi+1]=0x4E } // IN 156 if b.kind == NX_LAYOUT_BOX_TEXT { line[pi]=0x54; line[pi+1]=0x58 } // TX 157 if b.kind == NX_LAYOUT_BOX_ANONYMOUS { line[pi]=0x41; line[pi+1]=0x4E } // AN 158 if b.kind == NX_LAYOUT_BOX_UNKNOWN { line[pi]=0x55; line[pi+1]=0x4E } // UN 159 if b.kind == NX_LAYOUT_BOX_INLINE_BLOCK { line[pi]=0x49; line[pi+1]=0x42 } // IB 160 sys_write(1, line, pi + 2) 161 162 // x,y,w,h pixel geometry (computed by nx_layout_block_layout) 163 sys_write(1, " [" as *u8, 3) 164 let geo_buf: *u8 = sys_mmap(64) 165 var gp: i64 = 0 166 var coords: i64 = 0 167 while coords < 4 { 168 var val: i64 = b.x 169 if coords == 1 { val = b.y } 170 if coords == 2 { val = b.w } 171 if coords == 3 { val = b.h } 172 if val < 0 { geo_buf[gp] = 0x2D; gp = gp + 1; val = 0 - val } 173 // up to 4 decimal digits 174 if val == 0 { 175 geo_buf[gp] = 0x30; gp = gp + 1 176 } else { 177 let digits: *u8 = sys_mmap(8) 178 var dn: i64 = 0 179 while val > 0 { 180 digits[dn] = (0x30 + (val % 10)) as u8 181 val = val / 10 182 dn = dn + 1 183 } 184 while dn > 0 { 185 dn = dn - 1 186 geo_buf[gp] = digits[dn] 187 gp = gp + 1 188 } 189 } 190 if coords < 3 { geo_buf[gp] = 0x2C; gp = gp + 1 } 191 coords = coords + 1 192 } 193 geo_buf[gp] = 0x5D 194 gp = gp + 1 195 sys_write(1, geo_buf, gp) 196 197 // For TEXT boxes, print the actual text content after the kind tag. 198 if b.kind == NX_LAYOUT_BOX_TEXT { 199 if b.text_len > 0 { 200 sys_write(1, " '" as *u8, 3) 201 // Trim leading whitespace + newlines for readability. 202 var ts: i64 = 0 203 var stop: i64 = 0 204 while stop == 0 { 205 if ts >= b.text_len { stop = 1 } 206 else { 207 let ch: i64 = html[b.text_off + ts] & 0xff 208 if ch == 0x20 { ts = ts + 1 } 209 else { if ch == 0x0A { ts = ts + 1 } 210 else { if ch == 0x09 { ts = ts + 1 } 211 else { stop = 1 }}} 212 } 213 } 214 let show_len: i64 = b.text_len - ts 215 var cap: i64 = show_len 216 if cap > 60 { cap = 60 } 217 if cap > 0 { sys_write(1, html + b.text_off + ts, cap) } 218 sys_write(1, "'" as *u8, 1) 219 } 220 } 221 sys_write(1, "\n" as *u8, 1) 222 i = i + 1 223 } 224 225 let ok: *u8 = sys_mmap(8) 226 ok[0]=0x4F; ok[1]=0x4B; ok[2]=0x21; ok[3]=0x0A // "OK!\n" 227 sys_write(1, ok, 4) 228 return 0 229}