nx_domtree.nx
buildroot/runtime/nx_domtree.nx
about
nx_domtree.nx -- a MATERIALIZED, MUTABLE DOM tree for the sovereign browser.
The JS engine's existing DOM is a READ-ONLY byte snapshot (nx_js_eval: genv[2]=html ptr,
queries re-scan the bytes). To RENDER JS-built content, page scripts must MUTATE the DOM and
have the result laid out. This organ is that missing piece: parse HTML -> a node arena (REUSING
nx_html_tokenizer, no duplicate parser), MUTATE it (createElement/appendChild/textContent=/
setAttribute), and SERIALIZE it back to HTML for nx_layout. Rung A of general JS rendering.
module: nx_domtree capability: mutable-dom
Sovereign: imports only nx_syscalls + the gated nx_html_tokenizer. No gcc/V8/libxml. ORIGINAL.
dependencies 2 imports · 4 importers
imports: nx_syscalls.nxnx_html_tokenizer.nx
imported by: nx_domtree_gate.nxnx_dtparse_bench.nxnx_dtroundtrip_bench.nxnx_js_eval.nx
structs
| 23 | struct DomNode |
| 37 | struct DtAttr |
| 41 | struct DomTree |
consts
| 12 | const DT_MAGIC_4096: i64 = 4096 |
| 13 | const DT_MAGIC_65536: i64 = 65536 |
| 15 | const DT_ELEM: i64 = 1 |
| 16 | const DT_TEXT: i64 = 2 |
| 17 | const DT_DOC: i64 = 3 |
| 18 | const DT_NODE_BYTES: i64 = 96 // 12 i64 fields |
| 19 | const DT_ATTR_BYTES: i64 = 16 // 2 i64 fields |
| 20 | const DT_ATTR_CAP: i64 = 32 // max attrs per element (rung-A bound) |
| 21 | const DT_MAX_NODES: i64 = 131072 // node arena capacity (mmap lazy zero-fill) |
functions
| 49 | func dt_clen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } |
| 51 | func dt_ceq(a: *u8, b: *u8) -> i64 |
| 63 | func dt_dup(src: *u8, off: i64, len: i64) -> i64 called by 5: dt_dup_cdt_create_textdt_clone_subtreedt_set_attr_spandt_sel_compound calls 1: sys_mmap |
| 73 | func dt_dup_lower(src: *u8, off: i64, len: i64) -> i64 called by 5: dt_dup_lower_cdt_create_element_spandt_set_attr_spandt_sel_compounddt_parse_into calls 1: sys_mmap |
| 87 | func dt_dup_c(s: *u8) -> i64 { return dt_dup(s, 0, dt_clen(s)) } |
| 88 | func dt_dup_lower_c(s: *u8) -> i64 { return dt_dup_lower(s, 0, dt_clen(s)) } |
| 91 | func dt_node(t: *DomTree, idx: i64) -> *DomNode |
| 94 | func dt_alloc(t: *DomTree, kind: i64) -> i64 |
| 112 | func dt_new() -> *DomTree |
| 122 | func dt_is_void(tag: *u8) -> i64 |
| 140 | func dt_create_element_span(t: *DomTree, src: *u8, off: i64, len: i64) -> i64 |
| 147 | func dt_create_element(t: *DomTree, tagc: *u8) -> i64 |
| 150 | func dt_create_text(t: *DomTree, src: *u8, off: i64, len: i64) -> i64 |
| 160 | func dt_append_child(t: *DomTree, parent: i64, child: i64) -> i64 |
| 177 | func dt_remove_child(t: *DomTree, parent: i64, child: i64) -> i64 calls 1: dt_node |
| 206 | func dt_clone_subtree(t: *DomTree, src: i64) -> i64 |
| 243 | func dt_attr_at(base: *DtAttr, i: i64) -> *DtAttr |
| 247 | func dt_set_attr_span(t: *DomTree, node: i64, nsrc: *u8, noff: i64, nlen: i64, vsrc: *u8, voff: i64, vlen: i64) -> i64 |
| 271 | func dt_set_attr(t: *DomTree, node: i64, namec: *u8, valc: *u8) -> i64 |
| 275 | func dt_get_attr(t: *DomTree, node: i64, namec: *u8) -> *u8 called by 4: dt_gebi_recdt_has_classdt_sel_matchdt_sel_compound calls 4: dt_nodedt_dup_lower_cdt_attr_atdt_ceq |
| 290 | func dt_set_text_content(t: *DomTree, node: i64, src: *u8, off: i64, len: i64) -> i64 |
| 304 | func dt_gebi_rec(t: *DomTree, idx: i64, idc: *u8) -> i64 |
| 320 | func dt_get_element_by_id(t: *DomTree, idc: *u8) -> i64 { return dt_gebi_rec(t, t.root, idc) } |
| 322 | func dt_fbt_rec(t: *DomTree, idx: i64, tagc: *u8) -> i64 |
| 335 | func dt_first_by_tag(t: *DomTree, tagc: *u8) -> i64 { return dt_fbt_rec(t, t.root, tagc) } |
| 338 | func dt_has_class(t: *DomTree, node: i64, cls: *u8) -> i64 |
| 359 | func dt_sel_match(t: *DomTree, node: i64, mode: i64, name: *u8) -> i64 |
| 371 | func dt_cstr_contains(hay: *u8, needle: *u8) -> i64 |
| 383 | func dt_cstr_prefix(hay: *u8, needle: *u8) -> i64 |
| 390 | func dt_cstr_suffix(hay: *u8, needle: *u8) -> i64 |
| 398 | func dt_attr_op(val: *u8, op: i64, want: *u8) -> i64 |
| 419 | func dt_sel_compound(t: *DomTree, node: i64, sel: *u8, a: i64, b: i64, scope_root: i64) -> i64 |
| 497 | func dt_sel_complex(t: *DomTree, node: i64, sel: *u8, a0: i64, b0: i64, scope_root: i64) -> i64 |
| 532 | func dt_sel_matches(t: *DomTree, node: i64, sel: *u8, slen: i64, scope_root: i64) -> i64 |
| 549 | func dt_sel_query_rec(t: *DomTree, idx: i64, sel: *u8, slen: i64, arr: *i64, cnt: *i64, cap: i64, scope_root: i64) -> i64 |
| 559 | func dt_sel_query(t: *DomTree, root: i64, sel: *u8, slen: i64, arr: *i64, cap: i64) -> i64 |
| 567 | func dt_query_one_rec(t: *DomTree, idx: i64, mode: i64, name: *u8) -> i64 |
| 580 | func dt_query_one(t: *DomTree, mode: i64, name: *u8) -> i64 { return dt_query_one_rec(t, t.root, mode, name) } calls 1: dt_query_one_rec |
| 581 | func dt_query_all_rec(t: *DomTree, idx: i64, mode: i64, name: *u8, arr: *i64, cnt: *i64, cap: i64) -> i64 |
| 593 | func dt_query_all(t: *DomTree, mode: i64, name: *u8, arr: *i64, cap: i64) -> i64 |
| 601 | func dt_tc_rec(t: *DomTree, idx: i64, out: *u8, cap: i64, posp: *i64) -> i64 |
| 618 | func dt_text_content(t: *DomTree, node: i64, out: *u8, cap: i64) -> i64 |
| 626 | func dt_is_name(b: i64) -> i64 called by 1: dt_parse_attrs |
| 635 | func dt_is_ws(b: i64) -> i64 called by 1: dt_parse_attrs |
| 643 | func dt_parse_attrs(t: *DomTree, node: i64, src: *u8, soff: i64, slen: i64) -> i64 |
| 676 | func dt_find_ci(buf: *u8, from: i64, hlen: i64, needle: *u8, nlen: i64) -> i64 called by 1: dt_parse_into |
| 695 | func dt_is_rawtext(tag: *u8) -> i64 |
| 700 | func dt_rawclose(tag: *u8) -> *u8 |
| 705 | func dt_parse_into(t: *DomTree, start: i64, html: *u8, hlen: i64) -> i64 |
| 767 | func dt_parse(html: *u8, hlen: i64) -> *DomTree |
| 773 | func dt_set_inner_html(t: *DomTree, node: i64, html: *u8, hlen: i64) -> i64 |
| 782 | func dt_app(out: *u8, cap: i64, posp: *i64, s: *u8, n: i64) -> i64 |
| 789 | func dt_app_c(out: *u8, cap: i64, posp: *i64, c: *u8) -> i64 |
| 793 | func dt_ser_rec(t: *DomTree, idx: i64, out: *u8, cap: i64, posp: *i64) -> i64 |
| 835 | func dt_serialize(t: *DomTree, out: *u8, cap: i64) -> i64 |