Skip to content

Export Functions

The @export decorator marks a function to be exposed as a public symbol of the wasm module. With --aot --host browser mode, the compiler generates:

  • 03-export.wasm — the compiled module
  • 03-export.js — typed JS wrappers for each @export function
  • 03-export.d.ts — corresponding TypeScript declarations

On the JS/TS side, usage feels natural:

import init, { fib, greet, even } from './03-export.js';
await init(); // instantiate the module
fib(10); // 55
greet('Zolo'); // "Hello, Zolo!"
even(4); // true

Boundary types (MVP): intnumber, boolboolean, strstring, and void return. Strings cross the boundary via generated glue (the loader writes the JS string into wasm memory and reads the result back); int and bool cross directly. Any other type in an @export function (float, arrays, structs) fails the build with E_WasmAotUnsupportedFeature.

Top-level code continues to run in zolo_main() — call it from JS if you need the initialization side effect:

Three @export functions with scalar boundary types: int, str, and bool.

03-export.zolo
// Feature: export Zolo functions to JS/TS — `@export` (AOT wasm)
// Syntax: `@export fn name(args) -> T { ... }`
// When to use: build a Zolo library that JavaScript/TypeScript calls directly.
//
// Build (AOT, browser):
//   zolo build 32-webassembly/03-export.zolo --emit wasm --host browser --aot \
//     -o 32-webassembly/target/03-export.wasm
//   # -> 03-export.wasm + 03-export.js (typed wrappers) + 03-export.d.ts
//
// Then from JS/TS:
//   import init, { fib, greet, even } from "./03-export.js"
//   await init()              // instantiate the module
//   fib(10)                   // 55
//   greet("Zolo")             // "Hello, Zolo!"
//   even(4)                   // true
//
// Boundary types (MVP): int <-> number, bool <-> boolean, str <-> string,
// and a void return. Anything else on an @export (float, arrays, structs)
// fails the build with E_WasmAotUnsupportedFeature. Strings cross via the
// generated glue (it writes the JS string into wasm memory and reads results
// back); int/bool cross directly. `print` still goes to the console.

@export
fn fib(n: int) -> int {
  if n < 2 { return n }
  return fib(n - 1) + fib(n - 2)
}

@export
fn greet(name: str) -> str {
  return "Hello, {name}!"
}

@export
fn even(n: int) -> bool {
  return n % 2 == 0
}

// Top-level code still runs on `zolo_main()` (call it from JS if you want it).
"03-export loaded" |> print()

// expected (run natively): 03-export loaded

Requires the Zolo CLI/host — open in the playground or run locally.

Challenge

Add a fourth @export fn square(n: int) -> int that returns n * n. Recompile and confirm that it appears in the generated .d.ts.

enespt-br