# What Runtime Helpers Does the Rust/WASM JSX Transformer Generate?

> Discover the three runtime helpers __jsxComponent __jsxSpread and __jsxList generated by the Rust WASM JSX transformer enabling efficient component rendering attribute serialization and list flattening.

- Repository: [Víctor García/sxo](https://github.com/gc-victor/sxo)
- Tags: internals
- Published: 2026-03-02

---

**The Rust/WASM JSX transformer in the sxo repository generates three runtime helpers—`__jsxComponent`, `__jsxSpread`, and `__jsxList`—that are injected into the global scope to handle component rendering, attribute serialization, and child array flattening without requiring module imports.**

The **sxo** project implements a Rust-based JSX transformer compiled to WebAssembly for transforming JSX syntax into plain JavaScript compatible with ESM-only Node 20+ environments. To maintain minimal bundle sizes and runtime-agnostic output, the transformer inserts a small set of **runtime helpers** once per bundle, attaching them to `globalThis` so every transformed module can reference them directly.

## The Three Runtime Helpers Generated by the Transformer

The transformer emits code that relies on three specific helper functions defined in [`src/js/esbuild/jsx-helpers.js`](https://github.com/gc-victor/sxo/blob/main/src/js/esbuild/jsx-helpers.js). These utilities emulate JSX semantics while keeping the Rust/WASM side focused purely on syntax transformation.

### `__jsxComponent`: Component and Element Rendering

The `__jsxComponent` helper handles the creation of both intrinsic HTML elements and user-defined components. According to the source code in [`src/js/esbuild/jsx-helpers.js#L6-L59`](https://github.com/gc-victor/sxo/blob/main/src/js/esbuild/jsx-helpers.js#L6-L59), this function accepts three parameters: a component reference or tag string, a props array or object, and optional children.

This helper validates the component type, handles prop spreading, serializes attributes, and constructs the final HTML string by building opening tags, injecting child content, and appending closing tags. When the transformer encounters a JSX element like `<div className="app">`, it emits a call to this helper with the normalized attributes.

### `__jsxSpread`: Attribute Serialization and Normalization

Defined in [`src/js/esbuild/jsx-helpers.js#L66-L109`](https://github.com/gc-victor/sxo/blob/main/src/js/esbuild/jsx-helpers.js#L66-L109), the `__jsxSpread` helper converts plain JavaScript objects into serialized HTML attribute strings. It performs critical normalizations such as converting `className` to `class`, `htmlFor` to `for`, and transforming event handler properties into their `on…` equivalents.

This utility takes an object of spread props and returns a string that can be directly interpolated into the template literal output. For example, when JSX contains `{...props}`, the transformer generates a call to `__jsxSpread(props)` to handle the runtime serialization.

### `__jsxList`: Array Flattening for Dynamic Children

The `__jsxList` helper, located at [`src/js/esbuild/jsx-helpers.js#L1-L4`](https://github.com/gc-victor/sxo/blob/main/src/js/esbuild/jsx-helpers.js#L1-L4), ensures that expressions yielding arrays—such as those produced by `Array.map`, `flatMap`, `forEach`, `filter`, or `reduce`—are converted into concatenated strings suitable for template literal insertion.

Without this helper, dynamic lists would output as comma-separated array literals instead of merged markup. The function accepts an array of child strings and returns a single flattened string, maintaining valid HTML structure when iterating over data in JSX.

## Global Scope Injection Mechanism

To eliminate the need for import statements in transformed modules, the helpers are explicitly exported onto the global object. As implemented at the bottom of [`src/js/esbuild/jsx-helpers.js#L110-L112`](https://github.com/gc-victor/sxo/blob/main/src/js/esbuild/jsx-helpers.js#L110-L112):

```javascript
globalThis.__jsxComponent = __jsxComponent;
globalThis.__jsxSpread   = __jsxSpread;
globalThis.__jsxList     = __jsxList;

```

This design choice ensures that the emitted JavaScript remains portable across Node.js, Bun, Deno, and Cloudflare Workers without requiring a specific module resolution strategy. The Rust/WASM transformer focuses solely on converting JSX syntax into template literals that invoke these global helpers, delegating all runtime behavior to the JavaScript implementation.

## JSX to JavaScript Transformation Examples

The following examples demonstrate how the transformer emits calls to these runtime helpers based on different JSX patterns.

### Simple Intrinsic Elements

When transforming standard HTML elements, the compiler generates `__jsxComponent` calls with string tag names:

```javascript
// JSX source
const el = <div className="banner" title="Welcome">Hello</div>;

```

**Transformed output:**

```javascript
const el = `\${__jsxComponent("div", [{"class":"banner","title":"Welcome"}], "Hello")}`;

```

The helper constructs the opening `<div class="banner" title="Welcome">`, inserts the text child, and adds the closing `</div>`.

### Components with Spread Props

For components receiving spread attributes, the transformer combines `__jsxComponent` with `__jsxSpread`:

```javascript
// JSX source
const extra = { id: "main", disabled: true };
const el = <Button {...extra} />;

```

**Transformed output:**

```javascript
const el = `\${__jsxComponent(Button, [${__jsxSpread(extra)}])}`;

```

Here, `__jsxSpread` serializes the `extra` object into the string ` id="main" disabled`, which the component helper interpolates into the final markup.

### Dynamic Lists of Children

When mapping arrays to JSX elements, the `__jsxList` helper ensures proper string concatenation:

```javascript
// JSX source
<ul>{items.map(i => <li>{i}</li>)}</ul>

```

**Transformed output:**

```javascript
const el = `<ul>\${__jsxList(items.map(i => \`<li>\${i}</li>\`))}</ul>`;

```

The helper converts the array returned by `map` into a single string, preventing comma separators from appearing in the rendered HTML.

### Nested Component Structures

Complex nesting generates recursive helper calls:

```javascript
// JSX source
const Page = ({ title, children }) => (
  <html>
    <head><title>{title}</title></head>
    <body>{children}</body>
  </html>
);

```

**Transformed output:**

```javascript
const Page = ({ title, children }) => 
  `\${__jsxComponent("html", [], 
    \`\${__jsxComponent("head", [], \`<title>\${title}</title>\`)}\` +
    \`\${__jsxComponent("body", [], children)}\`)}`
;

```

Each JSX boundary becomes a distinct `__jsxComponent` invocation, with children passed as strings or references to be recursively processed.

## Key Source Files and Architecture

Understanding the complete lifecycle of these helpers requires examining several files in the `src/js/esbuild/` directory:

- **[`src/js/esbuild/jsx-helpers.js`](https://github.com/gc-victor/sxo/blob/main/src/js/esbuild/jsx-helpers.js)**: Declares the three runtime helpers and attaches them to `globalThis`.
- **[`src/js/esbuild/jsx_transformer.test.js`](https://github.com/gc-victor/sxo/blob/main/src/js/esbuild/jsx_transformer.test.js)**: Contains test suites demonstrating how the WASM transformer emits calls to these helpers.
- **[`src/js/esbuild/jsx-helpers.test.js`](https://github.com/gc-victor/sxo/blob/main/src/js/esbuild/jsx-helpers.test.js)**: Provides unit tests for the helper implementations, covering prop spreading, list handling, and component validation.
- **[`src/js/esbuild/esbuild-jsx.plugin.js`](https://github.com/gc-victor/sxo/blob/main/src/js/esbuild/esbuild-jsx.plugin.js)**: The esbuild plugin that integrates the Rust/WASM transformer into the build pipeline.
- **[`src/js/esbuild/esbuild-jsx.plugin.test.js`](https://github.com/gc-victor/sxo/blob/main/src/js/esbuild/esbuild-jsx.plugin.test.js)**: Verifies that generated bundles contain the required helper identifiers.

This architecture isolates heavy parsing logic to the Rust/WASM layer while maintaining a minimal, pure-JavaScript runtime footprint that requires no external dependencies.

## Summary

- The **sxo** Rust/WASM JSX transformer generates exactly three runtime helpers: **`__jsxComponent`**, **`__jsxSpread`**, and **`__jsxList`**.
- These helpers are defined in [`src/js/esbuild/jsx-helpers.js`](https://github.com/gc-victor/sxo/blob/main/src/js/esbuild/jsx-helpers.js) and attached to `globalThis` to eliminate import overhead.
- **`__jsxComponent`** handles element creation and component invocation with proper attribute and child handling.
- **`__jsxSpread`** serializes prop objects into HTML attribute strings with React-to-HTML name mapping.
- **`__jsxList`** flattens arrays of child elements into concatenated strings for template literal compatibility.
- The design produces ESM-only output compatible with Node.js 20+, Bun, Deno, and Cloudflare Workers.

## Frequently Asked Questions

### Why does the sxo JSX transformer use global helpers instead of ES module imports?

The transformer attaches helpers to `globalThis` to keep emitted code maximally portable across JavaScript runtimes. By avoiding ES module imports, the output works immediately in ESM-only environments without requiring a specific import map or node_modules resolution strategy, making it suitable for edge computing platforms like Cloudflare Workers.

### How does `__jsxSpread` handle HTML attribute normalization?

According to the implementation in `src/js/esbuild/jsx-helpers.js#L66-L109`, the `__jsxSpread` function explicitly maps React-specific prop names to their HTML equivalents—converting `className` to `class`, `htmlFor` to `for`, and formatting event handlers—ensuring the output follows standard HTML conventions rather than React's DOM API naming.

### Can I use the sxo JSX transformer in environments other than Node.js?

Yes. Because the runtime helpers are pure JavaScript attached to the global scope and the transformer outputs standard ESM template literals, the generated code runs without modification in Bun, Deno, and Cloudflare Workers. The Rust/WASM compilation step occurs at build time, leaving only portable JavaScript for the runtime.

### Where are the runtime helpers injected into the final bundle?

The helpers are injected once per bundle by the code at `src/js/esbuild/jsx-helpers.js#L110-L112`, which explicitly assigns `globalThis.__jsxComponent`, `globalThis.__jsxSpread`, and `globalThis.__jsxList`. The esbuild plugin ([`esbuild-jsx.plugin.js`](https://github.com/gc-victor/sxo/blob/main/esbuild-jsx.plugin.js)) ensures this file is included in any build using the JSX transformer.