xstate 6.0.0-alpha.49 → 6.0.0-alpha.50

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 (65) hide show
  1. package/dist/{StateMachine-0adb3a70.cjs.js → StateMachine-1e6ee14a.cjs.js} +18 -6
  2. package/dist/{StateMachine-29450e6d.development.cjs.js → StateMachine-70df737c.development.cjs.js} +18 -6
  3. package/dist/{StateMachine-2af31c11.esm.js → StateMachine-8cea8974.esm.js} +18 -6
  4. package/dist/{StateMachine-faf50c5c.development.esm.js → StateMachine-bc28e207.development.esm.js} +18 -6
  5. package/dist/{createActor-b4dd05ae.cjs.js → createActor-27fd819f.cjs.js} +80 -10
  6. package/dist/{createActor-88709f74.development.esm.js → createActor-74e185ee.development.esm.js} +80 -11
  7. package/dist/{createActor-268165d4.esm.js → createActor-ad3a1abe.esm.js} +80 -11
  8. package/dist/{createActor-a1e0dffb.development.cjs.js → createActor-ea9a560c.development.cjs.js} +80 -10
  9. package/dist/declarations/src/effectDescriptor.d.ts +9 -0
  10. package/dist/declarations/src/index.d.ts +1 -1
  11. package/dist/declarations/src/inspection.d.ts +24 -7
  12. package/dist/declarations/src/runtimeHelpers.d.ts +6 -3
  13. package/dist/declarations/src/system.d.ts +38 -3
  14. package/dist/declarations/src/types.d.ts +35 -2
  15. package/dist/{effectDescriptor-7ff6802f.development.cjs.js → effectDescriptor-16b6f3b4.cjs.js} +12 -1
  16. package/dist/{effectDescriptor-39d22100.development.esm.js → effectDescriptor-38598bd3.development.esm.js} +12 -1
  17. package/dist/{effectDescriptor-be348e50.cjs.js → effectDescriptor-40ca302f.development.cjs.js} +12 -1
  18. package/dist/{effectDescriptor-30c9a744.esm.js → effectDescriptor-7dac431a.esm.js} +12 -1
  19. package/dist/{fsm-e18a7cb4.development.esm.js → fsm-25f10f50.development.esm.js} +1 -1
  20. package/dist/{fsm-c1316948.development.cjs.js → fsm-697ffd89.development.cjs.js} +1 -1
  21. package/dist/{fsm-7a2e9697.cjs.js → fsm-7adaf0ea.cjs.js} +1 -1
  22. package/dist/{fsm-b804b3e9.esm.js → fsm-dc1bb88b.esm.js} +1 -1
  23. package/dist/{types-fbabaeee.cjs.js → types-a14db10c.development.cjs.js} +6 -1
  24. package/dist/{types-3c3455f7.esm.js → types-a313e7e2.esm.js} +6 -1
  25. package/dist/{types-b3fea5bd.development.cjs.js → types-bc22b358.cjs.js} +6 -1
  26. package/dist/{types-adda3842.development.esm.js → types-c37714eb.development.esm.js} +6 -1
  27. package/dist/xstate-actors.cjs.js +12 -3
  28. package/dist/xstate-actors.development.cjs.js +12 -3
  29. package/dist/xstate-actors.development.esm.js +13 -4
  30. package/dist/xstate-actors.esm.js +13 -4
  31. package/dist/xstate-actors.umd.min.js +1 -1
  32. package/dist/xstate-actors.umd.min.js.map +1 -1
  33. package/dist/xstate-durable.cjs.js +2 -2
  34. package/dist/xstate-durable.development.cjs.js +2 -2
  35. package/dist/xstate-durable.development.esm.js +2 -2
  36. package/dist/xstate-durable.esm.js +2 -2
  37. package/dist/xstate-durable.umd.min.js +1 -1
  38. package/dist/xstate-durable.umd.min.js.map +1 -1
  39. package/dist/xstate-fsm.cjs.js +2 -2
  40. package/dist/xstate-fsm.development.cjs.js +2 -2
  41. package/dist/xstate-fsm.development.esm.js +2 -2
  42. package/dist/xstate-fsm.esm.js +2 -2
  43. package/dist/xstate-graph.cjs.js +2 -2
  44. package/dist/xstate-graph.development.cjs.js +2 -2
  45. package/dist/xstate-graph.development.esm.js +2 -2
  46. package/dist/xstate-graph.esm.js +2 -2
  47. package/dist/xstate-graph.umd.min.js +1 -1
  48. package/dist/xstate-graph.umd.min.js.map +1 -1
  49. package/dist/xstate-scxml.cjs.js +3 -3
  50. package/dist/xstate-scxml.development.cjs.js +3 -3
  51. package/dist/xstate-scxml.development.esm.js +3 -3
  52. package/dist/xstate-scxml.esm.js +3 -3
  53. package/dist/xstate-scxml.umd.min.js +1 -1
  54. package/dist/xstate-scxml.umd.min.js.map +1 -1
  55. package/dist/xstate-validation.cjs.js +1 -1
  56. package/dist/xstate-validation.development.cjs.js +1 -1
  57. package/dist/xstate-validation.development.esm.js +1 -1
  58. package/dist/xstate-validation.esm.js +1 -1
  59. package/dist/xstate.cjs.js +5 -5
  60. package/dist/xstate.development.cjs.js +5 -5
  61. package/dist/xstate.development.esm.js +8 -8
  62. package/dist/xstate.esm.js +8 -8
  63. package/dist/xstate.umd.min.js +1 -1
  64. package/dist/xstate.umd.min.js.map +1 -1
  65. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var createActor = require('./createActor-b4dd05ae.cjs.js');
