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
returnare needed:
let o = ''
for (let i = 0; i < Math.ceil(ui.w / 88); ++i) o += `<rect x="${i * 88}" width="84" height="38"/>`
oTo 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:
| Name | Value |
|---|---|
s | The instance’s view: its state as this instance sees it. |
ui | The pointer state. |
m | The current values of the instance’s motions, by name. |
env | The environment. |
The pointer state
| Member | Type | Description |
|---|---|---|
hover | boolean | The pointer is over the instance (never true on a device without hover). |
down | boolean | A press that began on the instance has not been released. |
focused | boolean | The instance has keyboard focus. |
region | string | The region under the pointer (or under the press while down); "" for none. |
w, h | number | The instance’s current width and height in design units. |
x, y | number | The 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. |
pointerType | string | "mouse", "pen", "touch", "rotary", "spatial" or "". |
shift | boolean | The Shift modifier is held. |
The environment
| Member | Type | Description |
|---|---|---|
width, height | number | The size of the area the root instance is shown in, in design units. |
sizeClass | string | "watch", "compact", "regular", "wide" or "spatial"; see Layout. |
shape | string | "rect" or "round". |
hover | boolean | The primary pointer can hover. |
rotary | boolean | The device has a rotary input (crown, bezel, encoder). |
density | number | Device pixels per design unit. |
dark | boolean | The host’s colour scheme is dark. |
reducedMotion | boolean | The 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;
NaNis treated as0; - where a string is expected, by ToString;
undefinedandnullgive""; - 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.