xstate 6.0.0-alpha.41 → 6.0.0-alpha.44

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 (56) hide show
  1. package/dist/{StateMachine-db4e6d4b.development.cjs.js → StateMachine-16d7ee93.development.cjs.js} +22 -5
  2. package/dist/{StateMachine-f60abe05.development.esm.js → StateMachine-1ea29688.development.esm.js} +22 -5
  3. package/dist/{StateMachine-ee89d49f.esm.js → StateMachine-b13b4b09.esm.js} +22 -5
  4. package/dist/{StateMachine-8e73d782.cjs.js → StateMachine-fcc48e11.cjs.js} +22 -5
  5. package/dist/{createActor-20615484.development.cjs.js → createActor-1a3a1d14.development.cjs.js} +175 -136
  6. package/dist/{createActor-f3afd774.cjs.js → createActor-9538c7f8.cjs.js} +175 -136
  7. package/dist/{createActor-a3f7750f.esm.js → createActor-973c72ad.esm.js} +174 -137
  8. package/dist/{createActor-c97c04c9.development.esm.js → createActor-f9cc6590.development.esm.js} +174 -137
  9. package/dist/declarations/src/StateMachine.d.ts +3 -3
  10. package/dist/declarations/src/createMachine.d.ts +7 -7
  11. package/dist/declarations/src/durable/index.d.ts +10 -0
  12. package/dist/declarations/src/runtimeHelpers.d.ts +5 -0
  13. package/dist/declarations/src/schema.types.d.ts +2 -0
  14. package/dist/declarations/src/setup.d.ts +33 -14
  15. package/dist/declarations/src/system.d.ts +25 -0
  16. package/dist/declarations/src/types.d.ts +10 -8
  17. package/dist/declarations/src/types.v6.d.ts +14 -9
  18. package/dist/{effectDescriptor-57ae11fa.esm.js → effectDescriptor-416ca00a.esm.js} +2 -2
  19. package/dist/{effectDescriptor-e2bb61e2.cjs.js → effectDescriptor-7d6f945a.development.cjs.js} +2 -2
  20. package/dist/{effectDescriptor-b7c48ceb.development.esm.js → effectDescriptor-e6730c9a.development.esm.js} +2 -2
  21. package/dist/{effectDescriptor-ba9e14f0.development.cjs.js → effectDescriptor-f8c9337f.cjs.js} +2 -2
  22. package/dist/{index-a8ce72f1.esm.js → index-b478f443.esm.js} +7 -2
  23. package/dist/{index-7fd92683.cjs.js → index-ba7170ba.cjs.js} +7 -2
  24. package/dist/{index-d42efc07.development.cjs.js → index-e0ba4813.development.cjs.js} +7 -2
  25. package/dist/{index-b5b1b2bc.development.esm.js → index-f284cc7b.development.esm.js} +7 -2
  26. package/dist/xstate-actors.cjs.js +2 -2
  27. package/dist/xstate-actors.development.cjs.js +2 -2
  28. package/dist/xstate-actors.development.esm.js +2 -2
  29. package/dist/xstate-actors.esm.js +2 -2
  30. package/dist/xstate-actors.umd.min.js +1 -1
  31. package/dist/xstate-actors.umd.min.js.map +1 -1
  32. package/dist/xstate-durable.cjs.js +15 -5
  33. package/dist/xstate-durable.development.cjs.js +15 -5
  34. package/dist/xstate-durable.development.esm.js +15 -5
  35. package/dist/xstate-durable.esm.js +15 -5
  36. package/dist/xstate-durable.umd.min.js +1 -1
  37. package/dist/xstate-durable.umd.min.js.map +1 -1
  38. package/dist/xstate-graph.cjs.js +3 -3
  39. package/dist/xstate-graph.development.cjs.js +3 -3
  40. package/dist/xstate-graph.development.esm.js +3 -3
  41. package/dist/xstate-graph.esm.js +3 -3
  42. package/dist/xstate-graph.umd.min.js +1 -1
  43. package/dist/xstate-graph.umd.min.js.map +1 -1
  44. package/dist/xstate-validation.cjs.js +20 -2
  45. package/dist/xstate-validation.development.cjs.js +20 -2
  46. package/dist/xstate-validation.development.esm.js +20 -2
  47. package/dist/xstate-validation.esm.js +20 -2
  48. package/dist/xstate-validation.umd.min.js +1 -1
  49. package/dist/xstate-validation.umd.min.js.map +1 -1
  50. package/dist/xstate.cjs.js +8 -5
  51. package/dist/xstate.development.cjs.js +8 -5
  52. package/dist/xstate.development.esm.js +10 -7
  53. package/dist/xstate.esm.js +10 -7
  54. package/dist/xstate.umd.min.js +1 -1
  55. package/dist/xstate.umd.min.js.map +1 -1
  56. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var createActor = require('./createActor-20615484.development.cjs.js');
4
- var dist_xstateActors = require('./index-d42efc07.development.cjs.js');
3
+ var createActor = require('./createActor-1a3a1d14.development.cjs.js');
4
+ var dist_xstateActors = require('./index-e0ba4813.development.cjs.js');
5
5
 
