UNPKG

finestate

Version:

Powerful and easy to use Finite State Machine with hierarchy, orthogonal states and 100% tests coverage.

3 lines (2 loc) 6.6 kB
(function(n,l){typeof exports=="object"&&typeof module<"u"?l(exports):typeof define=="function"&&define.amd?define(["exports"],l):(n=typeof globalThis<"u"?globalThis:n||self,l(n.FineState={}))})(this,function(n){"use strict";var Q=Object.defineProperty;var C=(n,l,_)=>l in n?Q(n,l,{enumerable:!0,configurable:!0,writable:!0,value:_}):n[l]=_;var c=(n,l,_)=>C(n,typeof l!="symbol"?l+"":l,_);const l="Destroyed state used";function _(h,...t){return[h,...t]}class O{}function f(h){return h[0]}function u(h){return h.length-1}function p(h,t){return h[1+t]}var D=(h=>(h[h.Ascending=0]="Ascending",h[h.Descending=1]="Descending",h))(D||{}),g=(h=>(h[h.StopOnProcessed=0]="StopOnProcessed",h[h.DontStopOnProcessed=1]="DontStopOnProcessed",h))(g||{});class F{constructor(t,e,i,s){c(this,"dispatchOrder",0);c(this,"dispatchOrthoPolicy",0);c(this,"_fsm");c(this,"_parent");c(this,"_orthoIndex");c(this,"_children");this._fsm=t,this._parent=e,this._orthoIndex=i,this._children=new Array(s);for(let r=0;r<s;++r)this._children[r]=null;this._parent&&(this._parent._children[i]=this)}context(t){return this._parent?this._parent instanceof t?this._parent:this._parent.context(t):null}get fsm(){if(!this._fsm)throw new Error(l);return this._fsm}get parent(){return this._parent}get children(){return this._children}get orthoIndex(){return this._orthoIndex}get destroyed(){return this._fsm===null}_init(t){this.initParams(t)}dispatchToChildren(t){let e=!1;const i=s=>{if(s)return!!(s.dispatch(t)&&(e=!0,this.dispatchOrthoPolicy==0))};switch(this.dispatchOrder){case 0:{for(let s=0;s<this.children.length&&!i(this.children[s]);++s);break}case 1:{for(let s=this.children.length;s--&&!i(this.children[s]););break}}return e}dispatch(t){if(this.dispatchToChildren(t))return!0;const e=this.processEvent(t);return!(!e||e instanceof Promise)}processEvent(t){return!1}_destroy(){for(let t=this._children.length;t--;){let e=this._children[t];e&&(e._destroy(),e=null)}this.destroy(),this._parent&&(this._parent._children[this._orthoIndex]=null,this._parent=null),this._fsm=null}transit(t,e){if(!this._fsm)throw l;return this._fsm.transit(this,t,e),!0}initParams(t){this.init()}init(){}destroy(){}}const m="The same class is used twice in FSM description: ",w="The state is not registered in FSM: ",y="Transition from transition or init is not allowed.",I="Transition from one ortho area to another is not allowed.";class M{constructor(t){c(this,"_descs");c(this,"_rootState");c(this,"_stateTypeToDesc",new Map);c(this,"_stateDescParent",new Map);c(this,"_stateOrthoIndex",new Map);c(this,"_dispatchDeferred",!1);c(this,"_dispatchQueue",[]);c(this,"_dispatchQueueIndex",0);c(this,"_inTransition",!1);this._descs=t,this._rootState=null,t.forEach(e=>{this._fillStateTypeToDescMap(e,0),this._fillStateDescParent(null,e)})}init(t){t||(t={});try{this._dispatchDeferred=!0,this._inTransition=!0,this._createDefaultStateTree(null,this._descs[0],0,t),this._inTransition=!1,this._dispatchDeferred=!1}catch(e){throw this._inTransition=!1,this._dispatchDeferred=!1,e}this._dispatchQueue.length>0&&this._dispatchDeferredQueue()}get rootState(){return this._rootState}transit(t,e,i){if(this._inTransition)throw new Error(y);const s=this._stateTypeToDesc.get(e);if(!s)throw w+e.name;const r=s;{const o=this._stateDescParent.get(r),a=this._stateOrthoIndex.get(e);if(t.parent&&o&&t.parent.constructor===f(o)&&t.orthoIndex!=a)throw new Error(I)}i||(i={});try{this._dispatchDeferred=!0,this._inTransition=!0;const o=t.parent;t._destroy();let a;if(o){const d=this._destroyTillFirstCommonAncestor(o,r);a=this._createSpecificState(d,r,i)}else a=this._createSpecificState(null,r,i);const T=u(r);for(let d=0;d<T;++d){const S=p(r,d);S&&S.length>0&&this._createDefaultStateTree(a,S[0],d,i)}this._inTransition=!1,this._dispatchDeferred=!1}catch(o){throw this._inTransition=!1,this._dispatchDeferred=!1,o}return this._dispatchQueue.length>0&&this._dispatchDeferredQueue(),!0}dispatch(t){if(this._dispatchDeferred)return this._dispatchQueue.push(t),!1;let e;try{this._dispatchDeferred=!0,e=this._rootState.dispatch(t),this._dispatchDeferred=!1,this._dispatchQueue.length>0&&this._dispatchDeferredQueue()}catch(i){throw this._dispatchDeferred=!1,i}return e}_dispatchDeferredQueue(){try{for(;this._dispatchQueueIndex<this._dispatchQueue.length;){const t=this._dispatchQueue[this._dispatchQueueIndex++];this._dispatchDeferred=!0,this._rootState.dispatch(t),this._dispatchDeferred=!1}this._dispatchQueue=[],this._dispatchQueueIndex=0}catch(t){throw this._dispatchQueue=[],this._dispatchQueueIndex=0,this._dispatchDeferred=!1,t}}_createDefaultStateTree(t,e,i,s){const r=u(e),o=f(e),a=new o(this,t,i,r);a._init(s),t||(this._rootState=a);for(let T=0;T<r;++T){const d=p(e,T);d&&d.length>0&&this._createDefaultStateTree(a,d[0],T,s)}return a}_destroyTillFirstCommonAncestor(t,e){const i=this._stateTypeToDesc.get(t.constructor);if(this._areFromTheSameStateTree(i,e))return t;const s=t.parent;return t._destroy(),s?this._destroyTillFirstCommonAncestor(s,e):null}_createSpecificState(t,e,i){const s=this._stateDescParent.get(e);if(t===null&&s===null||t!==null&&f(s)===t.constructor)return this._createSpecificStateWithOrthoSiblings(t,e,i);const r=this._createSpecificState(t,s,i);return this._createSpecificStateWithOrthoSiblings(r,e,i)}_createSpecificStateWithOrthoSiblings(t,e,i){const s=f(e),r=this._stateOrthoIndex.get(s),o=u(e);let a=null;return t===null?(a=new s(this,null,0,o),this._rootState=a,a._init(i)):(a=new s(this,t,r,o),a._init(i)),a}_fillStateTypeToDescMap(t,e){const i=f(t);if(this._stateTypeToDesc.has(i))throw m+i.name;this._stateTypeToDesc.set(i,t),this._stateOrthoIndex.set(i,e);const s=u(t);for(let r=0;r<s;++r){const o=p(t,r);o==null||o.forEach(a=>this._fillStateTypeToDescMap(a,r))}}_fillStateDescParent(t,e){this._stateDescParent.set(e,t);const i=u(e);for(let s=0;s<i;++s){const r=p(e,s);r==null||r.forEach(o=>{this._fillStateDescParent(e,o)})}}_areFromTheSameStateTree(t,e){if(t===e)return!1;const i=u(t);for(let s=0;s<i;++s){const r=p(t,s);for(const o of r)if(o===e||this._areFromTheSameStateTree(o,e))return!0}return!1}}n.DispatchOrder=D,n.DispatchOrthoPolicy=g,n.Event=O,n.Fsm=M,n.State=F,n.ThrowMsg_DestroyedStateUsed=l,n.ThrowMsg_TheSameClassUsedTwiceInTheFSMDescription=m,n.ThrowMsg_TheStateIsNotRegistered=w,n.ThrowMsg_TransitionFromOneOrthoAreaToAnotherIsNotAllowed=I,n.ThrowMsg_TransitionFromTransitionOrInitIsNotAllowed=y,n.numOrthoChildrenFromStateDesc=u,n.orthoChildrenFromStateDesc=p,n.stateDesc=_,n.stateTypeFromStateDesc=f,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})}); //# sourceMappingURL=finestate.umd.js.map