jssm 5.132.0 → 5.133.0

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.
package/README.md CHANGED
@@ -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.132.0 at 5/27/2026, 8:28:16 PM
21
+ * Generated for version 5.133.0 at 5/27/2026, 9:02:28 PM
22
22
 
23
23
  -->
24
- # jssm 5.132.0
24
+ # jssm 5.133.0
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/) ·
@@ -281,7 +281,7 @@ That decision shows up everywhere downstream:
281
281
  or run `npm run benny` against your own machine.
282
282
 
283
283
  - **More thoroughly tested than any other JavaScript state-machine
284
- library.** 6,155 tests at 100.0% line coverage
284
+ library.** 6,157 tests at 100.0% line coverage
285
285
  ([report](https://coveralls.io/github/StoneCypher/jssm)), plus
286
286
  fuzz testing via `fast-check`, with parser test data across ten natural
287
287
  languages and Emoji.
@@ -414,11 +414,11 @@ If your contribution is missing here, please open an issue.
414
414
 
415
415
  <br/>
416
416
 
417
- ***6,155 tests***, run 56,942 times.
417
+ ***6,157 tests***, run 56,944 times.
418
418
 
419
- - 5,642 specs with 100.0% coverage
420
- - 513 fuzz tests with 4.4% coverage
421
- - 4,380 TypeScript lines - 1.4 tests per line, 13.0 generated tests per line
419
+ - 5,644 specs with 100.0% coverage
420
+ - 513 fuzz tests with 4.3% coverage
421
+ - 4,415 TypeScript lines - 1.4 tests per line, 12.9 generated tests per line
422
422
 
423
423
  [![Actions Status](https://github.com/StoneCypher/jssm/workflows/Node%20CI/badge.svg)](https://github.com/StoneCypher/jssm/actions)
424
424
  [![NPM version](https://img.shields.io/npm/v/jssm.svg)](https://www.npmjs.com/package/jssm)
package/dist/cdn/viz.js CHANGED
@@ -19585,41 +19585,6 @@ function name_bind_prop_and_state(prop, state) {
19585
19585
  }
19586
19586
  return JSON.stringify([prop, state]);
19587
19587
  }
19588
- /*******
19589
- *
19590
- * Internal method generating composite keys for transition hooks by
19591
- * JSON-serializing a `[from, to]` state pair. Used to look up hooks
19592
- * registered on a specific edge. Not meant for external use.
19593
- *
19594
- * ```typescript
19595
- * hook_name('Red', 'Green'); // '["Red","Green"]'
19596
- * ```
19597
- *
19598
- * @param from - The source state name.
19599
- * @param to - The target state name.
19600
- *
19601
- * @returns A deterministic JSON string key for the `[from, to]` pair.
19602
- *
19603
- */
19604
- const hook_name = (from, to) => JSON.stringify([from, to]);
19605
- /*******
19606
- *
19607
- * Internal method generating composite keys for named-action hooks by
19608
- * JSON-serializing a `[from, to, action]` triple. Used to look up hooks
19609
- * registered on a specific action-labeled edge. Not meant for external use.
19610
- *
19611
- * ```typescript
19612
- * named_hook_name('Red', 'Green', 'next'); // '["Red","Green","next"]'
19613
- * ```
19614
- *
19615
- * @param from - The source state name.
19616
- * @param to - The target state name.
19617
- * @param action - The action label on the edge.
19618
- *
19619
- * @returns A deterministic JSON string key for the `[from, to, action]` triple.
19620
- *
19621
- */
19622
- const named_hook_name = (from, to, action) => JSON.stringify([from, to, action]);
19623
19588
  /*******
19624
19589
  *
19625
19590
  * Creates a SplitMix32 random generator. Used by the randomness test suite.
@@ -21387,7 +21352,7 @@ var constants = /*#__PURE__*/Object.freeze({
21387
21352
  * Useful for runtime diagnostics and for embedding in serialized machine
21388
21353
  * snapshots so that deserializers can detect version-skew.
21389
21354
  */
21390
- const version = "5.132.0";
21355
+ const version = "5.133.0";
21391
21356
 
21392
21357
  // whargarbl lots of these return arrays could/should be sets
21393
21358
  const { state_name_chars, state_name_first_chars, action_label_chars } = constants;
@@ -23014,16 +22979,35 @@ class Machine {
23014
22979
  */
23015
22980
  set_hook(HookDesc) {
23016
22981
  switch (HookDesc.kind) {
23017
- case 'hook':
23018
- this._hooks.set(hook_name(HookDesc.from, HookDesc.to), HookDesc.handler);
22982
+ case 'hook': {
22983
+ // Nested by `from` then `to`; avoids JSON.stringify on every transition (#642).
22984
+ let inner = this._hooks.get(HookDesc.from);
22985
+ if (inner === undefined) {
22986
+ inner = new Map();
22987
+ this._hooks.set(HookDesc.from, inner);
22988
+ }
22989
+ inner.set(HookDesc.to, HookDesc.handler);
23019
22990
  this._has_hooks = true;
23020
22991
  this._has_basic_hooks = true;
23021
22992
  break;
23022
- case 'named':
23023
- this._named_hooks.set(named_hook_name(HookDesc.from, HookDesc.to, HookDesc.action), HookDesc.handler);
22993
+ }
22994
+ case 'named': {
22995
+ // Nested by `from` then `to` then `action`; same rationale as 'hook' (#642).
22996
+ let inner = this._named_hooks.get(HookDesc.from);
22997
+ if (inner === undefined) {
22998
+ inner = new Map();
22999
+ this._named_hooks.set(HookDesc.from, inner);
23000
+ }
23001
+ let inner2 = inner.get(HookDesc.to);
23002
+ if (inner2 === undefined) {
23003
+ inner2 = new Map();
23004
+ inner.set(HookDesc.to, inner2);
23005
+ }
23006
+ inner2.set(HookDesc.action, HookDesc.handler);
23024
23007
  this._has_hooks = true;
23025
23008
  this._has_named_hooks = true;
23026
23009
  break;
23010
+ }
23027
23011
  case 'global action':
23028
23012
  this._global_action_hooks.set(HookDesc.action, HookDesc.handler);
23029
23013
  this._has_hooks = true;
@@ -23067,16 +23051,35 @@ class Machine {
23067
23051
  this._has_hooks = true;
23068
23052
  this._has_after_hooks = true;
23069
23053
  break;
23070
- case 'post hook':
23071
- this._post_hooks.set(hook_name(HookDesc.from, HookDesc.to), HookDesc.handler);
23054
+ case 'post hook': {
23055
+ // Nested by `from` then `to`; same rationale as 'hook' (#642).
23056
+ let inner = this._post_hooks.get(HookDesc.from);
23057
+ if (inner === undefined) {
23058
+ inner = new Map();
23059
+ this._post_hooks.set(HookDesc.from, inner);
23060
+ }
23061
+ inner.set(HookDesc.to, HookDesc.handler);
23072
23062
  this._has_post_hooks = true;
23073
23063
  this._has_post_basic_hooks = true;
23074
23064
  break;
23075
- case 'post named':
23076
- this._post_named_hooks.set(named_hook_name(HookDesc.from, HookDesc.to, HookDesc.action), HookDesc.handler);
23065
+ }
23066
+ case 'post named': {
23067
+ // Nested by `from` then `to` then `action`; same rationale as 'hook' (#642).
23068
+ let inner = this._post_named_hooks.get(HookDesc.from);
23069
+ if (inner === undefined) {
23070
+ inner = new Map();
23071
+ this._post_named_hooks.set(HookDesc.from, inner);
23072
+ }
23073
+ let inner2 = inner.get(HookDesc.to);
23074
+ if (inner2 === undefined) {
23075
+ inner2 = new Map();
23076
+ inner.set(HookDesc.to, inner2);
23077
+ }
23078
+ inner2.set(HookDesc.action, HookDesc.handler);
23077
23079
  this._has_post_hooks = true;
23078
23080
  this._has_post_named_hooks = true;
23079
23081
  break;
23082
+ }
23080
23083
  case 'post global action':
23081
23084
  this._post_global_action_hooks.set(HookDesc.action, HookDesc.handler);
23082
23085
  this._has_post_hooks = true;
@@ -23625,7 +23628,12 @@ class Machine {
23625
23628
  // 5. named transition / action hook
23626
23629
  if (this._has_named_hooks) {
23627
23630
  if (wasAction) {
23628
- const nhn = named_hook_name(this._state, newState, newStateOrAction), outcome = abstract_hook_step(this._named_hooks.get(nhn), hook_args);
23631
+ // Nested lookup: from -> to -> action. Each step is a small Map keyed by
23632
+ // an already-interned state/action name; no per-call string allocation.
23633
+ const byTo = this._named_hooks.get(this._state);
23634
+ const byAct = byTo === undefined ? undefined : byTo.get(newState);
23635
+ const nh = byAct === undefined ? undefined : byAct.get(newStateOrAction);
23636
+ const outcome = abstract_hook_step(nh, hook_args);
23629
23637
  if (outcome.pass === false) {
23630
23638
  return false;
23631
23639
  }
@@ -23634,7 +23642,10 @@ class Machine {
23634
23642
  }
23635
23643
  // 6. regular hook
23636
23644
  if (this._has_basic_hooks) {
23637
- const hn = hook_name(this._state, newState), outcome = abstract_hook_step(this._hooks.get(hn), hook_args);
23645
+ // Nested lookup: from -> to. See note on _hooks declaration (#642).
23646
+ const byTo = this._hooks.get(this._state);
23647
+ const h = byTo === undefined ? undefined : byTo.get(newState);
23648
+ const outcome = abstract_hook_step(h, hook_args);
23638
23649
  if (outcome.pass === false) {
23639
23650
  return false;
23640
23651
  }
@@ -23745,7 +23756,10 @@ class Machine {
23745
23756
  // 5. named transition / action hook
23746
23757
  if (this._has_post_named_hooks) {
23747
23758
  if (wasAction) {
23748
- const nhn = named_hook_name(hook_args.from, hook_args.to, hook_args.action), pnh = this._post_named_hooks.get(nhn);
23759
+ // Nested lookup: from -> to -> action. See note on _post_named_hooks (#642).
23760
+ const byTo = this._post_named_hooks.get(hook_args.from);
23761
+ const byAct = byTo === undefined ? undefined : byTo.get(hook_args.to);
23762
+ const pnh = byAct === undefined ? undefined : byAct.get(hook_args.action);
23749
23763
  if (pnh !== undefined) {
23750
23764
  pnh(hook_args);
23751
23765
  }
@@ -23753,7 +23767,9 @@ class Machine {
23753
23767
  }
23754
23768
  // 6. regular hook
23755
23769
  if (this._has_post_basic_hooks) {
23756
- const hook = this._post_hooks.get(hook_name(hook_args.from, hook_args.to));
23770
+ // Nested lookup: from -> to. See note on _post_hooks (#642).
23771
+ const byTo = this._post_hooks.get(hook_args.from);
23772
+ const hook = byTo === undefined ? undefined : byTo.get(hook_args.to);
23757
23773
  if (hook !== undefined) {
23758
23774
  hook(hook_args);
23759
23775
  }