JavaScript support
Which parts of modern JavaScript scripts can use, and the short list of exclusions that keep evaluation deterministic.
Scripts are modern JavaScript - the current ECMAScript standard library, minus a small set of exclusions that exist to keep evaluation deterministic and sandboxed. If a construct is ordinary JavaScript and not listed below, it works: classes, arrow functions, destructuring, template literals, iterators, Map/Set, typed arrays, JSON, the full Math object and friends.
The module shape
A script is a module. Its top level runs ONCE when the script compiles - the place for constants, helper functions and module-level handles - and the exported frame() runs once per evaluated frame:
export const outputs = ["layer_1:transform.position"];
const RADIUS = 120;
export function frame({ time, dt, frame, fps }) {
return [320 + Math.cos(time) * RADIUS, 180 + Math.sin(time) * RADIUS];
}
The argument to frame() carries the clock: time (seconds), dt (one frame in seconds), frame (the integer frame) and fps. The same values are available as globals, with ONE caution: inside frame() the bare word frame names the function itself, so destructure { frame } from the argument whenever you need the frame number in the body.
Excluded on purpose
evalandnew Function- no code from strings; both throw immediately.WeakRefandFinalizationRegistry- garbage-collector timing must never influence a frame.SharedArrayBufferandAtomics- no shared memory, no timing channels.Date.now()and the real clock -Datereports the comp's time; the time zone is pinned to UTC on every host.- Unseeded
Math.random- the global is replaced by the seeded stream, the same numbers on every machine (see Determinism). - Host surfaces - no
fetch, no DOM, no workers, no storage.typeof windowis"undefined", exactly as in any plain sandbox.
Absent libraries
Intl and Temporal are not present - locale tables and calendar databases would make renders differ between machines. Format numbers with the standard tools instead (toFixed, padStart, template literals - the Formatting page collects the recipes), and do date maths in frames and seconds.
Promises settle inside the frame
async helpers and promises work, but everything must SETTLE within the frame being evaluated - a frame's value cannot arrive later. A frame() whose returned promise never settles reports the typed async_unsettled error. In practice: use plain synchronous code in frame(); there is nothing asynchronous worth awaiting inside a sandbox with no outside world.
Budgets, not trust
The runtime does not rely on scripts being polite. Poll budgets stop runaway loops, a memory ceiling stops runaway allocation and a stack guard stops runaway recursion - each reported as a typed status while the frame renders with base values. The numbers live on the Budgets page.