xstate 6.0.0-alpha.63 → 6.0.0-alpha.64

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 (50) hide show
  1. package/README.md +18 -1
  2. package/dist/{createActor-eba8226e.cjs.js → createActor-29adb8a4.cjs.js} +33 -5
  3. package/dist/{createActor-f71670cf.development.cjs.js → createActor-521c8805.development.cjs.js} +33 -5
  4. package/dist/{createActor-523a98c7.esm.js → createActor-8493caa9.esm.js} +29 -6
  5. package/dist/{createActor-48f753a9.development.esm.js → createActor-bd2527dc.development.esm.js} +29 -6
  6. package/dist/declarations/src/SimulatedClock.d.ts +1 -1
  7. package/dist/declarations/src/createMachine.d.ts +3 -3
  8. package/dist/declarations/src/durable/index.d.ts +13 -0
  9. package/dist/declarations/src/index.d.ts +2 -1
  10. package/dist/declarations/src/setup.d.ts +152 -15
  11. package/dist/declarations/src/systemTransition.d.ts +103 -0
  12. package/dist/declarations/src/types.d.ts +3 -3
  13. package/dist/declarations/src/types.v6.d.ts +12 -4
  14. package/dist/{effectDescriptor-8c87a3e7.development.cjs.js → effectDescriptor-62b53c6d.development.cjs.js} +1 -1
  15. package/dist/{effectDescriptor-bc9e3e81.cjs.js → effectDescriptor-6dbc400a.cjs.js} +1 -1
  16. package/dist/{effectDescriptor-ad75e430.esm.js → effectDescriptor-85ea06c9.esm.js} +1 -1
  17. package/dist/{effectDescriptor-eadf1b25.development.esm.js → effectDescriptor-f76948fc.development.esm.js} +1 -1
  18. package/dist/{index-83f11f07.cjs.js → index-2afc57c3.development.cjs.js} +9 -2
  19. package/dist/{index-3cb56f46.development.cjs.js → index-5587e13b.cjs.js} +9 -2
  20. package/dist/{index-2a4be1f2.development.esm.js → index-90ebf5ae.development.esm.js} +9 -2
  21. package/dist/{index-211a5dce.esm.js → index-b0dc2b39.esm.js} +9 -2
  22. package/dist/xstate-actors.cjs.js +2 -2
  23. package/dist/xstate-actors.development.cjs.js +2 -2
  24. package/dist/xstate-actors.development.esm.js +2 -2
  25. package/dist/xstate-actors.esm.js +2 -2
  26. package/dist/xstate-actors.umd.min.js +1 -1
  27. package/dist/xstate-actors.umd.min.js.map +1 -1
  28. package/dist/xstate-durable.cjs.js +36 -4
  29. package/dist/xstate-durable.development.cjs.js +36 -4
  30. package/dist/xstate-durable.development.esm.js +36 -4
  31. package/dist/xstate-durable.esm.js +36 -4
  32. package/dist/xstate-durable.umd.min.js +1 -1
  33. package/dist/xstate-durable.umd.min.js.map +1 -1
  34. package/dist/xstate-graph.cjs.js +2 -2
  35. package/dist/xstate-graph.development.cjs.js +2 -2
  36. package/dist/xstate-graph.development.esm.js +2 -2
  37. package/dist/xstate-graph.esm.js +2 -2
  38. package/dist/xstate-validation.cjs.js +1 -1
  39. package/dist/xstate-validation.development.cjs.js +1 -1
  40. package/dist/xstate-validation.development.esm.js +1 -1
  41. package/dist/xstate-validation.esm.js +1 -1
  42. package/dist/xstate.cjs.js +842 -35
  43. package/dist/xstate.cjs.mjs +3 -0
  44. package/dist/xstate.development.cjs.js +842 -35
  45. package/dist/xstate.development.cjs.mjs +3 -0
  46. package/dist/xstate.development.esm.js +842 -38
  47. package/dist/xstate.esm.js +842 -38
  48. package/dist/xstate.umd.min.js +1 -1
  49. package/dist/xstate.umd.min.js.map +1 -1
  50. package/package.json +1 -1
package/README.md CHANGED
@@ -17,12 +17,29 @@ XState is a state management and orchestration solution for JavaScript and TypeS
17
17
 
18
18
  It uses event-driven programming, state machines, statecharts, and the actor model to handle complex logic in predictable, robust, and visual ways. XState provides a powerful and flexible way to manage application and workflow state by allowing developers to model logic as actors and state machines.
19
19
 
20
+ <!-- experimental whole-system transitions from packages/core/src/systemTransition.ts -->
21
+
22
+ For pure actor-system simulation, `initialSystemTransition`, `systemTransition`
23
+ and `advanceSystemTime` return an immutable system snapshot and external effects
24
+ as data. Branch or replay actors, messages and virtual timers without starting live
25
+ actors. See [pure system transitions](../../docs/system-transitions.md).
26
+
20
27
  <!-- durable execution and checkpoint restoration from packages/core/src/durable/index.ts -->
21
28
 
22
29
  For durable hosts, the experimental `xstate/durable` entry point provides
23
30
  `createDurable`. Resume a checkpoint with `execution.restore(persistedSnapshot)`
24
31
  and execute the returned effects to restart active embedded children and pending
