@unrulysystems/native-motion 0.1.0-alpha.0

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 (117) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/LICENSE +21 -0
  3. package/README.md +55 -0
  4. package/android/build.gradle +24 -0
  5. package/android/src/main/AndroidManifest.xml +1 -0
  6. package/android/src/main/java/com/unrulysystems/nativemotion/GestureExclusionModule.kt +55 -0
  7. package/android/src/main/java/com/unrulysystems/nativemotion/NativeMotionPackage.kt +27 -0
  8. package/package.json +57 -0
  9. package/react-native.config.js +14 -0
  10. package/src/native/driver/instantWindow.ts +31 -0
  11. package/src/native/driver/strictModeReplay.ts +20 -0
  12. package/src/native/driver/uiLayoutEngine.ts +845 -0
  13. package/src/native/driver/uiLayoutGraph.ts +338 -0
  14. package/src/native/driver/uiValueChannel.ts +4640 -0
  15. package/src/native/driver/workletDriver.ts +3860 -0
  16. package/src/native/motion/AnimatePresence.tsx +1605 -0
  17. package/src/native/motion/LayoutGroup.tsx +163 -0
  18. package/src/native/motion/MotionConfig.tsx +400 -0
  19. package/src/native/motion/MotionRoot.tsx +250 -0
  20. package/src/native/motion/MotionView.tsx +6761 -0
  21. package/src/native/motion/addScaleCorrector.ts +97 -0
  22. package/src/native/motion/colorEndpointUiFeed.ts +32 -0
  23. package/src/native/motion/colorProjection.ts +39 -0
  24. package/src/native/motion/composeTransform.ts +271 -0
  25. package/src/native/motion/constraintMeasure.ts +157 -0
  26. package/src/native/motion/deferredPendingSnapshots.ts +25 -0
  27. package/src/native/motion/discreteProjection.ts +36 -0
  28. package/src/native/motion/dragAncestorPanContext.ts +28 -0
  29. package/src/native/motion/dragControls.ts +152 -0
  30. package/src/native/motion/dragGestureWiring.ts +1168 -0
  31. package/src/native/motion/dragHandoffBinding.ts +179 -0
  32. package/src/native/motion/dragHubStream.ts +756 -0
  33. package/src/native/motion/dragPropagationLock.ts +57 -0
  34. package/src/native/motion/driverValueChannel.ts +3288 -0
  35. package/src/native/motion/externalDragDriver.ts +214 -0
  36. package/src/native/motion/frameData.ts +31 -0
  37. package/src/native/motion/gestureBinding.ts +107 -0
  38. package/src/native/motion/gestureStateGate.ts +563 -0
  39. package/src/native/motion/gestureStateResolver.ts +286 -0
  40. package/src/native/motion/identityValueChannelControllerAdapter.ts +2043 -0
  41. package/src/native/motion/identityValueChannelControllerReconciliation.ts +176 -0
  42. package/src/native/motion/identityValueChannelLaneMarker.ts +14 -0
  43. package/src/native/motion/imperativeAnimate.ts +816 -0
  44. package/src/native/motion/keyframeTiming.ts +7 -0
  45. package/src/native/motion/layoutIdBinding.ts +261 -0
  46. package/src/native/motion/layoutIdFlightConfig.ts +51 -0
  47. package/src/native/motion/layoutProjection.ts +89 -0
  48. package/src/native/motion/layoutScroll.ts +204 -0
  49. package/src/native/motion/layoutTransition.ts +1302 -0
  50. package/src/native/motion/lengthLayoutContext.tsx +100 -0
  51. package/src/native/motion/lengthLayoutHost.ts +44 -0
  52. package/src/native/motion/mappedKeys.ts +184 -0
  53. package/src/native/motion/motionViewController.ts +3180 -0
  54. package/src/native/motion/nativeHostMarker.ts +22 -0
  55. package/src/native/motion/panSessionWiring.ts +127 -0
  56. package/src/native/motion/pathTransition.ts +101 -0
  57. package/src/native/motion/popLayout.ts +176 -0
  58. package/src/native/motion/presenceBinding.ts +382 -0
  59. package/src/native/motion/scaleCorrectorRegistry.ts +123 -0
  60. package/src/native/motion/scrollValues.ts +260 -0
  61. package/src/native/motion/serializablePayload.ts +151 -0
  62. package/src/native/motion/severity.ts +16 -0
  63. package/src/native/motion/shippedSurface.ts +843 -0
  64. package/src/native/motion/staticLengthGate.ts +86 -0
  65. package/src/native/motion/styleBaseGate.ts +72 -0
  66. package/src/native/motion/styleValueBinding.ts +657 -0
  67. package/src/native/motion/systemGestureExclusion.ts +61 -0
  68. package/src/native/motion/tapGestureWiring.ts +215 -0
  69. package/src/native/motion/transformOrder.ts +38 -0
  70. package/src/native/motion/transformStringBinding.ts +200 -0
  71. package/src/native/motion/transformTemplateGate.ts +45 -0
  72. package/src/native/motion/transitionGate.ts +435 -0
  73. package/src/native/motion/useAnimate.ts +52 -0
  74. package/src/native/motion/useCycle.ts +44 -0
  75. package/src/native/motion/useInstantTransition.ts +68 -0
  76. package/src/native/motion/useReducedMotion.ts +58 -0
  77. package/src/native/motion/useScroll.ts +162 -0
  78. package/src/native/motion/useViewportScroll.ts +29 -0
  79. package/src/native/motion/valueChannel.ts +7121 -0
  80. package/src/native/motion/valueHooks.ts +901 -0
  81. package/src/native/motion/variantChildRegistry.ts +67 -0
  82. package/src/native/motion/variantContext.tsx +172 -0
  83. package/src/native/motion/variantProps.ts +598 -0
  84. package/src/native.ts +159 -0
  85. package/src/verification/harnessMetrics.ts +78 -0
  86. package/src/verification/probe/LayoutIdentityWorkletProbe.tsx +251 -0
  87. package/src/verification/probe/WorkletParityProbe.tsx +162 -0
  88. package/src/verification/probe/layoutIdentityProbeEngine.ts +429 -0
  89. package/src/verification/screens/ArcPathChecksScreen.tsx +273 -0
  90. package/src/verification/screens/BooleanAnimateChecksScreen.tsx +358 -0
  91. package/src/verification/screens/ChoreographyGalleryScreen.tsx +1010 -0
  92. package/src/verification/screens/ColorBindingChecksScreen.tsx +568 -0
  93. package/src/verification/screens/CompletionChecksScreen.tsx +294 -0
  94. package/src/verification/screens/ConformanceScreen.tsx +573 -0
  95. package/src/verification/screens/ContentionProbeScreen.tsx +224 -0
  96. package/src/verification/screens/DriverSmokeScreen.tsx +99 -0
  97. package/src/verification/screens/DurationOnlyTweenChecksScreen.tsx +294 -0
  98. package/src/verification/screens/DynamicDragConfigChecksScreen.tsx +237 -0
  99. package/src/verification/screens/FrameDataChecksScreen.tsx +252 -0
  100. package/src/verification/screens/GestureChecksScreen.tsx +685 -0
  101. package/src/verification/screens/InstantTransitionChecksScreen.tsx +839 -0
  102. package/src/verification/screens/LayoutAnimationStartChecksScreen.tsx +648 -0
  103. package/src/verification/screens/LayoutChecksScreen.tsx +822 -0
  104. package/src/verification/screens/LayoutCommitSpikeScreen.tsx +142 -0
  105. package/src/verification/screens/MotionViewChecksScreen.tsx +930 -0
  106. package/src/verification/screens/PresenceChecksScreen.tsx +614 -0
  107. package/src/verification/screens/ReducedMotionChecksScreen.tsx +614 -0
  108. package/src/verification/screens/RestThresholdChecksScreen.tsx +634 -0
  109. package/src/verification/screens/ScaleCorrectorChecksScreen.tsx +425 -0
  110. package/src/verification/screens/SharedLayoutContinuityChecksScreen.tsx +338 -0
  111. package/src/verification/screens/SharedLayoutCrossfadeChecksScreen.tsx +425 -0
  112. package/src/verification/screens/TransitionDefaultSelectionChecksScreen.tsx +514 -0
  113. package/src/verification/screens/ViewportScrollAliasChecksScreen.tsx +303 -0
  114. package/src/verification/screens/conformanceBanner.ts +21 -0
  115. package/src/verification/screens/proofConsoleTap.ts +18 -0
  116. package/src/verification.ts +47 -0
  117. package/src/web.ts +98 -0
