tempestweb.runtime¶
A cola entre o core e cada modo de execução: AppSession é o ciclo de vida por conexão do Modo B, WasmRuntime conduz o loop de rebuild no Modo A, e os helpers de serialização baixam a IR para o formato de fronteira. spawn mora aqui — é como um handler tira trabalho longo de cima da sessão.
Guia com exemplos: Contrato de fronteira · Boas práticas.
tempestweb.runtime ¶
tempestweb.runtime — execution-mode glue, session and wire serialization.
Mode A (WASM/Pyodide): :class:WasmRuntime drives the core's rebuild loop over a
:class:~tempestweb.transports.base.PatchTransport. Mode B (server):
:class:~tempestweb.runtime.session.AppSession is the per-connection lifecycle,
with serialization helpers that lower the IR to the wire format and resolve
handlers from client events.
See docs/plan.md (Trilhos A e B) and docs/contract.md.
NoSessionError ¶
AppSession ¶
Bases: Generic[S]
Drives one client connection: state, transport, and task lifecycle.
Each session builds its own :class:~tempest_core.App from a factory, so
connections are fully isolated — a set_state in one never affects another.
S is the application state type.
Attributes:
| Name | Type | Description |
|---|---|---|
transport |
PatchTransport
|
The patch transport carrying this client's patches and events. |
app |
App[S] | None
|
The isolated app instance, created in :meth: |
Source code in tempestweb/runtime/session.py
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 | |
start
async
¶
Mount the session: install the bridge and send initial patches.
Builds the isolated app, installs this session's :class:ProxyBridge as
the process-wide native bridge (so await native.<capability>() inside a
handler proxies to the client), records the initial scene, and pushes the
initial patch batch (a root replace) plus the resolved theme mode, so the
client renders the first screen on the right palette instead of flashing
light and correcting itself.
Note
install_bridge stores the bridge in a context-local variable (see
:mod:tempestweb.native.dispatch). Because this start is awaited
from the session's own run task, the bridge is isolated to that
connection's asyncio context: concurrent server sessions each resolve
await native.* through their own bridge, never clobbering one
another. :meth:native_call also uses this session's bridge directly.
Source code in tempestweb/runtime/session.py
dispatch
async
¶
Resolve and invoke the handler for one client event.
Looks up the live handler on the current scene by the event's key and
type, then invokes it. A handler that accepts a positional argument
receives the raw payload; a zero-argument handler is called bare. Async
handlers are awaited. Any set_state the handler triggers schedules the
coalesced rebuild that pushes the resulting patches back to the client.
Unknown keys / missing handlers are silently ignored (a stale event from a
widget that no longer exists is not an error). Three event types are
handled by the runtime instead of an app handler: scroll slides a
virtualized window, navigate applies a URL change, and resync
re-sends the whole scene (the client asks for it when it could not apply
a batch).
When observability is wired, the handler gets its own span, and the arrival time is stamped here rather than the latency being timed around this call: the rebuild is coalesced and runs after the handler returns, so timing this block reported rounds with zero patches. The histogram is taken where the batch actually leaves.
The theme mode is re-checked after every handler, not only after a batch:
a theme swap can change nothing in the tree — an app whose view does
not pass the theme to any widget rebuilds to the identical IR, so the core
emits no patch and the batch hook never runs — and the base stylesheet
still has to hear about it. The check runs outside the handler span, so a
stylesheet envelope is not accounted to the handler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
Event
|
The JSON-able client event |
required |
Source code in tempestweb/runtime/session.py
resync
async
¶
Re-send the current scene as a full initial patch batch.
The client's tree is only correct while it has applied every patch in order. When that chain breaks — a batch it could not apply, or an SSE reconnect whose gap the replay buffer no longer covers — no further index-relative patch can be trusted, and a resync is the only repair: one root replace carrying the scene as it stands now.
A no-op before the session has mounted or after it closed.
Source code in tempestweb/runtime/session.py
native_call
async
¶
Proxy a native Web API capability to the client and await its result.
Sends a native_call envelope, suspends until the matching
native_result arrives (correlated by call_id), then returns the
client's value or raises on failure. This is the server-side leg of the
4th boundary crossing (see docs/contract.md); in Mode A the same API
resolves in-process without a round-trip.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
capability
|
str
|
Stable capability name (e.g. |
required |
args
|
dict[str, Any]
|
JSON-able arguments forwarded to the client capability. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
The JSON-able |
Raises:
| Type | Description |
|---|---|
NativeCallError
|
If the client reports the capability failed. |
NativeError
|
With code |
TransportClosedError
|
If the connection drops before a result. |
Source code in tempestweb/runtime/session.py
run
async
¶
Serve the client until the transport closes.
Mounts (if not already) then loops: await the next event, dispatch it, let the rebuild loop flush patches. Returns cleanly when the transport closes.
A handler that raises is logged and the loop carries on, exactly as in concurrent mode. It used to end the connection instead — and in Mode B the connection is the session, so one buggy handler (a validation error in a rebuilt widget, say) dropped the client's whole state; the client silently reconnected onto a fresh session and the screen jumped back to its initial view with nothing in the server log to explain it.
Source code in tempestweb/runtime/session.py
close
async
¶
Unmount the session: cancel orphan tasks and tear down the transport.
Idempotent. Cancels every tracked task spawned for this connection
(structured concurrency) and awaits their cancellation, then closes the
transport. Safe to call from :meth:run's finally and externally.
Source code in tempestweb/runtime/session.py
NativeCallError ¶
WasmRuntime ¶
Bases: Generic[S]
Drives a tempestweb app in Mode A, bridging the core to a transport.
The runtime wires the :class:~tempest_core.App to a
:class:~tempestweb.transports.base.PatchTransport: the app's coalesced
rebuild loop produces patches, which the runtime serializes and pushes to the
client via :meth:PatchTransport.send_patches; the client's events flow back
through :meth:PatchTransport.recv_event and are routed to the matching
Python handler.
The same view runs unchanged in Mode B — only the transport differs — so
this class never names Pyodide. The live pyodide.ffi wiring lives in
:class:tempestweb.transports.wasm.WasmTransport.
S is the application state type.
Methods:
| Name | Description |
|---|---|
start |
Build the initial scene, register handlers, return the JSON node. |
dispatch_event |
Route one client event to its Python handler. |
run |
Await client events forever, dispatching each (the event loop). |
Source code in tempestweb/runtime/wasm.py
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 | |
app
property
¶
The underlying core app.
Returns:
| Name | Type | Description |
|---|---|---|
The |
App[S]
|
class: |
start ¶
Build the initial scene and return its serialized root node.
Registers the initial tree's handlers and returns the JSON-able root node the client mounts. Patches emitted by later rebuilds reach the client through the transport, not this method.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
The serialized initial root node (``{"type", "key", "props", |
dict[str, Any]
|
"children"}``). |
Source code in tempestweb/runtime/wasm.py
dispatch_event
async
¶
Route one client event to its Python handler and invoke it.
Resolves the handler by (event["key"], "on_" + event["type"]) against
the current handler registry. A zero-argument handler is called bare; a
handler that accepts a positional argument receives the raw payload dict.
Async handlers are awaited. Unknown keys or event types are ignored (the
widget may have been removed between dispatch and delivery).
Four event types are served by the runtime itself instead of an app
handler, matching what a Mode B session does with the same wire event:
scroll slides a virtualized window, navigate applies a URL
change, media updates the media-query context, and resync
re-sends the whole scene (the client asks for it when a patch would not
apply).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
Event
|
The wire event |
required |
Source code in tempestweb/runtime/wasm.py
resync
async
¶
Re-send the current scene as a full initial patch batch.
The client's tree is only correct while it has applied every patch in
order. Once a batch fails to apply, no later index-relative patch can be
trusted — they address a tree that no longer exists — so the DOM stays
truncated and every following tick fails the same way. One root
Replace carrying the scene as it stands now is the only repair, and
in Mode A it costs no round-trip: the app runs in this same tab.
Overlays follow the root replace as inserts under the reserved
"overlay" path, mirroring what a Mode B session sends, so a resync
restores the overlay layer too and not only the root tree.
A no-op before the app has started (no current scene), and on a transport
that has closed. That second guard is not decoration: this is the only
branch of :meth:dispatch_event that awaits the transport directly — the
others hand work to set_state and let the rebuild loop schedule the
send — so without it a resync arriving as the tab tears down raises
:class:TransportClosedError out of :meth:run, which only catches that
error around :meth:recv_event. The whole event loop would die on the way
out. Mode B's session guards the same case with its _closed flag.
Source code in tempestweb/runtime/wasm.py
spawn ¶
Schedule a coroutine as a tracked background task.
Backs :func:tempestweb.runtime.spawn in Mode A. The reference is held
until the task settles — the loop keeps only a weak one — and
:meth:cancel_background drops the lot at teardown.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coro
|
Coroutine[Any, Any, None]
|
The coroutine to run. |
required |
Source code in tempestweb/runtime/wasm.py
cancel_background ¶
Cancel every task started through :meth:spawn.
Called when the app tears down, so background work does not outlive the page that started it.
Source code in tempestweb/runtime/wasm.py
run
async
¶
Run the client→Python event loop until the transport closes.
Awaits events from the transport and dispatches each. Returns when the
transport raises :class:~tempestweb.transports.base.TransportClosedError
from :meth:recv_event (the page closed or the bridge tore down).
Installs this runtime as the context's task spawner first, so a handler
can hand long work to :func:tempestweb.runtime.spawn instead of holding
the dispatch — Mode A reads events in series exactly like a server
session, so a slow handler freezes the tab the same way.
Source code in tempestweb/runtime/wasm.py
WasmAppHandle ¶
Bases: Generic[S]
The handle JS holds onto for a running Mode A app.
Exposes just what the browser side needs: the JSON-able initial node to
mount, a way to push DOM events into Python, and teardown. Everything else
(the rebuild loop, serialization, event routing) is driven internally by the
wrapped :class:~tempestweb.runtime.wasm.WasmRuntime.
Methods:
| Name | Description |
|---|---|
initial_node_json |
The serialized initial root node, as a JSON string. |
theme_css |
The app palette as |
push_event_json |
Feed one DOM event (a JSON string) into the runtime. |
close |
Tear the app down, stopping the event loop. |
Source code in tempestweb/runtime/wasm_main.py
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | |
theme_css ¶
Return the app's palette as the CSS the base stylesheet reads.
The core resolves a component's own colors inline, but the base sheet's
--tw-* tokens style everything a widget leaves to it — interaction
states, the surface behind the app, indicators. Mode B emits these into
the page head (create_app(theme=...)); Mode A's page is static and the
app only exists once Pyodide is up, so the CSS is handed to JS here and
injected before the first mount.
Returns:
| Type | Description |
|---|---|
str
|
The |
str
|
none (the base sheet's own defaults then stand). |
Source code in tempestweb/runtime/wasm_main.py
initial_node_json ¶
Return the serialized initial root node as a JSON string.
JS parses this and hands it to the DOM renderer's mount. A string is
returned (rather than a dict) so the value crosses pyodide.ffi as a
plain string and JS controls the parse.
Returns:
| Type | Description |
|---|---|
str
|
The initial root node, JSON-encoded. |
Source code in tempestweb/runtime/wasm_main.py
push_event_json ¶
Feed one DOM event into the runtime.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_json
|
str
|
A JSON string of the wire event
|
required |
Source code in tempestweb/runtime/wasm_main.py
close
async
¶
Tear the app down: close the transport and stop the event loop.
Cancels any background work started through
:func:tempestweb.runtime.spawn so it does not outlive the app, and
uninstalls the in-process :class:FFIBridge if :func:bootstrap
installed one, so a torn-down app never leaves a stale process-wide bridge.
Source code in tempestweb/runtime/wasm_main.py
spawn ¶
Run coro in the background, owned by the current session.
Use it for anything that would otherwise hold the event dispatch: the handler
returns immediately, the session keeps serving events, and the work updates
the state through app.set_state when it finishes (each call schedules the
usual coalesced rebuild, so progress can be shown as it goes).
The task is tracked by the session and cancelled when the connection ends.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coro
|
Coroutine[Any, Any, None]
|
The coroutine to run. |
required |
Raises:
| Type | Description |
|---|---|
NoSessionError
|
If no session owns the calling context — you are outside
a handler, or in a plain |
Source code in tempestweb/runtime/background.py
apply_media ¶
Refresh the viewport context from a media wire event.
The browser owns the viewport, so the client reports it on mount and whenever
size, density, OS dark mode or orientation changes; this drives
:meth:~tempest_core.core.state.App._update_media, which records the snapshot
and requests a coalesced rebuild so a responsive view re-runs against the
new environment. Without this a server-side app runs forever on the default
MediaQueryData — width and height both 0.0 — so it can neither
switch layout at a breakpoint nor bound a frame to the viewport height.
Every field is optional and validated: a payload missing a key keeps that field's default, and one carrying a wrong type is ignored entirely rather than poisoning the context with a partial snapshot.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app
|
App[Any]
|
The application whose media context to refresh. |
required |
payload
|
Any
|
The wire payload, expected to carry any of |
required |
Source code in tempestweb/runtime/events.py
apply_navigate ¶
Resolve a deep-link / browser navigation into the app's nav stack.
The client reports the document path (plus query string) on load and on
popstate (back/forward); this resets the app's navigation stack to the
routes that path resolves to (path_to_routes), attaching any query params
to the linked route, so view re-renders it with its back stack intact.
A malformed payload is ignored.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app
|
App[Any]
|
The application whose navigation stack to reset. |
required |
payload
|
Any
|
The wire payload, expected to carry a string |
required |
Source code in tempestweb/runtime/events.py
apply_scroll ¶
Slide a virtualized list's visible window from a scroll wire event.
The DOM client reports a list's visible [start, end) window as it scrolls;
this drives :meth:~tempest_core.core.state.App.slide_window, which records
the window and requests a rebuild so the list materializes the slid items.
A malformed payload is ignored.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app
|
App[Any]
|
The application whose list window to slide. |
required |
key
|
str
|
The |
required |
payload
|
Any
|
The wire payload, expected to carry int |
required |
Source code in tempestweb/runtime/events.py
coerce_event ¶
Validate a wire payload into the typed event for (node_type, event_type).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
node_type
|
str | None
|
The target node's widget type tag (e.g. |
required |
event_type
|
str
|
The wire event type (e.g. |
required |
payload
|
Any
|
The raw JSON-able payload mapping from the wire event. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
The typed :class: |
Any
|
declares a schema for this event type and the payload validates; otherwise |
Any
|
the raw |
Any
|
|
Source code in tempestweb/runtime/events.py
find_node_type ¶
Return the widget type tag of the keyed node in a scene.
Searches the root tree then the overlay layer, mirroring
:func:resolve_handler, so an event's payload can be coerced into the typed
event the matched widget declares.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene
|
Scene
|
The session's current scene. |
required |
key
|
str
|
The widget key the event addresses. |
required |
Returns:
| Type | Description |
|---|---|
str | None
|
The node's |
Source code in tempestweb/runtime/serialize.py
node_to_wire ¶
Lower an IR node to its JSON-able wire shape.
The node is dumped with Pydantic (mode="json" for styles, enums, colors),
then its props are walked to replace any live handler callable with
None — handlers never cross the boundary (see docs/contract.md).
Since tempest-core 0.9.0 every widget carries the SSR-only tag and
attrs props (see :mod:tempestweb.html). They are meaningful to the
static HTML renderer but inert on the DOM-JS wire, so a falsy tag (None)
and a falsy attrs ({}) are omitted here. This keeps the wire
byte-identical to the pre-0.9.0 payload for widgets that do not use them —
avoiding per-node bloat and keeping the existing golden fixtures valid — while
a widget that does set them still ships them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
node
|
Node
|
The IR node to serialize. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
A JSON-able |
Source code in tempestweb/runtime/serialize.py
patch_to_wire ¶
Lower a single patch to its JSON-able wire shape.
Each patch kind is built explicitly rather than via a blanket
model_dump — the IR carries live handler callables inside
Update.set_props and inside the node of
:class:~tempest_core.Insert / :class:~tempest_core.Replace, which
Pydantic cannot serialize. :func:node_to_wire and :func:_json_safe strip
those handlers to None (see docs/contract.md). path tuples become
lists.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
patch
|
Patch
|
An IR patch produced by |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
A JSON-able patch dict matching |
Source code in tempestweb/runtime/serialize.py
patches_to_wire ¶
Lower a coalesced patch batch to JSON-able wire dicts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
patches
|
list[Patch]
|
The tick's patches, in apply order. May be empty. |
required |
Returns:
| Type | Description |
|---|---|
list[dict[str, Any]]
|
The JSON-able patch dicts, in the same order (empty list when empty). |
Source code in tempestweb/runtime/serialize.py
resolve_handler ¶
Resolve the live handler callable a client event targets.
Walks the current scene (root then overlays) for the node with key,
then looks up the handler prop for event_type using
:data:EVENT_TYPE_TO_HANDLER_PROPS, falling back to a literal on_<type>
prop name. Handlers live in the node's props as real Python callables
(they are only stripped to None when serialized for the wire).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene
|
Scene
|
The session's current scene ( |
required |
key
|
str
|
The |
required |
event_type
|
str
|
The wire event type ( |
required |
Returns:
| Type | Description |
|---|---|
Callable[..., Any] | None
|
The handler callable to invoke, or |
Callable[..., Any] | None
|
or the matched node declares no handler for that event type. |
Source code in tempestweb/runtime/serialize.py
scene_to_initial_patches ¶
Build the initial patch batch that mounts a scene from an empty root.
The client mounts by applying patches to an empty document. We model the
initial mount as a single :class:~tempest_core.Replace at the root
(path == []) carrying the whole built tree, which the DOM renderer (W1)
applies to materialize the screen. Overlays, when present, follow as inserts
under the reserved "overlay" path.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene
|
Scene
|
The freshly built scene ( |
required |
Returns:
| Type | Description |
|---|---|
list[dict[str, Any]]
|
The JSON-able initial patch batch. |
Source code in tempestweb/runtime/serialize.py
serialize_node ¶
Serialize an IR node tree into the JSON-able client shape.
Recurses the tree, dumping each node to {"type", "key", "props",
"children"} with handler callables nulled out (see :func:_serialize_props)
and Style/Color/Edge objects lowered to plain dicts via Pydantic.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
node
|
Node
|
The root IR node to serialize. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
The JSON-able node dict, ready to hand to the client. |
Source code in tempestweb/runtime/wasm.py
serialize_patches ¶
Serialize a reconciler patch list into JSON-able wire patches.
Each patch is dumped to its contract shape; any node payload it carries
(Insert/Replace) is serialized via :func:serialize_node so the
embedded subtree is sanitized exactly like the initial tree. path lists
keep the core's int | "overlay" steps unchanged.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
patches
|
list[Patch]
|
The patches emitted by |
required |
Returns:
| Type | Description |
|---|---|
list[Patch]
|
A list of JSON-able patch dicts, in apply order. |
Source code in tempestweb/runtime/wasm.py
bootstrap ¶
bootstrap(state: S, view: Callable[[App[S]], Widget], on_patches: Callable[[str], Any], dispatch: NativeDispatch | None = None, on_navigate: Callable[[str], Any] | None = None, subscribe: NativeSubscribe | None = None, unsubscribe: NativeUnsubscribe | None = None, theme: Theme | None = None, *, on_theme: Callable[[str], Any] | None = None) -> WasmAppHandle[S]
Wire an app to the JS client and start it.
When dispatch is provided, an :class:FFIBridge is installed so that
await native.<capability>() inside a handler resolves in-process through
client/native/index.js — no network hop. The dispatch callable is the one
Pyodide-aware seam: the generated bootstrap.js glue exposes
window.__tempestweb_native__ via :func:installNativeBridge and passes its
Pyodide proxy in here, so this module never imports pyodide itself and stays
type-checkable off-browser.
subscribe/unsubscribe are the streaming half of that same seam
(geolocation.watch, network.watch, sensors.*, …). Pass them
together with dispatch: an :class:FFIBridge built without them accepts
single-shot calls but raises
:class:~tempestweb.native.dispatch.BrowserUnavailableError on every
watch()/listen(), which is exactly what Mode A did before they were
wired.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
S
|
The app's initial state. |
required |
view
|
Callable[[App[S]], Widget]
|
The app's |
required |
on_patches
|
Callable[[str], Any]
|
The JS callback that applies a patch batch in the DOM. It is
called with a JSON string of the patch list, so the batch crosses
|
required |
dispatch
|
NativeDispatch | None
|
Optional in-process native dispatch (the Pyodide proxy of
|
None
|
on_navigate
|
Callable[[str], Any] | None
|
Optional JS callback invoked with the new top-route path when
the app navigates, so the client can |
None
|
on_theme
|
Callable[[str], Any] | None
|
Optional JS callback invoked with the resolved theme mode
( |
None
|
subscribe
|
NativeSubscribe | None
|
Optional in-process streaming subscribe (the Pyodide proxy of
the glue around |
None
|
unsubscribe
|
NativeUnsubscribe | None
|
Optional in-process streaming unsubscribe (the proxy of the
glue around |
None
|
theme
|
Theme | None
|
The app's palette, if it declares one (the generated bootstrap
passes |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
WasmAppHandle[S]
|
class: |
Source code in tempestweb/runtime/wasm_main.py
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | |