xstate 6.0.0-beta.0 → 6.0.0-beta.2

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 (81) hide show
  1. package/bin/xstate.js +10 -4
  2. package/dist/{createActor-551369be.development.esm.js → createActor-0250284a.development.esm.js} +244 -41
  3. package/dist/{createActor-cbe3abac.esm.js → createActor-20a97166.esm.js} +243 -40
  4. package/dist/{createActor-a49ae0ce.development.cjs.js → createActor-c029d29f.development.cjs.js} +245 -40
  5. package/dist/{createActor-25900f76.cjs.js → createActor-c91c9ffe.cjs.js} +244 -39
  6. package/dist/declarations/src/createActor.d.ts +3 -1
  7. package/dist/declarations/src/createMachine.d.ts +6 -3
  8. package/dist/declarations/src/durable/index.d.ts +43 -8
  9. package/dist/declarations/src/effectDescriptor.d.ts +2 -2
  10. package/dist/declarations/src/machineVersion.types.d.ts +2 -2
  11. package/dist/declarations/src/setup.d.ts +5 -5
  12. package/dist/declarations/src/systemTransition.d.ts +1 -1
  13. package/dist/declarations/src/types.d.ts +11 -3
  14. package/dist/declarations/src/types.v6.d.ts +37 -2
  15. package/dist/{effectDescriptor-f73da4ec.development.cjs.js → effectDescriptor-3fff5c51.development.cjs.js} +5 -5
  16. package/dist/{effectDescriptor-2fa27c54.cjs.js → effectDescriptor-47f73e7e.cjs.js} +5 -5
  17. package/dist/{effectDescriptor-321a8ce9.development.esm.js → effectDescriptor-5ac7dccb.development.esm.js} +5 -5
  18. package/dist/{effectDescriptor-d8b0f749.esm.js → effectDescriptor-e93df910.esm.js} +5 -5
  19. package/dist/{machineSchemas-88d01821.cjs.js → legacySnapshot-8d595687.cjs.js} +117 -1
  20. package/dist/{machineSchemas-45c21bc2.esm.js → legacySnapshot-9e06feb4.esm.js} +116 -2
  21. package/dist/{machineSchemas-b5736804.development.esm.js → legacySnapshot-ae6594a7.development.esm.js} +117 -3
  22. package/dist/{machineSchemas-6d96bef4.development.cjs.js → legacySnapshot-ebf0b2b8.development.cjs.js} +118 -2
  23. package/dist/xstate-actors.cjs.js +1 -1
  24. package/dist/xstate-actors.development.cjs.js +1 -1
  25. package/dist/xstate-actors.development.esm.js +2 -2
  26. package/dist/xstate-actors.esm.js +2 -2
  27. package/dist/xstate-actors.umd.min.js +1 -1
  28. package/dist/xstate-actors.umd.min.js.map +1 -1
  29. package/dist/xstate-durable.cjs.js +120 -10
  30. package/dist/xstate-durable.development.cjs.js +120 -10
  31. package/dist/xstate-durable.development.esm.js +120 -10
  32. package/dist/xstate-durable.esm.js +120 -10
  33. package/dist/xstate-durable.umd.min.js +1 -1
  34. package/dist/xstate-durable.umd.min.js.map +1 -1
  35. package/dist/xstate-fsm.cjs.js +4 -4
  36. package/dist/xstate-fsm.development.cjs.js +4 -4
  37. package/dist/xstate-fsm.development.esm.js +4 -4
  38. package/dist/xstate-fsm.esm.js +4 -4
  39. package/dist/xstate-fsm.umd.min.js +1 -1
  40. package/dist/xstate-fsm.umd.min.js.map +1 -1
  41. package/dist/xstate-graph.cjs.js +1 -1
  42. package/dist/xstate-graph.development.cjs.js +1 -1
  43. package/dist/xstate-graph.development.esm.js +2 -2
  44. package/dist/xstate-graph.esm.js +2 -2
  45. package/dist/xstate-graph.umd.min.js +1 -1
  46. package/dist/xstate-graph.umd.min.js.map +1 -1
  47. package/dist/xstate-persist.cjs.js +23 -12
  48. package/dist/xstate-persist.development.cjs.js +23 -12
  49. package/dist/xstate-persist.development.esm.js +17 -6
  50. package/dist/xstate-persist.esm.js +17 -6
  51. package/dist/xstate-persist.umd.min.js +1 -1
  52. package/dist/xstate-persist.umd.min.js.map +1 -1
  53. package/dist/xstate-validation.cjs.js +1 -1
  54. package/dist/xstate-validation.development.cjs.js +1 -1
  55. package/dist/xstate-validation.development.esm.js +1 -1
  56. package/dist/xstate-validation.esm.js +1 -1
  57. package/dist/xstate.cjs.js +63 -51
  58. package/dist/xstate.development.cjs.js +63 -51
  59. package/dist/xstate.development.esm.js +53 -41
  60. package/dist/xstate.esm.js +53 -41
  61. package/dist/xstate.umd.min.js +1 -1
  62. package/dist/xstate.umd.min.js.map +1 -1
  63. package/docs/agents.md +9 -0
  64. package/docs/api-stability.json +273 -249
  65. package/docs/backend-workflows.md +3 -3
  66. package/docs/durable-execution.md +72 -48
  67. package/docs/errors.md +2 -2
  68. package/docs/examples.md +34 -34
  69. package/docs/fsm.md +2 -1
  70. package/docs/guards.md +1 -1
  71. package/docs/index.md +1 -1
  72. package/docs/invoke.md +34 -2
  73. package/docs/persistence.md +16 -10
  74. package/docs/serialization.md +1 -1
  75. package/docs/setup-and-provide.md +3 -3
  76. package/docs/spawn.md +1 -1
  77. package/docs/system-transitions.md +6 -6
  78. package/docs/tutorial.md +5 -5
  79. package/docs/typescript.md +9 -0
  80. package/docs/xstate-v5-to-v6.md +176 -19
  81. package/package.json +1 -1
