xstate
Version:
Finite State Machines and Statecharts for the Modern Web.
3 lines (2 loc) • 12.8 kB
JavaScript
!function(t,s){"object"==typeof exports&&"undefined"!=typeof module?s(exports):"function"==typeof define&&define.amd?define(["exports"],s):s((t="undefined"!=typeof globalThis?globalThis:t||self).XStateActors={})}(this,(function(t){"use strict";class s{constructor(t){this._process=t,this._active=!1,this._current=null,this._last=null}start(){this._active=!0,this.flush()}clear(){this._current&&(this._current.next=null,this._last=this._current)}enqueue(t){const s={value:t,next:null};if(this._current)return this._last.next=s,void(this._last=s);this._current=s,this._last=s,this._active&&this.flush()}flush(){for(;this._current;){const t=this._current;this._process(t.value),this._current=t.next}this._last=null}}const e="xstate.stop";function i(){const t="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:window;if(t.__xstate__)return t.__xstate__}const o=t=>{const s=i();s&&s.register(t)};function r(t){setTimeout((()=>{throw t}))}const n="function"==typeof Symbol&&Symbol.observable||"@@observable";function a(t,s,e){const i="object"==typeof t,o=i?t:void 0;return{next:(i?t.next:t)?.bind(o),error:(i?t.error:s)?.bind(o),complete:(i?t.complete:e)?.bind(o)}}function h(t,s){return`${t.sessionId}.${s}`}let c=0;let p=!1;let u=function(t){return t[t.NotStarted=0]="NotStarted",t[t.Running=1]="Running",t[t.Stopped=2]="Stopped",t}({});const d={clock:{setTimeout:(t,s)=>setTimeout(t,s),clearTimeout:t=>clearTimeout(t)},logger:console.log.bind(console),devTools:!1};class l{constructor(t,e){this.logic=t,this._snapshot=void 0,this.clock=void 0,this.options=void 0,this.id=void 0,this.mailbox=new s(this._process.bind(this)),this.observers=new Set,this.eventListeners=new Map,this.logger=void 0,this._processingStatus=u.NotStarted,this._parent=void 0,this._syncSnapshot=void 0,this.ref=void 0,this._actorScope=void 0,this._systemId=void 0,this.sessionId=void 0,this.system=void 0,this._doneEvent=void 0,this.src=void 0,this._deferred=[];const i={...d,...e},{clock:o,logger:r,parent:n,syncSnapshot:l,id:_,systemId:v,inspect:f}=i;this.system=n?n.system:function(t,s){const e=new Map,i=new Map,o=new WeakMap,r=new Set,n={},{clock:p,logger:u}=s,d={schedule:(t,s,e,i,o=Math.random().toString(36).slice(2))=>{const r={source:t,target:s,event:e,delay:i,id:o,startedAt:Date.now()},a=h(t,o);l._snapshot._scheduledEvents[a]=r;const c=p.setTimeout((()=>{delete n[a],delete l._snapshot._scheduledEvents[a],l._relay(t,s,e)}),i);n[a]=c},cancel:(t,s)=>{const e=h(t,s),i=n[e];delete n[e],delete l._snapshot._scheduledEvents[e],void 0!==i&&p.clearTimeout(i)},cancelAll:t=>{for(const s in l._snapshot._scheduledEvents){const e=l._snapshot._scheduledEvents[s];e.source===t&&d.cancel(t,e.id)}}},l={_snapshot:{_scheduledEvents:(s?.snapshot&&s.snapshot.scheduler)??{}},_bookId:()=>"x:"+c++,_register:(t,s)=>(e.set(t,s),t),_unregister:t=>{e.delete(t.sessionId);const s=o.get(t);void 0!==s&&(i.delete(s),o.delete(t))},get:t=>i.get(t),_set:(t,s)=>{const e=i.get(t);if(e&&e!==s)throw new Error(`Actor with system ID '${t}' already exists.`);i.set(t,s),o.set(s,t)},inspect:t=>{const s=a(t);return r.add(s),{unsubscribe(){r.delete(s)}}},_sendInspectionEvent:s=>{if(!r.size)return;const e={...s,rootId:t.sessionId};r.forEach((t=>t.next?.(e)))},_relay:(t,s,e)=>{l._sendInspectionEvent({type:"@xstate.event",sourceRef:t,actorRef:s,event:e}),s._send(e)},scheduler:d,getSnapshot:()=>({_scheduledEvents:{...l._snapshot._scheduledEvents}}),start:()=>{const t=l._snapshot._scheduledEvents;l._snapshot._scheduledEvents={};for(const s in t){const{source:e,target:i,event:o,delay:r,id:n}=t[s];d.schedule(e,i,o,r,n)}},_clock:p,_logger:u};return l}(this,{clock:o,logger:r}),f&&!n&&this.system.inspect(a(f)),this.sessionId=this.system._bookId(),this.id=_??this.sessionId,this.logger=e?.logger??this.system._logger,this.clock=e?.clock??this.system._clock,this._parent=n,this._syncSnapshot=l,this.options=i,this.src=i.src??t,this.ref=this,this._actorScope={self:this,id:this.id,sessionId:this.sessionId,logger:this.logger,defer:t=>{this._deferred.push(t)},system:this.system,stopChild:t=>{if(t._parent!==this)throw new Error(`Cannot stop child actor ${t.id} of ${this.id} because it is not a child`);t._stop()},emit:t=>{const s=this.eventListeners.get(t.type),e=this.eventListeners.get("*");if(!s&&!e)return;const i=[...s?s.values():[],...e?e.values():[]];for(const s of i)s(t)},actionExecutor:t=>{const s=()=>{if(this._actorScope.system._sendInspectionEvent({type:"@xstate.action",actorRef:this,action:{type:t.type,params:t.params}}),!t.exec)return;const s=p;try{p=!0,t.exec(t.info,t.params)}finally{p=s}};this._processingStatus===u.Running?s():this._deferred.push(s)}},this.send=this.send.bind(this),this.system._sendInspectionEvent({type:"@xstate.actor",actorRef:this}),v&&(this._systemId=v,this.system._set(v,this)),this._initState(e?.snapshot??e?.state),v&&"active"!==this._snapshot.status&&this.system._unregister(this)}_initState(t){try{this._snapshot=t?this.logic.restoreSnapshot?this.logic.restoreSnapshot(t,this._actorScope):t:this.logic.getInitialSnapshot(this._actorScope,this.options?.input)}catch(t){this._snapshot={status:"error",output:void 0,error:t}}}update(t,s){let e;for(this._snapshot=t;e=this._deferred.shift();)try{e()}catch(s){this._deferred.length=0,this._snapshot={...t,status:"error",error:s}}switch(this._snapshot.status){case"active":for(const s of this.observers)try{s.next?.(t)}catch(t){r(t)}break;case"done":for(const s of this.observers)try{s.next?.(t)}catch(t){r(t)}this._stopProcedure(),this._complete(),this._doneEvent=(i=this.id,o=this._snapshot.output,{type:`xstate.done.actor.${i}`,output:o,actorId:i}),this._parent&&this.system._relay(this,this._parent,this._doneEvent);break;case"error":this._error(this._snapshot.error)}var i,o;this.system._sendInspectionEvent({type:"@xstate.snapshot",actorRef:this,event:s,snapshot:t})}subscribe(t,s,e){const i=a(t,s,e);if(this._processingStatus!==u.Stopped)this.observers.add(i);else switch(this._snapshot.status){case"done":try{i.complete?.()}catch(t){r(t)}break;case"error":{const t=this._snapshot.error;if(i.error)try{i.error(t)}catch(t){r(t)}else r(t);break}}return{unsubscribe:()=>{this.observers.delete(i)}}}on(t,s){let e=this.eventListeners.get(t);e||(e=new Set,this.eventListeners.set(t,e));const i=s.bind(void 0);return e.add(i),{unsubscribe:()=>{e.delete(i)}}}start(){if(this._processingStatus===u.Running)return this;this._syncSnapshot&&this.subscribe({next:t=>{"active"===t.status&&this.system._relay(this,this._parent,{type:`xstate.snapshot.${this.id}`,snapshot:t})},error:()=>{}}),this.system._register(this.sessionId,this),this._systemId&&this.system._set(this._systemId,this),this._processingStatus=u.Running;const t={type:"xstate.init",input:this.options.input};this.system._sendInspectionEvent({type:"@xstate.event",sourceRef:this._parent,actorRef:this,event:t});switch(this._snapshot.status){case"done":return this.update(this._snapshot,t),this;case"error":return this._error(this._snapshot.error),this}if(this._parent||this.system.start(),this.logic.start)try{this.logic.start(this._snapshot,this._actorScope)}catch(t){return this._snapshot={...this._snapshot,status:"error",error:t},this._error(t),this}return this.update(this._snapshot,t),this.options.devTools&&this.attachDevTools(),this.mailbox.start(),this}_process(t){let s,i;try{s=this.logic.transition(this._snapshot,t,this._actorScope)}catch(t){i={err:t}}if(i){const{err:t}=i;return this._snapshot={...this._snapshot,status:"error",error:t},void this._error(t)}this.update(s,t),t.type===e&&(this._stopProcedure(),this._complete())}_stop(){return this._processingStatus===u.Stopped?this:(this.mailbox.clear(),this._processingStatus===u.NotStarted?(this._processingStatus=u.Stopped,this):(this.mailbox.enqueue({type:e}),this))}stop(){if(this._parent)throw new Error("A non-root actor cannot be stopped directly.");return this._stop()}_complete(){for(const t of this.observers)try{t.complete?.()}catch(t){r(t)}this.observers.clear()}_reportError(t){if(!this.observers.size)return void(this._parent||r(t));let s=!1;for(const e of this.observers){const i=e.error;s||=!i;try{i?.(t)}catch(t){r(t)}}this.observers.clear(),s&&r(t)}_error(t){var s;this._stopProcedure(),this._reportError(t),this._parent&&this.system._relay(this,this._parent,{type:`xstate.error.actor.${s=this.id}`,error:t,actorId:s})}_stopProcedure(){return this._processingStatus!==u.Running||(this.system.scheduler.cancelAll(this),this.mailbox.clear(),this.mailbox=new s(this._process.bind(this)),this._processingStatus=u.Stopped,this.system._unregister(this)),this}_send(t){this._processingStatus!==u.Stopped&&this.mailbox.enqueue(t)}send(t){this.system._relay(void 0,this,t)}attachDevTools(){const{devTools:t}=this.options;if(t){("function"==typeof t?t:o)(this)}}toJSON(){return{xstate$$type:1,id:this.id}}getPersistedSnapshot(t){return this.logic.getPersistedSnapshot(this._snapshot,t)}[n](){return this}getSnapshot(){return this._snapshot}}function _(t,s){return{config:t,transition:(s,e,i)=>({...s,context:t(s.context,e,i)}),getInitialSnapshot:(t,e)=>({status:"active",output:void 0,error:void 0,context:"function"==typeof s?s({input:e}):s}),getPersistedSnapshot:t=>t,restoreSnapshot:t=>t}}const v=new WeakMap;const f="xstate.observable.next",y="xstate.observable.error",g="xstate.observable.complete";const b="xstate.promise.resolve",m="xstate.promise.reject",S=new WeakMap;const x=_((t=>{}),void 0);t.createEmptyActor=function(){return function(t,...[s]){return new l(t,s)}(x)},t.fromCallback=function(t){return{config:t,start:(s,e)=>{const{self:i,system:o,emit:r}=e,n={receivers:void 0,dispose:void 0};v.set(i,n),n.dispose=t({input:s.input,system:o,self:i,sendBack:t=>{"stopped"!==i.getSnapshot().status&&i._parent&&o._relay(i,i._parent,t)},receive:t=>{n.receivers??=new Set,n.receivers.add(t)},emit:r})},transition:(t,s,i)=>{const o=v.get(i.self);return s.type===e?(t={...t,status:"stopped",error:void 0},o.dispose?.(),t):(o.receivers?.forEach((t=>t(s))),t)},getInitialSnapshot:(t,s)=>({status:"active",output:void 0,error:void 0,input:s}),getPersistedSnapshot:t=>t,restoreSnapshot:t=>t}},t.fromEventObservable=function(t){return{config:t,transition:(t,s)=>{if("active"!==t.status)return t;switch(s.type){case y:return{...t,status:"error",error:s.data,input:void 0,_subscription:void 0};case g:return{...t,status:"done",input:void 0,_subscription:void 0};case e:return t._subscription.unsubscribe(),{...t,status:"stopped",input:void 0,_subscription:void 0};default:return t}},getInitialSnapshot:(t,s)=>({status:"active",output:void 0,error:void 0,context:void 0,input:s,_subscription:void 0}),start:(s,{self:e,system:i,emit:o})=>{"done"!==s.status&&(s._subscription=t({input:s.input,system:i,self:e,emit:o}).subscribe({next:t=>{e._parent&&i._relay(e,e._parent,t)},error:t=>{i._relay(e,e,{type:y,data:t})},complete:()=>{i._relay(e,e,{type:g})}}))},getPersistedSnapshot:({_subscription:t,...s})=>s,restoreSnapshot:t=>({...t,_subscription:void 0})}},t.fromObservable=function(t){return{config:t,transition:(t,s)=>{if("active"!==t.status)return t;switch(s.type){case f:return{...t,context:s.data};case y:return{...t,status:"error",error:s.data,input:void 0,_subscription:void 0};case g:return{...t,status:"done",input:void 0,_subscription:void 0};case e:return t._subscription.unsubscribe(),{...t,status:"stopped",input:void 0,_subscription:void 0};default:return t}},getInitialSnapshot:(t,s)=>({status:"active",output:void 0,error:void 0,context:void 0,input:s,_subscription:void 0}),start:(s,{self:e,system:i,emit:o})=>{"done"!==s.status&&(s._subscription=t({input:s.input,system:i,self:e,emit:o}).subscribe({next:t=>{i._relay(e,e,{type:f,data:t})},error:t=>{i._relay(e,e,{type:y,data:t})},complete:()=>{i._relay(e,e,{type:g})}}))},getPersistedSnapshot:({_subscription:t,...s})=>s,restoreSnapshot:t=>({...t,_subscription:void 0})}},t.fromPromise=function(t){return{config:t,transition:(t,s,i)=>{if("active"!==t.status)return t;switch(s.type){case b:{const e=s.data;return{...t,status:"done",output:e,input:void 0}}case m:return{...t,status:"error",error:s.data,input:void 0};case e:return S.get(i.self)?.abort(),{...t,status:"stopped",input:void 0};default:return t}},start:(s,{self:e,system:i,emit:o})=>{if("active"!==s.status)return;const r=new AbortController;S.set(e,r);Promise.resolve(t({input:s.input,system:i,self:e,signal:r.signal,emit:o})).then((t=>{"active"===e.getSnapshot().status&&(S.delete(e),i._relay(e,e,{type:b,data:t}))}),(t=>{"active"===e.getSnapshot().status&&(S.delete(e),i._relay(e,e,{type:m,data:t}))}))},getInitialSnapshot:(t,s)=>({status:"active",output:void 0,error:void 0,input:s}),getPersistedSnapshot:t=>t,restoreSnapshot:t=>t}},t.fromTransition=_,Object.defineProperty(t,"__esModule",{value:!0})}));
//# sourceMappingURL=xstate-actors.umd.min.js.map