effectable 1.0.0 → 1.1.0-canary.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +9 -3
  2. package/build/bootstrap/bootstrap.d.ts.map +1 -1
  3. package/build/bootstrap/bootstrap.js +18 -8
  4. package/build/bootstrap/bootstrap.js.map +1 -1
  5. package/build/bootstrap/types.d.ts +11 -3
  6. package/build/bootstrap/types.d.ts.map +1 -1
  7. package/build/component/Component.d.ts.map +1 -1
  8. package/build/component/Component.js +16 -4
  9. package/build/component/Component.js.map +1 -1
  10. package/build/component/GraphRuntime.d.ts +254 -24
  11. package/build/component/GraphRuntime.d.ts.map +1 -1
  12. package/build/component/GraphRuntime.js +1136 -239
  13. package/build/component/GraphRuntime.js.map +1 -1
  14. package/build/component/context.d.ts +3 -11
  15. package/build/component/context.d.ts.map +1 -1
  16. package/build/component/context.js +24 -23
  17. package/build/component/context.js.map +1 -1
  18. package/build/component/h.d.ts +14 -6
  19. package/build/component/h.d.ts.map +1 -1
  20. package/build/component/h.js +19 -1
  21. package/build/component/h.js.map +1 -1
  22. package/build/component/lifecycle.d.ts +11 -2
  23. package/build/component/lifecycle.d.ts.map +1 -1
  24. package/build/component/lifecycle.js +21 -4
  25. package/build/component/lifecycle.js.map +1 -1
  26. package/build/component/refs.d.ts +7 -5
  27. package/build/component/refs.d.ts.map +1 -1
  28. package/build/component/refs.js +45 -22
  29. package/build/component/refs.js.map +1 -1
  30. package/build/component/types.d.ts +16 -5
  31. package/build/component/types.d.ts.map +1 -1
  32. package/build/component/types.js.map +1 -1
  33. package/build/connect/connect.d.ts.map +1 -1
  34. package/build/connect/connect.js +143 -44
  35. package/build/connect/connect.js.map +1 -1
  36. package/build/connect/types.d.ts +2 -2
  37. package/build/connect/types.d.ts.map +1 -1
  38. package/build/runtime/BusDecorators.d.ts +6 -0
  39. package/build/runtime/BusDecorators.d.ts.map +1 -1
  40. package/build/runtime/BusDecorators.js +126 -56
  41. package/build/runtime/BusDecorators.js.map +1 -1
  42. package/build/runtime/CommandBus.d.ts +1 -1
  43. package/build/runtime/CommandBus.d.ts.map +1 -1
  44. package/build/runtime/CommandBus.js +6 -3
  45. package/build/runtime/CommandBus.js.map +1 -1
  46. package/build/runtime/EventBus.d.ts.map +1 -1
  47. package/build/runtime/EventBus.js +11 -3
  48. package/build/runtime/EventBus.js.map +1 -1
  49. package/build/runtime/HandleRegistry.d.ts +2 -1
  50. package/build/runtime/HandleRegistry.d.ts.map +1 -1
  51. package/build/runtime/HandleRegistry.js +38 -7
  52. package/build/runtime/HandleRegistry.js.map +1 -1
  53. package/build/runtime/QueryBus.d.ts +1 -1
  54. package/build/runtime/QueryBus.d.ts.map +1 -1
  55. package/build/runtime/QueryBus.js +6 -3
  56. package/build/runtime/QueryBus.js.map +1 -1
  57. package/build/store/createStore.d.ts +2 -2
  58. package/build/store/createStore.d.ts.map +1 -1
  59. package/build/store/createStore.js +31 -4
  60. package/build/store/createStore.js.map +1 -1
  61. package/build/store/middleware.d.ts +16 -1
  62. package/build/store/middleware.d.ts.map +1 -1
  63. package/build/store/middleware.js +28 -16
  64. package/build/store/middleware.js.map +1 -1
  65. package/build/store/selector.d.ts.map +1 -1
  66. package/build/store/selector.js +6 -2
  67. package/build/store/selector.js.map +1 -1
  68. package/build/store/types.d.ts +11 -4
  69. package/build/store/types.d.ts.map +1 -1
  70. package/build/store/types.js.map +1 -1
  71. package/package.json +10 -3