@@ -0,0 +1,2043 @@
1
+ import {
2
+ delayGenerator,
3
+ keyframesGenerator,
4
+ ManualClock,
5
+ resolveSpringGenerator,
6
+ timingGenerator,
7
+ toDelayMs,
8
+ toKeyframesConfig,
9
+ toSpringConfig,
10
+ type Animation,
11
+ type DriverCommand,
12
+ type ElementHandle,
13
+ type Generator,
14
+ type GeneratorFactory,
15
+ type MotionValue,
16
+ type Transition,
17
+ } from '@unrulysystems/native-motion-core'
18
+ import {
19
+ createExternalAnimationLedger,
20
+ createMotionValueDriverPort,
21
+ initialExternalAnimationLedgerState,
22
+ instantFinalKeyframe,
23
+ isDirectPublicNumericMotionValue,
24
+ isDurationZeroInstantTransition,
25
+ isTimingLaneTransition,
26
+ toTimingLaneConfig,
27
+ type TransportedSampleProgressEntry,
28
+ type TransportedSampleProgressState,
29
+ type TransportedSampleProgressWriter,
30
+ type TransportedSampleIrreversibleSubphase,
31
+ } from '@unrulysystems/native-motion-core/internal-driver'
32
+
33
+ import {
34
+ identityValueChannelDriverIdForBinding,
35
+ type WorkletDriverBinding,
36
+ } from '../driver/workletDriver'
37
+ import {
38
+ createDriverValueChannelIdentityRegistry,
39
+ type DriverValueChannelIdentityRegistry,
40
+ type DriverValueChannelIdentityRegistryRecord,
41
+ type DriverValueChannelSinkRegistration,
42
+ type DriverValueChannelState,
43
+ } from './driverValueChannel'
44
+ import {
45
+ advanceGlobalTargetBatch,
46
+ channelMailboxTransferStatusHandler,
47
+ channelMailboxTransferStatusValidator,
48
+ completeIdentityGlobalValueChannelExecution,
49
+ constructGlobalTargetBatchFromPostListenerMotionValueSlot,
50
+ createIdentityGlobalValueChannelHostOperationController,
51
+ drainChannelMailboxTurnEnvelope,
52
+ IdentityGlobalValueChannelInvariantError,
53
+ produceIdentityGlobalValueChannelSealedEmptyBatch,
54
+ sealChannelMailboxTurnEnvelope,
55
+ type ChannelMailboxDrainRuntime,
56
+ type ChannelMailboxDrainState,
57
+ type ChannelMailboxEntry,
58
+ type ChannelMailboxTurnEnvelope,
59
+ type GlobalTargetBatchRegistryState,
60
+ type IdentityGlobalValueChannelExternalAnimationRuntime,
61
+ type IdentityGlobalValueChannelHostOperationController,
62
+ type IdentityGlobalValueChannelHostOperationObservation,
63
+ type IdentityGlobalValueChannelIdentityState,
64
+ type IdentityGlobalValueChannelPublicControlState,
65
+ type IdentityGlobalValueChannelRuntimeState,
66
+ type TargetBatchDependencyEventKind,
67
+ type ValueChannel,
68
+ } from './valueChannel'
69
+ import type { IdentityValueChannelControllerElementReconciliationPlan } from './identityValueChannelControllerReconciliation'
70
+ import { IDENTITY_DECLARATIVE_LANE_COMMAND } from './identityValueChannelLaneMarker'
71
+ import {
72
+ identityChannelEligibleBoundStyleSnapshot,
73
+ type MotionViewAuthoredStyleMountPreparation,
74
+ } from './styleValueBinding'
75
+
76
+ /**
77
+ * Mount-known public-value bindings for one MotionView controller. The adapter attaches these
78
+ * exact objects when the controller registers its element, before that controller can issue a
79
+ * target command.
80
+ */
81
+ export interface IdentityValueChannelControllerElementBinding {
82
+ readonly ownerDriverId: number
83
+ readonly ownerGeneration: number
84
+ readonly stylePreparation: MotionViewAuthoredStyleMountPreparation
85
+ readonly delegate: WorkletDriverBinding
86
+ }
87
+
88
+ declare const identityValueChannelElementAdapterBrand: unique symbol
89
+
90
+ /** Opaque wrapper created only by the shared runtime; callers cannot forge a plain binding. */
91
+ export interface IdentityValueChannelControllerElementAdapter extends IdentityValueChannelControllerElementBinding {
92
+ readonly [identityValueChannelElementAdapterBrand]: true
93
+ readonly binding: WorkletDriverBinding
94
+ }
95
+
96
+ export interface IdentityValueChannelMountedElementObservation {
97
+ readonly adapter: IdentityValueChannelControllerElementAdapter
98
+ readonly handle: ElementHandle
99
+ readonly sinkRegistrations: readonly DriverValueChannelSinkRegistration[]
100
+ readonly delegateCommittedValues: Readonly<Record<string, number>>
101
+ }
102
+
103
+ export interface IdentityValueChannelIdentityObservation {
104
+ readonly record: DriverValueChannelIdentityRegistryRecord<number>
105
+ readonly host: IdentityGlobalValueChannelHostOperationObservation
106
+ readonly publicControlSlot: IdentityGlobalValueChannelPublicControlState | null
107
+ }
108
+
109
+ export type IdentityValueChannelControllerOrderedEdge =
110
+ | {
111
+ readonly kind: 'LISTENER_STACK_COMPLETED'
112
+ readonly sequence: number
113
+ readonly batchId: number
114
+ }
115
+ | {
116
+ readonly kind: 'TARGET_BATCH_DEPENDENCY_APPENDED'
117
+ readonly sequence: number
118
+ readonly batchId: number
119
+ readonly dependencyId: number
120
+ }
121
+ | {
122
+ readonly kind: 'ASYNCHRONOUS_COMPLETION_DRAINED'
123
+ readonly sequence: number
124
+ readonly batchId: number
125
+ readonly dependencyId: number
126
+ }
127
+
128
+ export interface IdentityValueChannelCarrierDelivery {
129
+ readonly batchId: number
130
+ readonly carrierId: number
131
+ readonly authoredIndex: number
132
+ readonly identityId: number
133
+ readonly key: string
134
+ readonly taskSequence: number
135
+ }
136
+
137
+ export interface IdentityValueChannelElementDelivery {
138
+ readonly batchId: number
139
+ readonly ownerDriverId: number
140
+ readonly ownerGeneration: number
141
+ }
142
+
143
+ /**
144
+ * Private production observability. Every record is the adapter's live canonical record or an
145
+ * immutable envelope/delivery emitted by the real command path; this surface never accepts a
146
+ * caller-authored capture, slot, dependency event, or scenario result.
147
+ */
148
+ export interface IdentityValueChannelControllerRuntimeObservation {
149
+ readonly identities: readonly IdentityValueChannelIdentityObservation[]
150
+ readonly mountedElements: readonly IdentityValueChannelMountedElementObservation[]
151
+ readonly runtimeState: IdentityGlobalValueChannelRuntimeState
152
+ readonly targetBatchState: GlobalTargetBatchRegistryState
153
+ readonly orderedEdges: readonly IdentityValueChannelControllerOrderedEdge[]
154
+ readonly closedMailboxTurns: readonly ChannelMailboxTurnEnvelope[]
155
+ readonly carrierDeliveries: readonly IdentityValueChannelCarrierDelivery[]
156
+ readonly elementDeliveries: readonly IdentityValueChannelElementDelivery[]
157
+ }
158
+
159
+ /**
160
+ * Shared JS-global target/value-channel authority used by every concrete MotionView controller
161
+ * binding in one channel. Controller commands and public MotionValue callbacks are the only
162
+ * mutation entrances; test code can drive frames and replay a real emitted envelope, but cannot
163
+ * manufacture the controller's internal batch/capture protocol.
164
+ */
165
+ export interface IdentityValueChannelControllerRuntime {
166
+ bindingForElement(
167
+ options: IdentityValueChannelControllerElementBinding,
168
+ ): IdentityValueChannelControllerElementAdapter
169
+ advanceFrame(elapsedMs: number): void
170
+ drainNextMailboxTurn(): void
171
+ replayMailboxTurn(envelope: ChannelMailboxTurnEnvelope): void
172
+ runReadyAggregateReactions(): void
173
+ observe(): IdentityValueChannelControllerRuntimeObservation
174
+ }
175
+
176
+ export interface CreateIdentityValueChannelControllerRuntimeOptions {
177
+ readonly channel: ValueChannel
178
+ readonly identityRegistry: DriverValueChannelIdentityRegistry<number>
179
+ }
180
+
181
+ export interface AttachIdentityValueChannelControllerElementOptions {
182
+ readonly channel: ValueChannel
183
+ readonly stylePreparation: MotionViewAuthoredStyleMountPreparation
184
+ readonly resolvedStyleValues: Readonly<Record<string, number | string>>
185
+ readonly delegate: WorkletDriverBinding
186
+ }
187
+
188
+ export interface ReconcileIdentityValueChannelControllerElementOptions {
189
+ readonly channel: ValueChannel
190
+ readonly handle: ElementHandle
191
+ readonly delegate: WorkletDriverBinding
192
+ readonly controllerBinding: WorkletDriverBinding
193
+ readonly adapter: IdentityValueChannelControllerElementAdapter | null
194
+ readonly plan: IdentityValueChannelControllerElementReconciliationPlan
195
+ }
196
+
197
+ export type IdentityValueChannelControllerAdapterOperation =
198
+ | 'CREATE_IDENTITY_VALUE_CHANNEL_CONTROLLER_RUNTIME'
199
+ | 'RECONCILE_IDENTITY_VALUE_CHANNEL_CONTROLLER_ELEMENT'
200
+
201
+ export const IDENTITY_VALUE_CHANNEL_CONTROLLER_ADAPTER_UNIMPLEMENTED =
202
+ 'NATIVE_MOTION_IDENTITY_VALUE_CHANNEL_CONTROLLER_ADAPTER_UNIMPLEMENTED' as const
203
+
204
+ export const IDENTITY_VALUE_CHANNEL_CONTROLLER_ADAPTER_INVARIANT =
205
+ 'NATIVE_MOTION_IDENTITY_VALUE_CHANNEL_CONTROLLER_ADAPTER_INVARIANT' as const
206
+
207
+ export type IdentityValueChannelControllerAdapterInvariant = 'UNREGISTERED_WORKLET_DRIVER_BINDING'
208
+
209
+ export class IdentityValueChannelControllerAdapterInvariantError extends Error {
210
+ readonly code = IDENTITY_VALUE_CHANNEL_CONTROLLER_ADAPTER_INVARIANT
211
+ readonly invariant: IdentityValueChannelControllerAdapterInvariant
212
+
213
+ constructor(invariant: IdentityValueChannelControllerAdapterInvariant) {
214
+ super(
215
+ `native-motion: identity value-channel controller adapter invariant '${invariant}' failed`,
216
+ )
217
+ this.name = 'IdentityValueChannelControllerAdapterInvariantError'
218
+ this.invariant = invariant
219
+ }
220
+ }
221
+
222
+ /** Typed fail-closed boundary for behavior deliberately absent from the RED scaffold. */
223
+ export class IdentityValueChannelControllerAdapterUnimplementedError extends Error {
224
+ readonly code = IDENTITY_VALUE_CHANNEL_CONTROLLER_ADAPTER_UNIMPLEMENTED
225
+ readonly operation: IdentityValueChannelControllerAdapterOperation
226
+
227
+ constructor(operation: IdentityValueChannelControllerAdapterOperation) {
228
+ super(
229
+ `native-motion: identity value-channel controller adapter operation '${operation}' is ` +
230
+ 'unimplemented (REQ-VALUE-015, REQ-DRIVER-034, REQ-API-061)',
231
+ )
232
+ this.name = 'IdentityValueChannelControllerAdapterUnimplementedError'
233
+ this.operation = operation
234
+ }
235
+ }
236
+
237
+ // ——— Runtime implementation (REQ-VALUE-015, REQ-DRIVER-034, REQ-API-061) ———
238
+ // The shared JS-global authority: every concrete MotionView controller binding on one channel
239
+ // resolves exact direct-public numeric identities into ONE canonical registry record, host
240
+ // operation controller, and target-batch protocol per value. Controller commands and public
241
+ // MotionValue callbacks are the only mutation entrances; frames, drains, replays, and reactions
242
+ // are driven through the runtime surface below.
243
+
244
+ interface IdentityValueChannelExecutionRecord {
245
+ readonly executionId: number
246
+ readonly controlId: number
247
+ readonly valueCompletionSequence: number
248
+ readonly lifecycleCallbackId: number
249
+ readonly directOperationEpoch: number
250
+ readonly executionLease: number
251
+ readonly owner: IdentityValueChannelElementAuthority
252
+ generator: Generator
253
+ handle: Animation
254
+ elapsedMs: number
255
+ done: boolean
256
+ stopped: boolean
257
+ }
258
+
259
+ interface IdentityValueChannelIdentityAuthority {
260
+ readonly identityId: number
261
+ readonly channelId: number
262
+ readonly record: DriverValueChannelIdentityRegistryRecord<number>
263
+ readonly controller: IdentityGlobalValueChannelHostOperationController
264
+ readonly slotByExecutionId: Map<number, IdentityGlobalValueChannelPublicControlState>
265
+ readonly executions: IdentityValueChannelExecutionRecord[]
266
+ readonly unsubscribeChangeLane: () => void
267
+ attachedSinkCount: number
268
+ }
269
+
270
+ interface IdentityValueChannelElementAuthority {
271
+ readonly adapter: IdentityValueChannelControllerElementAdapter
272
+ readonly delegate: WorkletDriverBinding
273
+ readonly ownerDriverId: number
274
+ readonly ownerGeneration: number
275
+ readonly eligibleKeys: readonly string[]
276
+ readonly resolvedStyleValues: Readonly<Record<string, number>>
277
+ readonly identityBindings: Map<string, IdentityValueChannelIdentityAuthority>
278
+ /**
279
+ * Identity keys a forwarded start/retarget made command-owned on the delegate. The driver's
280
+ * dual-authority law refuses a second write lane for them for the rest of the flight's life,
281
+ * so every adapter-originated delegate write skips them once the delegate proves it enforces
282
+ * that law (rigs without the guard keep receiving the writes their traces pin).
283
+ */
284
+ readonly commandOwnedKeys: Set<string>
285
+ /** Set on the delegate's first observed dual-authority write refusal; owned writes then skip. */
286
+ delegateRefusesOwnedWrites: boolean
287
+ handle: ElementHandle | null
288
+ frameValuesListener: ((values: Readonly<Record<string, number>>) => void) | null
289
+ /**
290
+ * False until the mount commit's synchronous block yields. Mount-phase entrance commands keep
291
+ * the timed trajectory class; only a settled element's host-resolved retargets commit their
292
+ * carrier synchronously (the carrier keyed to the host's own returned controls).
293
+ */
294
+ mountSettled: boolean
295
+ }
296
+
297
+ /**
298
+ * The reconcile entry's backchannel into a runtime's element/identity authorities. Only
299
+ * `createIdentityValueChannelControllerRuntime` registers here, so a caller cannot manufacture
300
+ * element authority through the public runtime surface.
301
+ */
302
+ interface IdentityValueChannelControllerRuntimeInternals {
303
+ findElementByAdapter(
304
+ adapter: IdentityValueChannelControllerElementAdapter,
305
+ ): IdentityValueChannelElementAuthority | null
306
+ ensureElement(options: {
307
+ readonly adapter: IdentityValueChannelControllerElementAdapter
308
+ readonly delegate: WorkletDriverBinding
309
+ readonly ownerDriverId: number
310
+ readonly ownerGeneration: number
311
+ readonly handle: ElementHandle
312
+ }): IdentityValueChannelElementAuthority
313
+ detachIdentityValue(
314
+ element: IdentityValueChannelElementAuthority,
315
+ key: string,
316
+ value: MotionValue<number>,
317
+ spliceRegistry: boolean,
318
+ ): DriverValueChannelSinkRegistration | null
319
+ attachIdentityValue(
320
+ element: IdentityValueChannelElementAuthority,
321
+ key: string,
322
+ value: MotionValue<number>,
323
+ currentValue: number,
324
+ previous: {
325
+ readonly previousValue: MotionValue<number>
326
+ readonly previousSink: DriverValueChannelSinkRegistration
327
+ } | null,
328
+ ): void
329
+ }
330
+
331
+ const controllerRuntimeInternals = new WeakMap<
332
+ IdentityValueChannelControllerRuntime,
333
+ IdentityValueChannelControllerRuntimeInternals
334
+ >()
335
+
336
+ /** Every element authority by its branded adapter, for the mount-commit notification seam. */
337
+ const elementByAdapter = new WeakMap<
338
+ IdentityValueChannelControllerElementAdapter,
339
+ IdentityValueChannelElementAuthority
340
+ >()
341
+
342
+ /**
343
+ * MotionView's first insertion effect of every commit reports it here: render-phase entrance
344
+ * commands (the mount block) keep their timed trajectory class, while everything after the
345
+ * boundary follows the settled carrier law. Idempotent per element.
346
+ */
347
+ export function notifyIdentityValueChannelControllerMountCommit(
348
+ adapter: IdentityValueChannelControllerElementAdapter,
349
+ ): void {
350
+ const element = elementByAdapter.get(adapter)
351
+ if (element !== undefined) element.mountSettled = true
352
+ }
353
+
354
+ /** Whether a forwarded command owns the element's property for the rest of its flight's life. */
355
+ function delegateOwnsKey(element: IdentityValueChannelElementAuthority, key: string): boolean {
356
+ return element.commandOwnedKeys.has(key)
357
+ }
358
+
359
+ const DUAL_AUTHORITY_WRITE_REFUSAL = 'cannot write bound value'
360
+
361
+ /**
362
+ * The one adapter-originated delegate write lane. Command-owned keys ride it unless the
363
+ * delegate proves it enforces the dual-authority refusal — then they stay with the flight.
364
+ */
365
+ function writeDelegateValues(
366
+ element: IdentityValueChannelElementAuthority,
367
+ values: Readonly<Record<string, number>>,
368
+ ): void {
369
+ if (element.handle === null || element.delegate.isDisposed()) return
370
+ const writable: Record<string, number> = {}
371
+ const owned: Record<string, number> = {}
372
+ for (const [key, value] of Object.entries(values)) {
373
+ if (delegateOwnsKey(element, key)) owned[key] = value
374
+ else writable[key] = value
375
+ }
376
+ if (Object.keys(writable).length > 0) {
377
+ element.delegate.driver.write(element.handle, writable, undefined, 'bound-value-retarget')
378
+ }
379
+ if (element.delegateRefusesOwnedWrites || Object.keys(owned).length === 0) return
380
+ try {
381
+ element.delegate.driver.write(element.handle, owned, undefined, 'bound-value-retarget')
382
+ } catch (error) {
383
+ if (error instanceof Error && error.message.startsWith(DUAL_AUTHORITY_WRITE_REFUSAL)) {
384
+ element.delegateRefusesOwnedWrites = true
385
+ return
386
+ }
387
+ throw error
388
+ }
389
+ }
390
+
391
+ /**
392
+ * The empty mount snapshot for a reconcile-time attach whose mount had no eligible identity. Only
393
+ * the reconcile entrance constructs it; eligibility itself always comes from the plan's edges.
394
+ */
395
+ const EMPTY_MOUNT_STYLE_PREPARATION = {
396
+ boundStyleValues: {},
397
+ resolvedBoundStyleValues: {},
398
+ staticStyleValues: {},
399
+ } as unknown as MotionViewAuthoredStyleMountPreparation
400
+
401
+ /** The value's @internal lifecycle emitter (motion-value.ts), the same seam the graph uses. */
402
+ function emitIdentityValueEvent(
403
+ value: MotionValue<number>,
404
+ event: 'animationStart' | 'animationComplete',
405
+ ): void {
406
+ const emitter = value as Partial<{
407
+ emitEvent: (emitted: 'animationStart' | 'animationComplete') => void
408
+ }>
409
+ emitter.emitEvent?.(event)
410
+ }
411
+
412
+ function isInstantIdentityTransition(transition: Transition): boolean {
413
+ return transition.type === false || isDurationZeroInstantTransition(transition)
414
+ }
415
+
416
+ /** One trajectory factory for a scalar/keyframe target, mirroring the drivers' lane selection. */
417
+ function identityTrajectoryFactory(
418
+ target: number | readonly (number | null)[],
419
+ transition: Transition,
420
+ ): GeneratorFactory {
421
+ const delayMs = toDelayMs(transition)
422
+ const base: GeneratorFactory =
423
+ typeof target !== 'number'
424
+ ? keyframesGenerator(target, toKeyframesConfig(transition))
425
+ : transition.type === 'tween' || isTimingLaneTransition(transition)
426
+ ? timingGenerator(target, toTimingLaneConfig(transition))
427
+ : resolveSpringGenerator(target, toSpringConfig(transition))
428
+ return (seed) => (delayMs > 0 ? delayGenerator(base(seed), delayMs) : base(seed))
429
+ }
430
+
431
+ class IdentityValueChannelDrainProgressWriter implements TransportedSampleProgressWriter {
432
+ #state: TransportedSampleProgressState = {
433
+ activeEntry: null,
434
+ lastIrreversibleSubphase: null,
435
+ deliveredWriteWatermark: 0,
436
+ deliveredEventWatermark: 0,
437
+ retentionFinalization: 'pending',
438
+ }
439
+
440
+ beginEntry(entry: TransportedSampleProgressEntry): void {
441
+ this.#state = { ...this.#state, activeEntry: entry }
442
+ }
443
+
444
+ markIrreversibleSubphase(subphase: TransportedSampleIrreversibleSubphase): void {
445
+ this.#state = { ...this.#state, lastIrreversibleSubphase: subphase }
446
+ }
447
+
448
+ finalizeDeliveredWriteWatermarkAndRetention(
449
+ _channelId: number,
450
+ deliveredWriteWatermark: number,
451
+ ): void {
452
+ this.#state = {
453
+ ...this.#state,
454
+ deliveredWriteWatermark,
455
+ retentionFinalization: 'finalized',
456
+ }
457
+ }
458
+
459
+ finalizeDeliveredEventWatermarkAndRetention(
460
+ _channelId: number,
461
+ deliveredEventWatermark: number,
462
+ ): void {
463
+ this.#state = {
464
+ ...this.#state,
465
+ deliveredEventWatermark,
466
+ retentionFinalization: 'finalized',
467
+ }
468
+ }
469
+
470
+ clearEntry(): void {
471
+ this.#state = { ...this.#state, activeEntry: null, lastIrreversibleSubphase: null }
472
+ }
473
+
474
+ observe(): TransportedSampleProgressState {
475
+ return this.#state
476
+ }
477
+ }
478
+
479
+ function freshIdentityValueChannelDrainState(): ChannelMailboxDrainState {
480
+ return {
481
+ acceptedDrainIds: [],
482
+ completedPositions: [],
483
+ appliedEntryIds: [],
484
+ deliveredWriteWatermarks: [],
485
+ successfulTailCount: 0,
486
+ abortCount: 0,
487
+ abortPrefixReadyResolutionCount: 0,
488
+ retentionFinalizationCount: 0,
489
+ }
490
+ }
491
+
492
+ function resolveIdentityTarget(
493
+ command: DriverCommand & { readonly targets: object },
494
+ key: string,
495
+ ): {
496
+ readonly target: number | readonly (number | null)[]
497
+ readonly transition: Transition
498
+ } {
499
+ if (command.kind === 'start') {
500
+ const targets = command.targets as Readonly<
501
+ Record<
502
+ string,
503
+ { readonly to: number | readonly (number | null)[]; readonly transition?: unknown }
504
+ >
505
+ >
506
+ const propTarget = targets[key]!
507
+ return {
508
+ target: propTarget.to,
509
+ transition: (propTarget.transition ?? command.transition) as Transition,
510
+ }
511
+ }
512
+ const retarget = command as Extract<DriverCommand, { readonly kind: 'retarget' }>
513
+ return {
514
+ target: (retarget.targets as Readonly<Record<string, number>>)[key]!,
515
+ transition: (retarget.targetTransitions?.[key] ?? retarget.transition) as Transition,
516
+ }
517
+ }
518
+
519
+ function partitionIdentityCommandKeys(
520
+ identityBindings: ReadonlyMap<string, unknown>,
521
+ targets: Readonly<Record<string, unknown>>,
522
+ ): { readonly identityKeys: string[]; readonly restKeys: string[] } {
523
+ const identityKeys: string[] = []
524
+ const restKeys: string[] = []
525
+ for (const key of Object.keys(targets)) {
526
+ if (identityBindings.has(key)) identityKeys.push(key)
527
+ else restKeys.push(key)
528
+ }
529
+ return { identityKeys, restKeys }
530
+ }
531
+
532
+ const unexpectedIdentityMailboxEntry = (): void => undefined
533
+
534
+ /** Host frames never stage a transfer status; reaching one is a caller defect, fail closed. */
535
+ const unexpectedIdentityTransferStatus = (): never => {
536
+ throw new IdentityGlobalValueChannelInvariantError('identity-unknown')
537
+ }
538
+
539
+ /** The one JS-global identity runtime for an exact public ValueChannel graph. */
540
+ export function createIdentityValueChannelControllerRuntime(
541
+ options: CreateIdentityValueChannelControllerRuntimeOptions,
542
+ ): IdentityValueChannelControllerRuntime {
543
+ const { channel, identityRegistry } = options
544
+
545
+ // Monotonic id allocators; every sequence the tests pin is > 0 and order-consistent.
546
+ let nextIdentityId = 1
547
+ let nextChannelId = 1
548
+ let nextJsRecordId = 1
549
+ let nextUiRecordId = 1
550
+ let nextSinkId = 1
551
+ let nextExecutionId = 1
552
+ let nextControlId = 1
553
+ let nextValueCompletionSequence = 1
554
+ let nextCaptureId = 1
555
+ let nextDependencyId = 1
556
+ let nextCarrierId = 1
557
+ let nextCallbackId = 1
558
+ let nextBatchCreationSequence = 1
559
+ let nextExecutionCreationSequence = 1
560
+ let nextCommandSequence = 1
561
+ let nextDirectOperationEpoch = 1
562
+ let nextExecutionLease = 1
563
+ let nextWriteSequence = 1
564
+ let nextDependencyEventSequence = 1
565
+ let nextEdgeSequence = 1
566
+ let frameTimeMs = 0
567
+ let changeLaneSuppressionDepth = 0
568
+
569
+ const identities: IdentityValueChannelIdentityAuthority[] = []
570
+ const elements: IdentityValueChannelElementAuthority[] = []
571
+ const mountedElements: IdentityValueChannelElementAuthority[] = []
572
+ const lifecycleCallbacks = new Map<number, () => void>()
573
+ const transitionCallbacks = new Map<number, (value: number) => void>()
574
+ const carrierValues = new Map<number, number>()
575
+ const orderedEdges: IdentityValueChannelControllerOrderedEdge[] = []
576
+ const closedMailboxTurns: ChannelMailboxTurnEnvelope[] = []
577
+ const carrierDeliveries: IdentityValueChannelCarrierDelivery[] = []
578
+ const recordedCarrierDeliveryIds = new Set<number>()
579
+ const elementDeliveries: IdentityValueChannelElementDelivery[] = []
580
+ let mailboxDrainCursor = 0
581
+ let targetBatchState: GlobalTargetBatchRegistryState = {
582
+ batches: [],
583
+ nextBatchId: 1,
584
+ nextAggregateReactionSequence: 1,
585
+ readyBatchIdsByMailboxDrain: [],
586
+ }
587
+ let drainState: ChannelMailboxDrainState = freshIdentityValueChannelDrainState()
588
+ let replayDrainState: ChannelMailboxDrainState = freshIdentityValueChannelDrainState()
589
+
590
+ const runtime: IdentityGlobalValueChannelExternalAnimationRuntime = {
591
+ channel,
592
+ state: {
593
+ identities: [],
594
+ frameBuffers: {
595
+ executionCapacity: 4,
596
+ taskCapacity: 8,
597
+ completionCapacity: 4,
598
+ envelopeEntryCapacity: 16,
599
+ liveGrowthCount: 0,
600
+ },
601
+ pendingJsFrame: null,
602
+ nextMailboxDrainId: 1,
603
+ disposedOwnerDriverIds: [],
604
+ },
605
+ callbacks: {
606
+ publishChange: () => undefined,
607
+ markDerivedDirty: () => undefined,
608
+ invokeTransitionCallback(callbackId, _identityId, value) {
609
+ transitionCallbacks.get(callbackId)?.(value)
610
+ },
611
+ invokeLifecycleCallback(callbackId, _identityId) {
612
+ lifecycleCallbacks.get(callbackId)?.()
613
+ },
614
+ commitHostUpdate(record) {
615
+ const element = mountedElements.find(
616
+ (candidate) =>
617
+ candidate.ownerDriverId === record.driverId &&
618
+ (candidate.handle as number | null) === record.handleId,
619
+ )
620
+ if (element === null || element === undefined || element.handle === null) return
621
+ if (element.delegate.isDisposed()) return
622
+ const values: Record<string, number> = {}
623
+ for (const value of record.values) values[value.key] = value.value
624
+ writeDelegateValues(element, values)
625
+ element.frameValuesListener?.(element.delegate.driver.committed(element.handle))
626
+ },
627
+ requestJsFrame: () => undefined,
628
+ cancelJsFrame: () => undefined,
629
+ },
630
+ externalAnimationLedger: createExternalAnimationLedger({
631
+ graph: channel.graph,
632
+ initialState: initialExternalAnimationLedgerState(),
633
+ }),
634
+ }
635
+
636
+ const runtimeIdentities = runtime.state.identities as IdentityGlobalValueChannelIdentityState[]
637
+
638
+ function currentIdentity(
639
+ authority: IdentityValueChannelIdentityAuthority,
640
+ ): IdentityGlobalValueChannelIdentityState {
641
+ const identity = runtimeIdentities.find(
642
+ (candidate) => candidate.identityId === authority.identityId,
643
+ )
644
+ if (identity === undefined) {
645
+ throw new IdentityGlobalValueChannelInvariantError('identity-unknown')
646
+ }
647
+ return identity
648
+ }
649
+
650
+ function updateIdentity(
651
+ authority: IdentityValueChannelIdentityAuthority,
652
+ update: (
653
+ identity: IdentityGlobalValueChannelIdentityState,
654
+ ) => IdentityGlobalValueChannelIdentityState,
655
+ ): IdentityGlobalValueChannelIdentityState {
656
+ const index = runtimeIdentities.findIndex(
657
+ (candidate) => candidate.identityId === authority.identityId,
658
+ )
659
+ if (index < 0) throw new IdentityGlobalValueChannelInvariantError('identity-unknown')
660
+ const updated = update(runtimeIdentities[index]!)
661
+ runtimeIdentities[index] = updated
662
+ return updated
663
+ }
664
+
665
+ function readPublicControlSlot(
666
+ authority: IdentityValueChannelIdentityAuthority,
667
+ ): IdentityGlobalValueChannelPublicControlState | null {
668
+ const executionId = currentIdentity(authority).publicControlExecutionId
669
+ if (executionId === null) return null
670
+ return authority.slotByExecutionId.get(executionId) ?? null
671
+ }
672
+
673
+ /** The stop continuation every physical stopper routes: runtime state + the adapter's record. */
674
+ function onExecutionStopped(
675
+ authority: IdentityValueChannelIdentityAuthority,
676
+ executionId: number,
677
+ ): void {
678
+ const execution = authority.executions.find(
679
+ (candidate) => candidate.executionId === executionId,
680
+ )
681
+ if (execution !== undefined) execution.stopped = true
682
+ updateIdentity(authority, (current) => ({
683
+ ...current,
684
+ publicControlExecutionId:
685
+ current.publicControlExecutionId === executionId ? null : current.publicControlExecutionId,
686
+ physicalExecutions: current.physicalExecutions.map((candidate) =>
687
+ candidate.executionId === executionId
688
+ ? { ...candidate, phase: 'STOPPED' as const }
689
+ : candidate,
690
+ ),
691
+ }))
692
+ }
693
+
694
+ function initialRecordState(
695
+ channelId: number,
696
+ currentValue: number,
697
+ ownerGeneration: number,
698
+ ): DriverValueChannelState {
699
+ return {
700
+ identity: {
701
+ channelId,
702
+ jsRecordId: nextJsRecordId++,
703
+ uiRecordId: nextUiRecordId++,
704
+ creationKind: 'direct-public-finite-number',
705
+ publicReferenceRetained: true,
706
+ sinkCount: 1,
707
+ changeObserverCount: 0,
708
+ publicControlSlotId: null,
709
+ physicalExecutionIds: [],
710
+ dueWorkSequences: [],
711
+ valueCompletionSequences: [],
712
+ targetBatchDependencyIds: [],
713
+ dependencyEventOutboxSequences: [],
714
+ dependencyEventAckWatermark: 0,
715
+ sharedBatchReferenceCount: 0,
716
+ pendingFrameActivity: false,
717
+ currentBindingGeneration: ownerGeneration,
718
+ retiredBindingGeneration: 0,
719
+ directOperationEpoch: 1,
720
+ executionLeaseEpoch: 1,
721
+ history: {
722
+ currentValue,
723
+ previousValue: currentValue,
724
+ currentTimestampMs: 0,
725
+ previousTimestampMs: 0,
726
+ },
727
+ sequences: {
728
+ authoritativeSequence: 1,
729
+ commandSequence: 1,
730
+ writeSequence: 1,
731
+ eventSequence: 1,
732
+ frameSequence: 1,
733
+ dueWorkSequence: 1,
734
+ valueCompletionSequence: 1,
735
+ batchDependencyEventSequence: 0,
736
+ dependencyOutboxAckSequence: 0,
737
+ },
738
+ },
739
+ handoff: {
740
+ ownership: 'UI_RUNNING',
741
+ desiredSide: null,
742
+ direction: null,
743
+ transferLease: 1,
744
+ phaseToken: 1,
745
+ sourceRecordId: null,
746
+ destinationRecordId: null,
747
+ absoluteTransferDeadlineMs: null,
748
+ absoluteNoConsumerDeadlineMs: null,
749
+ releaseFenceSequence: null,
750
+ sentThroughAuthoritativeSequence: 1,
751
+ drainedThroughAuthoritativeSequence: 1,
752
+ preparedMutableTuple: null,
753
+ destinationRuntime: null,
754
+ sourceMutationQueue: [],
755
+ commitQueue: [],
756
+ resources: {
757
+ preparedStateRetained: false,
758
+ preparedCloneRetained: false,
759
+ transferActivityRetained: false,
760
+ transferTimerArmed: false,
761
+ },
762
+ },
763
+ }
764
+ }
765
+
766
+ /** The change lane: a public direct write schedules its task and commits every attached sink. */
767
+ function subscribeChangeLane(authority: IdentityValueChannelIdentityAuthority): () => void {
768
+ return authority.record.value.on('change', (latest: number) => {
769
+ if (changeLaneSuppressionDepth > 0) return
770
+ if (typeof latest !== 'number') return
771
+ authority.controller.schedule({
772
+ kind: 'SCHEDULE_IDENTITY_GLOBAL_VALUE_CHANNEL_DIRECT_WRITE',
773
+ operation: 'SET',
774
+ value: latest,
775
+ })
776
+ for (const sink of currentIdentity(authority).sinks) {
777
+ if (!sink.attached) continue
778
+ const element = mountedElements.find(
779
+ (candidate) =>
780
+ candidate.ownerDriverId === sink.driverId &&
781
+ (candidate.handle as number | null) === sink.handleId,
782
+ )
783
+ if (element === undefined || element.handle === null || element.delegate.isDisposed()) {
784
+ continue
785
+ }
786
+ writeDelegateValues(element, { [sink.key]: latest })
787
+ element.frameValuesListener?.(element.delegate.driver.committed(element.handle))
788
+ }
789
+ })
790
+ }
791
+
792
+ /** Attach one element's key to an exact identity, creating the canonical record on first use. */
793
+ function attachIdentityValueToElement(
794
+ element: IdentityValueChannelElementAuthority,
795
+ key: string,
796
+ value: MotionValue<number>,
797
+ currentValue: number,
798
+ previous: {
799
+ readonly previousValue: MotionValue<number>
800
+ readonly previousSink: DriverValueChannelSinkRegistration
801
+ } | null,
802
+ ): IdentityValueChannelIdentityAuthority | null {
803
+ if (element.handle === null) return null
804
+ const handle = element.handle as number
805
+ const existing = identities.find((candidate) => candidate.record.value === value)
806
+ if (existing !== undefined) {
807
+ const sink: DriverValueChannelSinkRegistration = {
808
+ driverId: element.ownerDriverId,
809
+ handle,
810
+ key,
811
+ bindingGeneration: element.ownerGeneration,
812
+ }
813
+ if (previous !== null) {
814
+ identityRegistry.rebind({
815
+ previousValue: previous.previousValue,
816
+ previousSink: previous.previousSink,
817
+ replacement: {
818
+ value: existing.record.value,
819
+ port: existing.record.port,
820
+ currentValue,
821
+ requestedState: existing.record.state,
822
+ sink,
823
+ },
824
+ })
825
+ } else {
826
+ identityRegistry.resolveBinding({
827
+ value: existing.record.value,
828
+ port: existing.record.port,
829
+ currentValue,
830
+ requestedState: existing.record.state,
831
+ sink,
832
+ })
833
+ }
834
+ const sinkId = nextSinkId++
835
+ updateIdentity(existing, (current) => ({
836
+ ...current,
837
+ sinks: [
838
+ ...current.sinks,
839
+ {
840
+ sinkId,
841
+ driverId: element.ownerDriverId,
842
+ handleId: handle,
843
+ bindingGeneration: element.ownerGeneration,
844
+ key,
845
+ passive: false,
846
+ attached: true,
847
+ },
848
+ ],
849
+ }))
850
+ existing.attachedSinkCount += 1
851
+ element.identityBindings.set(key, existing)
852
+ return existing
853
+ }
854
+
855
+ const identityId = nextIdentityId++
856
+ const channelId = nextChannelId++
857
+ const port = createMotionValueDriverPort({
858
+ value,
859
+ clock: new ManualClock(),
860
+ channelId,
861
+ rawSnapshot: {
862
+ kind: 'collector-silent-motion-value-raw-snapshot',
863
+ currentValue,
864
+ history: { kind: 'single-sample', currentValue, currentTimestampMs: 0 },
865
+ directOperationEpoch: 1,
866
+ authoritativeSequence: 1,
867
+ },
868
+ })
869
+ const sink: DriverValueChannelSinkRegistration = {
870
+ driverId: element.ownerDriverId,
871
+ handle,
872
+ key,
873
+ bindingGeneration: element.ownerGeneration,
874
+ }
875
+ const requestedState = initialRecordState(channelId, currentValue, element.ownerGeneration)
876
+ const resolution =
877
+ previous !== null
878
+ ? identityRegistry.rebind({
879
+ previousValue: previous.previousValue,
880
+ previousSink: previous.previousSink,
881
+ replacement: { value, port, currentValue, requestedState, sink },
882
+ }).replacement
883
+ : identityRegistry.resolveBinding({ value, port, currentValue, requestedState, sink })
884
+ if (resolution.kind !== 'eligible') return null
885
+ const record = resolution.record
886
+ const identity: IdentityGlobalValueChannelIdentityState = {
887
+ identityId,
888
+ channelId,
889
+ value: record.value,
890
+ ownership: {
891
+ kind: 'UI_RUNNING',
892
+ driverId: element.ownerDriverId,
893
+ ownerGeneration: element.ownerGeneration,
894
+ },
895
+ publicControlExecutionId: null,
896
+ sinks: [
897
+ {
898
+ sinkId: nextSinkId++,
899
+ driverId: element.ownerDriverId,
900
+ handleId: handle,
901
+ bindingGeneration: element.ownerGeneration,
902
+ key,
903
+ passive: false,
904
+ attached: true,
905
+ },
906
+ ],
907
+ observers: [],
908
+ physicalExecutions: [],
909
+ pendingTasks: [],
910
+ pendingValueCompletions: [],
911
+ pendingFrameActivity: false,
912
+ targetBatchDependencyEvents: [],
913
+ dependencyEventAckWatermark: 0,
914
+ carrierReferenceCount: 0,
915
+ cache: {
916
+ currentValue,
917
+ previousValue: currentValue,
918
+ currentTimestampMs: 0,
919
+ previousTimestampMs: 0,
920
+ velocity: 0,
921
+ },
922
+ }
923
+ runtimeIdentities.push(identity)
924
+ const authority: IdentityValueChannelIdentityAuthority = {
925
+ identityId,
926
+ channelId,
927
+ record,
928
+ controller: createIdentityGlobalValueChannelHostOperationController({ record, runtime }),
929
+ slotByExecutionId: new Map(),
930
+ executions: [],
931
+ unsubscribeChangeLane: () => undefined,
932
+ attachedSinkCount: 1,
933
+ }
934
+ identities.push(authority)
935
+ ;(authority as { unsubscribeChangeLane: () => void }).unsubscribeChangeLane =
936
+ subscribeChangeLane(authority)
937
+ element.identityBindings.set(key, authority)
938
+ return authority
939
+ }
940
+
941
+ /** Detach one element's sink from an exact identity; returns the sink for a rebind chain. */
942
+ function detachIdentityValueFromElement(
943
+ element: IdentityValueChannelElementAuthority,
944
+ key: string,
945
+ value: MotionValue<number>,
946
+ spliceRegistry: boolean,
947
+ ): DriverValueChannelSinkRegistration | null {
948
+ if (element.handle === null) return null
949
+ const authority = identities.find((candidate) => candidate.record.value === value)
950
+ if (authority === undefined) {
951
+ element.identityBindings.delete(key)
952
+ return null
953
+ }
954
+ const handle = element.handle as number
955
+ const sink =
956
+ authority.record.sinks.find(
957
+ (candidate) =>
958
+ candidate.driverId === element.ownerDriverId &&
959
+ candidate.handle === handle &&
960
+ candidate.key === key,
961
+ ) ?? null
962
+ if (sink !== null && spliceRegistry) {
963
+ identityRegistry.detachBinding({ value: authority.record.value, sink })
964
+ }
965
+ if (sink !== null) {
966
+ updateIdentity(authority, (current) => ({
967
+ ...current,
968
+ sinks: current.sinks.map((candidate) =>
969
+ candidate.driverId === element.ownerDriverId &&
970
+ candidate.handleId === handle &&
971
+ candidate.key === key
972
+ ? { ...candidate, attached: false }
973
+ : candidate,
974
+ ),
975
+ }))
976
+ authority.attachedSinkCount -= 1
977
+ if (authority.attachedSinkCount === 0) authority.unsubscribeChangeLane()
978
+ }
979
+ element.identityBindings.delete(key)
980
+ return sink
981
+ }
982
+
983
+ /** Attach one element's eligible key to its value's canonical identity, creating it on first use. */
984
+ function bindIdentityKey(
985
+ element: IdentityValueChannelElementAuthority,
986
+ key: string,
987
+ ): IdentityValueChannelIdentityAuthority | null {
988
+ const bound = element.adapter.stylePreparation.boundStyleValues[key]
989
+ const currentValue = element.resolvedStyleValues[key]
990
+ if (bound === undefined || currentValue === undefined || element.handle === null) return null
991
+ // The mount snapshot already filtered to this class; the predicate re-narrows the type (and
992
+ // keeps the one-read law — the scalar is the captured snapshot, never a fresh get()).
993
+ if (!isDirectPublicNumericMotionValue(bound, currentValue)) return null
994
+ return attachIdentityValueToElement(element, key, bound, currentValue, null)
995
+ }
996
+
997
+ /**
998
+ * One ordinary identity start: install the runtime control BEFORE the physical start so the
999
+ * synchronous animationStart stack observes it, then capture the graph handle/generator.
1000
+ */
1001
+ function startIdentityExecution(
1002
+ element: IdentityValueChannelElementAuthority,
1003
+ authority: IdentityValueChannelIdentityAuthority,
1004
+ target: number | readonly (number | null)[],
1005
+ transition: Transition,
1006
+ ): void {
1007
+ const identity = currentIdentity(authority)
1008
+ // Stale-clear: executions stopped BEFORE this start retire with it, so a successor coexists
1009
+ // only with the live orphan lineage (the current start's own interruption is not stale).
1010
+ const preStoppedExecutionIds = new Set(
1011
+ identity.physicalExecutions
1012
+ .filter((candidate) => candidate.phase === 'STOPPED')
1013
+ .map((candidate) => candidate.executionId),
1014
+ )
1015
+ const executionId = nextExecutionId++
1016
+ const controlId = nextControlId++
1017
+ const valueCompletionSequence = nextValueCompletionSequence++
1018
+ const directOperationEpoch = nextDirectOperationEpoch++
1019
+ const executionLease = nextExecutionLease++
1020
+ const initiatingSink = identity.sinks.find(
1021
+ (candidate) =>
1022
+ candidate.attached &&
1023
+ candidate.driverId === element.ownerDriverId &&
1024
+ candidate.handleId === (element.handle as number),
1025
+ )
1026
+ authority.controller.dispatch({
1027
+ kind: 'HOST_START_IDENTITY_GLOBAL_VALUE_CHANNEL_EXECUTION',
1028
+ identityId: authority.identityId,
1029
+ initiatingSinkId: initiatingSink?.sinkId ?? 0,
1030
+ commandSequence: nextCommandSequence++,
1031
+ directOperationEpoch,
1032
+ executionLease,
1033
+ requestedExecution: {
1034
+ executionId,
1035
+ creationSequence: nextExecutionCreationSequence++,
1036
+ updateSequence: 0,
1037
+ phase: 'RUNNING',
1038
+ orphaned: false,
1039
+ retained: true,
1040
+ sample: {
1041
+ writeSequence: 0,
1042
+ value: identity.cache.currentValue,
1043
+ velocity: identity.cache.velocity,
1044
+ done: false,
1045
+ },
1046
+ transitionOnUpdateCallbackId: null,
1047
+ transitionOnCompleteCallbackId: null,
1048
+ },
1049
+ })
1050
+ authority.slotByExecutionId.set(executionId, {
1051
+ controlId,
1052
+ executionId,
1053
+ valueCompletionSequence,
1054
+ })
1055
+ const lifecycleCallbackId = nextCallbackId++
1056
+ lifecycleCallbacks.set(lifecycleCallbackId, () =>
1057
+ emitIdentityValueEvent(authority.record.value, 'animationComplete'),
1058
+ )
1059
+ updateIdentity(authority, (current) => ({
1060
+ ...current,
1061
+ pendingValueCompletions: [
1062
+ ...current.pendingValueCompletions,
1063
+ {
1064
+ completionSequence: valueCompletionSequence,
1065
+ executionId,
1066
+ lifecycleCallbackId,
1067
+ publicStartPromiseId: null,
1068
+ armed: true,
1069
+ },
1070
+ ],
1071
+ }))
1072
+ const factory = identityTrajectoryFactory(target, transition)
1073
+ const execution: IdentityValueChannelExecutionRecord = {
1074
+ executionId,
1075
+ controlId,
1076
+ valueCompletionSequence,
1077
+ lifecycleCallbackId,
1078
+ directOperationEpoch,
1079
+ executionLease,
1080
+ owner: element,
1081
+ generator: null as unknown as Generator,
1082
+ handle: null as unknown as Animation,
1083
+ elapsedMs: 0,
1084
+ done: false,
1085
+ stopped: false,
1086
+ }
1087
+ const handle = channel.graph.animate(authority.record.value, (seed) => {
1088
+ const generator = factory(seed)
1089
+ execution.generator = generator
1090
+ return generator
1091
+ })
1092
+ execution.handle = handle
1093
+ authority.executions.push(execution)
1094
+ // A stop through the graph's own stopper during the animationStart stack (no port installation
1095
+ // existed yet) leaves no continuation hook; reconcile it from the finished handle.
1096
+ if (handle.done && !execution.stopped) onExecutionStopped(authority, executionId)
1097
+ // The port slot installs only while the runtime slot still holds THIS execution; a listener
1098
+ // that replaced or stopped it keeps its own outcome.
1099
+ if (currentIdentity(authority).publicControlExecutionId === executionId) {
1100
+ authority.record.port.installPublicControlSlot({
1101
+ controlId,
1102
+ executionId,
1103
+ stopPhysicalExecution: () => {
1104
+ handle.stop()
1105
+ onExecutionStopped(authority, executionId)
1106
+ },
1107
+ })
1108
+ }
1109
+ if (preStoppedExecutionIds.size > 0) {
1110
+ updateIdentity(authority, (current) => ({
1111
+ ...current,
1112
+ physicalExecutions: current.physicalExecutions.filter(
1113
+ (candidate) => !preStoppedExecutionIds.has(candidate.executionId),
1114
+ ),
1115
+ }))
1116
+ }
1117
+ }
1118
+
1119
+ /** The canonical target-command flow: one batch per command, one capture/carrier per key. */
1120
+ function runIdentityTargetCommandFlow(
1121
+ element: IdentityValueChannelElementAuthority,
1122
+ command: DriverCommand & { readonly targets: object },
1123
+ identityKeys: readonly string[],
1124
+ carrierClass: boolean,
1125
+ ): void {
1126
+ targetBatchState = advanceGlobalTargetBatch(targetBatchState, {
1127
+ kind: 'OPEN_TARGET_BATCH',
1128
+ creationSequence: nextBatchCreationSequence++,
1129
+ ownerDriverId: element.ownerDriverId,
1130
+ ownerGeneration: element.ownerGeneration,
1131
+ orchestrationDependencyCount: 0,
1132
+ }).state
1133
+ const batchId = targetBatchState.batches[targetBatchState.batches.length - 1]!.batchId
1134
+ const deferredCarriers: {
1135
+ readonly authority: IdentityValueChannelIdentityAuthority
1136
+ readonly key: string
1137
+ readonly authoredIndex: number
1138
+ readonly carrierId: number
1139
+ readonly value: number
1140
+ }[] = []
1141
+ identityKeys.forEach((key, authoredIndex) => {
1142
+ const authority = element.identityBindings.get(key)
1143
+ if (authority === undefined) return
1144
+ const { target, transition } = resolveIdentityTarget(command, key)
1145
+ // The host-resolved carrier class (a gesture-state/presence retarget of any transition
1146
+ // shape) rides the apparent-instant lane: no control, no flight — the carrier commit below
1147
+ // is the write — while a declarative/transition-defined target keeps its timed trajectory.
1148
+ const instant = carrierClass || isInstantIdentityTransition(transition)
1149
+ if (instant) {
1150
+ // The apparent-instant lane leaves no slot and emits no cancel: no runtime control, no
1151
+ // physical execution; the start still publishes so listeners observe the absent slot.
1152
+ if (currentIdentity(authority).publicControlExecutionId !== null) {
1153
+ authority.record.value.stop()
1154
+ }
1155
+ emitIdentityValueEvent(authority.record.value, 'animationStart')
1156
+ } else {
1157
+ startIdentityExecution(element, authority, target, transition)
1158
+ }
1159
+ const captureId = nextCaptureId++
1160
+ const listenerStackCompletionSequence = nextEdgeSequence++
1161
+ orderedEdges.push({
1162
+ kind: 'LISTENER_STACK_COMPLETED',
1163
+ sequence: listenerStackCompletionSequence,
1164
+ batchId,
1165
+ })
1166
+ const dependencyId = nextDependencyId++
1167
+ const constructed = constructGlobalTargetBatchFromPostListenerMotionValueSlot(
1168
+ targetBatchState,
1169
+ {
1170
+ kind: instant
1171
+ ? 'CONSTRUCT_APPARENT_INSTANT_GLOBAL_TARGET_BATCH_CAPTURE'
1172
+ : 'CONSTRUCT_REPLACED_ORDINARY_GLOBAL_TARGET_BATCH_CAPTURE',
1173
+ batchId,
1174
+ identityId: authority.identityId,
1175
+ captureId,
1176
+ authoredIndex,
1177
+ listenerStackCompletionSequence,
1178
+ dependencyId,
1179
+ },
1180
+ {
1181
+ value: authority.record.value,
1182
+ readPublicControlSlot: () => readPublicControlSlot(authority),
1183
+ },
1184
+ )
1185
+ targetBatchState = constructed.state
1186
+ const batch = targetBatchState.batches.find((candidate) => candidate.batchId === batchId)
1187
+ const capture = batch?.capturedControls.find((candidate) => candidate.captureId === captureId)
1188
+ const carrierValue = instantFinalKeyframe(target)
1189
+ if (capture?.kind === 'PUBLIC_IDENTITY') {
1190
+ orderedEdges.push({
1191
+ kind: 'TARGET_BATCH_DEPENDENCY_APPENDED',
1192
+ sequence: nextEdgeSequence++,
1193
+ batchId,
1194
+ dependencyId,
1195
+ })
1196
+ const carrierId = nextCarrierId++
1197
+ const receipt = authority.controller.schedule({
1198
+ kind: 'SCHEDULE_IDENTITY_GLOBAL_VALUE_CHANNEL_CARRIER',
1199
+ carrierId,
1200
+ authoredIndex,
1201
+ key,
1202
+ value: carrierValue,
1203
+ })
1204
+ targetBatchState = advanceGlobalTargetBatch(targetBatchState, {
1205
+ kind: 'APPEND_AUTHORED_TARGET_BATCH_CARRIER',
1206
+ batchId,
1207
+ carrier: {
1208
+ carrierId,
1209
+ authoredIndex,
1210
+ identityId: authority.identityId,
1211
+ key,
1212
+ taskSequence: receipt.scheduledTask.taskSequence,
1213
+ },
1214
+ }).state
1215
+ carrierValues.set(carrierId, carrierValue)
1216
+ // A raw-waiting carrier's delivery records when it actually drains at the reaction.
1217
+ return
1218
+ }
1219
+ deferredCarriers.push({
1220
+ authority,
1221
+ key,
1222
+ authoredIndex,
1223
+ carrierId: nextCarrierId++,
1224
+ value: carrierValue,
1225
+ })
1226
+ })
1227
+ const sealed = targetBatchState.batches.find((candidate) => candidate.batchId === batchId)
1228
+ if (sealed !== undefined && sealed.dependencies.length === 0) {
1229
+ // Zero-dependency seal: the carrier tasks schedule inside the production boundary, and the
1230
+ // delivery records land now while the element delivery waits for the reaction.
1231
+ const produced = produceIdentityGlobalValueChannelSealedEmptyBatch(
1232
+ targetBatchState,
1233
+ runtime,
1234
+ {
1235
+ kind: 'PRODUCE_IDENTITY_GLOBAL_VALUE_CHANNEL_SEALED_EMPTY_BATCH',
1236
+ batchId,
1237
+ preparedTargets: [],
1238
+ authoredCarriers: deferredCarriers.map(
1239
+ ({ authority, authoredIndex, carrierId, key, value }) => ({
1240
+ identityId: authority.identityId,
1241
+ command: {
1242
+ kind: 'SCHEDULE_IDENTITY_GLOBAL_VALUE_CHANNEL_CARRIER',
1243
+ carrierId,
1244
+ authoredIndex,
1245
+ key,
1246
+ value,
1247
+ },
1248
+ }),
1249
+ ),
1250
+ },
1251
+ )
1252
+ targetBatchState = produced.batchState
1253
+ produced.carrierReceipts.forEach((receipt, index) => {
1254
+ const deferred = deferredCarriers[index]!
1255
+ carrierValues.set(deferred.carrierId, deferred.value)
1256
+ // A sealed-empty carrier queued synchronously at seal: its delivery records now, while
1257
+ // the element delivery still waits for the reaction.
1258
+ recordCarrierDelivery({
1259
+ batchId,
1260
+ carrierId: deferred.carrierId,
1261
+ authoredIndex: deferred.authoredIndex,
1262
+ identityId: deferred.authority.identityId,
1263
+ key: deferred.key,
1264
+ taskSequence: receipt.scheduledTask.taskSequence,
1265
+ })
1266
+ })
1267
+ return
1268
+ }
1269
+ targetBatchState = advanceGlobalTargetBatch(targetBatchState, {
1270
+ kind: 'SEAL_TARGET_BATCH',
1271
+ batchId,
1272
+ }).state
1273
+ }
1274
+
1275
+ /**
1276
+ * A completing execution: the lifecycle emits while the post-listener slot is still installed,
1277
+ * then the slot clears token-blind WITHOUT stopping the retained physical execution (the
1278
+ * successor keeps sampling as an orphan), and only then do the batch dependency events stage.
1279
+ */
1280
+ function completeIdentityExecution(
1281
+ authority: IdentityValueChannelIdentityAuthority,
1282
+ execution: IdentityValueChannelExecutionRecord,
1283
+ openEntries: ChannelMailboxEntry[],
1284
+ ): void {
1285
+ const descriptor = {
1286
+ controlId: execution.controlId,
1287
+ executionId: execution.executionId,
1288
+ valueCompletionSequence: execution.valueCompletionSequence,
1289
+ target: currentIdentity(authority).cache.currentValue,
1290
+ }
1291
+ const slot = readPublicControlSlot(authority)
1292
+ completeIdentityGlobalValueChannelExecution(
1293
+ {
1294
+ value: authority.record.value,
1295
+ readPublicControlSlot: () => readPublicControlSlot(authority),
1296
+ startExecution: () => undefined,
1297
+ invokeDetachedCallback: () => undefined,
1298
+ invokeCompletionListener: (listenerId) => {
1299
+ transitionCallbacks.get(listenerId)?.(currentIdentity(authority).cache.currentValue)
1300
+ },
1301
+ emitAnimationCancel: () => undefined,
1302
+ emitAnimationComplete: () =>
1303
+ emitIdentityValueEvent(authority.record.value, 'animationComplete'),
1304
+ clearPublicControlSlotTokenBlind: (causedByExecutionId) => {
1305
+ const cleared = currentIdentity(authority).publicControlExecutionId
1306
+ // Token-blind (pinned completion/cancellation continuation): the post-listener slot
1307
+ // clears unconditionally and the retained physical execution is NEVER stopped.
1308
+ authority.record.port.clearPublicControlSlotTokenBlind(causedByExecutionId)
1309
+ updateIdentity(authority, (current) => ({
1310
+ ...current,
1311
+ publicControlExecutionId: null,
1312
+ physicalExecutions: current.physicalExecutions.map((candidate) =>
1313
+ candidate.executionId === cleared && cleared !== causedByExecutionId
1314
+ ? { ...candidate, orphaned: true }
1315
+ : candidate,
1316
+ ),
1317
+ pendingValueCompletions: current.pendingValueCompletions.filter(
1318
+ (candidate) => candidate.completionSequence !== execution.valueCompletionSequence,
1319
+ ),
1320
+ }))
1321
+ },
1322
+ stopPublicControl: () => authority.record.value.stop(),
1323
+ adoptPassiveTerminalCache: () => undefined,
1324
+ readSynchronousUiSnapshot: () => {
1325
+ const cache = currentIdentity(authority).cache
1326
+ return { value: cache.currentValue, velocity: cache.velocity }
1327
+ },
1328
+ },
1329
+ {
1330
+ kind: 'DELIVER_ORPHAN_IDENTITY_COMPLETION_AGAINST_SUCCESSOR_SLOT',
1331
+ identityId: authority.identityId,
1332
+ orphanExecution: descriptor,
1333
+ installedSuccessor:
1334
+ slot === null
1335
+ ? descriptor
1336
+ : {
1337
+ controlId: slot.controlId,
1338
+ executionId: slot.executionId,
1339
+ valueCompletionSequence: slot.valueCompletionSequence,
1340
+ target: currentIdentity(authority).cache.currentValue,
1341
+ },
1342
+ listenerId: execution.lifecycleCallbackId,
1343
+ },
1344
+ )
1345
+ execution.done = true
1346
+ const drainId = runtime.state.nextMailboxDrainId
1347
+ const stage = (
1348
+ batchId: number,
1349
+ dependencyId: number,
1350
+ dependencyEventKind: TargetBatchDependencyEventKind,
1351
+ ): void => {
1352
+ openEntries.push({
1353
+ kind: 'TARGET_BATCH_DEPENDENCY_EVENT',
1354
+ entryId: drainId * 1000 + openEntries.length,
1355
+ index: openEntries.length,
1356
+ batchId,
1357
+ dependencyId,
1358
+ source: {
1359
+ kind: 'PUBLIC_IDENTITY',
1360
+ identityId: authority.identityId,
1361
+ channelId: authority.channelId,
1362
+ },
1363
+ dependencyEventKind,
1364
+ eventSequence: nextDependencyEventSequence++,
1365
+ })
1366
+ }
1367
+ for (const batch of targetBatchState.batches) {
1368
+ for (const dependency of batch.dependencies) {
1369
+ if (dependency.source.kind !== 'PUBLIC_IDENTITY') continue
1370
+ if (
1371
+ dependency.source.identityId !== authority.identityId ||
1372
+ dependency.source.executionId !== execution.executionId
1373
+ ) {
1374
+ continue
1375
+ }
1376
+ if (dependency.rawResolvedEventSequence === null) {
1377
+ stage(batch.batchId, dependency.dependencyId, 'RAW_RESOLVED')
1378
+ }
1379
+ if (dependency.valueAcknowledgedEventSequence === null) {
1380
+ stage(batch.batchId, dependency.dependencyId, 'VALUE_ACKNOWLEDGED')
1381
+ }
1382
+ }
1383
+ }
1384
+ }
1385
+
1386
+ function buildDrainRuntime(envelope: ChannelMailboxTurnEnvelope): ChannelMailboxDrainRuntime {
1387
+ return {
1388
+ transferStatusValidator: channelMailboxTransferStatusValidator,
1389
+ transferStatusHandler: channelMailboxTransferStatusHandler,
1390
+ transferStatusTimestampMs: 0,
1391
+ canonicalTransferStatusState: unexpectedIdentityTransferStatus,
1392
+ persistTransferStatusTransition: unexpectedIdentityTransferStatus,
1393
+ publishTransferStatus: unexpectedIdentityTransferStatus,
1394
+ reportTransferStatusRefusal: unexpectedIdentityTransferStatus,
1395
+ entryHandlers: {
1396
+ VALUE_WRITE: unexpectedIdentityMailboxEntry,
1397
+ TOKENLESS_TASK_CALLBACK: unexpectedIdentityMailboxEntry,
1398
+ ELEMENT_HOST_COMMIT: unexpectedIdentityMailboxEntry,
1399
+ TRANSITION_CALLBACK: unexpectedIdentityMailboxEntry,
1400
+ LIFECYCLE_CALLBACK: unexpectedIdentityMailboxEntry,
1401
+ DESTINATION_COMMIT_ACKNOWLEDGEMENT: unexpectedIdentityMailboxEntry,
1402
+ TARGET_BATCH_DEPENDENCY_EVENT(entry) {
1403
+ const reported = advanceGlobalTargetBatch(targetBatchState, {
1404
+ kind: 'REPORT_DEPENDENCY_EVENT',
1405
+ mailboxDrainId: envelope.mailboxDrainId,
1406
+ event: {
1407
+ batchId: entry.batchId,
1408
+ dependencyId: entry.dependencyId,
1409
+ kind: entry.dependencyEventKind,
1410
+ eventSequence: entry.eventSequence,
1411
+ },
1412
+ })
1413
+ targetBatchState = reported.state
1414
+ // One drained-completion edge per dependency: the acknowledgement report that advanced
1415
+ // (never the raw half, never a replayed dedupe).
1416
+ if (
1417
+ entry.dependencyEventKind === 'VALUE_ACKNOWLEDGED' &&
1418
+ reported.orderedEffects.some((effect) => effect.kind === 'ADVANCE_DEPENDENCY')
1419
+ ) {
1420
+ orderedEdges.push({
1421
+ kind: 'ASYNCHRONOUS_COMPLETION_DRAINED',
1422
+ sequence: nextEdgeSequence++,
1423
+ batchId: entry.batchId,
1424
+ dependencyId: entry.dependencyId,
1425
+ })
1426
+ }
1427
+ },
1428
+ TARGET_BATCH_DEPENDENCY_HANDOFF: unexpectedIdentityMailboxEntry,
1429
+ TARGET_BATCH_DEPENDENCY_OUTBOX_ACKNOWLEDGEMENT: unexpectedIdentityMailboxEntry,
1430
+ LAYOUT_RELEASE: unexpectedIdentityMailboxEntry,
1431
+ PROJECTION_STALE: unexpectedIdentityMailboxEntry,
1432
+ LAYOUT_SETTLE: unexpectedIdentityMailboxEntry,
1433
+ DRIVER_SETTLE: unexpectedIdentityMailboxEntry,
1434
+ },
1435
+ transportedSamplePort(channelId) {
1436
+ const authority = identities.find((candidate) => candidate.channelId === channelId)
1437
+ if (authority === undefined) {
1438
+ throw new IdentityGlobalValueChannelInvariantError('identity-unknown')
1439
+ }
1440
+ return authority.record.port
1441
+ },
1442
+ invokeTransitionCallback(callbackId) {
1443
+ transitionCallbacks.get(callbackId)?.(0)
1444
+ },
1445
+ invokeLifecycleCallback(callbackId) {
1446
+ lifecycleCallbacks.get(callbackId)?.()
1447
+ },
1448
+ abortAppliedPrefixAndResolveReadyAggregates: () => undefined,
1449
+ finishAuthoritativeMailboxDrainAndTargetBatchTail(mailboxDrainId) {
1450
+ targetBatchState = advanceGlobalTargetBatch(targetBatchState, {
1451
+ kind: 'FINISH_MAILBOX_TAIL',
1452
+ mailboxDrainId,
1453
+ }).state
1454
+ },
1455
+ }
1456
+ }
1457
+
1458
+ function recordCarrierDelivery(delivery: IdentityValueChannelCarrierDelivery): void {
1459
+ if (recordedCarrierDeliveryIds.has(delivery.carrierId)) return
1460
+ recordedCarrierDeliveryIds.add(delivery.carrierId)
1461
+ carrierDeliveries.push(delivery)
1462
+ }
1463
+
1464
+ function drainEnvelope(
1465
+ envelope: ChannelMailboxTurnEnvelope,
1466
+ state: ChannelMailboxDrainState,
1467
+ ): ChannelMailboxDrainState {
1468
+ return drainChannelMailboxTurnEnvelope(
1469
+ state,
1470
+ envelope,
1471
+ buildDrainRuntime(envelope),
1472
+ new IdentityValueChannelDrainProgressWriter(),
1473
+ ).state
1474
+ }
1475
+
1476
+ function createElementBinding(
1477
+ element: IdentityValueChannelElementAuthority,
1478
+ ): WorkletDriverBinding {
1479
+ const delegate = element.delegate
1480
+ // The scheduled lane's dual-authority refusal cannot reach writeDelegateValues' synchronous
1481
+ // catch — the crossing is fire-and-forget (REQ-DRIVER-013) — so the delegate delivers it
1482
+ // here instead of retiring the admitted flight. Same terminal as the catch: latch, and owned
1483
+ // writes stay with the flight.
1484
+ const unsubscribeBoundValueRefusal = delegate.onBoundValueWriteRefusal((refusedHandle) => {
1485
+ if (element.handle === null) return
1486
+ if ((element.handle as number) !== (refusedHandle as number)) return
1487
+ element.delegateRefusesOwnedWrites = true
1488
+ })
1489
+ const driver: WorkletDriverBinding['driver'] = {
1490
+ register(initial) {
1491
+ const handle = delegate.driver.register(initial)
1492
+ element.handle = handle
1493
+ // Sink attachment precedes any controller command (register returns first): every eligible
1494
+ // key resolves its canonical identity and appends its sink before mount() can issue one.
1495
+ for (const key of element.eligibleKeys) {
1496
+ bindIdentityKey(element, key)
1497
+ }
1498
+ mountedElements.push(element)
1499
+ // First-paint constructor writes (two-pass law): with every sink registered, each
1500
+ // eligible identity receives its per-key initial record value as an ordinary write —
1501
+ // no lifecycle, the value's own identical-write suppression keeps a resting key silent.
1502
+ for (const key of element.eligibleKeys) {
1503
+ const authority = element.identityBindings.get(key)
1504
+ const startValue = initial[key]
1505
+ if (authority === undefined || typeof startValue !== 'number') continue
1506
+ authority.record.value.set(startValue)
1507
+ }
1508
+ return handle
1509
+ },
1510
+ command(handle, command) {
1511
+ if (command.kind === 'stop') {
1512
+ for (const authority of element.identityBindings.values()) {
1513
+ authority.record.value.stop()
1514
+ }
1515
+ for (const key of element.identityBindings.keys()) element.commandOwnedKeys.delete(key)
1516
+ delegate.driver.command(handle, command)
1517
+ return
1518
+ }
1519
+ const { identityKeys } = partitionIdentityCommandKeys(
1520
+ element.identityBindings,
1521
+ command.targets,
1522
+ )
1523
+ // The delegate is the host authority for the property: every command crosses unchanged,
1524
+ // identity keys included (one trajectory family, REQ-DRIVER-003).
1525
+ delegate.driver.command(handle, command)
1526
+ if (identityKeys.length === 0) return
1527
+ for (const key of identityKeys) element.commandOwnedKeys.add(key)
1528
+ // The host-resolved carrier law (the carrier keyed to the host's own returned controls):
1529
+ // a settled element whose delegate did not take a flight commits the target's ordinary
1530
+ // set right away — gesture-state/presence retargets through the apparent-instant lane,
1531
+ // declarative updates through their timed trajectory plus the same carrier write.
1532
+ const hostResolved = element.mountSettled && !delegate.driver.isActive(handle)
1533
+ const declarative =
1534
+ (command as unknown as Record<symbol, unknown>)[IDENTITY_DECLARATIVE_LANE_COMMAND] ===
1535
+ true
1536
+ runIdentityTargetCommandFlow(element, command, identityKeys, hostResolved && !declarative)
1537
+ if (!hostResolved) return
1538
+ for (const key of identityKeys) {
1539
+ const authority = element.identityBindings.get(key)
1540
+ if (authority === undefined) continue
1541
+ const finalValue = instantFinalKeyframe(resolveIdentityTarget(command, key).target)
1542
+ if (typeof finalValue === 'number') authority.record.value.set(finalValue)
1543
+ }
1544
+ },
1545
+ step(elapsedMs) {
1546
+ delegate.driver.step(elapsedMs)
1547
+ },
1548
+ committed(committedHandle) {
1549
+ return delegate.driver.committed(committedHandle)
1550
+ },
1551
+ setActive(activeHandle, active) {
1552
+ if (!active) {
1553
+ // Quiesce-before-unmount: the element is leaving, so its in-flight identity flights
1554
+ // halt silently with it (teardown is not a cancellation) — the value rests where it is.
1555
+ for (const authority of element.identityBindings.values()) {
1556
+ for (const execution of authority.executions) {
1557
+ if (execution.owner !== element || execution.done || execution.stopped) continue
1558
+ execution.handle.stop()
1559
+ onExecutionStopped(authority, execution.executionId)
1560
+ }
1561
+ }
1562
+ }
1563
+ delegate.driver.setActive(activeHandle, active)
1564
+ },
1565
+ isActive(activeHandle) {
1566
+ if (delegate.driver.isActive(activeHandle)) return true
1567
+ return identities.some((authority) =>
1568
+ authority.executions.some(
1569
+ (execution) => execution.owner === element && !execution.done && !execution.stopped,
1570
+ ),
1571
+ )
1572
+ },
1573
+ write(writeHandle, values, velocities, eventShape) {
1574
+ delegate.driver.write(writeHandle, values, velocities, eventShape)
1575
+ },
1576
+ liveFor(liveHandle, key) {
1577
+ return delegate.driver.liveFor(liveHandle, key)
1578
+ },
1579
+ }
1580
+ return {
1581
+ driver,
1582
+ sharedFor(handle, key) {
1583
+ return delegate.sharedFor(handle, key)
1584
+ },
1585
+ writeBoundValue(handle, values) {
1586
+ const identityValues: Record<string, number> = {}
1587
+ const restValues: Record<string, number> = {}
1588
+ for (const [key, value] of Object.entries(values)) {
1589
+ const authority = element.identityBindings.get(key)
1590
+ if (authority === undefined) {
1591
+ restValues[key] = value
1592
+ continue
1593
+ }
1594
+ authority.controller.schedule({
1595
+ kind: 'SCHEDULE_IDENTITY_GLOBAL_VALUE_CHANNEL_DIRECT_WRITE',
1596
+ operation: 'SET',
1597
+ value,
1598
+ })
1599
+ identityValues[key] = value
1600
+ }
1601
+ if (Object.keys(identityValues).length > 0) {
1602
+ writeDelegateValues(element, identityValues)
1603
+ element.frameValuesListener?.(delegate.driver.committed(handle))
1604
+ }
1605
+ if (Object.keys(restValues).length > 0) delegate.writeBoundValue(handle, restValues)
1606
+ },
1607
+ ...(delegate.propertyStateFor === undefined
1608
+ ? {}
1609
+ : { propertyStateFor: delegate.propertyStateFor.bind(delegate) }),
1610
+ setFrameValuesListener(handle, listener) {
1611
+ element.frameValuesListener = listener
1612
+ delegate.setFrameValuesListener(handle, listener)
1613
+ },
1614
+ onBoundValueWriteRefusal(listener) {
1615
+ return delegate.onBoundValueWriteRefusal(listener)
1616
+ },
1617
+ layout: delegate.layout,
1618
+ dispose() {
1619
+ // Teardown stops this element's in-flight identity executions silently (teardown is not
1620
+ // a cancellation), then detaches its sinks and change lanes before the delegate tears down.
1621
+ unsubscribeBoundValueRefusal()
1622
+ for (const authority of element.identityBindings.values()) {
1623
+ for (const execution of authority.executions) {
1624
+ if (execution.owner !== element || execution.done || execution.stopped) continue
1625
+ execution.handle.stop()
1626
+ onExecutionStopped(authority, execution.executionId)
1627
+ }
1628
+ }
1629
+ for (const [key, authority] of element.identityBindings) {
1630
+ const handle = element.handle as number
1631
+ const sink = authority.record.sinks.find(
1632
+ (candidate) =>
1633
+ candidate.driverId === element.ownerDriverId &&
1634
+ candidate.handle === handle &&
1635
+ candidate.key === key,
1636
+ )
1637
+ if (sink !== undefined) {
1638
+ identityRegistry.detachBinding({ value: authority.record.value, sink })
1639
+ }
1640
+ updateIdentity(authority, (current) => ({
1641
+ ...current,
1642
+ sinks: current.sinks.map((candidate) =>
1643
+ candidate.driverId === element.ownerDriverId &&
1644
+ candidate.handleId === handle &&
1645
+ candidate.key === key
1646
+ ? { ...candidate, attached: false }
1647
+ : candidate,
1648
+ ),
1649
+ }))
1650
+ authority.attachedSinkCount -= 1
1651
+ if (authority.attachedSinkCount === 0) authority.unsubscribeChangeLane()
1652
+ }
1653
+ delegate.dispose()
1654
+ },
1655
+ isDisposed: () => delegate.isDisposed(),
1656
+ }
1657
+ }
1658
+
1659
+ const runtimeInterface: IdentityValueChannelControllerRuntime = {
1660
+ bindingForElement(bindingOptions) {
1661
+ const snapshot = identityChannelEligibleBoundStyleSnapshot(bindingOptions.stylePreparation)
1662
+ const element: IdentityValueChannelElementAuthority = {
1663
+ adapter: null as unknown as IdentityValueChannelControllerElementAdapter,
1664
+ delegate: bindingOptions.delegate,
1665
+ ownerDriverId: bindingOptions.ownerDriverId,
1666
+ ownerGeneration: bindingOptions.ownerGeneration,
1667
+ eligibleKeys: snapshot.keys,
1668
+ resolvedStyleValues: snapshot.resolvedStyleValues,
1669
+ identityBindings: new Map(),
1670
+ commandOwnedKeys: new Set(),
1671
+ delegateRefusesOwnedWrites: false,
1672
+ handle: null,
1673
+ frameValuesListener: null,
1674
+ mountSettled: false,
1675
+ }
1676
+ // The mount commit's synchronous block owns every entrance command; the first task boundary
1677
+ // after it flips the element to its settled (carrier-commit) law.
1678
+ queueMicrotask(() => {
1679
+ element.mountSettled = true
1680
+ })
1681
+ elements.push(element)
1682
+ const binding = createElementBinding(element)
1683
+ const adapter = {
1684
+ ownerDriverId: bindingOptions.ownerDriverId,
1685
+ ownerGeneration: bindingOptions.ownerGeneration,
1686
+ stylePreparation: bindingOptions.stylePreparation,
1687
+ delegate: bindingOptions.delegate,
1688
+ binding,
1689
+ } as IdentityValueChannelControllerElementAdapter
1690
+ ;(element as { adapter: IdentityValueChannelControllerElementAdapter }).adapter = adapter
1691
+ elementByAdapter.set(adapter, element)
1692
+ return adapter
1693
+ },
1694
+
1695
+ advanceFrame(elapsedMs) {
1696
+ frameTimeMs += elapsedMs
1697
+ for (const element of mountedElements) {
1698
+ if (element.handle === null || element.delegate.isDisposed()) continue
1699
+ element.delegate.driver.step(elapsedMs)
1700
+ }
1701
+ // Exactly one mailbox turn per frame across every identity; it seals only when the frame
1702
+ // actually staged dependency events (an empty turn has no envelope to close).
1703
+ const openEntries: ChannelMailboxEntry[] = []
1704
+ for (const authority of identities) {
1705
+ const running = authority.executions.filter((execution) => !execution.done)
1706
+ for (const execution of running) {
1707
+ const record = currentIdentity(authority).physicalExecutions.find(
1708
+ (candidate) => candidate.executionId === execution.executionId,
1709
+ )
1710
+ if (record === undefined || record.phase === 'STOPPED') {
1711
+ execution.stopped = true
1712
+ continue
1713
+ }
1714
+ execution.elapsedMs += elapsedMs
1715
+ const sample = execution.generator.sample(execution.elapsedMs)
1716
+ changeLaneSuppressionDepth += 1
1717
+ try {
1718
+ authority.controller.dispatch({
1719
+ kind: 'HOST_APPLY_IDENTITY_GLOBAL_VALUE_CHANNEL_WRITE',
1720
+ identityId: authority.identityId,
1721
+ executionId: execution.executionId,
1722
+ executionLease: execution.executionLease,
1723
+ directOperationEpoch: execution.directOperationEpoch,
1724
+ source: 'GENERATOR',
1725
+ writeSequence: nextWriteSequence++,
1726
+ value: sample.value,
1727
+ velocity: sample.velocity,
1728
+ absoluteTimestampMs: frameTimeMs,
1729
+ })
1730
+ } finally {
1731
+ changeLaneSuppressionDepth -= 1
1732
+ }
1733
+ // A completion whose host fanout reentrantly stopped the control still completes: the
1734
+ // lifecycle emission observes the post-listener slot before the token-blind clear.
1735
+ if (sample.done) completeIdentityExecution(authority, execution, openEntries)
1736
+ }
1737
+ }
1738
+ if (openEntries.length === 0) return
1739
+ const mailboxDrainId = runtime.state.nextMailboxDrainId
1740
+ const envelope = sealChannelMailboxTurnEnvelope({
1741
+ mailboxOrigin: 'UI',
1742
+ mailboxDrainId,
1743
+ stagedEntries: openEntries,
1744
+ sealed: false,
1745
+ })
1746
+ ;(runtime.state as { nextMailboxDrainId: number }).nextMailboxDrainId = mailboxDrainId + 1
1747
+ closedMailboxTurns.push(envelope)
1748
+ },
1749
+
1750
+ drainNextMailboxTurn() {
1751
+ const envelope = closedMailboxTurns[mailboxDrainCursor]
1752
+ if (envelope === undefined) return
1753
+ mailboxDrainCursor += 1
1754
+ drainState = drainEnvelope(envelope, drainState)
1755
+ },
1756
+
1757
+ replayMailboxTurn(envelope) {
1758
+ // The replay lane keeps its own drain cell: a valid replay applies (dedupe-inert through the
1759
+ // batch controller), while a malformed candidate refuses before anything mutates.
1760
+ replayDrainState = drainEnvelope(envelope, replayDrainState)
1761
+ },
1762
+
1763
+ runReadyAggregateReactions() {
1764
+ const ready = targetBatchState.batches
1765
+ .filter(
1766
+ (batch) =>
1767
+ batch.stage === 'READY_REACTION_REGISTERED' ||
1768
+ batch.stage === 'SEALED_EMPTY_REACTION_REGISTERED',
1769
+ )
1770
+ .sort(
1771
+ (left, right) =>
1772
+ (left.aggregateReactionSequence ?? 0) - (right.aggregateReactionSequence ?? 0),
1773
+ )
1774
+ for (const batch of ready) {
1775
+ const reaction = advanceGlobalTargetBatch(targetBatchState, {
1776
+ kind: 'RUN_AGGREGATE_REACTION',
1777
+ batchId: batch.batchId,
1778
+ })
1779
+ targetBatchState = reaction.state
1780
+ if (
1781
+ !reaction.orderedEffects.some((effect) => effect.kind === 'DELIVER_LIVE_OWNER_ELEMENT')
1782
+ ) {
1783
+ continue
1784
+ }
1785
+ elementDeliveries.push({
1786
+ batchId: batch.batchId,
1787
+ ownerDriverId: batch.ownerDriverId,
1788
+ ownerGeneration: batch.ownerGeneration,
1789
+ })
1790
+ const element = mountedElements.find(
1791
+ (candidate) =>
1792
+ candidate.ownerDriverId === batch.ownerDriverId &&
1793
+ candidate.ownerGeneration === batch.ownerGeneration,
1794
+ )
1795
+ const delivered = targetBatchState.batches.find(
1796
+ (candidate) => candidate.batchId === batch.batchId,
1797
+ )
1798
+ if (element === undefined || delivered === undefined || element.handle === null) continue
1799
+ for (const carrier of delivered.carriers) {
1800
+ if (!carrier.enqueued || carrier.pendingFrameActivityReleased) continue
1801
+ const authority = identities.find(
1802
+ (candidate) => candidate.identityId === carrier.identityId,
1803
+ )
1804
+ const value = carrierValues.get(carrier.carrierId)
1805
+ if (authority === undefined || value === undefined) continue
1806
+ // Enqueued carriers drain their tasks to the delegate host, then settle in order.
1807
+ recordCarrierDelivery({
1808
+ batchId: batch.batchId,
1809
+ carrierId: carrier.carrierId,
1810
+ authoredIndex: carrier.authoredIndex,
1811
+ identityId: carrier.identityId,
1812
+ key: carrier.key,
1813
+ taskSequence: carrier.taskSequence,
1814
+ })
1815
+ if (!delegateOwnsKey(element, carrier.key)) {
1816
+ writeDelegateValues(element, { [carrier.key]: value })
1817
+ }
1818
+ updateIdentity(authority, (current) => ({
1819
+ ...current,
1820
+ pendingTasks: current.pendingTasks.filter(
1821
+ (task) => task.taskSequence !== carrier.taskSequence,
1822
+ ),
1823
+ }))
1824
+ targetBatchState = advanceGlobalTargetBatch(targetBatchState, {
1825
+ kind: 'SETTLE_TARGET_BATCH_CARRIER',
1826
+ batchId: batch.batchId,
1827
+ carrierId: carrier.carrierId,
1828
+ identityId: carrier.identityId,
1829
+ taskSequence: carrier.taskSequence,
1830
+ }).state
1831
+ }
1832
+ }
1833
+ },
1834
+
1835
+ observe() {
1836
+ return {
1837
+ identities: identities.map((authority) => ({
1838
+ record: authority.record,
1839
+ host: authority.controller.observe(),
1840
+ publicControlSlot: readPublicControlSlot(authority),
1841
+ })),
1842
+ mountedElements: mountedElements.map((element) => ({
1843
+ adapter: element.adapter,
1844
+ handle: element.handle as ElementHandle,
1845
+ sinkRegistrations: identities.flatMap((authority) =>
1846
+ authority.record.sinks.filter(
1847
+ (sink) =>
1848
+ sink.driverId === element.ownerDriverId &&
1849
+ sink.handle === (element.handle as number),
1850
+ ),
1851
+ ),
1852
+ delegateCommittedValues: element.delegate.driver.committed(
1853
+ element.handle as ElementHandle,
1854
+ ),
1855
+ })),
1856
+ runtimeState: runtime.state,
1857
+ targetBatchState,
1858
+ orderedEdges: [...orderedEdges],
1859
+ closedMailboxTurns: [...closedMailboxTurns],
1860
+ carrierDeliveries: [...carrierDeliveries],
1861
+ elementDeliveries: [...elementDeliveries],
1862
+ }
1863
+ },
1864
+ }
1865
+
1866
+ controllerRuntimeInternals.set(runtimeInterface, {
1867
+ findElementByAdapter(adapter) {
1868
+ return elements.find((candidate) => candidate.adapter === adapter) ?? null
1869
+ },
1870
+ ensureElement(ensureOptions) {
1871
+ const existing = elements.find((candidate) => candidate.adapter === ensureOptions.adapter)
1872
+ if (existing !== undefined) {
1873
+ // A reconcile-created element carries its already-registered handle straight into the
1874
+ // mounted observation; no second register crossing exists for it.
1875
+ if (existing.handle === null) existing.handle = ensureOptions.handle
1876
+ if (!mountedElements.includes(existing)) mountedElements.push(existing)
1877
+ return existing
1878
+ }
1879
+ const element: IdentityValueChannelElementAuthority = {
1880
+ adapter: ensureOptions.adapter,
1881
+ delegate: ensureOptions.delegate,
1882
+ ownerDriverId: ensureOptions.ownerDriverId,
1883
+ ownerGeneration: ensureOptions.ownerGeneration,
1884
+ eligibleKeys: [],
1885
+ resolvedStyleValues: {},
1886
+ identityBindings: new Map(),
1887
+ commandOwnedKeys: new Set(),
1888
+ delegateRefusesOwnedWrites: false,
1889
+ handle: ensureOptions.handle,
1890
+ frameValuesListener: null,
1891
+ mountSettled: false,
1892
+ }
1893
+ queueMicrotask(() => {
1894
+ element.mountSettled = true
1895
+ })
1896
+ elements.push(element)
1897
+ mountedElements.push(element)
1898
+ return element
1899
+ },
1900
+ detachIdentityValue: detachIdentityValueFromElement,
1901
+ attachIdentityValue: attachIdentityValueToElement,
1902
+ })
1903
+ return runtimeInterface
1904
+ }
1905
+
1906
+ const canonicalRuntimes = new WeakMap<ValueChannel, IdentityValueChannelControllerRuntime>()
1907
+ const ownerGenerationByDelegate = new WeakMap<WorkletDriverBinding, number>()
1908
+
1909
+ /** The one JS-global identity runtime for an exact public ValueChannel graph. */
1910
+ export function resolveIdentityValueChannelControllerRuntime(
1911
+ channel: ValueChannel,
1912
+ ): IdentityValueChannelControllerRuntime {
1913
+ const existing = canonicalRuntimes.get(channel)
1914
+ if (existing !== undefined) return existing
1915
+ const runtime = createIdentityValueChannelControllerRuntime({
1916
+ channel,
1917
+ identityRegistry: createDriverValueChannelIdentityRegistry<number>(),
1918
+ })
1919
+ canonicalRuntimes.set(channel, runtime)
1920
+ return runtime
1921
+ }
1922
+
1923
+ /**
1924
+ * Production MotionView entrance. Legacy/derived/color bindings stay on their existing delegate;
1925
+ * an exact finite direct-public numeric value resolves the channel-global runtime and receives the
1926
+ * next engine-owned controller generation before `driver.register` can issue a command.
1927
+ */
1928
+ export function attachIdentityValueChannelControllerElement(
1929
+ options: AttachIdentityValueChannelControllerElementOptions,
1930
+ ): IdentityValueChannelControllerElementAdapter | null {
1931
+ const hasEligibleIdentity = Object.entries(options.stylePreparation.boundStyleValues).some(
1932
+ ([key, value]) => isDirectPublicNumericMotionValue(value, options.resolvedStyleValues[key]),
1933
+ )
1934
+ if (!hasEligibleIdentity) return null
1935
+
1936
+ const ownerDriverId = identityValueChannelDriverIdForBinding(options.delegate)
1937
+ if (ownerDriverId === null) {
1938
+ throw new IdentityValueChannelControllerAdapterInvariantError(
1939
+ 'UNREGISTERED_WORKLET_DRIVER_BINDING',
1940
+ )
1941
+ }
1942
+ const runtime = resolveIdentityValueChannelControllerRuntime(options.channel)
1943
+ const ownerGeneration = (ownerGenerationByDelegate.get(options.delegate) ?? 0) + 1
1944
+ ownerGenerationByDelegate.set(options.delegate, ownerGeneration)
1945
+ return runtime.bindingForElement({
1946
+ ownerDriverId,
1947
+ ownerGeneration,
1948
+ stylePreparation: options.stylePreparation,
1949
+ delegate: options.delegate,
1950
+ })
1951
+ }
1952
+
1953
+ /**
1954
+ * Production commit entrance for exact bound-value replacement and removal. The complete ordered
1955
+ * plan is consumed inside MotionView's first insertion effect — detach-before-attach per
1956
+ * replacement — before the same commit's controller update command may start through the key.
1957
+ */
1958
+ export function reconcileIdentityValueChannelControllerElement(
1959
+ options: ReconcileIdentityValueChannelControllerElementOptions,
1960
+ ): void {
1961
+ if (options.plan.changes.length === 0) return
1962
+ const runtime = resolveIdentityValueChannelControllerRuntime(options.channel)
1963
+ const internals = controllerRuntimeInternals.get(runtime)
1964
+ if (internals === undefined) {
1965
+ throw new IdentityValueChannelControllerAdapterInvariantError(
1966
+ 'UNREGISTERED_WORKLET_DRIVER_BINDING',
1967
+ )
1968
+ }
1969
+ let adapter = options.adapter
1970
+ if (adapter === null) {
1971
+ // The mount had no eligible identity, so no adapter exists yet: the attach still lands, on
1972
+ // the next engine-owned generation for this exact delegate.
1973
+ const ownerDriverId = identityValueChannelDriverIdForBinding(options.delegate)
1974
+ if (ownerDriverId === null) {
1975
+ throw new IdentityValueChannelControllerAdapterInvariantError(
1976
+ 'UNREGISTERED_WORKLET_DRIVER_BINDING',
1977
+ )
1978
+ }
1979
+ const ownerGeneration = (ownerGenerationByDelegate.get(options.delegate) ?? 0) + 1
1980
+ ownerGenerationByDelegate.set(options.delegate, ownerGeneration)
1981
+ adapter = runtime.bindingForElement({
1982
+ ownerDriverId,
1983
+ ownerGeneration,
1984
+ stylePreparation: EMPTY_MOUNT_STYLE_PREPARATION,
1985
+ delegate: options.delegate,
1986
+ })
1987
+ }
1988
+ const element = internals.ensureElement({
1989
+ adapter,
1990
+ delegate: options.delegate,
1991
+ ownerDriverId: adapter.ownerDriverId,
1992
+ ownerGeneration: adapter.ownerGeneration,
1993
+ handle: options.handle,
1994
+ })
1995
+
1996
+ for (const change of options.plan.changes) {
1997
+ if (change.kind === 'REPLACE_BOUND_VALUE') {
1998
+ const [detachEdge, attachEdge] = change.orderedEdges
1999
+ // Detach-then-attach in that order; the registry transition rides rebind for an exact
2000
+ // replacement, so the previous record and its successor never fork. An eligible edge is a
2001
+ // direct-public numeric identity by the plan's own admission.
2002
+ const previousSink = detachEdge.identityEligible
2003
+ ? internals.detachIdentityValue(
2004
+ element,
2005
+ detachEdge.key,
2006
+ detachEdge.value as MotionValue<number>,
2007
+ false,
2008
+ )
2009
+ : null
2010
+ if (!attachEdge.identityEligible || typeof attachEdge.resolvedValue !== 'number') continue
2011
+ internals.attachIdentityValue(
2012
+ element,
2013
+ attachEdge.key,
2014
+ attachEdge.value as MotionValue<number>,
2015
+ attachEdge.resolvedValue,
2016
+ previousSink === null
2017
+ ? null
2018
+ : { previousValue: detachEdge.value as MotionValue<number>, previousSink },
2019
+ )
2020
+ writeDelegateValues(element, { [attachEdge.key]: attachEdge.resolvedValue })
2021
+ continue
2022
+ }
2023
+ for (const edge of change.orderedEdges) {
2024
+ if (edge.kind === 'DETACH_BOUND_VALUE') {
2025
+ if (edge.identityEligible) {
2026
+ internals.detachIdentityValue(element, edge.key, edge.value as MotionValue<number>, true)
2027
+ }
2028
+ continue
2029
+ }
2030
+ if (!edge.identityEligible || typeof edge.resolvedValue !== 'number') continue
2031
+ internals.attachIdentityValue(
2032
+ element,
2033
+ edge.key,
2034
+ edge.value as MotionValue<number>,
2035
+ edge.resolvedValue,
2036
+ null,
2037
+ )
2038
+ // The rebind push law: the freshly attached source's live value writes through immediately,
2039
+ // so the host never shows the stale source for one commit.
2040
+ writeDelegateValues(element, { [edge.key]: edge.resolvedValue })
2041
+ }
2042
+ }
2043
+ }