@@ -119,6 +119,7 @@ const cloneWithHandlers = (
119119 machine . input = self . input
120120 machine . id = self . id
121121 machine . initial = self . initial
122+ machine . initialDefinition = self . initialDefinition
122123 machine . stateNodes = self . stateNodes
123124 machine . makeTargetBuilder = self . makeTargetBuilder
124125 machine . handlers = handlers
@@ -139,6 +140,15 @@ type CapturedBranch = DefinitionBranch & {
139140 readonly selection : Topology . TargetSelection
140141}
141142
143+ const transitionTargetSelection = (
144+ selection : Topology . TargetSelection
145+ ) : Machine . TransitionTargetSelection =>
146+ Object . freeze ( {
147+ path : selection . path ,
148+ kind : selection . kind ,
149+ scope : selection . scope
150+ } )
151+
142152const makeSelectionMethod = (
143153 kind : Topology . TargetSelectionKind ,
144154 path : string | undefined ,
@@ -349,6 +359,27 @@ const captureTransition = (
349359 return captured
350360 } )
351361 const otherwise = captureDefinitionBranch ( definition . otherwise , selector , path , trigger )
362+ const evaluate = ( context : Record < string , any > , enqueue : unknown) = > {
363+ const predicateContext = { ...context }
364+ delete predicateContext . target
365+ for ( let branchIndex = 0 ; branchIndex < cases . length ; branchIndex ++ ) {
366+ const branch = cases [ branchIndex ] !
367+ const result = branch . when ! ( predicateContext )
368+ if ( ! Option . isOption ( result ) ) {
369+ throw new Error ( `Machine conditional transition case "${ branch . title } " must return Option` )
370+ }
371+ if ( Option . isSome ( result ) ) {
372+ return {
373+ result : runCapturedBranch ( branch , context , enqueue , stateNodes , path , { value : result . value } ) ,
374+ branchIndex
375+ }
376+ }
377+ }
378+ return {
379+ result : runCapturedBranch ( otherwise , context , enqueue , stateNodes , path ) ,
380+ branchIndex : cases . length
381+ }
382+ }
352383 return {
353384 reenter,
354385 targets : [
@@ -357,32 +388,37 @@ const captureTransition = (
357388 )
358389 ] ,
359390 branches : [
360- ...cases . map ( ( branch ) => ( { type : "case" as const , title : branch . title ! , target : branch . selection . path } ) ) ,
361- { type : "otherwise" as const , target : otherwise . selection . path }
362- ] ,
363- transition : ( context : Record < string , any > , enqueue : unknown ) => {
364- const predicateContext = { ...context }
365- delete predicateContext . target
366- for ( const branch of cases ) {
367- const result = branch . when ! ( predicateContext )
368- if ( ! Option . isOption ( result ) ) {
369- throw new Error ( `Machine conditional transition case "${ branch . title } " must return Option` )
370- }
371- if ( Option . isSome ( result ) ) {
372- return runCapturedBranch ( branch , context , enqueue , stateNodes , path , { value : result . value } )
373- }
391+ ...cases . map ( ( branch ) => ( {
392+ type : "case" as const ,
393+ title : branch . title ! ,
394+ target : branch . selection . path ,
395+ selection : transitionTargetSelection ( branch . selection )
396+ } ) ) ,
397+ {
398+ type : "otherwise" as const ,
399+ target : otherwise . selection . path ,
400+ selection : transitionTargetSelection ( otherwise . selection )
374401 }
375- return runCapturedBranch ( otherwise , context , enqueue , stateNodes , path )
376- }
402+ ] ,
403+ evaluate,
404+ transition : ( context : Record < string , any > , enqueue : unknown ) => evaluate ( context , enqueue ) . result
377405 }
378406 }
379407 const branch = captureDefinitionBranch ( transition , selector , path , trigger )
408+ const evaluate = ( context : Record < string , any > , enqueue : unknown) = > ( {
409+ result : runCapturedBranch ( branch , context , enqueue , stateNodes , path ) ,
410+ branchIndex : 0
411+ } )
380412 return {
381413 reenter ,
382414 targets : branch . selection . path === undefined ? [ ] : [ branch . selection . path ] ,
383- branches : [ { type : "direct" as const , target : branch . selection . path } ] ,
384- transition : ( context : Record < string , any > , enqueue : unknown ) =>
385- runCapturedBranch ( branch , context , enqueue , stateNodes , path )
415+ branches : [ {
416+ type : "direct" as const ,
417+ target : branch . selection . path ,
418+ selection : transitionTargetSelection ( branch . selection )
419+ } ] ,
420+ evaluate ,
421+ transition : ( context : Record < string , any > , enqueue : unknown ) => evaluate ( context , enqueue ) . result
386422 }
387423}
388424
@@ -1067,19 +1103,28 @@ const compileInitial = (
10671103 definition : unknown,
10681104 states : Machine . StateTree ,
10691105 stateNodes : Machine . StateNodes
1070- ) : ( input ?: unknown) = > unknown => {
1106+ ) : {
1107+ readonly initial : ( input ?: unknown) = > unknown
1108+ readonly definition : Machine . InitialDefinition
1109+ } => {
10711110 if ( typeof definition !== "object" || definition === null ) {
10721111 throw new Error ( "Machine initial definition must be an object" )
10731112 }
10741113 const selector = makeInitialSelector ( stateNodes )
10751114 const initialBuilder = makeSnapshotBuilder ( states , { mode : "initial" , prefix : "" } ) as Record < string , any >
10761115 const branch = captureInitialBranch ( definition , selector , initialBuilder )
1077- return ( input ?: unknown ) => {
1078- const result = branch . resolve === undefined
1079- ? branch . builder ( )
1080- : branch . resolve ( { input, target : branch . builder } , undefined )
1081- validateInitialSelection ( result , branch . selection )
1082- return result
1116+ return {
1117+ initial : ( input ?: unknown) = > {
1118+ const result = branch . resolve === undefined
1119+ ? branch . builder ( )
1120+ : branch . resolve ( { input, target : branch . builder } , undefined )
1121+ validateInitialSelection ( result , branch . selection )
1122+ return result
1123+ } ,
1124+ definition : Object . freeze ( {
1125+ target : branch . selection . path ! ,
1126+ selection : transitionTargetSelection ( branch . selection ) as Machine . InitialDefinition [ "selection" ]
1127+ } )
10831128 }
10841129}
10851130
@@ -1221,7 +1266,9 @@ export const make: Make = (<
12211266 self . input = config . input
12221267 self . id = config . id
12231268 self . stateNodes = Topology . compileStateNodes ( config . states )
1224- self . initial = compileInitial ( config . initial , config . states , self . stateNodes )
1269+ const compiledInitial = compileInitial ( config . initial , config . states , self . stateNodes )
1270+ self . initial = compiledInitial . initial
1271+ self . initialDefinition = compiledInitial . definition
12251272 self . makeTargetBuilder = makeTargetBuilder ( config . states , self . stateNodes )
12261273 self . handlers = Object . create ( null )
12271274 self . handle = makeHandle ( self )
@@ -1427,6 +1474,15 @@ export const stateNodes = <M extends Machine.Any>(
14271474 >
14281475 >
14291476
1477+ export const initialDefinition = < M extends Machine . Any > (
1478+ machine : M
1479+ ) : Machine . InitialDefinition <
1480+ Machine . RootStateIdentifier < Machine . StateIdentifier < Machine . States < M > > >
1481+ > =>
1482+ machine . initialDefinition as Machine . InitialDefinition <
1483+ Machine . RootStateIdentifier < Machine . StateIdentifier < Machine . States < M > > >
1484+ >
1485+
14301486export const transitionDefinitions = < M extends Machine . Any > (
14311487 machine : M
14321488) : ReadonlyArray <
0 commit comments