6
6
  function createSpawner(actorScope, actors, spawnedChildren) {
7
7
  return (src, options) => {
@@ -418,6 +418,16 @@ function formatInitialTransition(stateNode, _target) {
418
418
  }
419
419
 
420
420
  const STATE_IDENTIFIER = '#';
421
+ function findEventSchema(schemas, eventType) {
422
+ if (!schemas) {
423
+ return undefined;
424
+ }
425
+ if (Object.hasOwn(schemas, eventType)) {
426
+ return schemas[eventType];
427
+ }
428
+ const descriptor = Object.keys(schemas).find(key => createActor.matchesEventDescriptor(eventType, key));
429
+ return descriptor === undefined ? undefined : schemas[descriptor];
430
+ }
421
431
  let emptyCanActor;
422
432
  let emptyCanActorScope;
423
433
  function getEmptyCanActor() {
@@ -462,6 +472,12 @@ class StateMachine {
462
472
  config, sources, validator) {
463
473
  this.config = config;
464
474
  this.validator = validator;
475
+ /**
476
+ * @internal Type-only marker for the actor's internal event protocol. Not
477
+ * `declare` (the build's babel pipeline rejects declare class fields); the
478
+ * one `undefined` property this emits per machine instance is inert.
479
+ */
480
+ this._internalEventType = void 0;
465
481
  /** The machine's own version. */
466
482
  this.version = void 0;
467
483
  this.schemas = void 0;
@@ -600,9 +616,10 @@ class StateMachine {
600
616
  }
601
617
  const event = value;
602
618
  const eventSchemas = this.schemas?.events;
619
+ const internalEventSchemas = this.schemas?.internalEvents;
603
620
  const isFrameworkEvent = event.type.startsWith('xstate.') || event.type.startsWith('@xstate.');
604
- const schema = eventSchemas && Object.hasOwn(eventSchemas, event.type) ? eventSchemas[event.type] : undefined;
605
- if (eventSchemas && !schema && !isFrameworkEvent) {
621
+ const schema = findEventSchema(internalEventSchemas, event.type) ?? findEventSchema(eventSchemas, event.type);
622
+ if ((eventSchemas || internalEventSchemas) && !schema && !isFrameworkEvent) {
606
623
  return {
607
624
  issues: [{
608
625
  message: `Unknown event '${event.type}' for machine '${this.id}' version '${this.version}'.`
@@ -638,7 +655,7 @@ class StateMachine {
638
655
  }
639
656
  }
640
657
  };
641
- this.internalEventDescriptors = this.config.internalEvents ?? [];
658
+ this.internalEventDescriptors = [...Object.keys(this.schemas?.internalEvents ?? {}), ...(this.config.internalEvents ?? [])];
642
659
  this.options = {
643
660
  maxIterations: Infinity,
644
661
  ...this.config.options
@@ -1,5 +1,5 @@
1
- import { Q as allocateChildId, R as assertChildIdFree, S as reserveChildId, T as STATE_DELIMITER, U as mapValues, t as toArray, V as createInvokeId, W as getDelayedTransitions, Y as getEventDescriptorKey, Z as getCandidates, _ as evaluateCandidate, $ as formatTransition, a0 as NULL_EVENT, a1 as toTransitionConfigArray, a2 as createInvokeTimeoutEventId, a3 as matchesActorSession, a4 as formatRouteTransitions, a5 as resolveStateValue, a6 as getAllStateNodes, x as getStateNodes, a7 as createMachineSnapshot, a8 as isInFinalState, a9 as createInertActorScope, aa as setInertActorScopeSnapshot, a as beginSpawnAllocation, ab as attachSnapshotActorRef, ac as macrostep, ad as isInertActorScope, ae as setSnapshotActorRef, af as cloneMachineSnapshot, ag as transitionNode, g as XSTATE_TIMER, m as matchesEventDescriptor, ah as getTransitionResult, ai as hasEffect, aj as createErrorPlatformEvent, ak as withActorSelf, r as resolveActionsWithContext, al as takeSpawnAllocationCounters, am as mergeActorIdCounters, K as createInitEvent, an as createSpawnEffect, ao as initialMicrostep, ap as toStatePath, aq as isStateId, ar as getStateNodeByPath, as as getPersistedSnapshot, at as createRemoteActorRef, au as resolveReferencedActor, av as createInvokeTimeoutEvent, aw as parseGeneratedActorId, ax as ACTOR_REF_TYPE, k as createActor } from './createActor-c97c04c9.development.esm.js';
2
- import { g as assertValid } from './index-b5b1b2bc.development.esm.js';
1
+ import { Q as allocateChildId, R as assertChildIdFree, S as reserveChildId, T as STATE_DELIMITER, U as mapValues, t as toArray, V as createInvokeId, W as getDelayedTransitions, Y as getEventDescriptorKey, Z as getCandidates, _ as evaluateCandidate, $ as formatTransition, a0 as NULL_EVENT, a1 as toTransitionConfigArray, a2 as createInvokeTimeoutEventId, a3 as matchesActorSession, a4 as formatRouteTransitions, a5 as resolveStateValue, a6 as getAllStateNodes, x as getStateNodes, a7 as createMachineSnapshot, a8 as isInFinalState, a9 as createInertActorScope, aa as setInertActorScopeSnapshot, a as beginSpawnAllocation, ab as attachSnapshotActorRef, ac as macrostep, ad as isInertActorScope, ae as setSnapshotActorRef, af as cloneMachineSnapshot, ag as transitionNode, g as XSTATE_TIMER, m as matchesEventDescriptor, ah as getTransitionResult, ai as hasEffect, aj as createErrorPlatformEvent, ak as withActorSelf, r as resolveActionsWithContext, al as takeSpawnAllocationCounters, am as mergeActorIdCounters, K as createInitEvent, an as createSpawnEffect, ao as initialMicrostep, ap as toStatePath, aq as isStateId, ar as getStateNodeByPath, as as getPersistedSnapshot, at as createRemoteActorRef, au as resolveReferencedActor, av as createInvokeTimeoutEvent, aw as parseGeneratedActorId, ax as ACTOR_REF_TYPE, k as createActor } from './createActor-f9cc6590.development.esm.js';
2
+ import { g as assertValid } from './index-f284cc7b.development.esm.js';
3
3
 
4
4
  function createSpawner(actorScope, actors, spawnedChildren) {
5
5
  return (src, options) => {
@@ -416,6 +416,16 @@ function formatInitialTransition(stateNode, _target) {
416
416
  }
417
417
 
418
418
  const STATE_IDENTIFIER = '#';
419
+ function findEventSchema(schemas, eventType) {
420
+ if (!schemas) {
421
+ return undefined;
422
+ }
423
+ if (Object.hasOwn(schemas, eventType)) {
424
+ return schemas[eventType];
425
+ }
426
+ const descriptor = Object.keys(schemas).find(key => matchesEventDescriptor(eventType, key));
427
+ return descriptor === undefined ? undefined : schemas[descriptor];
428
+ }
419
429
  let emptyCanActor;
420
430
  let emptyCanActorScope;
421
431
  function getEmptyCanActor() {
@@ -460,6 +470,12 @@ class StateMachine {
460
470
  config, sources, validator) {
461
471
  this.config = config;
462
472
  this.validator = validator;
473
+ /**
474
+ * @internal Type-only marker for the actor's internal event protocol. Not
475
+ * `declare` (the build's babel pipeline rejects declare class fields); the
476
+ * one `undefined` property this emits per machine instance is inert.
477
+ */
478
+ this._internalEventType = void 0;
463
479
  /** The machine's own version. */
464
480
  this.version = void 0;
465
481
  this.schemas = void 0;
@@ -598,9 +614,10 @@ class StateMachine {
598
614
  }
599
615
  const event = value;
600
616
  const eventSchemas = this.schemas?.events;
617
+ const internalEventSchemas = this.schemas?.internalEvents;
601
618
  const isFrameworkEvent = event.type.startsWith('xstate.') || event.type.startsWith('@xstate.');
602
- const schema = eventSchemas && Object.hasOwn(eventSchemas, event.type) ? eventSchemas[event.type] : undefined;
603
- if (eventSchemas && !schema && !isFrameworkEvent) {
619
+ const schema = findEventSchema(internalEventSchemas, event.type) ?? findEventSchema(eventSchemas, event.type);
620
+ if ((eventSchemas || internalEventSchemas) && !schema && !isFrameworkEvent) {
604
621
  return {
605
622
  issues: [{
606
623
  message: `Unknown event '${event.type}' for machine '${this.id}' version '${this.version}'.`
@@ -636,7 +653,7 @@ class StateMachine {
636
653
  }
637
654
  }
638
655
  };
639
- this.internalEventDescriptors = this.config.internalEvents ?? [];
656
+ this.internalEventDescriptors = [...Object.keys(this.schemas?.internalEvents ?? {}), ...(this.config.internalEvents ?? [])];
640
657
  this.options = {
641
658
  maxIterations: Infinity,
642
659
  ...this.config.options
@@ -1,5 +1,5 @@
1
- import { Q as allocateChildId, R as assertChildIdFree, S as reserveChildId, T as STATE_DELIMITER, U as mapValues, t as toArray, V as createInvokeId, W as getDelayedTransitions, Y as getEventDescriptorKey, Z as getCandidates, _ as evaluateCandidate, $ as formatTransition, a0 as NULL_EVENT, a1 as toTransitionConfigArray, a2 as createInvokeTimeoutEventId, a3 as matchesActorSession, a4 as formatRouteTransitions, a5 as resolveStateValue, a6 as getAllStateNodes, x as getStateNodes, a7 as createMachineSnapshot, a8 as isInFinalState, a9 as createInertActorScope, aa as setInertActorScopeSnapshot, a as beginSpawnAllocation, ab as attachSnapshotActorRef, ac as macrostep, ad as isInertActorScope, ae as setSnapshotActorRef, af as cloneMachineSnapshot, ag as transitionNode, g as XSTATE_TIMER, m as matchesEventDescriptor, ah as getTransitionResult, ai as hasEffect, aj as createErrorPlatformEvent, ak as withActorSelf, r as resolveActionsWithContext, al as takeSpawnAllocationCounters, am as mergeActorIdCounters, K as createInitEvent, an as createSpawnEffect, ao as initialMicrostep, ap as toStatePath, aq as isStateId, ar as getStateNodeByPath, as as getPersistedSnapshot, at as createRemoteActorRef, au as resolveReferencedActor, av as createInvokeTimeoutEvent, aw as parseGeneratedActorId, ax as ACTOR_REF_TYPE, k as createActor } from './createActor-a3f7750f.esm.js';
2
- import { g as assertValid } from './index-a8ce72f1.esm.js';
1
+ import { Q as allocateChildId, R as assertChildIdFree, S as reserveChildId, T as STATE_DELIMITER, U as mapValues, t as toArray, V as createInvokeId, W as getDelayedTransitions, Y as getEventDescriptorKey, Z as getCandidates, _ as evaluateCandidate, $ as formatTransition, a0 as NULL_EVENT, a1 as toTransitionConfigArray, a2 as createInvokeTimeoutEventId, a3 as matchesActorSession, a4 as formatRouteTransitions, a5 as resolveStateValue, a6 as getAllStateNodes, x as getStateNodes, a7 as createMachineSnapshot, a8 as isInFinalState, a9 as createInertActorScope, aa as setInertActorScopeSnapshot, a as beginSpawnAllocation, ab as attachSnapshotActorRef, ac as macrostep, ad as isInertActorScope, ae as setSnapshotActorRef, af as cloneMachineSnapshot, ag as transitionNode, g as XSTATE_TIMER, m as matchesEventDescriptor, ah as getTransitionResult, ai as hasEffect, aj as createErrorPlatformEvent, ak as withActorSelf, r as resolveActionsWithContext, al as takeSpawnAllocationCounters, am as mergeActorIdCounters, K as createInitEvent, an as createSpawnEffect, ao as initialMicrostep, ap as toStatePath, aq as isStateId, ar as getStateNodeByPath, as as getPersistedSnapshot, at as createRemoteActorRef, au as resolveReferencedActor, av as createInvokeTimeoutEvent, aw as parseGeneratedActorId, ax as ACTOR_REF_TYPE, k as createActor } from './createActor-973c72ad.esm.js';
2
+ import { g as assertValid } from './index-b478f443.esm.js';
3
3
 
4
4
  function createSpawner(actorScope, actors, spawnedChildren) {
5
5
  return (src, options) => {
@@ -398,6 +398,16 @@ function formatInitialTransition(stateNode, _target) {
398
398
  }
399
399
 
400
400
  const STATE_IDENTIFIER = '#';
401
+ function findEventSchema(schemas, eventType) {
402
+ if (!schemas) {
403
+ return undefined;
404
+ }
405
+ if (Object.hasOwn(schemas, eventType)) {
406
+ return schemas[eventType];
407
+ }
408
+ const descriptor = Object.keys(schemas).find(key => matchesEventDescriptor(eventType, key));
409
+ return descriptor === undefined ? undefined : schemas[descriptor];
410
+ }
401
411
  let emptyCanActor;
402
412
  let emptyCanActorScope;
403
413
  function getEmptyCanActor() {
@@ -442,6 +452,12 @@ class StateMachine {
442
452
  config, sources, validator) {
443
453
  this.config = config;
444
454
  this.validator = validator;
455
+ /**
456
+ * @internal Type-only marker for the actor's internal event protocol. Not
457
+ * `declare` (the build's babel pipeline rejects declare class fields); the
458
+ * one `undefined` property this emits per machine instance is inert.
459
+ */
460
+ this._internalEventType = void 0;
445
461
  /** The machine's own version. */
446
462
  this.version = void 0;
447
463
  this.schemas = void 0;
@@ -569,9 +585,10 @@ class StateMachine {
569
585
  }
570
586
  const event = value;
571
587
  const eventSchemas = this.schemas?.events;
588
+ const internalEventSchemas = this.schemas?.internalEvents;
572
589
  const isFrameworkEvent = event.type.startsWith('xstate.') || event.type.startsWith('@xstate.');
573
- const schema = eventSchemas && Object.hasOwn(eventSchemas, event.type) ? eventSchemas[event.type] : undefined;
574
- if (eventSchemas && !schema && !isFrameworkEvent) {
590
+ const schema = findEventSchema(internalEventSchemas, event.type) ?? findEventSchema(eventSchemas, event.type);
591
+ if ((eventSchemas || internalEventSchemas) && !schema && !isFrameworkEvent) {
575
592
  return {
576
593
  issues: [{
577
594
  message: `Unknown event '${event.type}' for machine '${this.id}' version '${this.version}'.`
@@ -607,7 +624,7 @@ class StateMachine {
607
624
  }
608
625
  }
609
626
  };
610
- this.internalEventDescriptors = this.config.internalEvents ?? [];
627
+ this.internalEventDescriptors = [...Object.keys(this.schemas?.internalEvents ?? {}), ...(this.config.internalEvents ?? [])];
611
628
  this.options = {
612
629
  maxIterations: Infinity,
613
630
  ...this.config.options
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var createActor = require('./createActor-f3afd774.cjs.js');
4
- var dist_xstateActors = require('./index-7fd92683.cjs.js');
3
+ var createActor = require('./createActor-9538c7f8.cjs.js');
4
+ var dist_xstateActors = require('./index-ba7170ba.cjs.js');
5
5
 
6
6
  function createSpawner(actorScope, actors, spawnedChildren) {
7
7
  return (src, options) => {
@@ -400,6 +400,16 @@ function formatInitialTransition(stateNode, _target) {
400
400
  }
401
401
 
402
402
  const STATE_IDENTIFIER = '#';
403
+ function findEventSchema(schemas, eventType) {
404
+ if (!schemas) {
405
+ return undefined;
406
+ }
407
+ if (Object.hasOwn(schemas, eventType)) {
408
+ return schemas[eventType];
409
+ }
410
+ const descriptor = Object.keys(schemas).find(key => createActor.matchesEventDescriptor(eventType, key));
411
+ return descriptor === undefined ? undefined : schemas[descriptor];
412
+ }
403
413
  let emptyCanActor;
404
414
  let emptyCanActorScope;
405
415
  function getEmptyCanActor() {
@@ -444,6 +454,12 @@ class StateMachine {
444
454
  config, sources, validator) {
445
455
  this.config = config;
446
456
  this.validator = validator;
457
+ /**
458
+ * @internal Type-only marker for the actor's internal event protocol. Not
459
+ * `declare` (the build's babel pipeline rejects declare class fields); the
460
+ * one `undefined` property this emits per machine instance is inert.
461
+ */
462
+ this._internalEventType = void 0;
447
463
  /** The machine's own version. */
448
464
  this.version = void 0;
449
465
  this.schemas = void 0;
@@ -571,9 +587,10 @@ class StateMachine {
571
587
  }
572
588
  const event = value;
573
589
  const eventSchemas = this.schemas?.events;
590
+ const internalEventSchemas = this.schemas?.internalEvents;
574
591
  const isFrameworkEvent = event.type.startsWith('xstate.') || event.type.startsWith('@xstate.');
575
- const schema = eventSchemas && Object.hasOwn(eventSchemas, event.type) ? eventSchemas[event.type] : undefined;
576
- if (eventSchemas && !schema && !isFrameworkEvent) {
592
+ const schema = findEventSchema(internalEventSchemas, event.type) ?? findEventSchema(eventSchemas, event.type);
593
+ if ((eventSchemas || internalEventSchemas) && !schema && !isFrameworkEvent) {
577
594
  return {
578
595
  issues: [{
579
596
  message: `Unknown event '${event.type}' for machine '${this.id}' version '${this.version}'.`
@@ -609,7 +626,7 @@ class StateMachine {
609
626
  }
610
627
  }
611
628
  };
612
- this.internalEventDescriptors = this.config.internalEvents ?? [];
629
+ this.internalEventDescriptors = [...Object.keys(this.schemas?.internalEvents ?? {}), ...(this.config.internalEvents ?? [])];
613
630
  this.options = {
614
631
  maxIterations: Infinity,
615
632
  ...this.config.options
@@ -183,118 +183,6 @@ function reportUnhandledError(err) {
183
183
 
184
184
  const symbolObservable = (() => typeof Symbol === 'function' && Symbol.observable || '@@observable')();
185
185
 
186
- const emptySubscription = {
187
- unsubscribe() {}
188
- };
189
- const restoreHint = 'or restore this snapshot with embedded children on the runtime that owns them.';
190
-
191
- /** @internal */
192
- function isRemoteActorRef(actorRef) {
193
- return actorRef._remote === true;
194
- }
195
-
196
- /**
197
- * The lifecycle-only snapshot a remote handle exposes. `active` is accurate
198
- * by construction: a completion removes the child from its parent's
199
- * `children`, so a handle only exists while the child is presumed active,
200
- * and the terminal result arrives as a completion event instead of a
201
- * snapshot. Full snapshots are a co-location capability.
202
- */
203
- const remoteSnapshot = Object.freeze({
204
- status: 'active',
205
- output: undefined,
206
- error: undefined
207
- });
208
-
209
- /**
210
- * Creates a location-transparent handle to an actor whose state lives with
211
- * another runtime. The handle is constructed from identity alone — no lookup
212
- * — and every send routes through the system's runtime; its state is not
213
- * synchronously readable.
214
- *
215
- * The surface is deliberately minimal: it covers every member the runtime
216
- * reaches for a restored child (send/_send, lifecycle via start/_stop and
217
- * system.stopActor, persistence, subscribe/on as inert subscriptions).
218
- * Members that only make sense for a co-located actor (public stop(),
219
- * select(), trigger) throw a descriptive error rather than being absent, so
220
- * calling one reports what went wrong instead of a bare TypeError. Observable
221
- * interop and _processingStatus are omitted entirely.
222
- *
223
- * @internal
224
- */
225
- function createRemoteActorRef(system, options) {
226
- const handle = {
227
- _remote: true,
228
- // Self-reference so context persistence recognizes the handle as an
229
- // actor reference instead of recursing into it.
230
- ref: undefined,
231
- id: options.id,
232
- address: options.address,
233
- src: options.src,
234
- registryKey: options.registryKey,
235
- // A remote handle does not know the child's incarnation; the runtime that
236
- // owns the child is the authority on completion staleness — unless the
237
- // host supplied an incarnation token, which lets this side drop stale
238
- // completions and lets journaled sends name the intended incarnation.
239
- sessionId: undefined,
240
- _incarnation: options.incarnation,
241
- system,
242
- _parent: options.parent,
243
- // Round-trips through persistence verbatim (undefined stays undefined,
244
- // so re-persisting is byte-stable); a remote handle cannot act on it
245
- // locally.
246
- _syncSnapshot: options.syncSnapshot,
247
- send(event) {
248
- void system.sendEvent(undefined, ref, event);
249
- },
250
- _send(event) {
251
- throw new Error(`Remote actor '${options.address}' has no local mailbox to receive "${event.type}". Its state lives with another runtime; install a runtime that can reach it (via \`createDurable\`'s adapter runtime operations, or \`system.runtime\`) before sending, ${restoreHint}`);
252
- },
253
- getSnapshot() {
254
- return remoteSnapshot;
255
- },
256
- getPersistedSnapshot() {
257
- throw new Error(`Cannot persist remote actor '${options.address}' from here: its state lives with the runtime that owns it. Persist it there, ${restoreHint}`);
258
- },
259
- start() {},
260
- _stop() {},
261
- stop() {
262
- throw new Error(`Cannot stop remote actor '${options.address}' directly: stopping is a co-located operation. Stop it through the system runtime that owns it (\`system.stopActor(ref)\`), ${restoreHint}`);
263
- },
264
- select() {
265
- throw new Error(`Cannot select from remote actor '${options.address}': its snapshot is not synchronously readable because its state lives with another runtime. Read it on the runtime that owns it, ${restoreHint}`);
266
- },
267
- get trigger() {
268
- throw new Error(`Remote actor '${options.address}' has no \`trigger\` shorthand: it requires a co-located actor. Use \`send(...)\`, which routes through the system runtime.`);
269
- },
270
- // Observation is a co-location capability: a remote handle never emits,
271
- // so subscriptions are inert rather than errors — generic observers may
272
- // attach to any ref.
273
- subscribe() {
274
- return emptySubscription;
275
- },
276
- on() {
277
- return emptySubscription;
278
- },
279
- _isRunning() {
280
- return false;
281
- },
282
- // The same shape Actor.toJSON produces, so serialized snapshots carry
283
- // one actor-reference marker whether a child is co-located or remote.
284
- toJSON() {
285
- return {
286
- xstate$type: ACTOR_REF_TYPE,
287
- id: options.id,
288
- address: options.address,
289
- src: options.src
290
- };
291
- }
292
- };
293
- const ref = handle;
294
- handle.ref = ref;
295
- return ref;
296
- }
297
-
298
186
  function assertSendToEvent(event) {
299
187
  if (typeof event === 'string') {
300
188
  throw new Error(// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
@@ -2010,13 +1898,10 @@ function matchesActorSession(event, snapshot, actorId) {
2010
1898
  if (!child || !('sessionId' in event)) {
2011
1899
  return true;
2012
1900
  }
2013
- if (isRemoteActorRef(child)) {
2014
- // Without a host-supplied incarnation token the runtime that owns the
2015
- // child is the authority on staleness; with one, a completion from a
2016
- // different incarnation of the same address is dropped here.
2017
- return child._incarnation === undefined || child._incarnation === event.sessionId;
2018
- }
2019
- return child.sessionId === event.sessionId;
1901
+ // One rule: a ref that knows its incarnation compares it; a remote handle
1902
+ // without a host-supplied token (sessionId undefined) defers to the
1903
+ // runtime that owns the child.
1904
+ return child.sessionId === undefined || child.sessionId === event.sessionId;
2020
1905
  }
2021
1906
  function normalizeLegacyInternalEvent(event, machine) {
2022
1907
  if (event.type === 'xstate.done.actor' || event.type === 'xstate.error.actor' || event.type === 'xstate.snapshot.actor' || event.type === 'xstate.done.state' || event.type === 'xstate.after' || event.type === 'xstate.timeout' || event.type === 'xstate.timeout.actor') {
@@ -3223,11 +3108,7 @@ function macrostep(snapshot, event, actorScope, internalQueue, initialMicrosteps
3223
3108
  // The same staleness rule matchesActorSession applies to transition
3224
3109
  // selection: a completion from a different incarnation must not remove
3225
3110
  // the still-running child either.
3226
- if (isRemoteActorRef(child)) {
3227
- if (child._incarnation !== undefined && child._incarnation !== sessionId) {
3228
- return;
3229
- }
3230
- } else if (child.sessionId !== sessionId) {
3111
+ if (child.sessionId !== undefined && child.sessionId !== sessionId) {
3231
3112
  return;
3232
3113
  }
3233
3114
  const children = {
@@ -3519,6 +3400,118 @@ function evaluateCandidate(candidate, event, snapshot, stateNode, actorScope, se
3519
3400
  return true;
3520
3401
  }
3521
3402
 
3403
+ const emptySubscription = {
3404
+ unsubscribe() {}
3405
+ };
3406
+ const restoreHint = 'or restore this snapshot with embedded children on the runtime that owns them.';
3407
+
3408
+ /** @internal */
3409
+ function isRemoteActorRef(actorRef) {
3410
+ return actorRef._remote === true;
3411
+ }
3412
+
3413
+ /**
3414
+ * The lifecycle-only snapshot a remote handle exposes. `active` is accurate
3415
+ * by construction: a completion removes the child from its parent's
3416
+ * `children`, so a handle only exists while the child is presumed active,
3417
+ * and the terminal result arrives as a completion event instead of a
3418
+ * snapshot. Full snapshots are a co-location capability.
3419
+ */
3420
+ const remoteSnapshot = Object.freeze({
3421
+ status: 'active',
3422
+ output: undefined,
3423
+ error: undefined
3424
+ });
3425
+
3426
+ /**
3427
+ * Creates a location-transparent handle to an actor whose state lives with
3428
+ * another runtime. The handle is constructed from identity alone — no lookup
3429
+ * — and every send routes through the system's runtime; its state is not
3430
+ * synchronously readable.
3431
+ *
3432
+ * The surface is deliberately minimal: it covers every member the runtime
3433
+ * reaches for a restored child (send/_send, lifecycle via start/_stop and
3434
+ * system.stopActor, persistence, subscribe/on as inert subscriptions).
3435
+ * Members that only make sense for a co-located actor (public stop(),
3436
+ * select(), trigger) throw a descriptive error rather than being absent, so
3437
+ * calling one reports what went wrong instead of a bare TypeError. Observable
3438
+ * interop and _processingStatus are omitted entirely.
3439
+ *
3440
+ * @internal
3441
+ */
3442
+ function createRemoteActorRef(system, options) {
3443
+ const handle = {
3444
+ _remote: true,
3445
+ // Self-reference so context persistence recognizes the handle as an
3446
+ // actor reference instead of recursing into it.
3447
+ ref: undefined,
3448
+ id: options.id,
3449
+ address: options.address,
3450
+ src: options.src,
3451
+ registryKey: options.registryKey,
3452
+ // The host-supplied incarnation token, when present: the owner's
3453
+ // sessionId for this child, letting this side drop stale completions and
3454
+ // journaled sends name the intended incarnation. Without one the handle
3455
+ // does not know the child's incarnation and the owning runtime is the
3456
+ // authority on staleness.
3457
+ sessionId: options.incarnation,
3458
+ system,
3459
+ _parent: options.parent,
3460
+ // Round-trips through persistence verbatim (undefined stays undefined,
3461
+ // so re-persisting is byte-stable); a remote handle cannot act on it
3462
+ // locally.
3463
+ _syncSnapshot: options.syncSnapshot,
3464
+ send(event) {
3465
+ void system.sendEvent(undefined, ref, event);
3466
+ },
3467
+ _send(event) {
3468
+ throw new Error(`Remote actor '${options.address}' has no local mailbox to receive "${event.type}". Its state lives with another runtime; install a runtime that can reach it (via \`createDurable\`'s adapter runtime operations, or \`system.runtime\`) before sending, ${restoreHint}`);
3469
+ },
3470
+ getSnapshot() {
3471
+ return remoteSnapshot;
3472
+ },
3473
+ getPersistedSnapshot() {
3474
+ throw new Error(`Cannot persist remote actor '${options.address}' from here: its state lives with the runtime that owns it. Persist it there, ${restoreHint}`);
3475
+ },
3476
+ start() {},
3477
+ _stop() {},
3478
+ stop() {
3479
+ throw new Error(`Cannot stop remote actor '${options.address}' directly: stopping is a co-located operation. Stop it through the system runtime that owns it (\`system.stopActor(ref)\`), ${restoreHint}`);
3480
+ },
3481
+ select() {
3482
+ throw new Error(`Cannot select from remote actor '${options.address}': its snapshot is not synchronously readable because its state lives with another runtime. Read it on the runtime that owns it, ${restoreHint}`);
3483
+ },
3484
+ get trigger() {
3485
+ throw new Error(`Remote actor '${options.address}' has no \`trigger\` shorthand: it requires a co-located actor. Use \`send(...)\`, which routes through the system runtime.`);
3486
+ },
3487
+ // Observation is a co-location capability: a remote handle never emits,
3488
+ // so subscriptions are inert rather than errors — generic observers may
3489
+ // attach to any ref.
3490
+ subscribe() {
3491
+ return emptySubscription;
3492
+ },
3493
+ on() {
3494
+ return emptySubscription;
3495
+ },
3496
+ _isRunning() {
3497
+ return false;
3498
+ },
3499
+ // The same shape Actor.toJSON produces, so serialized snapshots carry
3500
+ // one actor-reference marker whether a child is co-located or remote.
3501
+ toJSON() {
3502
+ return {
3503
+ xstate$type: ACTOR_REF_TYPE,
3504
+ id: options.id,
3505
+ address: options.address,
3506
+ src: options.src
3507
+ };
3508
+ }
3509
+ };
3510
+ const ref = handle;
3511
+ handle.ref = ref;
3512
+ return ref;
3513
+ }
3514
+
3522
3515
  const emptySnapshotRecord = Object.freeze({});
3523
3516
  function compactSnapshotRecord(value) {
3524
3517
  if (value === emptySnapshotRecord) {
@@ -3704,10 +3697,12 @@ function getPersistedSnapshot(snapshot, options) {
3704
3697
  snapshot: child.getPersistedSnapshot(options)
3705
3698
  } : {
3706
3699
  remote: true,
3707
- // Round-trips verbatim: the host that owns the child injects the
3708
- // token; XState never stamps one (a local sessionId would make
3709
- // persisted snapshots nondeterministic across replays).
3710
- incarnation: child._incarnation
3700
+ // A remote handle's sessionId IS the host-supplied incarnation
3701
+ // token, round-tripped verbatim. A local child persisted by
3702
+ // address never stamps its own sessionId: that value is this
3703
+ // incarnation's, not a durable identity, and it would make
3704
+ // persisted snapshots nondeterministic across replays.
3705
+ incarnation: isRemoteActorRef(child) ? child.sessionId : undefined
3711
3706
  }),
3712
3707
  src: child.src,
3713
3708
  registryKey: child.registryKey,
@@ -4129,14 +4124,21 @@ async function runStep(actor, key, exec, sendSelf = event => void actor.system.s
4129
4124
  * @experimental
4130
4125
  */
4131
4126
  function deliverEvent(source, target, event) {
4127
+ assertEventCanBeSent(source, target, event);
4128
+ const runtimeTarget = target;
4129
+ runtimeTarget._lastSourceRef = source;
4130
+ runtimeTarget._send(event);
4131
+ }
4132
+
4133
+ /**
4134
+ * Ensures internal events cannot cross an actor boundary from an external
4135
+ * sender. Host runtimes must call this before taking ownership of delivery.
4136
+ */
4137
+ function assertEventCanBeSent(source, target, event) {
4132
4138
  const runtimeTarget = target;
4133
- // The same guard local delivery has always applied: internal events may
4134
- // only originate from the actor itself, whichever runtime delivers them.
4135
4139
  if (source !== target && runtimeTarget.logic?.isInternalEventType?.(event.type)) {
4136
4140
  throw new Error(`Internal event "${event.type}" cannot be sent to actor "${target.id}" from outside.`);
4137
4141
  }
4138
- runtimeTarget._lastSourceRef = source;
4139
- runtimeTarget._send(event);
4140
4142
  }
4141
4143
 
4142
4144
  /**
@@ -4198,6 +4200,32 @@ function createSystemId() {
4198
4200
  return `${systemIdPrefix}:${(nextSystemId++).toString(36)}`;
4199
4201
  }
4200
4202
 
4203
+ /**
4204
+ * The identity a durable execution pins on every system its transitions
4205
+ * create. Shared across all transitions (and replays) of one execution, so
4206
+ * session ids become a deterministic function of actor-creation order:
4207
+ * `<executionId>:0`, `<executionId>:1`, … A replayed execution re-creates
4208
+ * the same session ids, so journaled completion events (which carry the
4209
+ * producing incarnation's `sessionId`) still match the children the replay
4210
+ * re-creates.
4211
+ */
4212
+
4213
+ let ambientExecutionIdentity;
4214
+
4215
+ /** @internal Runs `fn` with systems it creates pinned to `identity`. */
4216
+ function withExecutionIdentity(identity, fn) {
4217
+ if (!identity) {
4218
+ return fn();
4219
+ }
4220
+ const previous = ambientExecutionIdentity;
4221
+ ambientExecutionIdentity = identity;
4222
+ try {
4223
+ return fn();
4224
+ } finally {
4225
+ ambientExecutionIdentity = previous;
4226
+ }
4227
+ }
4228
+
4201
4229
  /**
4202
4230
  * Derives the deterministic id prefix for a generated actor id from its actor
4203
4231
  * source: the registered source key when the source is a string, the logic's
@@ -4314,9 +4342,10 @@ function bookSessionId(system) {
4314
4342
 
4315
4343
  /** @internal Every operation of `ActorSystemRuntime`, for runtime wrappers. */
4316
4344
  const RUNTIME_OPERATIONS = ['spawnActor', 'startActor', 'stopActor', 'terminateActor', 'emitEvent', 'scheduleTimer', 'cancelTimer', 'cancelAllTimers', 'deadLetter'
4317
- // `runStep` and `sendEvent` are deliberately absent: durable executions
4318
- // wire them separately, since a step awaits other runtime operations and
4319
- // root-addressed sends are captured per batch.
4345
+ // `runLogic`, `runStep` and `sendEvent` are deliberately absent: durable
4346
+ // executions wire them separately, since logic bodies and steps await
4347
+ // other runtime operations and root-addressed sends are captured per
4348
+ // batch.
4320
4349
  ];
4321
4350
  const emptyScheduledTimers = Object.freeze({});
4322
4351
  function createScheduledTimerId(actor, id) {
@@ -4362,7 +4391,7 @@ class RuntimeSystem {
4362
4391
  }
4363
4392
  constructor(_rootActor, options) {
4364
4393
  this._rootActor = _rootActor;
4365
- this._identity = {
4394
+ this._identity = ambientExecutionIdentity ?? {
4366
4395
  systemId: createSystemId(),
4367
4396
  nextSessionId: 0
4368
4397
  };
@@ -4566,6 +4595,7 @@ class RuntimeSystem {
4566
4595
  terminateActor(actor, termination);
4567
4596
  }
4568
4597
  sendEvent(source, target, event) {
4598
+ assertEventCanBeSent(source, target, event);
4569
4599
  // Record for the inspection `sent[]` facet regardless of which runtime
4570
4600
  // delivers, so host runtimes keep inspection parity.
4571
4601
  this._recordSent(source, target, event);
@@ -4605,6 +4635,13 @@ class RuntimeSystem {
4605
4635
  }
4606
4636
  return runStep(actor, key, exec);
4607
4637
  }
4638
+ runLogic(actor, exec) {
4639
+ const override = this.runtime?.runLogic;
4640
+ if (override) {
4641
+ return override(actor, exec);
4642
+ }
4643
+ return exec();
4644
+ }
4608
4645
  scheduleTimer(source, id, delay) {
4609
4646
  const override = this.runtime?.scheduleTimer;
4610
4647
  if (override) {
@@ -5685,6 +5722,7 @@ exports.isInFinalState = isInFinalState;
5685
5722
  exports.isInertActorScope = isInertActorScope;
5686
5723
  exports.isLazyActorScope = isLazyActorScope;
5687
5724
  exports.isMachineSnapshot = isMachineSnapshot;
5725
+ exports.isRemoteActorRef = isRemoteActorRef;
5688
5726
  exports.isStateId = isStateId;
5689
5727
  exports.listenerLogic = listenerLogic;
5690
5728
  exports.macrostep = macrostep;
@@ -5715,3 +5753,4 @@ exports.toTransitionConfigArray = toTransitionConfigArray;
5715
5753
  exports.transitionNode = transitionNode;
5716
5754
  exports.withActorScope = withActorScope;
5717
5755
  exports.withActorSelf = withActorSelf;
5756
+ exports.withExecutionIdentity = withExecutionIdentity;