xstate 6.0.0-alpha.40 → 6.0.0-alpha.41
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.
- package/dist/{StateMachine-1464d5e4.cjs.js → StateMachine-8e73d782.cjs.js} +65 -4
- package/dist/{StateMachine-76ee1d6e.development.cjs.js → StateMachine-db4e6d4b.development.cjs.js} +65 -4
- package/dist/{StateMachine-6082c3cf.esm.js → StateMachine-ee89d49f.esm.js} +65 -4
- package/dist/{StateMachine-f8c7feca.development.esm.js → StateMachine-f60abe05.development.esm.js} +65 -4
- package/dist/{createActor-c0f78b8a.development.cjs.js → createActor-20615484.development.cjs.js} +787 -62
- package/dist/{createActor-a211c276.esm.js → createActor-a3f7750f.esm.js} +757 -55
- package/dist/{createActor-2a03d4b2.development.esm.js → createActor-c97c04c9.development.esm.js} +767 -62
- package/dist/{createActor-d5305cc9.cjs.js → createActor-f3afd774.cjs.js} +777 -55
- package/dist/declarations/src/actors/logic.d.ts +0 -3
- package/dist/declarations/src/createActor.d.ts +41 -6
- package/dist/declarations/src/durable/index.d.ts +75 -8
- package/dist/declarations/src/effectDescriptor.d.ts +81 -0
- package/dist/declarations/src/fsm.d.ts +1 -0
- package/dist/declarations/src/index.d.ts +3 -1
- package/dist/declarations/src/inspection.d.ts +11 -1
- package/dist/declarations/src/machineVersion.types.d.ts +1 -0
- package/dist/declarations/src/runtimeHelpers.d.ts +35 -0
- package/dist/declarations/src/system.d.ts +38 -2
- package/dist/declarations/src/transitionActions.d.ts +1 -1
- package/dist/declarations/src/types.d.ts +18 -0
- package/dist/{transition-e8a13c00.esm.js → effectDescriptor-57ae11fa.esm.js} +110 -2
- package/dist/{transition-f581ffa6.development.esm.js → effectDescriptor-b7c48ceb.development.esm.js} +110 -2
- package/dist/{transition-4ba58b71.development.cjs.js → effectDescriptor-ba9e14f0.development.cjs.js} +110 -1
- package/dist/{transition-2dcabac8.cjs.js → effectDescriptor-e2bb61e2.cjs.js} +110 -1
- package/dist/{index-21d08fff.cjs.js → index-7fd92683.cjs.js} +9 -53
- package/dist/{index-7020402e.esm.js → index-a8ce72f1.esm.js} +6 -50
- package/dist/{index-17f889df.development.esm.js → index-b5b1b2bc.development.esm.js} +6 -50
- package/dist/{index-3d1368f7.development.cjs.js → index-d42efc07.development.cjs.js} +9 -53
- package/dist/xstate-actors.cjs.js +2 -2
- package/dist/xstate-actors.development.cjs.js +2 -2
- package/dist/xstate-actors.development.esm.js +2 -2
- package/dist/xstate-actors.esm.js +2 -2
- package/dist/xstate-actors.umd.min.js +1 -1
- package/dist/xstate-actors.umd.min.js.map +1 -1
- package/dist/xstate-durable.cjs.js +245 -24
- package/dist/xstate-durable.development.cjs.js +245 -24
- package/dist/xstate-durable.development.esm.js +243 -22
- package/dist/xstate-durable.esm.js +243 -22
- package/dist/xstate-durable.umd.min.js +1 -1
- package/dist/xstate-durable.umd.min.js.map +1 -1
- package/dist/xstate-graph.cjs.js +3 -3
- package/dist/xstate-graph.development.cjs.js +3 -3
- package/dist/xstate-graph.development.esm.js +3 -3
- package/dist/xstate-graph.esm.js +3 -3
- package/dist/xstate-graph.umd.min.js +1 -1
- package/dist/xstate-graph.umd.min.js.map +1 -1
- package/dist/xstate.cjs.js +20 -9
- package/dist/xstate.cjs.mjs +5 -0
- package/dist/xstate.development.cjs.js +20 -9
- package/dist/xstate.development.cjs.mjs +5 -0
- package/dist/xstate.development.esm.js +12 -6
- package/dist/xstate.esm.js +12 -6
- package/dist/xstate.umd.min.js +1 -1
- package/dist/xstate.umd.min.js.map +1 -1
- package/package.json +1 -1
package/dist/{createActor-c0f78b8a.development.cjs.js → createActor-20615484.development.cjs.js}
RENAMED
|
@@ -58,6 +58,9 @@ const XSTATE_SPAWN = '@xstate.spawn';
|
|
|
58
58
|
const XSTATE_STOP = '@xstate.stop';
|
|
59
59
|
const XSTATE_TERMINATE = '@xstate.terminate';
|
|
60
60
|
const XSTATE_TIMER = 'xstate.timer';
|
|
61
|
+
const XSTATE_LOGIC_EFFECT_RESOLVE = 'xstate.logic.effect.resolve';
|
|
62
|
+
const XSTATE_LOGIC_EFFECT_REJECT = 'xstate.logic.effect.reject';
|
|
63
|
+
const XSTATE_LOGIC_EFFECT_START = 'xstate.logic.effect.start';
|
|
61
64
|
|
|
62
65
|
/**
|
|
63
66
|
* Returns an event that represents an implicit event that is sent after the
|
|
@@ -180,6 +183,118 @@ function reportUnhandledError(err) {
|
|
|
180
183
|
|
|
181
184
|
const symbolObservable = (() => typeof Symbol === 'function' && Symbol.observable || '@@observable')();
|
|
182
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
|
+
|
|
183
298
|
function assertSendToEvent(event) {
|
|
184
299
|
if (typeof event === 'string') {
|
|
185
300
|
throw new Error(// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
@@ -223,7 +338,12 @@ const subscriptions = /* #__PURE__ */new WeakMap();
|
|
|
223
338
|
* Internal factory for actor logic that attaches to another actor on start
|
|
224
339
|
* (`enq.listen()` / `enq.subscribeTo()`) and detaches when stopped.
|
|
225
340
|
*/
|
|
226
|
-
function createAttachedLogic(attach
|
|
341
|
+
function createAttachedLogic(attach,
|
|
342
|
+
/**
|
|
343
|
+
* Names the logic so its generated actor ids get their own prefix, out of
|
|
344
|
+
* the id space that user sources allocate from.
|
|
345
|
+
*/
|
|
346
|
+
id) {
|
|
227
347
|
const initialTransition = (input, _) => [{
|
|
228
348
|
status: 'active',
|
|
229
349
|
output: undefined,
|
|
@@ -231,6 +351,7 @@ function createAttachedLogic(attach) {
|
|
|
231
351
|
input
|
|
232
352
|
}, []];
|
|
233
353
|
return {
|
|
354
|
+
id,
|
|
234
355
|
start: (state, {
|
|
235
356
|
self,
|
|
236
357
|
system
|
|
@@ -329,7 +450,7 @@ function createListenerLogic() {
|
|
|
329
450
|
}
|
|
330
451
|
relayMappedToParent(self, system, () => mapper(emittedEvent));
|
|
331
452
|
});
|
|
332
|
-
});
|
|
453
|
+
}, 'xstate.listener');
|
|
333
454
|
}
|
|
334
455
|
|
|
335
456
|
// Singleton logic instance
|
|
@@ -371,7 +492,7 @@ function createSubscriptionLogic() {
|
|
|
371
492
|
// Actor completed without output (stopped); no action needed
|
|
372
493
|
}
|
|
373
494
|
});
|
|
374
|
-
});
|
|
495
|
+
}, 'xstate.subscription');
|
|
375
496
|
}
|
|
376
497
|
|
|
377
498
|
// Singleton logic instance
|
|
@@ -570,6 +691,17 @@ function pushBuiltInAction(actions, action, ...args) {
|
|
|
570
691
|
actions.push(actionRecord);
|
|
571
692
|
return actionRecord;
|
|
572
693
|
}
|
|
694
|
+
|
|
695
|
+
/** @internal Max-merges generated-id counter records, copy-on-write. */
|
|
696
|
+
function mergeActorIdCounters(current, update) {
|
|
697
|
+
const merged = {
|
|
698
|
+
...current
|
|
699
|
+
};
|
|
700
|
+
for (const key of Object.keys(update)) {
|
|
701
|
+
merged[key] = Math.max(merged[key] ?? 0, update[key]);
|
|
702
|
+
}
|
|
703
|
+
return merged;
|
|
704
|
+
}
|
|
573
705
|
function applyChildUpdate(snapshot, update, actorScope) {
|
|
574
706
|
if (update.type === 'add') {
|
|
575
707
|
return {
|
|
@@ -577,7 +709,10 @@ function applyChildUpdate(snapshot, update, actorScope) {
|
|
|
577
709
|
children: {
|
|
578
710
|
...snapshot.children,
|
|
579
711
|
[update.id]: update.actor
|
|
580
|
-
}
|
|
712
|
+
},
|
|
713
|
+
...(update.counters && {
|
|
714
|
+
_nextActorIds: mergeActorIdCounters(snapshot._nextActorIds, update.counters)
|
|
715
|
+
})
|
|
581
716
|
};
|
|
582
717
|
}
|
|
583
718
|
const children = {
|
|
@@ -605,15 +740,187 @@ function getTransitionActionRecord(action) {
|
|
|
605
740
|
}
|
|
606
741
|
return undefined;
|
|
607
742
|
}
|
|
608
|
-
function pushSpawnedChild(actions, actor, id) {
|
|
743
|
+
function pushSpawnedChild(actions, actor, id, counters) {
|
|
609
744
|
const action = pushBuiltInAction(actions, builtInActions['@xstate.spawn'], actor);
|
|
610
745
|
action.childUpdate = {
|
|
611
746
|
type: 'add',
|
|
612
747
|
actor,
|
|
613
|
-
id
|
|
748
|
+
id,
|
|
749
|
+
counters
|
|
614
750
|
};
|
|
615
751
|
}
|
|
752
|
+
|
|
753
|
+
/**
|
|
754
|
+
* Spawn-allocation state shared by every enqueue object of one transition, so
|
|
755
|
+
* generated ids stay unique and resolvable across action functions and
|
|
756
|
+
* microsteps of the same event.
|
|
757
|
+
*/
|
|
758
|
+
|
|
759
|
+
const spawnAllocations = new WeakMap();
|
|
760
|
+
const createSpawnAllocation = () => ({
|
|
761
|
+
counters: new Map(),
|
|
762
|
+
explicitIds: new Set(),
|
|
763
|
+
stoppedIds: new Set()
|
|
764
|
+
});
|
|
765
|
+
|
|
766
|
+
/**
|
|
767
|
+
* Starts a fresh spawn-allocation transaction for one logical transition.
|
|
768
|
+
* Called at every transition boundary so pure replays from the same snapshot
|
|
769
|
+
* allocate identical ids.
|
|
770
|
+
*
|
|
771
|
+
* @internal
|
|
772
|
+
*/
|
|
773
|
+
function beginSpawnAllocation(actorScope) {
|
|
774
|
+
spawnAllocations.set(actorScope, createSpawnAllocation());
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// Read the raw snapshot: getSnapshot() throws while the actor initializes,
|
|
778
|
+
// and entry actions run before any snapshot exists.
|
|
779
|
+
function getWorkingSnapshotOf(actorScope) {
|
|
780
|
+
return actorScope.self._snapshot;
|
|
781
|
+
}
|
|
782
|
+
const srcKeyCaches = new WeakMap();
|
|
783
|
+
function getRegisteredSrcKey(actorScope, logic) {
|
|
784
|
+
const registeredActors = actorScope.self.logic?.sources?.actors;
|
|
785
|
+
if (!registeredActors) {
|
|
786
|
+
return undefined;
|
|
787
|
+
}
|
|
788
|
+
let cache = srcKeyCaches.get(registeredActors);
|
|
789
|
+
if (!cache) {
|
|
790
|
+
cache = new Map();
|
|
791
|
+
for (const key of Object.keys(registeredActors)) {
|
|
792
|
+
cache.set(registeredActors[key], key);
|
|
793
|
+
}
|
|
794
|
+
srcKeyCaches.set(registeredActors, cache);
|
|
795
|
+
}
|
|
796
|
+
return cache.get(logic);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
/**
|
|
800
|
+
* Internal helper actors (listeners, subscriptions) number their ids from
|
|
801
|
+
* system-level counters under `xstate.`-prefixed names; snapshot-owned
|
|
802
|
+
* children number from per-snapshot counters. The two spaces only stay
|
|
803
|
+
* collision-free because their prefixes are disjoint, so user sources must
|
|
804
|
+
* not enter the reserved namespace.
|
|
805
|
+
*/
|
|
806
|
+
function assertUnreservedPrefix(prefix) {
|
|
807
|
+
if (prefix.startsWith('xstate.')) {
|
|
808
|
+
throw new Error(`Child actor ids with the "xstate." prefix are reserved for internal actors; rename the "${prefix}" source or logic id.`);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* The next free index for a prefix. The parent snapshot's persisted counter
|
|
814
|
+
* is always a floor, so a freed id is never handed out again — not even when
|
|
815
|
+
* an explicit id reserved a lower one earlier in the transition.
|
|
816
|
+
*/
|
|
817
|
+
function nextChildIndex(actorScope, allocation, prefix) {
|
|
818
|
+
return Math.max(allocation.counters.get(prefix) ?? 0, getWorkingSnapshotOf(actorScope)?._nextActorIds?.[prefix] ?? 0);
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
/**
|
|
822
|
+
* Allocates the next generated child id for the transition's allocation
|
|
823
|
+
* transaction, seeded from the parent snapshot's own persisted counters. This
|
|
824
|
+
* is the single allocator for snapshot-owned children (`enq.spawn` and
|
|
825
|
+
* context-factory spawns); a correct allocation cannot collide.
|
|
826
|
+
*
|
|
827
|
+
* @internal
|
|
828
|
+
*/
|
|
829
|
+
function allocateChildId(actorScope, src, localAllocation) {
|
|
830
|
+
if (!spawnAllocations.get(actorScope)) {
|
|
831
|
+
console.warn('A child id was generated outside a spawn-allocation transaction; ids may repeat across enqueue objects. Transition entry points must call beginSpawnAllocation().');
|
|
832
|
+
}
|
|
833
|
+
const allocation = spawnAllocations.get(actorScope) ?? localAllocation ?? createSpawnAllocation();
|
|
834
|
+
const prefix = getActorIdPrefix(src);
|
|
835
|
+
assertUnreservedPrefix(prefix);
|
|
836
|
+
const next = nextChildIndex(actorScope, allocation, prefix);
|
|
837
|
+
allocation.counters.set(prefix, next + 1);
|
|
838
|
+
return {
|
|
839
|
+
id: `${prefix}:${next}`,
|
|
840
|
+
counters: {
|
|
841
|
+
[prefix]: next + 1
|
|
842
|
+
}
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
/**
|
|
847
|
+
* Requires an explicit child id to be unoccupied before a spawn or invoke
|
|
848
|
+
* claims it: an address must name at most one live actor. An id is occupied
|
|
849
|
+
* when a child of this parent already holds it and this transition has not
|
|
850
|
+
* stopped that child, or when an earlier spawn of this transition claimed it.
|
|
851
|
+
*
|
|
852
|
+
* @internal
|
|
853
|
+
*/
|
|
854
|
+
function assertChildIdFree(actorScope, id, localAllocation) {
|
|
855
|
+
const allocation = spawnAllocations.get(actorScope) ?? localAllocation ?? createSpawnAllocation();
|
|
856
|
+
const existing = getWorkingSnapshotOf(actorScope)?.children?.[id];
|
|
857
|
+
// A terminated child no longer occupies its id: it relayed its completion
|
|
858
|
+
// and is removed from `children` right after the transition handling it,
|
|
859
|
+
// so the supervisor pattern — respawn under the same name while handling
|
|
860
|
+
// the child's done/error event — must not conflict with the outgoing
|
|
861
|
+
// entry. Remote handles never expose a terminal status locally; the
|
|
862
|
+
// completion event that removes one is the owning runtime's business.
|
|
863
|
+
const occupied = existing !== undefined && !allocation.stoppedIds.has(id) && existing.getSnapshot().status === 'active';
|
|
864
|
+
if (allocation.explicitIds.has(id) || occupied) {
|
|
865
|
+
throw new Error(`Cannot spawn child actor with id '${id}': the id is already in use by another child of '${actorScope.self.id}'. Stop the existing child before reusing its id.` );
|
|
866
|
+
}
|
|
867
|
+
allocation.explicitIds.add(id);
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
/**
|
|
871
|
+
* Records that this transition stopped a child, freeing its id for a later
|
|
872
|
+
* spawn or invoke of the same transition (the invoke restart pattern).
|
|
873
|
+
*
|
|
874
|
+
* @internal
|
|
875
|
+
*/
|
|
876
|
+
function recordStoppedChild(actorScope, actor) {
|
|
877
|
+
const allocation = spawnAllocations.get(actorScope);
|
|
878
|
+
if (allocation) {
|
|
879
|
+
allocation.stoppedIds.add(actor.id);
|
|
880
|
+
allocation.explicitIds.delete(actor.id);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
* Reserves an explicit generated-shaped id (`worker:5`) in the transaction
|
|
886
|
+
* and the parent snapshot, so live runs and pure replays allocate the same
|
|
887
|
+
* later ids even after this child is removed.
|
|
888
|
+
*
|
|
889
|
+
* @internal
|
|
890
|
+
*/
|
|
891
|
+
function reserveChildId(actorScope, id, localAllocation) {
|
|
892
|
+
const generated = parseGeneratedActorId(id);
|
|
893
|
+
if (!generated) {
|
|
894
|
+
return undefined;
|
|
895
|
+
}
|
|
896
|
+
assertUnreservedPrefix(generated.prefix);
|
|
897
|
+
const allocation = spawnAllocations.get(actorScope) ?? localAllocation ?? createSpawnAllocation();
|
|
898
|
+
// The requested id is used as asked, but numbering continues from the
|
|
899
|
+
// highest reservation: an explicit low id never rewinds the counter.
|
|
900
|
+
const next = Math.max(nextChildIndex(actorScope, allocation, generated.prefix), generated.index + 1);
|
|
901
|
+
allocation.counters.set(generated.prefix, next);
|
|
902
|
+
return {
|
|
903
|
+
[generated.prefix]: next
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
/**
|
|
908
|
+
* The counters allocated so far in the transition's transaction, for
|
|
909
|
+
* committing into a snapshot built outside `applyChildUpdate` (the
|
|
910
|
+
* pre-initial snapshot with context-factory spawns).
|
|
911
|
+
*
|
|
912
|
+
* @internal
|
|
913
|
+
*/
|
|
914
|
+
function takeSpawnAllocationCounters(actorScope) {
|
|
915
|
+
const counters = spawnAllocations.get(actorScope)?.counters;
|
|
916
|
+
if (!counters?.size) {
|
|
917
|
+
return undefined;
|
|
918
|
+
}
|
|
919
|
+
return Object.fromEntries(counters);
|
|
920
|
+
}
|
|
616
921
|
function createTransitionEnqueue(actorScope, actions, internalEvents, actorSubscriptions = false, createActors = true) {
|
|
922
|
+
// Paths that never begin a transaction keep a per-enqueue scope.
|
|
923
|
+
const localAllocation = spawnAllocations.get(actorScope) ?? createSpawnAllocation();
|
|
617
924
|
const props = {
|
|
618
925
|
cancel: id => {
|
|
619
926
|
pushBuiltInAction(actions, builtInActions['@xstate.cancel'], actorScope, id);
|
|
@@ -641,11 +948,33 @@ function createTransitionEnqueue(actorScope, actions, internalEvents, actorSubsc
|
|
|
641
948
|
id: options?.id ?? options?.registryKey ?? logic.id
|
|
642
949
|
};
|
|
643
950
|
}
|
|
951
|
+
// Recover the registered source key for setup-provided logic so the
|
|
952
|
+
// spawned child persists (and gets a deterministic id prefix) by key
|
|
953
|
+
// instead of by inline logic reference.
|
|
954
|
+
const src = getRegisteredSrcKey(actorScope, logic);
|
|
955
|
+
// Generated ids allocate from the parent snapshot's own counters
|
|
956
|
+
// through the transition's allocation transaction; explicit
|
|
957
|
+
// generated-shaped ids reserve their numbering the same way.
|
|
958
|
+
let id = options?.id;
|
|
959
|
+
let counters;
|
|
960
|
+
if (id === undefined) {
|
|
961
|
+
({
|
|
962
|
+
id,
|
|
963
|
+
counters
|
|
964
|
+
} = allocateChildId(actorScope, src ?? logic, localAllocation));
|
|
965
|
+
} else {
|
|
966
|
+
assertChildIdFree(actorScope, id, localAllocation);
|
|
967
|
+
counters = reserveChildId(actorScope, id, localAllocation);
|
|
968
|
+
}
|
|
644
969
|
const actor = actorScope.system.createActorRef(logic, {
|
|
645
970
|
...options,
|
|
971
|
+
...(src !== undefined && {
|
|
972
|
+
src
|
|
973
|
+
}),
|
|
974
|
+
id,
|
|
646
975
|
parent: actorScope.self
|
|
647
976
|
});
|
|
648
|
-
pushSpawnedChild(actions, actor,
|
|
977
|
+
pushSpawnedChild(actions, actor, id, counters);
|
|
649
978
|
return actor;
|
|
650
979
|
},
|
|
651
980
|
sendTo: (actor, event, options) => {
|
|
@@ -665,6 +994,7 @@ function createTransitionEnqueue(actorScope, actions, internalEvents, actorSubsc
|
|
|
665
994
|
type: 'remove',
|
|
666
995
|
actor
|
|
667
996
|
};
|
|
997
|
+
recordStoppedChild(actorScope, actor);
|
|
668
998
|
}
|
|
669
999
|
}
|
|
670
1000
|
};
|
|
@@ -1401,6 +1731,10 @@ function createMaterializedInertActorScope(actorLogic, sourceRef, sourceChildren
|
|
|
1401
1731
|
});
|
|
1402
1732
|
if (previousSelf?._parent) {
|
|
1403
1733
|
self._parent = previousSelf._parent;
|
|
1734
|
+
// `address` memoizes on first read assuming `_parent` is final; nothing
|
|
1735
|
+
// reads it between construction and this assignment, but drop any memo so
|
|
1736
|
+
// a future construction-time read cannot pin a root-shaped address.
|
|
1737
|
+
self._address = undefined;
|
|
1404
1738
|
}
|
|
1405
1739
|
if (currentSnapshot) {
|
|
1406
1740
|
self._snapshot = currentSnapshot;
|
|
@@ -1672,7 +2006,17 @@ function getEventDescriptorKey(event) {
|
|
|
1672
2006
|
return legacyType ? `${event.type}|${legacyType}` : event.type;
|
|
1673
2007
|
}
|
|
1674
2008
|
function matchesActorSession(event, snapshot, actorId) {
|
|
1675
|
-
|
|
2009
|
+
const child = snapshot.children[actorId];
|
|
2010
|
+
if (!child || !('sessionId' in event)) {
|
|
2011
|
+
return true;
|
|
2012
|
+
}
|
|
2013
|
+
if (isRemoteActorRef(child)) {
|
|
2014
|
+
// Without a host-supplied incarnation token the runtime that owns the
|
|
2015
|
+
// child is the authority on staleness; with one, a completion from a
|
|
2016
|
+
// different incarnation of the same address is dropped here.
|
|
2017
|
+
return child._incarnation === undefined || child._incarnation === event.sessionId;
|
|
2018
|
+
}
|
|
2019
|
+
return child.sessionId === event.sessionId;
|
|
1676
2020
|
}
|
|
1677
2021
|
function normalizeLegacyInternalEvent(event, machine) {
|
|
1678
2022
|
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') {
|
|
@@ -2258,9 +2602,17 @@ function narrowParallelDomain(domain, targetStates) {
|
|
|
2258
2602
|
function getTransitionDomain(transition, snapshot, resolveTransition) {
|
|
2259
2603
|
const targetStates = getEffectiveTargetStates(transition, snapshot, resolveTransition);
|
|
2260
2604
|
const {
|
|
2605
|
+
targets,
|
|
2261
2606
|
reenter
|
|
2262
2607
|
} = resolveTransition(transition);
|
|
2263
|
-
|
|
2608
|
+
|
|
2609
|
+
// A history target that restores the source itself must exit and reenter
|
|
2610
|
+
// the source (SCXML domain = the source's ancestor), unlike a plain
|
|
2611
|
+
// non-reentering self-target: the enter set restores the stored
|
|
2612
|
+
// configuration from outside the source, so the exit set must match or the
|
|
2613
|
+
// source's invoked actors are re-created without being stopped.
|
|
2614
|
+
const restoresSourceViaHistory = targets?.some(isHistoryNode) && targetStates.some(target => target === transition.source);
|
|
2615
|
+
if (!restoresSourceViaHistory && targetStates.every(target => target === transition.source || isDescendant(target, transition.source))) {
|
|
2264
2616
|
// Targets are contained within the source. A reentering transition
|
|
2265
2617
|
// exits and reenters the source itself; otherwise the domain narrows
|
|
2266
2618
|
// past parallel nodes so sibling regions are left untouched.
|
|
@@ -2629,6 +2981,7 @@ function microstep(transitions, currentSnapshot, actorScope, event, isInitial, i
|
|
|
2629
2981
|
event,
|
|
2630
2982
|
output: getEventOutput(event)
|
|
2631
2983
|
}) : invokeDef.input;
|
|
2984
|
+
assertChildIdFree(actorScope, invokeDef.id);
|
|
2632
2985
|
const actor = actorScope.system.createActorRef(logic, {
|
|
2633
2986
|
...invokeDef,
|
|
2634
2987
|
input,
|
|
@@ -2864,7 +3217,17 @@ function macrostep(snapshot, event, actorScope, internalQueue, initialMicrosteps
|
|
|
2864
3217
|
return;
|
|
2865
3218
|
}
|
|
2866
3219
|
const child = nextSnapshot.children[actorId];
|
|
2867
|
-
if (!child
|
|
3220
|
+
if (!child) {
|
|
3221
|
+
return;
|
|
3222
|
+
}
|
|
3223
|
+
// The same staleness rule matchesActorSession applies to transition
|
|
3224
|
+
// selection: a completion from a different incarnation must not remove
|
|
3225
|
+
// the still-running child either.
|
|
3226
|
+
if (isRemoteActorRef(child)) {
|
|
3227
|
+
if (child._incarnation !== undefined && child._incarnation !== sessionId) {
|
|
3228
|
+
return;
|
|
3229
|
+
}
|
|
3230
|
+
} else if (child.sessionId !== sessionId) {
|
|
2868
3231
|
return;
|
|
2869
3232
|
}
|
|
2870
3233
|
const children = {
|
|
@@ -3236,6 +3599,7 @@ function createMachineSnapshot(config, machine, actorRef) {
|
|
|
3236
3599
|
historyValue: compactSnapshotRecord(config.historyValue),
|
|
3237
3600
|
_stateInputs: compactSnapshotRecord(config._stateInputs),
|
|
3238
3601
|
_nextTimerId: config._nextTimerId ?? 0,
|
|
3602
|
+
_nextActorIds: config._nextActorIds,
|
|
3239
3603
|
matches: machineSnapshotMatches,
|
|
3240
3604
|
hasTag: machineSnapshotHasTag,
|
|
3241
3605
|
can: machineSnapshotCan,
|
|
@@ -3268,6 +3632,7 @@ function cloneMachineSnapshot(snapshot, config = {}) {
|
|
|
3268
3632
|
historyValue: compactSnapshotRecord(configWithSnapshot.historyValue),
|
|
3269
3633
|
_stateInputs: compactSnapshotRecord(configWithSnapshot._stateInputs),
|
|
3270
3634
|
_nextTimerId: configWithSnapshot._nextTimerId ?? 0,
|
|
3635
|
+
_nextActorIds: configWithSnapshot._nextActorIds,
|
|
3271
3636
|
matches: machineSnapshotMatches,
|
|
3272
3637
|
hasTag: machineSnapshotHasTag,
|
|
3273
3638
|
can: machineSnapshotCan,
|
|
@@ -3316,18 +3681,46 @@ function getPersistedSnapshot(snapshot, options) {
|
|
|
3316
3681
|
} = snapshot;
|
|
3317
3682
|
const childrenJson = {};
|
|
3318
3683
|
const timersJson = {};
|
|
3684
|
+
const embedChildren = options?.embedChildren !== false;
|
|
3319
3685
|
for (const id in children) {
|
|
3320
3686
|
const child = children[id];
|
|
3321
3687
|
if (typeof child.src !== 'string' && (!options || !('__unsafeAllowInlineActors' in options))) {
|
|
3322
3688
|
throw new Error('An inline child actor cannot be persisted.');
|
|
3323
3689
|
}
|
|
3690
|
+
// Children are referenced by their logical address. Embedding the child
|
|
3691
|
+
// state is the co-locating runtime's whole-tree checkpoint capability;
|
|
3692
|
+
// remote handles never embed — their state lives with another runtime.
|
|
3693
|
+
const embed = embedChildren && !isRemoteActorRef(child);
|
|
3694
|
+
if (!embed && typeof child.src !== 'string') {
|
|
3695
|
+
// Fail where it is actionable: a by-address reference without a
|
|
3696
|
+
// registered source key could be persisted but never restored.
|
|
3697
|
+
throw new Error(`Unable to persist child '${id}' by address: it requires a registered source key.`);
|
|
3698
|
+
}
|
|
3324
3699
|
childrenJson[id] = {
|
|
3325
|
-
|
|
3700
|
+
address: child.address,
|
|
3701
|
+
// The explicit marker disambiguates a by-address reference from a child
|
|
3702
|
+
// whose own persisted snapshot happens to be undefined.
|
|
3703
|
+
...(embed ? {
|
|
3704
|
+
snapshot: child.getPersistedSnapshot(options)
|
|
3705
|
+
} : {
|
|
3706
|
+
remote: true,
|
|
3707
|
+
// Round-trips verbatim: the host that owns the child injects the
|
|
3708
|
+
// token; XState never stamps one (a local sessionId would make
|
|
3709
|
+
// persisted snapshots nondeterministic across replays).
|
|
3710
|
+
incarnation: child._incarnation
|
|
3711
|
+
}),
|
|
3326
3712
|
src: child.src,
|
|
3327
3713
|
registryKey: child.registryKey,
|
|
3328
3714
|
syncSnapshot: child._syncSnapshot
|
|
3329
3715
|
};
|
|
3330
3716
|
}
|
|
3717
|
+
const snapshotActor = getSnapshotActorRef(snapshot)?.actor;
|
|
3718
|
+
// Only the wall clock is stamped into persisted timers: a custom clock's
|
|
3719
|
+
// readings (a simulated clock, a monotonic counter) are meaningless in any
|
|
3720
|
+
// other process, and restoring them under the wall clock would fire every
|
|
3721
|
+
// pending delay instantly. Pure-transition snapshots have no local
|
|
3722
|
+
// schedule and persist no timestamp.
|
|
3723
|
+
const scheduledTimers = snapshotActor?.system?._clock?.now ? undefined : snapshotActor?.system?._snapshot?._scheduledTimers;
|
|
3331
3724
|
for (const id in timers) {
|
|
3332
3725
|
const timer = timers[id];
|
|
3333
3726
|
let event = timer.event;
|
|
@@ -3352,17 +3745,28 @@ function getPersistedSnapshot(snapshot, options) {
|
|
|
3352
3745
|
throw new Error(`Unable to persist timer '${id}': target actor '${timer.target.id}' is no longer addressable from this snapshot.`);
|
|
3353
3746
|
}
|
|
3354
3747
|
}
|
|
3748
|
+
// A live runtime knows when the timer is due; persist the wall-clock
|
|
3749
|
+
// start (dueAt - declared delay) so restore can honor the absolute
|
|
3750
|
+
// deadline. Derived from dueAt, not the scheduling moment, so repeated
|
|
3751
|
+
// persist/restore cycles keep the same deadline. Without a live schedule
|
|
3752
|
+
// (a restored-but-never-started actor, a pure-transition snapshot) the
|
|
3753
|
+
// timer's carried-in start — which only a wall-clock actor ever stamped —
|
|
3754
|
+
// passes through, so re-persisting cannot push the deadline back.
|
|
3755
|
+
const scheduled = scheduledTimers?.[`${snapshotActor.sessionId}.${id}`];
|
|
3756
|
+
const startedAt = scheduled ? scheduled.dueAt - timer.delay : timer.startedAt;
|
|
3355
3757
|
timersJson[id] = {
|
|
3356
3758
|
id: timer.id,
|
|
3357
3759
|
delay: timer.delay,
|
|
3358
3760
|
type: timer.type,
|
|
3359
3761
|
event,
|
|
3360
|
-
target
|
|
3762
|
+
target,
|
|
3763
|
+
...(startedAt !== undefined && {
|
|
3764
|
+
startedAt
|
|
3765
|
+
})
|
|
3361
3766
|
};
|
|
3362
3767
|
}
|
|
3363
3768
|
const persisted = {
|
|
3364
3769
|
...jsonValues,
|
|
3365
|
-
_nextActorId: getSnapshotActorRef(snapshot)?.systemState.snapshot._nextActorId,
|
|
3366
3770
|
context: persistContext(context),
|
|
3367
3771
|
children: childrenJson,
|
|
3368
3772
|
timers: timersJson,
|
|
@@ -3390,7 +3794,7 @@ function persistContext(contextPart) {
|
|
|
3390
3794
|
...contextPart
|
|
3391
3795
|
};
|
|
3392
3796
|
copy[key] = {
|
|
3393
|
-
xstate
|
|
3797
|
+
xstate$type: ACTOR_REF_TYPE,
|
|
3394
3798
|
id: value.id
|
|
3395
3799
|
};
|
|
3396
3800
|
} else {
|
|
@@ -3657,6 +4061,106 @@ function matchesEventDescriptor(eventType, descriptor) {
|
|
|
3657
4061
|
return true;
|
|
3658
4062
|
}
|
|
3659
4063
|
|
|
4064
|
+
function getStepEffect(actor, key) {
|
|
4065
|
+
return actor.getSnapshot().effects?.[key];
|
|
4066
|
+
}
|
|
4067
|
+
function waitForStep(actor, key) {
|
|
4068
|
+
return new Promise((resolve, reject) => {
|
|
4069
|
+
const subscription = actor.subscribe(snapshot => {
|
|
4070
|
+
const effect = snapshot.effects?.[key];
|
|
4071
|
+
if (effect?.status === 'done') {
|
|
4072
|
+
subscription.unsubscribe();
|
|
4073
|
+
resolve(effect.output);
|
|
4074
|
+
} else if (effect?.status === 'error') {
|
|
4075
|
+
subscription.unsubscribe();
|
|
4076
|
+
reject(effect.error);
|
|
4077
|
+
}
|
|
4078
|
+
});
|
|
4079
|
+
});
|
|
4080
|
+
}
|
|
4081
|
+
|
|
4082
|
+
/**
|
|
4083
|
+
* Runs one keyed step of an async actor with the built-in journal: the
|
|
4084
|
+
* result is memoized in the actor's own snapshot (`effects[key]`), so a
|
|
4085
|
+
* restored actor skips completed steps when its logic function re-runs.
|
|
4086
|
+
* Custom runtimes that implement `runStep` use this for the default local
|
|
4087
|
+
* behavior, the same way `deliverEvent` exposes local delivery.
|
|
4088
|
+
*
|
|
4089
|
+
* @experimental
|
|
4090
|
+
*/
|
|
4091
|
+
async function runStep(actor, key, exec, sendSelf = event => void actor.system.sendEvent(actor, actor, event)) {
|
|
4092
|
+
const effect = getStepEffect(actor, key);
|
|
4093
|
+
if (effect?.status === 'done') {
|
|
4094
|
+
return effect.output;
|
|
4095
|
+
}
|
|
4096
|
+
if (effect?.status === 'error') {
|
|
4097
|
+
throw effect.error;
|
|
4098
|
+
}
|
|
4099
|
+
if (effect?.status === 'active') {
|
|
4100
|
+
return waitForStep(actor, key);
|
|
4101
|
+
}
|
|
4102
|
+
sendSelf({
|
|
4103
|
+
type: XSTATE_LOGIC_EFFECT_START,
|
|
4104
|
+
key
|
|
4105
|
+
});
|
|
4106
|
+
try {
|
|
4107
|
+
const output = await exec();
|
|
4108
|
+
sendSelf({
|
|
4109
|
+
type: XSTATE_LOGIC_EFFECT_RESOLVE,
|
|
4110
|
+
key,
|
|
4111
|
+
output
|
|
4112
|
+
});
|
|
4113
|
+
return output;
|
|
4114
|
+
} catch (error) {
|
|
4115
|
+
sendSelf({
|
|
4116
|
+
type: XSTATE_LOGIC_EFFECT_REJECT,
|
|
4117
|
+
key,
|
|
4118
|
+
error
|
|
4119
|
+
});
|
|
4120
|
+
throw error;
|
|
4121
|
+
}
|
|
4122
|
+
}
|
|
4123
|
+
|
|
4124
|
+
/**
|
|
4125
|
+
* Delivers an event directly to a target actor, bypassing any installed host
|
|
4126
|
+
* runtime. Custom runtimes use this for the default local delivery behavior
|
|
4127
|
+
* inside their own `sendEvent` implementations.
|
|
4128
|
+
*
|
|
4129
|
+
* @experimental
|
|
4130
|
+
*/
|
|
4131
|
+
function deliverEvent(source, target, event) {
|
|
4132
|
+
const runtimeTarget = target;
|
|
4133
|
+
// The same guard local delivery has always applied: internal events may
|
|
4134
|
+
// only originate from the actor itself, whichever runtime delivers them.
|
|
4135
|
+
if (source !== target && runtimeTarget.logic?.isInternalEventType?.(event.type)) {
|
|
4136
|
+
throw new Error(`Internal event "${event.type}" cannot be sent to actor "${target.id}" from outside.`);
|
|
4137
|
+
}
|
|
4138
|
+
runtimeTarget._lastSourceRef = source;
|
|
4139
|
+
runtimeTarget._send(event);
|
|
4140
|
+
}
|
|
4141
|
+
|
|
4142
|
+
/**
|
|
4143
|
+
* Publishes an actor's terminal result, notifying its parent and observers.
|
|
4144
|
+
* Custom runtimes use this for the default local behavior inside their own
|
|
4145
|
+
* `terminateActor` implementations.
|
|
4146
|
+
*
|
|
4147
|
+
* @experimental
|
|
4148
|
+
*/
|
|
4149
|
+
function terminateActor(actor, termination) {
|
|
4150
|
+
actor._terminate(termination);
|
|
4151
|
+
}
|
|
4152
|
+
|
|
4153
|
+
/**
|
|
4154
|
+
* Stops an actor without producing a completion result. Custom runtimes use
|
|
4155
|
+
* this for the default local behavior inside their own `stopActor`
|
|
4156
|
+
* implementations.
|
|
4157
|
+
*
|
|
4158
|
+
* @experimental
|
|
4159
|
+
*/
|
|
4160
|
+
function stopActor(actor) {
|
|
4161
|
+
actor._stop();
|
|
4162
|
+
}
|
|
4163
|
+
|
|
3660
4164
|
let systemIdPrefix;
|
|
3661
4165
|
let nextSystemId = 0;
|
|
3662
4166
|
|
|
@@ -3694,23 +4198,104 @@ function createSystemId() {
|
|
|
3694
4198
|
return `${systemIdPrefix}:${(nextSystemId++).toString(36)}`;
|
|
3695
4199
|
}
|
|
3696
4200
|
|
|
4201
|
+
/**
|
|
4202
|
+
* Derives the deterministic id prefix for a generated actor id from its actor
|
|
4203
|
+
* source: the registered source key when the source is a string, the logic's
|
|
4204
|
+
* own `id` otherwise, with `x` as the last-resort prefix.
|
|
4205
|
+
*
|
|
4206
|
+
* @internal
|
|
4207
|
+
*/
|
|
4208
|
+
function getActorIdPrefix(src) {
|
|
4209
|
+
if (typeof src === 'string') {
|
|
4210
|
+
return src;
|
|
4211
|
+
}
|
|
4212
|
+
const logicId = src?.id;
|
|
4213
|
+
// Anonymous machines get the placeholder id '(machine)'; only named logic
|
|
4214
|
+
// earns a named id prefix.
|
|
4215
|
+
return typeof logicId === 'string' && logicId.length && logicId !== '(machine)' ? logicId : 'x';
|
|
4216
|
+
}
|
|
4217
|
+
|
|
4218
|
+
/**
|
|
4219
|
+
* Encodes one actor id as an address segment. `/` separates segments, so it
|
|
4220
|
+
* is percent-encoded, and the escape character `%` is escaped first so the
|
|
4221
|
+
* encoding stays injective: the ids 'a/b' and 'a%2Fb' must not produce the
|
|
4222
|
+
* same address.
|
|
4223
|
+
*
|
|
4224
|
+
* @internal
|
|
4225
|
+
*/
|
|
4226
|
+
function encodeAddressSegment(id) {
|
|
4227
|
+
return id.includes('/') || id.includes('%') ? id.replaceAll('%', '%25').replaceAll('/', '%2F') : id;
|
|
4228
|
+
}
|
|
4229
|
+
|
|
4230
|
+
/**
|
|
4231
|
+
* Parses a generated-shaped actor id (`prefix:<n>`). This single definition is
|
|
4232
|
+
* the determinism contract for id reservation: live allocation, replay, and
|
|
4233
|
+
* restore must all agree on what counts as generated-shaped. Deliberately
|
|
4234
|
+
* broader than ids a generated allocation could produce — over-reserving
|
|
4235
|
+
* skips numbers, which is harmless, while under-reserving could collide.
|
|
4236
|
+
*
|
|
4237
|
+
* @internal
|
|
4238
|
+
*/
|
|
4239
|
+
function parseGeneratedActorId(id) {
|
|
4240
|
+
const separator = id.lastIndexOf(':');
|
|
4241
|
+
if (separator <= 0 || separator === id.length - 1) {
|
|
4242
|
+
return undefined;
|
|
4243
|
+
}
|
|
4244
|
+
const index = Number(id.slice(separator + 1));
|
|
4245
|
+
return Number.isSafeInteger(index) && index >= 0 ? {
|
|
4246
|
+
prefix: id.slice(0, separator),
|
|
4247
|
+
index
|
|
4248
|
+
} : undefined;
|
|
4249
|
+
}
|
|
4250
|
+
|
|
4251
|
+
/**
|
|
4252
|
+
* The id (and address root segment) of the first parentless actor of a logic:
|
|
4253
|
+
* the logic's own name, or `x:0` for anonymous logic.
|
|
4254
|
+
*
|
|
4255
|
+
* @internal
|
|
4256
|
+
*/
|
|
4257
|
+
function getRootActorId(src) {
|
|
4258
|
+
const prefix = getActorIdPrefix(src);
|
|
4259
|
+
return prefix === 'x' ? 'x:0' : prefix;
|
|
4260
|
+
}
|
|
4261
|
+
function getActorIdCounterKey(parent, prefix) {
|
|
4262
|
+
return `${parent ? parent.address : ''}|${prefix}`;
|
|
4263
|
+
}
|
|
4264
|
+
function bumpActorIdCounter(system, counterKey, next) {
|
|
4265
|
+
const counters = system._snapshot._nextActorIds;
|
|
4266
|
+
if ((counters[counterKey] ?? 0) >= next) {
|
|
4267
|
+
return;
|
|
4268
|
+
}
|
|
4269
|
+
// Copy-on-write: snapshot systems share this record by shallow `_snapshot`
|
|
4270
|
+
// copies, so branches must not observe each other's allocations.
|
|
4271
|
+
system._snapshot._nextActorIds = {
|
|
4272
|
+
...counters,
|
|
4273
|
+
[counterKey]: next
|
|
4274
|
+
};
|
|
4275
|
+
markSystemSnapshotDirty(system);
|
|
4276
|
+
}
|
|
4277
|
+
|
|
3697
4278
|
/** @internal */
|
|
3698
|
-
function resolveActorId(system, requestedId) {
|
|
4279
|
+
function resolveActorId(system, requestedId, options) {
|
|
3699
4280
|
if (requestedId !== undefined) {
|
|
3700
|
-
const
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
}
|
|
4281
|
+
const generated = parseGeneratedActorId(requestedId);
|
|
4282
|
+
if (generated) {
|
|
4283
|
+
bumpActorIdCounter(system, getActorIdCounterKey(options?.parent, generated.prefix), generated.index + 1);
|
|
4284
|
+
} else if (!options?.parent) {
|
|
4285
|
+
// Reserve a restored root's bare name so a later parentless actor of
|
|
4286
|
+
// the same logic in this system numbers past it.
|
|
4287
|
+
bumpActorIdCounter(system, getActorIdCounterKey(undefined, requestedId), 1);
|
|
3708
4288
|
}
|
|
3709
4289
|
return requestedId;
|
|
3710
4290
|
}
|
|
3711
|
-
const
|
|
3712
|
-
|
|
3713
|
-
|
|
4291
|
+
const prefix = getActorIdPrefix(options?.src);
|
|
4292
|
+
const counterKey = getActorIdCounterKey(options?.parent, prefix);
|
|
4293
|
+
const counter = system._snapshot._nextActorIds[counterKey] ?? 0;
|
|
4294
|
+
bumpActorIdCounter(system, counterKey, counter + 1);
|
|
4295
|
+
// The first parentless actor of a logic gets the logic's own name; later
|
|
4296
|
+
// parentless actors of the same logic in a shared system get numbered so
|
|
4297
|
+
// addresses stay unique.
|
|
4298
|
+
return !options?.parent && prefix !== 'x' && counter === 0 ? prefix : `${prefix}:${counter}`;
|
|
3714
4299
|
}
|
|
3715
4300
|
|
|
3716
4301
|
/** @internal */
|
|
@@ -3721,10 +4306,18 @@ function bookSessionId(system) {
|
|
|
3721
4306
|
/**
|
|
3722
4307
|
* Runtime operations used to execute effects.
|
|
3723
4308
|
*
|
|
3724
|
-
*
|
|
3725
|
-
*
|
|
4309
|
+
* XState calculates pure transitions; a runtime executes their effects. The
|
|
4310
|
+
* built-in local runtime is one implementation at the same level as any
|
|
4311
|
+
* other: install a different one via `system.runtime` (for durable hosts,
|
|
4312
|
+
* through `createDurable`'s adapter runtime operations).
|
|
3726
4313
|
*/
|
|
3727
4314
|
|
|
4315
|
+
/** @internal Every operation of `ActorSystemRuntime`, for runtime wrappers. */
|
|
4316
|
+
const RUNTIME_OPERATIONS = ['spawnActor', 'startActor', 'stopActor', 'terminateActor', 'emitEvent', 'scheduleTimer', 'cancelTimer', 'cancelAllTimers', 'deadLetter'
|
|
4317
|
+
// `runStep` and `sendEvent` are deliberately absent: durable executions
|
|
4318
|
+
// wire them separately, since a step awaits other runtime operations and
|
|
4319
|
+
// root-addressed sends are captured per batch.
|
|
4320
|
+
];
|
|
3728
4321
|
const emptyScheduledTimers = Object.freeze({});
|
|
3729
4322
|
function createScheduledTimerId(actor, id) {
|
|
3730
4323
|
return `${actor.sessionId}.${id}`;
|
|
@@ -3785,7 +4378,10 @@ class RuntimeSystem {
|
|
|
3785
4378
|
this.createActorRef = options.createActorRef;
|
|
3786
4379
|
this._snapshot = {
|
|
3787
4380
|
_scheduledTimers: restoredSnapshot?.scheduler ?? emptyScheduledTimers,
|
|
3788
|
-
|
|
4381
|
+
// System-level counters are process-local backstops; per-actor
|
|
4382
|
+
// counters persist on each machine snapshot, and restored explicit ids
|
|
4383
|
+
// reserve their numbering here via `resolveActorId`.
|
|
4384
|
+
_nextActorIds: {}
|
|
3789
4385
|
};
|
|
3790
4386
|
}
|
|
3791
4387
|
|
|
@@ -3869,16 +4465,7 @@ class RuntimeSystem {
|
|
|
3869
4465
|
// Delivers an event to the target actor. Used by both `_relay` (which also
|
|
3870
4466
|
// records the send) and the scheduler's timer (which already recorded it).
|
|
3871
4467
|
_deliver(source, target, event) {
|
|
3872
|
-
|
|
3873
|
-
const targetMachine = runtimeTarget.logic;
|
|
3874
|
-
const isInternalEvent = typeof targetMachine?.isInternalEventType === 'function' && targetMachine.isInternalEventType(event.type);
|
|
3875
|
-
if (isInternalEvent && source !== target) {
|
|
3876
|
-
throw new Error(`Internal event "${event.type}" cannot be sent to actor "${target.id}" from outside.`);
|
|
3877
|
-
}
|
|
3878
|
-
|
|
3879
|
-
// remember the last source for unified transition inspect event
|
|
3880
|
-
runtimeTarget._lastSourceRef = source;
|
|
3881
|
-
target._send(event);
|
|
4468
|
+
deliverEvent(source, target, event);
|
|
3882
4469
|
}
|
|
3883
4470
|
_register(sessionId, actor) {
|
|
3884
4471
|
if (actor === this._rootActor) {
|
|
@@ -3891,11 +4478,13 @@ class RuntimeSystem {
|
|
|
3891
4478
|
}
|
|
3892
4479
|
_unregister(actor) {
|
|
3893
4480
|
let changed;
|
|
4481
|
+
// Remote handles have no sessionId and are never in the session map;
|
|
4482
|
+
// their registry cleanup happens through the keyed-actor path below.
|
|
3894
4483
|
if (actor === this._rootActor) {
|
|
3895
4484
|
changed = this._getRootActor() !== undefined;
|
|
3896
|
-
changed = (this._children?.delete(actor.sessionId) ?? false) || changed;
|
|
4485
|
+
changed = actor.sessionId !== undefined && (this._children?.delete(actor.sessionId) ?? false) || changed;
|
|
3897
4486
|
} else {
|
|
3898
|
-
changed = this._children?.delete(actor.sessionId) ?? false;
|
|
4487
|
+
changed = actor.sessionId !== undefined && (this._children?.delete(actor.sessionId) ?? false);
|
|
3899
4488
|
}
|
|
3900
4489
|
const registryKey = this._reverseKeyedActors?.get(actor);
|
|
3901
4490
|
if (registryKey !== undefined) {
|
|
@@ -3948,37 +4537,109 @@ class RuntimeSystem {
|
|
|
3948
4537
|
};
|
|
3949
4538
|
this._inspectionObservers.forEach(observer => observer.next?.(resolvedInspectionEvent));
|
|
3950
4539
|
}
|
|
3951
|
-
|
|
4540
|
+
|
|
4541
|
+
// Unlike the other operations, spawn has no local work: local actors
|
|
4542
|
+
// register with the system when they are constructed, so this only
|
|
4543
|
+
// notifies a host runtime.
|
|
4544
|
+
spawnActor(source, actor) {
|
|
4545
|
+
return this.runtime?.spawnActor?.(source, actor);
|
|
4546
|
+
}
|
|
3952
4547
|
startActor(actor) {
|
|
4548
|
+
const override = this.runtime?.startActor;
|
|
4549
|
+
if (override) {
|
|
4550
|
+
return override(actor);
|
|
4551
|
+
}
|
|
3953
4552
|
actor.start();
|
|
3954
4553
|
}
|
|
3955
4554
|
stopActor(actor) {
|
|
3956
|
-
|
|
4555
|
+
const override = this.runtime?.stopActor;
|
|
4556
|
+
if (override) {
|
|
4557
|
+
return override(actor);
|
|
4558
|
+
}
|
|
4559
|
+
stopActor(actor);
|
|
3957
4560
|
}
|
|
3958
4561
|
terminateActor(actor, termination) {
|
|
3959
|
-
|
|
4562
|
+
const override = this.runtime?.terminateActor;
|
|
4563
|
+
if (override) {
|
|
4564
|
+
return override(actor, termination);
|
|
4565
|
+
}
|
|
4566
|
+
terminateActor(actor, termination);
|
|
3960
4567
|
}
|
|
3961
4568
|
sendEvent(source, target, event) {
|
|
4569
|
+
// Record for the inspection `sent[]` facet regardless of which runtime
|
|
4570
|
+
// delivers, so host runtimes keep inspection parity.
|
|
3962
4571
|
this._recordSent(source, target, event);
|
|
4572
|
+
const override = this.runtime?.sendEvent;
|
|
4573
|
+
if (override) {
|
|
4574
|
+
return override(source, target, event);
|
|
4575
|
+
}
|
|
3963
4576
|
this._deliver(source, target, event);
|
|
3964
4577
|
}
|
|
3965
4578
|
emitEvent(source, event) {
|
|
4579
|
+
const override = this.runtime?.emitEvent;
|
|
4580
|
+
if (override) {
|
|
4581
|
+
return override(source, event);
|
|
4582
|
+
}
|
|
3966
4583
|
source._emit(event);
|
|
3967
4584
|
}
|
|
4585
|
+
deadLetter(source, target, event, reason) {
|
|
4586
|
+
this._sendInspectionEvent({
|
|
4587
|
+
type: '@xstate.deadletter',
|
|
4588
|
+
actorRef: target,
|
|
4589
|
+
sourceRef: source,
|
|
4590
|
+
event,
|
|
4591
|
+
reason
|
|
4592
|
+
});
|
|
4593
|
+
const override = this.runtime?.deadLetter;
|
|
4594
|
+
if (override) {
|
|
4595
|
+
return override(source, target, event, reason);
|
|
4596
|
+
}
|
|
4597
|
+
{
|
|
4598
|
+
console.warn(`Event "${event.type}" to actor "${target.id}" was not delivered (${reason}).`);
|
|
4599
|
+
}
|
|
4600
|
+
}
|
|
4601
|
+
runStep(actor, key, exec) {
|
|
4602
|
+
const override = this.runtime?.runStep;
|
|
4603
|
+
if (override) {
|
|
4604
|
+
return override(actor, key, exec);
|
|
4605
|
+
}
|
|
4606
|
+
return runStep(actor, key, exec);
|
|
4607
|
+
}
|
|
3968
4608
|
scheduleTimer(source, id, delay) {
|
|
4609
|
+
const override = this.runtime?.scheduleTimer;
|
|
4610
|
+
if (override) {
|
|
4611
|
+
// The local scheduler records delayed sends for inspection inside
|
|
4612
|
+
// `schedule`; keep that parity for host runtimes.
|
|
4613
|
+
const timer = source.getSnapshot()?.timers?.[id];
|
|
4614
|
+
if (timer) {
|
|
4615
|
+
const target = timer.target === 'self' ? source : timer.target;
|
|
4616
|
+
this._recordSent(source, target, timer.event, delay, id);
|
|
4617
|
+
}
|
|
4618
|
+
return override(source, id, delay);
|
|
4619
|
+
}
|
|
3969
4620
|
this.schedule(source, id, delay);
|
|
3970
4621
|
}
|
|
3971
4622
|
cancelTimer(source, id) {
|
|
4623
|
+
const override = this.runtime?.cancelTimer;
|
|
4624
|
+
if (override) {
|
|
4625
|
+
return override(source, id);
|
|
4626
|
+
}
|
|
3972
4627
|
this.cancel(source, id);
|
|
3973
4628
|
}
|
|
3974
4629
|
cancelAllTimers(source) {
|
|
4630
|
+
const override = this.runtime?.cancelAllTimers;
|
|
4631
|
+
if (override) {
|
|
4632
|
+
return override(source);
|
|
4633
|
+
}
|
|
3975
4634
|
this.cancelAll(source);
|
|
3976
4635
|
}
|
|
3977
4636
|
_relay(source, target, event) {
|
|
3978
4637
|
if (transitionEffectTargets.length && transitionEffectTargets.includes(target)) {
|
|
3979
4638
|
throw transitionEffectSignal;
|
|
3980
4639
|
}
|
|
3981
|
-
|
|
4640
|
+
// Returned so callers that can observe a host runtime's asynchronous
|
|
4641
|
+
// delivery do; the built-in runtime delivers synchronously.
|
|
4642
|
+
return this.sendEvent(source, target, event);
|
|
3982
4643
|
}
|
|
3983
4644
|
getSnapshot() {
|
|
3984
4645
|
return {
|
|
@@ -4014,7 +4675,12 @@ function createRuntimeSystem(rootActor, options) {
|
|
|
4014
4675
|
// oxlint-enable no-unused-vars
|
|
4015
4676
|
|
|
4016
4677
|
let executingCustomAction = false;
|
|
4017
|
-
|
|
4678
|
+
|
|
4679
|
+
/**
|
|
4680
|
+
* Marks a serialized object as an actor reference (`xstate$type` in JSON
|
|
4681
|
+
* output and persisted context).
|
|
4682
|
+
*/
|
|
4683
|
+
const ACTOR_REF_TYPE = 'actorRef';
|
|
4018
4684
|
const emptyInspectionRecords = Object.freeze([]);
|
|
4019
4685
|
|
|
4020
4686
|
// those values are currently used by @xstate/react directly so it's important to keep the assigned values in sync
|
|
@@ -4065,6 +4731,23 @@ function createActorRef(logic, options) {
|
|
|
4065
4731
|
* or read snapshots.
|
|
4066
4732
|
*/
|
|
4067
4733
|
class Actor {
|
|
4734
|
+
/**
|
|
4735
|
+
* The deterministic logical address of this actor within its system: the
|
|
4736
|
+
* `/`-joined path of actor ids from the root. Stable across persistence and
|
|
4737
|
+
* restore, unlike `sessionId`, which identifies one incarnation.
|
|
4738
|
+
*
|
|
4739
|
+
* `/` separates segments, so an id containing one (a state name with a
|
|
4740
|
+
* slash reaches its invoked child's id) is percent-encoded to keep the
|
|
4741
|
+
* path unambiguous.
|
|
4742
|
+
*/
|
|
4743
|
+
get address() {
|
|
4744
|
+
// `id` and `_parent` never change after construction, so the whole chain
|
|
4745
|
+
// memoizes to O(1) amortized.
|
|
4746
|
+
return this._address ??= this._parent ? `${this._parent.address}/${encodeAddressSegment(this.id)}` : encodeAddressSegment(this.id);
|
|
4747
|
+
}
|
|
4748
|
+
|
|
4749
|
+
/** The system to which this actor belongs. */
|
|
4750
|
+
|
|
4068
4751
|
get trigger() {
|
|
4069
4752
|
return this._trigger ??= new Proxy({}, {
|
|
4070
4753
|
get: (_, eventType) => {
|
|
@@ -4127,7 +4810,7 @@ class Actor {
|
|
|
4127
4810
|
this.registryKey = void 0;
|
|
4128
4811
|
/** The globally unique process ID for this invocation. */
|
|
4129
4812
|
this.sessionId = void 0;
|
|
4130
|
-
|
|
4813
|
+
this._address = void 0;
|
|
4131
4814
|
this.system = void 0;
|
|
4132
4815
|
this._trigger = void 0;
|
|
4133
4816
|
this._boundSend = void 0;
|
|
@@ -4162,7 +4845,10 @@ class Actor {
|
|
|
4162
4845
|
this.system.inspect(toObserver(inspect));
|
|
4163
4846
|
}
|
|
4164
4847
|
this.sessionId = resolvedOptions._sessionId ?? bookSessionId(this.system);
|
|
4165
|
-
this.id = resolveActorId(this.system, id
|
|
4848
|
+
this.id = resolveActorId(this.system, id, {
|
|
4849
|
+
parent,
|
|
4850
|
+
src: resolvedOptions.src ?? logic
|
|
4851
|
+
});
|
|
4166
4852
|
this.logger = options?.logger ?? this.system._logger;
|
|
4167
4853
|
this.clock = options?.clock ?? this.system._clock;
|
|
4168
4854
|
this._parent = parent;
|
|
@@ -4630,8 +5316,20 @@ class Actor {
|
|
|
4630
5316
|
}
|
|
4631
5317
|
if (this._restored) {
|
|
4632
5318
|
const timers = this._snapshot.timers ?? {};
|
|
5319
|
+
// startedAt is only persisted from — and only meaningful under — the
|
|
5320
|
+
// wall clock; a custom clock (a simulated clock, a monotonic counter)
|
|
5321
|
+
// restores every timer with its declared delay. The clamp bounds
|
|
5322
|
+
// remaining time by the declared delay in case the wall clock moved
|
|
5323
|
+
// backwards between persist and restore.
|
|
5324
|
+
const wallClock = !this.system._clock.now;
|
|
5325
|
+
const now = Date.now();
|
|
4633
5326
|
for (const timer of Object.values(timers)) {
|
|
4634
|
-
|
|
5327
|
+
// A timer persisted from a live runtime carries its wall-clock start;
|
|
5328
|
+
// honor the absolute deadline instead of restarting the full delay.
|
|
5329
|
+
// Without a start (a pure-transition snapshot, or an older snapshot)
|
|
5330
|
+
// the declared delay is all there is.
|
|
5331
|
+
const delay = wallClock && timer.startedAt !== undefined ? Math.min(timer.delay, Math.max(0, timer.startedAt + timer.delay - now)) : timer.delay;
|
|
5332
|
+
this.system.scheduleTimer(this, timer.id, delay);
|
|
4635
5333
|
}
|
|
4636
5334
|
this._restored = false;
|
|
4637
5335
|
}
|
|
@@ -4791,13 +5489,7 @@ class Actor {
|
|
|
4791
5489
|
/** @internal */
|
|
4792
5490
|
_send(event) {
|
|
4793
5491
|
if (this._processingStatus === ProcessingStatus.Stopped) {
|
|
4794
|
-
|
|
4795
|
-
{
|
|
4796
|
-
// TODO: circular serialization issues
|
|
4797
|
-
// const eventString = ''; //JSON.stringify(event);
|
|
4798
|
-
|
|
4799
|
-
console.warn(`Event "${event.type}" was sent to stopped actor "${this.id} (${this.sessionId})". This actor has already reached its final state, and will not transition.`);
|
|
4800
|
-
}
|
|
5492
|
+
this.system.deadLetter(this._lastSourceRef, this, event, 'stopped');
|
|
4801
5493
|
return;
|
|
4802
5494
|
}
|
|
4803
5495
|
let mailbox = this.mailbox;
|
|
@@ -4822,10 +5514,17 @@ class Actor {
|
|
|
4822
5514
|
}
|
|
4823
5515
|
this.system._relay(undefined, this, event);
|
|
4824
5516
|
}
|
|
5517
|
+
|
|
5518
|
+
/**
|
|
5519
|
+
* Returns the actor's serializable logical identity: its `id`, `address`,
|
|
5520
|
+
* and registered source key (when the actor was created from one).
|
|
5521
|
+
*/
|
|
4825
5522
|
toJSON() {
|
|
4826
5523
|
return {
|
|
4827
|
-
xstate
|
|
4828
|
-
id: this.id
|
|
5524
|
+
xstate$type: ACTOR_REF_TYPE,
|
|
5525
|
+
id: this.id,
|
|
5526
|
+
address: this.address,
|
|
5527
|
+
src: typeof this.src === 'string' ? this.src : undefined
|
|
4829
5528
|
};
|
|
4830
5529
|
}
|
|
4831
5530
|
|
|
@@ -4854,10 +5553,16 @@ class Actor {
|
|
|
4854
5553
|
* Read an actor’s snapshot synchronously.
|
|
4855
5554
|
*
|
|
4856
5555
|
* @remarks
|
|
4857
|
-
* The snapshot
|
|
5556
|
+
* The snapshot is the last value the actor published, not a query of its
|
|
5557
|
+
* private state: the actor emits a snapshot when it transitions, and this
|
|
5558
|
+
* returns that cached last emission. The read is coherent within one
|
|
5559
|
+
* synchronous transition turn because event processing runs to completion;
|
|
5560
|
+
* across asynchronous boundaries it may be stale, like any observed value.
|
|
4858
5561
|
*
|
|
4859
|
-
*
|
|
4860
|
-
*
|
|
5562
|
+
* Only co-located actors publish full snapshots. A location-transparent
|
|
5563
|
+
* remote handle exposes lifecycle only ({ status, output?, error? }): while
|
|
5564
|
+
* the handle exists among its parent's children the child is presumed
|
|
5565
|
+
* `active`, and its terminal result arrives as a completion event.
|
|
4861
5566
|
*
|
|
4862
5567
|
* Note that some actors, such as callback actors generated with
|
|
4863
5568
|
* `createCallbackLogic`, will not emit snapshots.
|
|
@@ -4914,14 +5619,21 @@ function createActor(logic, options) {
|
|
|
4914
5619
|
return new Actor(logic, options);
|
|
4915
5620
|
}
|
|
4916
5621
|
|
|
4917
|
-
exports
|
|
5622
|
+
exports.ACTOR_REF_TYPE = ACTOR_REF_TYPE;
|
|
4918
5623
|
exports.Actor = Actor;
|
|
4919
5624
|
exports.NULL_EVENT = NULL_EVENT;
|
|
5625
|
+
exports.RUNTIME_OPERATIONS = RUNTIME_OPERATIONS;
|
|
4920
5626
|
exports.STATE_DELIMITER = STATE_DELIMITER;
|
|
4921
5627
|
exports.XSTATE_INIT = XSTATE_INIT;
|
|
5628
|
+
exports.XSTATE_LOGIC_EFFECT_REJECT = XSTATE_LOGIC_EFFECT_REJECT;
|
|
5629
|
+
exports.XSTATE_LOGIC_EFFECT_RESOLVE = XSTATE_LOGIC_EFFECT_RESOLVE;
|
|
5630
|
+
exports.XSTATE_LOGIC_EFFECT_START = XSTATE_LOGIC_EFFECT_START;
|
|
4922
5631
|
exports.XSTATE_STOP = XSTATE_STOP;
|
|
4923
5632
|
exports.XSTATE_TIMER = XSTATE_TIMER;
|
|
5633
|
+
exports.allocateChildId = allocateChildId;
|
|
5634
|
+
exports.assertChildIdFree = assertChildIdFree;
|
|
4924
5635
|
exports.attachSnapshotActorRef = attachSnapshotActorRef;
|
|
5636
|
+
exports.beginSpawnAllocation = beginSpawnAllocation;
|
|
4925
5637
|
exports.builtInActions = builtInActions;
|
|
4926
5638
|
exports.checkStateIn = checkStateIn;
|
|
4927
5639
|
exports.cloneMachineSnapshot = cloneMachineSnapshot;
|
|
@@ -4936,16 +5648,20 @@ exports.createInvokeTimeoutEvent = createInvokeTimeoutEvent;
|
|
|
4936
5648
|
exports.createInvokeTimeoutEventId = createInvokeTimeoutEventId;
|
|
4937
5649
|
exports.createListenerLogic = createListenerLogic;
|
|
4938
5650
|
exports.createMachineSnapshot = createMachineSnapshot;
|
|
5651
|
+
exports.createRemoteActorRef = createRemoteActorRef;
|
|
4939
5652
|
exports.createSendToEffect = createSendToEffect;
|
|
4940
5653
|
exports.createSpawnEffect = createSpawnEffect;
|
|
4941
5654
|
exports.createSubscriptionLogic = createSubscriptionLogic;
|
|
4942
5655
|
exports.createTransitionEnqueue = createTransitionEnqueue;
|
|
5656
|
+
exports.deliverEvent = deliverEvent;
|
|
4943
5657
|
exports.deriveDeferredStarts = deriveDeferredStarts;
|
|
5658
|
+
exports.encodeAddressSegment = encodeAddressSegment;
|
|
4944
5659
|
exports.evaluateCandidate = evaluateCandidate;
|
|
4945
5660
|
exports.executeEffects = executeEffects;
|
|
4946
5661
|
exports.finalizeTransitionResult = finalizeTransitionResult;
|
|
4947
5662
|
exports.formatRouteTransitions = formatRouteTransitions;
|
|
4948
5663
|
exports.formatTransition = formatTransition;
|
|
5664
|
+
exports.getActorIdPrefix = getActorIdPrefix;
|
|
4949
5665
|
exports.getAllOwnEventDescriptors = getAllOwnEventDescriptors;
|
|
4950
5666
|
exports.getAllOwnEvents = getAllOwnEvents;
|
|
4951
5667
|
exports.getAllStateNodes = getAllStateNodes;
|
|
@@ -4956,6 +5672,8 @@ exports.getInitialSnapshot = getInitialSnapshot;
|
|
|
4956
5672
|
exports.getNextSnapshot = getNextSnapshot;
|
|
4957
5673
|
exports.getPersistedSnapshot = getPersistedSnapshot;
|
|
4958
5674
|
exports.getProperAncestors = getProperAncestors;
|
|
5675
|
+
exports.getRootActorId = getRootActorId;
|
|
5676
|
+
exports.getSnapshotActorRef = getSnapshotActorRef;
|
|
4959
5677
|
exports.getStateNodeByPath = getStateNodeByPath;
|
|
4960
5678
|
exports.getStateNodes = getStateNodes;
|
|
4961
5679
|
exports.getTransitionResult = getTransitionResult;
|
|
@@ -4975,14 +5693,21 @@ exports.matchesActorSession = matchesActorSession;
|
|
|
4975
5693
|
exports.matchesEvent = matchesEvent;
|
|
4976
5694
|
exports.matchesEventDescriptor = matchesEventDescriptor;
|
|
4977
5695
|
exports.matchesState = matchesState;
|
|
5696
|
+
exports.mergeActorIdCounters = mergeActorIdCounters;
|
|
4978
5697
|
exports.parseDelayToMilliseconds = parseDelayToMilliseconds;
|
|
5698
|
+
exports.parseGeneratedActorId = parseGeneratedActorId;
|
|
4979
5699
|
exports.pathToStateValue = pathToStateValue;
|
|
5700
|
+
exports.reserveChildId = reserveChildId;
|
|
4980
5701
|
exports.resolveActionsWithContext = resolveActionsWithContext;
|
|
4981
5702
|
exports.resolveReferencedActor = resolveReferencedActor;
|
|
4982
5703
|
exports.resolveStateValue = resolveStateValue;
|
|
5704
|
+
exports.runStep = runStep;
|
|
4983
5705
|
exports.setInertActorScopeSnapshot = setInertActorScopeSnapshot;
|
|
4984
5706
|
exports.setSnapshotActorRef = setSnapshotActorRef;
|
|
5707
|
+
exports.stopActor = stopActor;
|
|
4985
5708
|
exports.subscriptionLogic = subscriptionLogic;
|
|
5709
|
+
exports.takeSpawnAllocationCounters = takeSpawnAllocationCounters;
|
|
5710
|
+
exports.terminateActor = terminateActor;
|
|
4986
5711
|
exports.toArray = toArray;
|
|
4987
5712
|
exports.toObserver = toObserver;
|
|
4988
5713
|
exports.toStatePath = toStatePath;
|