25
- timers without replaying entry actions. See [durable execution](../../docs/durable-execution.md).
32
+ timers without replaying entry actions. Await `executeEffects()` before persisting
33
+ to retain accepted timer deadlines. The host handles root error snapshots;
34
+ `run()` rejects with the root error. See [durable execution](../../docs/durable-execution.md).
35
+
36
+ <!-- typed inline invocation from packages/core/src/setup.ts -->
37
+
38
+ Use `s.createInvoke({ src, input, onDone })` inline in `s.createMachine(...)` for an actor used in one state. It infers the actor's input and output and the enclosing state's narrowed context without registering that actor in `setup.actors`. See [typed inline invokes](../../docs/invoke.md#typed-inline-invokes).
39
+
40
+ Pass an async function directly as `src`, with `schemas.input`, `schemas.output`, and `schemas.error` on the same invoke. Output also infers from the async return when its schema is omitted. Existing logic values use their own schemas.
41
+
42
+ The helper requires input for actors whose input excludes `undefined`, and checks child IDs and source compatibility against `schemas.children` declared in the setup or machine.
26
43
 
27
44
  For flat finite state machines, `xstate/fsm` provides a tiny pure transition
28
45
  table with context and TypeScript support:
@@ -183,6 +183,20 @@ function reportUnhandledError(err) {
183
183
 
184
184
  const symbolObservable = (() => typeof Symbol === 'function' && Symbol.observable || '@@observable')();
185
185
 
186
+ // Runtime metadata stays outside pure snapshots. Timer objects survive unrelated
187
+ // transitions; a cancelled/replaced timer gets a new object and a new deadline.
188
+ const starts = new WeakMap();
189
+
190
+ /** @internal */
191
+ function getTimerStart(timer) {
192
+ return starts.get(timer) ?? timer.startedAt;
193
+ }
194
+
195
+ /** @internal */
196
+ function recordTimerStart(timer, startedAt) {
197
+ starts.set(timer, startedAt);
198
+ }
199
+
186
200
  function assertSendToEvent(event) {
187
201
  if (typeof event === 'string') {
188
202
  throw new Error(`Only event objects may be used with sendTo`);
@@ -240,6 +254,9 @@ function resolveRegisteredActorSource(actors, logic) {
240
254
  return cache.get(logic);
241
255
  }
242
256
 
257
+ /** Static scheduling metadata on actor definitions, never on live actors. @internal */
258
+ const systemLogicMetadata = Symbol('xstate.systemLogicMetadata');
259
+
243
260
  const subscriptions = /* #__PURE__ */new WeakMap();
244
261
 
245
262
  /**
@@ -258,7 +275,7 @@ id) {
258
275
  error: undefined,
259
276
  input
260
277
  }, []];
261
- return {
278
+ const logic = {
262
279
  id,
263
280
  start: (state, {
264
281
  self,
@@ -322,6 +339,12 @@ id) {
322
339
  getPersistedSnapshot: snapshot => snapshot,
323
340
  restoreSnapshot: snapshot => snapshot
324
341
  };
342
+ Object.defineProperty(logic, systemLogicMetadata, {
343
+ value: {
344
+ kind: id
345
+ }
346
+ });
347
+ return logic;
325
348
  }
326
349
 
327
350
  /**
@@ -4052,7 +4075,7 @@ function getPersistedSnapshot(snapshot, options) {
4052
4075
  // readings (a simulated clock, a monotonic counter) are meaningless in any
4053
4076
  // other process, and restoring them under the wall clock would fire every
4054
4077
  // pending delay instantly. Pure-transition snapshots have no local
4055
- // schedule and persist no timestamp.
4078
+ // schedule; durable executions record an accepted start separately.
4056
4079
  const scheduledTimers = snapshotActor?.system?._clock?.now ? undefined : snapshotActor?.system?._snapshot?._scheduledTimers;
4057
4080
  for (const id in timers) {
4058
4081
  const timer = timers[id];
@@ -4083,10 +4106,10 @@ function getPersistedSnapshot(snapshot, options) {
4083
4106
  // deadline. Derived from dueAt, not the scheduling moment, so repeated
4084
4107
  // persist/restore cycles keep the same deadline. Without a live schedule
4085
4108
  // (a restored-but-never-started actor, a pure-transition snapshot) the
4086
- // timer's carried-in start — which only a wall-clock actor ever stamped —
4087
- // passes through, so re-persisting cannot push the deadline back.
4109
+ // timer's accepted durable start or carried-in start passes through,
4110
+ // so re-persisting cannot push the deadline back.
4088
4111
  const scheduled = scheduledTimers?.[`${snapshotActor.sessionId}.${id}`];
4089
- const startedAt = scheduled ? scheduled.dueAt - timer.delay : timer.startedAt;
4112
+ const startedAt = scheduled ? scheduled.dueAt - timer.delay : getTimerStart(timer);
4090
4113
  timersJson[id] = {
4091
4114
  id: timer.id,
4092
4115
  delay: timer.delay,
@@ -6252,7 +6275,9 @@ exports.cloneMachineSnapshot = cloneMachineSnapshot;
6252
6275
  exports.createActor = createActor;
6253
6276
  exports.createCustomEffect = createCustomEffect;
6254
6277
  exports.createDeadLetterEffect = createDeadLetterEffect;
6278
+ exports.createDoneActorEvent = createDoneActorEvent;
6255
6279
  exports.createEmitEffect = createEmitEffect;
6280
+ exports.createErrorActorEvent = createErrorActorEvent;
6256
6281
  exports.createErrorPlatformEvent = createErrorPlatformEvent;
6257
6282
  exports.createInertActorScope = createInertActorScope;
6258
6283
  exports.createInitEvent = createInitEvent;
@@ -6287,6 +6312,7 @@ exports.getRootActorId = getRootActorId;
6287
6312
  exports.getSnapshotActorRef = getSnapshotActorRef;
6288
6313
  exports.getStateNodeByPath = getStateNodeByPath;
6289
6314
  exports.getStateNodes = getStateNodes;
6315
+ exports.getTimerStart = getTimerStart;
6290
6316
  exports.getTransitionResult = getTransitionResult;
6291
6317
  exports.hasAmbientInspector = hasAmbientInspector;
6292
6318
  exports.hasEffect = hasEffect;
@@ -6310,6 +6336,7 @@ exports.mergeActorIdCounters = mergeActorIdCounters;
6310
6336
  exports.parseDelayToMilliseconds = parseDelayToMilliseconds;
6311
6337
  exports.parseGeneratedActorId = parseGeneratedActorId;
6312
6338
  exports.pathToStateValue = pathToStateValue;
6339
+ exports.recordTimerStart = recordTimerStart;
6313
6340
  exports.reserveChildId = reserveChildId;
6314
6341
  exports.resolveActionsWithContext = resolveActionsWithContext;
6315
6342
  exports.resolveReferencedActor = resolveReferencedActor;
@@ -6320,6 +6347,7 @@ exports.setInertActorScopeSnapshot = setInertActorScopeSnapshot;
6320
6347
  exports.setSnapshotActorRef = setSnapshotActorRef;
6321
6348
  exports.stopActor = stopActor;
6322
6349
  exports.subscriptionLogic = subscriptionLogic;
6350
+ exports.systemLogicMetadata = systemLogicMetadata;
6323
6351
  exports.takeSpawnAllocationCounters = takeSpawnAllocationCounters;
6324
6352
  exports.terminateActor = terminateActor;
6325
6353
  exports.toArray = toArray;
@@ -183,6 +183,20 @@ function reportUnhandledError(err) {
183
183
 
184
184
  const symbolObservable = (() => typeof Symbol === 'function' && Symbol.observable || '@@observable')();
185
185
 
186
+ // Runtime metadata stays outside pure snapshots. Timer objects survive unrelated
187
+ // transitions; a cancelled/replaced timer gets a new object and a new deadline.
188
+ const starts = new WeakMap();
189
+
190
+ /** @internal */
191
+ function getTimerStart(timer) {
192
+ return starts.get(timer) ?? timer.startedAt;
193
+ }
194
+
195
+ /** @internal */
196
+ function recordTimerStart(timer, startedAt) {
197
+ starts.set(timer, startedAt);
198
+ }
199
+
186
200
  function assertSendToEvent(event) {
187
201
  if (typeof event === 'string') {
188
202
  throw new Error(// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
@@ -241,6 +255,9 @@ function resolveRegisteredActorSource(actors, logic) {
241
255
  return cache.get(logic);
242
256
  }
243
257
 
258
+ /** Static scheduling metadata on actor definitions, never on live actors. @internal */
259
+ const systemLogicMetadata = Symbol('xstate.systemLogicMetadata');
260
+
244
261
  const subscriptions = /* #__PURE__ */new WeakMap();
245
262
 
246
263
  /**
@@ -259,7 +276,7 @@ id) {
259
276
  error: undefined,
260
277
  input
261
278
  }, []];
262
- return {
279
+ const logic = {
263
280
  id,
264
281
  start: (state, {
265
282
  self,
@@ -323,6 +340,12 @@ id) {
323
340
  getPersistedSnapshot: snapshot => snapshot,
324
341
  restoreSnapshot: snapshot => snapshot
325
342
  };
343
+ Object.defineProperty(logic, systemLogicMetadata, {
344
+ value: {
345
+ kind: id
346
+ }
347
+ });
348
+ return logic;
326
349
  }
327
350
 
328
351
  /**
@@ -4158,7 +4181,7 @@ function getPersistedSnapshot(snapshot, options) {
4158
4181
  // readings (a simulated clock, a monotonic counter) are meaningless in any
4159
4182
  // other process, and restoring them under the wall clock would fire every
4160
4183
  // pending delay instantly. Pure-transition snapshots have no local
4161
- // schedule and persist no timestamp.
4184
+ // schedule; durable executions record an accepted start separately.
4162
4185
  const scheduledTimers = snapshotActor?.system?._clock?.now ? undefined : snapshotActor?.system?._snapshot?._scheduledTimers;
4163
4186
  for (const id in timers) {
4164
4187
  const timer = timers[id];
@@ -4189,10 +4212,10 @@ function getPersistedSnapshot(snapshot, options) {
4189
4212
  // deadline. Derived from dueAt, not the scheduling moment, so repeated
4190
4213
  // persist/restore cycles keep the same deadline. Without a live schedule
4191
4214
  // (a restored-but-never-started actor, a pure-transition snapshot) the
4192
- // timer's carried-in start — which only a wall-clock actor ever stamped —
4193
- // passes through, so re-persisting cannot push the deadline back.
4215
+ // timer's accepted durable start or carried-in start passes through,
4216
+ // so re-persisting cannot push the deadline back.
4194
4217
  const scheduled = scheduledTimers?.[`${snapshotActor.sessionId}.${id}`];
4195
- const startedAt = scheduled ? scheduled.dueAt - timer.delay : timer.startedAt;
4218
+ const startedAt = scheduled ? scheduled.dueAt - timer.delay : getTimerStart(timer);
4196
4219
  timersJson[id] = {
4197
4220
  id: timer.id,
4198
4221
  delay: timer.delay,
@@ -6395,7 +6418,9 @@ exports.cloneMachineSnapshot = cloneMachineSnapshot;
6395
6418
  exports.createActor = createActor;
6396
6419
  exports.createCustomEffect = createCustomEffect;
6397
6420
  exports.createDeadLetterEffect = createDeadLetterEffect;
6421
+ exports.createDoneActorEvent = createDoneActorEvent;
6398
6422
  exports.createEmitEffect = createEmitEffect;
6423
+ exports.createErrorActorEvent = createErrorActorEvent;
6399
6424
  exports.createErrorPlatformEvent = createErrorPlatformEvent;
6400
6425
  exports.createInertActorScope = createInertActorScope;
6401
6426
  exports.createInitEvent = createInitEvent;
@@ -6430,6 +6455,7 @@ exports.getRootActorId = getRootActorId;
6430
6455
  exports.getSnapshotActorRef = getSnapshotActorRef;
6431
6456
  exports.getStateNodeByPath = getStateNodeByPath;
6432
6457
  exports.getStateNodes = getStateNodes;
6458
+ exports.getTimerStart = getTimerStart;
6433
6459
  exports.getTransitionResult = getTransitionResult;
6434
6460
  exports.hasAmbientInspector = hasAmbientInspector;
6435
6461
  exports.hasEffect = hasEffect;
@@ -6453,6 +6479,7 @@ exports.mergeActorIdCounters = mergeActorIdCounters;
6453
6479
  exports.parseDelayToMilliseconds = parseDelayToMilliseconds;
6454
6480
  exports.parseGeneratedActorId = parseGeneratedActorId;
6455
6481
  exports.pathToStateValue = pathToStateValue;
6482
+ exports.recordTimerStart = recordTimerStart;
6456
6483
  exports.reserveChildId = reserveChildId;
6457
6484
  exports.resolveActionsWithContext = resolveActionsWithContext;
6458
6485
  exports.resolveReferencedActor = resolveReferencedActor;
@@ -6463,6 +6490,7 @@ exports.setInertActorScopeSnapshot = setInertActorScopeSnapshot;
6463
6490
  exports.setSnapshotActorRef = setSnapshotActorRef;
6464
6491
  exports.stopActor = stopActor;
6465
6492
  exports.subscriptionLogic = subscriptionLogic;
6493
+ exports.systemLogicMetadata = systemLogicMetadata;
6466
6494
  exports.takeSpawnAllocationCounters = takeSpawnAllocationCounters;
6467
6495
  exports.terminateActor = terminateActor;
6468
6496
  exports.toArray = toArray;
@@ -181,6 +181,20 @@ function reportUnhandledError(err) {
181
181
 
182
182
  const symbolObservable = (() => typeof Symbol === 'function' && Symbol.observable || '@@observable')();
183
183
 
184
+ // Runtime metadata stays outside pure snapshots. Timer objects survive unrelated
185
+ // transitions; a cancelled/replaced timer gets a new object and a new deadline.
186
+ const starts = new WeakMap();
187
+
188
+ /** @internal */
189
+ function getTimerStart(timer) {
190
+ return starts.get(timer) ?? timer.startedAt;
191
+ }
192
+
193
+ /** @internal */
194
+ function recordTimerStart(timer, startedAt) {
195
+ starts.set(timer, startedAt);
196
+ }
197
+
184
198
  function assertSendToEvent(event) {
185
199
  if (typeof event === 'string') {
186
200
  throw new Error(`Only event objects may be used with sendTo`);
@@ -238,6 +252,9 @@ function resolveRegisteredActorSource(actors, logic) {
238
252
  return cache.get(logic);
239
253
  }
240
254
 
255
+ /** Static scheduling metadata on actor definitions, never on live actors. @internal */
256
+ const systemLogicMetadata = Symbol('xstate.systemLogicMetadata');
257
+
241
258
  const subscriptions = /* #__PURE__ */new WeakMap();
242
259
 
243
260
  /**
@@ -256,7 +273,7 @@ id) {
256
273
  error: undefined,
257
274
  input
258
275
  }, []];
259
- return {
276
+ const logic = {
260
277
  id,
261
278
  start: (state, {
262
279
  self,
@@ -320,6 +337,12 @@ id) {
320
337
  getPersistedSnapshot: snapshot => snapshot,
321
338
  restoreSnapshot: snapshot => snapshot
322
339
  };
340
+ Object.defineProperty(logic, systemLogicMetadata, {
341
+ value: {
342
+ kind: id
343
+ }
344
+ });
345
+ return logic;
323
346
  }
324
347
 
325
348
  /**
@@ -4050,7 +4073,7 @@ function getPersistedSnapshot(snapshot, options) {
4050
4073
  // readings (a simulated clock, a monotonic counter) are meaningless in any
4051
4074
  // other process, and restoring them under the wall clock would fire every
4052
4075
  // pending delay instantly. Pure-transition snapshots have no local
4053
- // schedule and persist no timestamp.
4076
+ // schedule; durable executions record an accepted start separately.
4054
4077
  const scheduledTimers = snapshotActor?.system?._clock?.now ? undefined : snapshotActor?.system?._snapshot?._scheduledTimers;
4055
4078
  for (const id in timers) {
4056
4079
  const timer = timers[id];
@@ -4081,10 +4104,10 @@ function getPersistedSnapshot(snapshot, options) {
4081
4104
  // deadline. Derived from dueAt, not the scheduling moment, so repeated
4082
4105
  // persist/restore cycles keep the same deadline. Without a live schedule
4083
4106
  // (a restored-but-never-started actor, a pure-transition snapshot) the
4084
- // timer's carried-in start — which only a wall-clock actor ever stamped —
4085
- // passes through, so re-persisting cannot push the deadline back.
4107
+ // timer's accepted durable start or carried-in start passes through,
4108
+ // so re-persisting cannot push the deadline back.
4086
4109
  const scheduled = scheduledTimers?.[`${snapshotActor.sessionId}.${id}`];
4087
- const startedAt = scheduled ? scheduled.dueAt - timer.delay : timer.startedAt;
4110
+ const startedAt = scheduled ? scheduled.dueAt - timer.delay : getTimerStart(timer);
4088
4111
  timersJson[id] = {
4089
4112
  id: timer.id,
4090
4113
  delay: timer.delay,
@@ -6228,4 +6251,4 @@ function createActor(logic, ...[options]) {
6228
6251
  return new Actor(logic, options);
6229
6252
  }
6230
6253
 
6231
- export { parseGeneratedActorId as $, attachSnapshotActorRef as A, macrostep as B, isInertActorScope as C, setSnapshotActorRef as D, cloneMachineSnapshot as E, transitionNode as F, getTransitionResult as G, hasEffect as H, createErrorPlatformEvent as I, withActorSelf as J, resolveActionsWithContext as K, takeSpawnAllocationCounters as L, mergeActorIdCounters as M, NULL_EVENT as N, createInitEvent as O, createSpawnEffect as P, initialMicrostep as Q, createStartEffect as R, STATE_DELIMITER as S, toStatePath as T, isStateId as U, getStateNodeByPath as V, getPersistedSnapshot as W, XSTATE_TIMER as X, createRemoteActorRef as Y, resolveReferencedActor as Z, createInvokeTimeoutEvent as _, allocateChildId as a, ACTOR_REF_TYPE as a0, createActor as a1, parseDelayToMilliseconds as a2, isAtomicStateNode as a3, ProcessingStatus as a4, isActorRefLike as a5, createListenerLogic as a6, createSubscriptionLogic as a7, listenerLogic as a8, subscriptionLogic as a9, getActorIdPrefix as aA, getAllOwnEvents as aB, matchesEvent as aC, encodeAddressSegment as aD, getRootActorId as aE, RUNTIME_OPERATIONS as aF, withSystemInspector as aG, createTimerEffect as aH, getSnapshotActorRef as aI, withExecutionIdentity as aJ, Actor as aa, isMachineSnapshot as ab, InfiniteTransitionError as ac, getAllOwnEventDescriptors as ad, matchesState as ae, checkStateIn as af, pathToStateValue as ag, toObserver as ah, executeEffects as ai, isBuiltInExecutableAction as aj, deliverEvent as ak, runStep as al, stopActor as am, terminateActor as an, XSTATE_STOP as ao, createCustomEffect as ap, XSTATE_LOGIC_EFFECT_START as aq, XSTATE_LOGIC_EFFECT_RESOLVE as ar, XSTATE_LOGIC_EFFECT_REJECT as as, finalizeTransitionResult as at, createEmitEffect as au, createSendToEffect as av, XSTATE_INIT as aw, hasAmbientInspector as ax, getProperAncestors as ay, isRemoteActorRef as az, assertChildIdFree as b, reserveChildId as c, mapValues as d, createInvokeId as e, getEventDescriptorKey as f, getDelayedTransitions as g, getCandidates as h, evaluateCandidate as i, formatTransition as j, toTransitionConfigArray as k, createInvokeTimeoutEventId as l, matchesEventDescriptor as m, matchesActorSession as n, formatRouteTransitions as o, resolveStateValue as p, getAllStateNodes as q, resolveRegisteredActorSource as r, getStateNodes as s, toArray as t, createMachineSnapshot as u, isInFinalState as v, createInertActorScope as w, setInertActorScopeSnapshot as x, createDeadLetterEffect as y, beginSpawnAllocation as z };
6254
+ export { parseGeneratedActorId as $, attachSnapshotActorRef as A, macrostep as B, isInertActorScope as C, setSnapshotActorRef as D, cloneMachineSnapshot as E, transitionNode as F, getTransitionResult as G, hasEffect as H, createErrorPlatformEvent as I, withActorSelf as J, resolveActionsWithContext as K, takeSpawnAllocationCounters as L, mergeActorIdCounters as M, NULL_EVENT as N, createInitEvent as O, createSpawnEffect as P, initialMicrostep as Q, createStartEffect as R, STATE_DELIMITER as S, toStatePath as T, isStateId as U, getStateNodeByPath as V, getPersistedSnapshot as W, XSTATE_TIMER as X, createRemoteActorRef as Y, resolveReferencedActor as Z, createInvokeTimeoutEvent as _, allocateChildId as a, ACTOR_REF_TYPE as a0, createActor as a1, parseDelayToMilliseconds as a2, isAtomicStateNode as a3, ProcessingStatus as a4, isActorRefLike as a5, encodeAddressSegment as a6, systemLogicMetadata as a7, getActorIdPrefix as a8, finalizeTransitionResult as a9, createSendToEffect as aA, XSTATE_INIT as aB, hasAmbientInspector as aC, getProperAncestors as aD, isRemoteActorRef as aE, getAllOwnEvents as aF, matchesEvent as aG, getRootActorId as aH, RUNTIME_OPERATIONS as aI, withSystemInspector as aJ, createTimerEffect as aK, getSnapshotActorRef as aL, withExecutionIdentity as aM, getTimerStart as aN, recordTimerStart as aO, createDoneActorEvent as aa, createErrorActorEvent as ab, isMachineSnapshot as ac, listenerLogic as ad, subscriptionLogic as ae, createListenerLogic as af, createSubscriptionLogic as ag, Actor as ah, InfiniteTransitionError as ai, getAllOwnEventDescriptors as aj, matchesState as ak, checkStateIn as al, pathToStateValue as am, toObserver as an, executeEffects as ao, isBuiltInExecutableAction as ap, deliverEvent as aq, runStep as ar, stopActor as as, terminateActor as at, XSTATE_STOP as au, createCustomEffect as av, XSTATE_LOGIC_EFFECT_START as aw, XSTATE_LOGIC_EFFECT_RESOLVE as ax, XSTATE_LOGIC_EFFECT_REJECT as ay, createEmitEffect as az, assertChildIdFree as b, reserveChildId as c, mapValues as d, createInvokeId as e, getEventDescriptorKey as f, getDelayedTransitions as g, getCandidates as h, evaluateCandidate as i, formatTransition as j, toTransitionConfigArray as k, createInvokeTimeoutEventId as l, matchesEventDescriptor as m, matchesActorSession as n, formatRouteTransitions as o, resolveStateValue as p, getAllStateNodes as q, resolveRegisteredActorSource as r, getStateNodes as s, toArray as t, createMachineSnapshot as u, isInFinalState as v, createInertActorScope as w, setInertActorScopeSnapshot as x, createDeadLetterEffect as y, beginSpawnAllocation as z };
@@ -181,6 +181,20 @@ function reportUnhandledError(err) {
181
181
 
182
182
  const symbolObservable = (() => typeof Symbol === 'function' && Symbol.observable || '@@observable')();
183
183
 
184
+ // Runtime metadata stays outside pure snapshots. Timer objects survive unrelated
185
+ // transitions; a cancelled/replaced timer gets a new object and a new deadline.
186
+ const starts = new WeakMap();
187
+
188
+ /** @internal */
189
+ function getTimerStart(timer) {
190
+ return starts.get(timer) ?? timer.startedAt;
191
+ }
192
+
193
+ /** @internal */
194
+ function recordTimerStart(timer, startedAt) {
195
+ starts.set(timer, startedAt);
196
+ }
197
+
184
198
  function assertSendToEvent(event) {
185
199
  if (typeof event === 'string') {
186
200
  throw new Error(// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
@@ -239,6 +253,9 @@ function resolveRegisteredActorSource(actors, logic) {
239
253
  return cache.get(logic);
240
254
  }
241
255
 
256
+ /** Static scheduling metadata on actor definitions, never on live actors. @internal */
257
+ const systemLogicMetadata = Symbol('xstate.systemLogicMetadata');
258
+
242
259
  const subscriptions = /* #__PURE__ */new WeakMap();
243
260
 
244
261
  /**
@@ -257,7 +274,7 @@ id) {
257
274
  error: undefined,
258
275
  input
259
276
  }, []];
260
- return {
277
+ const logic = {
261
278
  id,
262
279
  start: (state, {
263
280
  self,
@@ -321,6 +338,12 @@ id) {
321
338
  getPersistedSnapshot: snapshot => snapshot,
322
339
  restoreSnapshot: snapshot => snapshot
323
340
  };
341
+ Object.defineProperty(logic, systemLogicMetadata, {
342
+ value: {
343
+ kind: id
344
+ }
345
+ });
346
+ return logic;
324
347
  }
325
348
 
326
349
  /**
@@ -4156,7 +4179,7 @@ function getPersistedSnapshot(snapshot, options) {
4156
4179
  // readings (a simulated clock, a monotonic counter) are meaningless in any
4157
4180
  // other process, and restoring them under the wall clock would fire every
4158
4181
  // pending delay instantly. Pure-transition snapshots have no local
4159
- // schedule and persist no timestamp.
4182
+ // schedule; durable executions record an accepted start separately.
4160
4183
  const scheduledTimers = snapshotActor?.system?._clock?.now ? undefined : snapshotActor?.system?._snapshot?._scheduledTimers;
4161
4184
  for (const id in timers) {
4162
4185
  const timer = timers[id];
@@ -4187,10 +4210,10 @@ function getPersistedSnapshot(snapshot, options) {
4187
4210
  // deadline. Derived from dueAt, not the scheduling moment, so repeated
4188
4211
  // persist/restore cycles keep the same deadline. Without a live schedule
4189
4212
  // (a restored-but-never-started actor, a pure-transition snapshot) the
4190
- // timer's carried-in start — which only a wall-clock actor ever stamped —
4191
- // passes through, so re-persisting cannot push the deadline back.
4213
+ // timer's accepted durable start or carried-in start passes through,
4214
+ // so re-persisting cannot push the deadline back.
4192
4215
  const scheduled = scheduledTimers?.[`${snapshotActor.sessionId}.${id}`];
4193
- const startedAt = scheduled ? scheduled.dueAt - timer.delay : timer.startedAt;
4216
+ const startedAt = scheduled ? scheduled.dueAt - timer.delay : getTimerStart(timer);
4194
4217
  timersJson[id] = {
4195
4218
  id: timer.id,
4196
4219
  delay: timer.delay,
@@ -6371,4 +6394,4 @@ function createActor(logic, ...[options]) {
6371
6394
  return new Actor(logic, options);
6372
6395
  }
6373
6396
 
6374
- export { parseGeneratedActorId as $, attachSnapshotActorRef as A, macrostep as B, isInertActorScope as C, setSnapshotActorRef as D, cloneMachineSnapshot as E, transitionNode as F, getTransitionResult as G, hasEffect as H, createErrorPlatformEvent as I, withActorSelf as J, resolveActionsWithContext as K, takeSpawnAllocationCounters as L, mergeActorIdCounters as M, NULL_EVENT as N, createInitEvent as O, createSpawnEffect as P, initialMicrostep as Q, createStartEffect as R, STATE_DELIMITER as S, toStatePath as T, isStateId as U, getStateNodeByPath as V, getPersistedSnapshot as W, XSTATE_TIMER as X, createRemoteActorRef as Y, resolveReferencedActor as Z, createInvokeTimeoutEvent as _, allocateChildId as a, ACTOR_REF_TYPE as a0, createActor as a1, parseDelayToMilliseconds as a2, isAtomicStateNode as a3, ProcessingStatus as a4, isActorRefLike as a5, createListenerLogic as a6, createSubscriptionLogic as a7, listenerLogic as a8, subscriptionLogic as a9, getActorIdPrefix as aA, getAllOwnEvents as aB, matchesEvent as aC, encodeAddressSegment as aD, getRootActorId as aE, RUNTIME_OPERATIONS as aF, withSystemInspector as aG, createTimerEffect as aH, getSnapshotActorRef as aI, withExecutionIdentity as aJ, Actor as aa, isMachineSnapshot as ab, InfiniteTransitionError as ac, getAllOwnEventDescriptors as ad, matchesState as ae, checkStateIn as af, pathToStateValue as ag, toObserver as ah, executeEffects as ai, isBuiltInExecutableAction as aj, deliverEvent as ak, runStep as al, stopActor as am, terminateActor as an, XSTATE_STOP as ao, createCustomEffect as ap, XSTATE_LOGIC_EFFECT_START as aq, XSTATE_LOGIC_EFFECT_RESOLVE as ar, XSTATE_LOGIC_EFFECT_REJECT as as, finalizeTransitionResult as at, createEmitEffect as au, createSendToEffect as av, XSTATE_INIT as aw, hasAmbientInspector as ax, getProperAncestors as ay, isRemoteActorRef as az, assertChildIdFree as b, reserveChildId as c, mapValues as d, createInvokeId as e, getEventDescriptorKey as f, getDelayedTransitions as g, getCandidates as h, evaluateCandidate as i, formatTransition as j, toTransitionConfigArray as k, createInvokeTimeoutEventId as l, matchesEventDescriptor as m, matchesActorSession as n, formatRouteTransitions as o, resolveStateValue as p, getAllStateNodes as q, resolveRegisteredActorSource as r, getStateNodes as s, toArray as t, createMachineSnapshot as u, isInFinalState as v, createInertActorScope as w, setInertActorScopeSnapshot as x, createDeadLetterEffect as y, beginSpawnAllocation as z };
6397
+ export { parseGeneratedActorId as $, attachSnapshotActorRef as A, macrostep as B, isInertActorScope as C, setSnapshotActorRef as D, cloneMachineSnapshot as E, transitionNode as F, getTransitionResult as G, hasEffect as H, createErrorPlatformEvent as I, withActorSelf as J, resolveActionsWithContext as K, takeSpawnAllocationCounters as L, mergeActorIdCounters as M, NULL_EVENT as N, createInitEvent as O, createSpawnEffect as P, initialMicrostep as Q, createStartEffect as R, STATE_DELIMITER as S, toStatePath as T, isStateId as U, getStateNodeByPath as V, getPersistedSnapshot as W, XSTATE_TIMER as X, createRemoteActorRef as Y, resolveReferencedActor as Z, createInvokeTimeoutEvent as _, allocateChildId as a, ACTOR_REF_TYPE as a0, createActor as a1, parseDelayToMilliseconds as a2, isAtomicStateNode as a3, ProcessingStatus as a4, isActorRefLike as a5, encodeAddressSegment as a6, systemLogicMetadata as a7, getActorIdPrefix as a8, finalizeTransitionResult as a9, createSendToEffect as aA, XSTATE_INIT as aB, hasAmbientInspector as aC, getProperAncestors as aD, isRemoteActorRef as aE, getAllOwnEvents as aF, matchesEvent as aG, getRootActorId as aH, RUNTIME_OPERATIONS as aI, withSystemInspector as aJ, createTimerEffect as aK, getSnapshotActorRef as aL, withExecutionIdentity as aM, getTimerStart as aN, recordTimerStart as aO, createDoneActorEvent as aa, createErrorActorEvent as ab, isMachineSnapshot as ac, listenerLogic as ad, subscriptionLogic as ae, createListenerLogic as af, createSubscriptionLogic as ag, Actor as ah, InfiniteTransitionError as ai, getAllOwnEventDescriptors as aj, matchesState as ak, checkStateIn as al, pathToStateValue as am, toObserver as an, executeEffects as ao, isBuiltInExecutableAction as ap, deliverEvent as aq, runStep as ar, stopActor as as, terminateActor as at, XSTATE_STOP as au, createCustomEffect as av, XSTATE_LOGIC_EFFECT_START as aw, XSTATE_LOGIC_EFFECT_RESOLVE as ax, XSTATE_LOGIC_EFFECT_REJECT as ay, createEmitEffect as az, assertChildIdFree as b, reserveChildId as c, mapValues as d, createInvokeId as e, getEventDescriptorKey as f, getDelayedTransitions as g, getCandidates as h, evaluateCandidate as i, formatTransition as j, toTransitionConfigArray as k, createInvokeTimeoutEventId as l, matchesEventDescriptor as m, matchesActorSession as n, formatRouteTransitions as o, resolveStateValue as p, getAllStateNodes as q, resolveRegisteredActorSource as r, getStateNodes as s, toArray as t, createMachineSnapshot as u, isInFinalState as v, createInertActorScope as w, setInertActorScopeSnapshot as x, createDeadLetterEffect as y, beginSpawnAllocation as z };
@@ -7,10 +7,10 @@ export interface SimulatedClock extends Clock {
7
7
  }
8
8
  export declare class SimulatedClock implements SimulatedClock {
9
9
  private timeouts;
10
+ private readonly deadlines;
10
11
  private _now;
11
12
  private _id;
12
13
  private _flushing;
13
- private _flushingInvalidated;
14
14
  now(): number;
15
15
  private getId;
16
16
  setTimeout(fn: (...args: any[]) => void, timeout: number): number;
@@ -1,6 +1,6 @@
1
1
  import { StandardSchemaV1 } from "./schema.types.js";
2
2
  import { StateMachine } from "./StateMachine.js";
3
- import { AnyActorRef, EventObject, AnyEventObject, Cast, MachineContext, ProvidedActor, StateValueFromStateSchema, ToChildren, MetaObject, StateSchema, DoNotInfer, RoutableStateId, Compute } from "./types.js";
3
+ import { AnyActorRef, AnyStateMachine, EventObject, AnyEventObject, Cast, MachineContext, ProvidedActor, StateValueFromStateSchema, ToChildren, MetaObject, StateSchema, DoNotInfer, RoutableStateId, Compute } from "./types.js";
4
4
  import { ChildCompletionEvents, Sources, DelayMapFromNames, InferChildren, InferMachineInput, InferOutput, SchemaOrConfigOutput, InferEvents, InferInternalEvents, Next_MachineConfig, Next_StateNodeConfig, ValidateDelayReferences, ValidateEventDescriptors, ValidateHistoryDefaults, ValidateStateTargets, ValidateTopLevelFinalOutputs, WidenLiterals, WithDefault } from "./types.v6.js";
5
5
  type MergeChildren<TChildren extends Record<string, AnyActorRef | undefined>, TActor extends ProvidedActor> = [keyof TChildren] extends [never] ? Compute<ToChildren<TActor>> : Compute<TChildren>;
6
6
  type MachineIdentity<TConfig> = {
@@ -60,7 +60,7 @@ export declare function createMachine<TContextSchema extends StandardSchemaV1, c
60
60
  context: TContextSchema;
61
61
  children?: TChildrenSchemaMap;
62
62
  };
63
- } & ValidateTopLevelFinalOutputs<TSS, InferOutput<TContextSchema, MachineContext>, InferEvents<TEventSchemaMap> | InferInternalEvents<TInternalEventSchemaMap>>): StateMachine<InferOutput<TContextSchema, MachineContext>, (InferEvents<TEventSchemaMap> | InferInternalEvents<TInternalEventSchemaMap>) | ([RoutableStateId<TSS>] extends [never] ? never : {
63
+ } & ValidateTopLevelFinalOutputs<TSS, InferOutput<TContextSchema, MachineContext>, InferEvents<TEventSchemaMap> | InferInternalEvents<TInternalEventSchemaMap>>): [TSS] extends [never] ? AnyStateMachine : StateMachine<InferOutput<TContextSchema, MachineContext>, (InferEvents<TEventSchemaMap> | InferInternalEvents<TInternalEventSchemaMap>) | ([RoutableStateId<TSS>] extends [never] ? never : {
64
64
  type: 'xstate.route';
65
65
  to: RoutableStateId<TSS>;
66
66
  }), Cast<MergeChildren<InferChildren<TChildrenSchemaMap>, TActor>, Record<string, AnyActorRef | undefined>>, StateValueFromStateSchema<TSS>, TTag & string, InferMachineInput<TInputSchema>, SchemaOrConfigOutput<TOutputSchema, TSS>, WithDefault<InferEvents<TEmittedSchemaMap>, AnyEventObject>, InferOutput<TMetaSchema, MetaObject>, // TMeta
@@ -78,7 +78,7 @@ export declare function createMachine<TContext extends MachineContext = never, c
78
78
  input: InferOutput<TInputSchema, unknown>;
79
79
  self: any;
80
80
  }) => TContext);
81
- } & ValidateTopLevelFinalOutputs<TSS, WidenLiterals<TContext>, InferEvents<TEventSchemaMap> | InferInternalEvents<TInternalEventSchemaMap>>): StateMachine<WidenLiterals<TContext>, (InferEvents<TEventSchemaMap> | InferInternalEvents<TInternalEventSchemaMap>) | ([RoutableStateId<TSS>] extends [never] ? never : {
81
+ } & ValidateTopLevelFinalOutputs<TSS, WidenLiterals<TContext>, InferEvents<TEventSchemaMap> | InferInternalEvents<TInternalEventSchemaMap>>): [TSS] extends [never] ? AnyStateMachine : StateMachine<WidenLiterals<TContext>, (InferEvents<TEventSchemaMap> | InferInternalEvents<TInternalEventSchemaMap>) | ([RoutableStateId<TSS>] extends [never] ? never : {
82
82
  type: 'xstate.route';
83
83
  to: RoutableStateId<TSS>;
84
84
  }), Cast<MergeChildren<InferChildren<TChildrenSchemaMap>, TActor>, Record<string, AnyActorRef | undefined>>, StateValueFromStateSchema<TSS>, TTag & string, InferMachineInput<TInputSchema>, SchemaOrConfigOutput<TOutputSchema, TSS>, WithDefault<InferEvents<TEmittedSchemaMap>, AnyEventObject>, InferOutput<TMetaSchema, MetaObject>, // TMeta
@@ -57,6 +57,19 @@ export interface DurableEffect<TEffect> extends DurableEffectMetadata {
57
57
  * @experimental
58
58
  */
59
59
  export interface DurableExecutionAdapter<TLogic extends AnyActorLogic> extends Partial<ActorSystemRuntime> {
60
+ /**
61
+ * Absolute clock in milliseconds, defaulting to Date.now. Checkpoints and
62
+ * resumed executions must use the same time origin. Replay hosts should
63
+ * return the recorded scheduling time rather than the replay's wall clock.
64
+ */
65
+ now?(): number;
66
+ /**
67
+ * Accepts a timer synchronously, or fulfills its promise when registration
68
+ * accepts the timer and its delay begins. For a new timer, that acceptance
69
+ * time is read through now() and persisted. Retried/restored timers retain
70
+ * their original deadline; hosts must honor it during registration.
71
+ */
72
+ scheduleTimer?: ActorSystemRuntime['scheduleTimer'];
60
73
  /**
61
74
  * Enqueues an event addressed to this execution's root while the durable
62
75
  * loop is parked in `waitForEvent()`. Use this when the host only owns the
@@ -12,9 +12,10 @@ export type { ActorValidationBoundary, ActorValidationEventOrigin, ActorValidati
12
12
  /** @experimental Used by framework integrations for development hot reloading; not part of the stable API. */
13
13
  export { hotSwapActorLogic as _hotSwapActorLogic } from "./hotSwap.js";
14
14
  export { createSystem, setup } from "./setup.js";
15
- export type { ActiveStateContext, AnySetupConfig, RootContextMarker, StrictSetupStateSchemas, StrictSetupStateTargetsFlag, StrictSetupStateTargetsMarker, RelativeSetupStateSchemasMarker, CurrentSetupStateSchemaMarker, SetupStateParentTypeMarker, SetupStateSchemasWithParentType, RootSetupStateSchemasMarker, WithRootSetupStateSchemas, SetupConfig, SetupReturn, SetupReturnFromConfig, SetupSchemas, SystemActorMap, SystemConfig, SystemRuntime, SetupStateSchema, SetupStateSchemas, SetupStateType } from "./setup.js";
15
+ export type { CreateAsyncInvokeConfig, CreateInvokeConfig, CreatedInvoke, ActiveStateContext, AnySetupConfig, RootContextMarker, StrictSetupStateSchemas, StrictSetupStateTargetsFlag, StrictSetupStateTargetsMarker, RelativeSetupStateSchemasMarker, CurrentSetupStateSchemaMarker, SetupStateParentTypeMarker, SetupStateSchemasWithParentType, RootSetupStateSchemasMarker, WithRootSetupStateSchemas, SetupConfig, SetupReturn, SetupReturnFromConfig, SetupSchemas, SystemActorMap, SystemConfig, SystemRuntime, SetupStateSchema, SetupStateSchemas, SetupStateType } from "./setup.js";
16
16
  export type { InspectionEvent, ActorInspectionEvent, TransitionInspectionEvent, ActionRecord, SentRecord } from "./inspection.js";
17
17
  export { SimulatedClock } from "./SimulatedClock.js";
18
+ export { initialSystemTransition, systemTransition, advanceSystemTime, type SystemLogic, type SystemSnapshot, type SystemActorState, type SystemActorReference, type SystemMessage, type SystemTimer, type SystemExternalEffect, type SystemEffectResult, type InitialSystemTransitionOptions } from "./systemTransition.js";
18
19
  /** @experimental Used by `@xstate/scxml`; not part of the stable API. */
19
20
  export { parseDelayToMilliseconds as _parseDelayToMilliseconds } from "./delay.js";
20
21
  /** @experimental Used by `@xstate/scxml`; not part of the stable API. */