Resident buffers
Examples assume an initialized engine; see getting started.
Reuse memory within a scope
Use a scope to upload once, reuse allocations across operations, and copy the result back once. This avoids intermediate copies between JS and Wasm memory.
const processed = engine.scope(scope => {
const left = scope.f32.from(new Float32Array([0.2, 0.4, 0.6]))
const right = scope.f32.from(new Float32Array([0.1, 0.3, 0.5]))
const output = scope.f32.alloc(left.length)
scope.f32.add(left, right, { out: output })
scope.f32.mul(output, 0.5, { out: output })
scope.f32.clamp(output, 0, 1, { out: output })
return output.toArray()
})Each operation remains a separate traversal. Scope allocations are released in a finally block, including when your callback throws. Returning a buffer does not extend its lifetime. Promise/thenable results are rejected; use a persistent arena when the lifetime must span frames or asynchronous application code.
Keep buffers across calls
const arena = engine.createArena()
try {
const samples = arena.f32.alloc(1024) // initialized to zero
const output = arena.f32.alloc(1024)
samples.set(new Float32Array(1024).fill(0.25))
arena.f32.mul(samples, 2, { out: output })
const frame = output.toArray()
// Reuse samples and output on the next frame.
} finally {
arena.dispose()
}arena.f32 has the same operations, using F32Buffer instead of Float32Array. from and set always copy; toArray always returns an independent copy. There are no exposed pointers or persistent Wasm memory views.
Ownership and output rules
| Memory rule | Behavior |
|---|---|
| Exact input/output alias | Supported, including two views of the same exact region |
| Partial output/input overlap | Rejected before writing |
| Read-only inputs overlap | Supported |
| Array or buffer lengths differ | RangeError |
| Different engines' buffers mixed | Rejected |
| Different live arenas of the same engine | Supported |
| Access after arena/engine disposal | Rejected; disposal itself is idempotent |
| Wasm memory grows | Existing buffer handles remain valid |
| Shared, resizable or detached backing memory | Rejected |
| TypedArrays from a different JS realm | Rejected; copy into this realm first |
Copying and reclamation
Ordinary TypedArray calls to native borrow the existing memory synchronously; provided outputs are written directly. Ordinary TypedArray calls to Wasm copy inputs into scratch allocations and copy results back. Resident allocations avoid those per-operation copies. Arena disposal releases its allocations for reuse; Wasm linear memory does not shrink until the engine is disposed and collected. Retaining a disposed buffer does not retain its allocation.