Kernel
wybthon.kernel¶
kernel
¶
Batched DOM command buffer and rendering backends.
This module is the single point of contact between Wybthon's renderer and the real DOM. Instead of calling DOM APIs directly (each call crosses the Python-to-JS bridge in Pyodide), the reconciler and prop appliers emit compact operations into a buffer. At well-defined commit points (end of a render, end of an effect flush) the whole buffer is serialized once and handed to a small JavaScript kernel that applies every operation natively. A mount of a 1,000-row table becomes one bridge crossing instead of tens of thousands.
Core concepts:
- Node handles. DOM nodes are referred to by integer ids allocated
on the Python side. The kernel keeps an
id -> Noderegistry, so noJsProxyobjects flow through the hot path. - Ops. Each operation is a small tuple,
(opcode, ...args), serialized as a JSON array. See theOP_*constants. - Backends.
BrowserBackenddrives the real DOM through the embedded JS kernel.PythonBackendis a reference interpreter that applies the same ops to any DOM-like stub document; it backs the unit tests and the stubbed benchmark so both exercise the exact protocol the browser sees. - Events. Event delegation lives in the kernel: one native listener
per event type walks the ancestor chain natively and calls into
Python once per matched handler with a JSON payload. See
wybthon.eventsfor the Python half.
Application code never imports this module directly; it's plumbing for
the reconciler, wybthon.props, and wybthon.events.
Classes:
| Name | Description |
|---|---|
BrowserBackend |
Backend that drives the real DOM through the embedded JS kernel. |
PythonBackend |
Reference op interpreter over a DOM-like stub document. |
Functions:
| Name | Description |
|---|---|
commit |
Flush all queued ops to the backend in one crossing. |
set_backend |
Install a rendering backend (tests pass a |
reset |
Test helper: clear the op buffer, id counters, and template registry. |
BrowserBackend
¶
Backend that drives the real DOM through the embedded JS kernel.
Created automatically on first use inside Pyodide. Every apply
serializes the op list to JSON and makes exactly one call across
the bridge.
Methods:
| Name | Description |
|---|---|
apply |
Serialize |
get_node |
Return the raw DOM node registered under |
adopt |
Register an existing raw DOM node under |
query |
Register the first |
supports_html |
The browser can always parse template HTML. |
set_dispatcher |
Install the Python event dispatcher as the kernel's callback proxy. |
current_event |
Return the native event currently being dispatched, or |
PythonBackend
¶
PythonBackend(document: Any)
Reference op interpreter over a DOM-like stub document.
Mirrors the JS kernel's semantics against plain Python objects that
quack like DOM nodes (the test suite's StubNode and the benchmark
runner's _Node). Unit tests and the stubbed benchmark run the real
wire protocol through this class, so protocol bugs surface without
a browser.
Methods:
| Name | Description |
|---|---|
apply |
Interpret a batch of ops against the stub document. |
get_node |
Return the stub node registered under |
adopt |
Register an existing stub node under |
query |
Register the document's first |
supports_html |
Whether the stub document parses |
set_dispatcher |
Install the Python event dispatcher used by |
current_event |
Return the raw event passed to the in-flight |
dispatch |
Simulate a bubbling native event dispatch for tests. |
query
¶
Register the document's first selector match; False when none.
set_dispatcher
¶
Install the Python event dispatcher used by dispatch.
current_event
¶
current_event() -> Any
Return the raw event passed to the in-flight dispatch, or None.
dispatch
¶
dispatch(event_type: str, target: Any, raw_event: Any = None, payload: Optional[dict] = None) -> None
Simulate a bubbling native event dispatch for tests.
Walks the stub-node ancestor chain from target, invoking the
Python dispatcher for every registered (node, event_type)
handler, exactly like the JS kernel's root listener.
template_id
¶
Return the template id for html, registering it on first use.
The registration op travels in the same batch as the clone that needs it, so no extra bridge crossing occurs.
commit
¶
Flush all queued ops to the backend in one crossing.
No-op when the buffer is empty. Safe to call at any time; the
renderer calls it at the end of render, at the end of every
effect flush, and before any synchronous DOM read.
get_node
¶
Return the raw DOM node for node_id, committing pending ops first.
query
¶
Resolve a CSS selector to a node id, or None when nothing matches.
Commits pending ops first so the selector can match nodes created earlier in the same logical update.
supports_html
¶
supports_html() -> bool
Return whether the backend can parse templates (OP_REGISTER_TPL).
current_event
¶
current_event() -> Any
Return the native event being dispatched right now, or None.
Only valid synchronously inside an event handler; used as the
escape hatch behind DomEvent.raw.
set_event_dispatcher
¶
Install the Python-side event dispatcher (called by wybthon.events).
What's in this module¶
kernel is the single point of contact between Wybthon's renderer and
the real DOM. The reconciler, prop appliers, and event system never
call DOM APIs; they emit compact operations (JSON-serializable tuples
against integer node ids) into a buffer that commit() flushes to the
active backend in one Python-to-JS bridge crossing.
Two backends implement the protocol:
BrowserBackenddrives the real DOM through a small JavaScript kernel evaluated once in the page. The kernel owns the id-to-node registry, the registered template protos (parsed once, cloned per mount), and native event delegation.PythonBackendis a reference interpreter that applies the same ops to any DOM-like stub document. The unit tests and the stubbed benchmark run the full wire protocol through it, so protocol bugs surface without a browser.
The op protocol¶
| Op | Payload | Effect |
|---|---|---|
CREATE_ELEMENT |
id, tag |
document.createElement |
CREATE_TEXT |
id, text |
document.createTextNode |
CREATE_COMMENT |
id |
document.createComment |
REGISTER_TPL |
tpl_id, html |
Parse a skeleton once via <template> |
CLONE_TPL |
first_id, count, tpl_id |
Clone the proto; assign a dense id block in pre-order |
INSERT |
parent_id, id, anchor_id |
insertBefore (None anchor appends) |
REMOVE |
id |
Detach from parent |
SET_TEXT |
id, text |
nodeValue assignment |
SET_ATTR |
id, name, value |
setAttribute / removeAttribute (None removes) |
SET_PROP |
id, name, value |
DOM property assignment (value, checked) |
SET_STYLE |
id, decls |
style.setProperty / removeProperty per declaration |
LISTEN / UNLISTEN |
id, type |
Delegated handler bookkeeping plus root-listener refcounts |
RELEASE |
[ids] |
Drop registry entries and listener sets for a retired subtree |
Application code never imports this module directly; it's plumbing for
the reconciler, wybthon.props, and wybthon.events.
See also¶
- Concepts: Virtual DOM
template: the skeleton registration fast path.reconciler: emits the ops.