@@ -4,10 +4,14 @@
4
4
  * Responsibilities:
5
5
  * - Materialize a VirtualServiceNode tree into real component instances (Fiber tree).
6
6
  * - Fiber-like reconcile: diff current vs next trees by key + type, assign effectTags.
7
+ * Reconciliation mutates the live graph (not an isolated work-in-progress tree).
7
8
  * - Drive lifecycle via LifecycleEngine: startup in topological order (children before parent),
8
- * shutdown in reverse order (parent before children).
9
+ * shutdown in the same order (children before parent).
9
10
  * - Inject contexts (@UseContext) and bind refs on mount.
10
11
  * - Pass updated props into existing instances during reconcile.
12
+ * - Serialize all graph operations through a single operation queue.
13
+ * - Fail-stop on unrecoverable errors: mark runtime FAILED, reject later reconcile,
14
+ * unmount stays safe.
11
15
  *
12
16
  * Current limitations:
13
17
  * - Work loop is synchronous (no priority lanes — next increment).
@@ -22,6 +26,22 @@ import type { FiberEffectTag, FiberInspectNode, VirtualServiceNode } from './typ
22
26
  import type { ContextScope } from './context';
23
27
  import type { RuntimeCommand, RuntimeEvent, RuntimeQuery } from '../runtime/types';
24
28
  import type { RuntimeBusesBundle } from '../runtime/BusDecorators';
29
+ /**
30
+ * Runtime state literals.
31
+ * Private to GraphRuntime; reduced set without mounting/reconciling.
32
+ */
33
+ declare const RUNTIME_STATE: {
34
+ readonly IDLE: "idle";
35
+ readonly ACTIVE: "active";
36
+ readonly FAILED: "failed";
37
+ readonly UNMOUNTING: "unmounting";
38
+ readonly UNMOUNTED: "unmounted";
39
+ };
40
+ /**
41
+ * Runtime state type derived from RUNTIME_STATE.
42
+ * Not exported from package index (internal diagnostic only).
43
+ */
44
+ type RuntimeState = (typeof RUNTIME_STATE)[keyof typeof RUNTIME_STATE];
25
45
  /**
26
46
  * Runtime engine for a declarative component tree.
27
47
  *
@@ -35,13 +55,28 @@ import type { RuntimeBusesBundle } from '../runtime/BusDecorators';
35
55
  export declare class GraphRuntime {
36
56
  /** Current root fiber tree (current tree). */
37
57
  private currentRoot;
38
- /** Whether unmount has completed. */
39
- private unmounted;
40
58
  /**
41
59
  * Entry counter for {@link continueStableReconcileAsync} (test/debug probe).
42
60
  * Not reset automatically — compare before/after around reconcile.
43
61
  */
44
62
  private stableAsyncContinueCount;
63
+ /**
64
+ * Backing field for {@link GraphRuntime.state}. Writes and most reads go
65
+ * through the accessor; post-await re-reads use `_state` (TS 6 still narrows getters).
66
+ */
67
+ private _state;
68
+ /**
69
+ * Runtime state machine.
70
+ * IDLE → ACTIVE (on mount) → FAILED | UNMOUNTING → UNMOUNTED.
71
+ * FAILED is terminal: subsequent reconcile rejects, unmount is safe.
72
+ */
73
+ private get state();
74
+ private set state(value);
75
+ /**
76
+ * Terminal error captured by failStop().
77
+ * Stored to reject later reconcile calls with the same error.
78
+ */
79
+ private terminalError;
45
80
  /**
46
81
  * Runtime buses for auto-wiring decorators on nodes (optional, set in {@link GraphRuntime.mount}).
47
82
  */