@@ -166,11 +166,11 @@ function isRemoteActorRef(actorRef) {
166
166
  * JSON (`actor.toJSON()`): plain data carrying an address, not an actor.
167
167
  */
168
168
  function isSerializedActorRef(target) {
169
- if (typeof target !== 'object' || target === null || Array.isArray(target) || typeof target.$actor !== 'string') {
169
+ if (typeof target !== 'object' || target === null || Array.isArray(target) || typeof target['@actor'] !== 'string') {
170
170
  return false;
171
171
  }
172
172
  for (const key in target) {
173
- if (key !== '$actor' && key !== 'incarnation') {
173
+ if (key !== '@actor' && key !== 'incarnation') {
174
174
  return false;
175
175
  }
176
176
  }
@@ -186,7 +186,7 @@ function getAddressId(address) {
186
186
 
187
187
  /** @internal The error reported when no live actor has a serialized address. */
188
188
  function createMissingAddressError(target) {
189
- return new Error(xstateError(50, ...(target.incarnation === undefined ? [target.$actor] : [target.$actor, target.incarnation])) );
189
+ return new Error(xstateError(50, ...(target.incarnation === undefined ? [target['@actor']] : [target['@actor'], target.incarnation])) );
190
190
  }
191
191
 
192
192
  /**
@@ -195,7 +195,7 @@ function createMissingAddressError(target) {
195
195
  * without one follows whichever actor is live at the address.
196
196
  */
197
197
  function resolveSerializedActorRef(system, target) {
198
- const live = system._getByAddress?.(target.$actor);
198
+ const live = system._getByAddress?.(target['@actor']);
199
199
  return live && (target.incarnation === undefined || live.sessionId === target.incarnation) ? live : undefined;
200
200
  }
201
201
 
@@ -248,7 +248,7 @@ function createInertActorRef(options) {
248
248
  throw new Error(xstateError(51, id));
249
249
  }
250
250
  return {
251
- $actor: address
251
+ '@actor': address
252
252
  };
253
253
  }
254
254
  };
@@ -334,7 +334,7 @@ function createRemoteActorRef(system, options) {
334
334
  // one actor-reference shape whether a child is co-located or remote.
335
335
  toJSON() {
336
336
  return {
337
- $actor: options.address
337
+ '@actor': options.address
338
338
  };
339
339
  }
340
340
  };
@@ -454,7 +454,7 @@ function deliverEvent(source, target, event) {
454
454
  throw error;
455
455
  }
456
456
  void system.deadLetter(source, undefined, event, 'missingTarget', {
457
- targetId: getAddressId(serialized.$actor),
457
+ targetId: getAddressId(serialized['@actor']),
458
458
  error
459
459
  });
460
460
  return;
@@ -2114,6 +2114,18 @@ function withSystemInspector(inspect, fn) {
2114
2114
 
2115
2115
  /** Snapshot-scoped actor identity and system view. @internal */
2116
2116
 
2117
+ // Each view's execution system and whether it forwards inspection. Views
2118
+ // never chain: they all inherit from the execution system directly.
2119
+ const snapshotSystemViews = new WeakMap();
2120
+ // Facilities owned by the execution rather than by one snapshot's view. A view
2121
+ // reads and writes them on the execution system, so timers, listeners and the
2122
+ // runtime installed through any snapshot are visible through every other.
2123
+ const executionFacilities = ['runtime', '_timerMap', '_rejectionListeners', '_inspectionObservers', '_emissionListeners'];
2124
+ // The durable execution that owns each execution system.
2125
+ /** A durable execution, as the owner of the views its transitions create. @internal */
2126
+
2127
+ const executionOwners = new WeakMap();
2128
+ let ambientExecutionOwner;
2117
2129
  const snapshotActorRefs = new WeakMap();
2118
2130
  const lazySnapshotActorRefs = new WeakMap();
2119
2131
  const emptyKeyedActors = new Map();
@@ -2173,12 +2185,22 @@ function getSnapshotChildren(snapshot) {
2173
2185
  *
2174
2186
  * @internal
2175
2187
  */
2176
- function createSnapshotSystem(baseSystem, children, baseState) {
2177
- const forwardInspection = hasAmbientInspector();
2188
+ function createSnapshotSystem(baseSystem, children, baseState, owner) {
2189
+ const baseView = snapshotSystemViews.get(baseSystem);
2190
+ const baseExecutionSystem = baseView?.executionSystem ?? baseSystem;
2191
+ // The runtime system under every view. A view runs its methods against the
2192
+ // execution system's facilities.
2193
+ const rootSystem = baseView?.rootSystem ?? baseSystem;
2194
+ const forks = owner !== undefined && executionOwners.get(baseExecutionSystem) !== owner;
2195
+ // A view an execution owns reports to that execution's inspector.
2196
+ const forwardInspection = owner ? !!owner.inspect : hasAmbientInspector() && (baseView?.forwardInspection ?? true);
2178
2197
  const registeredActors = copyRegisteredActors(baseSystem, baseState);
2179
2198
  const keyedActors = new Map(baseState?.keyedActors ?? getKeyedActors(baseSystem));
2180
2199
  const reverseKeyedActors = new WeakMap();
2181
- const system = Object.assign(Object.create(baseSystem), {
2200
+ // The view's execution system; adoption can make the view its own.
2201
+ const execution = () => snapshotSystemViews.get(system).executionSystem;
2202
+ const forwards = () => snapshotSystemViews.get(system).forwardInspection;
2203
+ const system = Object.assign(Object.create(baseExecutionSystem), {
2182
2204
  children: registeredActors,
2183
2205
  keyedActors,
2184
2206
  reverseKeyedActors,
@@ -2213,15 +2235,38 @@ function createSnapshotSystem(baseSystem, children, baseState) {
2213
2235
  },
2214
2236
  get: registryKey => keyedActors.get(registryKey),
2215
2237
  getAll: () => Object.fromEntries(keyedActors),
2216
- onEmitted: listener => baseSystem.onEmitted(listener),
2217
- _notifyEmitted: (actorRef, event) => baseSystem._notifyEmitted(actorRef, event),
2238
+ onEmitted: listener => rootSystem.onEmitted.call(execution(), listener),
2239
+ _notifyEmitted: (actorRef, event) => rootSystem._notifyEmitted.call(execution(), actorRef, event),
2218
2240
  // Pure transition resolution must not leak topology inspection events
2219
2241
  // into a live runtime system — planning branches stay silent. The one
2220
2242
  // exception is a durable execution's own transitions (marked by the
2221
2243
  // ambient inspector at creation time): there the pure path IS the
2222
- // execution, so inspection forwards to the base system's observers.
2223
- _hasInspectionObservers: forwardInspection ? () => baseSystem._hasInspectionObservers?.() ?? false : () => false,
2224
- _sendInspectionEvent: forwardInspection ? event => baseSystem._sendInspectionEvent(event) : () => {}
2244
+ // execution, so inspection forwards to the execution system's observers.
2245
+ _hasInspectionObservers: () => forwards() && (rootSystem._hasInspectionObservers?.call(execution()) ?? false),
2246
+ _sendInspectionEvent: event => {
2247
+ if (forwards()) {
2248
+ rootSystem._sendInspectionEvent.call(execution(), event);
2249
+ }
2250
+ }
2251
+ });
2252
+ const executionSystem = forks ? system : baseExecutionSystem;
2253
+ if (forks) {
2254
+ forkFacilities(system, baseExecutionSystem, owner);
2255
+ } else {
2256
+ for (const key of executionFacilities) {
2257
+ Object.defineProperty(system, key, {
2258
+ configurable: true,
2259
+ get: () => execution()[key],
2260
+ set: value => {
2261
+ execution()[key] = value;
2262
+ }
2263
+ });
2264
+ }
2265
+ }
2266
+ snapshotSystemViews.set(system, {
2267
+ executionSystem,
2268
+ rootSystem,
2269
+ forwardInspection
2225
2270
  });
2226
2271
  for (const [registryKey, actor] of keyedActors) {
2227
2272
  if (!actor) {
@@ -2245,6 +2290,83 @@ function createSnapshotSystem(baseSystem, children, baseState) {
2245
2290
  return system;
2246
2291
  }
2247
2292
 
2293
+ /**
2294
+ * Makes `system` the execution system of `owner`, a new incarnation: it gets
2295
+ * the owner's runtime and the pending timers it saw, and starts with no
2296
+ * listeners or inspectors, so nothing registered on another execution
2297
+ * observes it.
2298
+ */
2299
+ function forkFacilities(system, from, owner) {
2300
+ const timers = from._timerMap;
2301
+ for (const key of executionFacilities) {
2302
+ Object.defineProperty(system, key, {
2303
+ configurable: true,
2304
+ writable: true,
2305
+ value: key === 'runtime' ? owner.runtime : key === '_timerMap' && timers ? {
2306
+ ...timers
2307
+ } : undefined
2308
+ });
2309
+ }
2310
+ executionOwners.set(system, owner);
2311
+ if (owner.inspect) {
2312
+ system.inspect(owner.inspect);
2313
+ }
2314
+ }
2315
+
2316
+ /**
2317
+ * Makes `owner` own `system` before it installs its runtime there, and
2318
+ * returns whether it does. An unowned view forks in place, so the install
2319
+ * never reaches the system it was derived from. A system another execution
2320
+ * owns is left alone.
2321
+ *
2322
+ * @internal
2323
+ */
2324
+ function adoptSystem(system, owner) {
2325
+ const view = snapshotSystemViews.get(system);
2326
+ const current = executionOwners.get(view?.executionSystem ?? system);
2327
+ if (current === owner) {
2328
+ if (view) {
2329
+ view.forwardInspection = !!owner.inspect;
2330
+ }
2331
+ return true;
2332
+ }
2333
+ // A system another execution owns stays with it.
2334
+ if (current) {
2335
+ return false;
2336
+ }
2337
+ if (!view) {
2338
+ executionOwners.set(system, owner);
2339
+ return true;
2340
+ }
2341
+ forkFacilities(system, view.executionSystem, owner);
2342
+ view.executionSystem = system;
2343
+ view.forwardInspection = !!owner.inspect;
2344
+ return true;
2345
+ }
2346
+
2347
+ /**
2348
+ * Runs `fn` as a transition of `owner`. A view it derives from a system the
2349
+ * owner does not own forks into the owner's own execution system.
2350
+ *
2351
+ * @internal
2352
+ */
2353
+ function withExecutionOwner(owner, fn) {
2354
+ const previous = ambientExecutionOwner;
2355
+ ambientExecutionOwner = owner;
2356
+ try {
2357
+ return fn();
2358
+ } finally {
2359
+ ambientExecutionOwner = previous;
2360
+ }
2361
+ }
2362
+
2363
+ /** Hands the ambient owner to the first scope that asks for it. @internal */
2364
+ function takeExecutionOwner() {
2365
+ const owner = ambientExecutionOwner;
2366
+ ambientExecutionOwner = undefined;
2367
+ return owner;
2368
+ }
2369
+
2248
2370
  /** Returns the actor identity associated with a transition snapshot. @internal */
2249
2371
  function getSnapshotActorRef(snapshot) {
2250
2372
  const existing = snapshotActorRefs.get(snapshot);
@@ -2438,8 +2560,9 @@ function setInertActorScopeSnapshot(actorScope, snapshot, attachActorRef = true)
2438
2560
  const lazyState = getLazyInertActorState(actorScope);
2439
2561
  if (lazyState) {
2440
2562
  lazyState.snapshot = snapshot;
2441
- if (lazyState.materialized) {
2442
- lazyState.materialized.self._snapshot = snapshot;
2563
+ const scope = lazyState.materialized ?? lazyState.identityScope;
2564
+ if (scope) {
2565
+ scope.self._snapshot = snapshot;
2443
2566
  }
2444
2567
  } else {
2445
2568
  actorScope.self._snapshot = snapshot;
@@ -2474,6 +2597,15 @@ function attachSnapshotActorRef(actorScope, snapshot) {
2474
2597
  setLazySnapshotActorRef(snapshot, create);
2475
2598
  return snapshot;
2476
2599
  }
2600
+ /** Records the materialized scope and releases its consumed source. */
2601
+ function commitMaterialization(state, scope) {
2602
+ // Dropping the consumed source keeps this scope from retaining earlier snapshots.
2603
+ state.sourceRef = undefined;
2604
+ state.sourceChildren = {};
2605
+ state.materialized = scope;
2606
+ state.materialize = () => scope;
2607
+ return scope;
2608
+ }
2477
2609
  const lazyInertActorState = Symbol();
2478
2610
  const snapshotActorScopes = new WeakMap();
2479
2611
  let inertActorMaterializationObserver;
@@ -2518,12 +2650,14 @@ const lazyInertActorScopePrototype = {
2518
2650
  return materializeInertActorScope(this).actionExecutor;
2519
2651
  }
2520
2652
  };
2521
- function createMaterializedInertActorScope(actorLogic, sourceRef, sourceChildren, currentSnapshot, sourceSelf) {
2653
+
2654
+ /** Creates a transactional planning scope backed by an inert actor. */
2655
+ function createMaterializedInertActorScope(actorLogic, sourceRef, sourceChildren, currentSnapshot, sourceSelf, owner) {
2522
2656
  inertActorMaterializationObserver?.();
2523
2657
  const snapshotRef = sourceRef?.();
2524
2658
  const previousSelf = sourceSelf ?? snapshotRef?.actor;
2525
2659
  const baseSystem = previousSelf?.system;
2526
- const system = previousSelf && baseSystem ? createSnapshotSystem(baseSystem, sourceChildren, sourceSelf ? undefined : snapshotRef?.systemState) : undefined;
2660
+ const system = previousSelf && baseSystem ? createSnapshotSystem(baseSystem, sourceChildren, sourceSelf ? undefined : snapshotRef?.systemState, owner) : undefined;
2527
2661
  const self = createActor(actorLogic, {
2528
2662
  _inert: true,
2529
2663
  ...(previousSelf ? {
@@ -2543,12 +2677,8 @@ function createMaterializedInertActorScope(actorLogic, sourceRef, sourceChildren
2543
2677
  // a future construction-time read cannot pin a root-shaped address.
2544
2678
  self._address = undefined;
2545
2679
  }
2546
- if (currentSnapshot) {
2547
- self._snapshot = currentSnapshot;
2548
- }
2549
-
2550
2680
  // Reuse the branch actor's scope while keeping planning transactional.
2551
- return Object.create(self._actorScope, {
2681
+ const scope = Object.create(self._actorScope, {
2552
2682
  defer: {
2553
2683
  value: () => {}
2554
2684
  },
@@ -2557,8 +2687,20 @@ function createMaterializedInertActorScope(actorLogic, sourceRef, sourceChildren
2557
2687
  },
2558
2688
  actionExecutor: {
2559
2689
  value: () => {}
2690
+ },
2691
+ _snapshot: {
2692
+ enumerable: true,
2693
+ configurable: true,
2694
+ get: () => self._snapshot,
2695
+ set: snapshot => {
2696
+ self._snapshot = snapshot;
2697
+ }
2560
2698
  }
2561
2699
  });
2700
+ if (currentSnapshot) {
2701
+ scope._snapshot = currentSnapshot;
2702
+ }
2703
+ return scope;
2562
2704
  }
2563
2705
 
2564
2706
  /** @internal */
@@ -2573,22 +2715,34 @@ function createInertActorScope(actorLogic, snapshot, sourceSelf, sourceActorScop
2573
2715
  sourceChildren: isMachineSnapshot(snapshot) ? snapshot.children : {},
2574
2716
  identityProvider: sourceState?.identityProvider ?? sourceRef,
2575
2717
  parent: sourceSelf?._parent ?? sourceState?.parent ?? eagerSourceRef?.actor._parent,
2718
+ // Only the outermost scope of an owned transition belongs to the owner;
2719
+ // scopes for its intermediate snapshots inherit it, and nested pure
2720
+ // transitions run unowned.
2721
+ owner: sourceActorScope ? sourceState?.owner : takeExecutionOwner(),
2576
2722
  parentKnown: !!sourceSelf || !!sourceState?.parentKnown || !!eagerSourceRef || !snapshot
2577
2723
  };
2578
- state.materialize = () => state.materialized ??= createMaterializedInertActorScope(actorLogic, state.sourceRef, state.sourceChildren, state.snapshot, sourceSelf);
2724
+ state.materialize = () => {
2725
+ const scope = createMaterializedInertActorScope(actorLogic, state.sourceRef, state.sourceChildren, state.snapshot, sourceSelf, state.owner);
2726
+ return commitMaterialization(state, scope);
2727
+ };
2579
2728
  if (!state.identityProvider && !snapshot) {
2580
2729
  const identitySnapshot = {};
2581
- const identitySourceRef = state.sourceRef;
2582
- const identitySourceChildren = state.sourceChildren;
2583
- let identityScope;
2584
2730
  let identityRef;
2585
- const getIdentityScope = () => identityScope ??= createMaterializedInertActorScope(actorLogic, identitySourceRef, identitySourceChildren, undefined, sourceSelf);
2731
+ const getIdentityScope = () => {
2732
+ if (!state.identityScope) {
2733
+ state.identityScope = createMaterializedInertActorScope(actorLogic, state.sourceRef, state.sourceChildren, undefined, sourceSelf, state.owner);
2734
+ if (state.snapshot !== undefined) {
2735
+ state.identityScope.self._snapshot = state.snapshot;
2736
+ }
2737
+ }
2738
+ return state.identityScope;
2739
+ };
2586
2740
  state.materialize = () => {
2587
2741
  const scope = getIdentityScope();
2588
2742
  if (state.snapshot !== undefined) {
2589
2743
  scope.self._snapshot = state.snapshot;
2590
2744
  }
2591
- return state.materialized = scope;
2745
+ return commitMaterialization(state, scope);
2592
2746
  };
2593
2747
  state.identityProvider = () => {
2594
2748
  if (identityRef) {
@@ -4561,6 +4715,8 @@ const machineSnapshotToJSON = function toJSON() {
4561
4715
  const {
4562
4716
  nodes,
4563
4717
  _stateInputs,
4718
+ _nextTimerId,
4719
+ _nextActorIds,
4564
4720
  tags,
4565
4721
  machine,
4566
4722
  getMeta,
@@ -4679,6 +4835,8 @@ function getPersistedSnapshot(snapshot, options) {
4679
4835
  const {
4680
4836
  nodes,
4681
4837
  _stateInputs,
4838
+ _nextTimerId,
4839
+ _nextActorIds,
4682
4840
  tags,
4683
4841
  machine,
4684
4842
  children,
@@ -4805,6 +4963,11 @@ function getPersistedSnapshot(snapshot, options) {
4805
4963
  if (_stateInputs && Object.keys(_stateInputs).length > 0) {
4806
4964
  persisted.stateInputs = _stateInputs;
4807
4965
  }
4966
+ // Stores such as Convex reject `_`-prefixed field names.
4967
+ persisted.nextTimerId = _nextTimerId;
4968
+ if (_nextActorIds && Object.keys(_nextActorIds).length > 0) {
4969
+ persisted.nextActorIds = _nextActorIds;
4970
+ }
4808
4971
  if (machine.version !== undefined) {
4809
4972
  persisted.machine = {
4810
4973
  id: machine.id,
@@ -4827,7 +4990,7 @@ function persistContext(contextPart, getActorId, path = 'context', ancestors = [
4827
4990
  };
4828
4991
  // The address lets refs to non-children still route after restore.
4829
4992
  copy[key] = {
4830
- $actor: value.address
4993
+ '@actor': value.address
4831
4994
  };
4832
4995
  } else {
4833
4996
  const valuePath = Array.isArray(contextPart) ? `${path}[${key}]` : `${path}.${key}`;
@@ -5460,11 +5623,18 @@ class RuntimeSystem {
5460
5623
  // Records a send on the *sender's* transition for the `sent[]` inspection
5461
5624
  // facet. Captures the send when it is initiated (including delayed sends that
5462
5625
  // may never deliver), keyed to the source actor's in-flight transition.
5626
+ // A send made with no transition in flight (a callback's `sendBack`, a value
5627
+ // an observable relays to its parent) is not recorded: no transition reports
5628
+ // it, so it would be held until the source's next transition, or for as long
5629
+ // as the source lives if it never makes one.
5463
5630
  _recordSent(source, target, event, delay, id) {
5464
5631
  if (!this._inspectionObservers?.size || !source) {
5465
5632
  return;
5466
5633
  }
5467
5634
  const inspectionSource = source;
5635
+ if (!inspectionSource._inTransition) {
5636
+ return;
5637
+ }
5468
5638
  const collected = inspectionSource._collectedSent ??= [];
5469
5639
  collected.push({
5470
5640
  targetRef: target,
@@ -5701,9 +5871,9 @@ class RuntimeSystem {
5701
5871
  } else if (
5702
5872
  // A live actor of another incarnation is stale locally; an
5703
5873
  // address this system cannot see may belong to a host runtime.
5704
- this._getByAddress(target.$actor) || !this.runtime?.sendEvent) {
5874
+ this._getByAddress(target['@actor']) || !this.runtime?.sendEvent) {
5705
5875
  return this.deadLetter(source, undefined, event, 'missingTarget', {
5706
- targetId: getAddressId(target.$actor),
5876
+ targetId: getAddressId(target['@actor']),
5707
5877
  error: createMissingAddressError(target)
5708
5878
  });
5709
5879
  }
@@ -5987,6 +6157,12 @@ class Actor {
5987
6157
  this._collectedActions = void 0;
5988
6158
  /** @internal Events relayed to other actors during the in-flight transition. */
5989
6159
  this._collectedSent = void 0;
6160
+ /**
6161
+ * @internal Whether a transition is in flight: while the actor starts,
6162
+ * processes an event, or recovers from an execution error. Sends are recorded
6163
+ * for `sent[]` only then.
6164
+ */
6165
+ this._inTransition = false;
5990
6166
  this._initialEffects = void 0;
5991
6167
  this.registryKey = void 0;
5992
6168
  /** The globally unique process ID for this invocation. */
@@ -6059,9 +6235,14 @@ class Actor {
6059
6235
  // transition functions; computing an initial snapshot here would run
6060
6236
  // init-time side effects (context factories, entry) a second time.
6061
6237
  } else {
6062
- const [snapshot, effects] = finalizeTransitionResult(this._actorScope, undefined, this.logic.initialTransition(this.options?.input, this._actorScope));
6063
- this._setSnapshot(snapshot);
6064
- this._initialEffects = effects.length ? effects : undefined;
6238
+ this._inTransition = true;
6239
+ try {
6240
+ const [snapshot, effects] = finalizeTransitionResult(this._actorScope, undefined, this.logic.initialTransition(this.options?.input, this._actorScope));
6241
+ this._setSnapshot(snapshot);
6242
+ this._initialEffects = effects.length ? effects : undefined;
6243
+ } finally {
6244
+ this._inTransition = false;
6245
+ }
6065
6246
  }
6066
6247
  } catch (err) {
6067
6248
  // Restored logic may keep its snapshot shape on restore failures (e.g.
@@ -6214,6 +6395,8 @@ class Actor {
6214
6395
  if (!errorEvent) {
6215
6396
  return false;
6216
6397
  }
6398
+ const inTransition = this._inTransition;
6399
+ this._inTransition = true;
6217
6400
  try {
6218
6401
  const [nextSnapshot, effects] = finalizeTransitionResult(this._actorScope, snapshot, this.logic.transition(snapshot, errorEvent, this._actorScope));
6219
6402
  this._setSnapshot(nextSnapshot);
@@ -6222,6 +6405,8 @@ class Actor {
6222
6405
  return true;
6223
6406
  } catch {
6224
6407
  return false;
6408
+ } finally {
6409
+ this._inTransition = inTransition;
6225
6410
  }
6226
6411
  }
6227
6412
  _next(snapshot) {
@@ -6433,6 +6618,15 @@ class Actor {
6433
6618
 
6434
6619
  /** Starts the Actor from the initial state */
6435
6620
  start() {
6621
+ const inTransition = this._inTransition;
6622
+ this._inTransition = true;
6623
+ try {
6624
+ return this._start();
6625
+ } finally {
6626
+ this._inTransition = inTransition;
6627
+ }
6628
+ }
6629
+ _start() {
6436
6630
  if (this._processingStatus === ProcessingStatus.Running) {
6437
6631
  // Do not restart the service if it is already started
6438
6632
  return this;
@@ -6548,7 +6742,16 @@ class Actor {
6548
6742
  this.mailbox?.start();
6549
6743
  return this;
6550
6744
  }
6551
- _process({
6745
+ _process(item) {
6746
+ const inTransition = this._inTransition;
6747
+ this._inTransition = true;
6748
+ try {
6749
+ this._processEvent(item);
6750
+ } finally {
6751
+ this._inTransition = inTransition;
6752
+ }
6753
+ }
6754
+ _processEvent({
6552
6755
  event,
6553
6756
  sourceRef
6554
6757
  }) {
@@ -6785,12 +6988,12 @@ class Actor {
6785
6988
  }
6786
6989
 
6787
6990
  /**
6788
- * Returns the actor's serializable logical identity: `{ $actor: address }`.
6991
+ * Returns the actor's serializable logical identity: `{ "@actor": address }`.
6789
6992
  * The result can be used as an `enq.sendTo(...)` target.
6790
6993
  */
6791
6994
  toJSON() {
6792
6995
  return {
6793
- $actor: this.address
6996
+ '@actor': this.address
6794
6997
  };
6795
6998
  }
6796
6999
 
@@ -6914,6 +7117,7 @@ exports.XSTATE_LOGIC_EFFECT_START = XSTATE_LOGIC_EFFECT_START;
6914
7117
  exports.XSTATE_STOP = XSTATE_STOP;
6915
7118
  exports.XSTATE_STOP_EFFECT = XSTATE_STOP_EFFECT;
6916
7119
  exports.XSTATE_TIMER = XSTATE_TIMER;
7120
+ exports.adoptSystem = adoptSystem;
6917
7121
  exports.allocateChildId = allocateChildId;
6918
7122
  exports.assertChildIdFree = assertChildIdFree;
6919
7123
  exports.assertUnreservedSourceName = assertUnreservedSourceName;
@@ -7011,5 +7215,6 @@ exports.toTransitionConfigArray = toTransitionConfigArray;
7011
7215
  exports.transitionNode = transitionNode;
7012
7216
  exports.withActorSelf = withActorSelf;
7013
7217
  exports.withExecutionIdentity = withExecutionIdentity;
7218
+ exports.withExecutionOwner = withExecutionOwner;
7014
7219
  exports.withSystemInspector = withSystemInspector;
7015
7220
  exports.xstateError = xstateError;
@@ -163,7 +163,9 @@ export declare class Actor<TLogic extends AnyActorLogic> implements ActorInstanc
163
163
  select<TSelected>(selector: (snapshot: SnapshotFrom<TLogic>) => TSelected, equalityFn?: (a: TSelected, b: TSelected) => boolean): Readable<TSelected>;
164
164
  /** Starts the Actor from the initial state */
165
165
  start(): this;
166
+ private _start;
166
167
  private _process;
168
+ private _processEvent;
167
169
  private _warnedUnhandledTypes?;
168
170
  private _reportUnhandledEvent;
169
171
  /** Stops the Actor and unsubscribe all listeners. */
@@ -185,7 +187,7 @@ export declare class Actor<TLogic extends AnyActorLogic> implements ActorInstanc
185
187
  */
186
188
  private _sendPublic;
187
189
  /**
188
- * Returns the actor's serializable logical identity: `{ $actor: address }`.
190
+ * Returns the actor's serializable logical identity: `{ "@actor": address }`.
189
191
  * The result can be used as an `enq.sendTo(...)` target.
190
192
  */
191
193
  toJSON(): SerializedActorRef;
@@ -4,8 +4,11 @@ import type { Spawner } from "./spawn.js";
4
4
  import type { ActorLogicValidator } from "./validation.types.js";
5
5
  import { AnyActorRef, AnyStateMachine, EventObject, AnyEventObject, MachineContext, ProvidedActor, StateValueFromStateSchema, ToChildren, MetaObject, StateSchema, RoutableStateId } from "./types.js";
6
6
  import type { Cast, DoNotInfer, Compute } from "./typeUtils.js";
7
- import { ChildCompletionEvents, Sources, DelayMapFromNames, InferChildren, InferMachineInput, InferOutput, SchemaOrConfigOutput, InferEvents, InferInternalEvents, Next_MachineConfig, Next_StateNodeConfig, ValidateDelayReferences, ValidateEventDescriptors, ValidateHistoryDefaults, ValidateInvokeInputs, ValidateVersionedMachineId, ValidateStateTargets, ValidateTopLevelFinalOutputs, WidenLiterals, WithDefault } from "./types.v6.js";
7
+ import { ChildCompletionEvents, Sources, DelayMapFromNames, InferChildren, InferredInvokeChildren, InferMachineInput, InferOutput, SchemaOrConfigOutput, InferEvents, InferInternalEvents, Next_MachineConfig, Next_StateNodeConfig, ValidateDelayReferences, ValidateEventDescriptors, ValidateHistoryDefaults, ValidateInvokeInputs, ValidateVersionedMachineId, ValidateStateTargets, ValidateTopLevelFinalOutputs, WidenLiterals, WithDefault } from "./types.v6.js";
8
8
  type MergeChildren<TChildren extends Record<string, AnyActorRef | undefined>, TActor extends ProvidedActor> = [keyof TChildren] extends [never] ? Compute<ToChildren<TActor>> : Compute<TChildren>;
9
+ type ConfigActors<TConfig, TActorMap extends Sources['actors']> = TConfig extends {
10
+ actors: infer TActors extends Sources['actors'];
11
+ } ? TActors : TActorMap;
9
12
  type MachineIdentity<TConfig> = {
10
13
  readonly id: TConfig extends {
11
14
  id: infer TId extends string;
@@ -66,7 +69,7 @@ export declare function createMachine<TContextSchema extends StandardSchemaV1, c
66
69
  } & ValidateTopLevelFinalOutputs<TSS, InferOutput<TContextSchema, MachineContext>, InferEvents<TEventSchemaMap> | InferInternalEvents<TInternalEventSchemaMap>>): [TSS] extends [never] ? AnyStateMachine : StateMachine<InferOutput<TContextSchema, MachineContext>, (InferEvents<TEventSchemaMap> | InferInternalEvents<TInternalEventSchemaMap>) | ([RoutableStateId<TSS>] extends [never] ? never : {
67
70
  type: 'xstate.route';
68
71
  to: RoutableStateId<TSS>;
69
- }), Cast<MergeChildren<InferChildren<TChildrenSchemaMap>, TActor>, Record<string, AnyActorRef | undefined>>, StateValueFromStateSchema<TSS>, TTag & string, InferMachineInput<TInputSchema>, SchemaOrConfigOutput<TOutputSchema, TSS>, WithDefault<InferEvents<TEmittedSchemaMap>, AnyEventObject>, InferOutput<TMetaSchema, MetaObject>, // TMeta
72
+ }), Cast<MergeChildren<InferChildren<TChildrenSchemaMap>, TActor> & InferredInvokeChildren<TSS, ConfigActors<TSS, TActorMap>>, Record<string, AnyActorRef | undefined>>, StateValueFromStateSchema<TSS>, TTag & string, InferMachineInput<TInputSchema>, SchemaOrConfigOutput<TOutputSchema, TSS>, WithDefault<InferEvents<TEmittedSchemaMap>, AnyEventObject>, InferOutput<TMetaSchema, MetaObject>, // TMeta
70
73
  TSS, // TStateSchema
71
74
  TActionMap, TActorMap, TGuardMap, DelayMapFromNames<TDelays, TDelayMap>, InferInternalEvents<TInternalEventSchemaMap>, TransitionMetaFromSchemas<TMetaSchema, TTransitionMetaSchema>> & {
72
75
  states: TSS;
@@ -84,7 +87,7 @@ export declare function createMachine<TContext extends MachineContext = never, c
84
87
  } & ValidateTopLevelFinalOutputs<TSS, WidenLiterals<TContext>, InferEvents<TEventSchemaMap> | InferInternalEvents<TInternalEventSchemaMap>>): [TSS] extends [never] ? AnyStateMachine : StateMachine<WidenLiterals<TContext>, (InferEvents<TEventSchemaMap> | InferInternalEvents<TInternalEventSchemaMap>) | ([RoutableStateId<TSS>] extends [never] ? never : {
85
88
  type: 'xstate.route';
86
89
  to: RoutableStateId<TSS>;
87
- }), Cast<MergeChildren<InferChildren<TChildrenSchemaMap>, TActor>, Record<string, AnyActorRef | undefined>>, StateValueFromStateSchema<TSS>, TTag & string, InferMachineInput<TInputSchema>, SchemaOrConfigOutput<TOutputSchema, TSS>, WithDefault<InferEvents<TEmittedSchemaMap>, AnyEventObject>, InferOutput<TMetaSchema, MetaObject>, // TMeta
90
+ }), Cast<MergeChildren<InferChildren<TChildrenSchemaMap>, TActor> & InferredInvokeChildren<TSS, ConfigActors<TSS, TActorMap>>, Record<string, AnyActorRef | undefined>>, StateValueFromStateSchema<TSS>, TTag & string, InferMachineInput<TInputSchema>, SchemaOrConfigOutput<TOutputSchema, TSS>, WithDefault<InferEvents<TEmittedSchemaMap>, AnyEventObject>, InferOutput<TMetaSchema, MetaObject>, // TMeta
88
91
  TSS, // TStateSchema
89
92
  TActionMap, TActorMap, TGuardMap, DelayMapFromNames<TDelays, TDelayMap>, InferInternalEvents<TInternalEventSchemaMap>, TransitionMetaFromSchemas<TMetaSchema, TTransitionMetaSchema>> & {
90
93
  states: TSS;
@@ -1,7 +1,7 @@
1
1
  import { type ExecutableEffectDescriptor } from "../effectDescriptor.js";
2
2
  import { type ActorSystemRuntime } from "../system.js";
3
3
  import type { InspectionEvent } from "../inspection.js";
4
- import type { AnyActor, AnyActorLogic, AnyEventObject, CustomExecutableEffect, EventFromLogic, ExecutableEffectFrom, InputFrom, OutputFrom, Snapshot, SnapshotFrom } from "../types.js";
4
+ import type { AnyActor, AnyActorLogic, AnyEventObject, CustomExecutableEffect, EventFromLogic, ExecutableEffectFrom, InputFrom, OutputFrom, SerializedActorRef, Snapshot, SnapshotFrom } from "../types.js";
5
5
  /** @experimental */
6
6
  export interface DurableEffectMetadata {
7
7
  /** Stable within one durable execution. */
@@ -26,6 +26,28 @@ export interface DurableRootEvent<TEvent> {
26
26
  event: TEvent;
27
27
  source: AnyActor | undefined;
28
28
  }
29
+ /**
30
+ * A root-addressed event that the execution received but has not processed,
31
+ * stored in a checkpoint. `source` is the sender's logical address.
32
+ *
33
+ * @experimental
34
+ */
35
+ export interface DurableInboxEntry {
36
+ event: AnyEventObject;
37
+ source: SerializedActorRef | undefined;
38
+ }
39
+ /**
40
+ * Everything needed to resume an execution: the persisted snapshot, the next
41
+ * transition index and the events received but not yet processed. Persist
42
+ * the whole object atomically and pass it to `restore()`.
43
+ *
44
+ * @experimental
45
+ */
46
+ export interface DurableCheckpoint {
47
+ snapshot: Snapshot<unknown>;
48
+ nextTransitionIndex: number;
49
+ inbox: DurableInboxEntry[];
50
+ }
29
51
  /** @experimental */
30
52
  export interface DurableEffect<TEffect> extends DurableEffectMetadata {
31
53
  effect: TEffect;
@@ -148,13 +170,26 @@ export interface DurableExecution<TLogic extends AnyActorLogic> {
148
170
  /** Index assigned to the next transition. Persist this with checkpoints. */
149
171
  readonly nextTransitionIndex: number;
150
172
  /**
151
- * Restores a checkpoint on a fresh execution. Returns effects that start
152
- * active embedded children and re-arm pending root timers; execute them
153
- * with `executeEffects` before waiting or processing the next event.
154
- * Does not send a machine event, replay entry actions, or advance the
155
- * transition index. Restoration effect IDs use `restore:<index>:<effect>`.
173
+ * Returns a checkpoint of `snapshot`: its persisted form, the next
174
+ * transition index and the inbox of root events captured by settled
175
+ * `executeEffects` batches but not yet taken by `waitForEvent()`. Call it
176
+ * after `executeEffects` resolves. Inbox event payloads are stored as they
177
+ * are, so they must be serializable data, like timer events in persisted
178
+ * snapshots. Lifecycle events for children no longer in `snapshot` are
179
+ * dropped, and child snapshot updates are not stored: a restored child
180
+ * reports its current snapshot when it starts.
181
+ */
182
+ checkpoint(snapshot: SnapshotFrom<TLogic>, options?: unknown): DurableCheckpoint;
183
+ /**
184
+ * Restores a checkpoint on a fresh execution. Accepts a `checkpoint()`
185
+ * result, whose inbox `waitForEvent()` hands out first, or a bare persisted
186
+ * snapshot. Returns effects that start active embedded children and re-arm
187
+ * pending root timers; execute them with `executeEffects` before waiting or
188
+ * processing the next event. Does not send a machine event, replay entry
189
+ * actions, or advance the transition index. Restoration effect IDs use
190
+ * `restore:<index>:<effect>`.
156
191
  */
157
- restore(persistedSnapshot: Snapshot<unknown>): [
192
+ restore(checkpoint: DurableCheckpoint | Snapshot<unknown>): [
158
193
  snapshot: DurableSnapshot<TLogic>,
159
194
  effects: DurableEffect<ExecutableEffectFrom<TLogic>>[]
160
195
  ];
@@ -196,7 +231,7 @@ export interface DurableExecution<TLogic extends AnyActorLogic> {
196
231
  * an event a prior `executeEffects` batch captured (an invoked actor
197
232
  * completing, a child reporting up), or — once none are queued — whatever
198
233
  * the adapter's durable wait produces. With `captureRootEvents: false`,
199
- * always delegates to the adapter's wait.
234
+ * delegates to the adapter's wait once a restored inbox is empty.
200
235
  */
201
236
  waitForEvent(): Promise<EventFromLogic<TLogic>>;
202
237
  run(...[input]: undefined extends InputFrom<TLogic> ? [input?: InputFrom<TLogic>] : [input: InputFrom<TLogic>]): Promise<OutputFrom<TLogic>>;