jssm 5.143.24 → 5.143.26
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 +6 -6
- package/dist/cdn/instance.js +48 -40
- package/dist/cdn/viz.js +48 -40
- package/dist/cli/fsl-render.cjs +1 -1
- package/dist/cli/fsl.cjs +1 -1
- package/dist/deno/README.md +6 -6
- 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/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.143.
|
|
21
|
+
* Generated for version 5.143.26 at 6/12/2026, 2:39:54 PM
|
|
22
22
|
|
|
23
23
|
-->
|
|
24
|
-
# jssm 5.143.
|
|
24
|
+
# jssm 5.143.26
|
|
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.** 7,
|
|
284
|
+
library.** 7,013 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
|
-
***7,
|
|
417
|
+
***7,013 tests***, run 81,857 times.
|
|
418
418
|
|
|
419
|
-
- 6,
|
|
419
|
+
- 6,257 specs with 100.0% coverage
|
|
420
420
|
- 756 fuzz tests with 83.5% coverage
|
|
421
|
-
- 5,
|
|
421
|
+
- 5,880 TypeScript lines - 1.2 tests per line, 13.9 generated tests per line
|
|
422
422
|
|
|
423
423
|
[](https://github.com/StoneCypher/jssm/actions)
|
|
424
424
|
[](https://www.npmjs.com/package/jssm)
|
package/dist/cdn/instance.js
CHANGED
|
@@ -3355,49 +3355,35 @@ function peg$parse(input, options) {
|
|
|
3355
3355
|
return s0;
|
|
3356
3356
|
}
|
|
3357
3357
|
function peg$parseIntegerLiteral() {
|
|
3358
|
-
var
|
|
3359
|
-
|
|
3360
|
-
if (
|
|
3361
|
-
s1 = peg$c312;
|
|
3358
|
+
var c, start;
|
|
3359
|
+
c = input.charCodeAt(peg$currPos);
|
|
3360
|
+
if (c === 48) { // '0' alternative
|
|
3362
3361
|
peg$currPos++;
|
|
3362
|
+
return '0';
|
|
3363
3363
|
}
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
}
|
|
3364
|
+
// the generated code records the "0" alternative's expectation whenever
|
|
3365
|
+
// input doesn't start with 0 — including on the successful 1-9 path
|
|
3366
|
+
if (peg$silentFails === 0 && peg$currPos >= peg$maxFailPos) {
|
|
3367
|
+
peg$fail(peg$c313);
|
|
3369
3368
|
}
|
|
3370
|
-
if (
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
s3.push(s4);
|
|
3378
|
-
s4 = peg$parseDecimalDigit();
|
|
3379
|
-
}
|
|
3380
|
-
if (s3 !== peg$FAILED) {
|
|
3381
|
-
s2 = [s2, s3];
|
|
3382
|
-
s1 = s2;
|
|
3383
|
-
}
|
|
3384
|
-
else {
|
|
3385
|
-
peg$currPos = s1;
|
|
3386
|
-
s1 = peg$FAILED;
|
|
3387
|
-
}
|
|
3369
|
+
if (c >= 49 && c <= 57) { // 1-9
|
|
3370
|
+
start = peg$currPos;
|
|
3371
|
+
peg$currPos++;
|
|
3372
|
+
c = input.charCodeAt(peg$currPos);
|
|
3373
|
+
while (c >= 48 && c <= 57) { // 0-9 run
|
|
3374
|
+
peg$currPos++;
|
|
3375
|
+
c = input.charCodeAt(peg$currPos);
|
|
3388
3376
|
}
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3377
|
+
// run-terminating DecimalDigit failure, recorded at the stop position
|
|
3378
|
+
if (peg$silentFails === 0 && peg$currPos >= peg$maxFailPos) {
|
|
3379
|
+
peg$fail(peg$c315);
|
|
3392
3380
|
}
|
|
3381
|
+
return input.substring(start, peg$currPos);
|
|
3393
3382
|
}
|
|
3394
|
-
if (
|
|
3395
|
-
|
|
3396
|
-
}
|
|
3397
|
-
else {
|
|
3398
|
-
s0 = s1;
|
|
3383
|
+
if (peg$silentFails === 0 && peg$currPos >= peg$maxFailPos) {
|
|
3384
|
+
peg$fail(peg$c317);
|
|
3399
3385
|
}
|
|
3400
|
-
return
|
|
3386
|
+
return peg$FAILED;
|
|
3401
3387
|
}
|
|
3402
3388
|
function peg$parseDecimalDigit() {
|
|
3403
3389
|
var s0;
|
|
@@ -22402,7 +22388,7 @@ var constants = /*#__PURE__*/Object.freeze({
|
|
|
22402
22388
|
* Useful for runtime diagnostics and for embedding in serialized machine
|
|
22403
22389
|
* snapshots so that deserializers can detect version-skew.
|
|
22404
22390
|
*/
|
|
22405
|
-
const version = "5.143.
|
|
22391
|
+
const version = "5.143.26";
|
|
22406
22392
|
|
|
22407
22393
|
// whargarbl lots of these return arrays could/should be sets
|
|
22408
22394
|
const { state_name_chars, state_name_first_chars, action_label_chars } = constants;
|
|
@@ -25221,7 +25207,19 @@ class Machine {
|
|
|
25221
25207
|
const edgeId = (to_id === undefined) ? undefined : this._edge_id_by_pair.get(pair_key(this._state_id, to_id));
|
|
25222
25208
|
if ((edgeId !== undefined) && (!(this._edges[edgeId].forced_only))) {
|
|
25223
25209
|
if (this._has_transition_hooks || this._has_post_transition_hooks) {
|
|
25224
|
-
|
|
25210
|
+
// first matching outbound edge's kind, without building the result
|
|
25211
|
+
// array edges_between allocated here on every hooked transition.
|
|
25212
|
+
// First-match semantics are kept deliberately: _edge_map is
|
|
25213
|
+
// last-wins for multi-edge (from, to) pairs, so lookup_transition_for
|
|
25214
|
+
// could disagree with the old edges_between(...)[0]. #735
|
|
25215
|
+
// TODO this won't do the right thing if various edges have different types
|
|
25216
|
+
for (const ob_eid of this._outbound_edge_ids.get(this._state)) {
|
|
25217
|
+
const ob_edge = this._edges[ob_eid];
|
|
25218
|
+
if (ob_edge.to === newStateOrAction) {
|
|
25219
|
+
trans_type = ob_edge.kind;
|
|
25220
|
+
break;
|
|
25221
|
+
}
|
|
25222
|
+
}
|
|
25225
25223
|
}
|
|
25226
25224
|
valid = true;
|
|
25227
25225
|
newState = newStateOrAction;
|
|
@@ -25235,6 +25233,11 @@ class Machine {
|
|
|
25235
25233
|
// unchanged for all downstream uses without introducing an impossible
|
|
25236
25234
|
// (uncoverable) branch; the value is only dereferenced under the guards
|
|
25237
25235
|
// that imply it was built. #670
|
|
25236
|
+
// NOTE (#735): the { ...hook_args, hook_name } spreads at the four
|
|
25237
|
+
// everything-hook sites are contractual, not waste — handlers may capture
|
|
25238
|
+
// their context, and each captured context must durably carry its own
|
|
25239
|
+
// hook_name (pinned by the simultaneous-everything-hook specs). A shared
|
|
25240
|
+
// mutated object cannot satisfy that; do not "optimize" the spreads away.
|
|
25238
25241
|
const hook_args_obj = (this._has_hooks || this._has_post_hooks)
|
|
25239
25242
|
? {
|
|
25240
25243
|
data: this._data,
|
|
@@ -25594,10 +25597,15 @@ class Machine {
|
|
|
25594
25597
|
cause: 'transition'
|
|
25595
25598
|
});
|
|
25596
25599
|
}
|
|
25597
|
-
|
|
25600
|
+
// one state-record fetch answers both checks; newState is known-valid
|
|
25601
|
+
// here, and the public state_is_terminal / state_is_complete pair would
|
|
25602
|
+
// each redo has_state plus its own map walk. Same predicates:
|
|
25603
|
+
// terminal = no exits, complete = the constructor-set flag. #735
|
|
25604
|
+
const new_state_rec = this._states.get(newState);
|
|
25605
|
+
if (new_state_rec.to.length === 0) {
|
|
25598
25606
|
this._fire('terminal', { state: newState, data: newData_after });
|
|
25599
25607
|
}
|
|
25600
|
-
if (
|
|
25608
|
+
if (new_state_rec.complete) {
|
|
25601
25609
|
this._fire('complete', { state: newState, data: newData_after });
|
|
25602
25610
|
}
|
|
25603
25611
|
}
|
package/dist/cdn/viz.js
CHANGED
|
@@ -3380,49 +3380,35 @@ function peg$parse(input, options) {
|
|
|
3380
3380
|
return s0;
|
|
3381
3381
|
}
|
|
3382
3382
|
function peg$parseIntegerLiteral() {
|
|
3383
|
-
var
|
|
3384
|
-
|
|
3385
|
-
if (
|
|
3386
|
-
s1 = peg$c312;
|
|
3383
|
+
var c, start;
|
|
3384
|
+
c = input.charCodeAt(peg$currPos);
|
|
3385
|
+
if (c === 48) { // '0' alternative
|
|
3387
3386
|
peg$currPos++;
|
|
3387
|
+
return '0';
|
|
3388
3388
|
}
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
}
|
|
3389
|
+
// the generated code records the "0" alternative's expectation whenever
|
|
3390
|
+
// input doesn't start with 0 — including on the successful 1-9 path
|
|
3391
|
+
if (peg$silentFails === 0 && peg$currPos >= peg$maxFailPos) {
|
|
3392
|
+
peg$fail(peg$c313);
|
|
3394
3393
|
}
|
|
3395
|
-
if (
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
s3.push(s4);
|
|
3403
|
-
s4 = peg$parseDecimalDigit();
|
|
3404
|
-
}
|
|
3405
|
-
if (s3 !== peg$FAILED) {
|
|
3406
|
-
s2 = [s2, s3];
|
|
3407
|
-
s1 = s2;
|
|
3408
|
-
}
|
|
3409
|
-
else {
|
|
3410
|
-
peg$currPos = s1;
|
|
3411
|
-
s1 = peg$FAILED;
|
|
3412
|
-
}
|
|
3394
|
+
if (c >= 49 && c <= 57) { // 1-9
|
|
3395
|
+
start = peg$currPos;
|
|
3396
|
+
peg$currPos++;
|
|
3397
|
+
c = input.charCodeAt(peg$currPos);
|
|
3398
|
+
while (c >= 48 && c <= 57) { // 0-9 run
|
|
3399
|
+
peg$currPos++;
|
|
3400
|
+
c = input.charCodeAt(peg$currPos);
|
|
3413
3401
|
}
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3402
|
+
// run-terminating DecimalDigit failure, recorded at the stop position
|
|
3403
|
+
if (peg$silentFails === 0 && peg$currPos >= peg$maxFailPos) {
|
|
3404
|
+
peg$fail(peg$c315);
|
|
3417
3405
|
}
|
|
3406
|
+
return input.substring(start, peg$currPos);
|
|
3418
3407
|
}
|
|
3419
|
-
if (
|
|
3420
|
-
|
|
3421
|
-
}
|
|
3422
|
-
else {
|
|
3423
|
-
s0 = s1;
|
|
3408
|
+
if (peg$silentFails === 0 && peg$currPos >= peg$maxFailPos) {
|
|
3409
|
+
peg$fail(peg$c317);
|
|
3424
3410
|
}
|
|
3425
|
-
return
|
|
3411
|
+
return peg$FAILED;
|
|
3426
3412
|
}
|
|
3427
3413
|
function peg$parseDecimalDigit() {
|
|
3428
3414
|
var s0;
|
|
@@ -22427,7 +22413,7 @@ var constants = /*#__PURE__*/Object.freeze({
|
|
|
22427
22413
|
* Useful for runtime diagnostics and for embedding in serialized machine
|
|
22428
22414
|
* snapshots so that deserializers can detect version-skew.
|
|
22429
22415
|
*/
|
|
22430
|
-
const version = "5.143.
|
|
22416
|
+
const version = "5.143.26";
|
|
22431
22417
|
|
|
22432
22418
|
// whargarbl lots of these return arrays could/should be sets
|
|
22433
22419
|
const { state_name_chars, state_name_first_chars, action_label_chars } = constants;
|
|
@@ -25246,7 +25232,19 @@ class Machine {
|
|
|
25246
25232
|
const edgeId = (to_id === undefined) ? undefined : this._edge_id_by_pair.get(pair_key(this._state_id, to_id));
|
|
25247
25233
|
if ((edgeId !== undefined) && (!(this._edges[edgeId].forced_only))) {
|
|
25248
25234
|
if (this._has_transition_hooks || this._has_post_transition_hooks) {
|
|
25249
|
-
|
|
25235
|
+
// first matching outbound edge's kind, without building the result
|
|
25236
|
+
// array edges_between allocated here on every hooked transition.
|
|
25237
|
+
// First-match semantics are kept deliberately: _edge_map is
|
|
25238
|
+
// last-wins for multi-edge (from, to) pairs, so lookup_transition_for
|
|
25239
|
+
// could disagree with the old edges_between(...)[0]. #735
|
|
25240
|
+
// TODO this won't do the right thing if various edges have different types
|
|
25241
|
+
for (const ob_eid of this._outbound_edge_ids.get(this._state)) {
|
|
25242
|
+
const ob_edge = this._edges[ob_eid];
|
|
25243
|
+
if (ob_edge.to === newStateOrAction) {
|
|
25244
|
+
trans_type = ob_edge.kind;
|
|
25245
|
+
break;
|
|
25246
|
+
}
|
|
25247
|
+
}
|
|
25250
25248
|
}
|
|
25251
25249
|
valid = true;
|
|
25252
25250
|
newState = newStateOrAction;
|
|
@@ -25260,6 +25258,11 @@ class Machine {
|
|
|
25260
25258
|
// unchanged for all downstream uses without introducing an impossible
|
|
25261
25259
|
// (uncoverable) branch; the value is only dereferenced under the guards
|
|
25262
25260
|
// that imply it was built. #670
|
|
25261
|
+
// NOTE (#735): the { ...hook_args, hook_name } spreads at the four
|
|
25262
|
+
// everything-hook sites are contractual, not waste — handlers may capture
|
|
25263
|
+
// their context, and each captured context must durably carry its own
|
|
25264
|
+
// hook_name (pinned by the simultaneous-everything-hook specs). A shared
|
|
25265
|
+
// mutated object cannot satisfy that; do not "optimize" the spreads away.
|
|
25263
25266
|
const hook_args_obj = (this._has_hooks || this._has_post_hooks)
|
|
25264
25267
|
? {
|
|
25265
25268
|
data: this._data,
|
|
@@ -25619,10 +25622,15 @@ class Machine {
|
|
|
25619
25622
|
cause: 'transition'
|
|
25620
25623
|
});
|
|
25621
25624
|
}
|
|
25622
|
-
|
|
25625
|
+
// one state-record fetch answers both checks; newState is known-valid
|
|
25626
|
+
// here, and the public state_is_terminal / state_is_complete pair would
|
|
25627
|
+
// each redo has_state plus its own map walk. Same predicates:
|
|
25628
|
+
// terminal = no exits, complete = the constructor-set flag. #735
|
|
25629
|
+
const new_state_rec = this._states.get(newState);
|
|
25630
|
+
if (new_state_rec.to.length === 0) {
|
|
25623
25631
|
this._fire('terminal', { state: newState, data: newData_after });
|
|
25624
25632
|
}
|
|
25625
|
-
if (
|
|
25633
|
+
if (new_state_rec.complete) {
|
|
25626
25634
|
this._fire('complete', { state: newState, data: newData_after });
|
|
25627
25635
|
}
|
|
25628
25636
|
}
|