jsboost
Version:
A tiny library that extends the capability of javascript
85 lines (73 loc) • 2.15 kB
JavaScript
/**
* Author: JCloudYu
* Create: 2018/11/16
**/
const DEFAULT_STATE_INFO = [ ___FIN_ERROR, {} ];
export function StateMachineCreate(states={}, initial_state=null) {
const _state_map = {};
const _state_names = Object.keys(states);
if ( _state_names.length <= 0 ) {
throw new RangeError( "Given state descriptor contains no states!" );
}
for( let state_name of _state_names ) {
let state_callback = states[state_name];
if ( typeof state_callback !== "function" ) {
throw new RangeError( "State processor must be a function!" );
}
_state_map[state_name] = [state_callback, {}];
}
let _current_state = initial_state || _state_names[0];
let _current_state_info = _state_map[_current_state];
const _state_instance = {
get state() {
return _current_state;
},
set state(state) {
if ( _current_state === 'fin' ) {
throw new RangeError( `The machine is finished!!` );
}
if ( state !== 'fin' ) {
let info = _state_map[state];
if ( !info ) {
throw new RangeError( `Given state ${state} is invalid!` );
}
_current_state = state;
_current_state_info = info;
}
else {
_current_state = 'fin';
_current_state_info = DEFAULT_STATE_INFO;
}
}
};
const _state_exec = function(...args){
_state_instance.storage = _current_state_info[1];
return _current_state_info[0].call(_state_instance, ...args);
};
Object.defineProperties(_state_exec, {
reset:{
value:(state)=>{
let info = _state_map[state];
if ( !info ) {
throw new RangeError( `Cannot reset state to ${state}!` );
}
for( let state_name in _state_map ) {
if ( !_state_map.hasOwnProperty(state_name) ) continue;
_state_map[state_name][1] = {};
}
_current_state = state;
_current_state_info = info;
}, enumerable:true
},
state:{
get:()=>_current_state,
set:(val)=>{_state_instance.state = val;},
enumerable:true, configurable:false
},
finished: {
get:()=>_current_state==='fin', enumerable:true, configurable:false
}
});
return _state_exec;
}
function ___FIN_ERROR(){ throw new Error( `The machine is finished!` ) }