code wiki / _hdl_build / nx_table_cell_gate.nx

nx_table_cell_gate.nx source

↩ module page · 155 lines · 8743 B

1// nx_table_cell_gate.nx -- VERDICT gate for TABLE CELL containment: <td>/<th> are BLOCK containers 2// (display:table-cell), NOT inline. Before the fix they defaulted to inline, so a cell's block children 3// flattened out (became flex siblings), the cell collapsed to h=0, and the table height was wrong (the 4// Wikipedia infobox overlap). This gate builds a 2-row table whose cells contain block <div>s and asserts: 5// each cell has NON-ZERO height, each cell CONTAINS its div (div.x within the cell), and the table height 6// == sum of its rows (no collapse). LIAR-KILL: a wrong expectation is rejected. 100% sovereign. 7// license_tier: ORIGINAL 8import "nx_syscalls.nx" 9import "nx_css_tokenize.nx" 10import "nx_css_parse.nx" 11import "nx_css_apply.nx" 12import "nx_css_color_decode.nx" 13import "nx_css_dimension_to_px.nx" 14import "nx_css_selector_match.nx" 15import "nx_html_tokenizer.nx" 16import "nx_dom_query.nx" 17import "nx_layout_box.nx" 18import "nx_layout_default_display.nx" 19import "nx_layout_from_dom.nx" 20import "nx_layout_block.nx" 21import "nx_render_html.nx" 22 23func g_w(s: *u8) -> i64 { var k: i64=0; while s[k]!=(0 as u8){k=k+1} sys_write(1,s,k); return 0 } 24func pn(v0: i64) -> i64 { var v: i64=v0; if v<0 { let m: *u8=sys_mmap(8); m[0]=45 as u8; sys_write(1,m,1); v=0-v } let b: *u8=sys_mmap(24); var k: i64=0; if v==0 {b[0]=48;k=1} while v>0 {b[k]=(48+(v%10)) as u8; v=v/10; k=k+1} let o: *u8=sys_mmap(24); var j: i64=0; while j<k {o[j]=b[k-1-j];j=j+1} sys_write(1,o,k); return 0 } 25 26func run_layout(html: *u8, css: *u8, vw: i64, tree_out: **LayoutTree, boxel_out: **CssElement, buf_out: **u8) -> i64 { 27 var hlen: i64 = 0 28 while html[hlen]!=(0 as u8) { hlen=hlen+1 } 29 var clen: i64 = 0 30 while css[clen]!=(0 as u8) { clen=clen+1 } 31 let total: i64 = hlen + clen 32 let buf: *u8 = sys_mmap(total + 16) 33 var i: i64 = 0 34 while i < hlen { buf[i]=html[i]; i=i+1 } 35 var j: i64 = 0 36 while j < clen { buf[hlen+j]=css[j]; j=j+1 } 37 38 let boxes: *LayoutBox = (sys_mmap(NX_LAYOUT_BOX_BYTES*1024+16)) as *LayoutBox 39 let tree: *LayoutTree = (sys_mmap(64)) as *LayoutTree 40 nx_layout_tree_init(tree, boxes, 1024) 41 let stk: *LayoutFromDomStack = (sys_mmap(NX_LAYOUT_FROM_DOM_STACK_BYTES+8)) as *LayoutFromDomStack 42 let sidx: *i64 = (sys_mmap(8*64)) as *i64 43 nx_layout_from_dom_stack_init(stk, sidx, 64) 44 nx_layout_from_dom(buf, hlen, tree, stk) 45 46 let ext: *CssElement = (sys_mmap(NX_CSS_ELEMENT_BYTES*1024 as nx_size)) as *CssElement 47 let n_ext: i64 = rh_extract(buf, hlen, ext, 1024) 48 let boxel: *CssElement = (sys_mmap((NX_CSS_ELEMENT_BYTES*(tree.count+1)) as nx_size)) as *CssElement 49 var k: i64 = 0 50 i = 0 51 while i < tree.count { 52 let bb: *LayoutBox = ((tree.boxes as i64)+i*NX_LAYOUT_BOX_BYTES) as *LayoutBox 53 let e: *CssElement = ((boxel as i64)+i*NX_CSS_ELEMENT_BYTES) as *CssElement 54 e.src = buf 55 var mapped: i64 = 0 56 if rh_is_elem(bb.kind)==1 { if bb.parent_idx != (0-1) { if k < n_ext { 57 let s: *CssElement = ((ext as i64)+k*NX_CSS_ELEMENT_BYTES) as *CssElement 58 e.tag_off=s.tag_off; e.tag_len=s.tag_len; e.id_off=s.id_off; e.id_len=s.id_len; e.class_off=s.class_off; e.class_len=s.class_len 59 k=k+1; mapped=1 60 } } } 61 if mapped==0 { e.tag_off=0; e.tag_len=0; e.id_off=0; e.id_len=0; e.class_off=0; e.class_len=0 } 62 i=i+1 63 } 64 65 let cur: *CssCursor = (sys_mmap(NX_CSS_CURSOR_BYTES) as nx_size) as *CssCursor 66 nx_css_cursor_init(cur, buf, total); cur.pos = hlen 67 let tok: *CssToken = (sys_mmap(NX_CSS_TOKEN_BYTES) as nx_size) as *CssToken 68 let rules: *CssRule = (sys_mmap(NX_CSS_RULE_BYTES*512 as nx_size)) as *CssRule 69 let decls: *CssDeclaration = (sys_mmap(NX_CSS_DECLARATION_BYTES*512 as nx_size)) as *CssDeclaration 70 let st: *CssParseState = (sys_mmap(128) as nx_size) as *CssParseState 71 nx_css_parse_state_init(st, cur, tok, rules, 512, decls, 512) 72 nx_css_parse(st) 73 let computed: *CssComputedDecl = (sys_mmap(NX_CSS_COMPUTED_DECL_BYTES*4096 as nx_size)) as *CssComputedDecl 74 let cb: *i64 = (sys_mmap(8)) as *i64 75 rh_cascade(buf, rules, st.rule_count, decls, st.decl_count, boxel, tree.count, tree, computed, 4096, cb) 76 let ncomp: i64 = cb[0] 77 78 let pbuf: *u8 = sys_mmap(256) 79 let ltable: *LayoutPropTable = (sys_mmap(NX_LAYOUT_PROP_TABLE_BYTES)) as *LayoutPropTable 80 nx_layout_prop_table_init(ltable, pbuf) 81 let resolve: *CssResolveCtx = (sys_mmap(NX_CSS_RESOLVE_CTX_BYTES)) as *CssResolveCtx 82 resolve.root_font_size_px = 16; resolve.parent_font_size_px = 16; resolve.parent_dimension_px = vw 83 let lctx: *LayoutCtx = (sys_mmap(NX_LAYOUT_CTX_BYTES)) as *LayoutCtx 84 nx_layout_ctx_init(lctx, tree, computed, ncomp, buf, vw, resolve) 85 nx_layout_block_layout(lctx, ltable, 0) 86 tree_out[0] = tree 87 boxel_out[0] = boxel 88 buf_out[0] = buf 89 return 0 90} 91 92// find the i-th (0-based) box whose mapped element tag == `tag` (NUL-term, lowercase). -1 if not found. 93func find_tag(tree: *LayoutTree, boxel: *CssElement, buf: *u8, tag: *u8, nth: i64) -> i64 { 94 var tl: i64 = 0 95 while tag[tl]!=(0 as u8) { tl=tl+1 } 96 var seen: i64 = 0 97 var i: i64 = 0 98 while i < tree.count { 99 let e: *CssElement = ((boxel as i64)+i*NX_CSS_ELEMENT_BYTES) as *CssElement 100 if e.tag_len == tl { 101 var ok: i64 = 1 102 var j: i64 = 0 103 while j < tl { if (buf[e.tag_off+j]&0xff) != (tag[j]&0xff) { ok=0; j=tl } else { j=j+1 } } 104 if ok==1 { if seen==nth { return i } seen=seen+1 } 105 } 106 i = i + 1 107 } 108 return 0 - 1 109} 110func box_at(tree: *LayoutTree, i: i64) -> *LayoutBox { return ((tree.boxes as i64)+i*NX_LAYOUT_BOX_BYTES) as *LayoutBox } 111func chk(cond: i64, label: *u8, pass: *i64) -> i64 { 112 g_w(" " as *u8); g_w(label); g_w(": " as *u8) 113 if cond==1 { g_w("OK\n" as *u8); pass[0]=pass[0]+1 } else { g_w("FAIL\n" as *u8) } 114 return cond 115} 116 117func main() -> i64 { 118 let pass: *i64 = sys_mmap(8) as *i64; pass[0]=0 119 g_w("=== TABLE-CELL GATE (td/th block containment, sovereign nx_cc->nxasm) ===\n" as *u8) 120 121 // 2-row table; each cell holds a BLOCK <div> with text. With td as block, each cell sizes to its div. 122 let tp: **LayoutTree = sys_mmap(8) as **LayoutTree 123 let bp: **CssElement = sys_mmap(8) as **CssElement 124 let up: **u8 = sys_mmap(8) as **u8 125 run_layout("<table><tr><td><div>Row one cell</div></td></tr><tr><td><div>Row two cell</div></td></tr></table>\x00" as *u8, 126 "td{padding-left:4px}\x00" as *u8, 800, tp, bp, up) 127 let tree: *LayoutTree = tp[0]; let boxel: *CssElement = bp[0]; let buf: *u8 = up[0] 128 129 let ti: i64 = find_tag(tree, boxel, buf, "table\x00" as *u8, 0) 130 let td0: i64 = find_tag(tree, boxel, buf, "td\x00" as *u8, 0) 131 let td1: i64 = find_tag(tree, boxel, buf, "td\x00" as *u8, 1) 132 let dv0: i64 = find_tag(tree, boxel, buf, "div\x00" as *u8, 0) 133 g_w(" found table=\x00" as *u8); pn(ti); g_w(" td0=\x00" as *u8); pn(td0); g_w(" td1=\x00" as *u8); pn(td1); g_w(" div0=\x00" as *u8); pn(dv0); g_w("\n" as *u8) 134 chk((ti>=0) as i64 * ((td0>=0) as i64) * ((td1>=0) as i64) * ((dv0>=0) as i64), "table + 2 td + div all present\x00" as *u8, pass) 135 if ti<0 { g_w("TABLE-CELL rows=6 pass=\x00" as *u8); pn(pass[0]); g_w(" verdict=RED\n\x00" as *u8); sys_exit(1); return 1 } 136 137 let tb: *LayoutBox = box_at(tree, ti) 138 let c0: *LayoutBox = box_at(tree, td0) 139 let c1: *LayoutBox = box_at(tree, td1) 140 let d0: *LayoutBox = box_at(tree, dv0) 141 g_w(" table h=\x00" as *u8); pn(tb.h); g_w(" td0(y=\x00" as *u8); pn(c0.y); g_w(" h=\x00" as *u8); pn(c0.h); g_w(") td1(y=\x00" as *u8); pn(c1.y); g_w(" h=\x00" as *u8); pn(c1.h); g_w(") div0(x=\x00" as *u8); pn(d0.x); g_w(" y=\x00" as *u8); pn(d0.y); g_w(")\n" as *u8) 142 143 // THE FIX: cells have NON-ZERO height (they contain their block div). Before fix td was inline -> h=0. 144 chk((c0.h > 0) as i64, "td0 has NON-ZERO height (cell contains its div)\x00" as *u8, pass) 145 chk((c1.h > 0) as i64, "td1 has NON-ZERO height\x00" as *u8, pass) 146 // div is INSIDE its cell (x at/after the cell origin, y within the cell's row) -- proper nesting 147 chk(((d0.x >= c0.x) as i64) * ((d0.y >= c0.y) as i64), "div0 nested INSIDE td0 (x,y within cell)\x00" as *u8, pass) 148 // row 2 is BELOW row 1 (cells don't collapse onto each other) and table height contains both 149 chk((c1.y >= c0.y + c0.h) as i64, "row2 cell BELOW row1 cell (no collapse)\x00" as *u8, pass) 150 chk((tb.h >= c0.h + c1.h) as i64, "table height contains both rows\x00" as *u8, pass) 151 152 g_w("TABLE-CELL rows=6 pass=\x00" as *u8); pn(pass[0]) 153 if pass[0]==6 { g_w(" verdict=GREEN\n\x00" as *u8); sys_exit(0); return 0 } 154 g_w(" verdict=RED\n\x00" as *u8); sys_exit(1); return 1 155}