jssm 5.141.5 → 5.141.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.
- package/README.md +3 -3
- package/dist/cdn/instance.js +131 -46
- package/dist/cdn/viz.js +131 -46
- package/dist/cli/fsl-render.cjs +1 -1
- package/dist/cli/fsl.cjs +1 -1
- package/dist/deno/README.md +3 -3
- package/dist/deno/jssm.d.ts +27 -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 +27 -0
- package/jssm.es6.d.ts +27 -0
- package/jssm_viz.es5.d.cts +27 -0
- package/jssm_viz.es6.d.ts +27 -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.141.
|
|
21
|
+
* Generated for version 5.141.6 at 6/4/2026, 4:19:34 PM
|
|
22
22
|
|
|
23
23
|
-->
|
|
24
|
-
# jssm 5.141.
|
|
24
|
+
# jssm 5.141.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/) ·
|
|
@@ -418,7 +418,7 @@ If your contribution is missing here, please open an issue.
|
|
|
418
418
|
|
|
419
419
|
- 5,971 specs with 100.0% coverage
|
|
420
420
|
- 513 fuzz tests with 3.4% coverage
|
|
421
|
-
- 5,
|
|
421
|
+
- 5,590 TypeScript lines - 1.2 tests per line, 10.2 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
|
@@ -21327,7 +21327,7 @@ var constants = /*#__PURE__*/Object.freeze({
|
|
|
21327
21327
|
* Useful for runtime diagnostics and for embedding in serialized machine
|
|
21328
21328
|
* snapshots so that deserializers can detect version-skew.
|
|
21329
21329
|
*/
|
|
21330
|
-
const version = "5.141.
|
|
21330
|
+
const version = "5.141.6";
|
|
21331
21331
|
|
|
21332
21332
|
// whargarbl lots of these return arrays could/should be sets
|
|
21333
21333
|
const { state_name_chars, state_name_first_chars, action_label_chars } = constants;
|
|
@@ -23848,6 +23848,44 @@ class Machine {
|
|
|
23848
23848
|
throw new JssmError(this, "Code specifies no override, but config tries to permit; config may not be less strict than code");
|
|
23849
23849
|
}
|
|
23850
23850
|
}
|
|
23851
|
+
/*********
|
|
23852
|
+
*
|
|
23853
|
+
* Fire a `'rejection'` event caused by a hook vetoing a pending transition.
|
|
23854
|
+
* Extracted from the per-call closures inside {@link transition_impl} so
|
|
23855
|
+
* that it is allocated once at class-definition time rather than on every
|
|
23856
|
+
* hooked transition.
|
|
23857
|
+
*
|
|
23858
|
+
* @param hook_name Name of the hook that rejected (e.g. `'exit'`).
|
|
23859
|
+
* @param fromState State the machine was in when the transition was
|
|
23860
|
+
* attempted; used as the `from` field of the rejection event.
|
|
23861
|
+
* @param newState State that would have been entered had the hook
|
|
23862
|
+
* passed; used as the `to` field of the rejection event.
|
|
23863
|
+
* @param fromAction Action name when the transition was initiated by an
|
|
23864
|
+
* action call; `undefined` for plain state transitions.
|
|
23865
|
+
* @param oldData Machine data at the moment the transition was
|
|
23866
|
+
* attempted, before any hook mutations.
|
|
23867
|
+
* @param newData The `next_data` value passed to the transition call.
|
|
23868
|
+
* @param wasForced Whether the transition was attempted via
|
|
23869
|
+
* `force_transition`.
|
|
23870
|
+
*
|
|
23871
|
+
* @see transition_impl
|
|
23872
|
+
* @see _fire
|
|
23873
|
+
*
|
|
23874
|
+
* @internal
|
|
23875
|
+
*
|
|
23876
|
+
*/
|
|
23877
|
+
_fire_hook_rejection(hook_name, fromState, newState, fromAction, oldData, newData, wasForced) {
|
|
23878
|
+
this._fire('rejection', {
|
|
23879
|
+
from: fromState,
|
|
23880
|
+
to: newState,
|
|
23881
|
+
action: fromAction,
|
|
23882
|
+
data: oldData,
|
|
23883
|
+
next_data: newData,
|
|
23884
|
+
reason: 'hook',
|
|
23885
|
+
hook_name,
|
|
23886
|
+
forced: wasForced
|
|
23887
|
+
});
|
|
23888
|
+
}
|
|
23851
23889
|
/*********
|
|
23852
23890
|
*
|
|
23853
23891
|
* Shared transition core used by {@link transition}, {@link force_transition},
|
|
@@ -23956,75 +23994,68 @@ class Machine {
|
|
|
23956
23994
|
if (this._has_hooks) {
|
|
23957
23995
|
// once validity is known, clear old 'after' timeout clause
|
|
23958
23996
|
this.clear_state_timeout();
|
|
23959
|
-
function update_fields(res) {
|
|
23960
|
-
if (res.hasOwnProperty('data')) {
|
|
23961
|
-
hook_args.data = res.data;
|
|
23962
|
-
hook_args.next_data = res.next_data;
|
|
23963
|
-
data_changed = true;
|
|
23964
|
-
}
|
|
23965
|
-
}
|
|
23966
23997
|
let data_changed = false;
|
|
23967
|
-
const fire_rejection = (hook_name) => {
|
|
23968
|
-
this._fire('rejection', {
|
|
23969
|
-
from: fromState,
|
|
23970
|
-
to: newState,
|
|
23971
|
-
action: fromAction,
|
|
23972
|
-
data: oldData,
|
|
23973
|
-
next_data: newData,
|
|
23974
|
-
reason: 'hook',
|
|
23975
|
-
hook_name,
|
|
23976
|
-
forced: wasForced
|
|
23977
|
-
});
|
|
23978
|
-
};
|
|
23979
23998
|
// 0. pre everything hook (fires before all other pre-hooks)
|
|
23980
23999
|
if (this._pre_everything_hook !== undefined) {
|
|
23981
24000
|
const outcome = abstract_everything_hook_step(this._pre_everything_hook, Object.assign(Object.assign({}, hook_args), { hook_name: 'pre everything' }));
|
|
23982
24001
|
if (outcome.pass === false) {
|
|
23983
|
-
|
|
24002
|
+
this._fire_hook_rejection('pre everything', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
23984
24003
|
return false;
|
|
23985
24004
|
}
|
|
23986
|
-
|
|
24005
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24006
|
+
data_changed = true;
|
|
24007
|
+
}
|
|
23987
24008
|
}
|
|
23988
24009
|
if (wasAction) {
|
|
23989
24010
|
// 1a. any action hook
|
|
23990
24011
|
const outcome = abstract_hook_step(this._any_action_hook, hook_args);
|
|
23991
24012
|
if (outcome.pass === false) {
|
|
23992
|
-
|
|
24013
|
+
this._fire_hook_rejection('any action', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
23993
24014
|
return false;
|
|
23994
24015
|
}
|
|
23995
|
-
|
|
24016
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24017
|
+
data_changed = true;
|
|
24018
|
+
}
|
|
23996
24019
|
// 1b. global specific action hook
|
|
23997
24020
|
const outcome2 = abstract_hook_step(this._global_action_hooks.get(newStateOrAction), hook_args);
|
|
23998
24021
|
if (outcome2.pass === false) {
|
|
23999
|
-
|
|
24022
|
+
this._fire_hook_rejection('global action', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24000
24023
|
return false;
|
|
24001
24024
|
}
|
|
24002
|
-
|
|
24025
|
+
if (_update_hook_fields(hook_args, outcome2)) {
|
|
24026
|
+
data_changed = true;
|
|
24027
|
+
}
|
|
24003
24028
|
}
|
|
24004
24029
|
// 2. after hook
|
|
24005
24030
|
if (this._has_after_hooks) {
|
|
24006
24031
|
const ah = this._after_hooks.get(newStateOrAction);
|
|
24007
24032
|
const outcome = abstract_hook_step(ah, hook_args);
|
|
24008
|
-
// there's no such thing as after not passing, so, omit the result pass check
|
|
24009
|
-
|
|
24033
|
+
// there's no such thing as after not passing, so, omit the result pass check.
|
|
24034
|
+
// after hooks are post-exit and informational — their outcome never changes
|
|
24035
|
+
// data, so there's no data_changed branch here (it would be unreachable).
|
|
24036
|
+
_update_hook_fields(hook_args, outcome);
|
|
24010
24037
|
}
|
|
24011
24038
|
// 3. any transition hook
|
|
24012
24039
|
if (this._any_transition_hook !== undefined) {
|
|
24013
24040
|
const outcome = abstract_hook_step(this._any_transition_hook, hook_args);
|
|
24014
24041
|
if (outcome.pass === false) {
|
|
24015
|
-
|
|
24042
|
+
this._fire_hook_rejection('any transition', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24016
24043
|
return false;
|
|
24017
24044
|
}
|
|
24018
|
-
|
|
24045
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24046
|
+
data_changed = true;
|
|
24047
|
+
}
|
|
24019
24048
|
}
|
|
24020
24049
|
// 4. exit hook
|
|
24021
24050
|
if (this._has_exit_hooks) {
|
|
24022
24051
|
const outcome = abstract_hook_step(this._exit_hooks.get(this._state), hook_args);
|
|
24023
24052
|
if (outcome.pass === false) {
|
|
24024
|
-
|
|
24053
|
+
this._fire_hook_rejection('exit', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24025
24054
|
return false;
|
|
24026
24055
|
}
|
|
24027
|
-
|
|
24056
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24057
|
+
data_changed = true;
|
|
24058
|
+
}
|
|
24028
24059
|
}
|
|
24029
24060
|
// 5. named transition / action hook
|
|
24030
24061
|
if (this._has_named_hooks) {
|
|
@@ -24036,10 +24067,12 @@ class Machine {
|
|
|
24036
24067
|
const nh = byAct === undefined ? undefined : byAct.get(newStateOrAction);
|
|
24037
24068
|
const outcome = abstract_hook_step(nh, hook_args);
|
|
24038
24069
|
if (outcome.pass === false) {
|
|
24039
|
-
|
|
24070
|
+
this._fire_hook_rejection('named', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24040
24071
|
return false;
|
|
24041
24072
|
}
|
|
24042
|
-
|
|
24073
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24074
|
+
data_changed = true;
|
|
24075
|
+
}
|
|
24043
24076
|
}
|
|
24044
24077
|
}
|
|
24045
24078
|
// 6. regular hook
|
|
@@ -24049,56 +24082,68 @@ class Machine {
|
|
|
24049
24082
|
const h = byTo === undefined ? undefined : byTo.get(newState);
|
|
24050
24083
|
const outcome = abstract_hook_step(h, hook_args);
|
|
24051
24084
|
if (outcome.pass === false) {
|
|
24052
|
-
|
|
24085
|
+
this._fire_hook_rejection('hook', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24053
24086
|
return false;
|
|
24054
24087
|
}
|
|
24055
|
-
|
|
24088
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24089
|
+
data_changed = true;
|
|
24090
|
+
}
|
|
24056
24091
|
}
|
|
24057
24092
|
// 7. edge type hook
|
|
24058
24093
|
// 7a. standard transition hook
|
|
24059
24094
|
if (trans_type === 'legal') {
|
|
24060
24095
|
const outcome = abstract_hook_step(this._standard_transition_hook, hook_args);
|
|
24061
24096
|
if (outcome.pass === false) {
|
|
24062
|
-
|
|
24097
|
+
this._fire_hook_rejection('standard transition', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24063
24098
|
return false;
|
|
24064
24099
|
}
|
|
24065
|
-
|
|
24100
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24101
|
+
data_changed = true;
|
|
24102
|
+
}
|
|
24066
24103
|
}
|
|
24067
24104
|
// 7b. main type hook
|
|
24068
24105
|
if (trans_type === 'main') {
|
|
24069
24106
|
const outcome = abstract_hook_step(this._main_transition_hook, hook_args);
|
|
24070
24107
|
if (outcome.pass === false) {
|
|
24071
|
-
|
|
24108
|
+
this._fire_hook_rejection('main transition', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24072
24109
|
return false;
|
|
24073
24110
|
}
|
|
24074
|
-
|
|
24111
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24112
|
+
data_changed = true;
|
|
24113
|
+
}
|
|
24075
24114
|
}
|
|
24076
24115
|
// 7c. forced transition hook
|
|
24077
24116
|
if (trans_type === 'forced') {
|
|
24078
24117
|
const outcome = abstract_hook_step(this._forced_transition_hook, hook_args);
|
|
24079
24118
|
if (outcome.pass === false) {
|
|
24080
|
-
|
|
24119
|
+
this._fire_hook_rejection('forced transition', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24081
24120
|
return false;
|
|
24082
24121
|
}
|
|
24083
|
-
|
|
24122
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24123
|
+
data_changed = true;
|
|
24124
|
+
}
|
|
24084
24125
|
}
|
|
24085
24126
|
// 8. entry hook
|
|
24086
24127
|
if (this._has_entry_hooks) {
|
|
24087
24128
|
const outcome = abstract_hook_step(this._entry_hooks.get(newState), hook_args);
|
|
24088
24129
|
if (outcome.pass === false) {
|
|
24089
|
-
|
|
24130
|
+
this._fire_hook_rejection('entry', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24090
24131
|
return false;
|
|
24091
24132
|
}
|
|
24092
|
-
|
|
24133
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24134
|
+
data_changed = true;
|
|
24135
|
+
}
|
|
24093
24136
|
}
|
|
24094
24137
|
// 9. everything hook (fires after all other pre-hooks)
|
|
24095
24138
|
if (this._everything_hook !== undefined) {
|
|
24096
24139
|
const outcome = abstract_everything_hook_step(this._everything_hook, Object.assign(Object.assign({}, hook_args), { hook_name: 'everything' }));
|
|
24097
24140
|
if (outcome.pass === false) {
|
|
24098
|
-
|
|
24141
|
+
this._fire_hook_rejection('everything', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24099
24142
|
return false;
|
|
24100
24143
|
}
|
|
24101
|
-
|
|
24144
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24145
|
+
data_changed = true;
|
|
24146
|
+
}
|
|
24102
24147
|
}
|
|
24103
24148
|
// all hooks passed! let's now establish the result
|
|
24104
24149
|
if (this._history_length) {
|
|
@@ -25024,6 +25069,46 @@ function is_hook_complex_result(hr) {
|
|
|
25024
25069
|
}
|
|
25025
25070
|
return false;
|
|
25026
25071
|
}
|
|
25072
|
+
/**
|
|
25073
|
+
*
|
|
25074
|
+
* Apply any data-field updates from a hook's complex result into `hook_args`,
|
|
25075
|
+
* and return whether data actually changed.
|
|
25076
|
+
*
|
|
25077
|
+
* This is the hoisted, allocation-free replacement for the `update_fields`
|
|
25078
|
+
* inner function that used to be re-created on every hooked transition inside
|
|
25079
|
+
* {@link Machine.transition_impl}. By moving it to module scope the function
|
|
25080
|
+
* object is allocated once at module load time.
|
|
25081
|
+
*
|
|
25082
|
+
* When the result does not carry a `data` property (the common case —
|
|
25083
|
+
* most hooks return `true` or `undefined`) the function returns `false`
|
|
25084
|
+
* immediately without touching `hook_args`.
|
|
25085
|
+
*
|
|
25086
|
+
* ```typescript
|
|
25087
|
+
* const args = { data: 'old', next_data: undefined, ... };
|
|
25088
|
+
* const changed = _update_hook_fields(args, { pass: true, data: 'new', next_data: undefined });
|
|
25089
|
+
* // changed === true, args.data === 'new'
|
|
25090
|
+
* ```
|
|
25091
|
+
*
|
|
25092
|
+
* @param hook_args The shared hook-argument object for the current
|
|
25093
|
+
* transition. Mutated in-place when the result carries `data`.
|
|
25094
|
+
* @param res The normalised complex result returned by
|
|
25095
|
+
* {@link abstract_hook_step} or {@link abstract_everything_hook_step}.
|
|
25096
|
+
*
|
|
25097
|
+
* @returns `true` if `res` contained a `data` property (i.e. the hook
|
|
25098
|
+
* mutated the machine's data); `false` otherwise.
|
|
25099
|
+
*
|
|
25100
|
+
* @see Machine.transition_impl
|
|
25101
|
+
* @see abstract_hook_step
|
|
25102
|
+
*
|
|
25103
|
+
*/
|
|
25104
|
+
function _update_hook_fields(hook_args, res) {
|
|
25105
|
+
if (Object.prototype.hasOwnProperty.call(res, 'data')) {
|
|
25106
|
+
hook_args.data = res.data;
|
|
25107
|
+
hook_args.next_data = res.next_data;
|
|
25108
|
+
return true;
|
|
25109
|
+
}
|
|
25110
|
+
return false;
|
|
25111
|
+
}
|
|
25027
25112
|
/**
|
|
25028
25113
|
*
|
|
25029
25114
|
* Invoke an optional transition/action hook and normalize its return value
|
package/dist/cdn/viz.js
CHANGED
|
@@ -21352,7 +21352,7 @@ var constants = /*#__PURE__*/Object.freeze({
|
|
|
21352
21352
|
* Useful for runtime diagnostics and for embedding in serialized machine
|
|
21353
21353
|
* snapshots so that deserializers can detect version-skew.
|
|
21354
21354
|
*/
|
|
21355
|
-
const version = "5.141.
|
|
21355
|
+
const version = "5.141.6";
|
|
21356
21356
|
|
|
21357
21357
|
// whargarbl lots of these return arrays could/should be sets
|
|
21358
21358
|
const { state_name_chars, state_name_first_chars, action_label_chars } = constants;
|
|
@@ -23873,6 +23873,44 @@ class Machine {
|
|
|
23873
23873
|
throw new JssmError(this, "Code specifies no override, but config tries to permit; config may not be less strict than code");
|
|
23874
23874
|
}
|
|
23875
23875
|
}
|
|
23876
|
+
/*********
|
|
23877
|
+
*
|
|
23878
|
+
* Fire a `'rejection'` event caused by a hook vetoing a pending transition.
|
|
23879
|
+
* Extracted from the per-call closures inside {@link transition_impl} so
|
|
23880
|
+
* that it is allocated once at class-definition time rather than on every
|
|
23881
|
+
* hooked transition.
|
|
23882
|
+
*
|
|
23883
|
+
* @param hook_name Name of the hook that rejected (e.g. `'exit'`).
|
|
23884
|
+
* @param fromState State the machine was in when the transition was
|
|
23885
|
+
* attempted; used as the `from` field of the rejection event.
|
|
23886
|
+
* @param newState State that would have been entered had the hook
|
|
23887
|
+
* passed; used as the `to` field of the rejection event.
|
|
23888
|
+
* @param fromAction Action name when the transition was initiated by an
|
|
23889
|
+
* action call; `undefined` for plain state transitions.
|
|
23890
|
+
* @param oldData Machine data at the moment the transition was
|
|
23891
|
+
* attempted, before any hook mutations.
|
|
23892
|
+
* @param newData The `next_data` value passed to the transition call.
|
|
23893
|
+
* @param wasForced Whether the transition was attempted via
|
|
23894
|
+
* `force_transition`.
|
|
23895
|
+
*
|
|
23896
|
+
* @see transition_impl
|
|
23897
|
+
* @see _fire
|
|
23898
|
+
*
|
|
23899
|
+
* @internal
|
|
23900
|
+
*
|
|
23901
|
+
*/
|
|
23902
|
+
_fire_hook_rejection(hook_name, fromState, newState, fromAction, oldData, newData, wasForced) {
|
|
23903
|
+
this._fire('rejection', {
|
|
23904
|
+
from: fromState,
|
|
23905
|
+
to: newState,
|
|
23906
|
+
action: fromAction,
|
|
23907
|
+
data: oldData,
|
|
23908
|
+
next_data: newData,
|
|
23909
|
+
reason: 'hook',
|
|
23910
|
+
hook_name,
|
|
23911
|
+
forced: wasForced
|
|
23912
|
+
});
|
|
23913
|
+
}
|
|
23876
23914
|
/*********
|
|
23877
23915
|
*
|
|
23878
23916
|
* Shared transition core used by {@link transition}, {@link force_transition},
|
|
@@ -23981,75 +24019,68 @@ class Machine {
|
|
|
23981
24019
|
if (this._has_hooks) {
|
|
23982
24020
|
// once validity is known, clear old 'after' timeout clause
|
|
23983
24021
|
this.clear_state_timeout();
|
|
23984
|
-
function update_fields(res) {
|
|
23985
|
-
if (res.hasOwnProperty('data')) {
|
|
23986
|
-
hook_args.data = res.data;
|
|
23987
|
-
hook_args.next_data = res.next_data;
|
|
23988
|
-
data_changed = true;
|
|
23989
|
-
}
|
|
23990
|
-
}
|
|
23991
24022
|
let data_changed = false;
|
|
23992
|
-
const fire_rejection = (hook_name) => {
|
|
23993
|
-
this._fire('rejection', {
|
|
23994
|
-
from: fromState,
|
|
23995
|
-
to: newState,
|
|
23996
|
-
action: fromAction,
|
|
23997
|
-
data: oldData,
|
|
23998
|
-
next_data: newData,
|
|
23999
|
-
reason: 'hook',
|
|
24000
|
-
hook_name,
|
|
24001
|
-
forced: wasForced
|
|
24002
|
-
});
|
|
24003
|
-
};
|
|
24004
24023
|
// 0. pre everything hook (fires before all other pre-hooks)
|
|
24005
24024
|
if (this._pre_everything_hook !== undefined) {
|
|
24006
24025
|
const outcome = abstract_everything_hook_step(this._pre_everything_hook, Object.assign(Object.assign({}, hook_args), { hook_name: 'pre everything' }));
|
|
24007
24026
|
if (outcome.pass === false) {
|
|
24008
|
-
|
|
24027
|
+
this._fire_hook_rejection('pre everything', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24009
24028
|
return false;
|
|
24010
24029
|
}
|
|
24011
|
-
|
|
24030
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24031
|
+
data_changed = true;
|
|
24032
|
+
}
|
|
24012
24033
|
}
|
|
24013
24034
|
if (wasAction) {
|
|
24014
24035
|
// 1a. any action hook
|
|
24015
24036
|
const outcome = abstract_hook_step(this._any_action_hook, hook_args);
|
|
24016
24037
|
if (outcome.pass === false) {
|
|
24017
|
-
|
|
24038
|
+
this._fire_hook_rejection('any action', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24018
24039
|
return false;
|
|
24019
24040
|
}
|
|
24020
|
-
|
|
24041
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24042
|
+
data_changed = true;
|
|
24043
|
+
}
|
|
24021
24044
|
// 1b. global specific action hook
|
|
24022
24045
|
const outcome2 = abstract_hook_step(this._global_action_hooks.get(newStateOrAction), hook_args);
|
|
24023
24046
|
if (outcome2.pass === false) {
|
|
24024
|
-
|
|
24047
|
+
this._fire_hook_rejection('global action', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24025
24048
|
return false;
|
|
24026
24049
|
}
|
|
24027
|
-
|
|
24050
|
+
if (_update_hook_fields(hook_args, outcome2)) {
|
|
24051
|
+
data_changed = true;
|
|
24052
|
+
}
|
|
24028
24053
|
}
|
|
24029
24054
|
// 2. after hook
|
|
24030
24055
|
if (this._has_after_hooks) {
|
|
24031
24056
|
const ah = this._after_hooks.get(newStateOrAction);
|
|
24032
24057
|
const outcome = abstract_hook_step(ah, hook_args);
|
|
24033
|
-
// there's no such thing as after not passing, so, omit the result pass check
|
|
24034
|
-
|
|
24058
|
+
// there's no such thing as after not passing, so, omit the result pass check.
|
|
24059
|
+
// after hooks are post-exit and informational — their outcome never changes
|
|
24060
|
+
// data, so there's no data_changed branch here (it would be unreachable).
|
|
24061
|
+
_update_hook_fields(hook_args, outcome);
|
|
24035
24062
|
}
|
|
24036
24063
|
// 3. any transition hook
|
|
24037
24064
|
if (this._any_transition_hook !== undefined) {
|
|
24038
24065
|
const outcome = abstract_hook_step(this._any_transition_hook, hook_args);
|
|
24039
24066
|
if (outcome.pass === false) {
|
|
24040
|
-
|
|
24067
|
+
this._fire_hook_rejection('any transition', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24041
24068
|
return false;
|
|
24042
24069
|
}
|
|
24043
|
-
|
|
24070
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24071
|
+
data_changed = true;
|
|
24072
|
+
}
|
|
24044
24073
|
}
|
|
24045
24074
|
// 4. exit hook
|
|
24046
24075
|
if (this._has_exit_hooks) {
|
|
24047
24076
|
const outcome = abstract_hook_step(this._exit_hooks.get(this._state), hook_args);
|
|
24048
24077
|
if (outcome.pass === false) {
|
|
24049
|
-
|
|
24078
|
+
this._fire_hook_rejection('exit', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24050
24079
|
return false;
|
|
24051
24080
|
}
|
|
24052
|
-
|
|
24081
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24082
|
+
data_changed = true;
|
|
24083
|
+
}
|
|
24053
24084
|
}
|
|
24054
24085
|
// 5. named transition / action hook
|
|
24055
24086
|
if (this._has_named_hooks) {
|
|
@@ -24061,10 +24092,12 @@ class Machine {
|
|
|
24061
24092
|
const nh = byAct === undefined ? undefined : byAct.get(newStateOrAction);
|
|
24062
24093
|
const outcome = abstract_hook_step(nh, hook_args);
|
|
24063
24094
|
if (outcome.pass === false) {
|
|
24064
|
-
|
|
24095
|
+
this._fire_hook_rejection('named', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24065
24096
|
return false;
|
|
24066
24097
|
}
|
|
24067
|
-
|
|
24098
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24099
|
+
data_changed = true;
|
|
24100
|
+
}
|
|
24068
24101
|
}
|
|
24069
24102
|
}
|
|
24070
24103
|
// 6. regular hook
|
|
@@ -24074,56 +24107,68 @@ class Machine {
|
|
|
24074
24107
|
const h = byTo === undefined ? undefined : byTo.get(newState);
|
|
24075
24108
|
const outcome = abstract_hook_step(h, hook_args);
|
|
24076
24109
|
if (outcome.pass === false) {
|
|
24077
|
-
|
|
24110
|
+
this._fire_hook_rejection('hook', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24078
24111
|
return false;
|
|
24079
24112
|
}
|
|
24080
|
-
|
|
24113
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24114
|
+
data_changed = true;
|
|
24115
|
+
}
|
|
24081
24116
|
}
|
|
24082
24117
|
// 7. edge type hook
|
|
24083
24118
|
// 7a. standard transition hook
|
|
24084
24119
|
if (trans_type === 'legal') {
|
|
24085
24120
|
const outcome = abstract_hook_step(this._standard_transition_hook, hook_args);
|
|
24086
24121
|
if (outcome.pass === false) {
|
|
24087
|
-
|
|
24122
|
+
this._fire_hook_rejection('standard transition', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24088
24123
|
return false;
|
|
24089
24124
|
}
|
|
24090
|
-
|
|
24125
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24126
|
+
data_changed = true;
|
|
24127
|
+
}
|
|
24091
24128
|
}
|
|
24092
24129
|
// 7b. main type hook
|
|
24093
24130
|
if (trans_type === 'main') {
|
|
24094
24131
|
const outcome = abstract_hook_step(this._main_transition_hook, hook_args);
|
|
24095
24132
|
if (outcome.pass === false) {
|
|
24096
|
-
|
|
24133
|
+
this._fire_hook_rejection('main transition', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24097
24134
|
return false;
|
|
24098
24135
|
}
|
|
24099
|
-
|
|
24136
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24137
|
+
data_changed = true;
|
|
24138
|
+
}
|
|
24100
24139
|
}
|
|
24101
24140
|
// 7c. forced transition hook
|
|
24102
24141
|
if (trans_type === 'forced') {
|
|
24103
24142
|
const outcome = abstract_hook_step(this._forced_transition_hook, hook_args);
|
|
24104
24143
|
if (outcome.pass === false) {
|
|
24105
|
-
|
|
24144
|
+
this._fire_hook_rejection('forced transition', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24106
24145
|
return false;
|
|
24107
24146
|
}
|
|
24108
|
-
|
|
24147
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24148
|
+
data_changed = true;
|
|
24149
|
+
}
|
|
24109
24150
|
}
|
|
24110
24151
|
// 8. entry hook
|
|
24111
24152
|
if (this._has_entry_hooks) {
|
|
24112
24153
|
const outcome = abstract_hook_step(this._entry_hooks.get(newState), hook_args);
|
|
24113
24154
|
if (outcome.pass === false) {
|
|
24114
|
-
|
|
24155
|
+
this._fire_hook_rejection('entry', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24115
24156
|
return false;
|
|
24116
24157
|
}
|
|
24117
|
-
|
|
24158
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24159
|
+
data_changed = true;
|
|
24160
|
+
}
|
|
24118
24161
|
}
|
|
24119
24162
|
// 9. everything hook (fires after all other pre-hooks)
|
|
24120
24163
|
if (this._everything_hook !== undefined) {
|
|
24121
24164
|
const outcome = abstract_everything_hook_step(this._everything_hook, Object.assign(Object.assign({}, hook_args), { hook_name: 'everything' }));
|
|
24122
24165
|
if (outcome.pass === false) {
|
|
24123
|
-
|
|
24166
|
+
this._fire_hook_rejection('everything', fromState, newState, fromAction, oldData, newData, wasForced);
|
|
24124
24167
|
return false;
|
|
24125
24168
|
}
|
|
24126
|
-
|
|
24169
|
+
if (_update_hook_fields(hook_args, outcome)) {
|
|
24170
|
+
data_changed = true;
|
|
24171
|
+
}
|
|
24127
24172
|
}
|
|
24128
24173
|
// all hooks passed! let's now establish the result
|
|
24129
24174
|
if (this._history_length) {
|
|
@@ -25049,6 +25094,46 @@ function is_hook_complex_result(hr) {
|
|
|
25049
25094
|
}
|
|
25050
25095
|
return false;
|
|
25051
25096
|
}
|
|
25097
|
+
/**
|
|
25098
|
+
*
|
|
25099
|
+
* Apply any data-field updates from a hook's complex result into `hook_args`,
|
|
25100
|
+
* and return whether data actually changed.
|
|
25101
|
+
*
|
|
25102
|
+
* This is the hoisted, allocation-free replacement for the `update_fields`
|
|
25103
|
+
* inner function that used to be re-created on every hooked transition inside
|
|
25104
|
+
* {@link Machine.transition_impl}. By moving it to module scope the function
|
|
25105
|
+
* object is allocated once at module load time.
|
|
25106
|
+
*
|
|
25107
|
+
* When the result does not carry a `data` property (the common case —
|
|
25108
|
+
* most hooks return `true` or `undefined`) the function returns `false`
|
|
25109
|
+
* immediately without touching `hook_args`.
|
|
25110
|
+
*
|
|
25111
|
+
* ```typescript
|
|
25112
|
+
* const args = { data: 'old', next_data: undefined, ... };
|
|
25113
|
+
* const changed = _update_hook_fields(args, { pass: true, data: 'new', next_data: undefined });
|
|
25114
|
+
* // changed === true, args.data === 'new'
|
|
25115
|
+
* ```
|
|
25116
|
+
*
|
|
25117
|
+
* @param hook_args The shared hook-argument object for the current
|
|
25118
|
+
* transition. Mutated in-place when the result carries `data`.
|
|
25119
|
+
* @param res The normalised complex result returned by
|
|
25120
|
+
* {@link abstract_hook_step} or {@link abstract_everything_hook_step}.
|
|
25121
|
+
*
|
|
25122
|
+
* @returns `true` if `res` contained a `data` property (i.e. the hook
|
|
25123
|
+
* mutated the machine's data); `false` otherwise.
|
|
25124
|
+
*
|
|
25125
|
+
* @see Machine.transition_impl
|
|
25126
|
+
* @see abstract_hook_step
|
|
25127
|
+
*
|
|
25128
|
+
*/
|
|
25129
|
+
function _update_hook_fields(hook_args, res) {
|
|
25130
|
+
if (Object.prototype.hasOwnProperty.call(res, 'data')) {
|
|
25131
|
+
hook_args.data = res.data;
|
|
25132
|
+
hook_args.next_data = res.next_data;
|
|
25133
|
+
return true;
|
|
25134
|
+
}
|
|
25135
|
+
return false;
|
|
25136
|
+
}
|
|
25052
25137
|
/**
|
|
25053
25138
|
*
|
|
25054
25139
|
* Invoke an optional transition/action hook and normalize its return value
|