//#region src/native-protocol.d.ts /** * The **native command protocol** — a small, strongly-typed, *serializable* * description of how to build and mutate a native view tree. * * The Helix reconciler ({@link import('./render').render}) drives a * {@link import('./backend').HostBackend}; the * {@link import('./native-command-backend').NativeCommandBackend} implements that * contract by emitting a stream of {@link NativeCommand}s instead of touching the * DOM. A native host (UIKit on iOS, Android View on Android, or another future * surface) consumes the stream and materializes real views. * * The protocol is deliberately platform-neutral and JSON-serializable: it carries * **no functions**. Event handlers are represented as stable handler-id * *registrations* ({@link RegisterEventCommand}); the host invokes a handler by * id (see {@link import('./native-command-backend').NativeCommandBackend.dispatchEvent}), * so a closure never has to cross a serialization boundary. * * This is the Phase 8A foundation for native rendering. It is **not** itself an * iOS/Android renderer — it is the wire format a real host backend will speak. * * @module */ /** Identifier for a native node. Stable for the node's lifetime. */ type NativeNodeId = string | number; /** * A value that may be sent as a native prop. Strictly serializable: primitives, * `null`, and (recursively) arrays/plain-objects of the same. Notably **not** * functions, `undefined`, symbols, bigints, or non-finite numbers — those cannot * cross the protocol boundary safely. Event handlers are modeled separately * (see {@link RegisterEventCommand}). */ type NativePropValue = string | number | boolean | null | readonly NativePropValue[] | { readonly [key: string]: NativePropValue; }; /** Create an element node with a tag (e.g. `"view"`, `"text"`, `"button"`). */ interface CreateNodeCommand { readonly type: 'createNode'; readonly id: NativeNodeId; readonly tag: string; } /** Create a text node holding `text`. */ interface CreateTextCommand { readonly type: 'createText'; readonly id: NativeNodeId; readonly text: string; } /** Set (or replace) a serializable prop on a node. */ interface SetPropCommand { readonly type: 'setProp'; readonly id: NativeNodeId; readonly name: string; readonly value: NativePropValue; } /** Remove a previously-set prop from a node. */ interface RemovePropCommand { readonly type: 'removeProp'; readonly id: NativeNodeId; readonly name: string; } /** Insert `childId` into `parentId` at `index` (0-based, among current children). */ interface InsertChildCommand { readonly type: 'insertChild'; readonly parentId: NativeNodeId; readonly childId: NativeNodeId; readonly index: number; } /** Detach `childId` from `parentId` (does not free the node — see {@link DisposeNodeCommand}). */ interface RemoveChildCommand { readonly type: 'removeChild'; readonly parentId: NativeNodeId; readonly childId: NativeNodeId; } /** Update a text node's content. */ interface UpdateTextCommand { readonly type: 'updateText'; readonly id: NativeNodeId; readonly text: string; } /** * Free a node's host resources. When a subtree is removed, exactly one * {@link RemoveChildCommand} detaches the subtree's **root**, then a `disposeNode` * is emitted for the root **and every descendant** (deepest-first). Interior nodes * are not individually detached — they are freed in the same batch as their parent * — so a host should treat `disposeNode` as "free this node (and remove it from any * parent it still holds)". No surviving node ever references a freed one. */ interface DisposeNodeCommand { readonly type: 'disposeNode'; readonly id: NativeNodeId; } /** * Register an event handler on a node under a stable `handlerId`. The host should * call back into the runtime (`dispatchEvent(handlerId, event)`) when the native * event fires. The handler function itself never crosses the protocol. */ interface RegisterEventCommand { readonly type: 'registerEvent'; readonly id: NativeNodeId; /** Normalized event name, e.g. `"press"` for an `onPress` prop. */ readonly eventName: string; /** Stable id the host echoes back to invoke the handler. */ readonly handlerId: string; } /** Remove a previously-registered event handler. */ interface UnregisterEventCommand { readonly type: 'unregisterEvent'; readonly id: NativeNodeId; readonly eventName: string; readonly handlerId: string; } /** A single instruction in the native command stream. */ type NativeCommand = CreateNodeCommand | CreateTextCommand | SetPropCommand | RemovePropCommand | InsertChildCommand | RemoveChildCommand | UpdateTextCommand | DisposeNodeCommand | RegisterEventCommand | UnregisterEventCommand; /** * Type guard: is `value` a valid {@link NativePropValue}? Rejects functions, * `undefined`, symbols, bigints, non-finite numbers, and non-plain objects * (recursively). */ declare function isNativePropValue(value: unknown): value is NativePropValue; /** * Coerce `value` to a {@link NativePropValue}, or `undefined` if it cannot be * represented (signalling the prop should be removed rather than set). * * - Primitives/`null` pass through (non-finite numbers are rejected). * - Arrays are rejected wholesale if **any** element is unrepresentable (so * element indices are never silently shifted). * - Plain objects keep only their representable entries (an unrepresentable value * drops that key); non-plain objects (Date, Map, class instances, …) are rejected. */ declare function normalizeNativeProp(value: unknown): NativePropValue | undefined; /** Type guard: is `value` a well-formed {@link NativeCommand}? */ declare function isNativeCommand(value: unknown): value is NativeCommand; /** * Create a generator of unique node ids. Each call returns the next id as * `` `${prefix}${n}` `` with a monotonically increasing `n`. Pass a distinct * `prefix` per backend instance so ids from different backends never collide. */ declare function createNativeNodeIdFactory(prefix?: string): () => string; //#endregion export { CreateNodeCommand, CreateTextCommand, DisposeNodeCommand, InsertChildCommand, NativeCommand, NativeNodeId, NativePropValue, RegisterEventCommand, RemoveChildCommand, RemovePropCommand, SetPropCommand, UnregisterEventCommand, UpdateTextCommand, createNativeNodeIdFactory, isNativeCommand, isNativePropValue, normalizeNativeProp }; //# sourceMappingURL=native-protocol.d.ts.map