jssm 5.130.0 → 5.131.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.130.0 at 5/27/2026, 12:05:25 PM
21
+ * Generated for version 5.131.0 at 5/27/2026, 3:21:52 PM
22
22
 
23
23
  -->
24
- # jssm 5.130.0
24
+ # jssm 5.131.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,151 tests at 100.0% line coverage
284
+ library.** 6,155 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,151 tests***, run 56,938 times.
417
+ ***6,155 tests***, run 56,942 times.
418
418
 
419
- - 5,638 specs with 100.0% coverage
419
+ - 5,642 specs with 100.0% coverage
420
420
  - 513 fuzz tests with 4.4% coverage
421
- - 4,366 TypeScript lines - 1.4 tests per line, 13.0 generated tests per line
421
+ - 4,380 TypeScript lines - 1.4 tests per line, 13.0 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
@@ -21387,7 +21387,7 @@ var constants = /*#__PURE__*/Object.freeze({
21387
21387
  * Useful for runtime diagnostics and for embedding in serialized machine
21388
21388
  * snapshots so that deserializers can detect version-skew.
21389
21389
  */
21390
- const version = "5.130.0";
21390
+ const version = "5.131.0";
21391
21391
 
21392
21392
  // whargarbl lots of these return arrays could/should be sets
21393
21393
  const { state_name_chars, state_name_first_chars, action_label_chars } = constants;
@@ -21587,6 +21587,7 @@ class Machine {
21587
21587
  this._state_declarations = new Map();
21588
21588
  this._edges = [];
21589
21589
  this._edge_map = new Map();
21590
+ this._outbound_edge_ids = new Map();
21590
21591
  this._named_transitions = new Map();
21591
21592
  this._actions = new Map();
21592
21593
  this._reverse_actions = new Map();
@@ -21752,6 +21753,17 @@ class Machine {
21752
21753
  }
21753
21754
  // const to_mapping = from_mapping.get(tr.to);
21754
21755
  from_mapping.set(tr.to, thisEdgeId); // already checked that this mapping doesn't exist, above
21756
+ // outbound adjacency: every edge originating at tr.from, regardless of action/target.
21757
+ // _edge_map above keys a single edge per (from, to) and overwrites on collision, which
21758
+ // is fine for lookup_transition_for but loses information for edges_between when several
21759
+ // edges share endpoints across distinct actions. This index preserves every edge id and
21760
+ // lets edges_between scan only one state's exits, not all of _edges.
21761
+ let outbound = this._outbound_edge_ids.get(tr.from);
21762
+ if (!outbound) {
21763
+ outbound = [];
21764
+ this._outbound_edge_ids.set(tr.from, outbound);
21765
+ }
21766
+ outbound.push(thisEdgeId);
21755
21767
  // set up the action mapping, so that actions can be looked up by origin
21756
21768
  if (tr.action) {
21757
21769
  // forward mapping first by action name
@@ -23425,7 +23437,21 @@ class Machine {
23425
23437
  * @returns An array of matching {@link JssmTransition} objects.
23426
23438
  */
23427
23439
  edges_between(from, to) {
23428
- return this._edges.filter(edge => ((edge.from === from) && (edge.to === to)));
23440
+ var _a;
23441
+ // Filter only this state's outbound edges instead of the full _edges array.
23442
+ // For machines with E total edges and average out-degree d, this is O(d)
23443
+ // instead of O(E) — a large win on dense graphs where d << E. The `?? []`
23444
+ // covers from-states that have no outgoing edges (terminal states) and
23445
+ // states that don't exist at all, both of which return [] without iterating.
23446
+ const outbound = (_a = this._outbound_edge_ids.get(from)) !== null && _a !== void 0 ? _a : [];
23447
+ const result = [];
23448
+ for (const edgeId of outbound) {
23449
+ const edge = this._edges[edgeId];
23450
+ if (edge.to === to) {
23451
+ result.push(edge);
23452
+ }
23453
+ }
23454
+ return result;
23429
23455
  }
23430
23456
  /*********
23431
23457
  *