1
1
// whargarbl lots of these return arrays could/should be sets
2
2
import { reduce as reduce_to_639 } from 'reduce-to-639-1' ;
3
- import { seq , weighted_rand_select , weighted_sample_select , histograph , weighted_histo_key , array_box_if_string } from './jssm_util' ;
3
+ import { seq , weighted_rand_select , weighted_sample_select , histograph , weighted_histo_key , array_box_if_string , hook_name , named_hook_name } from './jssm_util' ;
4
4
import { parse } from './jssm-dot' ; // TODO FIXME WHARGARBL this could be post-typed
5
5
import { version } from './version' ; // replaced from package.js in build // TODO FIXME currently broken
6
6
/* eslint-disable complexity */
@@ -345,6 +345,9 @@ class Machine {
345
345
this . _theme = theme ;
346
346
this . _flow = flow ;
347
347
this . _graph_layout = graph_layout ;
348
+ this . _has_hooks = false ;
349
+ this . _hooks = new Map ( ) ;
350
+ this . _named_hooks = new Map ( ) ;
348
351
if ( state_declaration ) {
349
352
state_declaration . map ( ( state_decl ) => {
350
353
if ( this . _state_declarations . has ( state_decl . state ) ) { // no repeats
@@ -694,14 +697,59 @@ class Machine {
694
697
has_completes ( ) {
695
698
return this . states ( ) . some ( ( x ) => this . state_is_complete ( x ) ) ;
696
699
}
700
+ // basic toolable hook call. convenience wrappers will follow, like
701
+ // hook(from, to, handler) and exit_hook(from, handler) and etc
702
+ set_hook ( HookDesc ) {
703
+ switch ( HookDesc . kind ) {
704
+ case 'hook' :
705
+ this . _hooks . set ( hook_name ( HookDesc . from , HookDesc . to ) , HookDesc . handler ) ;
706
+ this . _has_hooks = true ;
707
+ break ;
708
+ case 'named' :
709
+ this . _named_hooks . set ( named_hook_name ( HookDesc . from , HookDesc . to , HookDesc . action ) , HookDesc . handler ) ;
710
+ this . _has_hooks = true ;
711
+ break ;
712
+ // case 'entry':
713
+ // console.log('TODO: Should add entry hook here');
714
+ // throw 'TODO: Should add entry hook here';
715
+ // case 'exit':
716
+ // console.log('TODO: Should add exit hook here');
717
+ // throw 'TODO: Should add exit hook here';
718
+ default :
719
+ console . log ( `Unknown hook type ${ HookDesc . kind } , should be impossible` ) ;
720
+ throw new RangeError ( `Unknown hook type ${ HookDesc . kind } , should be impossible` ) ;
721
+ }
722
+ }
723
+ // remove_hook(HookDesc: HookDescription) {
724
+ // throw 'TODO: Should remove hook here';
725
+ // }
697
726
action ( name , newData ) {
698
727
// todo whargarbl implement hooks
699
728
// todo whargarbl implement data stuff
700
729
// todo major incomplete whargarbl comeback
701
730
if ( this . valid_action ( name , newData ) ) {
702
731
const edge = this . current_action_edge_for ( name ) ;
703
- this . _state = edge . to ;
704
- return true ;
732
+ if ( this . _has_hooks ) {
733
+ let hook_permits = undefined ;
734
+ const nhn = named_hook_name ( this . _state , edge . to , name ) , maybe_hook = this . _named_hooks . get ( nhn ) ;
735
+ if ( maybe_hook === undefined ) {
736
+ hook_permits = true ;
737
+ }
738
+ else {
739
+ hook_permits = maybe_hook ( { from : this . _state , to : edge . to , action : name } ) ;
740
+ }
741
+ if ( hook_permits !== false ) {
742
+ this . _state = edge . to ;
743
+ return true ;
744
+ }
745
+ else {
746
+ return false ;
747
+ }
748
+ }
749
+ else {
750
+ this . _state = edge . to ;
751
+ return true ;
752
+ }
705
753
}
706
754
else {
707
755
return false ;
@@ -712,8 +760,27 @@ class Machine {
712
760
// todo whargarbl implement data stuff
713
761
// todo major incomplete whargarbl comeback
714
762
if ( this . valid_transition ( newState , newData ) ) {
715
- this . _state = newState ;
716
- return true ;
763
+ if ( this . _has_hooks ) {
764
+ let hook_permits = undefined ;
765
+ const hn = hook_name ( this . _state , newState ) , maybe_hook = this . _hooks . get ( hn ) ;
766
+ if ( maybe_hook === undefined ) {
767
+ hook_permits = true ;
768
+ }
769
+ else {
770
+ hook_permits = maybe_hook ( { from : this . _state , to : newState } ) ;
771
+ }
772
+ if ( hook_permits !== false ) {
773
+ this . _state = newState ;
774
+ return true ;
775
+ }
776
+ else {
777
+ return false ;
778
+ }
779
+ }
780
+ else {
781
+ this . _state = newState ;
782
+ return true ;
783
+ }
717
784
}
718
785
else {
719
786
return false ;
@@ -725,16 +792,37 @@ class Machine {
725
792
// todo whargarbl implement data stuff
726
793
// todo major incomplete whargarbl comeback
727
794
if ( this . valid_force_transition ( newState , newData ) ) {
728
- this . _state = newState ;
729
- return true ;
795
+ if ( this . _has_hooks ) {
796
+ let hook_permits = undefined ;
797
+ const hn = hook_name ( this . _state , newState ) , maybe_hook = this . _hooks . get ( hn ) ;
798
+ if ( maybe_hook === undefined ) {
799
+ hook_permits = true ;
800
+ }
801
+ else {
802
+ hook_permits = maybe_hook ( { from : this . _state , to : newState , forced : true } ) ;
803
+ }
804
+ if ( hook_permits !== false ) {
805
+ this . _state = newState ;
806
+ return true ;
807
+ }
808
+ else {
809
+ return false ;
810
+ }
811
+ }
812
+ else {
813
+ this . _state = newState ;
814
+ return true ;
815
+ }
730
816
}
731
817
else {
732
818
return false ;
733
819
}
734
820
}
735
821
current_action_for ( action ) {
736
822
const action_base = this . _actions . get ( action ) ;
737
- return action_base ? action_base . get ( this . state ( ) ) : undefined ;
823
+ return action_base
824
+ ? action_base . get ( this . state ( ) )
825
+ : undefined ;
738
826
}
739
827
current_action_edge_for ( action ) {
740
828
const idx = this . current_action_for ( action ) ;
0 commit comments