Skip to main content

Interface: ComputeContext

Defined in: model/field.ts:348

What a compute Field runs inside. Built per pass, and two kinds of question live on it (ADR 0017, What a hypothetical row reads with, amended 2026-09-21 — #466). The amendment's rule 1 is why a structure question takes the row it asks about and a value question does not; rule 2 is the value/structure split itself.

A value question — read(key), hierarchyParentId() — stays bound to the row the pass is computing: a bottom-up pass has written only what it has reached, so a value asked of any other row would answer with whatever that row held before this pass touched it.

A structure question — children, descendants, leaves, hasChildren — answers about any row the pass hands out, because structure is the same fact at every depth. Each of these four takes the row to ask about. One tree answers all four:

Depot
├── Van 1
│ ├── Crate A
│ └── Crate B
└── Van 2
Asked about DepotAnswerIn one phrase
children(Depot)Van 1, Van 2one step down
descendants(Depot)Van 1, Van 2, Crate A, Crate Ball the way down
leaves(Depot)Van 2, Crate A, Crate Bthe bottom rows only

Van 1 is a descendant and is not a leaf, because Van 1 has children of its own. Van 2 is both. hasChildren(Van 1) is true; hasChildren(Crate A) is false.

leaves(row) includes row itself when row is a leaf: leaves(Van 2) is [Van 2], not []. descendants(row) never includes row — a row is not its own descendant, but it can be its own subtree's only leaf. leaves(Van 2) is [Van 2] while descendants(Van 2) is [].

The row the pass holds may be one the store does not hold — a post-edit row, or a Rollup's effective child — which is why the pass answers these and entry.read(key)/entry.children() cannot: those read the store, and this row may not be in it yet.

Every structure member takes a row, so across those four rule 4 (ADR 0017, cost read off the parentheses) cannot tell a cheap read from a walk — all four carry parentheses either way. The value members take no row and still compute, so they carry parentheses for rule 4's own reason. Each member's own doc states its cost.

Extends​

Extended by​

Properties​

timeZone​

readonly timeZone: string

Defined in: model/field.ts:303

Inherited from​

FieldContext.timeZone

Methods​

children()​

children(row): readonly StoredEntry<Record<string, unknown>>[]

Defined in: model/field.ts:358

One step down: Depot → Van 1, Van 2. One tree read, no allocation beyond the array returned.

Exactly one level, and that is load-bearing for a Rollup: a parent's value already aggregates its subtree when the bottom-up pass reaches it, so reaching past one level here would double count a grandchild both under its parent and again under its grandparent. descendants and leaves are how a consumer reaches past one level, under their own names.

Parameters​

row​

StoredEntry

Returns​

readonly StoredEntry<Record<string, unknown>>[]


descendants()​

descendants(row): readonly StoredEntry<Record<string, unknown>>[]

Defined in: model/field.ts:362

All the way down, never row itself: Depot → Van 1, Van 2, Crate A, Crate B. A subtree walk, one tree read per node found. Mirrors Entry.descendants() on the live row; this is the pass's own tree instead of the store's.

Parameters​

row​

StoredEntry

Returns​

readonly StoredEntry<Record<string, unknown>>[]


hasChildren()​

hasChildren(row): boolean

Defined in: model/field.ts:378

True when row derives (ADR 0013): hasChildren(Van 1) is true, hasChildren(Crate A) is false. The cost follows the binding, and there are three: the store reads a cached child index and never builds the list (data/entry-store.ts), a Rollup pass reads the length of the very list children(row) hands back, and the bare default derives it from children(row). All three agree with children(row).length > 0, so a caller never has to know which one answered. Mirrors Entry.hasChildren on the live row, which is a property because it reads a cached index and allocates nothing (ADR 0017 rule 4).

Parameters​

row​

StoredEntry

Returns​

boolean


hierarchyParentId()​

hierarchyParentId(): EntryId | undefined

Defined in: model/field.ts:382

The tree's answer to this row's parent, through the checked hierarchy source (ADR 0020) — the same answer entry.parent()?.id gives, never read('parentId')'s stored value (ADR 0024). Bound to the row this pass is computing (ADR 0017 amendment, rule 2).

Returns​

EntryId | undefined


leaves()​

leaves(row): readonly StoredEntry<Record<string, unknown>>[]

Defined in: model/field.ts:370

The bottom rows of row's subtree: Depot → Van 2, Crate A, Crate B. A leaf answers itself: leaves(Van 2) is [Van 2], not [], while descendants(Van 2) is []. A subtree of one leaf has one leaf.

A subtree walk, one tree read per node found, same cost as descendants. A node whose fetched children list is empty is the leaf; this never asks hasChildren and never filters descendants's result.

Parameters​

row​

StoredEntry

Returns​

readonly StoredEntry<Record<string, unknown>>[]


read()​

read<K>(key): CoreFieldValue<K> | undefined

Defined in: model/field.ts:351

Another Field on this same row — a core key, or another Field's compute. Bound to the row this pass is computing; not a structure question, so it takes no row (ADR 0017 amendment, rule 2).

Type Parameters​

K​

K extends FieldKey

Parameters​

key​

K

Returns​

CoreFieldValue<K> | undefined