jssm 5.162.5 → 5.162.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,10 +18,10 @@ Please edit the file it's derived from, instead: `./src/md/readme_base.md`
18
18
 
19
19
 
20
20
 
21
- * Generated for version 5.162.5 at 7/10/2026, 7:49:54 AM
21
+ * Generated for version 5.162.6 at 7/10/2026, 9:42:29 AM
22
22
 
23
23
  -->
24
- # jssm 5.162.5
24
+ # jssm 5.162.6
25
25
 
26
26
  [**Try the live editor**](https://stonecypher.github.io/jssm-viz-demo/graph_explorer.html) ·
27
27
  [Documentation](https://stonecypher.github.io/jssm/docs/) ·
@@ -333,7 +333,7 @@ That decision shows up everywhere downstream:
333
333
  or run `npm run benny` against your own machine.
334
334
 
335
335
  - **More thoroughly tested than any other JavaScript state-machine
336
- library.** 8,033 tests at 100.0% line coverage
336
+ library.** 8,071 tests at 100.0% line coverage
337
337
  ([report](https://coveralls.io/github/StoneCypher/jssm)), plus
338
338
  fuzz testing via `fast-check`, with parser test data across ten natural
339
339
  languages and Emoji.
@@ -466,11 +466,11 @@ If your contribution is missing here, please open an issue.
466
466
 
467
467
  <br/>
468
468
 
469
- ***8,033 tests***, run 83,174 times.
469
+ ***8,071 tests***, run 83,509 times.
470
470
 
471
- - 7,274 specs with 100.0% coverage
472
- - 759 fuzz tests with 48.0% coverage
473
- - 10,711 TypeScript lines - 0.7 tests per line, 7.8 generated tests per line
471
+ - 7,309 specs with 100.0% coverage
472
+ - 762 fuzz tests with 48.1% coverage
473
+ - 10,748 TypeScript lines - 0.8 tests per line, 7.8 generated tests per line
474
474
 
475
475
  [![Actions Status](https://github.com/StoneCypher/jssm/workflows/Node%20CI/badge.svg)](https://github.com/StoneCypher/jssm/actions)
476
476
  [![NPM version](https://img.shields.io/npm/v/jssm.svg)](https://www.npmjs.com/package/jssm)
@@ -148,6 +148,7 @@ declare class Machine<mDT> {
148
148
  _entry_hooks: Map<number, HookHandler<mDT>>;
149
149
  _exit_hooks: Map<number, HookHandler<mDT>>;
150
150
  _after_hooks: Map<string, HookHandler<mDT>>;
151
+ _after_any_hook: HookHandler<mDT> | undefined;
151
152
  _global_action_hooks: Map<number, HookHandler<mDT>>;
152
153
  _any_action_hook: HookHandler<mDT> | undefined;
153
154
  _standard_transition_hook: HookHandler<mDT> | undefined;
@@ -309,6 +310,40 @@ declare class Machine<mDT> {
309
310
  *
310
311
  */
311
312
  data(): mDT;
313
+ /*********
314
+ *
315
+ * Replace the machine's data in place, without a transition. This is the
316
+ * practical way to assign any value — including `undefined`, `null`, or
317
+ * `false` — outside a hook's complex return, closing the gap where an
318
+ * `undefined` assignment had no direct API (StoneCypher/fsl#1264). Fires
319
+ * a `data-change` event with cause `'set_data'` when the value actually
320
+ * changes; unlike {@link override} it requires no `allows_override`
321
+ * config, because it never moves the state.
322
+ *
323
+ * ```typescript
324
+ * import * as jssm from 'jssm';
325
+ *
326
+ * const lswitch = jssm.from('on <=> off;', {data: 1});
327
+ * console.log( lswitch.data() ); // 1
328
+ *
329
+ * lswitch.set_data(2);
330
+ * console.log( lswitch.data() ); // 2
331
+ *
332
+ * lswitch.set_data(undefined);
333
+ * console.log( lswitch.data() ); // undefined
334
+ * ```
335
+ *
336
+ * @typeParam mDT The type of the machine data member; usually omitted
337
+ *
338
+ * @param newData The value to install as the machine's data.
339
+ *
340
+ * @returns The machine, for chaining.
341
+ *
342
+ * @see Machine.data
343
+ * @see override
344
+ *
345
+ */
346
+ set_data(newData: mDT): Machine<mDT>;
312
347
  /**
313
348
  * The machine's current data by REFERENCE — no clone. The public
314
349
  * {@link Machine.data} contract is a deep clone per call (a mutation
@@ -1624,6 +1659,33 @@ declare class Machine<mDT> {
1624
1659
  * @see set_state_timeout
1625
1660
  */
1626
1661
  hook_after(from: string, handler: HookHandler<mDT>): Machine<mDT>;
1662
+ /** Register a hook that fires when ANY state's `after` timer elapses — the
1663
+ * whole-machine companion to {@link hook_after}, mirroring how
1664
+ * {@link hook_any_transition} companions {@link hook}. When the elapsing
1665
+ * state also has a specific {@link hook_after}, the specific hook fires
1666
+ * first and this one fires second; a specific after hook firing always
1667
+ * implies the any-after hook fires too (StoneCypher/fsl#1299). Like
1668
+ * `hook_after` it is informational — its outcome cannot reject the timed
1669
+ * transition — and it does NOT fire on ordinary dispatch.
1670
+ * @param handler - Callback invoked whenever any `after` timer fires, just
1671
+ * before the timed transition is taken.
1672
+ * @returns `this` for chaining.
1673
+ *
1674
+ * @example
1675
+ * const m = sm`a after 1000 -> b; a -> c; c -> a;`;
1676
+ * let calls = 0;
1677
+ * m.hook_after_any(() => { calls += 1; });
1678
+ * m.go('c');
1679
+ * m.go('a');
1680
+ * // ordinary dispatch never fires it; only a timer elapsing does:
1681
+ * calls; // => 0
1682
+ * m.clear_state_timeout();
1683
+ *
1684
+ * @see hook_after
1685
+ * @see hook_any_transition
1686
+ * @see set_state_timeout
1687
+ */
1688
+ hook_after_any(handler: HookHandler<mDT>): Machine<mDT>;
1627
1689
  /** Post-transition hook on a specific edge. Fires after the transition
1628
1690
  * from `from` to `to` has completed. Cannot block the transition.
1629
1691
  * @param from - Source state name.
@@ -1768,7 +1830,13 @@ declare class Machine<mDT> {
1768
1830
  edges_between(from: string, to: string): JssmTransition<StateType, mDT>[];
1769
1831
  /*********
1770
1832
  *
1771
- * Replace the current state and data with no regard to the graph.
1833
+ * Replace the current state and, when a data argument is provided, the
1834
+ * data — with no regard to the graph.
1835
+ *
1836
+ * The data argument is arity-detected: omitting it preserves the current
1837
+ * data, while explicitly passing `undefined` really sets the data to
1838
+ * `undefined` (StoneCypher/fsl#1264). Before 5.163 an omitted data
1839
+ * argument silently cleared the data.
1772
1840
  *
1773
1841
  * ```typescript
1774
1842
  * import { sm } from 'jssm';
@@ -1784,6 +1852,16 @@ declare class Machine<mDT> {
1784
1852
  * console.log( machine.state() ); // 'a'
1785
1853
  * ```
1786
1854
  *
1855
+ * @param newState The state to teleport to; must exist in the graph.
1856
+ *
1857
+ * @param newData Replacement data. Omit to keep the current data; pass
1858
+ * `undefined` explicitly to clear it.
1859
+ *
1860
+ * @throws {JssmError} If the machine's config does not set
1861
+ * `allows_override: true`, or if `newState` does not exist.
1862
+ *
1863
+ * @see set_data
1864
+ *
1787
1865
  */
1788
1866
  override(newState: StateType, newData?: mDT | undefined): void;
1789
1867
  /*********
@@ -1898,13 +1976,20 @@ declare class Machine<mDT> {
1898
1976
  * `newStateOrAction` is an action name and the target state is looked up
1899
1977
  * via the current action edge.
1900
1978
  *
1979
+ * @param dataProvided `true` when the caller explicitly supplied a data
1980
+ * argument — even an explicitly-`undefined` one, which commits `undefined`
1981
+ * as the new data (StoneCypher/fsl#1264). When `false` the current data
1982
+ * is preserved. The public wrappers derive this from call arity; the
1983
+ * default reproduces the old `!== undefined` inference for any direct
1984
+ * callers.
1985
+ *
1901
1986
  * @returns `true` if the transition was valid and every hook passed;
1902
1987
  * `false` if the transition was invalid or any hook rejected.
1903
1988
  *
1904
1989
  * @internal
1905
1990
  *
1906
1991
  */
1907
- transition_impl(newStateOrAction: StateType, newData: mDT | undefined, wasForced: boolean, wasAction: boolean): boolean;
1992
+ transition_impl(newStateOrAction: StateType, newData: mDT | undefined, wasForced: boolean, wasAction: boolean, dataProvided?: boolean): boolean;
1908
1993
  /** If the current state has an `after` timeout configured, schedule it.
1909
1994
  * Called internally after each transition.
1910
1995
  */