xstate 6.0.0-beta.1 → 6.0.0-beta.3
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/README.md +4 -2
- package/dist/{createActor-cbe3abac.esm.js → createActor-49ea55ba.esm.js} +259 -47
- package/dist/{createActor-25900f76.cjs.js → createActor-73aa92ba.cjs.js} +261 -46
- package/dist/{createActor-551369be.development.esm.js → createActor-a085b20b.development.esm.js} +260 -48
- package/dist/{createActor-a49ae0ce.development.cjs.js → createActor-dfb6b790.development.cjs.js} +262 -47
- package/dist/declarations/src/createActor.d.ts +3 -1
- package/dist/declarations/src/createMachine.d.ts +6 -3
- package/dist/declarations/src/durable/index.d.ts +43 -8
- package/dist/declarations/src/effectDescriptor.d.ts +2 -2
- package/dist/declarations/src/fsm.d.ts +7 -7
- package/dist/declarations/src/machineVersion.types.d.ts +2 -2
- package/dist/declarations/src/setup.d.ts +2 -2
- package/dist/declarations/src/systemTransition.d.ts +1 -1
- package/dist/declarations/src/types.d.ts +4 -2
- package/dist/declarations/src/types.v6.d.ts +37 -2
- package/dist/{effectDescriptor-2fa27c54.cjs.js → effectDescriptor-3402f63e.cjs.js} +5 -5
- package/dist/{effectDescriptor-d8b0f749.esm.js → effectDescriptor-65821048.development.esm.js} +5 -5
- package/dist/{effectDescriptor-321a8ce9.development.esm.js → effectDescriptor-72c62058.esm.js} +5 -5
- package/dist/{effectDescriptor-f73da4ec.development.cjs.js → effectDescriptor-d0ea44ad.development.cjs.js} +5 -5
- package/dist/{machineSchemas-b5736804.development.esm.js → legacySnapshot-11aba2d2.development.esm.js} +117 -3
- package/dist/{machineSchemas-6d96bef4.development.cjs.js → legacySnapshot-2e2c1d3b.development.cjs.js} +118 -2
- package/dist/{machineSchemas-88d01821.cjs.js → legacySnapshot-a85dfbe2.cjs.js} +117 -1
- package/dist/{machineSchemas-45c21bc2.esm.js → legacySnapshot-fffe81a0.esm.js} +116 -2
- package/dist/xstate-actors.cjs.js +30 -5
- package/dist/xstate-actors.development.cjs.js +30 -5
- package/dist/xstate-actors.development.esm.js +31 -6
- package/dist/xstate-actors.esm.js +31 -6
- 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 +120 -10
- package/dist/xstate-durable.development.cjs.js +120 -10
- package/dist/xstate-durable.development.esm.js +120 -10
- package/dist/xstate-durable.esm.js +120 -10
- package/dist/xstate-durable.umd.min.js +1 -1
- package/dist/xstate-durable.umd.min.js.map +1 -1
- package/dist/xstate-fsm.cjs.js +61 -31
- package/dist/xstate-fsm.development.cjs.js +61 -31
- package/dist/xstate-fsm.development.esm.js +61 -31
- package/dist/xstate-fsm.esm.js +61 -31
- package/dist/xstate-fsm.umd.min.js +1 -1
- package/dist/xstate-fsm.umd.min.js.map +1 -1
- package/dist/xstate-graph.cjs.js +1 -1
- package/dist/xstate-graph.development.cjs.js +1 -1
- package/dist/xstate-graph.development.esm.js +2 -2
- package/dist/xstate-graph.esm.js +2 -2
- package/dist/xstate-graph.umd.min.js +1 -1
- package/dist/xstate-graph.umd.min.js.map +1 -1
- package/dist/xstate-persist.cjs.js +23 -12
- package/dist/xstate-persist.development.cjs.js +23 -12
- package/dist/xstate-persist.development.esm.js +17 -6
- package/dist/xstate-persist.esm.js +17 -6
- package/dist/xstate-persist.umd.min.js +1 -1
- package/dist/xstate-persist.umd.min.js.map +1 -1
- package/dist/xstate-validation.cjs.js +1 -1
- package/dist/xstate-validation.development.cjs.js +1 -1
- package/dist/xstate-validation.development.esm.js +1 -1
- package/dist/xstate-validation.esm.js +1 -1
- package/dist/xstate.cjs.js +86 -56
- package/dist/xstate.development.cjs.js +86 -56
- package/dist/xstate.development.esm.js +76 -46
- package/dist/xstate.esm.js +76 -46
- package/dist/xstate.umd.min.js +1 -1
- package/dist/xstate.umd.min.js.map +1 -1
- package/docs/actor-logic.md +1 -1
- package/docs/api-stability.json +335 -305
- package/docs/backend-workflows.md +3 -3
- package/docs/durable-execution.md +72 -48
- package/docs/errors.md +2 -2
- package/docs/examples.md +34 -34
- package/docs/faq.md +1 -1
- package/docs/fsm.md +54 -10
- package/docs/guards.md +1 -1
- package/docs/index.md +2 -1
- package/docs/inspect-actor-systems.md +20 -3
- package/docs/inspection.md +5 -1
- package/docs/invoke.md +36 -4
- package/docs/migrate-inspector.md +141 -0
- package/docs/persistence.md +16 -10
- package/docs/serialization.md +1 -1
- package/docs/setup-and-provide.md +3 -3
- package/docs/spawn.md +1 -1
- package/docs/system-transitions.md +8 -6
- package/docs/transitions.md +5 -1
- package/docs/tutorial.md +5 -5
- package/docs/typescript.md +9 -0
- package/docs/xstate-v5-to-v6.md +23 -21
- package/package.json +1 -1
|
@@ -166,11 +166,11 @@ function isRemoteActorRef(actorRef) {
|
|
|
166
166
|
* JSON (`actor.toJSON()`): plain data carrying an address, not an actor.
|
|
167
167
|
*/
|
|
168
168
|
function isSerializedActorRef(target) {
|
|
169
|
-
if (typeof target !== 'object' || target === null || Array.isArray(target) || typeof target
|
|
169
|
+
if (typeof target !== 'object' || target === null || Array.isArray(target) || typeof target['@actor'] !== 'string') {
|
|
170
170
|
return false;
|
|
171
171
|
}
|
|
172
172
|
for (const key in target) {
|
|
173
|
-
if (key !== '
|
|
173
|
+
if (key !== '@actor' && key !== 'incarnation') {
|
|
174
174
|
return false;
|
|
175
175
|
}
|
|
176
176
|
}
|
|
@@ -186,7 +186,7 @@ function getAddressId(address) {
|
|
|
186
186
|
|
|
187
187
|
/** @internal The error reported when no live actor has a serialized address. */
|
|
188
188
|
function createMissingAddressError(target) {
|
|
189
|
-
return new Error(xstateError(50, ...(target.incarnation === undefined ? [target
|
|
189
|
+
return new Error(xstateError(50, ...(target.incarnation === undefined ? [target['@actor']] : [target['@actor'], target.incarnation])) );
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
/**
|
|
@@ -195,7 +195,7 @@ function createMissingAddressError(target) {
|
|
|
195
195
|
* without one follows whichever actor is live at the address.
|
|
196
196
|
*/
|
|
197
197
|
function resolveSerializedActorRef(system, target) {
|
|
198
|
-
const live = system._getByAddress?.(target
|
|
198
|
+
const live = system._getByAddress?.(target['@actor']);
|
|
199
199
|
return live && (target.incarnation === undefined || live.sessionId === target.incarnation) ? live : undefined;
|
|
200
200
|
}
|
|
201
201
|
|
|
@@ -248,7 +248,7 @@ function createInertActorRef(options) {
|
|
|
248
248
|
throw new Error(xstateError(51, id));
|
|
249
249
|
}
|
|
250
250
|
return {
|
|
251
|
-
|
|
251
|
+
'@actor': address
|
|
252
252
|
};
|
|
253
253
|
}
|
|
254
254
|
};
|
|
@@ -334,7 +334,7 @@ function createRemoteActorRef(system, options) {
|
|
|
334
334
|
// one actor-reference shape whether a child is co-located or remote.
|
|
335
335
|
toJSON() {
|
|
336
336
|
return {
|
|
337
|
-
|
|
337
|
+
'@actor': options.address
|
|
338
338
|
};
|
|
339
339
|
}
|
|
340
340
|
};
|
|
@@ -454,7 +454,7 @@ function deliverEvent(source, target, event) {
|
|
|
454
454
|
throw error;
|
|
455
455
|
}
|
|
456
456
|
void system.deadLetter(source, undefined, event, 'missingTarget', {
|
|
457
|
-
targetId: getAddressId(serialized
|
|
457
|
+
targetId: getAddressId(serialized['@actor']),
|
|
458
458
|
error
|
|
459
459
|
});
|
|
460
460
|
return;
|
|
@@ -907,6 +907,7 @@ function resolveRegisteredActorSource(actors, logic) {
|
|
|
907
907
|
const systemLogicMetadata = Symbol('xstate.systemLogicMetadata');
|
|
908
908
|
|
|
909
909
|
const subscriptions = /* #__PURE__ */new WeakMap();
|
|
910
|
+
const XSTATE_ATTACHED_FORWARD = 'xstate.attached.forward';
|
|
910
911
|
|
|
911
912
|
/**
|
|
912
913
|
* Internal factory for actor logic that attaches to another actor on start
|
|
@@ -969,9 +970,11 @@ id) {
|
|
|
969
970
|
unsubscribe: teardown
|
|
970
971
|
});
|
|
971
972
|
},
|
|
972
|
-
transition: (state, event, {
|
|
973
|
-
self
|
|
974
|
-
|
|
973
|
+
transition: (state, event, scope) => {
|
|
974
|
+
const self = scope.self;
|
|
975
|
+
if (event.type === XSTATE_ATTACHED_FORWARD) {
|
|
976
|
+
return [state, state.status === 'active' && self._parent ? [createSendToEffect(scope, self._parent, event.event)] : []];
|
|
977
|
+
}
|
|
975
978
|
if (event.type === XSTATE_STOP) {
|
|
976
979
|
subscriptions.get(self)?.unsubscribe();
|
|
977
980
|
subscriptions.delete(self);
|
|
@@ -986,7 +989,8 @@ id) {
|
|
|
986
989
|
initialTransition,
|
|
987
990
|
getInitialSnapshot: (actorScope, input) => initialTransition(input)[0],
|
|
988
991
|
getPersistedSnapshot: snapshot => snapshot,
|
|
989
|
-
restoreSnapshot: snapshot => snapshot
|
|
992
|
+
restoreSnapshot: snapshot => snapshot,
|
|
993
|
+
isInternalEventType: eventType => eventType === XSTATE_ATTACHED_FORWARD
|
|
990
994
|
};
|
|
991
995
|
Object.defineProperty(logic, systemLogicMetadata, {
|
|
992
996
|
value: {
|
|
@@ -1004,7 +1008,10 @@ function relayMappedToParent(self, system, getEvent) {
|
|
|
1004
1008
|
if (self.getSnapshot().status === 'stopped' || !self._parent) {
|
|
1005
1009
|
return;
|
|
1006
1010
|
}
|
|
1007
|
-
system._relay(self, self
|
|
1011
|
+
system._relay(self, self, {
|
|
1012
|
+
type: XSTATE_ATTACHED_FORWARD,
|
|
1013
|
+
event: getEvent()
|
|
1014
|
+
});
|
|
1008
1015
|
}
|
|
1009
1016
|
|
|
1010
1017
|
/** @public */
|
|
@@ -2114,6 +2121,18 @@ function withSystemInspector(inspect, fn) {
|
|
|
2114
2121
|
|
|
2115
2122
|
/** Snapshot-scoped actor identity and system view. @internal */
|
|
2116
2123
|
|
|
2124
|
+
// Each view's execution system and whether it forwards inspection. Views
|
|
2125
|
+
// never chain: they all inherit from the execution system directly.
|
|
2126
|
+
const snapshotSystemViews = new WeakMap();
|
|
2127
|
+
// Facilities owned by the execution rather than by one snapshot's view. A view
|
|
2128
|
+
// reads and writes them on the execution system, so timers, listeners and the
|
|
2129
|
+
// runtime installed through any snapshot are visible through every other.
|
|
2130
|
+
const executionFacilities = ['runtime', '_timerMap', '_rejectionListeners', '_inspectionObservers', '_emissionListeners'];
|
|
2131
|
+
// The durable execution that owns each execution system.
|
|
2132
|
+
/** A durable execution, as the owner of the views its transitions create. @internal */
|
|
2133
|
+
|
|
2134
|
+
const executionOwners = new WeakMap();
|
|
2135
|
+
let ambientExecutionOwner;
|
|
2117
2136
|
const snapshotActorRefs = new WeakMap();
|
|
2118
2137
|
const lazySnapshotActorRefs = new WeakMap();
|
|
2119
2138
|
const emptyKeyedActors = new Map();
|
|
@@ -2173,12 +2192,22 @@ function getSnapshotChildren(snapshot) {
|
|
|
2173
2192
|
*
|
|
2174
2193
|
* @internal
|
|
2175
2194
|
*/
|
|
2176
|
-
function createSnapshotSystem(baseSystem, children, baseState) {
|
|
2177
|
-
const
|
|
2195
|
+
function createSnapshotSystem(baseSystem, children, baseState, owner) {
|
|
2196
|
+
const baseView = snapshotSystemViews.get(baseSystem);
|
|
2197
|
+
const baseExecutionSystem = baseView?.executionSystem ?? baseSystem;
|
|
2198
|
+
// The runtime system under every view. A view runs its methods against the
|
|
2199
|
+
// execution system's facilities.
|
|
2200
|
+
const rootSystem = baseView?.rootSystem ?? baseSystem;
|
|
2201
|
+
const forks = owner !== undefined && executionOwners.get(baseExecutionSystem) !== owner;
|
|
2202
|
+
// A view an execution owns reports to that execution's inspector.
|
|
2203
|
+
const forwardInspection = owner ? !!owner.inspect : hasAmbientInspector() && (baseView?.forwardInspection ?? true);
|
|
2178
2204
|
const registeredActors = copyRegisteredActors(baseSystem, baseState);
|
|
2179
2205
|
const keyedActors = new Map(baseState?.keyedActors ?? getKeyedActors(baseSystem));
|
|
2180
2206
|
const reverseKeyedActors = new WeakMap();
|
|
2181
|
-
|
|
2207
|
+
// The view's execution system; adoption can make the view its own.
|
|
2208
|
+
const execution = () => snapshotSystemViews.get(system).executionSystem;
|
|
2209
|
+
const forwards = () => snapshotSystemViews.get(system).forwardInspection;
|
|
2210
|
+
const system = Object.assign(Object.create(baseExecutionSystem), {
|
|
2182
2211
|
children: registeredActors,
|
|
2183
2212
|
keyedActors,
|
|
2184
2213
|
reverseKeyedActors,
|
|
@@ -2213,15 +2242,38 @@ function createSnapshotSystem(baseSystem, children, baseState) {
|
|
|
2213
2242
|
},
|
|
2214
2243
|
get: registryKey => keyedActors.get(registryKey),
|
|
2215
2244
|
getAll: () => Object.fromEntries(keyedActors),
|
|
2216
|
-
onEmitted: listener =>
|
|
2217
|
-
_notifyEmitted: (actorRef, event) =>
|
|
2245
|
+
onEmitted: listener => rootSystem.onEmitted.call(execution(), listener),
|
|
2246
|
+
_notifyEmitted: (actorRef, event) => rootSystem._notifyEmitted.call(execution(), actorRef, event),
|
|
2218
2247
|
// Pure transition resolution must not leak topology inspection events
|
|
2219
2248
|
// into a live runtime system — planning branches stay silent. The one
|
|
2220
2249
|
// exception is a durable execution's own transitions (marked by the
|
|
2221
2250
|
// ambient inspector at creation time): there the pure path IS the
|
|
2222
|
-
// execution, so inspection forwards to the
|
|
2223
|
-
_hasInspectionObservers:
|
|
2224
|
-
_sendInspectionEvent:
|
|
2251
|
+
// execution, so inspection forwards to the execution system's observers.
|
|
2252
|
+
_hasInspectionObservers: () => forwards() && (rootSystem._hasInspectionObservers?.call(execution()) ?? false),
|
|
2253
|
+
_sendInspectionEvent: event => {
|
|
2254
|
+
if (forwards()) {
|
|
2255
|
+
rootSystem._sendInspectionEvent.call(execution(), event);
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
});
|
|
2259
|
+
const executionSystem = forks ? system : baseExecutionSystem;
|
|
2260
|
+
if (forks) {
|
|
2261
|
+
forkFacilities(system, baseExecutionSystem, owner);
|
|
2262
|
+
} else {
|
|
2263
|
+
for (const key of executionFacilities) {
|
|
2264
|
+
Object.defineProperty(system, key, {
|
|
2265
|
+
configurable: true,
|
|
2266
|
+
get: () => execution()[key],
|
|
2267
|
+
set: value => {
|
|
2268
|
+
execution()[key] = value;
|
|
2269
|
+
}
|
|
2270
|
+
});
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
snapshotSystemViews.set(system, {
|
|
2274
|
+
executionSystem,
|
|
2275
|
+
rootSystem,
|
|
2276
|
+
forwardInspection
|
|
2225
2277
|
});
|
|
2226
2278
|
for (const [registryKey, actor] of keyedActors) {
|
|
2227
2279
|
if (!actor) {
|
|
@@ -2245,6 +2297,83 @@ function createSnapshotSystem(baseSystem, children, baseState) {
|
|
|
2245
2297
|
return system;
|
|
2246
2298
|
}
|
|
2247
2299
|
|
|
2300
|
+
/**
|
|
2301
|
+
* Makes `system` the execution system of `owner`, a new incarnation: it gets
|
|
2302
|
+
* the owner's runtime and the pending timers it saw, and starts with no
|
|
2303
|
+
* listeners or inspectors, so nothing registered on another execution
|
|
2304
|
+
* observes it.
|
|
2305
|
+
*/
|
|
2306
|
+
function forkFacilities(system, from, owner) {
|
|
2307
|
+
const timers = from._timerMap;
|
|
2308
|
+
for (const key of executionFacilities) {
|
|
2309
|
+
Object.defineProperty(system, key, {
|
|
2310
|
+
configurable: true,
|
|
2311
|
+
writable: true,
|
|
2312
|
+
value: key === 'runtime' ? owner.runtime : key === '_timerMap' && timers ? {
|
|
2313
|
+
...timers
|
|
2314
|
+
} : undefined
|
|
2315
|
+
});
|
|
2316
|
+
}
|
|
2317
|
+
executionOwners.set(system, owner);
|
|
2318
|
+
if (owner.inspect) {
|
|
2319
|
+
system.inspect(owner.inspect);
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
|
|
2323
|
+
/**
|
|
2324
|
+
* Makes `owner` own `system` before it installs its runtime there, and
|
|
2325
|
+
* returns whether it does. An unowned view forks in place, so the install
|
|
2326
|
+
* never reaches the system it was derived from. A system another execution
|
|
2327
|
+
* owns is left alone.
|
|
2328
|
+
*
|
|
2329
|
+
* @internal
|
|
2330
|
+
*/
|
|
2331
|
+
function adoptSystem(system, owner) {
|
|
2332
|
+
const view = snapshotSystemViews.get(system);
|
|
2333
|
+
const current = executionOwners.get(view?.executionSystem ?? system);
|
|
2334
|
+
if (current === owner) {
|
|
2335
|
+
if (view) {
|
|
2336
|
+
view.forwardInspection = !!owner.inspect;
|
|
2337
|
+
}
|
|
2338
|
+
return true;
|
|
2339
|
+
}
|
|
2340
|
+
// A system another execution owns stays with it.
|
|
2341
|
+
if (current) {
|
|
2342
|
+
return false;
|
|
2343
|
+
}
|
|
2344
|
+
if (!view) {
|
|
2345
|
+
executionOwners.set(system, owner);
|
|
2346
|
+
return true;
|
|
2347
|
+
}
|
|
2348
|
+
forkFacilities(system, view.executionSystem, owner);
|
|
2349
|
+
view.executionSystem = system;
|
|
2350
|
+
view.forwardInspection = !!owner.inspect;
|
|
2351
|
+
return true;
|
|
2352
|
+
}
|
|
2353
|
+
|
|
2354
|
+
/**
|
|
2355
|
+
* Runs `fn` as a transition of `owner`. A view it derives from a system the
|
|
2356
|
+
* owner does not own forks into the owner's own execution system.
|
|
2357
|
+
*
|
|
2358
|
+
* @internal
|
|
2359
|
+
*/
|
|
2360
|
+
function withExecutionOwner(owner, fn) {
|
|
2361
|
+
const previous = ambientExecutionOwner;
|
|
2362
|
+
ambientExecutionOwner = owner;
|
|
2363
|
+
try {
|
|
2364
|
+
return fn();
|
|
2365
|
+
} finally {
|
|
2366
|
+
ambientExecutionOwner = previous;
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
|
|
2370
|
+
/** Hands the ambient owner to the first scope that asks for it. @internal */
|
|
2371
|
+
function takeExecutionOwner() {
|
|
2372
|
+
const owner = ambientExecutionOwner;
|
|
2373
|
+
ambientExecutionOwner = undefined;
|
|
2374
|
+
return owner;
|
|
2375
|
+
}
|
|
2376
|
+
|
|
2248
2377
|
/** Returns the actor identity associated with a transition snapshot. @internal */
|
|
2249
2378
|
function getSnapshotActorRef(snapshot) {
|
|
2250
2379
|
const existing = snapshotActorRefs.get(snapshot);
|
|
@@ -2438,8 +2567,9 @@ function setInertActorScopeSnapshot(actorScope, snapshot, attachActorRef = true)
|
|
|
2438
2567
|
const lazyState = getLazyInertActorState(actorScope);
|
|
2439
2568
|
if (lazyState) {
|
|
2440
2569
|
lazyState.snapshot = snapshot;
|
|
2441
|
-
|
|
2442
|
-
|
|
2570
|
+
const scope = lazyState.materialized ?? lazyState.identityScope;
|
|
2571
|
+
if (scope) {
|
|
2572
|
+
scope.self._snapshot = snapshot;
|
|
2443
2573
|
}
|
|
2444
2574
|
} else {
|
|
2445
2575
|
actorScope.self._snapshot = snapshot;
|
|
@@ -2474,6 +2604,15 @@ function attachSnapshotActorRef(actorScope, snapshot) {
|
|
|
2474
2604
|
setLazySnapshotActorRef(snapshot, create);
|
|
2475
2605
|
return snapshot;
|
|
2476
2606
|
}
|
|
2607
|
+
/** Records the materialized scope and releases its consumed source. */
|
|
2608
|
+
function commitMaterialization(state, scope) {
|
|
2609
|
+
// Dropping the consumed source keeps this scope from retaining earlier snapshots.
|
|
2610
|
+
state.sourceRef = undefined;
|
|
2611
|
+
state.sourceChildren = {};
|
|
2612
|
+
state.materialized = scope;
|
|
2613
|
+
state.materialize = () => scope;
|
|
2614
|
+
return scope;
|
|
2615
|
+
}
|
|
2477
2616
|
const lazyInertActorState = Symbol();
|
|
2478
2617
|
const snapshotActorScopes = new WeakMap();
|
|
2479
2618
|
let inertActorMaterializationObserver;
|
|
@@ -2518,12 +2657,14 @@ const lazyInertActorScopePrototype = {
|
|
|
2518
2657
|
return materializeInertActorScope(this).actionExecutor;
|
|
2519
2658
|
}
|
|
2520
2659
|
};
|
|
2521
|
-
|
|
2660
|
+
|
|
2661
|
+
/** Creates a transactional planning scope backed by an inert actor. */
|
|
2662
|
+
function createMaterializedInertActorScope(actorLogic, sourceRef, sourceChildren, currentSnapshot, sourceSelf, owner) {
|
|
2522
2663
|
inertActorMaterializationObserver?.();
|
|
2523
2664
|
const snapshotRef = sourceRef?.();
|
|
2524
2665
|
const previousSelf = sourceSelf ?? snapshotRef?.actor;
|
|
2525
2666
|
const baseSystem = previousSelf?.system;
|
|
2526
|
-
const system = previousSelf && baseSystem ? createSnapshotSystem(baseSystem, sourceChildren, sourceSelf ? undefined : snapshotRef?.systemState) : undefined;
|
|
2667
|
+
const system = previousSelf && baseSystem ? createSnapshotSystem(baseSystem, sourceChildren, sourceSelf ? undefined : snapshotRef?.systemState, owner) : undefined;
|
|
2527
2668
|
const self = createActor(actorLogic, {
|
|
2528
2669
|
_inert: true,
|
|
2529
2670
|
...(previousSelf ? {
|
|
@@ -2543,12 +2684,8 @@ function createMaterializedInertActorScope(actorLogic, sourceRef, sourceChildren
|
|
|
2543
2684
|
// a future construction-time read cannot pin a root-shaped address.
|
|
2544
2685
|
self._address = undefined;
|
|
2545
2686
|
}
|
|
2546
|
-
if (currentSnapshot) {
|
|
2547
|
-
self._snapshot = currentSnapshot;
|
|
2548
|
-
}
|
|
2549
|
-
|
|
2550
2687
|
// Reuse the branch actor's scope while keeping planning transactional.
|
|
2551
|
-
|
|
2688
|
+
const scope = Object.create(self._actorScope, {
|
|
2552
2689
|
defer: {
|
|
2553
2690
|
value: () => {}
|
|
2554
2691
|
},
|
|
@@ -2557,8 +2694,20 @@ function createMaterializedInertActorScope(actorLogic, sourceRef, sourceChildren
|
|
|
2557
2694
|
},
|
|
2558
2695
|
actionExecutor: {
|
|
2559
2696
|
value: () => {}
|
|
2697
|
+
},
|
|
2698
|
+
_snapshot: {
|
|
2699
|
+
enumerable: true,
|
|
2700
|
+
configurable: true,
|
|
2701
|
+
get: () => self._snapshot,
|
|
2702
|
+
set: snapshot => {
|
|
2703
|
+
self._snapshot = snapshot;
|
|
2704
|
+
}
|
|
2560
2705
|
}
|
|
2561
2706
|
});
|
|
2707
|
+
if (currentSnapshot) {
|
|
2708
|
+
scope._snapshot = currentSnapshot;
|
|
2709
|
+
}
|
|
2710
|
+
return scope;
|
|
2562
2711
|
}
|
|
2563
2712
|
|
|
2564
2713
|
/** @internal */
|
|
@@ -2573,22 +2722,34 @@ function createInertActorScope(actorLogic, snapshot, sourceSelf, sourceActorScop
|
|
|
2573
2722
|
sourceChildren: isMachineSnapshot(snapshot) ? snapshot.children : {},
|
|
2574
2723
|
identityProvider: sourceState?.identityProvider ?? sourceRef,
|
|
2575
2724
|
parent: sourceSelf?._parent ?? sourceState?.parent ?? eagerSourceRef?.actor._parent,
|
|
2725
|
+
// Only the outermost scope of an owned transition belongs to the owner;
|
|
2726
|
+
// scopes for its intermediate snapshots inherit it, and nested pure
|
|
2727
|
+
// transitions run unowned.
|
|
2728
|
+
owner: sourceActorScope ? sourceState?.owner : takeExecutionOwner(),
|
|
2576
2729
|
parentKnown: !!sourceSelf || !!sourceState?.parentKnown || !!eagerSourceRef || !snapshot
|
|
2577
2730
|
};
|
|
2578
|
-
state.materialize = () =>
|
|
2731
|
+
state.materialize = () => {
|
|
2732
|
+
const scope = createMaterializedInertActorScope(actorLogic, state.sourceRef, state.sourceChildren, state.snapshot, sourceSelf, state.owner);
|
|
2733
|
+
return commitMaterialization(state, scope);
|
|
2734
|
+
};
|
|
2579
2735
|
if (!state.identityProvider && !snapshot) {
|
|
2580
2736
|
const identitySnapshot = {};
|
|
2581
|
-
const identitySourceRef = state.sourceRef;
|
|
2582
|
-
const identitySourceChildren = state.sourceChildren;
|
|
2583
|
-
let identityScope;
|
|
2584
2737
|
let identityRef;
|
|
2585
|
-
const getIdentityScope = () =>
|
|
2738
|
+
const getIdentityScope = () => {
|
|
2739
|
+
if (!state.identityScope) {
|
|
2740
|
+
state.identityScope = createMaterializedInertActorScope(actorLogic, state.sourceRef, state.sourceChildren, undefined, sourceSelf, state.owner);
|
|
2741
|
+
if (state.snapshot !== undefined) {
|
|
2742
|
+
state.identityScope.self._snapshot = state.snapshot;
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
return state.identityScope;
|
|
2746
|
+
};
|
|
2586
2747
|
state.materialize = () => {
|
|
2587
2748
|
const scope = getIdentityScope();
|
|
2588
2749
|
if (state.snapshot !== undefined) {
|
|
2589
2750
|
scope.self._snapshot = state.snapshot;
|
|
2590
2751
|
}
|
|
2591
|
-
return state
|
|
2752
|
+
return commitMaterialization(state, scope);
|
|
2592
2753
|
};
|
|
2593
2754
|
state.identityProvider = () => {
|
|
2594
2755
|
if (identityRef) {
|
|
@@ -3716,7 +3877,7 @@ function microstep(transitions, currentSnapshot, actorScope, event, isInitial, i
|
|
|
3716
3877
|
}
|
|
3717
3878
|
addAncestorStatesToEnter(ancestors, !transition.source.parent && reenter ? undefined : domain);
|
|
3718
3879
|
}
|
|
3719
|
-
if (reenter && domain === transition.source) {
|
|
3880
|
+
if (targets?.length && reenter && domain === transition.source) {
|
|
3720
3881
|
// A reentering transition whose domain is its own source exits and
|
|
3721
3882
|
// reenters the source, so the source must be entered explicitly —
|
|
3722
3883
|
// it has no ancestor inside the domain to add it.
|
|
@@ -4265,7 +4426,9 @@ function macrostep(snapshot, event, actorScope, internalQueue, initialMicrosteps
|
|
|
4265
4426
|
if (!internalQueue.length && snapshot.machine._hasEventlessTransitions === false) {
|
|
4266
4427
|
return completeMacrostep();
|
|
4267
4428
|
}
|
|
4268
|
-
|
|
4429
|
+
|
|
4430
|
+
// A timer notification must not run eventless transitions before delivery.
|
|
4431
|
+
let shouldSelectEventlessTransitions = event.type !== XSTATE_TIMER;
|
|
4269
4432
|
const maxIterations = snapshot.machine.options?.maxIterations ?? Infinity;
|
|
4270
4433
|
let iterationCount = 0;
|
|
4271
4434
|
// The last few state values visited, for the infinite-loop error.
|
|
@@ -4561,6 +4724,8 @@ const machineSnapshotToJSON = function toJSON() {
|
|
|
4561
4724
|
const {
|
|
4562
4725
|
nodes,
|
|
4563
4726
|
_stateInputs,
|
|
4727
|
+
_nextTimerId,
|
|
4728
|
+
_nextActorIds,
|
|
4564
4729
|
tags,
|
|
4565
4730
|
machine,
|
|
4566
4731
|
getMeta,
|
|
@@ -4679,6 +4844,8 @@ function getPersistedSnapshot(snapshot, options) {
|
|
|
4679
4844
|
const {
|
|
4680
4845
|
nodes,
|
|
4681
4846
|
_stateInputs,
|
|
4847
|
+
_nextTimerId,
|
|
4848
|
+
_nextActorIds,
|
|
4682
4849
|
tags,
|
|
4683
4850
|
machine,
|
|
4684
4851
|
children,
|
|
@@ -4805,6 +4972,11 @@ function getPersistedSnapshot(snapshot, options) {
|
|
|
4805
4972
|
if (_stateInputs && Object.keys(_stateInputs).length > 0) {
|
|
4806
4973
|
persisted.stateInputs = _stateInputs;
|
|
4807
4974
|
}
|
|
4975
|
+
// Stores such as Convex reject `_`-prefixed field names.
|
|
4976
|
+
persisted.nextTimerId = _nextTimerId;
|
|
4977
|
+
if (_nextActorIds && Object.keys(_nextActorIds).length > 0) {
|
|
4978
|
+
persisted.nextActorIds = _nextActorIds;
|
|
4979
|
+
}
|
|
4808
4980
|
if (machine.version !== undefined) {
|
|
4809
4981
|
persisted.machine = {
|
|
4810
4982
|
id: machine.id,
|
|
@@ -4827,7 +4999,7 @@ function persistContext(contextPart, getActorId, path = 'context', ancestors = [
|
|
|
4827
4999
|
};
|
|
4828
5000
|
// The address lets refs to non-children still route after restore.
|
|
4829
5001
|
copy[key] = {
|
|
4830
|
-
|
|
5002
|
+
'@actor': value.address
|
|
4831
5003
|
};
|
|
4832
5004
|
} else {
|
|
4833
5005
|
const valuePath = Array.isArray(contextPart) ? `${path}[${key}]` : `${path}.${key}`;
|
|
@@ -5460,11 +5632,18 @@ class RuntimeSystem {
|
|
|
5460
5632
|
// Records a send on the *sender's* transition for the `sent[]` inspection
|
|
5461
5633
|
// facet. Captures the send when it is initiated (including delayed sends that
|
|
5462
5634
|
// may never deliver), keyed to the source actor's in-flight transition.
|
|
5635
|
+
// A send made with no transition in flight (a callback's `sendBack`, a value
|
|
5636
|
+
// an observable relays to its parent) is not recorded: no transition reports
|
|
5637
|
+
// it, so it would be held until the source's next transition, or for as long
|
|
5638
|
+
// as the source lives if it never makes one.
|
|
5463
5639
|
_recordSent(source, target, event, delay, id) {
|
|
5464
5640
|
if (!this._inspectionObservers?.size || !source) {
|
|
5465
5641
|
return;
|
|
5466
5642
|
}
|
|
5467
5643
|
const inspectionSource = source;
|
|
5644
|
+
if (!inspectionSource._inTransition) {
|
|
5645
|
+
return;
|
|
5646
|
+
}
|
|
5468
5647
|
const collected = inspectionSource._collectedSent ??= [];
|
|
5469
5648
|
collected.push({
|
|
5470
5649
|
targetRef: target,
|
|
@@ -5701,9 +5880,9 @@ class RuntimeSystem {
|
|
|
5701
5880
|
} else if (
|
|
5702
5881
|
// A live actor of another incarnation is stale locally; an
|
|
5703
5882
|
// address this system cannot see may belong to a host runtime.
|
|
5704
|
-
this._getByAddress(target
|
|
5883
|
+
this._getByAddress(target['@actor']) || !this.runtime?.sendEvent) {
|
|
5705
5884
|
return this.deadLetter(source, undefined, event, 'missingTarget', {
|
|
5706
|
-
targetId: getAddressId(target
|
|
5885
|
+
targetId: getAddressId(target['@actor']),
|
|
5707
5886
|
error: createMissingAddressError(target)
|
|
5708
5887
|
});
|
|
5709
5888
|
}
|
|
@@ -5987,6 +6166,12 @@ class Actor {
|
|
|
5987
6166
|
this._collectedActions = void 0;
|
|
5988
6167
|
/** @internal Events relayed to other actors during the in-flight transition. */
|
|
5989
6168
|
this._collectedSent = void 0;
|
|
6169
|
+
/**
|
|
6170
|
+
* @internal Whether a transition is in flight: while the actor starts,
|
|
6171
|
+
* processes an event, or recovers from an execution error. Sends are recorded
|
|
6172
|
+
* for `sent[]` only then.
|
|
6173
|
+
*/
|
|
6174
|
+
this._inTransition = false;
|
|
5990
6175
|
this._initialEffects = void 0;
|
|
5991
6176
|
this.registryKey = void 0;
|
|
5992
6177
|
/** The globally unique process ID for this invocation. */
|
|
@@ -6059,9 +6244,14 @@ class Actor {
|
|
|
6059
6244
|
// transition functions; computing an initial snapshot here would run
|
|
6060
6245
|
// init-time side effects (context factories, entry) a second time.
|
|
6061
6246
|
} else {
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6247
|
+
this._inTransition = true;
|
|
6248
|
+
try {
|
|
6249
|
+
const [snapshot, effects] = finalizeTransitionResult(this._actorScope, undefined, this.logic.initialTransition(this.options?.input, this._actorScope));
|
|
6250
|
+
this._setSnapshot(snapshot);
|
|
6251
|
+
this._initialEffects = effects.length ? effects : undefined;
|
|
6252
|
+
} finally {
|
|
6253
|
+
this._inTransition = false;
|
|
6254
|
+
}
|
|
6065
6255
|
}
|
|
6066
6256
|
} catch (err) {
|
|
6067
6257
|
// Restored logic may keep its snapshot shape on restore failures (e.g.
|
|
@@ -6214,6 +6404,8 @@ class Actor {
|
|
|
6214
6404
|
if (!errorEvent) {
|
|
6215
6405
|
return false;
|
|
6216
6406
|
}
|
|
6407
|
+
const inTransition = this._inTransition;
|
|
6408
|
+
this._inTransition = true;
|
|
6217
6409
|
try {
|
|
6218
6410
|
const [nextSnapshot, effects] = finalizeTransitionResult(this._actorScope, snapshot, this.logic.transition(snapshot, errorEvent, this._actorScope));
|
|
6219
6411
|
this._setSnapshot(nextSnapshot);
|
|
@@ -6222,6 +6414,8 @@ class Actor {
|
|
|
6222
6414
|
return true;
|
|
6223
6415
|
} catch {
|
|
6224
6416
|
return false;
|
|
6417
|
+
} finally {
|
|
6418
|
+
this._inTransition = inTransition;
|
|
6225
6419
|
}
|
|
6226
6420
|
}
|
|
6227
6421
|
_next(snapshot) {
|
|
@@ -6433,6 +6627,15 @@ class Actor {
|
|
|
6433
6627
|
|
|
6434
6628
|
/** Starts the Actor from the initial state */
|
|
6435
6629
|
start() {
|
|
6630
|
+
const inTransition = this._inTransition;
|
|
6631
|
+
this._inTransition = true;
|
|
6632
|
+
try {
|
|
6633
|
+
return this._start();
|
|
6634
|
+
} finally {
|
|
6635
|
+
this._inTransition = inTransition;
|
|
6636
|
+
}
|
|
6637
|
+
}
|
|
6638
|
+
_start() {
|
|
6436
6639
|
if (this._processingStatus === ProcessingStatus.Running) {
|
|
6437
6640
|
// Do not restart the service if it is already started
|
|
6438
6641
|
return this;
|
|
@@ -6548,7 +6751,16 @@ class Actor {
|
|
|
6548
6751
|
this.mailbox?.start();
|
|
6549
6752
|
return this;
|
|
6550
6753
|
}
|
|
6551
|
-
_process({
|
|
6754
|
+
_process(item) {
|
|
6755
|
+
const inTransition = this._inTransition;
|
|
6756
|
+
this._inTransition = true;
|
|
6757
|
+
try {
|
|
6758
|
+
this._processEvent(item);
|
|
6759
|
+
} finally {
|
|
6760
|
+
this._inTransition = inTransition;
|
|
6761
|
+
}
|
|
6762
|
+
}
|
|
6763
|
+
_processEvent({
|
|
6552
6764
|
event,
|
|
6553
6765
|
sourceRef
|
|
6554
6766
|
}) {
|
|
@@ -6785,12 +6997,12 @@ class Actor {
|
|
|
6785
6997
|
}
|
|
6786
6998
|
|
|
6787
6999
|
/**
|
|
6788
|
-
* Returns the actor's serializable logical identity: `{
|
|
7000
|
+
* Returns the actor's serializable logical identity: `{ "@actor": address }`.
|
|
6789
7001
|
* The result can be used as an `enq.sendTo(...)` target.
|
|
6790
7002
|
*/
|
|
6791
7003
|
toJSON() {
|
|
6792
7004
|
return {
|
|
6793
|
-
|
|
7005
|
+
'@actor': this.address
|
|
6794
7006
|
};
|
|
6795
7007
|
}
|
|
6796
7008
|
|
|
@@ -6907,6 +7119,7 @@ exports.NULL_EVENT = NULL_EVENT;
|
|
|
6907
7119
|
exports.ProcessingStatus = ProcessingStatus;
|
|
6908
7120
|
exports.RUNTIME_OPERATIONS = RUNTIME_OPERATIONS;
|
|
6909
7121
|
exports.STATE_DELIMITER = STATE_DELIMITER;
|
|
7122
|
+
exports.XSTATE_ATTACHED_FORWARD = XSTATE_ATTACHED_FORWARD;
|
|
6910
7123
|
exports.XSTATE_INIT = XSTATE_INIT;
|
|
6911
7124
|
exports.XSTATE_LOGIC_EFFECT_REJECT = XSTATE_LOGIC_EFFECT_REJECT;
|
|
6912
7125
|
exports.XSTATE_LOGIC_EFFECT_RESOLVE = XSTATE_LOGIC_EFFECT_RESOLVE;
|
|
@@ -6914,6 +7127,7 @@ exports.XSTATE_LOGIC_EFFECT_START = XSTATE_LOGIC_EFFECT_START;
|
|
|
6914
7127
|
exports.XSTATE_STOP = XSTATE_STOP;
|
|
6915
7128
|
exports.XSTATE_STOP_EFFECT = XSTATE_STOP_EFFECT;
|
|
6916
7129
|
exports.XSTATE_TIMER = XSTATE_TIMER;
|
|
7130
|
+
exports.adoptSystem = adoptSystem;
|
|
6917
7131
|
exports.allocateChildId = allocateChildId;
|
|
6918
7132
|
exports.assertChildIdFree = assertChildIdFree;
|
|
6919
7133
|
exports.assertUnreservedSourceName = assertUnreservedSourceName;
|
|
@@ -7011,5 +7225,6 @@ exports.toTransitionConfigArray = toTransitionConfigArray;
|
|
|
7011
7225
|
exports.transitionNode = transitionNode;
|
|
7012
7226
|
exports.withActorSelf = withActorSelf;
|
|
7013
7227
|
exports.withExecutionIdentity = withExecutionIdentity;
|
|
7228
|
+
exports.withExecutionOwner = withExecutionOwner;
|
|
7014
7229
|
exports.withSystemInspector = withSystemInspector;
|
|
7015
7230
|
exports.xstateError = xstateError;
|