Skip to main content

StaticJsTypeFactory

The type factory is the primary way to create and coerce values within a realm. It is accessible by the types property of StaticJsRealm.

Import

import type { StaticJsTypeFactory } from "@suntime-js/core";

Overview

Every value used inside the sandbox must be a StaticJsValue owned by the same realm. The type factory creates those values and coerces native host values into their sandbox equivalents.

const realm = StaticJsRealm();

const n = realm.types.number(42);
const s = realm.types.string("hello");
const obj = realm.types.object({ x: { value: n, enumerable: true } });

Values created by one realm cannot be shared with another realm.


Well-known values

These properties return the canonical singleton instances for their type. Use them instead of constructing new instances each time.

PropertyTypeSandbox equivalent
undefinedStaticJsUndefinedundefined
nullStaticJsNullnull
trueStaticJsBooleantrue
falseStaticJsBooleanfalse
zeroStaticJsNumber0
NaNStaticJsNumberNaN
InfinityStaticJsNumberInfinity

Well-known symbols

symbols

Type: IntrinsicSymbols

The realm's well-known Symbol.* instances. Use these instead of creating new symbols when you need a spec-defined symbol.

KeySandbox equivalent
asyncDisposeSymbol.asyncDispose
asyncIteratorSymbol.asyncIterator
disposeSymbol.dispose
hasInstanceSymbol.hasInstance
isConcatSpreadableSymbol.isConcatSpreadable
iteratorSymbol.iterator
matchSymbol.match
matchAllSymbol.matchAll
replaceSymbol.replace
searchSymbol.search
speciesSymbol.species
splitSymbol.split
toPrimitiveSymbol.toPrimitive
toStringTagSymbol.toStringTag
unscopablesSymbol.unscopables

symbolRegistry

Type: Map<string, StaticJsSymbol>

The realm's global symbol registry. This is the sandbox-side equivalent of Symbol.for / Symbol.keyFor. Keys are the description strings passed to Symbol.for(...) inside the sandbox.


Factory methods

boolean(value)

boolean(value: boolean): StaticJsBoolean

Creates a StaticJsBoolean. Prefer types.true and types.false when the value is a literal.

number(value)

number(value: number): StaticJsNumber

Creates a StaticJsNumber. Prefer types.zero, types.NaN, and types.Infinity for those specific values.

string(value)

string(value: string): StaticJsString

Creates a StaticJsString.

symbol(description?)

symbol(description?: string): StaticJsSymbol

Creates a fresh StaticJsSymbol. Equivalent to Symbol(description).

object(properties?, prototype?)

object(
properties?:
| Record<string, StaticJsPropertyDescriptorRecord>
| Map<StaticJsPropertyKey, StaticJsPropertyDescriptorRecord>,
prototype?: StaticJsObject | StaticJsNull | null,
): StaticJsPlainObject

Creates a plain object. properties is a map of StaticJsPropertyKey keys to descriptor records, which may be strings or StaticJsSymbol instances. (). prototype defaults to the realm's Object.prototype when omitted.

const obj = realm.types.object({
x: { value: realm.types.number(1), enumerable: true, writable: true, configurable: true },
y: { value: realm.types.number(2), enumerable: true, writable: true, configurable: true },
});

StaticJsPropertyDescriptorRecord

PropertyTypeDescription
value?StaticJsValueData descriptor value.
writable?booleanWhether the value can be reassigned.
get?StaticJsCallable | undefinedAccessor getter.
set?StaticJsCallable | undefinedAccessor setter.
enumerable?booleanAppears in for...in / Object.keys.
configurable?booleanWhether the descriptor itself can change.

array(itemsOrLength?)

array(itemsOrLength?: StaticJsValue[] | number): StaticJsArray

Creates a StaticJsArray. Pass an array of StaticJsValue to pre-populate it, or a number to create a sparse array with the given length.

const arr = realm.types.array([realm.types.number(1), realm.types.string("hello")]);

function(name, func, opts?)

function(
name: string,
func: (this: StaticJsValue, ...args: StaticJsValue[]) => MaybeEvaluationGenerator<StaticJsValue>,
opts?: StaticJsFunctionTypeCreationOptions,
): StaticJsFunction

Creates a host-defined function that participates in the task runner. For best results, func should be a generator function so it can be suspended and resumed by the task runner. See Evaluator Functions for the full authoring guide.

const add = realm.types.function("add", function* (a, b) {
// ...
return realm.types.number(/* result */);
});

StaticJsFunctionTypeCreationOptions

PropertyTypeDefaultDescription
isConstructorbooleanfalseWhether the function can be called with new.
lengthnumberfunc.lengthThe function's reported .length (formal parameter count).
prototypeStaticJsObject | StaticJsNull | nullFunction.prototype intrinsicThe prototype for the new function. Not to be confused with the prototype property.

error(errorType?, message)

error(errorType: ErrorTypeName, message: string): StaticJsObject
error(message: string): StaticJsObject

Creates a sandbox error object. When called with two arguments, errorType sets which error constructor is used. When called with one string argument, defaults to "Error".

const err = realm.types.error("TypeError", "Expected a number");
throw new StaticJsRuntimeError(err);

ErrorTypeName is one of: "Error", "TypeError", "ReferenceError", "SyntaxError", "RangeError", "AggregateError".

Note that errors created this way will not have a stack trace.

proxy(target, handlers)

proxy(target: StaticJsProxyTarget, handlers: StaticJsProxyHandlers): StaticJsProxy

Creates a StaticJsProxy, the sandbox equivalent of new Proxy(target, handlers). All handler methods may be ordinary functions or EvaluationGenerator functions.

StaticJsProxyTarget accepts an existing StaticJsObject or StaticJsCallable, a native object or Function, or the string literals "object" or "function" to create a fresh empty target of the given shape.

StaticJsProxyHandlers

All traps are optional. Each receives a StaticJsObject (or StaticJsCallable for apply/construct) as its first argument and may return a value or yield from an EvaluationGenerator.

TrapSignature
getPrototypeOf(target) => StaticJsObject | null
setPrototypeOf(target, prototype) => boolean
isExtensible(target) => boolean
preventExtensions(target) => boolean
getOwnPropertyDescriptor(target, key) => StaticJsPropertyDescriptor | undefined
defineProperty(target, key, desc) => boolean
has(target, key) => boolean
get(target, key, receiver) => StaticJsValue
set(target, key, value, receiver) => boolean
deleteProperty(target, key) => boolean
ownKeys(target) => StaticJsPropertyKey[]
apply(target, thisArgument, argArray) => StaticJsValue
construct(target, argArray, newTarget) => StaticJsObject

toStaticJsValue(value)

toStaticJsValue(value: unknown): StaticJsValue

Coerces a native host value into the sandbox. Scalars (boolean, number, string, symbol, null, undefined) are wrapped in their StaticJs counterparts. Functions are wrapped as non-generator host functions. Objects and arrays become shallow-on-demand proxies: only own enumerable properties are visible, they are read-only, and the prototype is replaced with the sandbox's Object.prototype.

Object coercion caveats

Coerced objects are read-only proxies. Writes made inside the sandbox are silently discarded. If you need a mutable object, create it with types.object(...) and set properties explicitly.

See Type Coercion for the complete coercion rules.