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}