API Reference
Core Compilation
WasmTarget.compile — Function
compile(f, arg_types; optimize=false) -> Vector{UInt8}Compile a Julia function f with the given argument types to WebAssembly bytes. Returns a valid WebAssembly binary that can be instantiated and executed.
Set optimize=true for size-optimized output (default -Os like dart2wasm), optimize=:speed for -O3, or optimize=:debug for -O1 without --traps-never-happen.
WasmTarget.compile_multi — Function
compile_multi(functions; optimize=false) -> Vector{UInt8}Compile multiple Julia functions into a single WebAssembly module.
Each element should be (function, argtypes) or (function, argtypes, name).
Set optimize=true for size-optimized output, optimize=:speed for -O3, or optimize=:debug for -O1 without --traps-never-happen.
Example
wasm_bytes = compile_multi([
(add, (Int32, Int32)),
(sub, (Int32, Int32)),
(helper, (Int32,), "internal_helper"),
])Functions can call each other within the module.
WasmTarget.compile_from_codeinfo — Function
compile_from_codeinfo(code_info, return_type, func_name, arg_types; optimize=false) -> Vector{UInt8}Compile a pre-computed typed CodeInfo to WebAssembly bytes, bypassing Base.codetyped(). This is the entry point for the evaljulia pipeline where type inference has already been run.
Arguments
code_info::Core.CodeInfo: Typed CodeInfo (from Base.code_typed or equivalent)return_type::Type: The inferred return typefunc_name::String: Export name for the WASM functionarg_types::Tuple: Argument types for the functionoptimize: Same as compile() — false, true, :speed, or :debug
WasmTarget.compile_with_base — Function
compile_with_base(functions; base_wasm_path, optimize=false) -> Vector{UInt8}Compile user functions and merge with a pre-compiled base.wasm module. User functions that would normally be compiled standalone are instead compiled into a separate user.wasm module, then merged with base.wasm via wasm-merge.
The merged module contains all base exports + user exports, and user code can call base functions directly.
Arguments
functions: Same format ascompile_multi—[(f, arg_types, name), ...]base_wasm_path: Path to pre-compiled base.wasm (default: base.wasm in project root)optimize: Same as compile() — false, true, :speed, or :debug
Returns
Merged Vector{UInt8} containing both base and user functions.
WasmTarget.optimize — Function
optimize(bytes::Vector{UInt8}; level=:size, validate=true) -> Vector{UInt8}Run Binaryen wasm-opt on compiled WebAssembly bytes for size and performance optimization. Uses dart2wasm's production WasmGC flags by default.
Keywords
level: Optimization level —:size(default,-Oslike dart2wasm),:speed(-O3), or:debug(-O1, no--traps-never-happen)validate: Runwasm-tools validateafter optimization (defaulttrue)
Returns
Optimized Vector{UInt8}.
Throws
- Error if
wasm-optis not found (with install instructions) - Error if optimization or validation fails
Types
WasmTarget.JSValue — Type
JSValueA Julia type representing a JavaScript value held as an externref. Used for DOM elements, JS objects, and other JS values.
This is a primitive type to prevent Julia from optimizing it away.
WasmTarget.WasmGlobal — Type
WasmGlobal{T, IDX}A handle to a WebAssembly global variable at index IDX. When compiled to Wasm:
global[](getindex) →global.get IDXglobal[] = x(setindex!) →global.set IDX, x
The index is a type parameter so it's known at compile time, which is required because Wasm's global.get and global.set instructions take immediate indices.
This is a general-purpose abstraction for any Julia code that needs to interact with Wasm global variables. Use cases include:
- Stateful applications
- Game engines
- Reactive frameworks
- Any code needing mutable Wasm state
Type Parameters
T: The type of value stored in the global (Int32, Float64, etc.)IDX: The Wasm global index (0-based), must be an Int literal
Example
# Define types for specific globals (index is compile-time constant)
const Counter = WasmGlobal{Int32, 0} # Global index 0
const Flag = WasmGlobal{Int32, 1} # Global index 1
# Functions that use globals - index is known from the type
function increment(g::Counter)::Int32
g[] = g[] + Int32(1)
return g[]
end
function toggle(g::Flag)::Int32
g[] = g[] == Int32(0) ? Int32(1) : Int32(0)
return g[]
end
# Create instances (value is for Julia-side testing)
counter = Counter(0)
flag = Flag(1)
# Compile to Wasm - global index extracted from type
wasm_bytes = compile(increment, (Counter,))WasmTarget.WasmModule — Type
WasmModuleA WebAssembly module builder. Use this to construct modules programmatically.
Module Building
WasmTarget.add_import! — Function
add_import!(mod, module_name, field_name, params, results) -> func_idxAdd an imported function to the module and return its function index. Imported functions come before local functions in the function index space.
WasmTarget.add_function! — Function
add_function!(mod, params, results, locals, body) -> func_idxAdd a function to the module and return its index. Note: Local function indices start after imported functions. Params and results can be NumType or WasmValType vectors.
WasmTarget.add_export! — Function
add_export!(mod, name, kind, idx)Add an export entry to the module.
- kind: 0=func, 1=table, 2=memory, 3=global
WasmTarget.add_global! — Function
add_global!(mod, valtype, mutable, init_value) -> global_idxAdd a global variable to the module and return its index. The init_value should be a constant of the appropriate type.
WasmTarget.add_global_export! — Function
add_global_export!(mod, name, global_idx)Export a global variable.
Package Extensions
WasmTarget.register_package! — Function
register_package!(name::Symbol, functions::Vector)Register a package's functions for pre-compilation. Each entry is (function, argtypes) or (function, argtypes, export_name).
WasmTarget.list_packages — Function
list_packages() -> Vector{Symbol}List all registered curated packages.
WasmTarget.package_functions — Function
package_functions(name::Symbol) -> Vector{Tuple{Any, Tuple}}Get the registered functions for a package.
WasmTarget.compile_with_packages — Function
compile_with_packages(user_functions::Vector, packages::Vector{Symbol}; optimize=false)
-> Vector{UInt8}Compile user functions alongside pre-registered package functions in a single module. Package functions are included alongside user functions so cross-calls resolve correctly.
Caching
WasmTarget.compile_cached — Function
compile_cached(f, arg_types::Tuple; optimize=false) -> Vector{UInt8}Like compile() but uses the global cache. Enable with enable_cache!().
WasmTarget.compile_multi_cached — Function
compile_multi_cached(functions::Vector; optimize=false, kwargs...) -> Vector{UInt8}Like compile_multi() but uses the global cache.
WasmTarget.enable_cache! — Function
enable_cache!(; max_entries=256)Enable the global compilation cache. Subsequent calls to compile() and compile_multi() will use the cache.
WasmTarget.disable_cache! — Function
disable_cache!()Disable the global compilation cache.
WasmTarget.clear_cache! — Function
clear_cache!()Clear all entries from the global compilation cache.
WasmTarget.cache_stats — Function
cache_stats() -> NamedTupleReturn cache hit/miss statistics.
Source Maps
WasmTarget.compile_with_sourcemap — Function
compile_with_sourcemap(f, arg_types; optimize=false, sourcemap_url="module.wasm.map")
-> (wasm_bytes, sourcemap_json)Compile a function and generate both the Wasm binary and a Source Map V3 JSON. The Wasm binary includes a sourceMappingURL custom section.
WasmTarget.compile_multi_with_sourcemap — Function
compile_multi_with_sourcemap(functions; optimize=false, sourcemap_url="module.wasm.map")
-> (wasm_bytes, sourcemap_json)Compile multiple functions and generate both Wasm binary and Source Map V3 JSON.
Low-Level / Advanced
WasmTarget.to_bytes — Function
to_bytes(mod::WasmModule) -> Vector{UInt8}Serialize a WasmModule to binary format.
WasmTarget.FrozenCompilationState — Type
FrozenCompilationStateSnapshot of WasmModule + TypeRegistry after all setup (type registration, hierarchy, box types, etc.) but BEFORE function body compilation. This allows Phase 1-mini to pre-compute the Dict-heavy setup at build time and ship only the pure codegen to WASM.
The frozen state captures everything needed to compile function bodies without re-running any Dict-based setup code.
WasmTarget.build_frozen_state — Function
build_frozen_state(ir_entries::Vector) -> FrozenCompilationStateRun the SETUP portion of compilemodulefromir for representative functions, capturing the resulting WasmModule and TypeRegistry state. The frozen state can then be used by compilemodulefromir_frozen to skip all Dict-heavy setup.
Each entry is (codeinfo::CodeInfo, returntype::Type, arg_types::Tuple, name::String).
WasmTarget.TypeRegistry — Type
Registry for struct and array type mappings within a module.
WasmTarget.FunctionRegistry — Type
Registry for functions within a module, enabling cross-function calls.
WasmTarget.compile_handler — Function
compile_handler(closure, signal_fields, export_name; globals, imports, dom_bindings) -> WasmModuleCompile a Therapy.jl event handler closure to WebAssembly with signal substitution.
The signal_fields dict maps captured closure field names to their signal info:
- Key: field name (Symbol), e.g., :count, :set_count
- Value: tuple (isgetter::Bool, globalidx::UInt32, value_type::Type)
The handler closure should take no arguments. Signal getters/setters are captured in the closure and compiled to Wasm global.get/global.set operations.
When dom_bindings is provided, DOM update calls are automatically injected after each signal write. This is used by Therapy.jl for reactive DOM updates.
Example
count, set_count = create_signal(0)
handler = () -> set_count(count() + 1)
signal_fields = Dict(
:count => (true, UInt32(0), Int64), # getter for global 0
:set_count => (false, UInt32(0), Int64) # setter for global 0
)
mod = compile_handler(handler, signal_fields, "onclick")WasmTarget.DOMBindingSpec — Type
Specification for a DOM update call after signal write. Used by compile_handler to inject DOM update calls after signal writes.