Skip to content
Ooidget

Ooidget Component Format 0.1Editor's Draft

Expressions

Syntax

An expression is a string of ECMAScript [ECMA-262] in one of two forms:

  • a single Expression: s.on && !ui.down, `${s.tempo} bpm`;
  • a block: a sequence of statements (declarations, loops, conditionals) whose value is the value of its last expression statement, as the completion value of a script is. No wrapping function and no return are needed:
let o = ''
for (let i = 0; i < Math.ceil(ui.w / 88); ++i) o += `<rect x="${i * 88}" width="84" height="38"/>`
o

To evaluate a block, a runtime evaluates it as the body of a function of the scope whose last expression statement is returned. A block whose last statement is not an expression statement evaluates to undefined. An immediately invoked arrow function, (() => { …; return o })(), remains a valid single expression.

A runtime MUST evaluate expressions with the semantics of ECMAScript 2023 or later. It MAY do so by any means, including compiling a recognised subset ahead of time, provided the results are identical.

The scope

An expression is evaluated with exactly these bindings in scope, in addition to the standard globals:

NameValue
sThe instance’s view: its state as this instance sees it.
uiThe pointer state.
mThe current values of the instance’s motions, by name.
envThe environment.

The pointer state

MemberTypeDescription
hoverbooleanThe pointer is over the instance (never true on a device without hover).
downbooleanA press that began on the instance has not been released.
focusedbooleanThe instance has keyboard focus.
regionstringThe region under the pointer (or under the press while down); "" for none.
w, hnumberThe instance’s current width and height in design units.
x, ynumberThe pointer’s position inside the instance, in design units, while it is over the instance or pressing it; absent otherwise. A drag reads where its press began as x - dx, y - dy.
pointerTypestring"mouse", "pen", "touch", "rotary", "spatial" or "".
shiftbooleanThe Shift modifier is held.

The environment

MemberTypeDescription
width, heightnumberThe size of the area the root instance is shown in, in design units.
sizeClassstring"watch", "compact", "regular", "wide" or "spatial"; see Layout.
shapestring"rect" or "round".
hoverbooleanThe primary pointer can hover.
rotarybooleanThe device has a rotary input (crown, bezel, encoder).
densitynumberDevice pixels per design unit.
darkbooleanThe host’s colour scheme is dark.
reducedMotionbooleanThe user prefers reduced motion.

Globals

Expressions and behaviours run in a sandbox. The global object MUST provide the ECMAScript standard built-in objects except those that reach outside the sandbox or depend on time. A runtime MUST NOT expose eval, Function (as a constructor), Date.now, Math.random, timers, network or file access, or any host object not defined here.

Evaluation is deterministic: the same expression with the same scope MUST give the same result. A runtime that needs randomness or time for a component provides it through state.

Results and errors

The result of an expression is converted for its use:

  • where a condition is expected (when), by ECMAScript ToBoolean;
  • where a number is expected, by ToNumber; NaN is treated as 0;
  • where a string is expected, by ToString; undefined and null give "";
  • where a box is expected, the result MUST be an array of four numbers, or the value is treated as absent.

An expression that throws, that does not parse, or that exceeds the runtime’s evaluation budget evaluates to undefined. A runtime MUST continue rendering, and SHOULD report the expression and the error to the host. The evaluation budget MUST allow at least 100,000 loop iterations per expression per frame.