Soundorv0.13.0
Build a runtime

Execution contract

Bundles, generated declarations, soundor:* semantics and the portable Web surface.

Purpose

The execution environment makes a CLI-built UI run unchanged. It resolves the portable modules, supplies the supported Web globals and presents the same observable behavior on its platform.

Where the code is

packages/core/src/generate.ts assembles the portable declarations from the *-dts.ts generators. packages/core/runtime/ contains their checked-in shared forms. The API pages specify the modules; engine, web and simulated implementations and their tests provide the detailed behavior and errors.

How it works

flowchart TD
    config["Validated parameters and native API"] --> gen["gen: portable and runtime sources"]
    gen --> declarations["UI TypeScript declarations"]
    gen --> adapters["Platform bindings and manifests"]
    bundle["ctx.ui: bundle and assets"] --> execution["Runtime execution environment"]
    adapters --> execution
    execution --> modules["soundor:* and Web globals"]

UI bundle

ctx.ui.dir contains the bundle and its assets. ctx.ui.entry identifies bundle.js, a CommonJS module function lowered for Hermes. ctx.ui.module identifies bundle.mjs, the same UI as an ES2023 module. Use the form your execution engine supports; do not treat the native module function as an ES module. soundor:* imports are left for runtime resolution. Other npm dependencies have been inlined.

Production engine builds compile native module sources with the engine's matching hermesc and run bytecode with the compiler excluded. Development loads live resources. Bundle assets must resolve through the same resource identity in either mode. ctx.ui can be absent for a project with no UI entry.

Generated contract

Core emits these files under .soundor/generated/:

FileContents
soundor.d.tsEntry referencing the portable declarations
parameters.d.tsExactly the configured parameters and their types
native.d.tsConfigured native methods, structs, enums and opaque handles
globals.d.tsSupported Web globals, excluding the full DOM
platform.d.tsHost, storage and filesystem declarations
ui.d.tsNodes, styles, events, canvases and animations

The runtime's gen adds platform-specific sources under ctx.paths.gen through ctx.codegen. JUCE generates C++ interfaces and bindings plus its build setup; the web runtime generates manifests, module shims and native API wrappers. A new runtime should consume the same portable declarations.

Module behavior

Use the linked API page as the public specification, and the listed code and tests when matching exact validation, error text and ordering. This table is a review map, rather than a replacement declaration of each method.

ModuleSemantics to preserveImplementation starting points
parametersTyped values, clamping and integer rounding, invalid values, deduplicated/coalesced subscriptions, nested gestures and teardownEngine src/parameters/, web client parameters.ts, generated declarations
nativeDeclared argument order and types, path-specific TypeErrors, synchronous results versus promises, opaque handle ownership and native exceptionsJUCE src/native-codegen.ts, web src/native-codegen.ts, core src/native-api.ts
hostPlugin identity, host snapshot and transport shape, change subscriptions, platform availabilityEngine src/web/, web client modules/host.ts and host context
uiNode ownership, style/layout defaults, input routing, focus, portals, semantic visibility, canvases and animation lifetimeEngine src/ui/ and src/a11y/, web client ui/, React renderer
storageAsync key/value operations, serialization, missing values, persistence and isolation by plugin IDEngine src/web/, web client storage.ts and persistence.ts
fsPrivate relative paths, binary/text operations, atomic writes, directory rules and DOMException error namesEngine src/web/, web client fs.ts

For example, repeated parameter writes of the same value do not produce new notifications. Nested gestures reach the host as one; an unmatched end is ignored, and reload closes outstanding gestures. Filesystem traversal and symlinks escaping the private root are refused. Native argument failures name the offending method and value path before user code executes.

Web globals

The portable declarations, generated by globals-dts.ts, are the inventory. They cover the supported timers and animation frames, promises and microtasks, fetch and its related objects, URL handling, encoding, binary data, logging and other declared globals. A browser's full DOM is not part of the UI contract.

Read engine src/web/ and tests/web/ for edge cases, cancellation and error behavior. Prefer standard browser facilities when their behavior matches, then adapt where necessary. A non-browser runtime must also settle asynchronous operations and promise jobs on the owning JavaScript thread. The simulated test runtime supports deterministic application tests; it does not implement every rendering or audio facility of a production runtime.

Invariants and tests

API success and failure paths, subscriptions, ordering and teardown are all observable. Engine module suites, web client module/UI suites, generated native goldens and React tests cover different parts. Rendering and audio require their own integration tests. Conformance sets out the test coverage a new runtime should assemble.

How to change it

Start with a contract example that fails in the affected implementations. Update portable declarations and their doc comments, implement matching behavior and errors, regenerate affected output, then update the API page. Avoid making a platform's extra APIs a hidden dependency of portable UI code.

On this page