@typeonce/effect-machine 0.12.0 → 0.13.0
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 +56 -4
- package/dist/Machine.d.ts +353 -84
- package/dist/Machine.d.ts.map +1 -1
- package/dist/Machine.js +12 -10
- package/dist/Machine.js.map +1 -1
- package/dist/internal/machine/atom.d.ts +1 -0
- package/dist/internal/machine/atom.d.ts.map +1 -1
- package/dist/internal/machine/atom.js +23 -0
- package/dist/internal/machine/atom.js.map +1 -1
- package/dist/internal/machine/commandRuntime.d.ts.map +1 -1
- package/dist/internal/machine/commandRuntime.js +2 -5
- package/dist/internal/machine/commandRuntime.js.map +1 -1
- package/dist/internal/machine/configuration.d.ts +5 -0
- package/dist/internal/machine/configuration.d.ts.map +1 -1
- package/dist/internal/machine/configuration.js +6 -2
- package/dist/internal/machine/configuration.js.map +1 -1
- package/dist/internal/machine/executionPlan.d.ts +1 -0
- package/dist/internal/machine/executionPlan.d.ts.map +1 -1
- package/dist/internal/machine/executionPlan.js +43 -18
- package/dist/internal/machine/executionPlan.js.map +1 -1
- package/dist/internal/machine/initialization.d.ts +5 -0
- package/dist/internal/machine/initialization.d.ts.map +1 -0
- package/dist/internal/machine/initialization.js +61 -0
- package/dist/internal/machine/initialization.js.map +1 -0
- package/dist/internal/machine/inspectionRuntime.d.ts +25 -0
- package/dist/internal/machine/inspectionRuntime.d.ts.map +1 -0
- package/dist/internal/machine/inspectionRuntime.js +79 -0
- package/dist/internal/machine/inspectionRuntime.js.map +1 -0
- package/dist/internal/machine/invocation.d.ts +2 -1
- package/dist/internal/machine/invocation.d.ts.map +1 -1
- package/dist/internal/machine/invocation.js +17 -10
- package/dist/internal/machine/invocation.js.map +1 -1
- package/dist/internal/machine/machine.d.ts +1 -2
- package/dist/internal/machine/machine.d.ts.map +1 -1
- package/dist/internal/machine/machine.js +21 -6
- package/dist/internal/machine/machine.js.map +1 -1
- package/dist/internal/machine/planner.d.ts +15 -0
- package/dist/internal/machine/planner.d.ts.map +1 -1
- package/dist/internal/machine/planner.js +117 -44
- package/dist/internal/machine/planner.js.map +1 -1
- package/dist/internal/machine/process.d.ts.map +1 -1
- package/dist/internal/machine/process.js +4 -2
- package/dist/internal/machine/process.js.map +1 -1
- package/dist/internal/machine/runtime.d.ts +27 -3
- package/dist/internal/machine/runtime.d.ts.map +1 -1
- package/dist/internal/machine/runtime.js +440 -64
- package/dist/internal/machine/runtime.js.map +1 -1
- package/dist/internal/machine/symbols.d.ts +2 -0
- package/dist/internal/machine/symbols.d.ts.map +1 -1
- package/dist/internal/machine/symbols.js +2 -0
- package/dist/internal/machine/symbols.js.map +1 -1
- package/dist/internal/machine/topology.d.ts +13 -0
- package/dist/internal/machine/topology.d.ts.map +1 -1
- package/dist/internal/machine/topology.js +9 -0
- package/dist/internal/machine/topology.js.map +1 -1
- package/dist/internal/testing/machine/finiteModel.d.ts.map +1 -1
- package/dist/internal/testing/machine/finiteModel.js +3 -3
- package/dist/internal/testing/machine/finiteModel.js.map +1 -1
- package/dist/unstable/reactivity/AtomMachine.d.ts +9 -0
- package/dist/unstable/reactivity/AtomMachine.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomMachine.js +9 -0
- package/dist/unstable/reactivity/AtomMachine.js.map +1 -1
- package/docs/agent-guide.md +102 -9
- package/package.json +5 -5
- package/src/Machine.ts +505 -174
- package/src/internal/machine/atom.ts +26 -0
- package/src/internal/machine/commandRuntime.ts +2 -9
- package/src/internal/machine/configuration.ts +28 -3
- package/src/internal/machine/executionPlan.ts +50 -17
- package/src/internal/machine/initialization.ts +73 -0
- package/src/internal/machine/inspectionRuntime.ts +102 -0
- package/src/internal/machine/invocation.ts +37 -12
- package/src/internal/machine/machine.ts +31 -6
- package/src/internal/machine/planner.ts +136 -42
- package/src/internal/machine/process.ts +4 -2
- package/src/internal/machine/runtime.ts +661 -89
- package/src/internal/machine/symbols.ts +3 -0
- package/src/internal/machine/topology.ts +27 -0
- package/src/internal/testing/machine/finiteModel.ts +8 -7
- package/src/unstable/reactivity/AtomMachine.ts +12 -0
|
@@ -33,7 +33,7 @@ import type { EnsureExecutable } from "./readiness.js"
|
|
|
33
33
|
import * as internalRuntime from "./runtime.js"
|
|
34
34
|
import * as Serialization from "./serialization.js"
|
|
35
35
|
import * as StateDefinition from "./stateDefinition.js"
|
|
36
|
-
import { ChildMachineLogicTypeId } from "./symbols.js"
|
|
36
|
+
import { ChildMachineLogicTypeId, SnapshotBuilderStateTypeId } from "./symbols.js"
|
|
37
37
|
import * as Topology from "./topology.js"
|
|
38
38
|
|
|
39
39
|
export {
|
|
@@ -45,10 +45,9 @@ export {
|
|
|
45
45
|
StartupError,
|
|
46
46
|
StoppedError
|
|
47
47
|
} from "./errors.js"
|
|
48
|
-
export { ChildMachineLogicTypeId, InitialEventTypeId } from "./symbols.js"
|
|
48
|
+
export { ChildMachineLogicTypeId, InitialEventTypeId, SnapshotBuilderStateTypeId } from "./symbols.js"
|
|
49
49
|
|
|
50
50
|
const TypeId = "~effect/Machine"
|
|
51
|
-
export const SnapshotBuilderStateTypeId: unique symbol = Symbol("effect/Machine/SnapshotBuilderState")
|
|
52
51
|
export const InvokeTypeId: unique symbol = Symbol.for("effect/Machine/Invoke")
|
|
53
52
|
const ChildMachineTypeId = "~effect/Machine/ChildMachine"
|
|
54
53
|
type IsAny<A> = 0 extends 1 & A ? true : false
|
|
@@ -300,6 +299,24 @@ const withFrom = <Method extends (value: unknown, ...args: ReadonlyArray<any>) =
|
|
|
300
299
|
return method as Method & { readonly from: (...args: ReadonlyArray<any>) => unknown }
|
|
301
300
|
}
|
|
302
301
|
|
|
302
|
+
const withInitial = <Builder extends object>(
|
|
303
|
+
builder: Builder,
|
|
304
|
+
path: string,
|
|
305
|
+
valued: boolean,
|
|
306
|
+
values?: Readonly<Record<string, unknown>>
|
|
307
|
+
): Builder => {
|
|
308
|
+
const initial = withFrom(
|
|
309
|
+
(value: unknown) => Topology.makeInitialTarget(path, value, values),
|
|
310
|
+
"leaf",
|
|
311
|
+
valued
|
|
312
|
+
)
|
|
313
|
+
Object.defineProperty(builder, "initial", {
|
|
314
|
+
value: initial,
|
|
315
|
+
enumerable: false
|
|
316
|
+
})
|
|
317
|
+
return builder
|
|
318
|
+
}
|
|
319
|
+
|
|
303
320
|
const makeSnapshotBuilder = (
|
|
304
321
|
states: Machine.StateTree,
|
|
305
322
|
options: SnapshotBuilderOptions
|
|
@@ -317,12 +334,15 @@ const makeSnapshotBuilder = (
|
|
|
317
334
|
continue
|
|
318
335
|
}
|
|
319
336
|
const node = Topology.getStateNodeDefinition(path, definition)
|
|
320
|
-
|
|
337
|
+
const method = withFrom(
|
|
321
338
|
(value: unknown, selector?: (builder: unknown) => unknown) =>
|
|
322
339
|
makeSnapshotForNode(definition, key, value, selector, options),
|
|
323
340
|
node.states === undefined ? "leaf" : "nested",
|
|
324
341
|
node.schema !== undefined
|
|
325
342
|
)
|
|
343
|
+
builder[key] = node.states === undefined || options.mode !== "full" || options.prefix !== ""
|
|
344
|
+
? method
|
|
345
|
+
: withInitial(method, path, node.schema !== undefined)
|
|
326
346
|
}
|
|
327
347
|
return builder
|
|
328
348
|
}
|
|
@@ -348,7 +368,7 @@ const makeParallelSnapshotBuilder = (
|
|
|
348
368
|
}
|
|
349
369
|
const path = options.prefix === "" ? key : `${options.prefix}.${key}`
|
|
350
370
|
const node = Topology.getStateNodeDefinition(path, definition)
|
|
351
|
-
|
|
371
|
+
const method = withFrom(
|
|
352
372
|
(value: unknown, selector?: (builder: unknown) => unknown) => {
|
|
353
373
|
const nextRegions: Record<string, unknown> = {}
|
|
354
374
|
for (const regionKey of Object.keys(regions)) {
|
|
@@ -360,6 +380,7 @@ const makeParallelSnapshotBuilder = (
|
|
|
360
380
|
node.states === undefined ? "leaf" : "nested",
|
|
361
381
|
node.schema !== undefined
|
|
362
382
|
)
|
|
383
|
+
builder[key] = method
|
|
363
384
|
}
|
|
364
385
|
return builder
|
|
365
386
|
}
|
|
@@ -538,7 +559,7 @@ const makeLocalTargetChildBuilder = (
|
|
|
538
559
|
builder[child.key] = () => Topology.makeChoiceTarget(child.path, parent.path, values)
|
|
539
560
|
continue
|
|
540
561
|
}
|
|
541
|
-
|
|
562
|
+
const method = withFrom(
|
|
542
563
|
(value: unknown, selector?: (builder: unknown) => unknown) => {
|
|
543
564
|
if (child.type === "atomic" || child.type === "final") {
|
|
544
565
|
return makeTargetWithValues(child.path, value, values)
|
|
@@ -572,6 +593,9 @@ const makeLocalTargetChildBuilder = (
|
|
|
572
593
|
child.type === "atomic" || child.type === "final" ? "leaf" : "nested",
|
|
573
594
|
child.schema !== undefined
|
|
574
595
|
)
|
|
596
|
+
builder[child.key] = child.type === "atomic" || child.type === "final"
|
|
597
|
+
? method
|
|
598
|
+
: withInitial(method, child.path, child.schema !== undefined, values)
|
|
575
599
|
}
|
|
576
600
|
return builder
|
|
577
601
|
}
|
|
@@ -677,6 +701,7 @@ const makeBranchTargetNodeBuilder = (
|
|
|
677
701
|
"nested",
|
|
678
702
|
node.schema !== undefined
|
|
679
703
|
) as unknown as Record<string, unknown>
|
|
704
|
+
withInitial(builder, node.path, node.schema !== undefined, values)
|
|
680
705
|
if (node.type !== "parallel" || source === node.path || source.startsWith(`${node.path}.`)) {
|
|
681
706
|
addBranchTargetChildren(builder, states, stateNodes, node.path, values, source)
|
|
682
707
|
}
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
completeConfigurationEffect,
|
|
23
23
|
completeConfigurationSync,
|
|
24
24
|
configurationFromHistoryRecord,
|
|
25
|
+
configurationFromInitialTargetSync,
|
|
25
26
|
getActiveLeafPathFrom,
|
|
26
27
|
getActiveLeafPaths,
|
|
27
28
|
getHistoryRecord,
|
|
@@ -44,13 +45,16 @@ import {
|
|
|
44
45
|
validateInitialConfiguration
|
|
45
46
|
} from "./configuration.js"
|
|
46
47
|
import { InfiniteTransitionError, MachineSchemaDecodeError, StartupError, StoppedError } from "./errors.js"
|
|
48
|
+
import { getStateInitializeValues, makeStateInitializeBuilder } from "./initialization.js"
|
|
47
49
|
import * as InvocationEvent from "./invocationEvent.js"
|
|
48
50
|
import { decodeEventSync, decodeInputSync, decodeStateValueSync } from "./protocol.js"
|
|
49
51
|
import { InitialEventTypeId } from "./symbols.js"
|
|
50
52
|
import {
|
|
51
53
|
getNode,
|
|
54
|
+
type InitialTarget as InitialTargetInstruction,
|
|
52
55
|
isChoiceTarget,
|
|
53
56
|
isHistoryTarget,
|
|
57
|
+
isInitialTarget,
|
|
54
58
|
isNoTarget,
|
|
55
59
|
isSnapshot,
|
|
56
60
|
isTarget,
|
|
@@ -230,6 +234,7 @@ const completeHistoryConfiguration = (
|
|
|
230
234
|
const commands: Array<RuntimeCommand> = []
|
|
231
235
|
const raisedEvents: Array<unknown> = []
|
|
232
236
|
const emittedEvents: Array<unknown> = []
|
|
237
|
+
const transitions: Array<ResolvedChoiceTransition> = []
|
|
233
238
|
|
|
234
239
|
let changed = true
|
|
235
240
|
while (changed) {
|
|
@@ -248,9 +253,47 @@ const completeHistoryConfiguration = (
|
|
|
248
253
|
history: configuration.history,
|
|
249
254
|
machineReferences: configuration.machineReferences
|
|
250
255
|
} as ActiveConfiguration
|
|
256
|
+
if (child.type === "choice") {
|
|
257
|
+
const choice = resolveChoiceTarget(
|
|
258
|
+
machine,
|
|
259
|
+
current,
|
|
260
|
+
makeChoiceTarget(child.path, path, Object.fromEntries(values)),
|
|
261
|
+
event
|
|
262
|
+
)
|
|
263
|
+
let next = current
|
|
264
|
+
for (const routed of [choice.target, ...choice.additionalTargets]) {
|
|
265
|
+
if (routed === undefined || isHistoryTarget(routed)) {
|
|
266
|
+
throw new Error(`Machine initial choice "${child.path}" must resolve to an active state target`)
|
|
267
|
+
}
|
|
268
|
+
const resolved = isInitialTarget(routed)
|
|
269
|
+
? resolveInitialTarget(machine, next, routed, event)
|
|
270
|
+
: undefined
|
|
271
|
+
next = normalizeTargetConfigurationSync(
|
|
272
|
+
machine,
|
|
273
|
+
next,
|
|
274
|
+
(resolved?.target ?? routed) as Machine.Snapshot<any> | Machine.Target<any, any>
|
|
275
|
+
)
|
|
276
|
+
if (resolved !== undefined) {
|
|
277
|
+
commands.push(...resolved.commands)
|
|
278
|
+
raisedEvents.push(...resolved.raisedEvents)
|
|
279
|
+
emittedEvents.push(...resolved.emittedEvents)
|
|
280
|
+
transitions.push(...resolved.transitions)
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
active.clear()
|
|
284
|
+
values.clear()
|
|
285
|
+
for (const activePath of next.active) active.add(activePath)
|
|
286
|
+
for (const [valuePath, stateValue] of next.values) values.set(valuePath, stateValue)
|
|
287
|
+
commands.push(...choice.commands)
|
|
288
|
+
raisedEvents.push(...choice.raisedEvents)
|
|
289
|
+
emittedEvents.push(...choice.emittedEvents)
|
|
290
|
+
transitions.push(...choice.transitions)
|
|
291
|
+
changed = true
|
|
292
|
+
continue
|
|
293
|
+
}
|
|
251
294
|
active.add(child.path)
|
|
252
295
|
if (child.schema !== undefined) {
|
|
253
|
-
const initializer = machine.handlers[path]?.
|
|
296
|
+
const initializer = machine.handlers[path]?.initialize
|
|
254
297
|
if (initializer === undefined) {
|
|
255
298
|
throw new Error(`Machine shallow history requires an initial value implementation for state "${path}"`)
|
|
256
299
|
}
|
|
@@ -259,9 +302,11 @@ const completeHistoryConfiguration = (
|
|
|
259
302
|
state: current.values.get(path),
|
|
260
303
|
containingState: getParentValue(machine, current, path),
|
|
261
304
|
ancestors: getParentValues(machine, current, path),
|
|
262
|
-
event
|
|
305
|
+
event,
|
|
306
|
+
builder: makeStateInitializeBuilder(machine, path)
|
|
263
307
|
})
|
|
264
|
-
|
|
308
|
+
const initializedValues = getStateInitializeValues(path, initialized.value)
|
|
309
|
+
values.set(child.path, decodeStateValueSync(machine, child, initializedValues[child.key]))
|
|
265
310
|
commands.push(...initialized.commands)
|
|
266
311
|
raisedEvents.push(...initialized.raisedEvents)
|
|
267
312
|
emittedEvents.push(...initialized.emittedEvents)
|
|
@@ -279,7 +324,7 @@ const completeHistoryConfiguration = (
|
|
|
279
324
|
history: configuration.history,
|
|
280
325
|
machineReferences: configuration.machineReferences
|
|
281
326
|
} as ActiveConfiguration
|
|
282
|
-
const initializer = valuedMissing.length === 0 ? undefined : machine.handlers[path]?.
|
|
327
|
+
const initializer = valuedMissing.length === 0 ? undefined : machine.handlers[path]?.initialize
|
|
283
328
|
if (valuedMissing.length > 0 && initializer === undefined) {
|
|
284
329
|
throw new Error(`Machine shallow history requires an initial value implementation for state "${path}"`)
|
|
285
330
|
}
|
|
@@ -288,24 +333,25 @@ const completeHistoryConfiguration = (
|
|
|
288
333
|
state: current.values.get(path),
|
|
289
334
|
containingState: getParentValue(machine, current, path),
|
|
290
335
|
ancestors: getParentValues(machine, current, path),
|
|
291
|
-
event
|
|
336
|
+
event,
|
|
337
|
+
builder: makeStateInitializeBuilder(machine, path)
|
|
292
338
|
})
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
339
|
+
const initializedValues = initialized === undefined
|
|
340
|
+
? undefined
|
|
341
|
+
: getStateInitializeValues(path, initialized.value)
|
|
296
342
|
for (const childPath of missing) {
|
|
297
343
|
const child = getNode(machine, childPath)
|
|
298
344
|
active.add(child.path)
|
|
299
345
|
if (child.schema !== undefined) {
|
|
300
346
|
if (
|
|
301
347
|
initialized === undefined ||
|
|
302
|
-
!Object.prototype.hasOwnProperty.call(
|
|
348
|
+
initializedValues === undefined || !Object.prototype.hasOwnProperty.call(initializedValues, child.key)
|
|
303
349
|
) {
|
|
304
350
|
throw new Error(`Machine parallel state initializer for "${path}" must return region "${child.key}"`)
|
|
305
351
|
}
|
|
306
352
|
values.set(
|
|
307
353
|
child.path,
|
|
308
|
-
decodeStateValueSync(machine, child,
|
|
354
|
+
decodeStateValueSync(machine, child, initializedValues[child.key])
|
|
309
355
|
)
|
|
310
356
|
}
|
|
311
357
|
}
|
|
@@ -328,16 +374,38 @@ const completeHistoryConfiguration = (
|
|
|
328
374
|
} as ActiveConfiguration,
|
|
329
375
|
commands,
|
|
330
376
|
raisedEvents,
|
|
331
|
-
emittedEvents
|
|
377
|
+
emittedEvents,
|
|
378
|
+
transitions
|
|
332
379
|
}
|
|
333
380
|
}
|
|
334
381
|
|
|
335
|
-
|
|
382
|
+
export function resolveInitialTarget(
|
|
383
|
+
machine: Machine.Any,
|
|
384
|
+
configuration: ActiveConfiguration,
|
|
385
|
+
target: InitialTargetInstruction,
|
|
386
|
+
event: unknown
|
|
387
|
+
) {
|
|
388
|
+
const partial = configurationFromInitialTargetSync(machine, configuration, target)
|
|
389
|
+
const completed = completeHistoryConfiguration(machine, partial, event)
|
|
390
|
+
const snapshot = snapshotFromConfigurationAtPath(machine, completed.configuration, target.path)
|
|
391
|
+
return {
|
|
392
|
+
target: makeTarget(target.path as any, snapshot.value as any, {
|
|
393
|
+
snapshot: snapshot as any,
|
|
394
|
+
values: Object.fromEntries(completed.configuration.values) as any
|
|
395
|
+
}),
|
|
396
|
+
commands: completed.commands,
|
|
397
|
+
raisedEvents: completed.raisedEvents,
|
|
398
|
+
emittedEvents: completed.emittedEvents,
|
|
399
|
+
transitions: completed.transitions
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function resolveHistoryTarget(
|
|
336
404
|
machine: Machine.Any,
|
|
337
405
|
configuration: ActiveConfiguration,
|
|
338
406
|
target: { readonly path: string; readonly parent: string },
|
|
339
407
|
event: unknown
|
|
340
|
-
)
|
|
408
|
+
) {
|
|
341
409
|
const node = getNode(machine, target.path)
|
|
342
410
|
if (node.type !== "history" || node.parent !== target.parent) {
|
|
343
411
|
throw new Error(`Machine expected history target "${target.path}" to resolve to its declared parent`)
|
|
@@ -359,7 +427,7 @@ const resolveHistoryTarget = (
|
|
|
359
427
|
commands: completed.commands,
|
|
360
428
|
raisedEvents: completed.raisedEvents,
|
|
361
429
|
emittedEvents: completed.emittedEvents,
|
|
362
|
-
transitions:
|
|
430
|
+
transitions: completed.transitions
|
|
363
431
|
}
|
|
364
432
|
}
|
|
365
433
|
|
|
@@ -1065,12 +1133,12 @@ interface ResolvedChoiceTransition {
|
|
|
1065
1133
|
readonly resolvedTarget: string
|
|
1066
1134
|
}
|
|
1067
1135
|
|
|
1068
|
-
|
|
1136
|
+
function resolveChoiceTarget(
|
|
1069
1137
|
machine: Machine.Any,
|
|
1070
1138
|
configuration: ActiveConfiguration,
|
|
1071
1139
|
initialTarget: unknown,
|
|
1072
1140
|
event: unknown
|
|
1073
|
-
)
|
|
1141
|
+
) {
|
|
1074
1142
|
const pending: Array<unknown> = [initialTarget]
|
|
1075
1143
|
const resolvedTargets: Array<unknown> = []
|
|
1076
1144
|
const commands: Array<RuntimeCommand> = []
|
|
@@ -1141,7 +1209,7 @@ const resolveChoiceTarget = (
|
|
|
1141
1209
|
emittedEvents.push(...collected.emittedEvents)
|
|
1142
1210
|
}
|
|
1143
1211
|
|
|
1144
|
-
if (!isTarget(current) && !isSnapshot(current) && !isHistoryTarget(current)) {
|
|
1212
|
+
if (!isTarget(current) && !isSnapshot(current) && !isHistoryTarget(current) && !isInitialTarget(current)) {
|
|
1145
1213
|
throw new Error("Machine choice resolver must return a concrete typed target")
|
|
1146
1214
|
}
|
|
1147
1215
|
resolvedTargets.push(current)
|
|
@@ -1196,6 +1264,10 @@ const collectEvaluatedTransition = <
|
|
|
1196
1264
|
(selection.context as any).event
|
|
1197
1265
|
)
|
|
1198
1266
|
const choiceResolvedTarget = choiceResolution?.target ?? unresolvedTarget
|
|
1267
|
+
const initialResolution = choiceResolvedTarget !== undefined && isInitialTarget(choiceResolvedTarget)
|
|
1268
|
+
? resolveInitialTarget(machine, state, choiceResolvedTarget, (selection.context as any).event)
|
|
1269
|
+
: undefined
|
|
1270
|
+
const routedTarget = initialResolution?.target ?? choiceResolvedTarget
|
|
1199
1271
|
let historyResolution: {
|
|
1200
1272
|
readonly target: unknown
|
|
1201
1273
|
readonly commands: ReadonlyArray<RuntimeCommand>
|
|
@@ -1203,50 +1275,64 @@ const collectEvaluatedTransition = <
|
|
|
1203
1275
|
readonly emittedEvents: ReadonlyArray<unknown>
|
|
1204
1276
|
readonly transitions: ReadonlyArray<ResolvedChoiceTransition>
|
|
1205
1277
|
} | undefined
|
|
1206
|
-
const reenteredHistoryTarget = isHistoryTarget(
|
|
1207
|
-
state.active.has(
|
|
1208
|
-
?
|
|
1278
|
+
const reenteredHistoryTarget = isHistoryTarget(routedTarget) && selection.transition.reenter &&
|
|
1279
|
+
state.active.has(routedTarget.parent)
|
|
1280
|
+
? routedTarget
|
|
1209
1281
|
: undefined
|
|
1210
|
-
if (
|
|
1282
|
+
if (routedTarget !== undefined && isHistoryTarget(routedTarget)) {
|
|
1211
1283
|
// A reentering transition may exit the history node's own parent. SCXML
|
|
1212
1284
|
// history observes that same exit, so resolve against a provisional
|
|
1213
1285
|
// capture rather than an older record (or the default).
|
|
1214
1286
|
const provisionalBoundary = selection.transition.reenter
|
|
1215
1287
|
? getNode(machine, selection.sourcePath).parent
|
|
1216
|
-
: getLeastCommonAncestor(machine, stateIdentifier,
|
|
1288
|
+
: getLeastCommonAncestor(machine, stateIdentifier, routedTarget.parent)
|
|
1217
1289
|
const provisionalExitPaths = reenteredHistoryTarget !== undefined
|
|
1218
1290
|
? sortExitPaths(
|
|
1219
1291
|
machine,
|
|
1220
|
-
Array.from(state.active).filter((path) => isPathInSubtree(path,
|
|
1292
|
+
Array.from(state.active).filter((path) => isPathInSubtree(path, routedTarget.parent))
|
|
1221
1293
|
)
|
|
1222
1294
|
: getExitPaths(machine, state, provisionalBoundary)
|
|
1223
|
-
const stateAtHistoryResolution = provisionalExitPaths.includes(
|
|
1295
|
+
const stateAtHistoryResolution = provisionalExitPaths.includes(routedTarget.parent)
|
|
1224
1296
|
? captureHistory(machine, state, state, provisionalExitPaths)
|
|
1225
1297
|
: state
|
|
1226
1298
|
historyResolution = resolveHistoryTarget(
|
|
1227
1299
|
machine,
|
|
1228
1300
|
stateAtHistoryResolution,
|
|
1229
|
-
|
|
1301
|
+
routedTarget,
|
|
1230
1302
|
(selection.context as any).event
|
|
1231
1303
|
)
|
|
1232
1304
|
}
|
|
1233
1305
|
const target: Machine.Snapshot<States> | Machine.Target<States, Machine.StateIdentifier<States>> | undefined =
|
|
1234
1306
|
historyResolution === undefined
|
|
1235
|
-
?
|
|
1307
|
+
? routedTarget as
|
|
1236
1308
|
| Machine.Snapshot<States>
|
|
1237
1309
|
| Machine.Target<States, Machine.StateIdentifier<States>>
|
|
1238
1310
|
| undefined
|
|
1239
1311
|
: historyResolution.target as
|
|
1240
1312
|
| Machine.Snapshot<States>
|
|
1241
1313
|
| Machine.Target<States, Machine.StateIdentifier<States>>
|
|
1242
|
-
const
|
|
1243
|
-
const
|
|
1244
|
-
const
|
|
1245
|
-
const
|
|
1314
|
+
const additionalTargetActions: Array<RuntimeCommand> = []
|
|
1315
|
+
const additionalTargetRaisedEvents: Array<unknown> = []
|
|
1316
|
+
const additionalTargetEmittedEvents: Array<unknown> = []
|
|
1317
|
+
const additionalTargetChoiceTransitions: Array<ResolvedChoiceTransition> = []
|
|
1246
1318
|
const additionalChoiceTargets: Array<
|
|
1247
1319
|
Machine.Snapshot<States> | Machine.Target<States, Machine.StateIdentifier<States>>
|
|
1248
1320
|
> = []
|
|
1249
1321
|
for (const additionalTarget of choiceResolution?.additionalTargets ?? []) {
|
|
1322
|
+
if (isInitialTarget(additionalTarget)) {
|
|
1323
|
+
const resolved = resolveInitialTarget(
|
|
1324
|
+
machine,
|
|
1325
|
+
state,
|
|
1326
|
+
additionalTarget,
|
|
1327
|
+
(selection.context as any).event
|
|
1328
|
+
)
|
|
1329
|
+
additionalChoiceTargets.push(resolved.target as any)
|
|
1330
|
+
additionalTargetActions.push(...resolved.commands)
|
|
1331
|
+
additionalTargetRaisedEvents.push(...resolved.raisedEvents)
|
|
1332
|
+
additionalTargetEmittedEvents.push(...resolved.emittedEvents)
|
|
1333
|
+
additionalTargetChoiceTransitions.push(...resolved.transitions)
|
|
1334
|
+
continue
|
|
1335
|
+
}
|
|
1250
1336
|
if (!isHistoryTarget(additionalTarget)) {
|
|
1251
1337
|
additionalChoiceTargets.push(additionalTarget as any)
|
|
1252
1338
|
continue
|
|
@@ -1258,10 +1344,10 @@ const collectEvaluatedTransition = <
|
|
|
1258
1344
|
(selection.context as any).event
|
|
1259
1345
|
)
|
|
1260
1346
|
additionalChoiceTargets.push(resolved.target as any)
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1347
|
+
additionalTargetActions.push(...resolved.commands)
|
|
1348
|
+
additionalTargetRaisedEvents.push(...resolved.raisedEvents)
|
|
1349
|
+
additionalTargetEmittedEvents.push(...resolved.emittedEvents)
|
|
1350
|
+
additionalTargetChoiceTransitions.push(...resolved.transitions)
|
|
1265
1351
|
}
|
|
1266
1352
|
const targetPath = target === undefined
|
|
1267
1353
|
? undefined
|
|
@@ -1288,28 +1374,32 @@ const collectEvaluatedTransition = <
|
|
|
1288
1374
|
commands: [
|
|
1289
1375
|
...transitionResult.commands,
|
|
1290
1376
|
...(choiceResolution?.commands ?? []),
|
|
1377
|
+
...(initialResolution?.commands ?? []),
|
|
1291
1378
|
...(historyResolution?.commands ?? []),
|
|
1292
|
-
...
|
|
1379
|
+
...additionalTargetActions
|
|
1293
1380
|
],
|
|
1294
1381
|
raisedEvents: [
|
|
1295
1382
|
...transitionResult.raisedEvents,
|
|
1296
1383
|
...(choiceResolution?.raisedEvents ?? []),
|
|
1384
|
+
...(initialResolution?.raisedEvents ?? []),
|
|
1297
1385
|
...(historyResolution?.raisedEvents ?? []),
|
|
1298
|
-
...
|
|
1386
|
+
...additionalTargetRaisedEvents
|
|
1299
1387
|
],
|
|
1300
1388
|
emittedEvents: [
|
|
1301
1389
|
...transitionResult.emittedEvents,
|
|
1302
1390
|
...(choiceResolution?.emittedEvents ?? []),
|
|
1391
|
+
...(initialResolution?.emittedEvents ?? []),
|
|
1303
1392
|
...(historyResolution?.emittedEvents ?? []),
|
|
1304
|
-
...
|
|
1393
|
+
...additionalTargetEmittedEvents
|
|
1305
1394
|
],
|
|
1306
1395
|
changed,
|
|
1307
1396
|
exitPaths: [],
|
|
1308
1397
|
entryPaths: [],
|
|
1309
1398
|
choiceTransitions: [
|
|
1310
1399
|
...(choiceResolution?.transitions ?? []),
|
|
1400
|
+
...(initialResolution?.transitions ?? []),
|
|
1311
1401
|
...(historyResolution?.transitions ?? []),
|
|
1312
|
-
...
|
|
1402
|
+
...additionalTargetChoiceTransitions
|
|
1313
1403
|
]
|
|
1314
1404
|
} as EvaluatedTransition<States, Event, E, R, Context>
|
|
1315
1405
|
}
|
|
@@ -1329,20 +1419,23 @@ const collectEvaluatedTransition = <
|
|
|
1329
1419
|
commands: [
|
|
1330
1420
|
...transitionResult.commands,
|
|
1331
1421
|
...(choiceResolution?.commands ?? []),
|
|
1422
|
+
...(initialResolution?.commands ?? []),
|
|
1332
1423
|
...(historyResolution?.commands ?? []),
|
|
1333
|
-
...
|
|
1424
|
+
...additionalTargetActions
|
|
1334
1425
|
],
|
|
1335
1426
|
raisedEvents: [
|
|
1336
1427
|
...transitionResult.raisedEvents,
|
|
1337
1428
|
...(choiceResolution?.raisedEvents ?? []),
|
|
1429
|
+
...(initialResolution?.raisedEvents ?? []),
|
|
1338
1430
|
...(historyResolution?.raisedEvents ?? []),
|
|
1339
|
-
...
|
|
1431
|
+
...additionalTargetRaisedEvents
|
|
1340
1432
|
],
|
|
1341
1433
|
emittedEvents: [
|
|
1342
1434
|
...transitionResult.emittedEvents,
|
|
1343
1435
|
...(choiceResolution?.emittedEvents ?? []),
|
|
1436
|
+
...(initialResolution?.emittedEvents ?? []),
|
|
1344
1437
|
...(historyResolution?.emittedEvents ?? []),
|
|
1345
|
-
...
|
|
1438
|
+
...additionalTargetEmittedEvents
|
|
1346
1439
|
],
|
|
1347
1440
|
changed,
|
|
1348
1441
|
exitPaths: reenteredHistoryTarget !== undefined
|
|
@@ -1359,8 +1452,9 @@ const collectEvaluatedTransition = <
|
|
|
1359
1452
|
: getEntryPaths(machine, stateAfterTransition, boundary),
|
|
1360
1453
|
choiceTransitions: [
|
|
1361
1454
|
...(choiceResolution?.transitions ?? []),
|
|
1455
|
+
...(initialResolution?.transitions ?? []),
|
|
1362
1456
|
...(historyResolution?.transitions ?? []),
|
|
1363
|
-
...
|
|
1457
|
+
...additionalTargetChoiceTransitions
|
|
1364
1458
|
]
|
|
1365
1459
|
} as EvaluatedTransition<States, Event, E, R, Context>
|
|
1366
1460
|
}
|
|
@@ -73,8 +73,7 @@ const acknowledgedPlan = (
|
|
|
73
73
|
commands: planned.commands,
|
|
74
74
|
emittedEvents: planned.emittedEvents,
|
|
75
75
|
microsteps: planned.microsteps.map((microstep) => {
|
|
76
|
-
|
|
77
|
-
return { ...evidence, next: snapshot(microstep.next) }
|
|
76
|
+
return { ...microstep, transitions: microstep.transitions ?? [], next: snapshot(microstep.next) }
|
|
78
77
|
}),
|
|
79
78
|
done: planned.done,
|
|
80
79
|
output: planned.output
|
|
@@ -433,6 +432,7 @@ const makeProcessLogic: <
|
|
|
433
432
|
) => {
|
|
434
433
|
try {
|
|
435
434
|
const planned = compiledInitial(initialArgs, scope)
|
|
435
|
+
scope.inspectInitial(planned.initialEntryPaths)
|
|
436
436
|
const result = {
|
|
437
437
|
state: planned.state as Machine.Snapshot<States>,
|
|
438
438
|
done: planned.done,
|
|
@@ -461,6 +461,7 @@ const makeProcessLogic: <
|
|
|
461
461
|
? internalRuntime.provideMachineRuntime(
|
|
462
462
|
internalPlanner.planInitial(internalPlanner.withMachineReferences(machine, scope), ...initialArgs).pipe(
|
|
463
463
|
Effect.flatMap((planned) => {
|
|
464
|
+
scope.inspectInitial(planned.initialEntryPaths, planned.microsteps)
|
|
464
465
|
const commands = planned.commands.length === 0
|
|
465
466
|
? undefined
|
|
466
467
|
: CommandRuntime.runCommands(planned.commands, scope)
|
|
@@ -486,6 +487,7 @@ const makeProcessLogic: <
|
|
|
486
487
|
)
|
|
487
488
|
: Effect.try({ try: () => makeCompiledInitial!(scope), catch: (error) => error as any })
|
|
488
489
|
return ({
|
|
490
|
+
inspection: { kind: "Machine", definition: machine },
|
|
489
491
|
execution: {
|
|
490
492
|
_tag: "Compiled",
|
|
491
493
|
childless: !hasInvokes,
|