@@ -81,10 +116,45 @@ export declare class GraphRuntime {
81
116
  * Set via the fourth argument of {@link GraphRuntime.mount}.
82
117
  */
83
118
  private onAutoReconcileError;
119
+ /**
120
+ * Operation queue: serializes reconcile and unmount.
121
+ * Each operation is a Promise-returning function executed sequentially.
122
+ */
123
+ private operationQueue;
124
+ /**
125
+ * Whether an operation is currently running.
126
+ */
127
+ private operationInProgress;
128
+ /**
129
+ * Cached unmount promise for concurrent unmount callers.
130
+ */
131
+ private cachedUnmountPromise;
132
+ /**
133
+ * Pending fail-stop teardown work.
134
+ * When failStop nulls currentRoot but destroy is async, this tracks the in-flight cleanup.
135
+ * unmount() must await this before concluding teardown is finished.
136
+ */
137
+ private pendingTeardown;
84
138
  /**
85
139
  * Instances are created only via {@link GraphRuntime.mount}; direct `new GraphRuntime()` is unavailable externally.
86
140
  */
87
141
  private constructor();
142
+ /**
143
+ * Fail-stop: mark the runtime as failed, disable scheduling, tear down the graph best-effort.
144
+ * After fail-stop:
145
+ * - state is FAILED
146
+ * - terminalError is set
147
+ * - currentRoot is null (even if destroyFiber throws)
148
+ * - later reconcile() rejects with the terminal error
149
+ * - unmount() is safe and joinable
150
+ *
151
+ * No failed reconcile leaves the runtime active with a partial graph.
152
+ * Primary-error rules: cleanup errors attached as rollbackErrors, never replace primary.
153
+ *
154
+ * @param {Error} error - unrecoverable error that triggered fail-stop
155
+ * @returns {void | Promise<void>}
156
+ */
157
+ private failStop;
88
158
  /**
89
159
  * Auto-wires runtime-bus decorators onto the instance before {@link LifecycleEngine.runStartup}.
90
160
  *
@@ -101,6 +171,97 @@ export declare class GraphRuntime {
101
171
  * @returns {void}
102
172
  */
103
173
  private disposeEffectableRuntimeBusWiring;
174
+ /**
175
+ * Identity-safe ref clearing: clears ref.current only if it still points to the expected owner.
176
+ * Prevents an old rollback from clearing a ref that a newer materialization already reused.
177
+ * No cast required (Component | null → unknown | null is assignable).
178
+ *
179
+ * @param {RefObject<unknown>} ref - ref object
180
+ * @param {Component<unknown, unknown>} expectedOwner - expected current owner
181
+ * @returns {void}
182
+ */
183
+ private clearRefSafe;
184
+ /**
185
+ * Centralized ref ownership transition.
186
+ * Handles every ref binding/clearing operation: add, remove, replace.
187
+ *
188
+ * Rules:
189
+ * - Clear previousRef only if it still points to expectedPreviousOwner (identity-safe).
190
+ * - Bind nextRef to instance if nextRef is provided.
191
+ * - previousRef and nextRef can be the same object (ref reuse) or different (ref swap).
192
+ * - Do not let an old disposer clear a newer owner.
193
+ *
194
+ * No casts: Component | null → unknown | null is assignable (widening).
195
+ *
196
+ * @param {RefObject<unknown> | undefined} previousRef - ref to clear (can be undefined if no previous ref)
197
+ * @param {Component<unknown, unknown> | null} expectedPreviousOwner - expected owner of previousRef (null if unknown)
198
+ * @param {RefObject<unknown> | undefined} nextRef - ref to bind to instance (can be undefined if removing ref)
199
+ * @param {Component<unknown, unknown> | null} instance - instance to bind nextRef to (null when clearing only)
200
+ * @returns {void}
201
+ */
202
+ private commitRef;
203
+ /**
204
+ * Finalize fiber destroy: dispose wiring, clear ref, update status.
205
+ * Collects errors when collectErrors is provided (best-effort cleanup).
206
+ * When collectErrors is null, errors are thrown immediately.
207
+ *
208
+ * Uses commitRef for identity-safe ref clearing.
209
+ *
210
+ * @param {RuntimeFiber<unknown>} fiber - fiber being finalized
211
+ * @param {Error[] | null} collectErrors - array to collect errors (null to throw)
212
+ * @returns {void}
213
+ */
214
+ private finalizeFiberDestroy;
215
+ /**
216
+ * Transactional rollback for failed fiber materialization.
217
+ * Releases acquired resources in reverse acquisition order:
218
+ * 1. disable scheduler hook
219
+ * 2. dispose runtime bus registrations
220
+ * 3. clear bound ref (identity-safe)
221
+ * 4. run failed-startup cleanup
222
+ * 5. destroy mounted children in reverse order
223
+ * 6. unlink the partial fiber
224
+ * Cleanup is best-effort: one failure does not skip remaining steps.
225
+ * Preserves the original materialization error; cleanup errors are attached.
226
+ * Rollback is idempotent.
227
+ *
228
+ * @param {RuntimeFiber<P>} fiber - fiber being rolled back
229
+ * @param {Error} primaryError - original materialization/startup error
230
+ * @returns {void | Promise<void>}
231
+ */
232
+ private rollbackFailedMaterialization;
233
+ /**
234
+ * Async continuation of rollback child destruction after one child's destroy returned a Promise.
235
+ *
236
+ * @param {RuntimeFiber<unknown>[]} children - mounted children
237
+ * @param {number} lastIdx - index of the last processed child
238
+ * @param {Promise<void>} pending - Promise from destroying the previous child
239
+ * @param {Error} primaryError - original materialization error
240
+ * @param {Error[]} cleanupErrors - accumulated cleanup errors
241
+ * @param {RuntimeFiber<unknown>} fiber - parent fiber being rolled back
242
+ * @param {Component<unknown, unknown> | null} instance - parent instance (for post-child cleanup)
243
+ * @returns {Promise<void>}
244
+ */
245
+ private continueRollbackDestroyAsync;
246
+ /**
247
+ * After rollback destroyed children: run parent failed-cleanup only when startup
248
+ * actually ran (`status !== 'registered'`), then attach cleanup errors and rethrow.
249
+ *
250
+ * @param {RuntimeFiber<unknown>} fiber - parent fiber being rolled back
251
+ * @param {Component<unknown, unknown> | null} instance - parent instance
252
+ * @param {Error} primaryError - original materialization error
253
+ * @param {Error[]} cleanupErrors - accumulated cleanup errors
254
+ * @returns {void | Promise<void>} always rejects via {@link finalizeRollback}
255
+ */
256
+ private finishRollbackParentCleanup;
257
+ /**
258
+ * Attaches cleanup errors to the primary error and rethrows.
259
+ *
260
+ * @param {Error} primaryError - original materialization error
261
+ * @param {Error[]} cleanupErrors - cleanup errors
262
+ * @returns {never}
263
+ */
264
+ private finalizeRollback;
104
265
  /**
105
266
  * Injects the scheduler hook onto the component instance after successful startup.
106
267
  * The hook is called from {@link Component.setState} and enqueues the fiber for automatic reconcile.
@@ -113,10 +274,12 @@ export declare class GraphRuntime {
113
274
  */
114
275
  private injectUpdateHook;
115
276
  /**
116
- * Pre-mount buffer: `setState` during `onMount` cannot yet schedule reconcile
117
- * (the live hook is injected after startup). Marks the fiber; {@link injectUpdateHook}
118
- * after startup will call {@link scheduleUpdate}
119
- * (deferred until the mount pass completes).
277
+ * Pre-mount buffer: `setState` cannot yet schedule reconcile (the live hook is
278
+ * injected after startup). Marks the fiber; {@link injectUpdateHook} after
279
+ * startup will call {@link scheduleUpdate} (deferred until the mount pass completes).
280
+ *
281
+ * Injected before child materialization so descendant `onMount` callbacks that
282
+ * `setState` an ancestor are buffered instead of silently dropped.
120
283
  *
121
284
  * @param {Component<unknown, unknown>} instance - instance before/during startup
122
285
  * @param {RuntimeFiber<unknown>} fiber - instance fiber
@@ -138,13 +301,38 @@ export declare class GraphRuntime {
138
301
  * - If an ancestor of the fiber is already queued → skip (ancestor covers the subtree).
139
302
  * - If descendants of the fiber are queued → remove them (fiber covers their subtrees).
140
303
  *
304
+ * Skip scheduling when runtime is FAILED.
305
+ *
141
306
  * @param {RuntimeFiber<unknown>} fiber - fiber whose subtree needs rebuild
142
307
  * @returns {void}
143
308
  */
144
309
  private scheduleUpdate;
310
+ /**
311
+ * Enqueues an operation and starts the queue processor if idle.
312
+ * Operations are executed sequentially; concurrent callers await the same in-flight operation.
313
+ * Serialize all graph mutations.
314
+ *
315
+ * @param {() => Promise<void>} operation - operation to enqueue
316
+ * @returns {Promise<void>}
317
+ */
318
+ private enqueueOperation;
319
+ /**
320
+ * Processes the operation queue: runs operations one at a time.
321
+ * Single serialized owner of tree mutations.
322
+ * Errors from individual operations are propagated to their callers but do not stop the queue.
323
+ *
324
+ * @returns {Promise<void>}
325
+ */
326
+ private processOperationQueue;
145
327
  /**
146
328
  * Queues one dirty-flush microtask and publishes {@link activeFlush} for await from `reconcile`.
147
329
  *
330
+ * Skip scheduling when runtime is not ACTIVE (IDLE / FAILED / UNMOUNTING / UNMOUNTED),
331
+ * a public graph operation is in flight, or an async flush is already running. Callers that
332
+ * mutate `dirtyFibers` during those windows must kick this method again after the tree is
333
+ * ACTIVE and idle ({@link GraphRuntime.mount} / {@link processOperationQueue}), or after the
334
+ * outer flush finishes (end-of-pass kick).
335
+ *
148
336
  * @returns {void}
149
337
  */
150
338
  private scheduleDirtyFlushMicrotask;
@@ -154,6 +342,9 @@ export declare class GraphRuntime {
154
342
  * Guarded by the `flushing` flag against re-entrancy.
155
343
  * The chain of repeat passes is capped by {@link GRAPH_RUNTIME_MAX_DIRTY_FLUSH_PASSES}.
156
344
  *
345
+ * Respects state (UNMOUNTING/UNMOUNTED/FAILED) to cancel flush when unmount begins or failure occurs.
346
+ * On unrecoverable error, invokes onAutoReconcileError then fail-stops.
347
+ *
157
348
  * @returns {Promise<void>}
158
349
  */
159
350
  private flushDirtyFibers;
@@ -180,24 +371,35 @@ export declare class GraphRuntime {
180
371
  static mount<P = unknown>(root: VirtualServiceNode<P>, initialScope?: ContextScope, runtimeBuses?: RuntimeBusesBundle<RuntimeCommand, RuntimeQuery, RuntimeEvent>, onAutoReconcileError?: (err: unknown) => void): Promise<GraphRuntime>;
181
372
  /**
182
373
  * Reconciles against a new tree.
183
- * Builds a work-in-progress tree, computes effectTags, applies changes:
374
+ * Diffs the current tree against the new one, computes effectTags, applies changes:
184
375
  * - PLACE: create and mount a new node
185
376
  * - UPDATE: update props on an existing instance, call onUpdate
186
377
  * - DELETE: unmount and destroy a node
187
378
  *
379
+ * All reconcile calls are serialized through the operation queue.
380
+ * Rejects with terminal error when runtime is FAILED.
381
+ *
188
382
  * @param {VirtualServiceNode<P>} nextTree - new virtual tree
189
383
  * @returns {Promise<void>}
190
- * @throws {Error} if the runtime is already unmounted
384
+ * @throws {Error} if the runtime state is UNMOUNTING, UNMOUNTED, or FAILED
191
385
  */
192
386
  reconcile<P = unknown>(nextTree: VirtualServiceNode<P>): Promise<void>;
193
387
  /**
194
388
  * Fully unmounts the component tree.
195
- * Calls onUnmount for each node in reverse order (children before parent) and
389
+ * Calls onUnmount for each node (children before parent) and
196
390
  * moves stages to destroyed via LifecycleEngine.
197
391
  *
392
+ * Unmount is serialized, cached promise returned for concurrent callers.
393
+ * Safe and joinable even when runtime is FAILED.
394
+ * Collects cleanup errors when `rejectOnCleanupError: true` is passed.
395
+ *
396
+ * @param {object} [options] - unmount options
397
+ * @param {boolean} [options.rejectOnCleanupError=false] - reject on cleanup errors
198
398
  * @returns {Promise<void>}
199
399
  */
200
- unmount(): Promise<void>;
400
+ unmount(options?: {
401
+ rejectOnCleanupError?: boolean;
402
+ }): Promise<void>;
201
403
  /**
202
404
  * Returns the root component instance (for testing and introspection).
203
405
  *
@@ -205,7 +407,8 @@ export declare class GraphRuntime {
205
407
  */
206
408
  getRootInstance(): Component<unknown, unknown> | null;
207
409
  /**
208
- * Whether the runtime is active (unmount has not been called).
410
+ * Whether the runtime is active (not failed and unmount has not been called).
411
+ * Returns false when state is FAILED.
209
412
  *
210
413
  * @returns {boolean}
211
414
  */
@@ -232,6 +435,13 @@ export declare class GraphRuntime {
232
435
  * @returns {number} accumulated counter
233
436
  */
234
437
  getStableAsyncContinueCount(): number;
438
+ /**
439
+ * Current runtime state.
440
+ * Test/debug probe; not a production API.
441
+ *
442
+ * @returns {RuntimeState} current state
443
+ */
444
+ getState(): RuntimeState;
235
445
  /**
236
446
  * Builds a deep readonly {@link FiberInspectNode} from a RuntimeFiber.
237
447
  *
@@ -263,7 +473,7 @@ export declare class GraphRuntime {
263
473
  * @param {LifecycleEngine} engine - lifecycle engine
264
474
  * @param {VirtualServiceNode<P>} vnode - virtual node
265
475
  * @param {VirtualServiceNode[]} childVnodes - all child vnodes
266
- * @param {RuntimeFiber<unknown>[]} childFibers - already materialized child fibers
476
+ * @param {ContextScope} childScope - scope for child nodes
267
477
  * @param {Promise<RuntimeFiber<unknown>>} pending - Promise for the current child
268
478
  * @param {number} pendingIdx - index of the current child
269
479
  * @returns {Promise<RuntimeFiber<P>>}
@@ -275,19 +485,10 @@ export declare class GraphRuntime {
275
485
  * @template P node props type
276
486
  * @param {RuntimeFiber<P>} fiber - fiber of the subtree root node
277
487
  * @param {LifecycleEngine} engine - lifecycle engine for this node
278
- * @param {RuntimeFiber<unknown>[]} childFibers - already mounted child fibers (for rollback on error)
279
488
  * @param {PromiseLike<import('./lifecycle').LifecycleTransitionResult>} pendingStartup - Promise of the `runStartup` result
280
489
  * @returns {Promise<RuntimeFiber<P>>} ready fiber, or rollback children and rethrow
281
490
  */
282
491
  private finalizeMaterializeAsync;
283
- /**
284
- * Unmounts already-mounted children when parent startup fails.
285
- * Returns sync void if all demounts are sync, otherwise a Promise.
286
- *
287
- * @param {RuntimeFiber<unknown>[]} childFibers
288
- * @returns {void | Promise<void>}
289
- */
290
- private destroyChildrenOnError;
291
492
  /**
292
493
  * Runs fiber-like reconcile for a single node.
293
494
  * If type and key match — UPDATE: update props, reconcile children.
@@ -312,10 +513,13 @@ export declare class GraphRuntime {
312
513
  */
313
514
  private updateFiber;
314
515
  /**
315
- * Fiber cleanup after update/compose error: `runFailedCleanup` + bus dispose.
316
- * Does not leave the node in `ready`.
516
+ * Fiber cleanup after update/compose error: destroy children first (children → parent),
517
+ * then `runFailedCleanup` + bus dispose. Does not leave the node in `ready`.
518
+ * Child destroy / disposer errors are attached to `primaryError.rollbackErrors` when provided
519
+ * so fail-stop observability still surfaces them (children are no longer destroyed in failStop).
317
520
  *
318
521
  * @param {RuntimeFiber<unknown>} fiber - fiber that failed
522
+ * @param {unknown} [primaryError] - originating error to attach cleanup failures onto
319
523
  * @returns {void | Promise<void>}
320
524
  */
321
525
  private runFiberFailedCleanup;
@@ -362,15 +566,35 @@ export declare class GraphRuntime {
362
566
  * @returns {Promise<RuntimeFiber<unknown>[]>}
363
567
  */
364
568
  private continueStableReconcileAsync;
569
+ /**
570
+ * Validates that sibling keys are unique within a list.
571
+ * Follows React v16.5 keyed child reconciliation contract: duplicate keys are invalid.
572
+ * Throws a descriptive error including the duplicate key and parent component identity.
573
+ *
574
+ * @param {Array<{ vnode: { key?: string }; instance?: Component<unknown, unknown> | null }>} items - list of fibers or vnodes
575
+ * @param {RuntimeFiber<unknown>} parentFiber - parent fiber (for error message)
576
+ * @param {string} listName - "current" or "next" (for error message)
577
+ * @returns {void}
578
+ * @throws {Error} when duplicate keys are detected
579
+ */
580
+ private validateUniqueKeys;
365
581
  /**
366
582
  * Full-diff reconcile: keyed/unkeyed Map + destroy orphans.
367
583
  * Always async — internal branching is too complex for an efficient sync path.
368
584
  *
585
+ * Contract: Sibling keys must be unique (React v16.5 keyed child reconciliation).
586
+ * Validates both current and next children BEFORE any side effects.
587
+ * Throws deterministic error on duplicate keys to prevent lifecycle leaks.
588
+ *
589
+ * HOLE 3: On throw during PLACE, cleans up previously placed new nodes
590
+ * to prevent lifecycle leaks. Uses identity-safe check against currentChildren Set.
591
+ *
369
592
  * @param {RuntimeFiber<unknown>[]} currentChildren - current child fibers
370
593
  * @param {VirtualServiceNode[]} nextVnodes - new vnodes
371
594
  * @param {RuntimeFiber<unknown>} parentFiber - parent fiber
372
595
  * @param {ContextScope} childScope - children scope
373
596
  * @returns {Promise<RuntimeFiber<unknown>[]>}
597
+ * @throws {Error} when duplicate keys are detected in current or next children
374
598
  */
375
599
  private reconcileChildrenFullDiff;
376
600
  /**
@@ -406,7 +630,10 @@ export declare class GraphRuntime {
406
630
  * Returns `void` synchronously if the whole subtree is sync (up to 266x speedup
407
631
  * on an 85-node tree); otherwise a Promise. `await` works correctly with either union branch.
408
632
  *
633
+ * Collects cleanup errors via `collectErrors` parameter (best-effort cleanup).
634
+ *
409
635
  * @param {RuntimeFiber} fiber - fiber to destroy
636
+ * @param {Error[] | null} collectErrors - array to collect cleanup errors (null to throw immediately)
410
637
  * @returns {void | Promise<void>}
411
638
  */
412
639
  private destroyFiber;
@@ -417,6 +644,7 @@ export declare class GraphRuntime {
417
644
  * @param {Fiber[]} children - children list
418
645
  * @param {number} pendingIdx - index of the pending child
419
646
  * @param {PromiseLike<void>} pending - Promise from destroying the child
647
+ * @param {Error[] | null} collectErrors - array to collect cleanup errors
420
648
  * @returns {Promise<void>}
421
649
  */
422
650
  private continueDestroyAsync;
@@ -426,6 +654,7 @@ export declare class GraphRuntime {
426
654
  *
427
655
  * @param {RuntimeFiber<unknown>} fiber
428
656
  * @param {PromiseLike<unknown>} pendingShutdown
657
+ * @param {Error[] | null} collectErrors - array to collect cleanup errors
429
658
  * @returns {Promise<void>}
430
659
  */
431
660
  private finalizeDestroyAsync;
@@ -454,4 +683,5 @@ export declare class GraphRuntime {
454
683
  * @returns {FiberEffectTag}
455
684
  */
456
685
  export declare function makeFiberEffectTag(tag: FiberEffectTag): FiberEffectTag;
686
+ export {};
457
687
  //# sourceMappingURL=GraphRuntime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GraphRuntime.d.ts","sourceRoot":"","sources":["../../src/component/GraphRuntime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"GraphRuntime.d.ts","sourceRoot":"","sources":["../../src/component/GraphRuntime.ts"],"names":[],"mappings":"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"}