jssm 5.144.7 → 5.144.8
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 +7 -7
- package/dist/cdn/instance.js +77 -3
- package/dist/cdn/viz.js +77 -3
- package/dist/cli/fsl-export-system-prompt.cjs +2 -2
- package/dist/cli/fsl-render.cjs +1 -1
- package/dist/cli/fsl.cjs +1 -1
- package/dist/cli/lib.cjs +1 -1
- package/dist/cli/lib.mjs +1 -1
- package/dist/deno/jssm.d.ts +18 -0
- package/dist/deno/jssm.js +1 -1
- package/dist/jssm.es5.cjs +1 -1
- package/dist/jssm.es5.iife.js +1 -1
- package/dist/jssm.es6.mjs +1 -1
- package/dist/jssm_viz.cjs +1 -1
- package/dist/jssm_viz.iife.cjs +1 -1
- package/dist/jssm_viz.mjs +1 -1
- package/jssm.es5.d.cts +18 -0
- package/jssm.es6.d.ts +18 -0
- package/jssm_viz.es5.d.cts +18 -0
- package/jssm_viz.es6.d.ts +18 -0
- package/package.json +1 -1
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.144.
|
|
21
|
+
* Generated for version 5.144.8 at 6/22/2026, 3:15:53 PM
|
|
22
22
|
|
|
23
23
|
-->
|
|
24
|
-
# jssm 5.144.
|
|
24
|
+
# jssm 5.144.8
|
|
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/) ·
|
|
@@ -312,7 +312,7 @@ That decision shows up everywhere downstream:
|
|
|
312
312
|
or run `npm run benny` against your own machine.
|
|
313
313
|
|
|
314
314
|
- **More thoroughly tested than any other JavaScript state-machine
|
|
315
|
-
library.** 7,
|
|
315
|
+
library.** 7,328 tests at 100.0% line coverage
|
|
316
316
|
([report](https://coveralls.io/github/StoneCypher/jssm)), plus
|
|
317
317
|
fuzz testing via `fast-check`, with parser test data across ten natural
|
|
318
318
|
languages and Emoji.
|
|
@@ -445,11 +445,11 @@ If your contribution is missing here, please open an issue.
|
|
|
445
445
|
|
|
446
446
|
<br/>
|
|
447
447
|
|
|
448
|
-
***7,
|
|
448
|
+
***7,328 tests***, run 82,370 times.
|
|
449
449
|
|
|
450
|
-
- 6,
|
|
451
|
-
- 758 fuzz tests with 73.
|
|
452
|
-
- 6,
|
|
450
|
+
- 6,570 specs with 100.0% coverage
|
|
451
|
+
- 758 fuzz tests with 73.9% coverage
|
|
452
|
+
- 6,936 TypeScript lines - 1.1 tests per line, 11.9 generated tests per line
|
|
453
453
|
|
|
454
454
|
[](https://github.com/StoneCypher/jssm/actions)
|
|
455
455
|
[](https://www.npmjs.com/package/jssm)
|
package/dist/cdn/instance.js
CHANGED
|
@@ -23512,11 +23512,48 @@ var constants = /*#__PURE__*/Object.freeze({
|
|
|
23512
23512
|
* Useful for runtime diagnostics and for embedding in serialized machine
|
|
23513
23513
|
* snapshots so that deserializers can detect version-skew.
|
|
23514
23514
|
*/
|
|
23515
|
-
const version = "5.144.
|
|
23515
|
+
const version = "5.144.8";
|
|
23516
23516
|
|
|
23517
23517
|
// whargarbl lots of these return arrays could/should be sets
|
|
23518
23518
|
const { state_name_chars, state_name_first_chars, action_label_chars } = constants;
|
|
23519
23519
|
const empty_string_set = new Set();
|
|
23520
|
+
// The spatial fields (besides `handler`, which every hook needs) that each
|
|
23521
|
+
// hook kind requires, mirroring exactly what `set_hook` reads per case. Used
|
|
23522
|
+
// to validate a HookDescription so a mis-shaped one is rejected rather than
|
|
23523
|
+
// silently registering a dead hook — e.g. an `exit` hook given `to` instead of
|
|
23524
|
+
// `from` would otherwise intern `undefined` and never fire (#734). Typed as a
|
|
23525
|
+
// `Record` over the kind union so the table is exhaustive at compile time:
|
|
23526
|
+
// adding a hook kind without listing its fields is a build error.
|
|
23527
|
+
const hook_required_fields = {
|
|
23528
|
+
'hook': ['from', 'to'],
|
|
23529
|
+
'named': ['from', 'to', 'action'],
|
|
23530
|
+
'global action': ['action'],
|
|
23531
|
+
'any action': [],
|
|
23532
|
+
'standard transition': [],
|
|
23533
|
+
'main transition': [],
|
|
23534
|
+
'forced transition': [],
|
|
23535
|
+
'any transition': [],
|
|
23536
|
+
'entry': ['to'],
|
|
23537
|
+
'exit': ['from'],
|
|
23538
|
+
'after': ['from'],
|
|
23539
|
+
'post hook': ['from', 'to'],
|
|
23540
|
+
'post named': ['from', 'to', 'action'],
|
|
23541
|
+
'post global action': ['action'],
|
|
23542
|
+
'post any action': [],
|
|
23543
|
+
'post standard transition': [],
|
|
23544
|
+
'post main transition': [],
|
|
23545
|
+
'post forced transition': [],
|
|
23546
|
+
'post any transition': [],
|
|
23547
|
+
'post entry': ['to'],
|
|
23548
|
+
'post exit': ['from'],
|
|
23549
|
+
'pre everything': [],
|
|
23550
|
+
'everything': [],
|
|
23551
|
+
'pre post everything': [],
|
|
23552
|
+
'post everything': [],
|
|
23553
|
+
};
|
|
23554
|
+
// The spatial fields a hook descriptor can carry, checked against the per-kind
|
|
23555
|
+
// requirements above.
|
|
23556
|
+
const hook_spatial_fields = ['from', 'to', 'action'];
|
|
23520
23557
|
/*********
|
|
23521
23558
|
*
|
|
23522
23559
|
* An internal method meant to take a series of declarations and fold them into
|
|
@@ -25774,7 +25811,44 @@ class Machine {
|
|
|
25774
25811
|
* calling this directly.
|
|
25775
25812
|
* @param HookDesc - A hook descriptor specifying kind, states, and handler.
|
|
25776
25813
|
*/
|
|
25814
|
+
/**
|
|
25815
|
+
* Validate a {@link HookDescription} before registration. Every hook needs
|
|
25816
|
+
* a `handler` function, and each kind's identifying spatial fields
|
|
25817
|
+
* (`from`/`to`/`action`) must be exactly those `set_hook` reads for that
|
|
25818
|
+
* kind — present when required, absent otherwise. This turns a mis-shaped
|
|
25819
|
+
* descriptor into a thrown error instead of a silently dead hook keyed on
|
|
25820
|
+
* `undefined` (e.g. an `exit` hook handed `to` instead of `from`, #734).
|
|
25821
|
+
*
|
|
25822
|
+
* @param HookDesc - The descriptor about to be registered.
|
|
25823
|
+
* @throws JssmError if the kind is unknown, the handler is not a function, a
|
|
25824
|
+
* required field is missing, or an inapplicable field is present.
|
|
25825
|
+
*
|
|
25826
|
+
* @example
|
|
25827
|
+
* const m = sm`a -> b;`;
|
|
25828
|
+
* // an exit hook is keyed by `from`, so supplying `to` is rejected:
|
|
25829
|
+
* expect(() => m.set_hook({ kind: 'exit', to: 'a', handler: () => true })).toThrow();
|
|
25830
|
+
*/
|
|
25831
|
+
_validate_hook_description(HookDesc) {
|
|
25832
|
+
const required = hook_required_fields[HookDesc.kind];
|
|
25833
|
+
if (required === undefined) {
|
|
25834
|
+
throw new JssmError(this, `unknown hook kind ${JSON.stringify(HookDesc.kind)}`);
|
|
25835
|
+
}
|
|
25836
|
+
if (typeof HookDesc.handler !== 'function') {
|
|
25837
|
+
throw new JssmError(this, `${HookDesc.kind} hook requires a handler function`);
|
|
25838
|
+
}
|
|
25839
|
+
for (const field of hook_spatial_fields) {
|
|
25840
|
+
const needed = required.includes(field);
|
|
25841
|
+
const present = HookDesc[field] !== undefined;
|
|
25842
|
+
if (needed && !present) {
|
|
25843
|
+
throw new JssmError(this, `${HookDesc.kind} hook requires '${field}'`);
|
|
25844
|
+
}
|
|
25845
|
+
if (!needed && present) {
|
|
25846
|
+
throw new JssmError(this, `${HookDesc.kind} hook does not take '${field}'`);
|
|
25847
|
+
}
|
|
25848
|
+
}
|
|
25849
|
+
}
|
|
25777
25850
|
set_hook(HookDesc) {
|
|
25851
|
+
this._validate_hook_description(HookDesc);
|
|
25778
25852
|
switch (HookDesc.kind) {
|
|
25779
25853
|
case 'hook': {
|
|
25780
25854
|
// Numeric pair key (#729). intern() rather than id_of(): a hook may
|
|
@@ -25916,8 +25990,8 @@ class Machine {
|
|
|
25916
25990
|
this._post_everything_hook = HookDesc.handler;
|
|
25917
25991
|
this._has_post_hooks = true;
|
|
25918
25992
|
break;
|
|
25919
|
-
default:
|
|
25920
|
-
|
|
25993
|
+
// No default: `_validate_hook_description` above rejects any unknown kind
|
|
25994
|
+
// before we reach here, so the switch is exhaustive over the known kinds.
|
|
25921
25995
|
}
|
|
25922
25996
|
// The hooked-state styling layer (tier 2.5 of resolve_state_config) depends
|
|
25923
25997
|
// on which states carry hooks, so registering a hook can change the composed
|
package/dist/cdn/viz.js
CHANGED
|
@@ -23537,11 +23537,48 @@ var constants = /*#__PURE__*/Object.freeze({
|
|
|
23537
23537
|
* Useful for runtime diagnostics and for embedding in serialized machine
|
|
23538
23538
|
* snapshots so that deserializers can detect version-skew.
|
|
23539
23539
|
*/
|
|
23540
|
-
const version = "5.144.
|
|
23540
|
+
const version = "5.144.8";
|
|
23541
23541
|
|
|
23542
23542
|
// whargarbl lots of these return arrays could/should be sets
|
|
23543
23543
|
const { state_name_chars, state_name_first_chars, action_label_chars } = constants;
|
|
23544
23544
|
const empty_string_set = new Set();
|
|
23545
|
+
// The spatial fields (besides `handler`, which every hook needs) that each
|
|
23546
|
+
// hook kind requires, mirroring exactly what `set_hook` reads per case. Used
|
|
23547
|
+
// to validate a HookDescription so a mis-shaped one is rejected rather than
|
|
23548
|
+
// silently registering a dead hook — e.g. an `exit` hook given `to` instead of
|
|
23549
|
+
// `from` would otherwise intern `undefined` and never fire (#734). Typed as a
|
|
23550
|
+
// `Record` over the kind union so the table is exhaustive at compile time:
|
|
23551
|
+
// adding a hook kind without listing its fields is a build error.
|
|
23552
|
+
const hook_required_fields = {
|
|
23553
|
+
'hook': ['from', 'to'],
|
|
23554
|
+
'named': ['from', 'to', 'action'],
|
|
23555
|
+
'global action': ['action'],
|
|
23556
|
+
'any action': [],
|
|
23557
|
+
'standard transition': [],
|
|
23558
|
+
'main transition': [],
|
|
23559
|
+
'forced transition': [],
|
|
23560
|
+
'any transition': [],
|
|
23561
|
+
'entry': ['to'],
|
|
23562
|
+
'exit': ['from'],
|
|
23563
|
+
'after': ['from'],
|
|
23564
|
+
'post hook': ['from', 'to'],
|
|
23565
|
+
'post named': ['from', 'to', 'action'],
|
|
23566
|
+
'post global action': ['action'],
|
|
23567
|
+
'post any action': [],
|
|
23568
|
+
'post standard transition': [],
|
|
23569
|
+
'post main transition': [],
|
|
23570
|
+
'post forced transition': [],
|
|
23571
|
+
'post any transition': [],
|
|
23572
|
+
'post entry': ['to'],
|
|
23573
|
+
'post exit': ['from'],
|
|
23574
|
+
'pre everything': [],
|
|
23575
|
+
'everything': [],
|
|
23576
|
+
'pre post everything': [],
|
|
23577
|
+
'post everything': [],
|
|
23578
|
+
};
|
|
23579
|
+
// The spatial fields a hook descriptor can carry, checked against the per-kind
|
|
23580
|
+
// requirements above.
|
|
23581
|
+
const hook_spatial_fields = ['from', 'to', 'action'];
|
|
23545
23582
|
/*********
|
|
23546
23583
|
*
|
|
23547
23584
|
* An internal method meant to take a series of declarations and fold them into
|
|
@@ -25799,7 +25836,44 @@ class Machine {
|
|
|
25799
25836
|
* calling this directly.
|
|
25800
25837
|
* @param HookDesc - A hook descriptor specifying kind, states, and handler.
|
|
25801
25838
|
*/
|
|
25839
|
+
/**
|
|
25840
|
+
* Validate a {@link HookDescription} before registration. Every hook needs
|
|
25841
|
+
* a `handler` function, and each kind's identifying spatial fields
|
|
25842
|
+
* (`from`/`to`/`action`) must be exactly those `set_hook` reads for that
|
|
25843
|
+
* kind — present when required, absent otherwise. This turns a mis-shaped
|
|
25844
|
+
* descriptor into a thrown error instead of a silently dead hook keyed on
|
|
25845
|
+
* `undefined` (e.g. an `exit` hook handed `to` instead of `from`, #734).
|
|
25846
|
+
*
|
|
25847
|
+
* @param HookDesc - The descriptor about to be registered.
|
|
25848
|
+
* @throws JssmError if the kind is unknown, the handler is not a function, a
|
|
25849
|
+
* required field is missing, or an inapplicable field is present.
|
|
25850
|
+
*
|
|
25851
|
+
* @example
|
|
25852
|
+
* const m = sm`a -> b;`;
|
|
25853
|
+
* // an exit hook is keyed by `from`, so supplying `to` is rejected:
|
|
25854
|
+
* expect(() => m.set_hook({ kind: 'exit', to: 'a', handler: () => true })).toThrow();
|
|
25855
|
+
*/
|
|
25856
|
+
_validate_hook_description(HookDesc) {
|
|
25857
|
+
const required = hook_required_fields[HookDesc.kind];
|
|
25858
|
+
if (required === undefined) {
|
|
25859
|
+
throw new JssmError(this, `unknown hook kind ${JSON.stringify(HookDesc.kind)}`);
|
|
25860
|
+
}
|
|
25861
|
+
if (typeof HookDesc.handler !== 'function') {
|
|
25862
|
+
throw new JssmError(this, `${HookDesc.kind} hook requires a handler function`);
|
|
25863
|
+
}
|
|
25864
|
+
for (const field of hook_spatial_fields) {
|
|
25865
|
+
const needed = required.includes(field);
|
|
25866
|
+
const present = HookDesc[field] !== undefined;
|
|
25867
|
+
if (needed && !present) {
|
|
25868
|
+
throw new JssmError(this, `${HookDesc.kind} hook requires '${field}'`);
|
|
25869
|
+
}
|
|
25870
|
+
if (!needed && present) {
|
|
25871
|
+
throw new JssmError(this, `${HookDesc.kind} hook does not take '${field}'`);
|
|
25872
|
+
}
|
|
25873
|
+
}
|
|
25874
|
+
}
|
|
25802
25875
|
set_hook(HookDesc) {
|
|
25876
|
+
this._validate_hook_description(HookDesc);
|
|
25803
25877
|
switch (HookDesc.kind) {
|
|
25804
25878
|
case 'hook': {
|
|
25805
25879
|
// Numeric pair key (#729). intern() rather than id_of(): a hook may
|
|
@@ -25941,8 +26015,8 @@ class Machine {
|
|
|
25941
26015
|
this._post_everything_hook = HookDesc.handler;
|
|
25942
26016
|
this._has_post_hooks = true;
|
|
25943
26017
|
break;
|
|
25944
|
-
default:
|
|
25945
|
-
|
|
26018
|
+
// No default: `_validate_hook_description` above rejects any unknown kind
|
|
26019
|
+
// before we reach here, so the switch is exhaustive over the known kinds.
|
|
25946
26020
|
}
|
|
25947
26021
|
// The hooked-state styling layer (tier 2.5 of resolve_state_config) depends
|
|
25948
26022
|
// on which states carry hooks, so registering a hook can change the composed
|
|
@@ -108,7 +108,7 @@ function parseFslArgs(argv, spec) {
|
|
|
108
108
|
return { positional, flags, helpText };
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
const getVersion = () => "5.144.
|
|
111
|
+
const getVersion = () => "5.144.8";
|
|
112
112
|
const SPEC = {
|
|
113
113
|
flags: {
|
|
114
114
|
help: { short: "h", boolean: true },
|
|
@@ -214,6 +214,6 @@ async function cli(argv) {
|
|
|
214
214
|
async function main() {
|
|
215
215
|
const argv = process.argv.slice(2);
|
|
216
216
|
const code = await cli(argv);
|
|
217
|
-
process.
|
|
217
|
+
process.exitCode = code;
|
|
218
218
|
}
|
|
219
219
|
void main();
|