Runtime
Reactive.Runtime is what a driver calls. A program uses
Reactive.State, Reactive.Reverse, Reactive.Match, and the rest of the
application surface. The calls below are the ones a driver needs to register its types and holes, to see locks,
to keep a child scope, and to write a value back.
Driver
Reactive.Runtime.Driver(name, body) builds the instance you pass to Reactive.Run.
The name is the context. The body registers that context's types and holes.
const maths = Reactive.Runtime.Driver("Maths", () => {
Reactive.Runtime.NativeType(Maths.Integer.Number, { default: 0 });
Reactive.Runtime.Simple("Add", (left, right) => left + right);
});NativeType
Reactive.Runtime.NativeType(type, options) registers a native type on the context.
options.default is the value, or a function that returns it. options.parse is
optional. The parser receives source text and returns the value. A missing field of this type uses the
default.
Simple
Reactive.Runtime.Simple(name, calculation) implements a hole that finishes in the call. The
calculation receives the raw values of the inputs, in order, and returns the raw result. The runtime applies
the read lock and the write lock. Maths and strings use this.
Full
Reactive.Runtime.Full(name, body) implements a hole that sees the locks, or writes a value
later. The body receives each argument as a boxed value. If, Each, a network
request, and a control use this.
Value
Reactive.Runtime.Value(boxed) returns the raw value inside a boxed argument. A full hole uses
it when it needs the current contents. The raw value of a native type is the value that driver stored.
Locks
Reactive.Runtime.Locks(boxed) returns the read lock and the write lock. The read lock is a
flag. The write lock is a counter. The program does not receive this. A driver that finds the write lock
set chooses to cancel the root process, or to keep its own queue and call Set when the lock
is clear.
Set
Reactive.Runtime.Set(target, value) writes a state or a reverse the hole was given. One write
is one refresh. A write of state stores that state. A write of a reverse starts a reverse process. A call
that belonged to a reverse process which has finished is not made again.
Cancel
Reactive.Runtime.Cancel(target) cancels the root process that holds that value. The locks
release and nothing is stored. A participating reverse is left in place. The driver then calls
Set if it still has a new value.
Probe
Reactive.Runtime.Probe(arm) runs the arm and returns the gather objects it emitted into. The
arm stores no state and sets no reverse. A read-locked If or Each probes each arm,
locks those gathers, and takes no arm. Nested If and Each drivers see the probe and
probe their own arms.
const gathers = Reactive.Runtime.Probe(arm);Enter and Absent
Reactive.Runtime.Enter(body) runs the body in the child scope of the current If
slot. The next run finds the same scope. Reactive.Runtime.Absent() leaves that scope unused.
The If driver calls one of them after it has read the condition. A read-locked condition calls
neither, and calls Probe instead.
Each
Reactive.Runtime.Each(elements, body) keeps one child scope per element. elements
is the list of stable ids and values the driver read from its array. The runtime matches the scopes it held
last time by those ids, runs body for each id that is present, and drops a scope whose id is
gone.
Id
Reactive.Runtime.Id() allocates a stable id. The id is not a slot in the program. The driver
stores it in its own map, for example from the id to a DOM node. The runtime does not keep that map.
After
Reactive.Runtime.After(hook) runs the hook when the refresh finishes. The hook receives the
ids this driver's holes produced this time. The driver reconciles there and clears its list for the next
run.