# Browser WASM

> Compile Java or Kotlin to WasmGC with Elide: build a WebAssembly module and JavaScript loader, load it from a web page, and check browser support.

A [WebImage](https://elide.help/docs/toolchain/jvm/webimage) artifact with `backend = "wasm-gc"` compiles Java or Kotlin to WasmGC: a
WebAssembly module whose objects live in the browser's garbage-collected heap, plus a JavaScript loader that fetches
and starts it. To run an existing `.wasm` file with Elide, see [WebAssembly](https://elide.help/docs/wasm).

## Prerequisites

- [Binaryen](https://github.com/WebAssembly/binaryen) 119 or later, with `wasm-as` on `PATH` at build time.
- Code that meets the [Native Image requirements](https://elide.help/docs/toolchain/jvm/native-image): reachability metadata for reflection,
  resources and proxies; no native dependencies.

## Build

```text
hello-wasm/
  elide.pkl
  src/main/java/Hello.java
```

```java
public class Hello {
  public static void main(String[] args) {
    System.out.println("Hello from WasmGC");
  }
}
```

```pkl
amends "elide:project.pkl"
import "elide:Jvm.pkl" as jvm
import "elide:NativeImage.pkl" as nativeImage

name = "hello-wasm"

artifacts {
  ["app-jar"] = new jvm.Jar {
    sources { "main" }
  }
  ["web"] = new nativeImage.WebImage {
    from { "app-jar" }
    name = "hello"
    entrypoint = "Hello"
    backend = "wasm-gc"
    runtime = "browser"
  }
}
```

```bash
elide build
```

Output goes to `.dev/artifacts/native-image/`:

| File | Deploy | Hello-world size |
| --- | --- | --- |
| `hello.js` | Yes: the loader. | 110 KB |
| `hello.js.wasm` | Yes: the module. | 1.3 MB (480 KB gzipped) |
| `hello.js.wat` | No: text form, for inspection. | 32 MB |
| `hello.js.map` | Optional: emitted with `sourceMap = true`. | |

| Property | Browser value |
| --- | --- |
| `backend` | `"wasm-gc"` (the default). |
| `runtime` | `"browser"`, or `"generic"` to keep Node support in the same loader. |
| `autoRun` | `true` (default) runs `main` when `hello.js` loads. |

Other properties and compiler options: [WebImage](https://elide.help/docs/toolchain/jvm/webimage#choose-a-backend-and-host).

## Load it in a page

Put `index.html` next to the bundle:

```html
<!doctype html>
<html lang="en">
  <meta charset="utf-8" />
  <title>Hello WasmGC</title>
  <body>
    <script src="./hello.js"></script>
  </body>
</html>
```

```bash
elide dev --no-tui --port 8000 .dev/artifacts/native-image
```

Open `http://localhost:8000/`; `Hello from WasmGC` appears in the browser console.

- The loader requests the module at its own URL plus `.wasm`, so keep `hello.js` and `hello.js.wasm` in the same
  directory.
- Load it with a classic `<script>`. With `type="module"` the loader requests the page's URL plus `.wasm` instead.
- Serve over HTTP or HTTPS; `file://` URLs do not work.
- `System.out` writes to the browser console.

To deploy, copy `hello.js`, `hello.js.wasm` and the page to any static host.

## Browser support

WasmGC bundles need WebAssembly garbage collection and exception handling with `exnref`:

| Browser | Minimum version |
| --- | --- |
| Chrome, Edge | 137 |
| Firefox | 131 |
| Safari | 18.4 |

An older browser rejects the module with a `CompileError` when the page loads. To serve hosts without WasmGC, see
[Edge WASM](https://elide.help/docs/toolchain/edge/wasm).
