xstate 6.0.0-alpha.62 → 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 (52) hide show
  1. package/README.md +24 -0
  2. package/dist/{createActor-8dfa9b5c.cjs.js → createActor-29adb8a4.cjs.js} +72 -5
  3. package/dist/{createActor-6d6bfee1.development.cjs.js → createActor-521c8805.development.cjs.js} +72 -5
  4. package/dist/{createActor-f9b188f2.esm.js → createActor-8493caa9.esm.js} +66 -6
  5. package/dist/{createActor-55f62c08.development.esm.js → createActor-bd2527dc.development.esm.js} +66 -6
  6. package/dist/declarations/src/SimulatedClock.d.ts +1 -1
  7. package/dist/declarations/src/StateMachine.d.ts +1 -1
  8. package/dist/declarations/src/createMachine.d.ts +3 -3
  9. package/dist/declarations/src/durable/index.d.ts +25 -1
  10. package/dist/declarations/src/index.d.ts +2 -1
  11. package/dist/declarations/src/setup.d.ts +152 -15
  12. package/dist/declarations/src/systemTransition.d.ts +103 -0
  13. package/dist/declarations/src/types.d.ts +3 -3
  14. package/dist/declarations/src/types.v6.d.ts +12 -4
  15. package/dist/{effectDescriptor-a3ff2473.development.cjs.js → effectDescriptor-62b53c6d.development.cjs.js} +1 -1
  16. package/dist/{effectDescriptor-0a7315fa.cjs.js → effectDescriptor-6dbc400a.cjs.js} +1 -1
  17. package/dist/{effectDescriptor-35129133.esm.js → effectDescriptor-85ea06c9.esm.js} +1 -1
  18. package/dist/{effectDescriptor-5048c471.development.esm.js → effectDescriptor-f76948fc.development.esm.js} +1 -1
  19. package/dist/{index-ad40a951.cjs.js → index-2afc57c3.development.cjs.js} +9 -2
  20. package/dist/{index-05e9e83b.development.cjs.js → index-5587e13b.cjs.js} +9 -2
  21. package/dist/{index-eda79ddc.development.esm.js → index-90ebf5ae.development.esm.js} +9 -2
  22. package/dist/{index-e5f3a62b.esm.js → index-b0dc2b39.esm.js} +9 -2
  23. package/dist/xstate-actors.cjs.js +2 -2
  24. package/dist/xstate-actors.development.cjs.js +2 -2
  25. package/dist/xstate-actors.development.esm.js +2 -2
  26. package/dist/xstate-actors.esm.js +2 -2
  27. package/dist/xstate-actors.umd.min.js +1 -1
  28. package/dist/xstate-actors.umd.min.js.map +1 -1
  29. package/dist/xstate-durable.cjs.js +125 -31
  30. package/dist/xstate-durable.development.cjs.js +125 -31
  31. package/dist/xstate-durable.development.esm.js +125 -31
  32. package/dist/xstate-durable.esm.js +125 -31
  33. package/dist/xstate-durable.umd.min.js +1 -1
  34. package/dist/xstate-durable.umd.min.js.map +1 -1
  35. package/dist/xstate-graph.cjs.js +2 -2
  36. package/dist/xstate-graph.development.cjs.js +2 -2
  37. package/dist/xstate-graph.development.esm.js +2 -2
  38. package/dist/xstate-graph.esm.js +2 -2
  39. package/dist/xstate-graph.umd.min.js.map +1 -1
  40. package/dist/xstate-validation.cjs.js +1 -1
  41. package/dist/xstate-validation.development.cjs.js +1 -1
  42. package/dist/xstate-validation.development.esm.js +1 -1
  43. package/dist/xstate-validation.esm.js +1 -1
  44. package/dist/xstate.cjs.js +848 -37
  45. package/dist/xstate.cjs.mjs +3 -0
  46. package/dist/xstate.development.cjs.js +848 -37
  47. package/dist/xstate.development.cjs.mjs +3 -0
  48. package/dist/xstate.development.esm.js +848 -40
  49. package/dist/xstate.esm.js +848 -40
  50. package/dist/xstate.umd.min.js +1 -1
  51. package/dist/xstate.umd.min.js.map +1 -1
  52. package/package.json +1 -1
