State.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var _tslib = require('./_virtual/_tslib.js');
  4. var constants = require('./constants.js');
  5. var utils = require('./utils.js');
  6. var stateUtils = require('./stateUtils.js');
  7. var actions = require('./actions.js');
  8. var environment = require('./environment.js');
  9. function stateValuesEqual(a, b) {
  10. if (a === b) {
  11. return true;
  12. }
  13. if (a === undefined || b === undefined) {
  14. return false;
  15. }
  16. if (utils.isString(a) || utils.isString(b)) {
  17. return a === b;
  18. }
  19. var aKeys = Object.keys(a);
  20. var bKeys = Object.keys(b);
  21. return aKeys.length === bKeys.length && aKeys.every(function (key) {
  22. return stateValuesEqual(a[key], b[key]);
  23. });
  24. }
  25. function isStateConfig(state) {
  26. if (typeof state !== 'object' || state === null) {
  27. return false;
  28. }
  29. return 'value' in state && '_event' in state;
  30. }
  31. /**
  32. * @deprecated Use `isStateConfig(object)` or `state instanceof State` instead.
  33. */
  34. var isState = isStateConfig;
  35. function bindActionToState(action, state) {
  36. var exec = action.exec;
  37. var boundAction = _tslib.__assign(_tslib.__assign({}, action), {
  38. exec: exec !== undefined ? function () {
  39. return exec(state.context, state.event, {
  40. action: action,
  41. state: state,
  42. _event: state._event
  43. });
  44. } : undefined
  45. });
  46. return boundAction;
  47. }
  48. var State =
  49. /*#__PURE__*/
  50. /** @class */
  51. function () {
  52. /**
  53. * Creates a new State instance.
  54. * @param value The state value
  55. * @param context The extended state
  56. * @param historyValue The tree representing historical values of the state nodes
  57. * @param history The previous state
  58. * @param actions An array of action objects to execute as side-effects
  59. * @param activities A mapping of activities and whether they are started (`true`) or stopped (`false`).
  60. * @param meta
  61. * @param events Internal event queue. Should be empty with run-to-completion semantics.
  62. * @param configuration
  63. */
  64. function State(config) {
  65. var _this = this;
  66. var _a;
  67. this.actions = [];
  68. this.activities = constants.EMPTY_ACTIVITY_MAP;
  69. this.meta = {};
  70. this.events = [];
  71. this.value = config.value;
  72. this.context = config.context;
  73. this._event = config._event;
  74. this._sessionid = config._sessionid;
  75. this.event = this._event.data;
  76. this.historyValue = config.historyValue;
  77. this.history = config.history;
  78. this.actions = config.actions || [];
  79. this.activities = config.activities || constants.EMPTY_ACTIVITY_MAP;
  80. this.meta = stateUtils.getMeta(config.configuration);
  81. this.events = config.events || [];
  82. this.matches = this.matches.bind(this);
  83. this.toStrings = this.toStrings.bind(this);
  84. this.configuration = config.configuration;
  85. this.transitions = config.transitions;
  86. this.children = config.children;
  87. this.done = !!config.done;
  88. this.tags = (_a = Array.isArray(config.tags) ? new Set(config.tags) : config.tags) !== null && _a !== void 0 ? _a : new Set();
  89. this.machine = config.machine;
  90. Object.defineProperty(this, 'nextEvents', {
  91. get: function () {
  92. return stateUtils.nextEvents(_this.configuration);
  93. }
  94. });
  95. }
  96. /**
  97. * Creates a new State instance for the given `stateValue` and `context`.
  98. * @param stateValue
  99. * @param context
  100. */
  101. State.from = function (stateValue, context) {
  102. if (stateValue instanceof State) {
  103. if (stateValue.context !== context) {
  104. return new State({
  105. value: stateValue.value,
  106. context: context,
  107. _event: stateValue._event,
  108. _sessionid: null,
  109. historyValue: stateValue.historyValue,
  110. history: stateValue.history,
  111. actions: [],
  112. activities: stateValue.activities,
  113. meta: {},
  114. events: [],
  115. configuration: [],
  116. transitions: [],
  117. children: {}
  118. });
  119. }
  120. return stateValue;
  121. }
  122. var _event = actions.initEvent;
  123. return new State({
  124. value: stateValue,
  125. context: context,
  126. _event: _event,
  127. _sessionid: null,
  128. historyValue: undefined,
  129. history: undefined,
  130. actions: [],
  131. activities: undefined,
  132. meta: undefined,
  133. events: [],
  134. configuration: [],
  135. transitions: [],
  136. children: {}
  137. });
  138. };
  139. /**
  140. * Creates a new State instance for the given `config`.
  141. * @param config The state config
  142. */
  143. State.create = function (config) {
  144. return new State(config);
  145. };
  146. /**
  147. * Creates a new `State` instance for the given `stateValue` and `context` with no actions (side-effects).
  148. * @param stateValue
  149. * @param context
  150. */
  151. State.inert = function (stateValue, context) {
  152. if (stateValue instanceof State) {
  153. if (!stateValue.actions.length) {
  154. return stateValue;
  155. }
  156. var _event = actions.initEvent;
  157. return new State({
  158. value: stateValue.value,
  159. context: context,
  160. _event: _event,
  161. _sessionid: null,
  162. historyValue: stateValue.historyValue,
  163. history: stateValue.history,
  164. activities: stateValue.activities,
  165. configuration: stateValue.configuration,
  166. transitions: [],
  167. children: {}
  168. });
  169. }
  170. return State.from(stateValue, context);
  171. };
  172. /**
  173. * Returns an array of all the string leaf state node paths.
  174. * @param stateValue
  175. * @param delimiter The character(s) that separate each subpath in the string state node path.
  176. */
  177. State.prototype.toStrings = function (stateValue, delimiter) {
  178. var _this = this;
  179. if (stateValue === void 0) {
  180. stateValue = this.value;
  181. }
  182. if (delimiter === void 0) {
  183. delimiter = '.';
  184. }
  185. if (utils.isString(stateValue)) {
  186. return [stateValue];
  187. }
  188. var valueKeys = Object.keys(stateValue);
  189. return valueKeys.concat.apply(valueKeys, _tslib.__spreadArray([], _tslib.__read(valueKeys.map(function (key) {
  190. return _this.toStrings(stateValue[key], delimiter).map(function (s) {
  191. return key + delimiter + s;
  192. });
  193. })), false));
  194. };
  195. State.prototype.toJSON = function () {
  196. var _a = this;
  197. _a.configuration;
  198. _a.transitions;
  199. var tags = _a.tags;
  200. _a.machine;
  201. var jsonValues = _tslib.__rest(_a, ["configuration", "transitions", "tags", "machine"]);
  202. return _tslib.__assign(_tslib.__assign({}, jsonValues), {
  203. tags: Array.from(tags)
  204. });
  205. };
  206. State.prototype.matches = function (parentStateValue) {
  207. return utils.matchesState(parentStateValue, this.value);
  208. };
  209. /**
  210. * Whether the current state configuration has a state node with the specified `tag`.
  211. * @param tag
  212. */
  213. State.prototype.hasTag = function (tag) {
  214. return this.tags.has(tag);
  215. };
  216. /**
  217. * Determines whether sending the `event` will cause a non-forbidden transition
  218. * to be selected, even if the transitions have no actions nor
  219. * change the state value.
  220. *
  221. * @param event The event to test
  222. * @returns Whether the event will cause a transition
  223. */
  224. State.prototype.can = function (event) {
  225. var _a;
  226. if (environment.IS_PRODUCTION) {
  227. utils.warn(!!this.machine, "state.can(...) used outside of a machine-created State object; this will always return false.");
  228. }
  229. var transitionData = (_a = this.machine) === null || _a === void 0 ? void 0 : _a.getTransitionData(this, event);
  230. return !!(transitionData === null || transitionData === void 0 ? void 0 : transitionData.transitions.length) && // Check that at least one transition is not forbidden
  231. transitionData.transitions.some(function (t) {
  232. return t.target !== undefined || t.actions.length;
  233. });
  234. };
  235. return State;
  236. }();
  237. exports.State = State;
  238. exports.bindActionToState = bindActionToState;
  239. exports.isState = isState;
  240. exports.isStateConfig = isStateConfig;
  241. exports.stateValuesEqual = stateValuesEqual;