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
@@ -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(`Only event objects may be used with sendTo`);
@@ -2002,13 +1890,10 @@ function matchesActorSession(event, snapshot, actorId) {
2002
1890
  if (!child || !('sessionId' in event)) {
2003
1891
  return true;
2004
1892
  }
2005
- if (isRemoteActorRef(child)) {
2006
- // Without a host-supplied incarnation token the runtime that owns the
2007
- // child is the authority on staleness; with one, a completion from a
2008
- // different incarnation of the same address is dropped here.
2009
- return child._incarnation === undefined || child._incarnation === event.sessionId;
2010
- }
2011
- return child.sessionId === event.sessionId;
1893
+ // One rule: a ref that knows its incarnation compares it; a remote handle
1894
+ // without a host-supplied token (sessionId undefined) defers to the
1895
+ // runtime that owns the child.
1896
+ return child.sessionId === undefined || child.sessionId === event.sessionId;
2012
1897
  }
2013
1898
  function normalizeLegacyInternalEvent(event, machine) {
2014
1899
  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') {
@@ -3205,11 +3090,7 @@ function macrostep(snapshot, event, actorScope, internalQueue, initialMicrosteps
3205
3090
  // The same staleness rule matchesActorSession applies to transition
3206
3091
  // selection: a completion from a different incarnation must not remove
3207
3092
  // the still-running child either.
3208
- if (isRemoteActorRef(child)) {
3209
- if (child._incarnation !== undefined && child._incarnation !== sessionId) {
3210
- return;
3211
- }
3212
- } else if (child.sessionId !== sessionId) {
3093
+ if (child.sessionId !== undefined && child.sessionId !== sessionId) {
3213
3094
  return;
3214
3095
  }
3215
3096
  const children = {
@@ -3501,6 +3382,118 @@ function evaluateCandidate(candidate, event, snapshot, stateNode, actorScope, se
3501
3382
  return true;
3502
3383
  }
3503
3384
 
3385
+ const emptySubscription = {
3386
+ unsubscribe() {}
3387
+ };
3388
+ const restoreHint = 'or restore this snapshot with embedded children on the runtime that owns them.';
3389
+
3390
+ /** @internal */
3391
+ function isRemoteActorRef(actorRef) {
3392
+ return actorRef._remote === true;
3393
+ }
3394
+
3395
+ /**
3396
+ * The lifecycle-only snapshot a remote handle exposes. `active` is accurate
3397
+ * by construction: a completion removes the child from its parent's
3398
+ * `children`, so a handle only exists while the child is presumed active,
3399
+ * and the terminal result arrives as a completion event instead of a
3400
+ * snapshot. Full snapshots are a co-location capability.
3401
+ */
3402
+ const remoteSnapshot = Object.freeze({
3403
+ status: 'active',
3404
+ output: undefined,
3405
+ error: undefined
3406
+ });
3407
+
3408
+ /**
3409
+ * Creates a location-transparent handle to an actor whose state lives with
3410
+ * another runtime. The handle is constructed from identity alone — no lookup
3411
+ * — and every send routes through the system's runtime; its state is not
3412
+ * synchronously readable.
3413
+ *
3414
+ * The surface is deliberately minimal: it covers every member the runtime
3415
+ * reaches for a restored child (send/_send, lifecycle via start/_stop and
3416
+ * system.stopActor, persistence, subscribe/on as inert subscriptions).
3417
+ * Members that only make sense for a co-located actor (public stop(),
3418
+ * select(), trigger) throw a descriptive error rather than being absent, so
3419
+ * calling one reports what went wrong instead of a bare TypeError. Observable
3420
+ * interop and _processingStatus are omitted entirely.
3421
+ *
3422
+ * @internal
3423
+ */
3424
+ function createRemoteActorRef(system, options) {
3425
+ const handle = {
3426
+ _remote: true,
3427
+ // Self-reference so context persistence recognizes the handle as an
3428
+ // actor reference instead of recursing into it.
3429
+ ref: undefined,
3430
+ id: options.id,
3431
+ address: options.address,
3432
+ src: options.src,
3433
+ registryKey: options.registryKey,
3434
+ // The host-supplied incarnation token, when present: the owner's
3435
+ // sessionId for this child, letting this side drop stale completions and
3436
+ // journaled sends name the intended incarnation. Without one the handle
3437
+ // does not know the child's incarnation and the owning runtime is the
3438
+ // authority on staleness.
3439
+ sessionId: options.incarnation,
3440
+ system,
3441
+ _parent: options.parent,
3442
+ // Round-trips through persistence verbatim (undefined stays undefined,
3443
+ // so re-persisting is byte-stable); a remote handle cannot act on it
3444
+ // locally.
3445
+ _syncSnapshot: options.syncSnapshot,
3446
+ send(event) {
3447
+ void system.sendEvent(undefined, ref, event);
3448
+ },
3449
+ _send(event) {
3450
+ 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}`);
3451
+ },
3452
+ getSnapshot() {
3453
+ return remoteSnapshot;
3454
+ },
3455
+ getPersistedSnapshot() {
3456
+ throw new Error(`Cannot persist remote actor '${options.address}' from here: its state lives with the runtime that owns it. Persist it there, ${restoreHint}`);
3457
+ },
3458
+ start() {},
3459
+ _stop() {},
3460
+ stop() {
3461
+ 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}`);
3462
+ },
3463
+ select() {
3464
+ 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}`);
3465
+ },
3466
+ get trigger() {
3467
+ 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.`);
3468
+ },
3469
+ // Observation is a co-location capability: a remote handle never emits,
3470
+ // so subscriptions are inert rather than errors — generic observers may
3471
+ // attach to any ref.
3472
+ subscribe() {
3473
+ return emptySubscription;
3474
+ },
3475
+ on() {
3476
+ return emptySubscription;
3477
+ },
3478
+ _isRunning() {
3479
+ return false;
3480
+ },
3481
+ // The same shape Actor.toJSON produces, so serialized snapshots carry
3482
+ // one actor-reference marker whether a child is co-located or remote.
3483
+ toJSON() {
3484
+ return {
3485
+ xstate$type: ACTOR_REF_TYPE,
3486
+ id: options.id,
3487
+ address: options.address,
3488
+ src: options.src
3489
+ };
3490
+ }
3491
+ };
3492
+ const ref = handle;
3493
+ handle.ref = ref;
3494
+ return ref;
3495
+ }
3496
+
3504
3497
  const emptySnapshotRecord = Object.freeze({});
