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
package/README.md
CHANGED
|
@@ -171,8 +171,8 @@ import { createFSM } from 'xstate/fsm';
|
|
|
171
171
|
const machine = createFSM({
|
|
172
172
|
initial: 'inactive',
|
|
173
173
|
states: {
|
|
174
|
-
inactive: { on: { toggle: 'active' } },
|
|
175
|
-
active: { on: { toggle: 'inactive' } }
|
|
174
|
+
inactive: { on: { toggle: { target: 'active' } } },
|
|
175
|
+
active: { on: { toggle: { target: 'inactive' } } }
|
|
176
176
|
}
|
|
177
177
|
});
|
|
178
178
|
|
|
@@ -180,6 +180,8 @@ let state = machine.initialState;
|
|
|
180
180
|
[state] = machine.transition(state, { type: 'toggle' });
|
|
181
181
|
```
|
|
182
182
|
|
|
183
|
+
States can declare eventless `always` transitions. The machine follows them
|
|
184
|
+
during initialization and after handled events until it reaches a stable state.
|
|
183
185
|
The FSM is also actor logic, so `createActor(machine)` from `xstate` runs it.
|
|
184
186
|
|
|
185
187
|
For typed context, event payloads, or state-specific context snapshots, use
|
|
@@ -164,11 +164,11 @@ function isRemoteActorRef(actorRef) {
|
|
|
164
164
|
* JSON (`actor.toJSON()`): plain data carrying an address, not an actor.
|
|
165
165
|
*/
|
|
166
166
|
function isSerializedActorRef(target) {
|
|
167
|
-
if (typeof target !== 'object' || target === null || Array.isArray(target) || typeof target
|
|
167
|
+
if (typeof target !== 'object' || target === null || Array.isArray(target) || typeof target['@actor'] !== 'string') {
|
|
168
168
|
return false;
|
|
169
169
|
}
|
|
170
170
|
for (const key in target) {
|
|
171
|
-
if (key !== '
|
|
171
|
+
if (key !== '@actor' && key !== 'incarnation') {
|
|
172
172
|
return false;
|
|
173
173
|
}
|
|
174
174
|
}
|
|
@@ -184,7 +184,7 @@ function getAddressId(address) {
|
|
|
184
184
|
|
|
185
185
|
/** @internal The error reported when no live actor has a serialized address. */
|
|
186
186
|
function createMissingAddressError(target) {
|
|
187
|
-
return new Error(xstateError(50, ...(target.incarnation === undefined ? [target
|
|
187
|
+
return new Error(xstateError(50, ...(target.incarnation === undefined ? [target['@actor']] : [target['@actor'], target.incarnation])) );
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
/**
|
|
@@ -193,7 +193,7 @@ function createMissingAddressError(target) {
|
|
|
193
193
|
* without one follows whichever actor is live at the address.
|
|
194
194
|
*/
|
|
195
195
|
function resolveSerializedActorRef(system, target) {
|
|
196
|
-
const live = system._getByAddress?.(target
|
|
196
|
+
const live = system._getByAddress?.(target['@actor']);
|
|
197
197
|
return live && (target.incarnation === undefined || live.sessionId === target.incarnation) ? live : undefined;
|
|
198
198
|
}
|
|
199
199
|
|
|
@@ -246,7 +246,7 @@ function createInertActorRef(options) {
|
|
|
246
246
|
throw new Error(xstateError(51, id));
|
|
247
247
|
}
|
|
248
248
|
return {
|
|
249
|
-
|
|
249
|
+
'@actor': address
|
|
250
250
|
};
|
|
251
251
|
}
|
|
252
252
|
};
|
|
@@ -332,7 +332,7 @@ function createRemoteActorRef(system, options) {
|
|
|
332
332
|
// one actor-reference shape whether a child is co-located or remote.
|
|
333
333
|
toJSON() {
|
|
334
334
|
return {
|
|
335
|
-
|
|
335
|
+
'@actor': options.address
|
|
336
336
|
};
|
|
337
337
|
}
|
|
338
338
|
};
|
|
@@ -452,7 +452,7 @@ function deliverEvent(source, target, event) {
|
|
|
452
452
|
throw error;
|
|
453
453
|
}
|
|
454
454
|
void system.deadLetter(source, undefined, event, 'missingTarget', {
|
|
455
|
-
targetId: getAddressId(serialized
|
|
455
|
+
targetId: getAddressId(serialized['@actor']),
|
|
456
456
|
error
|
|
457
457
|
});
|
|
458
458
|
return;
|
|
@@ -905,6 +905,7 @@ function resolveRegisteredActorSource(actors, logic) {
|
|
|
905
905
|
const systemLogicMetadata = Symbol('xstate.systemLogicMetadata');
|
|
906
906
|
|
|
907
907
|
const subscriptions = /* #__PURE__ */new WeakMap();
|
|
908
|
+
const XSTATE_ATTACHED_FORWARD = 'xstate.attached.forward';
|
|
908
909
|
|
|
909
910
|
/**
|
|
910
911
|
* Internal factory for actor logic that attaches to another actor on start
|
|
@@ -967,9 +968,11 @@ id) {
|
|
|
967
968
|
unsubscribe: teardown
|
|
968
969
|
});
|
|
969
970
|
},
|
|
970
|
-
transition: (state, event, {
|
|
971
|
-
self
|
|
972
|
-
|
|
971
|
+
transition: (state, event, scope) => {
|
|
972
|
+
const self = scope.self;
|
|
973
|
+
if (event.type === XSTATE_ATTACHED_FORWARD) {
|
|
974
|
+
return [state, state.status === 'active' && self._parent ? [createSendToEffect(scope, self._parent, event.event)] : []];
|
|
975
|
+
}
|
|
973
976
|
if (event.type === XSTATE_STOP) {
|
|
974
977
|
subscriptions.get(self)?.unsubscribe();
|
|
975
978
|
subscriptions.delete(self);
|
|
@@ -984,7 +987,8 @@ id) {
|
|
|
984
987
|
initialTransition,
|
|
985
988
|
getInitialSnapshot: (actorScope, input) => initialTransition(input)[0],
|
|
986
989
|
getPersistedSnapshot: snapshot => snapshot,
|
|
987
|
-
restoreSnapshot: snapshot => snapshot
|
|
990
|
+
restoreSnapshot: snapshot => snapshot,
|
|
991
|
+
isInternalEventType: eventType => eventType === XSTATE_ATTACHED_FORWARD
|
|
988
992
|
};
|
|
989
993
|
Object.defineProperty(logic, systemLogicMetadata, {
|
|
990
994
|
value: {
|
|
@@ -1002,7 +1006,10 @@ function relayMappedToParent(self, system, getEvent) {
|
|
|
1002
1006
|
if (self.getSnapshot().status === 'stopped' || !self._parent) {
|
|
1003
1007
|
return;
|
|
1004
1008
|
}
|
|
1005
|
-
system._relay(self, self
|
|
1009
|
+
system._relay(self, self, {
|
|
1010
|
+
type: XSTATE_ATTACHED_FORWARD,
|
|
1011
|
+
event: getEvent()
|
|
1012
|
+
});
|
|
1006
1013
|
}
|
|
1007
1014
|
|
|
1008
1015
|
/** @public */
|
|
@@ -2112,6 +2119,18 @@ function withSystemInspector(inspect, fn) {
|
|
|
2112
2119
|
|
|
2113
2120
|
/** Snapshot-scoped actor identity and system view. @internal */
|
|
2114
2121
|
|
|
2122
|
+
// Each view's execution system and whether it forwards inspection. Views
|
|
2123
|
+
// never chain: they all inherit from the execution system directly.
|
|
2124
|
+
const snapshotSystemViews = new WeakMap();
|
|
2125
|
+
// Facilities owned by the execution rather than by one snapshot's view. A view
|
|
2126
|
+
// reads and writes them on the execution system, so timers, listeners and the
|
|
2127
|
+
// runtime installed through any snapshot are visible through every other.
|
|
2128
|
+
const executionFacilities = ['runtime', '_timerMap', '_rejectionListeners', '_inspectionObservers', '_emissionListeners'];
|
|
2129
|
+
// The durable execution that owns each execution system.
|
|
2130
|
+
/** A durable execution, as the owner of the views its transitions create. @internal */
|
|
2131
|
+
|
|
2132
|
+
const executionOwners = new WeakMap();
|
|
2133
|
+
let ambientExecutionOwner;
|
|
2115
2134
|
const snapshotActorRefs = new WeakMap();
|
|
2116
2135
|
const lazySnapshotActorRefs = new WeakMap();
|
|
2117
2136
|
const emptyKeyedActors = new Map();
|
|
@@ -2171,12 +2190,22 @@ function getSnapshotChildren(snapshot) {
|
|
|
2171
2190
|
*
|
|
2172
2191
|
* @internal
|
|
2173
2192
|
*/
|
|
2174
|
-
function createSnapshotSystem(baseSystem, children, baseState) {
|
|
2175
|
-
const
|
|
2193
|
+
function createSnapshotSystem(baseSystem, children, baseState, owner) {
|
|
2194
|
+
const baseView = snapshotSystemViews.get(baseSystem);
|
|
2195
|
+
const baseExecutionSystem = baseView?.executionSystem ?? baseSystem;
|
|
2196
|
+
// The runtime system under every view. A view runs its methods against the
|
|
2197
|
+
// execution system's facilities.
|
|
2198
|
+
const rootSystem = baseView?.rootSystem ?? baseSystem;
|
|
2199
|
+
const forks = owner !== undefined && executionOwners.get(baseExecutionSystem) !== owner;
|
|
2200
|
+
// A view an execution owns reports to that execution's inspector.
|
|
2201
|
+
const forwardInspection = owner ? !!owner.inspect : hasAmbientInspector() && (baseView?.forwardInspection ?? true);
|
|
2176
2202
|
const registeredActors = copyRegisteredActors(baseSystem, baseState);
|
|
2177
2203
|
const keyedActors = new Map(baseState?.keyedActors ?? getKeyedActors(baseSystem));
|
|
2178
2204
|
const reverseKeyedActors = new WeakMap();
|
|
2179
|
-
|
|
2205
|
+
// The view's execution system; adoption can make the view its own.
|
|
2206
|
+
const execution = () => snapshotSystemViews.get(system).executionSystem;
|
|
2207
|
+
const forwards = () => snapshotSystemViews.get(system).forwardInspection;
|
|
2208
|
+
const system = Object.assign(Object.create(baseExecutionSystem), {
|
|
2180
2209
|
children: registeredActors,
|
|
2181
2210
|
keyedActors,
|
|
2182
2211
|
reverseKeyedActors,
|
|
@@ -2211,15 +2240,38 @@ function createSnapshotSystem(baseSystem, children, baseState) {
|
|
|
2211
2240
|
},
|
|
2212
2241
|
get: registryKey => keyedActors.get(registryKey),
|
|
2213
2242
|
getAll: () => Object.fromEntries(keyedActors),
|
|
2214
|
-
onEmitted: listener =>
|
|
2215
|
-
_notifyEmitted: (actorRef, event) =>
|
|
2243
|
+
onEmitted: listener => rootSystem.onEmitted.call(execution(), listener),
|
|
2244
|
+
_notifyEmitted: (actorRef, event) => rootSystem._notifyEmitted.call(execution(), actorRef, event),
|
|
2216
2245
|
// Pure transition resolution must not leak topology inspection events
|
|
2217
2246
|
// into a live runtime system — planning branches stay silent. The one
|
|
2218
2247
|
// exception is a durable execution's own transitions (marked by the
|
|
2219
2248
|
// ambient inspector at creation time): there the pure path IS the
|
|
2220
|
-
// execution, so inspection forwards to the
|
|
2221
|
-
_hasInspectionObservers:
|
|
2222
|
-
_sendInspectionEvent:
|
|
2249
|
+
// execution, so inspection forwards to the execution system's observers.
|
|
2250
|
+
_hasInspectionObservers: () => forwards() && (rootSystem._hasInspectionObservers?.call(execution()) ?? false),
|
|
2251
|
+
_sendInspectionEvent: event => {
|
|
2252
|
+
if (forwards()) {
|
|
2253
|
+
rootSystem._sendInspectionEvent.call(execution(), event);
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
});
|
|
2257
|
+
const executionSystem = forks ? system : baseExecutionSystem;
|
|
2258
|
+
if (forks) {
|
|
2259
|
+
forkFacilities(system, baseExecutionSystem, owner);
|
|
2260
|
+
} else {
|
|
2261
|
+
for (const key of executionFacilities) {
|
|
2262
|
+
Object.defineProperty(system, key, {
|
|
2263
|
+
configurable: true,
|
|
2264
|
+
get: () => execution()[key],
|
|
2265
|
+
set: value => {
|
|
2266
|
+
execution()[key] = value;
|
|
2267
|
+
}
|
|
2268
|
+
});
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2271
|
+
snapshotSystemViews.set(system, {
|
|
2272
|
+
executionSystem,
|
|
2273
|
+
rootSystem,
|
|
2274
|
+
forwardInspection
|
|
2223
2275
|
});
|
|
2224
2276
|
for (const [registryKey, actor] of keyedActors) {
|
|
2225
2277
|
if (!actor) {
|
|
@@ -2243,6 +2295,83 @@ function createSnapshotSystem(baseSystem, children, baseState) {
|
|
|
2243
2295
|
return system;
|
|
2244
2296
|
}
|
|
2245
2297
|
|
|
2298
|
+
/**
|
|
2299
|
+
* Makes `system` the execution system of `owner`, a new incarnation: it gets
|
|
2300
|
+
* the owner's runtime and the pending timers it saw, and starts with no
|
|
2301
|
+
* listeners or inspectors, so nothing registered on another execution
|
|
2302
|
+
* observes it.
|
|
2303
|
+
*/
|
|
2304
|
+
function forkFacilities(system, from, owner) {
|
|
2305
|
+
const timers = from._timerMap;
|
|
2306
|
+
for (const key of executionFacilities) {
|
|
2307
|
+
Object.defineProperty(system, key, {
|
|
2308
|
+
configurable: true,
|
|
2309
|
+
writable: true,
|
|
2310
|
+
value: key === 'runtime' ? owner.runtime : key === '_timerMap' && timers ? {
|
|
2311
|
+
...timers
|
|
2312
|
+
} : undefined
|
|
2313
|
+
});
|
|
2314
|
+
}
|
|
2315
|
+
executionOwners.set(system, owner);
|
|
2316
|
+
if (owner.inspect) {
|
|
2317
|
+
system.inspect(owner.inspect);
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2320
|
+
|
|
2321
|
+
/**
|
|
2322
|
+
* Makes `owner` own `system` before it installs its runtime there, and
|
|
2323
|
+
* returns whether it does. An unowned view forks in place, so the install
|
|
2324
|
+
* never reaches the system it was derived from. A system another execution
|
|
2325
|
+
* owns is left alone.
|
|
2326
|
+
*
|
|
2327
|
+
* @internal
|
|
2328
|
+
*/
|
|
2329
|
+
function adoptSystem(system, owner) {
|
|
2330
|
+
const view = snapshotSystemViews.get(system);
|
|
2331
|
+
const current = executionOwners.get(view?.executionSystem ?? system);
|
|
2332
|
+
if (current === owner) {
|
|
2333
|
+
if (view) {
|
|
2334
|
+
view.forwardInspection = !!owner.inspect;
|
|
2335
|
+
}
|
|
2336
|
+
return true;
|
|
2337
|
+
}
|
|
2338
|
+
// A system another execution owns stays with it.
|
|
2339
|
+
if (current) {
|
|
2340
|
+
return false;
|
|
2341
|
+
}
|
|
2342
|
+
if (!view) {
|
|
2343
|
+
executionOwners.set(system, owner);
|
|
2344
|
+
return true;
|
|
2345
|
+
}
|
|
2346
|
+
forkFacilities(system, view.executionSystem, owner);
|
|
2347
|
+
view.executionSystem = system;
|
|
2348
|
+
view.forwardInspection = !!owner.inspect;
|
|
2349
|
+
return true;
|
|
2350
|
+
}
|
|
2351
|
+
|
|
2352
|
+
/**
|
|
2353
|
+
* Runs `fn` as a transition of `owner`. A view it derives from a system the
|
|
2354
|
+
* owner does not own forks into the owner's own execution system.
|
|
2355
|
+
*
|
|
2356
|
+
* @internal
|
|
2357
|
+
*/
|
|
2358
|
+
function withExecutionOwner(owner, fn) {
|
|
2359
|
+
const previous = ambientExecutionOwner;
|
|
2360
|
+
ambientExecutionOwner = owner;
|
|
2361
|
+
try {
|
|
2362
|
+
return fn();
|
|
2363
|
+
} finally {
|
|
2364
|
+
ambientExecutionOwner = previous;
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
|
|
2368
|
+
/** Hands the ambient owner to the first scope that asks for it. @internal */
|
|
2369
|
+
function takeExecutionOwner() {
|
|
2370
|
+
const owner = ambientExecutionOwner;
|
|
2371
|
+
ambientExecutionOwner = undefined;
|
|
2372
|
+
return owner;
|
|
2373
|
+
}
|
|
2374
|
+
|
|
2246
2375
|
/** Returns the actor identity associated with a transition snapshot. @internal */
|
|
2247
2376
|
function getSnapshotActorRef(snapshot) {
|
|
2248
2377
|
const existing = snapshotActorRefs.get(snapshot);
|
|
@@ -2436,8 +2565,9 @@ function setInertActorScopeSnapshot(actorScope, snapshot, attachActorRef = true)
|
|
|
2436
2565
|
const lazyState = getLazyInertActorState(actorScope);
|
|
2437
2566
|
if (lazyState) {
|
|
2438
2567
|
lazyState.snapshot = snapshot;
|
|
2439
|
-
|
|
2440
|
-
|
|
2568
|
+
const scope = lazyState.materialized ?? lazyState.identityScope;
|
|
2569
|
+
if (scope) {
|
|
2570
|
+
scope.self._snapshot = snapshot;
|
|
2441
2571
|
}
|
|
2442
2572
|
} else {
|
|
2443
2573
|
actorScope.self._snapshot = snapshot;
|
|
@@ -2472,6 +2602,15 @@ function attachSnapshotActorRef(actorScope, snapshot) {
|
|
|
2472
2602
|
setLazySnapshotActorRef(snapshot, create);
|
|
2473
2603
|
return snapshot;
|
|
2474
2604
|
}
|
|
2605
|
+
/** Records the materialized scope and releases its consumed source. */
|
|
2606
|
+
function commitMaterialization(state, scope) {
|
|
2607
|
+
// Dropping the consumed source keeps this scope from retaining earlier snapshots.
|
|
2608
|
+
state.sourceRef = undefined;
|
|
2609
|
+
state.sourceChildren = {};
|
|
2610
|
+
state.materialized = scope;
|
|
2611
|
+
state.materialize = () => scope;
|
|
2612
|
+
return scope;
|
|
2613
|
+
}
|
|
2475
2614
|
const lazyInertActorState = Symbol();
|
|
2476
2615
|
const snapshotActorScopes = new WeakMap();
|
|
2477
2616
|
let inertActorMaterializationObserver;
|
|
@@ -2516,12 +2655,14 @@ const lazyInertActorScopePrototype = {
|
|
|
2516
2655
|
return materializeInertActorScope(this).actionExecutor;
|
|
2517
2656
|
}
|
|
2518
2657
|
};
|
|
2519
|
-
|
|
2658
|
+
|
|
2659
|
+
/** Creates a transactional planning scope backed by an inert actor. */
|
|
2660
|
+
function createMaterializedInertActorScope(actorLogic, sourceRef, sourceChildren, currentSnapshot, sourceSelf, owner) {
|
|
2520
2661
|
inertActorMaterializationObserver?.();
|
|
2521
2662
|
const snapshotRef = sourceRef?.();
|
|
2522
2663
|
const previousSelf = sourceSelf ?? snapshotRef?.actor;
|
|
2523
2664
|
const baseSystem = previousSelf?.system;
|
|
2524
|
-
const system = previousSelf && baseSystem ? createSnapshotSystem(baseSystem, sourceChildren, sourceSelf ? undefined : snapshotRef?.systemState) : undefined;
|
|
2665
|
+
const system = previousSelf && baseSystem ? createSnapshotSystem(baseSystem, sourceChildren, sourceSelf ? undefined : snapshotRef?.systemState, owner) : undefined;
|
|
2525
2666
|
const self = createActor(actorLogic, {
|
|
2526
2667
|
_inert: true,
|
|
2527
2668
|
...(previousSelf ? {
|
|
@@ -2541,12 +2682,8 @@ function createMaterializedInertActorScope(actorLogic, sourceRef, sourceChildren
|
|
|
2541
2682
|
// a future construction-time read cannot pin a root-shaped address.
|
|
2542
2683
|
self._address = undefined;
|
|
2543
2684
|
}
|
|
2544
|
-
if (currentSnapshot) {
|
|
2545
|
-
self._snapshot = currentSnapshot;
|
|
2546
|
-
}
|
|
2547
|
-
|
|
2548
2685
|
// Reuse the branch actor's scope while keeping planning transactional.
|
|
2549
|
-
|
|
2686
|
+
const scope = Object.create(self._actorScope, {
|
|
2550
2687
|
defer: {
|
|
2551
2688
|
value: () => {}
|
|
2552
2689
|
},
|
|
@@ -2555,8 +2692,20 @@ function createMaterializedInertActorScope(actorLogic, sourceRef, sourceChildren
|
|
|
2555
2692
|
},
|
|
2556
2693
|
actionExecutor: {
|
|
2557
2694
|
value: () => {}
|
|
2695
|
+
},
|
|
2696
|
+
_snapshot: {
|
|
2697
|
+
enumerable: true,
|
|
2698
|
+
configurable: true,
|
|
2699
|
+
get: () => self._snapshot,
|
|
2700
|
+
set: snapshot => {
|
|
2701
|
+
self._snapshot = snapshot;
|
|
2702
|
+
}
|
|
2558
2703
|
}
|
|
2559
2704
|
});
|
|
2705
|
+
if (currentSnapshot) {
|
|
2706
|
+
scope._snapshot = currentSnapshot;
|
|
2707
|
+
}
|
|
2708
|
+
return scope;
|
|
2560
2709
|
}
|
|
2561
2710
|
|
|
2562
2711
|
/** @internal */
|
|
@@ -2571,22 +2720,34 @@ function createInertActorScope(actorLogic, snapshot, sourceSelf, sourceActorScop
|
|
|
2571
2720
|
sourceChildren: isMachineSnapshot(snapshot) ? snapshot.children : {},
|
|
2572
2721
|
identityProvider: sourceState?.identityProvider ?? sourceRef,
|
|
2573
2722
|
parent: sourceSelf?._parent ?? sourceState?.parent ?? eagerSourceRef?.actor._parent,
|
|
2723
|
+
// Only the outermost scope of an owned transition belongs to the owner;
|
|
2724
|
+
// scopes for its intermediate snapshots inherit it, and nested pure
|
|
2725
|
+
// transitions run unowned.
|
|
2726
|
+
owner: sourceActorScope ? sourceState?.owner : takeExecutionOwner(),
|
|
2574
2727
|
parentKnown: !!sourceSelf || !!sourceState?.parentKnown || !!eagerSourceRef || !snapshot
|
|
2575
2728
|
};
|
|
2576
|
-
state.materialize = () =>
|
|
2729
|
+
state.materialize = () => {
|
|
2730
|
+
const scope = createMaterializedInertActorScope(actorLogic, state.sourceRef, state.sourceChildren, state.snapshot, sourceSelf, state.owner);
|
|
2731
|
+
return commitMaterialization(state, scope);
|
|
2732
|
+
};
|
|
2577
2733
|
if (!state.identityProvider && !snapshot) {
|
|
2578
2734
|
const identitySnapshot = {};
|
|
2579
|
-
const identitySourceRef = state.sourceRef;
|
|
2580
|
-
const identitySourceChildren = state.sourceChildren;
|
|
2581
|
-
let identityScope;
|
|
2582
2735
|
let identityRef;
|
|
2583
|
-
const getIdentityScope = () =>
|
|
2736
|
+
const getIdentityScope = () => {
|
|
2737
|
+
if (!state.identityScope) {
|
|
2738
|
+
state.identityScope = createMaterializedInertActorScope(actorLogic, state.sourceRef, state.sourceChildren, undefined, sourceSelf, state.owner);
|
|
2739
|
+
if (state.snapshot !== undefined) {
|
|
2740
|
+
state.identityScope.self._snapshot = state.snapshot;
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2743
|
+
return state.identityScope;
|
|
2744
|
+
};
|
|
2584
2745
|
state.materialize = () => {
|
|
2585
2746
|
const scope = getIdentityScope();
|
|
2586
2747
|
if (state.snapshot !== undefined) {
|
|
2587
2748
|
scope.self._snapshot = state.snapshot;
|
|
2588
2749
|
}
|
|
2589
|
-
return state
|
|
2750
|
+
return commitMaterialization(state, scope);
|
|
2590
2751
|
};
|
|
2591
2752
|
state.identityProvider = () => {
|
|
2592
2753
|
if (identityRef) {
|
|
@@ -3714,7 +3875,7 @@ function microstep(transitions, currentSnapshot, actorScope, event, isInitial, i
|
|
|
3714
3875
|
}
|
|
3715
3876
|
addAncestorStatesToEnter(ancestors, !transition.source.parent && reenter ? undefined : domain);
|
|
3716
3877
|
}
|
|
3717
|
-
if (reenter && domain === transition.source) {
|
|
3878
|
+
if (targets?.length && reenter && domain === transition.source) {
|
|
3718
3879
|
// A reentering transition whose domain is its own source exits and
|
|
3719
3880
|
// reenters the source, so the source must be entered explicitly —
|
|
3720
3881
|
// it has no ancestor inside the domain to add it.
|
|
@@ -4263,7 +4424,9 @@ function macrostep(snapshot, event, actorScope, internalQueue, initialMicrosteps
|
|
|
4263
4424
|
if (!internalQueue.length && snapshot.machine._hasEventlessTransitions === false) {
|
|
4264
4425
|
return completeMacrostep();
|
|
4265
4426
|
}
|
|
4266
|
-
|
|
4427
|
+
|
|
4428
|
+
// A timer notification must not run eventless transitions before delivery.
|
|
4429
|
+
let shouldSelectEventlessTransitions = event.type !== XSTATE_TIMER;
|
|
4267
4430
|
const maxIterations = snapshot.machine.options?.maxIterations ?? Infinity;
|
|
4268
4431
|
let iterationCount = 0;
|
|
4269
4432
|
// The last few state values visited, for the infinite-loop error.
|
|
@@ -4559,6 +4722,8 @@ const machineSnapshotToJSON = function toJSON() {
|
|
|
4559
4722
|
const {
|
|
4560
4723
|
nodes,
|
|
4561
4724
|
_stateInputs,
|
|
4725
|
+
_nextTimerId,
|
|
4726
|
+
_nextActorIds,
|
|
4562
4727
|
tags,
|
|
4563
4728
|
machine,
|
|
4564
4729
|
getMeta,
|
|
@@ -4677,6 +4842,8 @@ function getPersistedSnapshot(snapshot, options) {
|
|
|
4677
4842
|
const {
|
|
4678
4843
|
nodes,
|
|
4679
4844
|
_stateInputs,
|
|
4845
|
+
_nextTimerId,
|
|
4846
|
+
_nextActorIds,
|
|
4680
4847
|
tags,
|
|
4681
4848
|
machine,
|
|
4682
4849
|
children,
|
|
@@ -4803,6 +4970,11 @@ function getPersistedSnapshot(snapshot, options) {
|
|
|
4803
4970
|
if (_stateInputs && Object.keys(_stateInputs).length > 0) {
|
|
4804
4971
|
persisted.stateInputs = _stateInputs;
|
|
4805
4972
|
}
|
|
4973
|
+
// Stores such as Convex reject `_`-prefixed field names.
|
|
4974
|
+
persisted.nextTimerId = _nextTimerId;
|
|
4975
|
+
if (_nextActorIds && Object.keys(_nextActorIds).length > 0) {
|
|
4976
|
+
persisted.nextActorIds = _nextActorIds;
|
|
4977
|
+
}
|
|
4806
4978
|
if (machine.version !== undefined) {
|
|
4807
4979
|
persisted.machine = {
|
|
4808
4980
|
id: machine.id,
|
|
@@ -4825,7 +4997,7 @@ function persistContext(contextPart, getActorId, path = 'context', ancestors = [
|
|
|
4825
4997
|
};
|
|
4826
4998
|
// The address lets refs to non-children still route after restore.
|
|
4827
4999
|
copy[key] = {
|
|
4828
|
-
|
|
5000
|
+
'@actor': value.address
|
|
4829
5001
|
};
|
|
4830
5002
|
} else {
|
|
4831
5003
|
const valuePath = Array.isArray(contextPart) ? `${path}[${key}]` : `${path}.${key}`;
|
|
@@ -5458,11 +5630,18 @@ class RuntimeSystem {
|
|
|
5458
5630
|
// Records a send on the *sender's* transition for the `sent[]` inspection
|
|
5459
5631
|
// facet. Captures the send when it is initiated (including delayed sends that
|
|
5460
5632
|
// may never deliver), keyed to the source actor's in-flight transition.
|
|
5633
|
+
// A send made with no transition in flight (a callback's `sendBack`, a value
|
|
5634
|
+
// an observable relays to its parent) is not recorded: no transition reports
|
|
5635
|
+
// it, so it would be held until the source's next transition, or for as long
|
|
5636
|
+
// as the source lives if it never makes one.
|
|
5461
5637
|
_recordSent(source, target, event, delay, id) {
|
|
5462
5638
|
if (!this._inspectionObservers?.size || !source) {
|
|
5463
5639
|
return;
|
|
5464
5640
|
}
|
|
5465
5641
|
const inspectionSource = source;
|
|
5642
|
+
if (!inspectionSource._inTransition) {
|
|
5643
|
+
return;
|
|
5644
|
+
}
|
|
5466
5645
|
const collected = inspectionSource._collectedSent ??= [];
|
|
5467
5646
|
collected.push({
|
|
5468
5647
|
targetRef: target,
|
|
@@ -5699,9 +5878,9 @@ class RuntimeSystem {
|
|
|
5699
5878
|
} else if (
|
|
5700
5879
|
// A live actor of another incarnation is stale locally; an
|
|
5701
5880
|
// address this system cannot see may belong to a host runtime.
|
|
5702
|
-
this._getByAddress(target
|
|
5881
|
+
this._getByAddress(target['@actor']) || !this.runtime?.sendEvent) {
|
|
5703
5882
|
return this.deadLetter(source, undefined, event, 'missingTarget', {
|
|
5704
|
-
targetId: getAddressId(target
|
|
5883
|
+
targetId: getAddressId(target['@actor']),
|
|
5705
5884
|
error: createMissingAddressError(target)
|
|
5706
5885
|
});
|
|
5707
5886
|
}
|
|
@@ -5985,6 +6164,12 @@ class Actor {
|
|
|
5985
6164
|
this._collectedActions = void 0;
|
|
5986
6165
|
/** @internal Events relayed to other actors during the in-flight transition. */
|
|
5987
6166
|
this._collectedSent = void 0;
|
|
6167
|
+
/**
|
|
6168
|
+
* @internal Whether a transition is in flight: while the actor starts,
|
|
6169
|
+
* processes an event, or recovers from an execution error. Sends are recorded
|
|
6170
|
+
* for `sent[]` only then.
|
|
6171
|
+
*/
|
|
6172
|
+
this._inTransition = false;
|
|
5988
6173
|
this._initialEffects = void 0;
|
|
5989
6174
|
this.registryKey = void 0;
|
|
5990
6175
|
/** The globally unique process ID for this invocation. */
|
|
@@ -6057,9 +6242,14 @@ class Actor {
|
|
|
6057
6242
|
// transition functions; computing an initial snapshot here would run
|
|
6058
6243
|
// init-time side effects (context factories, entry) a second time.
|
|
6059
6244
|
} else {
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6245
|
+
this._inTransition = true;
|
|
6246
|
+
try {
|
|
6247
|
+
const [snapshot, effects] = finalizeTransitionResult(this._actorScope, undefined, this.logic.initialTransition(this.options?.input, this._actorScope));
|
|
6248
|
+
this._setSnapshot(snapshot);
|
|
6249
|
+
this._initialEffects = effects.length ? effects : undefined;
|
|
6250
|
+
} finally {
|
|
6251
|
+
this._inTransition = false;
|
|
6252
|
+
}
|
|
6063
6253
|
}
|
|
6064
6254
|
} catch (err) {
|
|
6065
6255
|
// Restored logic may keep its snapshot shape on restore failures (e.g.
|
|
@@ -6212,6 +6402,8 @@ class Actor {
|
|
|
6212
6402
|
if (!errorEvent) {
|
|
6213
6403
|
return false;
|
|
6214
6404
|
}
|
|
6405
|
+
const inTransition = this._inTransition;
|
|
6406
|
+
this._inTransition = true;
|
|
6215
6407
|
try {
|
|
6216
6408
|
const [nextSnapshot, effects] = finalizeTransitionResult(this._actorScope, snapshot, this.logic.transition(snapshot, errorEvent, this._actorScope));
|
|
6217
6409
|
this._setSnapshot(nextSnapshot);
|
|
@@ -6220,6 +6412,8 @@ class Actor {
|
|
|
6220
6412
|
return true;
|
|
6221
6413
|
} catch {
|
|
6222
6414
|
return false;
|
|
6415
|
+
} finally {
|
|
6416
|
+
this._inTransition = inTransition;
|
|
6223
6417
|
}
|
|
6224
6418
|
}
|
|
6225
6419
|
_next(snapshot) {
|
|
@@ -6431,6 +6625,15 @@ class Actor {
|
|
|
6431
6625
|
|
|
6432
6626
|
/** Starts the Actor from the initial state */
|
|
6433
6627
|
start() {
|
|
6628
|
+
const inTransition = this._inTransition;
|
|
6629
|
+
this._inTransition = true;
|
|
6630
|
+
try {
|
|
6631
|
+
return this._start();
|
|
6632
|
+
} finally {
|
|
6633
|
+
this._inTransition = inTransition;
|
|
6634
|
+
}
|
|
6635
|
+
}
|
|
6636
|
+
_start() {
|
|
6434
6637
|
if (this._processingStatus === ProcessingStatus.Running) {
|
|
6435
6638
|
// Do not restart the service if it is already started
|
|
6436
6639
|
return this;
|
|
@@ -6546,7 +6749,16 @@ class Actor {
|
|
|
6546
6749
|
this.mailbox?.start();
|
|
6547
6750
|
return this;
|
|
6548
6751
|
}
|
|
6549
|
-
_process({
|
|
6752
|
+
_process(item) {
|
|
6753
|
+
const inTransition = this._inTransition;
|
|
6754
|
+
this._inTransition = true;
|
|
6755
|
+
try {
|
|
6756
|
+
this._processEvent(item);
|
|
6757
|
+
} finally {
|
|
6758
|
+
this._inTransition = inTransition;
|
|
6759
|
+
}
|
|
6760
|
+
}
|
|
6761
|
+
_processEvent({
|
|
6550
6762
|
event,
|
|
6551
6763
|
sourceRef
|
|
6552
6764
|
}) {
|
|
@@ -6783,12 +6995,12 @@ class Actor {
|
|
|
6783
6995
|
}
|
|
6784
6996
|
|
|
6785
6997
|
/**
|
|
6786
|
-
* Returns the actor's serializable logical identity: `{
|
|
6998
|
+
* Returns the actor's serializable logical identity: `{ "@actor": address }`.
|
|
6787
6999
|
* The result can be used as an `enq.sendTo(...)` target.
|
|
6788
7000
|
*/
|
|
6789
7001
|
toJSON() {
|
|
6790
7002
|
return {
|
|
6791
|
-
|
|
7003
|
+
'@actor': this.address
|
|
6792
7004
|
};
|
|
6793
7005
|
}
|
|
6794
7006
|
|
|
@@ -6899,4 +7111,4 @@ function createActor(logic, ...[options]) {
|
|
|
6899
7111
|
return new Actor(logic, options);
|
|
6900
7112
|
}
|
|
6901
7113
|
|
|
6902
|
-
export {
|
|
7114
|
+
export { publishEmittedEvent as $, matchesTimerKey as A, isMachineSnapshot as B, listenerLogic as C, subscriptionLogic as D, createListenerLogic as E, createSubscriptionLogic as F, Actor as G, matchesState as H, InfiniteTransitionError as I, toObserver as J, executeEffects as K, isBuiltInExecutableEffect as L, deliverEvent as M, runStep as N, stopActor as O, ProcessingStatus as P, terminateActor as Q, createInitEvent as R, createDeadLetterEffect as S, createCustomEffect as T, XSTATE_LOGIC_EFFECT_START as U, XSTATE_LOGIC_EFFECT_RESOLVE as V, XSTATE_LOGIC_EFFECT_REJECT as W, XSTATE_ATTACHED_FORWARD as X, createEmitEffect as Y, createSendToEffect as Z, XSTATE_INIT as _, assertUnreservedSourceName as a, resolveRegisteredActorSource as a0, allocateChildId as a1, assertChildIdFree as a2, reserveChildId as a3, hasUnescapedDot as a4, STATE_DELIMITER as a5, mapValues as a6, createInvokeId as a7, getDelayedTransitions as a8, getCandidates as a9, createSpawnEffect as aA, initialMicrostep as aB, createStartEffect as aC, isStateId as aD, getPersistedSnapshot as aE, detachedScopes as aF, hasAmbientInspector as aG, getProperAncestors as aH, isRemoteActorRef as aI, getAllOwnEvents as aJ, matchesEvent as aK, getRootActorId as aL, RUNTIME_OPERATIONS as aM, createTimerEffect as aN, getSnapshotActorRef as aO, withExecutionOwner as aP, getTimerStart as aQ, recordTimerStart as aR, withSystemInspector as aS, adoptSystem as aT, withExecutionIdentity as aU, diagnoseActorOptions as aV, createRemoteActorRef as aW, createInvokeTimeoutEvent as aX, parseGeneratedActorId as aY, evaluateCandidate as aa, formatTransition as ab, NULL_EVENT as ac, toTransitionConfigArray as ad, matchesActorSession as ae, describeMachine as af, formatRouteTransitions as ag, resolveStateValue as ah, isInFinalState as ai, createInertActorScope as aj, setInertActorScopeSnapshot as ak, beginSpawnAllocation as al, attachSnapshotActorRef as am, macrostep as an, isInertActorScope as ao, setSnapshotActorRef as ap, cloneMachineSnapshot as aq, transitionNode as ar, XSTATE_TIMER as as, getTransitionResult as at, hasEffect as au, createErrorPlatformEvent as av, withActorSelf as aw, resolveActionsWithContext as ax, takeSpawnAllocationCounters as ay, mergeActorIdCounters as az, getStateNodes as b, isActorRefLike as c, diagnoseAuthorConfig as d, createMachineSnapshot as e, diagnoseSetupConfig as f, getAllStateNodes as g, createActor as h, isAtomicStateNode as i, encodeAddressSegment as j, getActorIdPrefix as k, finalizeTransitionResult as l, matchesEventDescriptor as m, getTimerKey as n, isSerializedActorRef as o, parseDelayToMilliseconds as p, readTimerKey as q, resolveInvokedActorLogic as r, systemLogicMetadata as s, toArray as t, XSTATE_STOP_EFFECT as u, XSTATE_STOP as v, createDoneActorEvent as w, xstateError as x, createErrorActorEvent as y, serializeTimerKey as z };
|