3
+ var createActor = require('./createActor-27fd819f.cjs.js');
4
4
  var validation = require('./validation-4561b43c.cjs.js');
5
5
 
6
6
  function createSpawner(actorScope, actors, spawnedChildren) {
@@ -714,16 +714,28 @@ class StateMachine {
714
714
  transition(snapshot, event, actorScope) {
715
715
  const usesInertScope = !actorScope;
716
716
  const resolvedActorScope = actorScope ?? createActor.createInertActorScope(this, snapshot);
717
+ if (usesInertScope) {
718
+ createActor.setInertActorScopeSnapshot(resolvedActorScope, snapshot, false);
719
+ }
717
720
  if (this.validator) {
718
- validation.assertValid(this.validator, {
721
+ const sourceRef = actorScope && actorScope.self._lastSourceRef;
722
+ const eventOrigin = sourceRef ? 'actor' : 'external';
723
+ const error = this.validator.check({
719
724
  kind: 'event',
720
725
  logic: this,
721
726
  event,
722
- eventOrigin: actorScope && actorScope.self._lastSourceRef ? 'actor' : 'external'
727
+ eventOrigin
723
728
  });
724
- }
725
- if (usesInertScope) {
726
- createActor.setInertActorScopeSnapshot(resolvedActorScope, snapshot, false);
729
+ if (error) {
730
+ // Boundary fault: an invalid event arriving from outside the machine
731
+ // is rejected (never delivered), not routed to the error channel. The
732
+ // snapshot is returned unchanged; the rejection is represented as an
733
+ // effect so hosts and the actor runtime can report it.
734
+ return [snapshot, [createActor.createDeadLetterEffect(resolvedActorScope, sourceRef, event, 'invalidEvent', {
735
+ issues: error.issues,
736
+ error
737
+ })]];
738
+ }
727
739
  }
728
740
  createActor.beginSpawnAllocation(resolvedActorScope);
729
741
  const fastSnapshot = this._transitionFast(snapshot, event, resolvedActorScope);
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var createActor = require('./createActor-a1e0dffb.development.cjs.js');
3
+ var createActor = require('./createActor-ea9a560c.development.cjs.js');
4
4
  var validation = require('./validation-f2714a35.development.cjs.js');
5
5
 
6
6
  function createSpawner(actorScope, actors, spawnedChildren) {
@@ -743,16 +743,28 @@ class StateMachine {
743
743
  transition(snapshot, event, actorScope) {
744
744
  const usesInertScope = !actorScope;
745
745
  const resolvedActorScope = actorScope ?? createActor.createInertActorScope(this, snapshot);
746
+ if (usesInertScope) {
747
+ createActor.setInertActorScopeSnapshot(resolvedActorScope, snapshot, false);
748
+ }
746
749
  if (this.validator) {
747
- validation.assertValid(this.validator, {
750
+ const sourceRef = actorScope && actorScope.self._lastSourceRef;
751
+ const eventOrigin = sourceRef ? 'actor' : 'external';
752
+ const error = this.validator.check({
748
753
  kind: 'event',
749
754
  logic: this,
750
755
  event,
751
- eventOrigin: actorScope && actorScope.self._lastSourceRef ? 'actor' : 'external'
756
+ eventOrigin
752
757
  });
753
- }
754
- if (usesInertScope) {
755
- createActor.setInertActorScopeSnapshot(resolvedActorScope, snapshot, false);
758
+ if (error) {
759
+ // Boundary fault: an invalid event arriving from outside the machine
760
+ // is rejected (never delivered), not routed to the error channel. The
761
+ // snapshot is returned unchanged; the rejection is represented as an
762
+ // effect so hosts and the actor runtime can report it.
763
+ return [snapshot, [createActor.createDeadLetterEffect(resolvedActorScope, sourceRef, event, 'invalidEvent', {
764
+ issues: error.issues,
765
+ error
766
+ })]];
767
+ }
756
768
  }
757
769
  createActor.beginSpawnAllocation(resolvedActorScope);
758
770
  const fastSnapshot = this._transitionFast(snapshot, event, resolvedActorScope);
@@ -1,4 +1,4 @@
1
- import { L as resolveRegisteredActorSource, M as allocateChildId, N as assertChildIdFree, O as reserveChildId, S as STATE_DELIMITER, P as mapValues, t as toArray, Q as createInvokeId, R as getDelayedTransitions, T as getEventDescriptorKey, U as getCandidates, V as evaluateCandidate, W as formatTransition, Y as NULL_EVENT, Z as toTransitionConfigArray, _ as createInvokeTimeoutEventId, $ as matchesActorSession, a0 as formatRouteTransitions, a1 as resolveStateValue, a2 as getAllStateNodes, f as getStateNodes, a3 as createMachineSnapshot, a4 as isInFinalState, a5 as createInertActorScope, a6 as setInertActorScopeSnapshot, a7 as beginSpawnAllocation, a8 as attachSnapshotActorRef, a9 as macrostep, aa as isInertActorScope, ab as setSnapshotActorRef, ac as cloneMachineSnapshot, ad as transitionNode, J as XSTATE_TIMER, m as matchesEventDescriptor, ae as getTransitionResult, af as hasEffect, ag as createErrorPlatformEvent, ah as withActorSelf, ai as resolveActionsWithContext, aj as takeSpawnAllocationCounters, ak as mergeActorIdCounters, y as createInitEvent, al as createSpawnEffect, am as initialMicrostep, an as toStatePath, ao as isStateId, ap as getStateNodeByPath, aq as getPersistedSnapshot, ar as createRemoteActorRef, as as resolveReferencedActor, at as createInvokeTimeoutEvent, au as parseGeneratedActorId, av as ACTOR_REF_TYPE, c as createActor } from './createActor-268165d4.esm.js';
1
+ import { M as resolveRegisteredActorSource, N as allocateChildId, O as assertChildIdFree, P as reserveChildId, S as STATE_DELIMITER, Q as mapValues, t as toArray, R as createInvokeId, T as getDelayedTransitions, U as getEventDescriptorKey, V as getCandidates, W as evaluateCandidate, Y as formatTransition, Z as NULL_EVENT, _ as toTransitionConfigArray, $ as createInvokeTimeoutEventId, a0 as matchesActorSession, a1 as formatRouteTransitions, a2 as resolveStateValue, a3 as getAllStateNodes, f as getStateNodes, a4 as createMachineSnapshot, a5 as isInFinalState, a6 as createInertActorScope, a7 as setInertActorScopeSnapshot, z as createDeadLetterEffect, a8 as beginSpawnAllocation, a9 as attachSnapshotActorRef, aa as macrostep, ab as isInertActorScope, ac as setSnapshotActorRef, ad as cloneMachineSnapshot, ae as transitionNode, K as XSTATE_TIMER, m as matchesEventDescriptor, af as getTransitionResult, ag as hasEffect, ah as createErrorPlatformEvent, ai as withActorSelf, aj as resolveActionsWithContext, ak as takeSpawnAllocationCounters, al as mergeActorIdCounters, y as createInitEvent, am as createSpawnEffect, an as initialMicrostep, ao as toStatePath, ap as isStateId, aq as getStateNodeByPath, ar as getPersistedSnapshot, as as createRemoteActorRef, at as resolveReferencedActor, au as createInvokeTimeoutEvent, av as parseGeneratedActorId, aw as ACTOR_REF_TYPE, c as createActor } from './createActor-ad3a1abe.esm.js';
2
2
  import { a as assertValid } from './validation-05f1d517.esm.js';
3
3
 
4
4
  function createSpawner(actorScope, actors, spawnedChildren) {
@@ -712,16 +712,28 @@ class StateMachine {
712
712
  transition(snapshot, event, actorScope) {
713
713
  const usesInertScope = !actorScope;
714
714
  const resolvedActorScope = actorScope ?? createInertActorScope(this, snapshot);
715
+ if (usesInertScope) {
716
+ setInertActorScopeSnapshot(resolvedActorScope, snapshot, false);
717
+ }
715
718
  if (this.validator) {
716
- assertValid(this.validator, {
719
+ const sourceRef = actorScope && actorScope.self._lastSourceRef;
720
+ const eventOrigin = sourceRef ? 'actor' : 'external';
721
+ const error = this.validator.check({
717
722
  kind: 'event',
718
723
  logic: this,
719
724
  event,
720
- eventOrigin: actorScope && actorScope.self._lastSourceRef ? 'actor' : 'external'
725
+ eventOrigin
721
726
  });
722
- }
723
- if (usesInertScope) {
724
- setInertActorScopeSnapshot(resolvedActorScope, snapshot, false);
727
+ if (error) {
728
+ // Boundary fault: an invalid event arriving from outside the machine
729
+ // is rejected (never delivered), not routed to the error channel. The
730
+ // snapshot is returned unchanged; the rejection is represented as an
731
+ // effect so hosts and the actor runtime can report it.
732
+ return [snapshot, [createDeadLetterEffect(resolvedActorScope, sourceRef, event, 'invalidEvent', {
733
+ issues: error.issues,
734
+ error
735
+ })]];
736
+ }
725
737
  }
726
738
  beginSpawnAllocation(resolvedActorScope);
727
739
  const fastSnapshot = this._transitionFast(snapshot, event, resolvedActorScope);
@@ -1,4 +1,4 @@
1
- import { L as resolveRegisteredActorSource, M as allocateChildId, N as assertChildIdFree, O as reserveChildId, S as STATE_DELIMITER, P as mapValues, t as toArray, Q as createInvokeId, R as getDelayedTransitions, T as getEventDescriptorKey, U as getCandidates, V as evaluateCandidate, W as formatTransition, Y as NULL_EVENT, Z as toTransitionConfigArray, _ as createInvokeTimeoutEventId, $ as matchesActorSession, a0 as formatRouteTransitions, a1 as resolveStateValue, a2 as getAllStateNodes, f as getStateNodes, a3 as createMachineSnapshot, a4 as isInFinalState, a5 as createInertActorScope, a6 as setInertActorScopeSnapshot, a7 as beginSpawnAllocation, a8 as attachSnapshotActorRef, a9 as macrostep, aa as isInertActorScope, ab as setSnapshotActorRef, ac as cloneMachineSnapshot, ad as transitionNode, J as XSTATE_TIMER, m as matchesEventDescriptor, ae as getTransitionResult, af as hasEffect, ag as createErrorPlatformEvent, ah as withActorSelf, ai as resolveActionsWithContext, aj as takeSpawnAllocationCounters, ak as mergeActorIdCounters, y as createInitEvent, al as createSpawnEffect, am as initialMicrostep, an as toStatePath, ao as isStateId, ap as getStateNodeByPath, aq as getPersistedSnapshot, ar as createRemoteActorRef, as as resolveReferencedActor, at as createInvokeTimeoutEvent, au as parseGeneratedActorId, av as ACTOR_REF_TYPE, c as createActor } from './createActor-88709f74.development.esm.js';
1
+ import { M as resolveRegisteredActorSource, N as allocateChildId, O as assertChildIdFree, P as reserveChildId, S as STATE_DELIMITER, Q as mapValues, t as toArray, R as createInvokeId, T as getDelayedTransitions, U as getEventDescriptorKey, V as getCandidates, W as evaluateCandidate, Y as formatTransition, Z as NULL_EVENT, _ as toTransitionConfigArray, $ as createInvokeTimeoutEventId, a0 as matchesActorSession, a1 as formatRouteTransitions, a2 as resolveStateValue, a3 as getAllStateNodes, f as getStateNodes, a4 as createMachineSnapshot, a5 as isInFinalState, a6 as createInertActorScope, a7 as setInertActorScopeSnapshot, z as createDeadLetterEffect, a8 as beginSpawnAllocation, a9 as attachSnapshotActorRef, aa as macrostep, ab as isInertActorScope, ac as setSnapshotActorRef, ad as cloneMachineSnapshot, ae as transitionNode, K as XSTATE_TIMER, m as matchesEventDescriptor, af as getTransitionResult, ag as hasEffect, ah as createErrorPlatformEvent, ai as withActorSelf, aj as resolveActionsWithContext, ak as takeSpawnAllocationCounters, al as mergeActorIdCounters, y as createInitEvent, am as createSpawnEffect, an as initialMicrostep, ao as toStatePath, ap as isStateId, aq as getStateNodeByPath, ar as getPersistedSnapshot, as as createRemoteActorRef, at as resolveReferencedActor, au as createInvokeTimeoutEvent, av as parseGeneratedActorId, aw as ACTOR_REF_TYPE, c as createActor } from './createActor-74e185ee.development.esm.js';
2
2
  import { a as assertValid } from './validation-e69470ad.development.esm.js';
3
3
 
4
4
  function createSpawner(actorScope, actors, spawnedChildren) {
@@ -741,16 +741,28 @@ class StateMachine {
741
741
  transition(snapshot, event, actorScope) {
742
742
  const usesInertScope = !actorScope;
743
743
  const resolvedActorScope = actorScope ?? createInertActorScope(this, snapshot);
744
+ if (usesInertScope) {
745
+ setInertActorScopeSnapshot(resolvedActorScope, snapshot, false);
746
+ }
744
747
  if (this.validator) {
745
- assertValid(this.validator, {
748
+ const sourceRef = actorScope && actorScope.self._lastSourceRef;
749
+ const eventOrigin = sourceRef ? 'actor' : 'external';
750
+ const error = this.validator.check({
746
751
  kind: 'event',
747
752
  logic: this,
748
753
  event,
749
- eventOrigin: actorScope && actorScope.self._lastSourceRef ? 'actor' : 'external'
754
+ eventOrigin
750
755
  });
751
- }
752
- if (usesInertScope) {
753
- setInertActorScopeSnapshot(resolvedActorScope, snapshot, false);
756
+ if (error) {
757
+ // Boundary fault: an invalid event arriving from outside the machine
758
+ // is rejected (never delivered), not routed to the error channel. The
759
+ // snapshot is returned unchanged; the rejection is represented as an
760
+ // effect so hosts and the actor runtime can report it.
761
+ return [snapshot, [createDeadLetterEffect(resolvedActorScope, sourceRef, event, 'invalidEvent', {
762
+ issues: error.issues,
763
+ error
764
+ })]];
765
+ }
754
766
  }
755
767
  beginSpawnAllocation(resolvedActorScope);
756
768
  const fastSnapshot = this._transitionFast(snapshot, event, resolvedActorScope);
@@ -500,6 +500,25 @@ function createEmitEffect(actorScope, event) {
500
500
  args: []
501
501
  };
502
502
  }
503
+ function execDeadLetterEffect(runtime = this.target.system) {
504
+ return runtime.deadLetter(this.source, this.target, this.event, this.reason, this.detail);
505
+ }
506
+
507
+ /** @internal Creates a dead-letter effect for a boundary-rejected event. */
508
+ function createDeadLetterEffect(actorScope, source, event, reason, detail) {
509
+ return {
510
+ kind: 'builtin',
511
+ type: '@xstate.deadLetter',
512
+ exec: execDeadLetterEffect,
513
+ source,
514
+ target: actorScope.self,
515
+ event,
516
+ reason,
517
+ detail,
518
+ params: undefined,
519
+ args: []
520
+ };
521
+ }
503
522
 
504
523
  /** @internal Creates a directly executable user effect. */
505
524
  function createCustomEffect(type, action, params) {
@@ -4227,21 +4246,42 @@ async function runStep(actor, key, exec, sendSelf = event => void actor.system.s
4227
4246
  * @experimental
4228
4247
  */
4229
4248
  function deliverEvent(source, target, event) {
4230
- assertEventCanBeSent(source, target, event);
4249
+ if (rejectUndeliverableEvent(source, target, event)) {
4250
+ return;
4251
+ }
4231
4252
  const runtimeTarget = target;
4232
4253
  runtimeTarget._lastSourceRef = source;
4233
4254
  runtimeTarget._send(event);
4234
4255
  }
4235
4256
 
4236
4257
  /**
4237
- * Ensures internal events cannot cross an actor boundary from an external
4238
- * sender. Host runtimes must call this before taking ownership of delivery.
4258
+ * Returns the boundary error preventing this delivery, if any: an internal
4259
+ * event type cannot cross an actor boundary from an external sender.
4239
4260
  */
4240
- function assertEventCanBeSent(source, target, event) {
4261
+ function getEventBoundaryError(source, target, event) {
4241
4262
  const runtimeTarget = target;
4242
4263
  if (source !== target && runtimeTarget.logic?.isInternalEventType?.(event.type)) {
4243
- throw new Error(`Internal event "${event.type}" cannot be sent to actor "${target.id}" from outside.`);
4264
+ return new Error(`Internal event "${event.type}" cannot be sent to actor "${target.id}" from outside.`);
4265
+ }
4266
+ return undefined;
4267
+ }
4268
+
4269
+ /**
4270
+ * Rejects an event that must not cross the delivery boundary — an internal
4271
+ * event type sent from outside its owning actor — by reporting it as a dead
4272
+ * letter. Returns `true` when the event was rejected and must not be
4273
+ * delivered. Host runtimes must call this before taking ownership of
4274
+ * delivery.
4275
+ */
4276
+ function rejectUndeliverableEvent(source, target, event) {
4277
+ const error = getEventBoundaryError(source, target, event);
4278
+ if (error) {
4279
+ void target.system.deadLetter(source, target, event, 'internalEvent', {
4280
+ error
4281
+ });
4282
+ return true;
4244
4283
  }
4284
+ return false;
4245
4285
  }
4246
4286
 
4247
4287
  /**
@@ -4442,6 +4482,19 @@ function bookSessionId(system) {
4442
4482
  * other: install a different one via `system.runtime` (for durable hosts,
4443
4483
  * through `createDurable`'s adapter runtime operations).
4444
4484
  */
4485
+ /**
4486
+ * Why an event was not delivered: `'invalidEvent'` (payload failed its
4487
+ * declared schema), `'internalEvent'` (an internal event type sent from
4488
+ * outside its owning actor) or `'stopped'` (the target actor already
4489
+ * stopped). Hosts may report additional reasons.
4490
+ */
4491
+
4492
+ /** Extra detail attached to a dead letter. */
4493
+
4494
+ /**
4495
+ * Describes an event that was rejected at the delivery boundary instead of
4496
+ * being delivered to its target actor (a dead letter).
4497
+ */
4445
4498
 
4446
4499
  /** @internal Every operation of `ActorSystemRuntime`, for runtime wrappers. */
4447
4500
  const RUNTIME_OPERATIONS = ['spawnActor', 'startActor', 'stopActor', 'terminateActor', 'emitEvent', 'scheduleTimer', 'cancelTimer', 'cancelAllTimers', 'deadLetter'
@@ -4504,6 +4557,7 @@ class RuntimeSystem {
4504
4557
  this._clock = void 0;
4505
4558
  this._logger = void 0;
4506
4559
  this.createActorRef = void 0;
4560
+ this._onRejectedEvent = options.onRejectedEvent;
4507
4561
  const restoredSnapshot = typeof options.snapshot === 'object' && options.snapshot !== null ? options.snapshot : undefined;
4508
4562
  this._clock = options.clock;
4509
4563
  this._logger = options.logger;
@@ -4702,7 +4756,9 @@ class RuntimeSystem {
4702
4756
  terminateActor(actor, termination);
4703
4757
  }
4704
4758
  sendEvent(source, target, event) {
4705
- assertEventCanBeSent(source, target, event);
4759
+ if (rejectUndeliverableEvent(source, target, event)) {
4760
+ return;
4761
+ }
4706
4762
  // Record for the inspection `sent[]` facet regardless of which runtime
4707
4763
  // delivers, so host runtimes keep inspection parity.
4708
4764
  this._recordSent(source, target, event);
@@ -4719,17 +4775,29 @@ class RuntimeSystem {
4719
4775
  }
4720
4776
  source._emit(event);
4721
4777
  }
4722
- deadLetter(source, target, event, reason) {
4778
+ deadLetter(source, target, event, reason, detail) {
4723
4779
  this._sendInspectionEvent({
4724
4780
  type: '@xstate.deadletter',
4725
4781
  actorRef: target,
4726
4782
  sourceRef: source,
4727
4783
  event,
4728
- reason
4784
+ reason,
4785
+ issues: detail?.issues,
4786
+ error: detail?.error
4787
+ });
4788
+ this._onRejectedEvent?.({
4789
+ event,
4790
+ targetRef: target,
4791
+ targetId: target.id,
4792
+ sourceRef: source,
4793
+ eventOrigin: source ? 'actor' : 'external',
4794
+ reason,
4795
+ issues: detail?.issues,
4796
+ error: detail?.error
4729
4797
  });
4730
4798
  const override = this.runtime?.deadLetter;
4731
4799
  if (override) {
4732
- return override(source, target, event, reason);
4800
+ return override(source, target, event, reason, detail);
4733
4801
  }
4734
4802
  }
4735
4803
  runStep(actor, key, exec) {
@@ -4976,7 +5044,8 @@ class Actor {
4976
5044
  clock,
4977
5045
  logger,
4978
5046
  snapshot: resolvedOptions.snapshot ?? resolvedOptions.state,
4979
- createActorRef
5047
+ createActorRef,
5048
+ onRejectedEvent: resolvedOptions.onRejectedEvent
4980
5049
  });
4981
5050
  if (!parent && resolvedOptions._systemRef && !resolvedOptions._systemRef.current) {
4982
5051
  resolvedOptions._systemRef.current = this.system;
@@ -5776,6 +5845,7 @@ exports.checkStateIn = checkStateIn;
5776
5845
  exports.cloneMachineSnapshot = cloneMachineSnapshot;
5777
5846
  exports.createActor = createActor;
5778
5847
  exports.createCustomEffect = createCustomEffect;
5848
+ exports.createDeadLetterEffect = createDeadLetterEffect;
5779
5849
  exports.createEmitEffect = createEmitEffect;
5780
5850
  exports.createErrorPlatformEvent = createErrorPlatformEvent;
5781
5851
  exports.createInertActorScope = createInertActorScope;
@@ -499,6 +499,25 @@ function createEmitEffect(actorScope, event) {
499
499
  args: []
500
500
  };
501
501
  }
502
+ function execDeadLetterEffect(runtime = this.target.system) {
503
+ return runtime.deadLetter(this.source, this.target, this.event, this.reason, this.detail);
504
+ }
505
+
506
+ /** @internal Creates a dead-letter effect for a boundary-rejected event. */
507
+ function createDeadLetterEffect(actorScope, source, event, reason, detail) {
508
+ return {
509
+ kind: 'builtin',
510
+ type: '@xstate.deadLetter',
511
+ exec: execDeadLetterEffect,
512
+ source,
513
+ target: actorScope.self,
514
+ event,
515
+ reason,
516
+ detail,
517
+ params: undefined,
518
+ args: []
519
+ };
520
+ }
502
521
 
503
522
  /** @internal Creates a directly executable user effect. */
504
523
  function createCustomEffect(type, action, params) {
@@ -4255,21 +4274,42 @@ async function runStep(actor, key, exec, sendSelf = event => void actor.system.s
4255
4274
  * @experimental
4256
4275
  */
4257
4276
  function deliverEvent(source, target, event) {
4258
- assertEventCanBeSent(source, target, event);
4277
+ if (rejectUndeliverableEvent(source, target, event)) {
4278
+ return;
4279
+ }
4259
4280
  const runtimeTarget = target;
4260
4281
  runtimeTarget._lastSourceRef = source;
4261
4282
  runtimeTarget._send(event);
4262
4283
  }
4263
4284
 
4264
4285
  /**
4265
- * Ensures internal events cannot cross an actor boundary from an external
4266
- * sender. Host runtimes must call this before taking ownership of delivery.
4286
+ * Returns the boundary error preventing this delivery, if any: an internal
4287
+ * event type cannot cross an actor boundary from an external sender.
4267
4288
  */
4268
- function assertEventCanBeSent(source, target, event) {
4289
+ function getEventBoundaryError(source, target, event) {
4269
4290
  const runtimeTarget = target;
4270
4291
  if (source !== target && runtimeTarget.logic?.isInternalEventType?.(event.type)) {
4271
- throw new Error(`Internal event "${event.type}" cannot be sent to actor "${target.id}" from outside.`);
4292
+ return new Error(`Internal event "${event.type}" cannot be sent to actor "${target.id}" from outside.`);
4293
+ }
4294
+ return undefined;
4295
+ }
4296
+
4297
+ /**
4298
+ * Rejects an event that must not cross the delivery boundary — an internal
4299
+ * event type sent from outside its owning actor — by reporting it as a dead
4300
+ * letter. Returns `true` when the event was rejected and must not be
4301
+ * delivered. Host runtimes must call this before taking ownership of
4302
+ * delivery.
4303
+ */
4304
+ function rejectUndeliverableEvent(source, target, event) {
4305
+ const error = getEventBoundaryError(source, target, event);
4306
+ if (error) {
4307
+ void target.system.deadLetter(source, target, event, 'internalEvent', {
4308
+ error
4309
+ });
4310
+ return true;
4272
4311
  }
4312
+ return false;
4273
4313
  }
4274
4314
 
4275
4315
  /**
@@ -4470,6 +4510,19 @@ function bookSessionId(system) {
4470
4510
  * other: install a different one via `system.runtime` (for durable hosts,
4471
4511
  * through `createDurable`'s adapter runtime operations).
4472
4512
  */
4513
+ /**
4514
+ * Why an event was not delivered: `'invalidEvent'` (payload failed its
4515
+ * declared schema), `'internalEvent'` (an internal event type sent from
4516
+ * outside its owning actor) or `'stopped'` (the target actor already
4517
+ * stopped). Hosts may report additional reasons.
4518
+ */
4519
+
4520
+ /** Extra detail attached to a dead letter. */
4521
+
4522
+ /**
4523
+ * Describes an event that was rejected at the delivery boundary instead of
4524
+ * being delivered to its target actor (a dead letter).
4525
+ */
4473
4526
 
4474
4527
  /** @internal Every operation of `ActorSystemRuntime`, for runtime wrappers. */
4475
4528
  const RUNTIME_OPERATIONS = ['spawnActor', 'startActor', 'stopActor', 'terminateActor', 'emitEvent', 'scheduleTimer', 'cancelTimer', 'cancelAllTimers', 'deadLetter'
@@ -4532,6 +4585,7 @@ class RuntimeSystem {
4532
4585
  this._clock = void 0;
4533
4586
  this._logger = void 0;
4534
4587
  this.createActorRef = void 0;
4588
+ this._onRejectedEvent = options.onRejectedEvent;
4535
4589
  const restoredSnapshot = typeof options.snapshot === 'object' && options.snapshot !== null ? options.snapshot : undefined;
4536
4590
  this._clock = options.clock;
4537
4591
  this._logger = options.logger;
@@ -4730,7 +4784,9 @@ class RuntimeSystem {
4730
4784
  terminateActor(actor, termination);
4731
4785
  }
4732
4786
  sendEvent(source, target, event) {
4733
- assertEventCanBeSent(source, target, event);
4787
+ if (rejectUndeliverableEvent(source, target, event)) {
4788
+ return;
4789
+ }
4734
4790
  // Record for the inspection `sent[]` facet regardless of which runtime
4735
4791
  // delivers, so host runtimes keep inspection parity.
4736
4792
  this._recordSent(source, target, event);
@@ -4747,17 +4803,29 @@ class RuntimeSystem {
4747
4803
  }
4748
4804
  source._emit(event);
4749
4805
  }
4750
- deadLetter(source, target, event, reason) {
4806
+ deadLetter(source, target, event, reason, detail) {
4751
4807
  this._sendInspectionEvent({
4752
4808
  type: '@xstate.deadletter',
4753
4809
  actorRef: target,
4754
4810
  sourceRef: source,
4755
4811
  event,
4756
- reason
4812
+ reason,
4813
+ issues: detail?.issues,
4814
+ error: detail?.error
4815
+ });
4816
+ this._onRejectedEvent?.({
4817
+ event,
4818
+ targetRef: target,
4819
+ targetId: target.id,
4820
+ sourceRef: source,
4821
+ eventOrigin: source ? 'actor' : 'external',
4822
+ reason,
4823
+ issues: detail?.issues,
4824
+ error: detail?.error
4757
4825
  });
4758
4826
  const override = this.runtime?.deadLetter;
4759
4827
  if (override) {
4760
- return override(source, target, event, reason);
4828
+ return override(source, target, event, reason, detail);
4761
4829
  }
4762
4830
  {
4763
4831
  console.warn(`Event "${event.type}" to actor "${target.id}" was not delivered (${reason}).`);
@@ -5007,7 +5075,8 @@ class Actor {
5007
5075
  clock,
5008
5076
  logger,
5009
5077
  snapshot: resolvedOptions.snapshot ?? resolvedOptions.state,
5010
- createActorRef
5078
+ createActorRef,
5079
+ onRejectedEvent: resolvedOptions.onRejectedEvent
5011
5080
  });
5012
5081
  if (!parent && resolvedOptions._systemRef && !resolvedOptions._systemRef.current) {
5013
5082
  resolvedOptions._systemRef.current = this.system;
@@ -5794,4 +5863,4 @@ function createActor(logic, options) {
5794
5863
  return new Actor(logic, options);
5795
5864
  }
5796
5865
 
5797
- export { matchesActorSession as $, Actor as A, XSTATE_LOGIC_EFFECT_START as B, XSTATE_LOGIC_EFFECT_RESOLVE as C, XSTATE_LOGIC_EFFECT_REJECT as D, finalizeTransitionResult as E, createEmitEffect as F, createSendToEffect as G, XSTATE_INIT as H, withActorScope as I, XSTATE_TIMER as J, isLazyActorScope as K, resolveRegisteredActorSource as L, allocateChildId as M, assertChildIdFree as N, reserveChildId as O, mapValues as P, createInvokeId as Q, getDelayedTransitions as R, STATE_DELIMITER as S, getEventDescriptorKey as T, getCandidates as U, evaluateCandidate as V, formatTransition as W, XSTATE_STOP as X, NULL_EVENT as Y, toTransitionConfigArray as Z, createInvokeTimeoutEventId as _, createListenerLogic as a, formatRouteTransitions as a0, resolveStateValue as a1, getAllStateNodes as a2, createMachineSnapshot as a3, isInFinalState as a4, createInertActorScope as a5, setInertActorScopeSnapshot as a6, beginSpawnAllocation as a7, attachSnapshotActorRef as a8, macrostep as a9, getAllOwnEvents as aA, matchesEvent as aB, encodeAddressSegment as aC, getRootActorId as aD, RUNTIME_OPERATIONS as aE, withSystemInspector as aF, getSnapshotActorRef as aG, withExecutionIdentity as aH, isInertActorScope as aa, setSnapshotActorRef as ab, cloneMachineSnapshot as ac, transitionNode as ad, getTransitionResult as ae, hasEffect as af, createErrorPlatformEvent as ag, withActorSelf as ah, resolveActionsWithContext as ai, takeSpawnAllocationCounters as aj, mergeActorIdCounters as ak, createSpawnEffect as al, initialMicrostep as am, toStatePath as an, isStateId as ao, getStateNodeByPath as ap, getPersistedSnapshot as aq, createRemoteActorRef as ar, resolveReferencedActor as as, createInvokeTimeoutEvent as at, parseGeneratedActorId as au, ACTOR_REF_TYPE as av, hasAmbientInspector as aw, getProperAncestors as ax, isRemoteActorRef as ay, getActorIdPrefix as az, createSubscriptionLogic as b, createActor as c, getNextSnapshot as d, isMachineSnapshot as e, getStateNodes as f, getInitialSnapshot as g, getAllOwnEventDescriptors as h, isAtomicStateNode as i, matchesState as j, checkStateIn as k, listenerLogic as l, matchesEventDescriptor as m, pathToStateValue as n, toObserver as o, parseDelayToMilliseconds as p, executeEffects as q, isBuiltInExecutableAction as r, subscriptionLogic as s, toArray as t, deliverEvent as u, runStep as v, stopActor as w, terminateActor as x, createInitEvent as y, createCustomEffect as z };
5866
+ export { createInvokeTimeoutEventId as $, Actor as A, createCustomEffect as B, XSTATE_LOGIC_EFFECT_START as C, XSTATE_LOGIC_EFFECT_RESOLVE as D, XSTATE_LOGIC_EFFECT_REJECT as E, finalizeTransitionResult as F, createEmitEffect as G, createSendToEffect as H, XSTATE_INIT as I, withActorScope as J, XSTATE_TIMER as K, isLazyActorScope as L, resolveRegisteredActorSource as M, allocateChildId as N, assertChildIdFree as O, reserveChildId as P, mapValues as Q, createInvokeId as R, STATE_DELIMITER as S, getDelayedTransitions as T, getEventDescriptorKey as U, getCandidates as V, evaluateCandidate as W, XSTATE_STOP as X, formatTransition as Y, NULL_EVENT as Z, toTransitionConfigArray as _, createListenerLogic as a, matchesActorSession as a0, formatRouteTransitions as a1, resolveStateValue as a2, getAllStateNodes as a3, createMachineSnapshot as a4, isInFinalState as a5, createInertActorScope as a6, setInertActorScopeSnapshot as a7, beginSpawnAllocation as a8, attachSnapshotActorRef as a9, getActorIdPrefix as aA, getAllOwnEvents as aB, matchesEvent as aC, encodeAddressSegment as aD, getRootActorId as aE, RUNTIME_OPERATIONS as aF, withSystemInspector as aG, getSnapshotActorRef as aH, withExecutionIdentity as aI, macrostep as aa, isInertActorScope as ab, setSnapshotActorRef as ac, cloneMachineSnapshot as ad, transitionNode as ae, getTransitionResult as af, hasEffect as ag, createErrorPlatformEvent as ah, withActorSelf as ai, resolveActionsWithContext as aj, takeSpawnAllocationCounters as ak, mergeActorIdCounters as al, createSpawnEffect as am, initialMicrostep as an, toStatePath as ao, isStateId as ap, getStateNodeByPath as aq, getPersistedSnapshot as ar, createRemoteActorRef as as, resolveReferencedActor as at, createInvokeTimeoutEvent as au, parseGeneratedActorId as av, ACTOR_REF_TYPE as aw, hasAmbientInspector as ax, getProperAncestors as ay, isRemoteActorRef as az, createSubscriptionLogic as b, createActor as c, getNextSnapshot as d, isMachineSnapshot as e, getStateNodes as f, getInitialSnapshot as g, getAllOwnEventDescriptors as h, isAtomicStateNode as i, matchesState as j, checkStateIn as k, listenerLogic as l, matchesEventDescriptor as m, pathToStateValue as n, toObserver as o, parseDelayToMilliseconds as p, executeEffects as q, isBuiltInExecutableAction as r, subscriptionLogic as s, toArray as t, deliverEvent as u, runStep as v, stopActor as w, terminateActor as x, createInitEvent as y, createDeadLetterEffect as z };