@huukhanhnguyen/model / nodes/hooks
nodes/hooks
addHook()
addHook<
K>(host,name,handler):void
Attach handler to host's name point. COMPOSES: a second handler on the same point runs after the first, in registration order.
Type Parameters
K
K extends keyof NodeHooks | keyof SceneHooks
Parameters
host
name
K
handler
NonNullable<Hooks[K]>
Returns
void
beginEvaluate()
beginEvaluate(
node):EvaluateSettle
Open one evaluation attempt: fires beforeEvaluate now, and returns the function that fires afterEvaluate — exactly once, however the attempt ends.
PAIRING IS THE LAW, and this is what enforces it structurally rather than by every path remembering to. The settled flag lives in this closure, one per attempt, which closes three holes that a flag on the node could not:
- a settle routed through another (a
postComputethrow sends_commitinto_fail) fires once, not twice; - an attempt superseded mid-flight still CLOSES its pair, instead of leaving a
beforeEvaluateopen forever; - a re-entrant evaluation gets its own attempt and cannot close someone else's.
Every path that STARTS an evaluation goes through here — BaseNode.evaluate, DataNode.evaluateStep, LaneNode.track, and the two lane readers that compute inline (EntryNode.header, CollectionNode.keys). A caller that did NOT open an attempt (an override reaching _commit directly) threads no settle, and then nothing fires — which is correct, because nothing opened.
Parameters
node
Returns
callHook()
callHook<
K>(host,name, ...args):void
Fire host's name hook if one is attached. The hook's return value is discarded HERE, deliberately and in one place: that discard is what makes "a hook cannot change what the node decided" true by construction rather than by convention.
Type Parameters
K
K extends keyof NodeHooks | keyof SceneHooks
Parameters
host
HookHost | null | undefined
name
K
args
...Parameters<NonNullable<Hooks[K]>>
Returns
void