xstate 6.0.0-beta.1 → 6.0.0-beta.3

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 (87) hide show
  1. package/README.md +4 -2
  2. package/dist/{createActor-cbe3abac.esm.js → createActor-49ea55ba.esm.js} +259 -47
  3. package/dist/{createActor-25900f76.cjs.js → createActor-73aa92ba.cjs.js} +261 -46
  4. package/dist/{createActor-551369be.development.esm.js → createActor-a085b20b.development.esm.js} +260 -48
  5. package/dist/{createActor-a49ae0ce.development.cjs.js → createActor-dfb6b790.development.cjs.js} +262 -47
  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/fsm.d.ts +7 -7
  11. package/dist/declarations/src/machineVersion.types.d.ts +2 -2
  12. package/dist/declarations/src/setup.d.ts +2 -2
  13. package/dist/declarations/src/systemTransition.d.ts +1 -1
  14. package/dist/declarations/src/types.d.ts +4 -2
  15. package/dist/declarations/src/types.v6.d.ts +37 -2
  16. package/dist/{effectDescriptor-2fa27c54.cjs.js → effectDescriptor-3402f63e.cjs.js} +5 -5
  17. package/dist/{effectDescriptor-d8b0f749.esm.js → effectDescriptor-65821048.development.esm.js} +5 -5
  18. package/dist/{effectDescriptor-321a8ce9.development.esm.js → effectDescriptor-72c62058.esm.js} +5 -5
  19. package/dist/{effectDescriptor-f73da4ec.development.cjs.js → effectDescriptor-d0ea44ad.development.cjs.js} +5 -5
  20. package/dist/{machineSchemas-b5736804.development.esm.js → legacySnapshot-11aba2d2.development.esm.js} +117 -3
  21. package/dist/{machineSchemas-6d96bef4.development.cjs.js → legacySnapshot-2e2c1d3b.development.cjs.js} +118 -2
  22. package/dist/{machineSchemas-88d01821.cjs.js → legacySnapshot-a85dfbe2.cjs.js} +117 -1
  23. package/dist/{machineSchemas-45c21bc2.esm.js → legacySnapshot-fffe81a0.esm.js} +116 -2
  24. package/dist/xstate-actors.cjs.js +30 -5
  25. package/dist/xstate-actors.development.cjs.js +30 -5
  26. package/dist/xstate-actors.development.esm.js +31 -6
  27. package/dist/xstate-actors.esm.js +31 -6
  28. package/dist/xstate-actors.umd.min.js +1 -1
  29. package/dist/xstate-actors.umd.min.js.map +1 -1
  30. package/dist/xstate-durable.cjs.js +120 -10
  31. package/dist/xstate-durable.development.cjs.js +120 -10
  32. package/dist/xstate-durable.development.esm.js +120 -10
  33. package/dist/xstate-durable.esm.js +120 -10
  34. package/dist/xstate-durable.umd.min.js +1 -1
  35. package/dist/xstate-durable.umd.min.js.map +1 -1
  36. package/dist/xstate-fsm.cjs.js +61 -31
  37. package/dist/xstate-fsm.development.cjs.js +61 -31
  38. package/dist/xstate-fsm.development.esm.js +61 -31
  39. package/dist/xstate-fsm.esm.js +61 -31
  40. package/dist/xstate-fsm.umd.min.js +1 -1
  41. package/dist/xstate-fsm.umd.min.js.map +1 -1
  42. package/dist/xstate-graph.cjs.js +1 -1
  43. package/dist/xstate-graph.development.cjs.js +1 -1
  44. package/dist/xstate-graph.development.esm.js +2 -2
  45. package/dist/xstate-graph.esm.js +2 -2
  46. package/dist/xstate-graph.umd.min.js +1 -1
  47. package/dist/xstate-graph.umd.min.js.map +1 -1
  48. package/dist/xstate-persist.cjs.js +23 -12
  49. package/dist/xstate-persist.development.cjs.js +23 -12
  50. package/dist/xstate-persist.development.esm.js +17 -6
  51. package/dist/xstate-persist.esm.js +17 -6
  52. package/dist/xstate-persist.umd.min.js +1 -1
  53. package/dist/xstate-persist.umd.min.js.map +1 -1
  54. package/dist/xstate-validation.cjs.js +1 -1
  55. package/dist/xstate-validation.development.cjs.js +1 -1
  56. package/dist/xstate-validation.development.esm.js +1 -1
  57. package/dist/xstate-validation.esm.js +1 -1
  58. package/dist/xstate.cjs.js +86 -56
  59. package/dist/xstate.development.cjs.js +86 -56
  60. package/dist/xstate.development.esm.js +76 -46
  61. package/dist/xstate.esm.js +76 -46
  62. package/dist/xstate.umd.min.js +1 -1
  63. package/dist/xstate.umd.min.js.map +1 -1
  64. package/docs/actor-logic.md +1 -1
  65. package/docs/api-stability.json +335 -305
  66. package/docs/backend-workflows.md +3 -3
  67. package/docs/durable-execution.md +72 -48
  68. package/docs/errors.md +2 -2
  69. package/docs/examples.md +34 -34
  70. package/docs/faq.md +1 -1
  71. package/docs/fsm.md +54 -10
  72. package/docs/guards.md +1 -1
  73. package/docs/index.md +2 -1
  74. package/docs/inspect-actor-systems.md +20 -3
  75. package/docs/inspection.md +5 -1
  76. package/docs/invoke.md +36 -4
  77. package/docs/migrate-inspector.md +141 -0
  78. package/docs/persistence.md +16 -10
  79. package/docs/serialization.md +1 -1
  80. package/docs/setup-and-provide.md +3 -3
  81. package/docs/spawn.md +1 -1
  82. package/docs/system-transitions.md +8 -6
  83. package/docs/transitions.md +5 -1
  84. package/docs/tutorial.md +5 -5
  85. package/docs/typescript.md +9 -0
  86. package/docs/xstate-v5-to-v6.md +23 -21
  87. package/package.json +1 -1
