# VDOM Debug Helpers The `commontools.vdom` object provides browser console helpers for inspecting the VDOM tree structure, applicator state, and DOM node mappings. These are useful when debugging rendering issues — wrong/missing content, stale updates, or broken reactivity. ## Quick Start Open the browser console on any page with a rendered pattern: ```javascript commontools.vdom.renders() // list active renderings await commontools.vdom.dump() // pretty-print the VDOM tree commontools.vdom.stats() // node/listener counts await commontools.vdom.tree() // raw tree object for inspection ``` ## Methods ### `renders()` Lists all active renderings in a `console.table` with: - **index** — position in the registry - **container** — the DOM element being rendered into - **cellId** — the cell ID backing this render - **path** — `"worker"` (VDomRenderer) or `"legacy"` (main-thread) - **renderer** — `"VDomRenderer"` or `"(legacy)"` ### `tree(el?)` (async) Reads the VDOM cell using the **debug schema** and returns the raw tree object. Children are expanded inline (not wrapped in CellHandles), so you can browse the full tree structure in one shot. Props remain as CellHandles since prop values can be large. The optional `el` argument can be: - omitted — uses the first/only active render - a number — index into the active renders list - an HTMLElement — the specific container element ### `dump(el?)` (async) Pretty-prints the VDOM tree to the console. Output looks like: ```
>

"Hello World"

> "count: 42"
``` - CellHandle props are shown as `` - String children are quoted - Self-closing tags for childless elements ### `stats()` Shows a `console.table` of node and listener counts per active renderer. Only meaningful for the worker path — legacy renders show `"(legacy)"`. - **nodeCount** — number of DOM nodes tracked by the applicator - **listenerCount** — number of nodes with event listeners - **totalListeners** — total event listener count across all nodes - **rootNodeId** — the applicator's root node ID ### `nodeForId(id, el?)` Looks up a DOM node by its internal applicator node ID. Only works for worker-path renders (the applicator tracks node IDs). ```javascript const node = commontools.vdom.nodeForId(1) // Returns the DOM element, or undefined ``` ### `registry` (getter) Raw access to the `Map` for advanced inspection. ```javascript commontools.vdom.registry // Map(1) { div#app => { parent, cell, renderer, path } } ``` ## The Debug Schema The key difference between the normal rendering schema and the debug schema is how children are handled: | | Normal (`rendererVDOMSchema`) | Debug (`debugVDOMSchema`) | |---|---|---| | **Children** | Each child wrapped in `asCell` (separate reactive subscription) | No `asCell` — children expand inline | | **Props** | `asCell` on each prop value | `asCell` on each prop value (unchanged) | The normal schema uses `asCell` on children for performance — each child becomes an independent reactive subscription, so only changed subtrees re-render. The debug schema removes this so you can read the entire tree structure in one `.get()` call, which is what you want when inspecting structure from the console. Props keep `asCell` because prop values can be arbitrarily large (style objects, data attributes) and aren't needed for structural debugging. ## Common Debugging Scenarios ### Stale render / content not updating ```javascript // Check if the render is active commontools.vdom.renders() // Dump the tree to see current VDOM state await commontools.vdom.dump() // Compare with what's in the DOM commontools.vdom.nodeForId(1) // look up specific nodes ``` ### Missing children ```javascript // Get the raw tree and inspect children arrays const tree = await commontools.vdom.tree() console.log(tree.children) // are children present in the VDOM? ``` ### Wrong props ```javascript // Get the tree and inspect a node's props const tree = await commontools.vdom.tree() // Props are CellHandles — call .get() on individual ones tree.props.className.get() ``` ### Multiple renders on the page ```javascript // List all renders commontools.vdom.renders() // Target a specific one by index await commontools.vdom.dump(0) // first render await commontools.vdom.dump(1) // second render // Or by container element await commontools.vdom.dump(document.querySelector('#my-container')) ``` ## See Also - [Console Commands](console-commands.md) — full `commontools.*` reference - [Logger System](logger-system.md) — structured logging and timing