Skip to content

SpatialBoard 0.3.2

Choose a tag to compare

@hishamk hishamk released this 25 Aug 07:33

Added

  • DataFlowEngine.getComputeError(nodeId) — the error the node's last
    compute threw (sync) or rejected with (async), or undefined after a
    successful run. Errors park there instead of aborting the flush, clear on
    the node's next successful run, and both transitions notify change
    listeners so hosts can render the failure.
  • A graph:replaced engine event, emitted when the whole nodes map is
    swapped at once (undo / redo / deserialize) rather than mutated through the
    granular node lifecycle events. Consumers that mirror per-node state — the
    data-flow engine does — rebuild against the new graph on it.

Fixed

  • Deleting a node now recomputes its dependents immediately. The delete
    handler marked them dirty but nothing scheduled the flush (node deletion
    cascades the connected edges away without events), so stale outputs
    survived until an unrelated event touched the graph.
  • A node recreated with a deleted node's id no longer accepts the dead
    instance's late async result: generation counters bump on delete instead
    of resetting, so an in-flight promise from the old instance can never
    match the new one. Matters for serialized boards, where ids are
    deterministic.
  • A fresh run supersedes an async run still in flight for the same node:
    the superseded landing can no longer overwrite a newer result — or erase
    the error a newer failing run parked.
  • One throwing compute no longer costs the rest of the flush its
    recompute: sync throws are caught and parked per node instead of escaping
    the flush microtask after the dirty set was already cleared, and async
    rejections are handled the same way instead of surfacing as unhandled
    rejections. Failed nodes keep their last good outputs.
  • dispose() now severs the SpatialEngine subscription itself — a host
    that never called the connect() cleanup no longer keeps a recomputing
    zombie — marks the engine inert (a flush already in progress stops, and
    a late markDirty schedules nothing), and bumps the generation counters
    so async computes still in flight resolve into nothing, even across a
    dispose-and-reconnect revival.
  • setContainerSize ignores any measurement that is not at least one whole
    pixel on both axes. A NaN/Infinity size from an unvalidated host measurement
    used to flow into the maintain-center shift and poison the viewport (and the
    stored size that later fit math reads); a hidden container's 0×0 measurement
    used to shift the viewport by half the old size on re-show; and a sub-pixel
    measurement while a panel animates open (e.g. 0.5×0.4) used to consume the
    one-shot parked fit against a degenerate size. Such measurements now change
    nothing, parked fits keep waiting, and the next real (≥1px) measurement
    recovers everything. Measurements are coerced to numbers first, so untyped
    hosts passing numeric strings keep working.
  • Undo, redo, and deserialize now replay the data flow. They replace the
    whole nodes map at once, which arrives with no granular node events, so the
    data-flow engine used to leave restored nodes stale and removed nodes'
    values lingering until an unrelated edit; it now reconciles against the new
    graph — dropping gone nodes' state and recomputing the rest — with no
    manual touch. Ordinary edits are unaffected (no whole-graph recompute).
  • Deleting a node drops its whole stored state by id, not just the ports its
    type resolves at delete time. A node whose port set is data-driven and was
    narrowed before deletion used to leak the dropped ports' values onto a
    later node reusing the same id.
  • A throwing onChange listener is isolated: it is reported and the
    remaining listeners still run, on the synchronous and asynchronous notify
    paths alike, instead of starving later listeners or surfacing as an
    unhandled rejection.