package/README.md CHANGED
@@ -17,6 +17,30 @@ 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
+
27
+ <!-- durable execution and checkpoint restoration from packages/core/src/durable/index.ts -->
28
+
29
+ For durable hosts, the experimental `xstate/durable` entry point provides
30
+ `createDurable`. Resume a checkpoint with `execution.restore(persistedSnapshot)`
31
+ and execute the returned effects to restart active embedded children and pending
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.
43
+
20
44
  For flat finite state machines, `xstate/fsm` provides a tiny pure transition
21
45
  table with context and TypeScript support:
22
46
 
@@ -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
  /**
@@ -1121,6 +1144,8 @@ function getBuiltInActionFields(action, args) {
1121
1144
  return undefined;
1122
1145
  }
1123
1146
  }
1147
+
1148
+ /** @internal Creates an actor-start effect, including for restored children. */
1124
1149
  function createStartEffect(actor) {
1125
1150
  const args = [actor];
1126
1151
  return {
@@ -1134,6 +1159,41 @@ function createStartEffect(actor) {
1134
1159
  id: actor.id
1135
1160
  };
1136
1161
  }
1162
+
1163
+ /** @internal Recreates a pending logical timer without re-entering its state. */
1164
+ function createTimerEffect(actorScope, timer, delay) {
1165
+ const source = actorScope.self;
1166
+ const options = {
1167
+ id: timer.id,
1168
+ delay
1169
+ };
1170
+ if (timer.type === '@xstate.raise') {
1171
+ return {
1172
+ kind: 'builtin',
1173
+ type: timer.type,
1174
+ source,
1175
+ event: timer.event,
1176
+ id: timer.id,
1177
+ delay,
1178
+ params: undefined,
1179
+ args: [actorScope, timer.event, options],
1180
+ exec: execRaiseEffect
1181
+ };
1182
+ }
1183
+ const target = timer.target === 'self' ? source : timer.target;
1184
+ return {
1185
+ kind: 'builtin',
1186
+ type: timer.type,
1187
+ source,
1188
+ target,
1189
+ event: timer.event,
1190
+ id: timer.id,
1191
+ delay,
1192
+ params: undefined,
1193
+ args: [actorScope, target, timer.event, options],
1194
+ exec: execSendToEffect
1195
+ };
1196
+ }
1137
1197
  function createSpawnEffect(actor) {
1138
1198
  const args = [actor];
1139
1199
  return {
@@ -4015,7 +4075,7 @@ function getPersistedSnapshot(snapshot, options) {
4015
4075
  // readings (a simulated clock, a monotonic counter) are meaningless in any
4016
4076
  // other process, and restoring them under the wall clock would fire every
4017
4077
  // pending delay instantly. Pure-transition snapshots have no local
4018
- // schedule and persist no timestamp.
4078
+ // schedule; durable executions record an accepted start separately.
4019
4079
  const scheduledTimers = snapshotActor?.system?._clock?.now ? undefined : snapshotActor?.system?._snapshot?._scheduledTimers;
4020
4080
  for (const id in timers) {
4021
4081
  const timer = timers[id];
@@ -4046,10 +4106,10 @@ function getPersistedSnapshot(snapshot, options) {
4046
4106
  // deadline. Derived from dueAt, not the scheduling moment, so repeated
4047
4107
  // persist/restore cycles keep the same deadline. Without a live schedule
4048
4108
  // (a restored-but-never-started actor, a pure-transition snapshot) the
4049
- // timer's carried-in start — which only a wall-clock actor ever stamped —
4050
- // 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.
4051
4111
  const scheduled = scheduledTimers?.[`${snapshotActor.sessionId}.${id}`];
4052
- const startedAt = scheduled ? scheduled.dueAt - timer.delay : timer.startedAt;
4112
+ const startedAt = scheduled ? scheduled.dueAt - timer.delay : getTimerStart(timer);
4053
4113
  timersJson[id] = {
4054
4114
  id: timer.id,
4055
4115
  delay: timer.delay,
@@ -6215,7 +6275,9 @@ exports.cloneMachineSnapshot = cloneMachineSnapshot;
6215
6275
  exports.createActor = createActor;
6216
6276
  exports.createCustomEffect = createCustomEffect;
6217
6277
  exports.createDeadLetterEffect = createDeadLetterEffect;
6278
+ exports.createDoneActorEvent = createDoneActorEvent;
6218
6279
  exports.createEmitEffect = createEmitEffect;
6280
+ exports.createErrorActorEvent = createErrorActorEvent;
6219
6281
  exports.createErrorPlatformEvent = createErrorPlatformEvent;
6220
6282
  exports.createInertActorScope = createInertActorScope;
6221
6283
  exports.createInitEvent = createInitEvent;
@@ -6227,7 +6289,9 @@ exports.createMachineSnapshot = createMachineSnapshot;
6227
6289
  exports.createRemoteActorRef = createRemoteActorRef;
6228
6290
  exports.createSendToEffect = createSendToEffect;
6229
6291
  exports.createSpawnEffect = createSpawnEffect;
6292
+ exports.createStartEffect = createStartEffect;
6230
6293
  exports.createSubscriptionLogic = createSubscriptionLogic;
6294
+ exports.createTimerEffect = createTimerEffect;
6231
6295
  exports.deliverEvent = deliverEvent;
6232
6296
  exports.encodeAddressSegment = encodeAddressSegment;
6233
6297
  exports.evaluateCandidate = evaluateCandidate;
@@ -6248,6 +6312,7 @@ exports.getRootActorId = getRootActorId;
6248
6312
  exports.getSnapshotActorRef = getSnapshotActorRef;
6249
6313
  exports.getStateNodeByPath = getStateNodeByPath;
6250
6314
  exports.getStateNodes = getStateNodes;
6315
+ exports.getTimerStart = getTimerStart;
6251
6316
  exports.getTransitionResult = getTransitionResult;
6252
6317
  exports.hasAmbientInspector = hasAmbientInspector;
6253
6318
  exports.hasEffect = hasEffect;
@@ -6271,6 +6336,7 @@ exports.mergeActorIdCounters = mergeActorIdCounters;
6271
6336
  exports.parseDelayToMilliseconds = parseDelayToMilliseconds;
6272
6337
  exports.parseGeneratedActorId = parseGeneratedActorId;
6273
6338
  exports.pathToStateValue = pathToStateValue;
6339
+ exports.recordTimerStart = recordTimerStart;
6274
6340
  exports.reserveChildId = reserveChildId;
6275
6341
  exports.resolveActionsWithContext = resolveActionsWithContext;
6276
6342
  exports.resolveReferencedActor = resolveReferencedActor;
@@ -6281,6 +6347,7 @@ exports.setInertActorScopeSnapshot = setInertActorScopeSnapshot;
6281
6347
  exports.setSnapshotActorRef = setSnapshotActorRef;
6282
6348
  exports.stopActor = stopActor;
6283
6349
  exports.subscriptionLogic = subscriptionLogic;
6350
+ exports.systemLogicMetadata = systemLogicMetadata;
6284
6351
  exports.takeSpawnAllocationCounters = takeSpawnAllocationCounters;
6285
6352
  exports.terminateActor = terminateActor;
6286
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
  /**
@@ -1131,6 +1154,8 @@ function getBuiltInActionFields(action, args) {
1131
1154
  return undefined;
1132
1155
  }
1133
1156
  }
1157
+
1158
+ /** @internal Creates an actor-start effect, including for restored children. */
1134
1159
  function createStartEffect(actor) {
1135
1160
  const args = [actor];
1136
1161
  return {
@@ -1144,6 +1169,41 @@ function createStartEffect(actor) {
1144
1169
  id: actor.id
1145
1170
  };
1146
1171
  }
1172
+
1173
+ /** @internal Recreates a pending logical timer without re-entering its state. */
1174
+ function createTimerEffect(actorScope, timer, delay) {
1175
+ const source = actorScope.self;
1176
+ const options = {
1177
+ id: timer.id,
1178
+ delay
1179
+ };
1180
+ if (timer.type === '@xstate.raise') {
1181
+ return {
1182
+ kind: 'builtin',
1183
+ type: timer.type,
1184
+ source,
1185
+ event: timer.event,
1186
+ id: timer.id,
1187
+ delay,
1188
+ params: undefined,
1189
+ args: [actorScope, timer.event, options],
1190
+ exec: execRaiseEffect
1191
+ };
1192
+ }
1193
+ const target = timer.target === 'self' ? source : timer.target;
1194
+ return {
1195
+ kind: 'builtin',
1196
+ type: timer.type,
1197
+ source,
1198
+ target,
1199
+ event: timer.event,
1200
+ id: timer.id,
1201
+ delay,
1202
+ params: undefined,
1203
+ args: [actorScope, target, timer.event, options],
1204
+ exec: execSendToEffect
1205
+ };
1206
+ }
1147
1207
  function createSpawnEffect(actor) {
1148
1208
  const args = [actor];
1149
1209
  return {
@@ -4121,7 +4181,7 @@ function getPersistedSnapshot(snapshot, options) {
4121
4181
  // readings (a simulated clock, a monotonic counter) are meaningless in any
4122
4182
  // other process, and restoring them under the wall clock would fire every
4123
4183
  // pending delay instantly. Pure-transition snapshots have no local
4124
- // schedule and persist no timestamp.
4184
+ // schedule; durable executions record an accepted start separately.
4125
4185
  const scheduledTimers = snapshotActor?.system?._clock?.now ? undefined : snapshotActor?.system?._snapshot?._scheduledTimers;
4126
4186
  for (const id in timers) {
4127
4187
  const timer = timers[id];
@@ -4152,10 +4212,10 @@ function getPersistedSnapshot(snapshot, options) {
4152
4212
  // deadline. Derived from dueAt, not the scheduling moment, so repeated
4153
4213
  // persist/restore cycles keep the same deadline. Without a live schedule
4154
4214
  // (a restored-but-never-started actor, a pure-transition snapshot) the
4155
- // timer's carried-in start — which only a wall-clock actor ever stamped —
4156
- // 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.
4157
4217
  const scheduled = scheduledTimers?.[`${snapshotActor.sessionId}.${id}`];
4158
- const startedAt = scheduled ? scheduled.dueAt - timer.delay : timer.startedAt;
4218
+ const startedAt = scheduled ? scheduled.dueAt - timer.delay : getTimerStart(timer);
4159
4219
  timersJson[id] = {
4160
4220
  id: timer.id,
4161
4221
  delay: timer.delay,
@@ -6358,7 +6418,9 @@ exports.cloneMachineSnapshot = cloneMachineSnapshot;
6358
6418
  exports.createActor = createActor;
6359
6419
  exports.createCustomEffect = createCustomEffect;
6360
6420
  exports.createDeadLetterEffect = createDeadLetterEffect;
6421
+ exports.createDoneActorEvent = createDoneActorEvent;
6361
6422
  exports.createEmitEffect = createEmitEffect;
6423
+ exports.createErrorActorEvent = createErrorActorEvent;
6362
6424
  exports.createErrorPlatformEvent = createErrorPlatformEvent;
6363
6425
  exports.createInertActorScope = createInertActorScope;
6364
6426
  exports.createInitEvent = createInitEvent;
@@ -6370,7 +6432,9 @@ exports.createMachineSnapshot = createMachineSnapshot;
6370
6432
  exports.createRemoteActorRef = createRemoteActorRef;
6371
6433
  exports.createSendToEffect = createSendToEffect;
6372
6434
  exports.createSpawnEffect = createSpawnEffect;
6435
+ exports.createStartEffect = createStartEffect;
6373
6436
  exports.createSubscriptionLogic = createSubscriptionLogic;
6437
+ exports.createTimerEffect = createTimerEffect;
6374
6438
  exports.deliverEvent = deliverEvent;
6375
6439
  exports.encodeAddressSegment = encodeAddressSegment;
6376
6440
  exports.evaluateCandidate = evaluateCandidate;
@@ -6391,6 +6455,7 @@ exports.getRootActorId = getRootActorId;
6391
6455
  exports.getSnapshotActorRef = getSnapshotActorRef;
6392
6456
  exports.getStateNodeByPath = getStateNodeByPath;
6393
6457
  exports.getStateNodes = getStateNodes;
6458
+ exports.getTimerStart = getTimerStart;
6394
6459
  exports.getTransitionResult = getTransitionResult;
6395
6460
  exports.hasAmbientInspector = hasAmbientInspector;
6396
6461
  exports.hasEffect = hasEffect;
@@ -6414,6 +6479,7 @@ exports.mergeActorIdCounters = mergeActorIdCounters;
6414
6479
  exports.parseDelayToMilliseconds = parseDelayToMilliseconds;
6415
6480
  exports.parseGeneratedActorId = parseGeneratedActorId;
6416
6481
  exports.pathToStateValue = pathToStateValue;
6482
+ exports.recordTimerStart = recordTimerStart;
6417
6483
  exports.reserveChildId = reserveChildId;
6418
6484
  exports.resolveActionsWithContext = resolveActionsWithContext;
6419
6485
  exports.resolveReferencedActor = resolveReferencedActor;
@@ -6424,6 +6490,7 @@ exports.setInertActorScopeSnapshot = setInertActorScopeSnapshot;
6424
6490
  exports.setSnapshotActorRef = setSnapshotActorRef;
6425
6491
  exports.stopActor = stopActor;
6426
6492
  exports.subscriptionLogic = subscriptionLogic;
6493
+ exports.systemLogicMetadata = systemLogicMetadata;
6427
6494
  exports.takeSpawnAllocationCounters = takeSpawnAllocationCounters;
6428
6495
  exports.terminateActor = terminateActor;
6429
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
  /**
@@ -1119,6 +1142,8 @@ function getBuiltInActionFields(action, args) {
1119
1142
  return undefined;
1120
1143
  }
1121
1144
  }
1145
+
1146
+ /** @internal Creates an actor-start effect, including for restored children. */
1122
1147
  function createStartEffect(actor) {
1123
1148
  const args = [actor];
1124
1149
  return {
@@ -1132,6 +1157,41 @@ function createStartEffect(actor) {
1132
1157
  id: actor.id
1133
1158
  };
1134
1159
  }
1160
+
1161
+ /** @internal Recreates a pending logical timer without re-entering its state. */
1162
+ function createTimerEffect(actorScope, timer, delay) {
1163
+ const source = actorScope.self;
1164
+ const options = {
1165
+ id: timer.id,
1166
+ delay
1167
+ };
1168
+ if (timer.type === '@xstate.raise') {
1169
+ return {
1170
+ kind: 'builtin',
1171
+ type: timer.type,
1172
+ source,
1173
+ event: timer.event,
1174
+ id: timer.id,
1175
+ delay,
1176
+ params: undefined,
1177
+ args: [actorScope, timer.event, options],
1178
+ exec: execRaiseEffect
1179
+ };
1180
+ }
1181
+ const target = timer.target === 'self' ? source : timer.target;
1182
+ return {
1183
+ kind: 'builtin',
1184
+ type: timer.type,
1185
+ source,
1186
+ target,
1187
+ event: timer.event,
1188
+ id: timer.id,
1189
+ delay,
1190
+ params: undefined,
1191
+ args: [actorScope, target, timer.event, options],
1192
+ exec: execSendToEffect
1193
+ };
1194
+ }
1135
1195
  function createSpawnEffect(actor) {
1136
1196
  const args = [actor];
1137
1197
  return {
@@ -4013,7 +4073,7 @@ function getPersistedSnapshot(snapshot, options) {
4013
4073
  // readings (a simulated clock, a monotonic counter) are meaningless in any
4014
4074
  // other process, and restoring them under the wall clock would fire every
4015
4075
  // pending delay instantly. Pure-transition snapshots have no local
4016
- // schedule and persist no timestamp.
4076
+ // schedule; durable executions record an accepted start separately.
4017
4077
  const scheduledTimers = snapshotActor?.system?._clock?.now ? undefined : snapshotActor?.system?._snapshot?._scheduledTimers;
4018
4078
  for (const id in timers) {
4019
4079
  const timer = timers[id];
@@ -4044,10 +4104,10 @@ function getPersistedSnapshot(snapshot, options) {
4044
4104
  // deadline. Derived from dueAt, not the scheduling moment, so repeated
4045
4105
  // persist/restore cycles keep the same deadline. Without a live schedule
4046
4106
  // (a restored-but-never-started actor, a pure-transition snapshot) the
4047
- // timer's carried-in start — which only a wall-clock actor ever stamped —
4048
- // 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.
4049
4109
  const scheduled = scheduledTimers?.[`${snapshotActor.sessionId}.${id}`];
4050
- const startedAt = scheduled ? scheduled.dueAt - timer.delay : timer.startedAt;
4110
+ const startedAt = scheduled ? scheduled.dueAt - timer.delay : getTimerStart(timer);
4051
4111
  timersJson[id] = {
4052
4112
  id: timer.id,
4053
4113
  delay: timer.delay,
@@ -6191,4 +6251,4 @@ function createActor(logic, ...[options]) {
6191
6251
  return new Actor(logic, options);
6192
6252
  }
6193
6253
 
6194
- export { ACTOR_REF_TYPE 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, toStatePath as R, STATE_DELIMITER as S, isStateId as T, getStateNodeByPath as U, getPersistedSnapshot as V, createRemoteActorRef as W, XSTATE_TIMER as X, resolveReferencedActor as Y, createInvokeTimeoutEvent as Z, parseGeneratedActorId as _, allocateChildId as a, createActor as a0, parseDelayToMilliseconds as a1, isAtomicStateNode as a2, ProcessingStatus as a3, isActorRefLike as a4, createListenerLogic as a5, createSubscriptionLogic as a6, listenerLogic as a7, subscriptionLogic as a8, Actor 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, isMachineSnapshot as aa, InfiniteTransitionError as ab, getAllOwnEventDescriptors as ac, matchesState as ad, checkStateIn as ae, pathToStateValue as af, toObserver as ag, executeEffects as ah, isBuiltInExecutableAction as ai, deliverEvent as aj, runStep as ak, stopActor as al, terminateActor as am, XSTATE_STOP as an, createCustomEffect as ao, XSTATE_LOGIC_EFFECT_START as ap, XSTATE_LOGIC_EFFECT_RESOLVE as aq, XSTATE_LOGIC_EFFECT_REJECT as ar, finalizeTransitionResult as as, createEmitEffect as at, createSendToEffect as au, XSTATE_INIT as av, hasAmbientInspector as aw, getProperAncestors as ax, isRemoteActorRef as ay, getActorIdPrefix 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
  /**
@@ -1129,6 +1152,8 @@ function getBuiltInActionFields(action, args) {
1129
1152
  return undefined;
1130
1153
  }
1131
1154
  }
1155
+
1156
+ /** @internal Creates an actor-start effect, including for restored children. */
1132
1157
  function createStartEffect(actor) {
1133
1158
  const args = [actor];
1134
1159
  return {
@@ -1142,6 +1167,41 @@ function createStartEffect(actor) {
1142
1167
  id: actor.id
1143
1168
  };
1144
1169
  }
1170
+
1171
+ /** @internal Recreates a pending logical timer without re-entering its state. */
1172
+ function createTimerEffect(actorScope, timer, delay) {
1173
+ const source = actorScope.self;
1174
+ const options = {
1175
+ id: timer.id,
1176
+ delay
1177
+ };
1178
+ if (timer.type === '@xstate.raise') {
1179
+ return {
1180
+ kind: 'builtin',
1181
+ type: timer.type,
1182
+ source,
1183
+ event: timer.event,
1184
+ id: timer.id,
1185
+ delay,
1186
+ params: undefined,
1187
+ args: [actorScope, timer.event, options],
1188
+ exec: execRaiseEffect
1189
+ };
1190
+ }
1191
+ const target = timer.target === 'self' ? source : timer.target;
1192
+ return {
1193
+ kind: 'builtin',
1194
+ type: timer.type,
1195
+ source,
1196
+ target,
1197
+ event: timer.event,
1198
+ id: timer.id,
1199
+ delay,
1200
+ params: undefined,
1201
+ args: [actorScope, target, timer.event, options],
1202
+ exec: execSendToEffect
1203
+ };
1204
+ }
1145
1205
  function createSpawnEffect(actor) {
1146
1206
  const args = [actor];
1147
1207
  return {
@@ -4119,7 +4179,7 @@ function getPersistedSnapshot(snapshot, options) {
4119
4179
  // readings (a simulated clock, a monotonic counter) are meaningless in any
4120
4180
  // other process, and restoring them under the wall clock would fire every
4121
4181
  // pending delay instantly. Pure-transition snapshots have no local
4122
- // schedule and persist no timestamp.
4182
+ // schedule; durable executions record an accepted start separately.
4123
4183
  const scheduledTimers = snapshotActor?.system?._clock?.now ? undefined : snapshotActor?.system?._snapshot?._scheduledTimers;
4124
4184
  for (const id in timers) {
4125
4185
  const timer = timers[id];
@@ -4150,10 +4210,10 @@ function getPersistedSnapshot(snapshot, options) {
4150
4210
  // deadline. Derived from dueAt, not the scheduling moment, so repeated
4151
4211
  // persist/restore cycles keep the same deadline. Without a live schedule
4152
4212
  // (a restored-but-never-started actor, a pure-transition snapshot) the
4153
- // timer's carried-in start — which only a wall-clock actor ever stamped —
4154
- // 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.
4155
4215
  const scheduled = scheduledTimers?.[`${snapshotActor.sessionId}.${id}`];
4156
- const startedAt = scheduled ? scheduled.dueAt - timer.delay : timer.startedAt;
4216
+ const startedAt = scheduled ? scheduled.dueAt - timer.delay : getTimerStart(timer);
4157
4217
  timersJson[id] = {
4158
4218
  id: timer.id,
4159
4219
  delay: timer.delay,
@@ -6334,4 +6394,4 @@ function createActor(logic, ...[options]) {
6334
6394
  return new Actor(logic, options);
6335
6395
  }
6336
6396
 
6337
- export { ACTOR_REF_TYPE 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, toStatePath as R, STATE_DELIMITER as S, isStateId as T, getStateNodeByPath as U, getPersistedSnapshot as V, createRemoteActorRef as W, XSTATE_TIMER as X, resolveReferencedActor as Y, createInvokeTimeoutEvent as Z, parseGeneratedActorId as _, allocateChildId as a, createActor as a0, parseDelayToMilliseconds as a1, isAtomicStateNode as a2, ProcessingStatus as a3, isActorRefLike as a4, createListenerLogic as a5, createSubscriptionLogic as a6, listenerLogic as a7, subscriptionLogic as a8, Actor 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, isMachineSnapshot as aa, InfiniteTransitionError as ab, getAllOwnEventDescriptors as ac, matchesState as ad, checkStateIn as ae, pathToStateValue as af, toObserver as ag, executeEffects as ah, isBuiltInExecutableAction as ai, deliverEvent as aj, runStep as ak, stopActor as al, terminateActor as am, XSTATE_STOP as an, createCustomEffect as ao, XSTATE_LOGIC_EFFECT_START as ap, XSTATE_LOGIC_EFFECT_RESOLVE as aq, XSTATE_LOGIC_EFFECT_REJECT as ar, finalizeTransitionResult as as, createEmitEffect as at, createSendToEffect as au, XSTATE_INIT as av, hasAmbientInspector as aw, getProperAncestors as ax, isRemoteActorRef as ay, getActorIdPrefix 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;
@@ -140,7 +140,7 @@ export declare class StateMachine<TContext extends MachineContext, TEvent extend
140
140
  */
141
141
  getInitialSnapshot(actorScope?: ActorScope<MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>, TEvent, AnyActorSystem, TEmitted>, input?: TInput): MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>;
142
142
  initialTransition(input: TInput | undefined, actorScope?: ActorScope<MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>, TEvent, AnyActorSystem, TEmitted>): ActorLogicTransitionResult<MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>, ExecutableActionObjectFromLogic<this>>;
143
- start(snapshot?: MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>): void;
143
+ start(snapshot?: MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>, actorScope?: ActorScope<MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>, TEvent, AnyActorSystem, TEmitted>): void;
144
144
  getStateNodeById(stateId: string): StateNode<TContext, TEvent, TMeta, TTransitionMeta>;
145
145
  getPersistedSnapshot(snapshot: MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>, options?: unknown): Snapshot<unknown>;
146
146
  restoreSnapshot(snapshot: Snapshot<unknown>, actorScope?: ActorScope<MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>, TEvent, AnyActorSystem, TEmitted>): MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TConfig>;