@@ -213,11 +213,11 @@ function isRemoteActorRef(actorRef) {
213
213
  * JSON (`actor.toJSON()`): plain data carrying an address, not an actor.
214
214
  */
215
215
  function isSerializedActorRef(target) {
216
- if (typeof target !== 'object' || target === null || Array.isArray(target) || typeof target.$actor !== 'string') {
216
+ if (typeof target !== 'object' || target === null || Array.isArray(target) || typeof target['@actor'] !== 'string') {
217
217
  return false;
218
218
  }
219
219
  for (const key in target) {
220
- if (key !== '$actor' && key !== 'incarnation') {
220
+ if (key !== '@actor' && key !== 'incarnation') {
221
221
  return false;
222
222
  }
223
223
  }
@@ -233,7 +233,7 @@ function getAddressId(address) {
233
233
 
234
234
  /** @internal The error reported when no live actor has a serialized address. */
235
235
  function createMissingAddressError(target) {
236
- return new Error(target.incarnation === undefined ? `Unable to send event to actor '${target.$actor}': no live actor has that address` : `Unable to send event to actor '${target.$actor}' (incarnation '${target.incarnation}'): no live actor has that address and incarnation`);
236
+ return new Error(target.incarnation === undefined ? `Unable to send event to actor '${target['@actor']}': no live actor has that address` : `Unable to send event to actor '${target['@actor']}' (incarnation '${target.incarnation}'): no live actor has that address and incarnation`);
237
237
  }
238
238
 
239
239
  /**
@@ -242,7 +242,7 @@ function createMissingAddressError(target) {
242
242
  * without one follows whichever actor is live at the address.
243
243
  */
244
244
  function resolveSerializedActorRef(system, target) {
245
- const live = system._getByAddress?.(target.$actor);
245
+ const live = system._getByAddress?.(target['@actor']);
246
246
  return live && (target.incarnation === undefined || live.sessionId === target.incarnation) ? live : undefined;
247
247
  }
248
248
 
@@ -295,7 +295,7 @@ function createInertActorRef(options) {
295
295
  throw new Error(`Cannot serialize actor ref '${id}': it was returned by a spawn during speculative transition evaluation, which creates no actor and has no parent address.` );
296
296
  }
297
297
  return {
298
- $actor: address
298
+ '@actor': address
299
299
  };
300
300
  }
301
301
  };
@@ -381,7 +381,7 @@ function createRemoteActorRef(system, options) {
381
381
  // one actor-reference shape whether a child is co-located or remote.
382
382
  toJSON() {
383
383
  return {
384
- $actor: options.address
384
+ '@actor': options.address
385
385
  };
386
386
  }
387
387
  };
@@ -501,7 +501,7 @@ function deliverEvent(source, target, event) {
501
501
  throw error;
502
502
  }
503
503
  void system.deadLetter(source, undefined, event, 'missingTarget', {
504
- targetId: getAddressId(serialized.$actor),
504
+ targetId: getAddressId(serialized['@actor']),
505
505
  error
506
506
  });
507
507
  return;
@@ -955,6 +955,7 @@ function resolveRegisteredActorSource(actors, logic) {
955
955
  const systemLogicMetadata = Symbol('xstate.systemLogicMetadata');
956
956
 
957
957
  const subscriptions = /* #__PURE__ */new WeakMap();
958
+ const XSTATE_ATTACHED_FORWARD = 'xstate.attached.forward';
958
959
 
959
960
  /**
960
961
  * Internal factory for actor logic that attaches to another actor on start
@@ -1017,9 +1018,11 @@ id) {
1017
1018
  unsubscribe: teardown
1018
1019
  });
1019
1020
  },
1020
- transition: (state, event, {
1021
- self
1022
- }) => {
1021
+ transition: (state, event, scope) => {
1022
+ const self = scope.self;
1023
+ if (event.type === XSTATE_ATTACHED_FORWARD) {
1024
+ return [state, state.status === 'active' && self._parent ? [createSendToEffect(scope, self._parent, event.event)] : []];
1025
+ }
1023
1026
  if (event.type === XSTATE_STOP) {
1024
1027
  subscriptions.get(self)?.unsubscribe();
1025
1028
  subscriptions.delete(self);
@@ -1034,7 +1037,8 @@ id) {
1034
1037
  initialTransition,
1035
1038
  getInitialSnapshot: (actorScope, input) => initialTransition(input)[0],
1036
1039
  getPersistedSnapshot: snapshot => snapshot,
1037
- restoreSnapshot: snapshot => snapshot
1040
+ restoreSnapshot: snapshot => snapshot,
1041
+ isInternalEventType: eventType => eventType === XSTATE_ATTACHED_FORWARD
1038
1042
  };
1039
1043
  Object.defineProperty(logic, systemLogicMetadata, {
1040
1044
  value: {
@@ -1052,7 +1056,10 @@ function relayMappedToParent(self, system, getEvent) {
1052
1056
  if (self.getSnapshot().status === 'stopped' || !self._parent) {
1053
1057
  return;
1054
1058
  }
1055
- system._relay(self, self._parent, getEvent());
1059
+ system._relay(self, self, {
1060
+ type: XSTATE_ATTACHED_FORWARD,
1061
+ event: getEvent()
1062
+ });
1056
1063
  }
1057
1064
 
1058
1065
  /** @public */
@@ -2203,6 +2210,18 @@ function withSystemInspector(inspect, fn) {
2203
2210
 
2204
2211
  /** Snapshot-scoped actor identity and system view. @internal */
2205
2212
 
2213
+ // Each view's execution system and whether it forwards inspection. Views
2214
+ // never chain: they all inherit from the execution system directly.
2215
+ const snapshotSystemViews = new WeakMap();
2216
+ // Facilities owned by the execution rather than by one snapshot's view. A view
2217
+ // reads and writes them on the execution system, so timers, listeners and the
2218
+ // runtime installed through any snapshot are visible through every other.
2219
+ const executionFacilities = ['runtime', '_timerMap', '_rejectionListeners', '_inspectionObservers', '_emissionListeners'];
2220
+ // The durable execution that owns each execution system.
2221
+ /** A durable execution, as the owner of the views its transitions create. @internal */
2222
+
2223
+ const executionOwners = new WeakMap();
2224
+ let ambientExecutionOwner;
2206
2225
  const snapshotActorRefs = new WeakMap();
2207
2226
  const lazySnapshotActorRefs = new WeakMap();
2208
2227
  const emptyKeyedActors = new Map();
@@ -2262,12 +2281,22 @@ function getSnapshotChildren(snapshot) {
2262
2281
  *
2263
2282
  * @internal
2264
2283
  */
2265
- function createSnapshotSystem(baseSystem, children, baseState) {
2266
- const forwardInspection = hasAmbientInspector();
2284
+ function createSnapshotSystem(baseSystem, children, baseState, owner) {
2285
+ const baseView = snapshotSystemViews.get(baseSystem);
2286
+ const baseExecutionSystem = baseView?.executionSystem ?? baseSystem;
2287
+ // The runtime system under every view. A view runs its methods against the
2288
+ // execution system's facilities.
2289
+ const rootSystem = baseView?.rootSystem ?? baseSystem;
2290
+ const forks = owner !== undefined && executionOwners.get(baseExecutionSystem) !== owner;
2291
+ // A view an execution owns reports to that execution's inspector.
2292
+ const forwardInspection = owner ? !!owner.inspect : hasAmbientInspector() && (baseView?.forwardInspection ?? true);
2267
2293
  const registeredActors = copyRegisteredActors(baseSystem, baseState);
2268
2294
  const keyedActors = new Map(baseState?.keyedActors ?? getKeyedActors(baseSystem));
2269
2295
  const reverseKeyedActors = new WeakMap();
2270
- const system = Object.assign(Object.create(baseSystem), {
2296
+ // The view's execution system; adoption can make the view its own.
2297
+ const execution = () => snapshotSystemViews.get(system).executionSystem;
2298
+ const forwards = () => snapshotSystemViews.get(system).forwardInspection;
2299
+ const system = Object.assign(Object.create(baseExecutionSystem), {
2271
2300
  children: registeredActors,
2272
2301
  keyedActors,
2273
2302
  reverseKeyedActors,
@@ -2302,15 +2331,38 @@ function createSnapshotSystem(baseSystem, children, baseState) {
2302
2331
  },
2303
2332
  get: registryKey => keyedActors.get(registryKey),
2304
2333
  getAll: () => Object.fromEntries(keyedActors),
2305
- onEmitted: listener => baseSystem.onEmitted(listener),
2306
- _notifyEmitted: (actorRef, event) => baseSystem._notifyEmitted(actorRef, event),
2334
+ onEmitted: listener => rootSystem.onEmitted.call(execution(), listener),
2335
+ _notifyEmitted: (actorRef, event) => rootSystem._notifyEmitted.call(execution(), actorRef, event),
2307
2336
  // Pure transition resolution must not leak topology inspection events
2308
2337
  // into a live runtime system — planning branches stay silent. The one
2309
2338
  // exception is a durable execution's own transitions (marked by the
2310
2339
  // ambient inspector at creation time): there the pure path IS the
2311
- // execution, so inspection forwards to the base system's observers.
2312
- _hasInspectionObservers: forwardInspection ? () => baseSystem._hasInspectionObservers?.() ?? false : () => false,
2313
- _sendInspectionEvent: forwardInspection ? event => baseSystem._sendInspectionEvent(event) : () => {}
2340
+ // execution, so inspection forwards to the execution system's observers.
2341
+ _hasInspectionObservers: () => forwards() && (rootSystem._hasInspectionObservers?.call(execution()) ?? false),
2342
+ _sendInspectionEvent: event => {
2343
+ if (forwards()) {
2344
+ rootSystem._sendInspectionEvent.call(execution(), event);
2345
+ }
2346
+ }
2347
+ });
2348
+ const executionSystem = forks ? system : baseExecutionSystem;
2349
+ if (forks) {
2350
+ forkFacilities(system, baseExecutionSystem, owner);
2351
+ } else {
2352
+ for (const key of executionFacilities) {
2353
+ Object.defineProperty(system, key, {
2354
+ configurable: true,
2355
+ get: () => execution()[key],
2356
+ set: value => {
2357
+ execution()[key] = value;
2358
+ }
2359
+ });
2360
+ }
2361
+ }
2362
+ snapshotSystemViews.set(system, {
2363
+ executionSystem,
2364
+ rootSystem,
2365
+ forwardInspection
2314
2366
  });
2315
2367
  for (const [registryKey, actor] of keyedActors) {
2316
2368
  if (!actor) {
@@ -2334,6 +2386,83 @@ function createSnapshotSystem(baseSystem, children, baseState) {
2334
2386
  return system;
2335
2387
  }
2336
2388
 
2389
+ /**
2390
+ * Makes `system` the execution system of `owner`, a new incarnation: it gets
2391
+ * the owner's runtime and the pending timers it saw, and starts with no
2392
+ * listeners or inspectors, so nothing registered on another execution
2393
+ * observes it.
2394
+ */
2395
+ function forkFacilities(system, from, owner) {
2396
+ const timers = from._timerMap;
2397
+ for (const key of executionFacilities) {
2398
+ Object.defineProperty(system, key, {
2399
+ configurable: true,
2400
+ writable: true,
2401
+ value: key === 'runtime' ? owner.runtime : key === '_timerMap' && timers ? {
2402
+ ...timers
2403
+ } : undefined
2404
+ });
2405
+ }
2406
+ executionOwners.set(system, owner);
2407
+ if (owner.inspect) {
2408
+ system.inspect(owner.inspect);
2409
+ }
2410
+ }
2411
+
2412
+ /**
2413
+ * Makes `owner` own `system` before it installs its runtime there, and
2414
+ * returns whether it does. An unowned view forks in place, so the install
2415
+ * never reaches the system it was derived from. A system another execution
2416
+ * owns is left alone.
2417
+ *
2418
+ * @internal
2419
+ */
2420
+ function adoptSystem(system, owner) {
2421
+ const view = snapshotSystemViews.get(system);
2422
+ const current = executionOwners.get(view?.executionSystem ?? system);
2423
+ if (current === owner) {
2424
+ if (view) {
2425
+ view.forwardInspection = !!owner.inspect;
2426
+ }
2427
+ return true;
2428
+ }
2429
+ // A system another execution owns stays with it.
2430
+ if (current) {
2431
+ return false;
2432
+ }
2433
+ if (!view) {
2434
+ executionOwners.set(system, owner);
2435
+ return true;
2436
+ }
2437
+ forkFacilities(system, view.executionSystem, owner);
2438
+ view.executionSystem = system;
2439
+ view.forwardInspection = !!owner.inspect;
2440
+ return true;
2441
+ }
2442
+
2443
+ /**
2444
+ * Runs `fn` as a transition of `owner`. A view it derives from a system the
2445
+ * owner does not own forks into the owner's own execution system.
2446
+ *
2447
+ * @internal
2448
+ */
2449
+ function withExecutionOwner(owner, fn) {
2450
+ const previous = ambientExecutionOwner;
2451
+ ambientExecutionOwner = owner;
2452
+ try {
2453
+ return fn();
2454
+ } finally {
2455
+ ambientExecutionOwner = previous;
2456
+ }
2457
+ }
2458
+
2459
+ /** Hands the ambient owner to the first scope that asks for it. @internal */
2460
+ function takeExecutionOwner() {
2461
+ const owner = ambientExecutionOwner;
2462
+ ambientExecutionOwner = undefined;
2463
+ return owner;
2464
+ }
2465
+
2337
2466
  /** Returns the actor identity associated with a transition snapshot. @internal */
2338
2467
  function getSnapshotActorRef(snapshot) {
2339
2468
  const existing = snapshotActorRefs.get(snapshot);
@@ -2527,8 +2656,9 @@ function setInertActorScopeSnapshot(actorScope, snapshot, attachActorRef = true)
2527
2656
  const lazyState = getLazyInertActorState(actorScope);
2528
2657
  if (lazyState) {
2529
2658
  lazyState.snapshot = snapshot;
2530
- if (lazyState.materialized) {
2531
- lazyState.materialized.self._snapshot = snapshot;
2659
+ const scope = lazyState.materialized ?? lazyState.identityScope;
2660
+ if (scope) {
2661
+ scope.self._snapshot = snapshot;
2532
2662
  }
2533
2663
  } else {
2534
2664
  actorScope.self._snapshot = snapshot;
@@ -2563,6 +2693,15 @@ function attachSnapshotActorRef(actorScope, snapshot) {
2563
2693
  setLazySnapshotActorRef(snapshot, create);
2564
2694
  return snapshot;
2565
2695
  }
2696
+ /** Records the materialized scope and releases its consumed source. */
2697
+ function commitMaterialization(state, scope) {
2698
+ // Dropping the consumed source keeps this scope from retaining earlier snapshots.
2699
+ state.sourceRef = undefined;
2700
+ state.sourceChildren = {};
2701
+ state.materialized = scope;
2702
+ state.materialize = () => scope;
2703
+ return scope;
2704
+ }
2566
2705
  const lazyInertActorState = Symbol();
2567
2706
  const snapshotActorScopes = new WeakMap();
2568
2707
  let inertActorMaterializationObserver;
@@ -2607,12 +2746,14 @@ const lazyInertActorScopePrototype = {
2607
2746
  return materializeInertActorScope(this).actionExecutor;
2608
2747
  }
2609
2748
  };
2610
- function createMaterializedInertActorScope(actorLogic, sourceRef, sourceChildren, currentSnapshot, sourceSelf) {
2749
+
2750
+ /** Creates a transactional planning scope backed by an inert actor. */
2751
+ function createMaterializedInertActorScope(actorLogic, sourceRef, sourceChildren, currentSnapshot, sourceSelf, owner) {
2611
2752
  inertActorMaterializationObserver?.();
2612
2753
  const snapshotRef = sourceRef?.();
2613
2754
  const previousSelf = sourceSelf ?? snapshotRef?.actor;
2614
2755
  const baseSystem = previousSelf?.system;
2615
- const system = previousSelf && baseSystem ? createSnapshotSystem(baseSystem, sourceChildren, sourceSelf ? undefined : snapshotRef?.systemState) : undefined;
2756
+ const system = previousSelf && baseSystem ? createSnapshotSystem(baseSystem, sourceChildren, sourceSelf ? undefined : snapshotRef?.systemState, owner) : undefined;
2616
2757
  const self = createActor(actorLogic, {
2617
2758
  _inert: true,
2618
2759
  ...(previousSelf ? {
@@ -2632,12 +2773,8 @@ function createMaterializedInertActorScope(actorLogic, sourceRef, sourceChildren
2632
2773
  // a future construction-time read cannot pin a root-shaped address.
2633
2774
  self._address = undefined;
2634
2775
  }
2635
- if (currentSnapshot) {
2636
- self._snapshot = currentSnapshot;
2637
- }
2638
-
2639
2776
  // Reuse the branch actor's scope while keeping planning transactional.
2640
- return Object.create(self._actorScope, {
2777
+ const scope = Object.create(self._actorScope, {
2641
2778
  defer: {
2642
2779
  value: () => {}
2643
2780
  },
@@ -2646,8 +2783,20 @@ function createMaterializedInertActorScope(actorLogic, sourceRef, sourceChildren
2646
2783
  },
2647
2784
  actionExecutor: {
2648
2785
  value: () => {}
2786
+ },
2787
+ _snapshot: {
2788
+ enumerable: true,
2789
+ configurable: true,
2790
+ get: () => self._snapshot,
2791
+ set: snapshot => {
2792
+ self._snapshot = snapshot;
2793
+ }
2649
2794
  }
2650
2795
  });
2796
+ if (currentSnapshot) {
2797
+ scope._snapshot = currentSnapshot;
2798
+ }
2799
+ return scope;
2651
2800
  }
2652
2801
 
2653
2802
  /** @internal */
@@ -2662,22 +2811,34 @@ function createInertActorScope(actorLogic, snapshot, sourceSelf, sourceActorScop
2662
2811
  sourceChildren: isMachineSnapshot(snapshot) ? snapshot.children : {},
2663
2812
  identityProvider: sourceState?.identityProvider ?? sourceRef,
2664
2813
  parent: sourceSelf?._parent ?? sourceState?.parent ?? eagerSourceRef?.actor._parent,
2814
+ // Only the outermost scope of an owned transition belongs to the owner;
2815
+ // scopes for its intermediate snapshots inherit it, and nested pure
2816
+ // transitions run unowned.
2817
+ owner: sourceActorScope ? sourceState?.owner : takeExecutionOwner(),
2665
2818
  parentKnown: !!sourceSelf || !!sourceState?.parentKnown || !!eagerSourceRef || !snapshot
2666
2819
  };
2667
- state.materialize = () => state.materialized ??= createMaterializedInertActorScope(actorLogic, state.sourceRef, state.sourceChildren, state.snapshot, sourceSelf);
2820
+ state.materialize = () => {
2821
+ const scope = createMaterializedInertActorScope(actorLogic, state.sourceRef, state.sourceChildren, state.snapshot, sourceSelf, state.owner);
2822
+ return commitMaterialization(state, scope);
2823
+ };
2668
2824
  if (!state.identityProvider && !snapshot) {
2669
2825
  const identitySnapshot = {};
2670
- const identitySourceRef = state.sourceRef;
2671
- const identitySourceChildren = state.sourceChildren;
2672
- let identityScope;
2673
2826
  let identityRef;
2674
- const getIdentityScope = () => identityScope ??= createMaterializedInertActorScope(actorLogic, identitySourceRef, identitySourceChildren, undefined, sourceSelf);
2827
+ const getIdentityScope = () => {
2828
+ if (!state.identityScope) {
2829
+ state.identityScope = createMaterializedInertActorScope(actorLogic, state.sourceRef, state.sourceChildren, undefined, sourceSelf, state.owner);
2830
+ if (state.snapshot !== undefined) {
2831
+ state.identityScope.self._snapshot = state.snapshot;
2832
+ }
2833
+ }
2834
+ return state.identityScope;
2835
+ };
2675
2836
  state.materialize = () => {
2676
2837
  const scope = getIdentityScope();
2677
2838
  if (state.snapshot !== undefined) {
2678
2839
  scope.self._snapshot = state.snapshot;
2679
2840
  }
2680
- return state.materialized = scope;
2841
+ return commitMaterialization(state, scope);
2681
2842
  };
2682
2843
  state.identityProvider = () => {
2683
2844
  if (identityRef) {
@@ -3815,7 +3976,7 @@ function microstep(transitions, currentSnapshot, actorScope, event, isInitial, i
3815
3976
  }
3816
3977
  addAncestorStatesToEnter(ancestors, !transition.source.parent && reenter ? undefined : domain);
3817
3978
  }
3818
- if (reenter && domain === transition.source) {
3979
+ if (targets?.length && reenter && domain === transition.source) {
3819
3980
  // A reentering transition whose domain is its own source exits and
3820
3981
  // reenters the source, so the source must be entered explicitly —
3821
3982
  // it has no ancestor inside the domain to add it.
@@ -4373,7 +4534,9 @@ function macrostep(snapshot, event, actorScope, internalQueue, initialMicrosteps
4373
4534
  if (!internalQueue.length && snapshot.machine._hasEventlessTransitions === false) {
4374
4535
  return completeMacrostep();
4375
4536
  }
4376
- let shouldSelectEventlessTransitions = true;
4537
+
4538
+ // A timer notification must not run eventless transitions before delivery.
4539
+ let shouldSelectEventlessTransitions = event.type !== XSTATE_TIMER;
4377
4540
  const maxIterations = snapshot.machine.options?.maxIterations ?? Infinity;
4378
4541
  let iterationCount = 0;
4379
4542
  // The last few state values visited, for the infinite-loop error.
@@ -4661,7 +4824,7 @@ function findNonJsonPath(value, path) {
4661
4824
  };
4662
4825
  }
4663
4826
  if ('sessionId' in current && 'send' in current && 'ref' in current) {
4664
- // Actor refs persist as `{ $actor: address }`.
4827
+ // Actor refs persist as `{ "@actor": address }`.
4665
4828
  return undefined;
4666
4829
  }
4667
4830
  if (ancestors.has(current)) {
@@ -4784,6 +4947,8 @@ const machineSnapshotToJSON = function toJSON() {
4784
4947
  const {
4785
4948
  nodes,
4786
4949
  _stateInputs,
4950
+ _nextTimerId,
4951
+ _nextActorIds,
4787
4952
  tags,
4788
4953
  machine,
4789
4954
  getMeta,
@@ -4908,6 +5073,8 @@ function getPersistedSnapshot(snapshot, options) {
4908
5073
  const {
4909
5074
  nodes,
4910
5075
  _stateInputs,
5076
+ _nextTimerId,
5077
+ _nextActorIds,
4911
5078
  tags,
4912
5079
  machine,
4913
5080
  children,
@@ -5043,6 +5210,11 @@ function getPersistedSnapshot(snapshot, options) {
5043
5210
  if (_stateInputs && Object.keys(_stateInputs).length > 0) {
5044
5211
  persisted.stateInputs = _stateInputs;
5045
5212
  }
5213
+ // Stores such as Convex reject `_`-prefixed field names.
5214
+ persisted.nextTimerId = _nextTimerId;
5215
+ if (_nextActorIds && Object.keys(_nextActorIds).length > 0) {
5216
+ persisted.nextActorIds = _nextActorIds;
5217
+ }
5046
5218
  if (machine.version !== undefined) {
5047
5219
  persisted.machine = {
5048
5220
  id: machine.id,
@@ -5074,7 +5246,7 @@ function persistContext(contextPart, getActorId, path = 'context', ancestors = [
5074
5246
  };
5075
5247
  // The address lets refs to non-children still route after restore.
5076
5248
  copy[key] = {
5077
- $actor: value.address
5249
+ '@actor': value.address
5078
5250
  };
5079
5251
  } else {
5080
5252
  const valuePath = Array.isArray(contextPart) ? `${path}[${key}]` : `${path}.${key}`;
@@ -5716,11 +5888,18 @@ class RuntimeSystem {
5716
5888
  // Records a send on the *sender's* transition for the `sent[]` inspection
5717
5889
  // facet. Captures the send when it is initiated (including delayed sends that
5718
5890
  // may never deliver), keyed to the source actor's in-flight transition.
5891
+ // A send made with no transition in flight (a callback's `sendBack`, a value
5892
+ // an observable relays to its parent) is not recorded: no transition reports
5893
+ // it, so it would be held until the source's next transition, or for as long
5894
+ // as the source lives if it never makes one.
5719
5895
  _recordSent(source, target, event, delay, id) {
5720
5896
  if (!this._inspectionObservers?.size || !source) {
5721
5897
  return;
5722
5898
  }
5723
5899
  const inspectionSource = source;
5900
+ if (!inspectionSource._inTransition) {
5901
+ return;
5902
+ }
5724
5903
  const collected = inspectionSource._collectedSent ??= [];
5725
5904
  collected.push({
5726
5905
  targetRef: target,
@@ -5957,9 +6136,9 @@ class RuntimeSystem {
5957
6136
  } else if (
5958
6137
  // A live actor of another incarnation is stale locally; an
5959
6138
  // address this system cannot see may belong to a host runtime.
5960
- this._getByAddress(target.$actor) || !this.runtime?.sendEvent) {
6139
+ this._getByAddress(target['@actor']) || !this.runtime?.sendEvent) {
5961
6140
  return this.deadLetter(source, undefined, event, 'missingTarget', {
5962
- targetId: getAddressId(target.$actor),
6141
+ targetId: getAddressId(target['@actor']),
5963
6142
  error: createMissingAddressError(target)
5964
6143
  });
5965
6144
  }
@@ -6246,6 +6425,12 @@ class Actor {
6246
6425
  this._collectedActions = void 0;
6247
6426
  /** @internal Events relayed to other actors during the in-flight transition. */
6248
6427
  this._collectedSent = void 0;
6428
+ /**
6429
+ * @internal Whether a transition is in flight: while the actor starts,
6430
+ * processes an event, or recovers from an execution error. Sends are recorded
6431
+ * for `sent[]` only then.
6432
+ */
6433
+ this._inTransition = false;
6249
6434
  this._initialEffects = void 0;
6250
6435
  this.registryKey = void 0;
6251
6436
  /** The globally unique process ID for this invocation. */
@@ -6318,9 +6503,14 @@ class Actor {
6318
6503
  // transition functions; computing an initial snapshot here would run
6319
6504
  // init-time side effects (context factories, entry) a second time.
6320
6505
  } else {
6321
- const [snapshot, effects] = finalizeTransitionResult(this._actorScope, undefined, this.logic.initialTransition(this.options?.input, this._actorScope));
6322
- this._setSnapshot(snapshot);
6323
- this._initialEffects = effects.length ? effects : undefined;
6506
+ this._inTransition = true;
6507
+ try {
6508
+ const [snapshot, effects] = finalizeTransitionResult(this._actorScope, undefined, this.logic.initialTransition(this.options?.input, this._actorScope));
6509
+ this._setSnapshot(snapshot);
6510
+ this._initialEffects = effects.length ? effects : undefined;
6511
+ } finally {
6512
+ this._inTransition = false;
6513
+ }
6324
6514
  }
6325
6515
  } catch (err) {
6326
6516
  // Restored logic may keep its snapshot shape on restore failures (e.g.
@@ -6473,6 +6663,8 @@ class Actor {
6473
6663
  if (!errorEvent) {
6474
6664
  return false;
6475
6665
  }
6666
+ const inTransition = this._inTransition;
6667
+ this._inTransition = true;
6476
6668
  try {
6477
6669
  const [nextSnapshot, effects] = finalizeTransitionResult(this._actorScope, snapshot, this.logic.transition(snapshot, errorEvent, this._actorScope));
6478
6670
  this._setSnapshot(nextSnapshot);
@@ -6481,6 +6673,8 @@ class Actor {
6481
6673
  return true;
6482
6674
  } catch {
6483
6675
  return false;
6676
+ } finally {
6677
+ this._inTransition = inTransition;
6484
6678
  }
6485
6679
  }
6486
6680
  _next(snapshot) {
@@ -6692,6 +6886,15 @@ class Actor {
6692
6886
 
6693
6887
  /** Starts the Actor from the initial state */
6694
6888
  start() {
6889
+ const inTransition = this._inTransition;
6890
+ this._inTransition = true;
6891
+ try {
6892
+ return this._start();
6893
+ } finally {
6894
+ this._inTransition = inTransition;
6895
+ }
6896
+ }
6897
+ _start() {
6695
6898
  if (this._processingStatus === ProcessingStatus.Running) {
6696
6899
  // Do not restart the service if it is already started
6697
6900
  return this;
@@ -6807,7 +7010,16 @@ class Actor {
6807
7010
  this.mailbox?.start();
6808
7011
  return this;
6809
7012
  }
6810
- _process({
7013
+ _process(item) {
7014
+ const inTransition = this._inTransition;
7015
+ this._inTransition = true;
7016
+ try {
7017
+ this._processEvent(item);
7018
+ } finally {
7019
+ this._inTransition = inTransition;
7020
+ }
7021
+ }
7022
+ _processEvent({
6811
7023
  event,
6812
7024
  sourceRef
6813
7025
  }) {
@@ -7055,12 +7267,12 @@ class Actor {
7055
7267
  }
7056
7268
 
7057
7269
  /**
7058
- * Returns the actor's serializable logical identity: `{ $actor: address }`.
7270
+ * Returns the actor's serializable logical identity: `{ "@actor": address }`.
7059
7271
  * The result can be used as an `enq.sendTo(...)` target.
7060
7272
  */
7061
7273
  toJSON() {
7062
7274
  return {
7063
- $actor: this.address
7275
+ '@actor': this.address
7064
7276
  };
7065
7277
  }
7066
7278
 
@@ -7180,6 +7392,7 @@ exports.NULL_EVENT = NULL_EVENT;
7180
7392
  exports.ProcessingStatus = ProcessingStatus;
7181
7393
  exports.RUNTIME_OPERATIONS = RUNTIME_OPERATIONS;
7182
7394
  exports.STATE_DELIMITER = STATE_DELIMITER;
7395
+ exports.XSTATE_ATTACHED_FORWARD = XSTATE_ATTACHED_FORWARD;
7183
7396
  exports.XSTATE_INIT = XSTATE_INIT;
7184
7397
  exports.XSTATE_LOGIC_EFFECT_REJECT = XSTATE_LOGIC_EFFECT_REJECT;
7185
7398
  exports.XSTATE_LOGIC_EFFECT_RESOLVE = XSTATE_LOGIC_EFFECT_RESOLVE;
@@ -7187,6 +7400,7 @@ exports.XSTATE_LOGIC_EFFECT_START = XSTATE_LOGIC_EFFECT_START;
7187
7400
  exports.XSTATE_STOP = XSTATE_STOP;
7188
7401
  exports.XSTATE_STOP_EFFECT = XSTATE_STOP_EFFECT;
7189
7402
  exports.XSTATE_TIMER = XSTATE_TIMER;
7403
+ exports.adoptSystem = adoptSystem;
7190
7404
  exports.allocateChildId = allocateChildId;
7191
7405
  exports.assertChildIdFree = assertChildIdFree;
7192
7406
  exports.assertUnreservedSourceName = assertUnreservedSourceName;
@@ -7286,4 +7500,5 @@ exports.toTransitionConfigArray = toTransitionConfigArray;
7286
7500
  exports.transitionNode = transitionNode;
7287
7501
  exports.withActorSelf = withActorSelf;
7288
7502
  exports.withExecutionIdentity = withExecutionIdentity;
7503
+ exports.withExecutionOwner = withExecutionOwner;
7289
7504
  exports.withSystemInspector = withSystemInspector;
@@ -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;