# WASM in the Browser

## JavaScript + WebAssembly

MatchBox can compile BoxLang for the browser and Node.js via WebAssembly. There are three distinct modes, chosen to match different use-cases.

| Mode                   | Command                                 | Use case                                         |
| ---------------------- | --------------------------------------- | ------------------------------------------------ |
| **JS Module (AOT)**    | `--target js`                           | Ship a pre-compiled BoxLang app as an ES module  |
| **WASM binary (AOT)**  | `--target wasm`                         | Raw `.wasm` binary, brought your own loader      |
| **Runtime (JIT-like)** | Build `pkg/` once, call `run_boxlang()` | Execute source strings at runtime in the browser |

***

### Mode 1: JavaScript ES Module (AOT)

This is the recommended way to ship a BoxLang application to the browser. MatchBox compiles your script to bytecode, embeds it in a WASM binary, and wraps it in a JavaScript ES module that bootstraps the runtime automatically.

#### Compile

```bash
matchbox --target js my_lib.bxs
# Produces: my_lib.js  +  my_lib.wasm
```

#### Use in HTML

```html
<!DOCTYPE html>
<html>
<head><title>BoxLang App</title></head>
<body>
<script type="module">
    import { greet, calculate } from './my_lib.js';

    const result = await greet("Developer");
    document.body.textContent = result;
</script>
</body>
</html>
```

#### Use in Node.js

```js
import { greet } from './my_lib.js';

const message = await greet("Node");
console.log(message);
```

#### Exporting Functions

BoxLang functions defined at the top level of your script are automatically exported. Access modifiers have no effect on WASM exports — all functions are accessible:

```boxlang
// my_lib.bxs

function greet(name) {
    return "Hello, " & name & "!"
}

function calculate(a, b) {
    return a * b
}
```

***

### Mode 2: Raw WASM Binary (AOT)

Use `--target wasm` when you want the raw `.wasm` file and full control over how it is loaded. This is useful for integration with non-standard JS runtimes, edge platforms, or when you are bundling the WASM via a tool like Webpack or Vite.

```bash
matchbox --target wasm my_app.bxs
# Produces: my_app.wasm
```

Load it manually using the standard WebAssembly API:

```js
const response = await fetch('./my_app.wasm');
const buffer   = await response.arrayBuffer();
const module   = await WebAssembly.instantiate(buffer, importObject);
```

Refer to the [MDN WebAssembly docs](https://developer.mozilla.org/en-US/docs/WebAssembly) for the full instantiation API.

***

### Mode 3: Runtime Mode (Dynamic Execution)

In runtime mode you ship the MatchBox engine itself (`pkg/`) and execute BoxLang source code dynamically at run time — similar to a JIT. This is useful for:

* Allowing user-provided BoxLang scripts in your application.
* Interactive BoxLang playgrounds.
* Server-side rendering on a WASM-capable edge runtime.

#### HTML Integration

```html
<script type="module">
    import init, { run_boxlang } from './pkg/matchbox.js';

    await init();   // load and compile the WASM runtime

    run_boxlang(`
        name = "Browser"
        println("Hello from BoxLang running in #name#!")
    `);
</script>
```

#### Persistent VM (calling functions by name)

For apps that need to call multiple BoxLang functions efficiently, use the persistent `BoxLangVM` instance rather than re-initialising on every call:

```js
import init, { BoxLangVM } from './pkg/matchbox.js';

await init();

const vm = new BoxLangVM();

// Load a script once  
vm.load_source(`
    function add(a, b) { return a + b }
    function greet(name) { return "Hello, " & name }
`);

// Call functions by name as many times as you like
const sum     = vm.call("add",   [10, 20]);
const message = vm.call("greet", ["BoxLang"]);

console.log(sum, message);
```

***

### JavaScript Interop from BoxLang

When BoxLang code is running inside a browser WASM context, it can access the JavaScript environment through the `js` global:

```boxlang
// DOM access
title = js.document.title
js.document.getElementById("output").innerText = "Updated by BoxLang"

// Browser APIs
js.alert("Hello!")
js.console.log("Logged from BoxLang")

// Location
url = js.window.location.href
```

> `js.*` is only available in browser WASM. Using it in a native build throws a runtime error.

***

### Serving Locally for Development

Browsers block WASM file loading over `file://`. Serve your project with any local HTTP server:

```bash
npx serve .
# or
python3 -m http.server 8080
```

Then open `http://localhost:8080` in your browser.

***

### Production Deployment

The WASM output files (`*.js` + `*.wasm`) can be deployed to any static hosting service:

* **CDN** — Upload to S3, Cloudflare R2, or a similar object store.
* **Vercel / Netlify** — Drop the files into your project's output directory.
* **Edge Workers** — The raw WASM binary can be loaded directly into Cloudflare Workers or similar runtimes. See WASM Container for details.

Ensure your server sets the correct `Content-Type` for `.wasm` files:

```
Content-Type: application/wasm
```

Most modern hosts handle this automatically.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://boxlang.ortusbooks.com/getting-started/running-boxlang/wasm-in-the-browser.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
