Reconciler
wybthon.reconciler¶
reconciler
¶
Reconciliation engine: mounting, patching, and unmounting VNode trees.
This module translates VNode trees into batched DOM operations. It
never touches the DOM directly: every mutation is emitted as a compact
op against an integer node id (see wybthon.kernel), and the whole
buffer is applied in a single bridge crossing at commit time (end of
render, end of each effect flush).
Mental model:
- Components run once. A function component is invoked a single time during mount. Its returned VNode tree is mounted directly. Reactive updates flow through reactive holes embedded in that tree, not by re-running the component body.
- Reactive holes are
_dynamicVNodes whosegetteris re-evaluated by an effect when its dependencies change. They're created automatically whenever a callable child or callable prop value appears in the tree, and explicitly viadynamic. - Components return a VNode (or a value coercible to one). The
idiomatic style is to return a static tree and use
dynamicfor explicit reactive subtrees; a returned zero-arg callable is also accepted and is wrapped in a single reactive hole for convenience (handy when authoring higher-order components).
Public surface:
render: top-level entry point.mount: emit ops creating DOM for a new VNode under a parent node id.unmount: tear down a VNode and its DOM.patch: diff two VNodes and emit the difference.
Functions:
| Name | Description |
|---|---|
render |
Render a VNode tree into a container element. |
mount |
Emit ops mounting a VNode (or string) under the node |
unmount |
Unmount |
patch |
Diff |
render
¶
Render a VNode tree into a container element.
Subsequent calls with the same container patch the existing tree
in place; only the differences are applied. All emitted DOM ops are
committed to the backend in one batch before this returns.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vnode
|
VNode
|
The root VNode to render. |
required |
container
|
Union[Element, str, int]
|
An |
required |
Returns:
| Type | Description |
|---|---|
Element
|
The wrapped container |
Element
|
retaining a reference to the mount point. |
mount
¶
Emit ops mounting a VNode (or string) under the node parent_id.
When the VNode carries an owner_scope (set by For/Index for
cached rows), mounting runs under that reactive owner so the row's
effects survive later list updates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vnode
|
Union[VNode, str]
|
The VNode to mount. Strings are coerced to text VNodes. |
required |
parent_id
|
int
|
Kernel id of the parent node. |
required |
anchor_id
|
Optional[int]
|
Optional id of the sibling node to insert before.
When |
None
|
unmount
¶
unmount(vnode: VNode) -> None
Unmount vnode, disposing its effects, ownership scope, and DOM.
Calls cleanup on the owning component context (if any), removes
delegated event handlers, runs on_cleanup callbacks, and removes
the subtree's DOM. The removal itself is a handful of ops (one
REMOVE per top-level node plus one RELEASE for the whole
subtree), applied in a single commit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vnode
|
VNode
|
The VNode to tear down. Safe to call on already-unmounted nodes (becomes a no-op). |
required |
patch
¶
Diff old against new and emit minimal DOM ops under parent_id.
Identical VNode instances (old is new, e.g. cached For rows) are
skipped entirely. Same-type VNodes are patched in place (props and
children diffed); different types are unmounted and remounted at the
same position.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
old
|
Optional[VNode]
|
The previously-rendered VNode, or |
required |
new
|
VNode
|
The new VNode to render. |
required |
parent_id
|
int
|
Kernel id of the node that directly contains this VNode's DOM. |
required |
What's in this module¶
The reconciler walks a previous and next VDOM tree and emits the
minimal set of DOM operations to bring the page into sync. It never
touches the DOM directly: every mutation is a compact op against an
integer node id (see wybthon.kernel), applied in one bridge crossing
per commit. It handles keyed lists, fragments, components, text nodes,
and reactive holes.
Most users never call into this module directly. render
mounts a tree and the reconciler kicks in for subsequent updates. Read
this page if you're contributing to Wybthon, debugging a diffing bug, or
curious how holes plug into the patching loop.
Key responsibilities¶
| Concern | How the reconciler handles it |
|---|---|
| Mounting | Static subtrees mount through the template fast path: one clone op per mount of a registered skeleton, instead of one op per node. |
| Element diffing | Matches by tag. If tags differ, the old subtree unmounts. |
| Children | A three-pass O(n) match (identity, then key, then type) with a longest-increasing-subsequence move pass keeps DOM moves minimal. |
| Components | A component's body runs once; the reconciler updates props on the existing component instance. |
| Reactive holes | Each hole is an effect; the reconciler patches only the affected region when the signal updates. |
| Cleanup | Unmounting disposes the owner recursively and retires the whole subtree with one REMOVE per top-level node plus one RELEASE op. |
See also¶
template: the template-based mounting fast path.vnode: the data structure being diffed.- Concepts: Virtual DOM
- Concepts: Lifecycle and Ownership