JavaScript, JSX and the WREN Toolchain
WREN and Atelier are standardizing on Ranvier for reactive views. Ranvier’s browser and native WebCore backends provide a shared view direction across different execution paths. Fickl serves the F#-to-JavaScript path; a future Clef frontend needs its own lowering and integration. JSX and a framework transform remain possible browser toolchain choices where an application actually selects them.
WrenHello’s earlier frontend uses F# compiled through Fable and a Solid/Vite build, with a Composer-compiled native host. That provides a host and bridge reference. Our current work moves toward Fickl and Ranvier. Clef-to-JavaScript lowering and any JSX extension remain separate implementation work.
Frontend Responsibilities
| Responsibility | Owner in the proposed WREN path |
|---|---|
| Realize Clef semantics and preserve view intent | CCS/Baker settle source facts; Alex witnesses portable operations; Composer’s backend realizes the target |
| Provide reactive state and view behavior | Ranvier’s selected backend and its application integration |
| Package browser frontend assets | The selected bundler and asset configuration, such as Vite |
The browser path can embed or serve those assets in a WebView. Ranvier’s native WebCore path instead connects native application code to the DOM through native interop. Vite, JSX and a Solid transform are not prerequisites for every Ranvier view. Where an application chooses JSX and Solid, the Solid Vite integration connects that optional transform to the build.
Babel and Bazel
Babel is an independent open-source toolkit for JavaScript syntax trees: parsing, traversing, transforming and printing them. Its parser already accepts JSX when enabled, its AST definitions already include JSX nodes, and its generator can print them. Babel AST is derived from ESTree with documented differences; native bridges must map the representation they actually use. Babel parser, JSX node definitions, generator.
There are two potential Babel uses for a JSX-based browser pipeline:
- JSIR source generation: convert the native AST representation to Babel AST and print JavaScript, or JSX after the bridge is extended. Printing JSX leaves its framework transformation for the next stage.
- Solid compilation: run Solid’s Babel transformation to consume that JSX and produce JavaScript using Solid’s DOM/reactive conventions. A React JSX transform would select a different implementation contract.
JSIR embeds a Babel payload and executes it through QuickJS. That does not provide a full Babel source checkout or install Solid’s compiler. Its bridge source shows the parser, traversal and generator calls.
Bazel is a separate build orchestrator used by JSIR. It can build the native compiler tools and could coordinate application stages if selected. It does not transform JSX, and WREN need not adopt it merely because JSIR uses it. Bun can contribute JavaScript analysis, execution and build facilities, but substituting it for any stage requires checking that stage’s contract, especially Solid’s transformation and the actual WebView runtime.
Where JSX Is Missing
The missing representation is in JSIR’s native AST/IR bridge, not Babel. At reviewed upstream revision d5322bd, the native AST classes and JSHIR operation definitions do not model JSX elements, fragments, attributes or expression containers. Enabling JSX parsing in Babel alone cannot carry them through that bridge.
Extending the bridge is a concrete candidate path:
Clef source and UI library contracts
→ CCS / PSG → Baker → Alex's portable MLIR
→ JavaScript/JSX realization with retained PSG/codata
→ extended JSHIR → native AST → Babel JSX AST → .jsx
→ Solid compiler through Vite → bundled JavaScript / CSS / HTML
→ native embedding → WebViewAlex’s witnessed vocabulary remains func, scf, arith, memref and index. JSHIR is itself an MLIR dialect below that boundary. UI identities, captures, effects and reactive intent must remain available until target realization; JSX does not require a new Clef semantic dialect in Alex.
The extension must cover both operations and conversion machinery. JSIR’s AST generator produces native AST, JSON conversion, visitors, TableGen and AST/IR conversion code from a schema. The reviewed public tree lacks the JavaScript ast_def.textproto named in its example, although test schemas are present. Reproducible extension therefore starts by obtaining or reconstructing that input, or defining a maintained extension mechanism; editing generated TableGen alone is insufficient.
The driver also needs qualification. jsir2ast,ast2source are reverse conversion names, but the current CLI starts from a JavaScript-source representation. They do not establish a reverse-only command accepting an MLIR file. Composer needs the conversion APIs or a JSHIR-input driver. The JSIR chapter records the checked revision and this distinction.
A structured Babel-AST exporter after portable witnessing remains another possible implementation choice. It would owe the same semantic and reactive preservation work. The proposed JSHIR extension offers a common MLIR analysis surface; AST emission itself does not inherently bypass Alex.
Preserve the Reactive Read
The UI design favors functional composition over shared semantic operations, with optional computation-expression surfaces. Ranvier provides the current direction for reactive state and views across browser and native WebCore backends. Elmish can supply pure state transitions where useful. A Clef integration must preserve the chosen view’s activation, dependency tracking, identity and cleanup contracts through its own lowering and runtime path.
For example, this JSX expression illustrates a Solid-specific browser transform:
const view = <span>{total()}</span>;The call’s position allows Solid to arrange a tracked update. Hoisting total() into a plain snapshot before constructing the view can lose that behavior. Similar obligations apply to deferred props, ordered spreads, event handlers and cleanup. Valid JSX alone is insufficient. Solid’s JSX explanation describes its compilation and reactive role.
MLIR regions can retain embedded expression structure, but JSX braces introduce no new JavaScript lexical scope. Outer captures must remain valid. A region does not by itself prove tracking, ordering or safe movement of expressions.
JSX can preserve a form on which a selected framework compiler performs transformations. Its usefulness depends on the chosen frontend; shared Ranvier views do not imply a Solid or JSX dependency. Clef’s numeric, boundary and proof obligations remain part of its own target contract.
Bundled Pages and Floating Views
WrenHello’s Vite configuration produces one self-contained HTML file: scripts and styles are inlined, CSS splitting is disabled and dynamic imports are inlined. Its weld script freezes that file into a native source literal. The build is currently scripted in the package commands.
Several authored pages can live in that one document, with a persistent shell and smooth transitions between sections. Source organization does not force full document navigation. Conversely, packaging several HTML documents together does not preserve their DOM or JavaScript state when navigating between them. Routing, transitions and state retention need an explicit interaction design.
Atelier’s multi-WebView design motivates a later asset model. Vite can build multiple HTML entries, but native embedding would then need an asset collection, entry/chunk manifest and resource resolver. Shared bytes do not create a shared JavaScript heap, and local assets still incur initialization and rendering costs.
Docked panels are a UI/runtime concern. Separate native WebView inspectors additionally need window creation, host messaging and explicit lifetime ownership. The workload, its observation subscription and its view should have separate lifetimes: closing an inspector normally stops observation without terminating the inspected activity. Reopening can obtain a snapshot and further updates. This can be a reusable WREN capability for Atelier and standalone diagnostic applications. Renderer-process isolation is a separate, platform-dependent property.
Carrying Proofs Through This Toolchain
This framing fits Carrying Proofs into JavaScript. The property to preserve concerns program behavior; compiler metadata need not appear in the final application payload. JSX adds a transformation edge at which preservation must be established or affected properties re-checked.
For a browser frontend, the argument extends through the selected reactive backend, any framework transform, bundling and embedding to the final assets and shipped dependency closure. Record tool versions and configuration, source/obligation identities and host assumptions. Source maps and artifact hashes support provenance; they do not prove behavior. A Solid runtime enters that closure only when the application selects it.
Fickl output can supply an executable reference over a declared shared contract. Compare actual Ranvier view behavior across the selected browser and native backends, including reactive reads, events and disposal. If a JSX transform is selected, include its input and output in the comparison. Producers sharing a transform can share its failures, so agreeing outputs do not independently prove that transform. WrenHello’s native UI acceptance gate supplies bounded cases for its earlier path, including button updates, rejected messages and shutdown. Rebuild the frontend and weld before using the gate to validate a changed frontend.
The next milestone is a small Clef view with a changing value and an event callback that survives this complete path, with mutations exposing lost tracking or duplicated dispatch. That would establish one supported UI lowering while ordinary JavaScript, broader UI coverage and future multiwindow hosting earn their own evidence.