3505
3498
  function compactSnapshotRecord(value) {
3506
3499
  if (value === emptySnapshotRecord) {
@@ -3680,10 +3673,12 @@ function getPersistedSnapshot(snapshot, options) {
3680
3673
  snapshot: child.getPersistedSnapshot(options)
3681
3674
  } : {
3682
3675
  remote: true,
3683
- // Round-trips verbatim: the host that owns the child injects the
3684
- // token; XState never stamps one (a local sessionId would make
3685
- // persisted snapshots nondeterministic across replays).
3686
- incarnation: child._incarnation
3676
+ // A remote handle's sessionId IS the host-supplied incarnation
3677
+ // token, round-tripped verbatim. A local child persisted by
3678
+ // address never stamps its own sessionId: that value is this
3679
+ // incarnation's, not a durable identity, and it would make
3680
+ // persisted snapshots nondeterministic across replays.
3681
+ incarnation: isRemoteActorRef(child) ? child.sessionId : undefined
3687
3682
  }),
3688
3683
  src: child.src,
3689
3684
  registryKey: child.registryKey,
@@ -4096,14 +4091,21 @@ async function runStep(actor, key, exec, sendSelf = event => void actor.system.s
4096
4091
  * @experimental
4097
4092
  */
4098
4093
  function deliverEvent(source, target, event) {
4094
+ assertEventCanBeSent(source, target, event);
4095
+ const runtimeTarget = target;
4096
+ runtimeTarget._lastSourceRef = source;
4097
+ runtimeTarget._send(event);
4098
+ }
4099
+
4100
+ /**
4101
+ * Ensures internal events cannot cross an actor boundary from an external
4102
+ * sender. Host runtimes must call this before taking ownership of delivery.
4103
+ */
4104
+ function assertEventCanBeSent(source, target, event) {
4099
4105
  const runtimeTarget = target;
4100
- // The same guard local delivery has always applied: internal events may
4101
- // only originate from the actor itself, whichever runtime delivers them.
4102
4106
  if (source !== target && runtimeTarget.logic?.isInternalEventType?.(event.type)) {
4103
4107
  throw new Error(`Internal event "${event.type}" cannot be sent to actor "${target.id}" from outside.`);
4104
4108
  }
4105
- runtimeTarget._lastSourceRef = source;
4106
- runtimeTarget._send(event);
4107
4109
  }
4108
4110
 
4109
4111
  /**
@@ -4165,6 +4167,32 @@ function createSystemId() {
4165
4167
  return `${systemIdPrefix}:${(nextSystemId++).toString(36)}`;
4166
4168
  }
4167
4169
 
4170
+ /**
4171
+ * The identity a durable execution pins on every system its transitions
4172
+ * create. Shared across all transitions (and replays) of one execution, so
4173
+ * session ids become a deterministic function of actor-creation order:
4174
+ * `<executionId>:0`, `<executionId>:1`, … A replayed execution re-creates
4175
+ * the same session ids, so journaled completion events (which carry the
4176
+ * producing incarnation's `sessionId`) still match the children the replay
4177
+ * re-creates.
4178
+ */
4179
+
4180
+ let ambientExecutionIdentity;
4181
+
4182
+ /** @internal Runs `fn` with systems it creates pinned to `identity`. */
4183
+ function withExecutionIdentity(identity, fn) {
4184
+ if (!identity) {
4185
+ return fn();
4186
+ }
4187
+ const previous = ambientExecutionIdentity;
4188
+ ambientExecutionIdentity = identity;
4189
+ try {
4190
+ return fn();
4191
+ } finally {
4192
+ ambientExecutionIdentity = previous;
4193
+ }
4194
+ }
4195
+
4168
4196
  /**
4169
4197
  * Derives the deterministic id prefix for a generated actor id from its actor
4170
4198
  * source: the registered source key when the source is a string, the logic's
@@ -4281,9 +4309,10 @@ function bookSessionId(system) {
4281
4309
 
4282
4310
  /** @internal Every operation of `ActorSystemRuntime`, for runtime wrappers. */
4283
4311
  const RUNTIME_OPERATIONS = ['spawnActor', 'startActor', 'stopActor', 'terminateActor', 'emitEvent', 'scheduleTimer', 'cancelTimer', 'cancelAllTimers', 'deadLetter'
4284
- // `runStep` and `sendEvent` are deliberately absent: durable executions
4285
- // wire them separately, since a step awaits other runtime operations and
4286
- // root-addressed sends are captured per batch.
4312
+ // `runLogic`, `runStep` and `sendEvent` are deliberately absent: durable
4313
+ // executions wire them separately, since logic bodies and steps await
4314
+ // other runtime operations and root-addressed sends are captured per
4315
+ // batch.
4287
4316
  ];
4288
4317
  const emptyScheduledTimers = Object.freeze({});
4289
4318
  function createScheduledTimerId(actor, id) {
@@ -4329,7 +4358,7 @@ class RuntimeSystem {
4329
4358
  }
4330
4359
  constructor(_rootActor, options) {
4331
4360
  this._rootActor = _rootActor;
4332
- this._identity = {
4361
+ this._identity = ambientExecutionIdentity ?? {
4333
4362
  systemId: createSystemId(),
4334
4363
  nextSessionId: 0
4335
4364
  };
@@ -4533,6 +4562,7 @@ class RuntimeSystem {
4533
4562
  terminateActor(actor, termination);
4534
4563
  }
4535
4564
  sendEvent(source, target, event) {
4565
+ assertEventCanBeSent(source, target, event);
4536
4566
  // Record for the inspection `sent[]` facet regardless of which runtime
4537
4567
  // delivers, so host runtimes keep inspection parity.
4538
4568
  this._recordSent(source, target, event);
@@ -4569,6 +4599,13 @@ class RuntimeSystem {
4569
4599
  }
4570
4600
  return runStep(actor, key, exec);
4571
4601
  }
4602
+ runLogic(actor, exec) {
4603
+ const override = this.runtime?.runLogic;
4604
+ if (override) {
4605
+ return override(actor, exec);
4606
+ }
4607
+ return exec();
4608
+ }
4572
4609
  scheduleTimer(source, id, delay) {
4573
4610
  const override = this.runtime?.scheduleTimer;
4574
4611
  if (override) {
@@ -5643,6 +5680,7 @@ exports.isInFinalState = isInFinalState;
5643
5680
  exports.isInertActorScope = isInertActorScope;
5644
5681
  exports.isLazyActorScope = isLazyActorScope;
5645
5682
  exports.isMachineSnapshot = isMachineSnapshot;
5683
+ exports.isRemoteActorRef = isRemoteActorRef;
5646
5684
  exports.isStateId = isStateId;
5647
5685
  exports.listenerLogic = listenerLogic;
5648
5686
  exports.macrostep = macrostep;
@@ -5673,3 +5711,4 @@ exports.toTransitionConfigArray = toTransitionConfigArray;
5673
5711
  exports.transitionNode = transitionNode;
5674
5712
  exports.withActorScope = withActorScope;
5675
5713
  exports.withActorSelf = withActorSelf;
5714
+ exports.withExecutionIdentity = withExecutionIdentity;