jssm 5.157.18 → 5.158.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 +28 -7
- package/dist/cdn/instance.js +1 -1
- package/dist/cdn/viz.js +1 -1
- package/dist/cli/fsl-export-system-prompt.cjs +1 -1
- 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/README.md +28 -7
- package/dist/deno/fence.d.ts +18 -0
- package/dist/deno/fsl_fence_highlight.d.ts +53 -0
- package/dist/deno/fsl_fence_render.d.ts +87 -0
- package/dist/deno/fsl_gif.d.ts +77 -0
- package/dist/deno/fsl_svg_patch.d.ts +28 -0
- package/dist/deno/fsl_walk.d.ts +21 -0
- package/dist/deno/jssm.js +1 -1
- package/dist/fence/fence.js +49657 -0
- 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/dist/wc/editor.js +5 -1
- package/jssm.cli.d.cts +15 -6
- package/jssm.cli.d.ts +15 -6
- package/jssm.fence.d.ts +4084 -0
- package/package.json +9 -1
package/jssm.fence.d.ts
ADDED
|
@@ -0,0 +1,4084 @@
|
|
|
1
|
+
import { circular_buffer } from 'circular_buffer_js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The descriptor interpreter for the FSL Markdown fence convention: turns a
|
|
5
|
+
* parsed {@link FenceDescriptor} plus FSL source into static HTML, and walks
|
|
6
|
+
* a whole Markdown document replacing every `fsl`/`jssm` fence in place.
|
|
7
|
+
* This is the integration point for the five pieces built ahead of it — the
|
|
8
|
+
* fence-info parser, the viz pipeline, the rasterizer, the SVG fill
|
|
9
|
+
* extractor, and the editor-parity highlighter.
|
|
10
|
+
*
|
|
11
|
+
* @see notes/superpowers/specs/2026-06-23-fsl-markdown-fence-convention-design.md
|
|
12
|
+
*/
|
|
13
|
+
/** Options shared by the static fence renderers. */
|
|
14
|
+
interface FenceRenderOptions {
|
|
15
|
+
/** Inline state colors in code spans (default true). @see highlight_fsl_html */
|
|
16
|
+
inline_colors?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Render one FSL markdown fence to static HTML per the fence convention:
|
|
20
|
+
* parts stack top-down in the order written, sized by width/height, with
|
|
21
|
+
* editor-parity code highlighting whose state names carry the diagram's own
|
|
22
|
+
* node colors. Invalid FSL renders a visible error box — this function
|
|
23
|
+
* never throws for bad machine source.
|
|
24
|
+
*
|
|
25
|
+
* @param source - The FSL machine source (fence body).
|
|
26
|
+
* @param info - The fence info string (e.g. `'fsl image code width=300'`).
|
|
27
|
+
* @param opts.inline_colors - Whether code spans carry inline diagram colors (default true).
|
|
28
|
+
* @returns The rendered `<div class="fsl-fence">…</div>` markup.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* await render_fence_html('Red => Green => Red;', 'fsl');
|
|
32
|
+
* // '<div class="fsl-fence" …><svg…/svg><pre class="fsl-code">…</pre></div>'
|
|
33
|
+
*/
|
|
34
|
+
declare function render_fence_html(source: string, info: string, opts?: FenceRenderOptions): Promise<string>;
|
|
35
|
+
/**
|
|
36
|
+
* Replace every fsl/jssm fenced code block in a Markdown string with its
|
|
37
|
+
* rendered static HTML; all other content passes through byte-identical.
|
|
38
|
+
* Each fence is isolated — a broken machine becomes its own error box and
|
|
39
|
+
* the rest of the document still renders. Backtick fences of length ≥3
|
|
40
|
+
* are recognized; tilde fences are out of scope (v1, spec §9).
|
|
41
|
+
*
|
|
42
|
+
* @param markdown - The full Markdown document source.
|
|
43
|
+
* @param opts.inline_colors - Whether code spans carry inline diagram colors (default true).
|
|
44
|
+
* @returns The document with every `fsl`/`jssm` fence replaced by rendered HTML.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* await transform_markdown('# Doc\n\n```fsl\na -> b;\n```\n');
|
|
48
|
+
* // '# Doc\n\n<div class="fsl-fence">…</div>\n'
|
|
49
|
+
*/
|
|
50
|
+
declare function transform_markdown(markdown: string, opts?: FenceRenderOptions): Promise<string>;
|
|
51
|
+
/** Options for {@link render_fence_gif}. */
|
|
52
|
+
interface GifRenderOptions {
|
|
53
|
+
/** Per-frame delay, centiseconds. Default 70 (~0.7s). */
|
|
54
|
+
delay_cs?: number;
|
|
55
|
+
/** Netscape loop count; 0 = forever (default). */
|
|
56
|
+
loop?: number;
|
|
57
|
+
/** Walk-length ceiling; longer walks truncate. Default 64. */
|
|
58
|
+
max_frames?: number;
|
|
59
|
+
/** Raster zoom percentage; 100 = 3× natural (the CLI raster convention). Default 100. */
|
|
60
|
+
scale?: number;
|
|
61
|
+
/** Fill painted on the walked state each frame. Default '#ff9930'. */
|
|
62
|
+
highlight_fill?: string;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Render an FSL machine as a looping animated GIF that walks its states:
|
|
66
|
+
* main-path (`=>`) states in order when a main path exists, else an
|
|
67
|
+
* every-edge tour. Graphviz lays the machine out ONCE; each frame patches
|
|
68
|
+
* one state's fill in the SVG string and rasterizes — identical geometry
|
|
69
|
+
* across frames, no layout jitter.
|
|
70
|
+
*
|
|
71
|
+
* @param source - The FSL machine source.
|
|
72
|
+
* @param opts.delay_cs - Per-frame delay in centiseconds (default 70).
|
|
73
|
+
* @param opts.loop - Netscape loop count, 0 = forever (default 0).
|
|
74
|
+
* @param opts.max_frames - Walk-length ceiling; longer walks truncate (default 64).
|
|
75
|
+
* @param opts.scale - Raster zoom percentage, 100 = 3× natural size (default 100).
|
|
76
|
+
* @param opts.highlight_fill - Fill painted on the walked state (default '#ff9930').
|
|
77
|
+
* @returns The encoded GIF89a bytes.
|
|
78
|
+
*
|
|
79
|
+
* @throws {JssmError} on invalid FSL (programmatic callers want exceptions;
|
|
80
|
+
* the HTML renderers catch and box instead).
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* const gif = await render_fence_gif('Red => Green => Yellow => Red;');
|
|
84
|
+
* // Uint8Array starting "GIF89a", three frames, looping forever
|
|
85
|
+
*
|
|
86
|
+
* @see plan_walk
|
|
87
|
+
* @see encode_gif
|
|
88
|
+
*/
|
|
89
|
+
declare function render_fence_gif(source: string, opts?: GifRenderOptions): Promise<Uint8Array>;
|
|
90
|
+
|
|
91
|
+
/** Result of {@link quantize}: an RGB palette plus one palette index per input pixel. */
|
|
92
|
+
interface Quantized {
|
|
93
|
+
/** RGB triples, `3 · palette_count` bytes. */
|
|
94
|
+
palette: Uint8Array;
|
|
95
|
+
/** Number of colors actually used (≤ the requested maximum). */
|
|
96
|
+
palette_count: number;
|
|
97
|
+
/** One palette index per input pixel. */
|
|
98
|
+
indices: Uint8Array;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Reduce an RGBA8888 buffer to an indexed-color image with at most
|
|
102
|
+
* `max_colors` colors, for GIF encoding. Alpha is composited over white
|
|
103
|
+
* (GIF v1 output carries no transparency). When the input already has
|
|
104
|
+
* `max_colors` or fewer distinct colors they are preserved exactly;
|
|
105
|
+
* otherwise a median-cut partition supplies the palette and each pixel maps
|
|
106
|
+
* to its box's weighted-average color.
|
|
107
|
+
*
|
|
108
|
+
* @param rgba - Straight RGBA bytes; length must be a multiple of 4.
|
|
109
|
+
* @param max_colors - Palette ceiling, 2..256.
|
|
110
|
+
*
|
|
111
|
+
* @throws {JssmError} when `rgba.length` is not a multiple of 4.
|
|
112
|
+
* @throws {JssmError} when `max_colors` is outside 2..256 — above 256 the
|
|
113
|
+
* palette index no longer fits the `Uint8Array` indices this module packs
|
|
114
|
+
* into GIF codes (silent index corruption instead of a clear failure);
|
|
115
|
+
* below 2 there is no palette to quantize into.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* const q = quantize(new Uint8Array([255,0,0,255, 0,255,0,255]));
|
|
119
|
+
* q.palette_count; // 2
|
|
120
|
+
*/
|
|
121
|
+
declare function quantize(rgba: Uint8Array, max_colors?: number): Quantized;
|
|
122
|
+
/**
|
|
123
|
+
* GIF-variant LZW compression: emits a leading clear code, grows code width
|
|
124
|
+
* from `min_code_size + 1` up to the format's 12-bit ceiling, resets the
|
|
125
|
+
* dictionary when full, terminates with EOI, and packs codes LSB-first.
|
|
126
|
+
* Returns raw compressed bytes; the caller wraps them in GIF data sub-blocks.
|
|
127
|
+
*
|
|
128
|
+
* @param indices - Palette indices, each `< 2^min_code_size`.
|
|
129
|
+
* @param min_code_size - Bits needed for the palette (2..8 for GIF).
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* lzw_encode(new Uint8Array([0, 0, 1]), 2); // Uint8Array of packed codes
|
|
133
|
+
*/
|
|
134
|
+
declare function lzw_encode(indices: Uint8Array, min_code_size: number): Uint8Array;
|
|
135
|
+
/** One animation frame for {@link encode_gif}: straight RGBA8888 pixels. */
|
|
136
|
+
interface GifFrame {
|
|
137
|
+
rgba: Uint8Array;
|
|
138
|
+
width: number;
|
|
139
|
+
height: number;
|
|
140
|
+
}
|
|
141
|
+
/** Options for {@link encode_gif}. */
|
|
142
|
+
interface GifOptions {
|
|
143
|
+
/** Per-frame delay in centiseconds (GIF's native unit). Default 70 (~0.7s). */
|
|
144
|
+
delay_cs?: number;
|
|
145
|
+
/** Netscape loop count; 0 = loop forever (the default). */
|
|
146
|
+
loop?: number;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Encode RGBA frames as a looping animated GIF89a. A single global color
|
|
150
|
+
* table is quantized over the UNION of all frames' pixels (≤256 colors,
|
|
151
|
+
* median-cut when over); each frame then maps nearest-neighbor into that
|
|
152
|
+
* palette, so every frame is pixel-exact while the union stays within 256
|
|
153
|
+
* distinct colors. Frames must share dimensions. No transparency,
|
|
154
|
+
* full-frame disposal — simple and correct first.
|
|
155
|
+
*
|
|
156
|
+
* @param frames - At least one frame; all with identical width/height and
|
|
157
|
+
* `rgba.length === 4 · width · height`.
|
|
158
|
+
*
|
|
159
|
+
* @throws {JssmError} on zero frames, mismatched dimensions, or an rgba
|
|
160
|
+
* buffer whose length contradicts its stated dimensions.
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* const red = { rgba: new Uint8Array([255,0,0,255]), width: 1, height: 1 };
|
|
164
|
+
* const gif = encode_gif([red], { delay_cs: 50 });
|
|
165
|
+
* gif.slice(0, 6); // "GIF89a" bytes
|
|
166
|
+
*/
|
|
167
|
+
declare function encode_gif(frames: GifFrame[], opts?: GifOptions): Uint8Array;
|
|
168
|
+
|
|
169
|
+
declare type StateType$1 = string;
|
|
170
|
+
/**
|
|
171
|
+
* A color value accepted by jssm-viz for state and arrow styling. Currently
|
|
172
|
+
* any string, validated downstream by Graphviz / the named-colors list.
|
|
173
|
+
* Intended to be narrowed to `#RRGGBB` / `#RRGGBBAA` and CSS named colors
|
|
174
|
+
* in a future release.
|
|
175
|
+
*/
|
|
176
|
+
declare type JssmColor = string;
|
|
177
|
+
/**
|
|
178
|
+
* Three-state policy flag: `'required'`, `'disallowed'`, or `'optional'`.
|
|
179
|
+
* Used by machine configuration where a default-permissive middle ground
|
|
180
|
+
* is meaningful (for example, the `actions` config key).
|
|
181
|
+
*/
|
|
182
|
+
declare type JssmPermittedOpt = 'required' | 'disallowed' | 'optional';
|
|
183
|
+
/**
|
|
184
|
+
* The set of ASCII arrow tokens recognized by the FSL grammar. Each arrow
|
|
185
|
+
* encodes a direction (one-way left/right, or two-way) and a "kind" for
|
|
186
|
+
* each direction (`-` legal, `=` main path, `~` forced-only). See the
|
|
187
|
+
* Language Reference docs for the full semantic table.
|
|
188
|
+
*/
|
|
189
|
+
declare type JssmArrow = '->' | '<-' | '<->' | '<=->' | '<~->' | '=>' | '<=' | '<=>' | '<-=>' | '<~=>' | '~>' | '<~' | '<~>' | '<-~>' | '<=~>';
|
|
190
|
+
/**
|
|
191
|
+
* A type teaching Typescript the various supported shapes for nodes, mostly inherited from GraphViz
|
|
192
|
+
*/
|
|
193
|
+
declare type JssmShape = "box" | "polygon" | "ellipse" | "oval" | "circle" | "point" | "egg" | "triangle" | "plaintext" | "plain" | "diamond" | "trapezium" | "parallelogram" | "house" | "pentagon" | "hexagon" | "septagon" | "octagon" | "doublecircle" | "doubleoctagon" | "tripleoctagon" | "invtriangle" | "invtrapezium" | "invhouse" | "Mdiamond" | "Msquare" | "Mcircle" | "rect" | "rectangle" | "square" | "star" | "none" | "underline" | "cylinder" | "note" | "tab" | "folder" | "box3d" | "component" | "promoter" | "cds" | "terminator" | "utr" | "primersite" | "restrictionsite" | "fivepoverhang" | "threepoverhang" | "noverhang" | "assembly" | "signature" | "insulator" | "ribosite" | "rnastab" | "proteasesite" | "proteinstab" | "rpromoter" | "rarrow" | "larrow" | "lpromoter" | "record";
|
|
194
|
+
/**
|
|
195
|
+
* Semantic category of an arrow's transition. `'legal'` is a normal
|
|
196
|
+
* transition, `'main'` is part of the machine's primary path, `'forced'`
|
|
197
|
+
* may only be taken via {@link Machine.force_transition}, and `'none'`
|
|
198
|
+
* means no transition exists in that direction.
|
|
199
|
+
*/
|
|
200
|
+
declare type JssmArrowKind = 'none' | 'legal' | 'main' | 'forced';
|
|
201
|
+
/**
|
|
202
|
+
* Graphviz layout engine selector. Controls how jssm-viz lays out the
|
|
203
|
+
* rendered diagram; `'dot'` is the default and most useful for state
|
|
204
|
+
* machines. See the Graphviz documentation for the differences.
|
|
205
|
+
*/
|
|
206
|
+
declare type JssmLayout = 'dot' | 'circo' | 'twopi' | 'fdp' | 'neato';
|
|
207
|
+
declare type JssmCorner = 'regular' | 'rounded' | 'lined';
|
|
208
|
+
declare type JssmLineStyle = 'solid' | 'dashed' | 'dotted';
|
|
209
|
+
/**
|
|
210
|
+
* Tristate flag for whether a property may be overridden at runtime.
|
|
211
|
+
* `true` permits overrides, `false` forbids them, and `undefined` defers
|
|
212
|
+
* the decision to the surrounding configuration's default.
|
|
213
|
+
*/
|
|
214
|
+
declare type JssmAllowsOverride = true | false | undefined;
|
|
215
|
+
/**
|
|
216
|
+
* Controls whether the state graph may contain disconnected components
|
|
217
|
+
* (islands). `true` permits islands (default), `false` requires a single
|
|
218
|
+
* connected component, and `'with_start'` permits islands only when every
|
|
219
|
+
* component contains at least one start state.
|
|
220
|
+
*/
|
|
221
|
+
declare type JssmAllowIslands = true | false | 'with_start';
|
|
222
|
+
/**
|
|
223
|
+
* Structured render-size hint for a machine visualization, set by the FSL
|
|
224
|
+
* `default_size` directive. All three forms are optional in the sense that
|
|
225
|
+
* only one or two fields will be present depending on the form used:
|
|
226
|
+
*
|
|
227
|
+
* - `{ width }` — single-number form (`default_size: 800;`)
|
|
228
|
+
* - `{ width, height }` — bounding-box form (`default_size: 800 600;`)
|
|
229
|
+
* - `{ height }` — height-only form (`default_size: height 600;`)
|
|
230
|
+
*
|
|
231
|
+
* This is a *hint*, not a hard constraint. Renderers may ignore it.
|
|
232
|
+
*
|
|
233
|
+
* @see Machine.default_size
|
|
234
|
+
*/
|
|
235
|
+
declare type JssmDefaultSize = {
|
|
236
|
+
width?: number;
|
|
237
|
+
height?: number;
|
|
238
|
+
};
|
|
239
|
+
/**
|
|
240
|
+
* Runtime-iterable list of valid `flow` directions for FSL diagrams.
|
|
241
|
+
* Use this when you need to enumerate directions; for the type itself
|
|
242
|
+
* see {@link FslDirection}.
|
|
243
|
+
*/
|
|
244
|
+
declare const FslDirections: readonly ["up", "right", "down", "left"];
|
|
245
|
+
/**
|
|
246
|
+
* String literal type of the four supported FSL flow directions. This is
|
|
247
|
+
* the type of the `flow` config key on a machine.
|
|
248
|
+
*/
|
|
249
|
+
declare type FslDirection = typeof FslDirections[number];
|
|
250
|
+
/**
|
|
251
|
+
* Runtime-iterable list of the built-in theme names that ship with jssm-viz.
|
|
252
|
+
* Use this when you need to enumerate themes; for the type itself see
|
|
253
|
+
* {@link FslTheme}.
|
|
254
|
+
*/
|
|
255
|
+
declare const FslThemes: readonly ["default", "ocean", "modern", "plain", "bold"];
|
|
256
|
+
/**
|
|
257
|
+
* String literal type of the built-in theme names. This is the element
|
|
258
|
+
* type of the `theme` config key (which accepts an array so that themes
|
|
259
|
+
* can be layered).
|
|
260
|
+
*/
|
|
261
|
+
declare type FslTheme = typeof FslThemes[number];
|
|
262
|
+
/**
|
|
263
|
+
* Persistable snapshot of a Machine produced by {@link Machine.serialize}
|
|
264
|
+
* and consumed by {@link deserialize}. Carries the current state, the
|
|
265
|
+
* associated machine data, the recent history (subject to the configured
|
|
266
|
+
* capacity), and metadata to detect version-skew on rehydration.
|
|
267
|
+
*
|
|
268
|
+
* @typeParam DataType - The type of the user-supplied data payload (`mDT`).
|
|
269
|
+
*/
|
|
270
|
+
declare type JssmSerialization<DataType> = {
|
|
271
|
+
jssm_version: string;
|
|
272
|
+
timestamp: number;
|
|
273
|
+
comment?: string | undefined;
|
|
274
|
+
state: StateType$1;
|
|
275
|
+
history: [string, DataType][];
|
|
276
|
+
history_capacity: number;
|
|
277
|
+
data: DataType;
|
|
278
|
+
};
|
|
279
|
+
/**
|
|
280
|
+
* One ordered member of a named group's membership list. A `'state'`
|
|
281
|
+
* member is an ordinary state (`a` inside `&g : [a]`). A `'group'` member
|
|
282
|
+
* references another group: `mode: 'nest'` is the `&child` form, which
|
|
283
|
+
* preserves the child group's identity for later precedence/viz, while
|
|
284
|
+
* `mode: 'spread'` is the `...&child` form, which inlines the child's
|
|
285
|
+
* members and erases that identity. Both modes resolve to the same flat
|
|
286
|
+
* set of states via {@link JssmGroupRegistry} resolution; only their
|
|
287
|
+
* structural bookkeeping differs.
|
|
288
|
+
*
|
|
289
|
+
* ```typescript
|
|
290
|
+
* // `&outer : [&inner x];` direct members:
|
|
291
|
+
* // [ { kind: 'group', name: 'inner', mode: 'nest' },
|
|
292
|
+
* // { kind: 'state', name: 'x' } ]
|
|
293
|
+
* ```
|
|
294
|
+
*
|
|
295
|
+
* @see JssmGroupRef
|
|
296
|
+
* @see JssmGroupRegistry
|
|
297
|
+
*/
|
|
298
|
+
declare type JssmGroupMemberRef = {
|
|
299
|
+
kind: 'state';
|
|
300
|
+
name: string;
|
|
301
|
+
} | {
|
|
302
|
+
kind: 'group';
|
|
303
|
+
name: string;
|
|
304
|
+
mode: 'nest' | 'spread';
|
|
305
|
+
};
|
|
306
|
+
/**
|
|
307
|
+
* The compiled group table: maps each declared group name to its
|
|
308
|
+
* **ordered, direct** members (a {@link JssmGroupMemberRef} list). Order
|
|
309
|
+
* is meaningful — it carries declaration/iteration/precedence order — so
|
|
310
|
+
* this is always an array-valued `Map`, never a `Set`. Only direct
|
|
311
|
+
* members are stored; transitive (flattened) membership is resolved
|
|
312
|
+
* lazily so the group→group graph survives for viz and precedence.
|
|
313
|
+
*
|
|
314
|
+
* ```typescript
|
|
315
|
+
* // for `&inner : [a b]; &outer : [&inner c];`
|
|
316
|
+
* // registry.get('inner') === [ { kind:'state', name:'a' },
|
|
317
|
+
* // { kind:'state', name:'b' } ]
|
|
318
|
+
* // registry.get('outer') === [ { kind:'group', name:'inner', mode:'nest' },
|
|
319
|
+
* // { kind:'state', name:'c' } ]
|
|
320
|
+
* ```
|
|
321
|
+
*
|
|
322
|
+
* @see JssmGroupMemberRef
|
|
323
|
+
*/
|
|
324
|
+
declare type JssmGroupRegistry = Map<string, JssmGroupMemberRef[]>;
|
|
325
|
+
/**
|
|
326
|
+
* The compiled boundary-hook surface for a single subject (a group or a
|
|
327
|
+
* state): the action to run on entry (`onEnter`) and/or on exit (`onExit`).
|
|
328
|
+
* Each is optional so a subject may declare only one direction; the compiler
|
|
329
|
+
* merges an `enter` and an `exit` declaration for the same subject into one
|
|
330
|
+
* of these.
|
|
331
|
+
*
|
|
332
|
+
* @see JssmHookDeclaration
|
|
333
|
+
*/
|
|
334
|
+
declare type JssmBoundaryHooks = {
|
|
335
|
+
onEnter?: string;
|
|
336
|
+
onExit?: string;
|
|
337
|
+
};
|
|
338
|
+
/**
|
|
339
|
+
* Maps each group name that has at least one boundary hook to its merged
|
|
340
|
+
* {@link JssmBoundaryHooks}. Carried on {@link JssmGenericConfig} for the
|
|
341
|
+
* runtime to consume; depth-aware firing is a later task.
|
|
342
|
+
*
|
|
343
|
+
* @see JssmHookDeclaration
|
|
344
|
+
*/
|
|
345
|
+
declare type JssmGroupHooks = Map<string, JssmBoundaryHooks>;
|
|
346
|
+
/**
|
|
347
|
+
* Maps each plain state name that has at least one boundary hook to its
|
|
348
|
+
* merged {@link JssmBoundaryHooks}. The state-subject analogue of
|
|
349
|
+
* {@link JssmGroupHooks}.
|
|
350
|
+
*
|
|
351
|
+
* @see JssmHookDeclaration
|
|
352
|
+
*/
|
|
353
|
+
declare type JssmStateHooks = Map<string, JssmBoundaryHooks>;
|
|
354
|
+
/**
|
|
355
|
+
* Declaration of a named property that a machine's states may carry.
|
|
356
|
+
* Set `required: true` to force every state to define the property, or
|
|
357
|
+
* provide `default_value` to fall back when the state does not specify it.
|
|
358
|
+
*
|
|
359
|
+
* For state-property *bindings* (the `state_property` config list), the
|
|
360
|
+
* compiler also writes `property` and `state` — the unserialized pair behind
|
|
361
|
+
* the serialized `name` — so the Machine constructor can validate bindings
|
|
362
|
+
* without parsing `name` back apart. Both are optional: hand-built configs
|
|
363
|
+
* may carry only the serialized `name`, and global property definitions
|
|
364
|
+
* never set them.
|
|
365
|
+
*/
|
|
366
|
+
declare type JssmPropertyDefinition = {
|
|
367
|
+
name: string;
|
|
368
|
+
default_value?: any;
|
|
369
|
+
required?: boolean;
|
|
370
|
+
property?: string;
|
|
371
|
+
state?: string;
|
|
372
|
+
};
|
|
373
|
+
declare type JssmTransitionPermitter<DataType> = (OldState: StateType$1, NewState: StateType$1, OldData: DataType, NewData: DataType) => boolean;
|
|
374
|
+
declare type JssmTransitionPermitterMaybeArray<DataType> = JssmTransitionPermitter<DataType> | Array<JssmTransitionPermitter<DataType>>;
|
|
375
|
+
/**
|
|
376
|
+
* A single directed transition (edge) within a state machine. Captures
|
|
377
|
+
* both the topology (`from` / `to`), the FSL semantics (`kind`,
|
|
378
|
+
* `forced_only`, `main_path`), and any optional metadata such as a
|
|
379
|
+
* per-edge `name`, an action label, a guard `check`, a transition
|
|
380
|
+
* `probability` for stochastic models, and an `after_time` for timed
|
|
381
|
+
* transitions.
|
|
382
|
+
*
|
|
383
|
+
* @typeParam StateType - The state-name type (usually `string`).
|
|
384
|
+
* @typeParam DataType - The machine's data payload type (`mDT`).
|
|
385
|
+
*/
|
|
386
|
+
declare type JssmTransition<StateType, DataType> = {
|
|
387
|
+
from: StateType;
|
|
388
|
+
to: StateType;
|
|
389
|
+
after_time?: number;
|
|
390
|
+
se?: JssmCompileSe<StateType, DataType>;
|
|
391
|
+
name?: StateType;
|
|
392
|
+
action?: StateType;
|
|
393
|
+
check?: JssmTransitionPermitterMaybeArray<DataType>;
|
|
394
|
+
probability?: number;
|
|
395
|
+
kind: JssmArrowKind;
|
|
396
|
+
forced_only: boolean;
|
|
397
|
+
main_path: boolean;
|
|
398
|
+
};
|
|
399
|
+
/** A list of {@link JssmTransition}s — the edge set of a machine. */
|
|
400
|
+
declare type JssmTransitions<StateType, DataType> = JssmTransition<StateType, DataType>[];
|
|
401
|
+
/**
|
|
402
|
+
* The set of states that can immediately precede or follow a given state.
|
|
403
|
+
* Returned by jssm helpers that report a state's connectivity in the graph.
|
|
404
|
+
*/
|
|
405
|
+
declare type JssmTransitionList = {
|
|
406
|
+
entrances: Array<StateType$1>;
|
|
407
|
+
exits: Array<StateType$1>;
|
|
408
|
+
};
|
|
409
|
+
/**
|
|
410
|
+
* Topology record for one node in a compiled machine: its name, the set of
|
|
411
|
+
* states it can be reached from, the set of states it can transition to,
|
|
412
|
+
* and whether reaching it constitutes "completing" the machine.
|
|
413
|
+
*/
|
|
414
|
+
declare type JssmGenericState = {
|
|
415
|
+
from: Array<StateType$1>;
|
|
416
|
+
name: StateType$1;
|
|
417
|
+
to: Array<StateType$1>;
|
|
418
|
+
complete: boolean;
|
|
419
|
+
};
|
|
420
|
+
/**
|
|
421
|
+
* The full internal bookkeeping snapshot of a {@link Machine}, exposed for
|
|
422
|
+
* advanced introspection. Contains the current state, the state map, the
|
|
423
|
+
* edge map and reverse-action map, and the original edge list. The
|
|
424
|
+
* `internal_state_impl_version` field exists so that consumers can detect
|
|
425
|
+
* shape changes if this representation evolves.
|
|
426
|
+
*/
|
|
427
|
+
declare type JssmMachineInternalState<DataType> = {
|
|
428
|
+
internal_state_impl_version: 1;
|
|
429
|
+
state: StateType$1;
|
|
430
|
+
states: Map<StateType$1, JssmGenericState>;
|
|
431
|
+
named_transitions: Map<StateType$1, number>;
|
|
432
|
+
edge_map: Map<StateType$1, Map<StateType$1, number>>;
|
|
433
|
+
actions: Map<StateType$1, Map<StateType$1, number>>;
|
|
434
|
+
reverse_actions: Map<StateType$1, Map<StateType$1, number>>;
|
|
435
|
+
edges: Array<JssmTransition<StateType$1, DataType>>;
|
|
436
|
+
};
|
|
437
|
+
declare type JssmStatePermitter<DataType> = (OldState: StateType$1, NewState: StateType$1, OldData: DataType, NewData: DataType) => boolean;
|
|
438
|
+
declare type JssmStatePermitterMaybeArray<DataType> = JssmStatePermitter<DataType> | Array<JssmStatePermitter<DataType>>;
|
|
439
|
+
/**
|
|
440
|
+
* A source span produced by the FSL parser when `parse(input, { locations:
|
|
441
|
+
* true })` is used. Mirrors PEG.js's native `location()` shape: byte
|
|
442
|
+
* `offset`s (0-based, half-open) plus 1-based `line`/`column` for display.
|
|
443
|
+
*
|
|
444
|
+
* ```typescript
|
|
445
|
+
* const [t] = parse('a -> b;', { locations: true });
|
|
446
|
+
* // t.loc === { start: { offset: 0, line: 1, column: 1 },
|
|
447
|
+
* // end: { offset: 7, line: 1, column: 8 } }
|
|
448
|
+
* ```
|
|
449
|
+
*/
|
|
450
|
+
declare type FslSourcePoint = {
|
|
451
|
+
offset: number;
|
|
452
|
+
line: number;
|
|
453
|
+
column: number;
|
|
454
|
+
};
|
|
455
|
+
declare type FslSourceLocation = {
|
|
456
|
+
start: FslSourcePoint;
|
|
457
|
+
end: FslSourcePoint;
|
|
458
|
+
};
|
|
459
|
+
/**
|
|
460
|
+
* A single key/value pair from an FSL `state X: { ... };` block, in the
|
|
461
|
+
* raw form produced by the parser before being condensed into a
|
|
462
|
+
* {@link JssmStateDeclaration}.
|
|
463
|
+
*/
|
|
464
|
+
declare type JssmStateDeclarationRule = {
|
|
465
|
+
key: string;
|
|
466
|
+
value: any;
|
|
467
|
+
name?: string;
|
|
468
|
+
loc?: FslSourceLocation;
|
|
469
|
+
value_loc?: FslSourceLocation;
|
|
470
|
+
};
|
|
471
|
+
/**
|
|
472
|
+
* The fully-condensed declaration for a single state, including its raw
|
|
473
|
+
* rule list (`declarations`) and the well-known styling fields jssm-viz
|
|
474
|
+
* understands. Returned by {@link Machine.state_declaration}.
|
|
475
|
+
*/
|
|
476
|
+
declare type JssmStateDeclaration = {
|
|
477
|
+
declarations: Array<JssmStateDeclarationRule>;
|
|
478
|
+
shape?: JssmShape;
|
|
479
|
+
color?: JssmColor;
|
|
480
|
+
corners?: JssmCorner;
|
|
481
|
+
lineStyle?: JssmLineStyle;
|
|
482
|
+
stateLabel?: string;
|
|
483
|
+
textColor?: JssmColor;
|
|
484
|
+
backgroundColor?: JssmColor;
|
|
485
|
+
borderColor?: JssmColor;
|
|
486
|
+
image?: string;
|
|
487
|
+
url?: string;
|
|
488
|
+
state: StateType$1;
|
|
489
|
+
property?: {
|
|
490
|
+
name: string;
|
|
491
|
+
value: unknown;
|
|
492
|
+
};
|
|
493
|
+
};
|
|
494
|
+
/**
|
|
495
|
+
* A loosened version of {@link JssmStateDeclaration} where every field is
|
|
496
|
+
* optional. Used as the value type for theme entries and for default
|
|
497
|
+
* state configuration where most fields will be inherited or merged.
|
|
498
|
+
*/
|
|
499
|
+
declare type JssmStateConfig = Partial<JssmStateDeclaration>;
|
|
500
|
+
declare type JssmStateStyleShape = {
|
|
501
|
+
key: 'shape';
|
|
502
|
+
value: JssmShape;
|
|
503
|
+
};
|
|
504
|
+
declare type JssmStateStyleColor = {
|
|
505
|
+
key: 'color';
|
|
506
|
+
value: JssmColor;
|
|
507
|
+
};
|
|
508
|
+
declare type JssmStateStyleTextColor = {
|
|
509
|
+
key: 'text-color';
|
|
510
|
+
value: JssmColor;
|
|
511
|
+
};
|
|
512
|
+
declare type JssmStateStyleCorners = {
|
|
513
|
+
key: 'corners';
|
|
514
|
+
value: JssmCorner;
|
|
515
|
+
};
|
|
516
|
+
declare type JssmStateStyleLineStyle = {
|
|
517
|
+
key: 'line-style';
|
|
518
|
+
value: JssmLineStyle;
|
|
519
|
+
};
|
|
520
|
+
declare type JssmStateStyleStateLabel = {
|
|
521
|
+
key: 'state-label';
|
|
522
|
+
value: string;
|
|
523
|
+
};
|
|
524
|
+
declare type JssmStateStyleBackgroundColor = {
|
|
525
|
+
key: 'background-color';
|
|
526
|
+
value: JssmColor;
|
|
527
|
+
};
|
|
528
|
+
declare type JssmStateStyleBorderColor = {
|
|
529
|
+
key: 'border-color';
|
|
530
|
+
value: JssmColor;
|
|
531
|
+
};
|
|
532
|
+
declare type JssmStateStyleImage = {
|
|
533
|
+
key: 'image';
|
|
534
|
+
value: string;
|
|
535
|
+
};
|
|
536
|
+
declare type JssmStateStyleUrl = {
|
|
537
|
+
key: 'url';
|
|
538
|
+
value: string;
|
|
539
|
+
};
|
|
540
|
+
/**
|
|
541
|
+
* Tagged union of all individual style key/value pairs that may appear in
|
|
542
|
+
* a state's style configuration. The `key` discriminator selects which
|
|
543
|
+
* member, and the `value` is typed accordingly.
|
|
544
|
+
*/
|
|
545
|
+
declare type JssmStateStyleKey = JssmStateStyleShape | JssmStateStyleColor | JssmStateStyleTextColor | JssmStateStyleCorners | JssmStateStyleLineStyle | JssmStateStyleBackgroundColor | JssmStateStyleStateLabel | JssmStateStyleBorderColor | JssmStateStyleImage | JssmStateStyleUrl;
|
|
546
|
+
/**
|
|
547
|
+
* An ordered list of {@link JssmStateStyleKey} entries. Used by the
|
|
548
|
+
* `default_*_state_config` machine config options to provide a fallback
|
|
549
|
+
* style stack.
|
|
550
|
+
*/
|
|
551
|
+
declare type JssmStateStyleKeyList = JssmStateStyleKey[];
|
|
552
|
+
/**
|
|
553
|
+
* The graph-wide default edge colour style item, produced by the
|
|
554
|
+
* `edge-color`/`edge_color` line inside a `transition: {}` (or `graph: {}`)
|
|
555
|
+
* config block. Kept distinct from {@link JssmStateStyleColor} because it
|
|
556
|
+
* applies to edges rather than nodes, and because it carries the legacy
|
|
557
|
+
* `graph_default_edge_color` key the grammar emits.
|
|
558
|
+
*/
|
|
559
|
+
declare type JssmGraphDefaultEdgeColor = {
|
|
560
|
+
key: 'graph_default_edge_color';
|
|
561
|
+
value: JssmColor;
|
|
562
|
+
};
|
|
563
|
+
/**
|
|
564
|
+
* A single item inside a `transition: {}` default-config block. For v1 this
|
|
565
|
+
* reuses the per-state style items (so `color: red;` works inside a
|
|
566
|
+
* `transition:` block exactly as inside a `state:` block) plus the
|
|
567
|
+
* edge-scoped {@link JssmGraphDefaultEdgeColor} default.
|
|
568
|
+
*
|
|
569
|
+
* @see JssmTransitionConfig
|
|
570
|
+
*/
|
|
571
|
+
declare type JssmTransitionStyleKey = JssmStateStyleKey | JssmGraphDefaultEdgeColor;
|
|
572
|
+
/**
|
|
573
|
+
* The compiled value of a `transition: {}` config block: an ordered list of
|
|
574
|
+
* edge-default style items. V1 mirrors the state-style shape used by
|
|
575
|
+
* `default_state_config`; group machinery that consumes it lands in a later
|
|
576
|
+
* task.
|
|
577
|
+
*
|
|
578
|
+
* ```typescript
|
|
579
|
+
* import { compile, parse } from 'jssm';
|
|
580
|
+
* const cfg = compile(parse('a -> b; transition: { color: red; };'));
|
|
581
|
+
* // cfg.default_transition_config === [ { key: 'color', value: '#ff0000ff' } ]
|
|
582
|
+
* ```
|
|
583
|
+
*
|
|
584
|
+
* @see JssmGraphConfig
|
|
585
|
+
*/
|
|
586
|
+
declare type JssmTransitionConfig = JssmTransitionStyleKey[];
|
|
587
|
+
/**
|
|
588
|
+
* Graph-scope default-config style items folded from the deprecated
|
|
589
|
+
* top-level graph keywords (`graph_layout`, `graph_bg_color`,
|
|
590
|
+
* `dot_preamble`, `theme`, `flow`, and the `edge-color`/`edge_color`
|
|
591
|
+
* default) into the consolidated `graph: {}` config. Each carries the
|
|
592
|
+
* legacy parse key so downstream consumers can disambiguate.
|
|
593
|
+
*/
|
|
594
|
+
declare type JssmGraphAliasKey = {
|
|
595
|
+
key: 'graph_layout';
|
|
596
|
+
value: JssmLayout;
|
|
597
|
+
} | {
|
|
598
|
+
key: 'graph_bg_color';
|
|
599
|
+
value: JssmColor;
|
|
600
|
+
} | {
|
|
601
|
+
key: 'dot_preamble';
|
|
602
|
+
value: string;
|
|
603
|
+
} | {
|
|
604
|
+
key: 'theme';
|
|
605
|
+
value: FslTheme | FslTheme[];
|
|
606
|
+
} | {
|
|
607
|
+
key: 'flow';
|
|
608
|
+
value: FslDirection;
|
|
609
|
+
} | JssmGraphDefaultEdgeColor;
|
|
610
|
+
/**
|
|
611
|
+
* A single item inside a `graph: {}` default-config block. For v1 this
|
|
612
|
+
* reuses the per-state style items plus the graph-scope alias items
|
|
613
|
+
* ({@link JssmGraphAliasKey}) folded in from the deprecated top-level
|
|
614
|
+
* graph keywords.
|
|
615
|
+
*
|
|
616
|
+
* @see JssmGraphConfig
|
|
617
|
+
*/
|
|
618
|
+
declare type JssmGraphStyleKey = JssmStateStyleKey | JssmGraphAliasKey;
|
|
619
|
+
/**
|
|
620
|
+
* The compiled value of a `graph: {}` config block: an ordered list of
|
|
621
|
+
* graph-default style items. The compiler folds the deprecated top-level
|
|
622
|
+
* graph keywords into this list first, then lets an explicit `graph: {}`
|
|
623
|
+
* block override on key conflict.
|
|
624
|
+
*
|
|
625
|
+
* ```typescript
|
|
626
|
+
* import { compile, parse } from 'jssm';
|
|
627
|
+
* const cfg = compile(parse('a -> b; graph_bg_color: #ffffff;'));
|
|
628
|
+
* // the compiler canonicalizes the folded `graph_bg_color` alias to a
|
|
629
|
+
* // `background-color` item, so:
|
|
630
|
+
* // cfg.default_graph_config includes { key: 'background-color', value: '#ffffffff' }
|
|
631
|
+
* ```
|
|
632
|
+
*
|
|
633
|
+
* @see JssmTransitionConfig
|
|
634
|
+
*/
|
|
635
|
+
declare type JssmGraphConfig = JssmGraphStyleKey[];
|
|
636
|
+
/**
|
|
637
|
+
* Complete shape of a jssm-viz theme. A theme provides a style block for
|
|
638
|
+
* each kind of state (`state`, `hooked`, `start`, `end`, `terminal`) as
|
|
639
|
+
* well as a matching `active_*` variant used while that state is current.
|
|
640
|
+
*
|
|
641
|
+
* The `graph`, `legal`, `main`, `forced`, `action`, and `title` slots are
|
|
642
|
+
* reserved for future use and currently typed as `undefined`.
|
|
643
|
+
*
|
|
644
|
+
* Most user-defined themes should be typed as {@link JssmTheme} (the
|
|
645
|
+
* `Partial` of this) so that omitted fields fall back to the base theme.
|
|
646
|
+
*/
|
|
647
|
+
declare type JssmBaseTheme = {
|
|
648
|
+
name: string;
|
|
649
|
+
state: JssmStateConfig;
|
|
650
|
+
hooked: JssmStateConfig;
|
|
651
|
+
start: JssmStateConfig;
|
|
652
|
+
end: JssmStateConfig;
|
|
653
|
+
terminal: JssmStateConfig;
|
|
654
|
+
active: JssmStateConfig;
|
|
655
|
+
active_hooked: JssmStateConfig;
|
|
656
|
+
active_start: JssmStateConfig;
|
|
657
|
+
active_end: JssmStateConfig;
|
|
658
|
+
active_terminal: JssmStateConfig;
|
|
659
|
+
graph: undefined;
|
|
660
|
+
legal: undefined;
|
|
661
|
+
main: undefined;
|
|
662
|
+
forced: undefined;
|
|
663
|
+
action: undefined;
|
|
664
|
+
title: undefined;
|
|
665
|
+
};
|
|
666
|
+
/**
|
|
667
|
+
* Full configuration object accepted by the {@link Machine} constructor and
|
|
668
|
+
* by {@link from}. Carries the transition list and the optional knobs
|
|
669
|
+
* governing layout, theming, history, start/end states, property
|
|
670
|
+
* definitions, machine metadata (author, license, version, ...) and the
|
|
671
|
+
* runtime hook surfaces (`time_source`, `timeout_source`, ...).
|
|
672
|
+
*
|
|
673
|
+
* Most users never construct one of these directly — the `sm` tagged
|
|
674
|
+
* template literal and {@link from} produce one from FSL source.
|
|
675
|
+
*
|
|
676
|
+
* @typeParam StateType - The state-name type (usually `string`).
|
|
677
|
+
* @typeParam DataType - The user-supplied data payload type (`mDT`).
|
|
678
|
+
*/
|
|
679
|
+
/**
|
|
680
|
+
* Editor/panel defaults an FSL machine declares in an `editor: {}` block
|
|
681
|
+
* (fsl#1334), read by the all-widgets web control: a stochastic run-count
|
|
682
|
+
* and the panels the machine requests under `request` panel mode.
|
|
683
|
+
*/
|
|
684
|
+
declare type JssmEditorConfig = {
|
|
685
|
+
stochastic_run_count?: number;
|
|
686
|
+
panels?: Array<string>;
|
|
687
|
+
};
|
|
688
|
+
/** Which stochastic view a run batch produces. */
|
|
689
|
+
declare type JssmStochasticMode = 'montecarlo' | 'steady_state';
|
|
690
|
+
/** Options for {@link Machine.stochastic_summary} / {@link Machine.stochastic_runs}. */
|
|
691
|
+
declare type JssmStochasticOptions = {
|
|
692
|
+
mode?: JssmStochasticMode;
|
|
693
|
+
runs?: number;
|
|
694
|
+
max_steps?: number;
|
|
695
|
+
seed?: number;
|
|
696
|
+
};
|
|
697
|
+
/** One walk's result, yielded by {@link Machine.stochastic_runs}. */
|
|
698
|
+
declare type JssmStochasticRun = {
|
|
699
|
+
states: Array<string>;
|
|
700
|
+
edges: Array<string>;
|
|
701
|
+
length: number;
|
|
702
|
+
terminated: boolean;
|
|
703
|
+
};
|
|
704
|
+
/** Aggregate statistics over a stochastic run batch. */
|
|
705
|
+
declare type JssmStochasticSummary = {
|
|
706
|
+
mode: JssmStochasticMode;
|
|
707
|
+
runs: number;
|
|
708
|
+
seed: number;
|
|
709
|
+
state_visits: Map<string, number>;
|
|
710
|
+
state_visit_fraction: Map<string, number>;
|
|
711
|
+
edge_traversals: Map<string, number>;
|
|
712
|
+
path_lengths?: Array<number>;
|
|
713
|
+
terminal_reached?: number;
|
|
714
|
+
capped?: number;
|
|
715
|
+
};
|
|
716
|
+
declare type JssmGenericConfig<StateType, DataType> = {
|
|
717
|
+
graph_layout?: JssmLayout;
|
|
718
|
+
complete?: Array<StateType>;
|
|
719
|
+
transitions: JssmTransitions<StateType, DataType>;
|
|
720
|
+
theme?: FslTheme[];
|
|
721
|
+
flow?: FslDirection;
|
|
722
|
+
name?: string;
|
|
723
|
+
data?: DataType;
|
|
724
|
+
nodes?: Array<StateType>;
|
|
725
|
+
check?: JssmStatePermitterMaybeArray<DataType>;
|
|
726
|
+
history?: number;
|
|
727
|
+
/**
|
|
728
|
+
* Maximum depth of the boundary-hook action cascade before the machine
|
|
729
|
+
* throws a {@link JssmError} rather than risking a stack overflow or hang.
|
|
730
|
+
*
|
|
731
|
+
* Each time a boundary action fires a transition that itself crosses a
|
|
732
|
+
* boundary, the depth counter increments. A cascade exceeding this limit is
|
|
733
|
+
* treated as a probable infinite loop and rejected.
|
|
734
|
+
*
|
|
735
|
+
* Defaults to `100`. Raise it for legitimate pipelines that genuinely nest
|
|
736
|
+
* more than 100 transitions via boundary hooks.
|
|
737
|
+
*
|
|
738
|
+
* @see Machine._boundary_depth_limit
|
|
739
|
+
* @see Machine._fire_boundary_actions
|
|
740
|
+
*/
|
|
741
|
+
boundary_depth_limit?: number;
|
|
742
|
+
min_exits?: number;
|
|
743
|
+
max_exits?: number;
|
|
744
|
+
allow_islands?: JssmAllowIslands;
|
|
745
|
+
editor_config?: JssmEditorConfig;
|
|
746
|
+
allow_force?: false;
|
|
747
|
+
actions?: JssmPermittedOpt;
|
|
748
|
+
simplify_bidi?: boolean;
|
|
749
|
+
allows_override?: JssmAllowsOverride;
|
|
750
|
+
config_allows_override?: JssmAllowsOverride;
|
|
751
|
+
dot_preamble?: string;
|
|
752
|
+
start_states: Array<StateType>;
|
|
753
|
+
end_states?: Array<StateType>;
|
|
754
|
+
failed_outputs?: Array<StateType>;
|
|
755
|
+
initial_state?: StateType;
|
|
756
|
+
start_states_no_enforce?: boolean;
|
|
757
|
+
state_declaration?: Object[];
|
|
758
|
+
property_definition?: JssmPropertyDefinition[];
|
|
759
|
+
state_property?: JssmPropertyDefinition[];
|
|
760
|
+
arrange_declaration?: Array<Array<StateType>>;
|
|
761
|
+
arrange_start_declaration?: Array<Array<StateType>>;
|
|
762
|
+
arrange_end_declaration?: Array<Array<StateType>>;
|
|
763
|
+
oarrange_declaration?: Array<Array<StateType>>;
|
|
764
|
+
farrange_declaration?: Array<Array<StateType>>;
|
|
765
|
+
machine_author?: string | Array<string>;
|
|
766
|
+
machine_comment?: string;
|
|
767
|
+
machine_contributor?: string | Array<string>;
|
|
768
|
+
machine_definition?: string;
|
|
769
|
+
machine_language?: string;
|
|
770
|
+
machine_license?: string;
|
|
771
|
+
machine_name?: string;
|
|
772
|
+
machine_version?: string;
|
|
773
|
+
npm_name?: string;
|
|
774
|
+
default_size?: JssmDefaultSize;
|
|
775
|
+
fsl_version?: string;
|
|
776
|
+
auto_api?: boolean | string;
|
|
777
|
+
instance_name?: string | undefined;
|
|
778
|
+
default_state_config?: JssmStateStyleKeyList;
|
|
779
|
+
default_start_state_config?: JssmStateStyleKeyList;
|
|
780
|
+
default_end_state_config?: JssmStateStyleKeyList;
|
|
781
|
+
default_hooked_state_config?: JssmStateStyleKeyList;
|
|
782
|
+
default_terminal_state_config?: JssmStateStyleKeyList;
|
|
783
|
+
default_active_state_config?: JssmStateStyleKeyList;
|
|
784
|
+
default_transition_config?: JssmTransitionConfig;
|
|
785
|
+
default_graph_config?: JssmGraphConfig;
|
|
786
|
+
/**
|
|
787
|
+
* Overlapping-state-group tables produced by the compile pass and consumed
|
|
788
|
+
* by the Task-3 runtime cascade.
|
|
789
|
+
*
|
|
790
|
+
* `group_registry` maps each group name to its ordered list of direct
|
|
791
|
+
* members (states and sub-group references) as declared in the FSL source.
|
|
792
|
+
*
|
|
793
|
+
* `group_metadata` maps each group name to its RAW style object
|
|
794
|
+
* `{ declarations: [...] }` — parsed style items from a
|
|
795
|
+
* `state &g : { … };` declaration, **not** condensed `JssmStateConfig`
|
|
796
|
+
* style fields. Condensation is intentionally deferred to the Task-3
|
|
797
|
+
* runtime cascade so that depth-specificity resolution can weight each
|
|
798
|
+
* group's contribution before merging into per-state config.
|
|
799
|
+
*
|
|
800
|
+
* `group_hooks` and `state_hooks` hold boundary-hook payloads keyed by
|
|
801
|
+
* group name and state name respectively; firing is also a Task-3 concern.
|
|
802
|
+
*
|
|
803
|
+
* All four fields are absent (`undefined`) on machines that declare no
|
|
804
|
+
* groups or hooks.
|
|
805
|
+
*/
|
|
806
|
+
group_registry?: JssmGroupRegistry;
|
|
807
|
+
group_metadata?: Map<string, JssmStateConfig>;
|
|
808
|
+
group_hooks?: JssmGroupHooks;
|
|
809
|
+
state_hooks?: JssmStateHooks;
|
|
810
|
+
rng_seed?: number | undefined;
|
|
811
|
+
time_source?: () => number;
|
|
812
|
+
timeout_source?: (Function: any, number: any) => number;
|
|
813
|
+
clear_timeout_source?: (number: any) => void;
|
|
814
|
+
};
|
|
815
|
+
/**
|
|
816
|
+
* Internal compiler intermediate: one link in a chained transition
|
|
817
|
+
* expression (an "s-expression" segment). Carries both directions of an
|
|
818
|
+
* arrow with optional per-direction action labels, probabilities, and
|
|
819
|
+
* after-times. The recursive `se` field allows the parser to chain
|
|
820
|
+
* arrows of the form `A -> B -> C`. Not intended for end-user code.
|
|
821
|
+
*
|
|
822
|
+
* @internal
|
|
823
|
+
*/
|
|
824
|
+
declare type JssmCompileSe<StateType, mDT> = {
|
|
825
|
+
to: StateType;
|
|
826
|
+
se?: JssmCompileSe<StateType, mDT>;
|
|
827
|
+
kind: JssmArrow;
|
|
828
|
+
l_action?: StateType;
|
|
829
|
+
r_action?: StateType;
|
|
830
|
+
l_probability: number;
|
|
831
|
+
r_probability: number;
|
|
832
|
+
l_after?: number;
|
|
833
|
+
r_after?: number;
|
|
834
|
+
loc?: FslSourceLocation;
|
|
835
|
+
to_loc?: FslSourceLocation;
|
|
836
|
+
l_action_loc?: FslSourceLocation;
|
|
837
|
+
r_action_loc?: FslSourceLocation;
|
|
838
|
+
};
|
|
839
|
+
declare type BasicHookDescription<mDT> = {
|
|
840
|
+
kind: 'hook';
|
|
841
|
+
from: string;
|
|
842
|
+
to: string;
|
|
843
|
+
handler: HookHandler<mDT>;
|
|
844
|
+
};
|
|
845
|
+
declare type HookDescriptionWithAction<mDT> = {
|
|
846
|
+
kind: 'named';
|
|
847
|
+
from: string;
|
|
848
|
+
to: string;
|
|
849
|
+
action: string;
|
|
850
|
+
handler: HookHandler<mDT>;
|
|
851
|
+
};
|
|
852
|
+
declare type StandardTransitionHook<mDT> = {
|
|
853
|
+
kind: 'standard transition';
|
|
854
|
+
handler: HookHandler<mDT>;
|
|
855
|
+
};
|
|
856
|
+
declare type MainTransitionHook<mDT> = {
|
|
857
|
+
kind: 'main transition';
|
|
858
|
+
handler: HookHandler<mDT>;
|
|
859
|
+
};
|
|
860
|
+
declare type ForcedTransitionHook<mDT> = {
|
|
861
|
+
kind: 'forced transition';
|
|
862
|
+
handler: HookHandler<mDT>;
|
|
863
|
+
};
|
|
864
|
+
declare type AnyTransitionHook<mDT> = {
|
|
865
|
+
kind: 'any transition';
|
|
866
|
+
handler: HookHandler<mDT>;
|
|
867
|
+
};
|
|
868
|
+
declare type GlobalActionHook<mDT> = {
|
|
869
|
+
kind: 'global action';
|
|
870
|
+
action: string;
|
|
871
|
+
handler: HookHandler<mDT>;
|
|
872
|
+
};
|
|
873
|
+
declare type AnyActionHook<mDT> = {
|
|
874
|
+
kind: 'any action';
|
|
875
|
+
handler: HookHandler<mDT>;
|
|
876
|
+
};
|
|
877
|
+
declare type EntryHook<mDT> = {
|
|
878
|
+
kind: 'entry';
|
|
879
|
+
to: string;
|
|
880
|
+
handler: HookHandler<mDT>;
|
|
881
|
+
};
|
|
882
|
+
declare type ExitHook<mDT> = {
|
|
883
|
+
kind: 'exit';
|
|
884
|
+
from: string;
|
|
885
|
+
handler: HookHandler<mDT>;
|
|
886
|
+
};
|
|
887
|
+
declare type AfterHook<mDT> = {
|
|
888
|
+
kind: 'after';
|
|
889
|
+
from: string;
|
|
890
|
+
handler: HookHandler<mDT>;
|
|
891
|
+
};
|
|
892
|
+
declare type PostBasicHookDescription<mDT> = {
|
|
893
|
+
kind: 'post hook';
|
|
894
|
+
from: string;
|
|
895
|
+
to: string;
|
|
896
|
+
handler: PostHookHandler<mDT>;
|
|
897
|
+
};
|
|
898
|
+
declare type PostHookDescriptionWithAction<mDT> = {
|
|
899
|
+
kind: 'post named';
|
|
900
|
+
from: string;
|
|
901
|
+
to: string;
|
|
902
|
+
action: string;
|
|
903
|
+
handler: PostHookHandler<mDT>;
|
|
904
|
+
};
|
|
905
|
+
declare type PostStandardTransitionHook<mDT> = {
|
|
906
|
+
kind: 'post standard transition';
|
|
907
|
+
handler: PostHookHandler<mDT>;
|
|
908
|
+
};
|
|
909
|
+
declare type PostMainTransitionHook<mDT> = {
|
|
910
|
+
kind: 'post main transition';
|
|
911
|
+
handler: PostHookHandler<mDT>;
|
|
912
|
+
};
|
|
913
|
+
declare type PostForcedTransitionHook<mDT> = {
|
|
914
|
+
kind: 'post forced transition';
|
|
915
|
+
handler: PostHookHandler<mDT>;
|
|
916
|
+
};
|
|
917
|
+
declare type PostAnyTransitionHook<mDT> = {
|
|
918
|
+
kind: 'post any transition';
|
|
919
|
+
handler: PostHookHandler<mDT>;
|
|
920
|
+
};
|
|
921
|
+
declare type PostGlobalActionHook<mDT> = {
|
|
922
|
+
kind: 'post global action';
|
|
923
|
+
action: string;
|
|
924
|
+
handler: PostHookHandler<mDT>;
|
|
925
|
+
};
|
|
926
|
+
declare type PostAnyActionHook<mDT> = {
|
|
927
|
+
kind: 'post any action';
|
|
928
|
+
handler: PostHookHandler<mDT>;
|
|
929
|
+
};
|
|
930
|
+
declare type PostEntryHook<mDT> = {
|
|
931
|
+
kind: 'post entry';
|
|
932
|
+
to: string;
|
|
933
|
+
handler: PostHookHandler<mDT>;
|
|
934
|
+
};
|
|
935
|
+
declare type PostExitHook<mDT> = {
|
|
936
|
+
kind: 'post exit';
|
|
937
|
+
from: string;
|
|
938
|
+
handler: PostHookHandler<mDT>;
|
|
939
|
+
};
|
|
940
|
+
declare type PreEverythingHook<mDT> = {
|
|
941
|
+
kind: 'pre everything';
|
|
942
|
+
handler: EverythingHookHandler<mDT>;
|
|
943
|
+
};
|
|
944
|
+
declare type EverythingHook<mDT> = {
|
|
945
|
+
kind: 'everything';
|
|
946
|
+
handler: EverythingHookHandler<mDT>;
|
|
947
|
+
};
|
|
948
|
+
declare type PrePostEverythingHook<mDT> = {
|
|
949
|
+
kind: 'pre post everything';
|
|
950
|
+
handler: PostEverythingHookHandler<mDT>;
|
|
951
|
+
};
|
|
952
|
+
declare type PostEverythingHook<mDT> = {
|
|
953
|
+
kind: 'post everything';
|
|
954
|
+
handler: PostEverythingHookHandler<mDT>;
|
|
955
|
+
};
|
|
956
|
+
/**
|
|
957
|
+
* Discriminated union of every kind of hook registration jssm understands,
|
|
958
|
+
* pre-transition and post-transition. The `kind` field selects the
|
|
959
|
+
* variant; remaining fields describe which transitions / states / actions
|
|
960
|
+
* the hook is bound to and supply the {@link HookHandler} or
|
|
961
|
+
* {@link PostHookHandler} to invoke.
|
|
962
|
+
*
|
|
963
|
+
* Pre-transition variants (`'hook'`, `'named'`, `'standard transition'`,
|
|
964
|
+
* `'main transition'`, `'forced transition'`, `'any transition'`,
|
|
965
|
+
* `'global action'`, `'any action'`, `'entry'`, `'exit'`, `'after'`)
|
|
966
|
+
* may return a falsy value to veto a transition. Post-transition
|
|
967
|
+
* variants (`'post *'`) cannot veto and are invoked only after a
|
|
968
|
+
* successful transition.
|
|
969
|
+
*/
|
|
970
|
+
declare type HookDescription<mDT> = BasicHookDescription<mDT> | HookDescriptionWithAction<mDT> | GlobalActionHook<mDT> | AnyActionHook<mDT> | StandardTransitionHook<mDT> | MainTransitionHook<mDT> | ForcedTransitionHook<mDT> | AnyTransitionHook<mDT> | EntryHook<mDT> | ExitHook<mDT> | AfterHook<mDT> | PostBasicHookDescription<mDT> | PostHookDescriptionWithAction<mDT> | PostGlobalActionHook<mDT> | PostAnyActionHook<mDT> | PostStandardTransitionHook<mDT> | PostMainTransitionHook<mDT> | PostForcedTransitionHook<mDT> | PostAnyTransitionHook<mDT> | PostEntryHook<mDT> | PostExitHook<mDT> | PreEverythingHook<mDT> | EverythingHook<mDT> | PrePostEverythingHook<mDT> | PostEverythingHook<mDT>;
|
|
971
|
+
/**
|
|
972
|
+
* Whether an observational hook runs in the pre-transition phase (where it
|
|
973
|
+
* may veto/mutate the transition) or the post-transition phase (a pure
|
|
974
|
+
* observer that runs only after a successful transition commits).
|
|
975
|
+
*/
|
|
976
|
+
declare type HookPhase = 'pre' | 'post';
|
|
977
|
+
/**
|
|
978
|
+
* Normalized description of the target a registry entry is bound to. Exactly
|
|
979
|
+
* one scope variant applies; the present fields depend on the scope:
|
|
980
|
+
*
|
|
981
|
+
* - `'edge'` carries `from` + `to` (+ optional `action` for named hooks),
|
|
982
|
+
* - `'state'` carries `state`,
|
|
983
|
+
* - `'action'` carries `action`,
|
|
984
|
+
* - `'global'` carries no further keys (it matches everything),
|
|
985
|
+
* - `'group'` carries `group` (a named state group with a boundary hook).
|
|
986
|
+
*/
|
|
987
|
+
declare type HookTarget = {
|
|
988
|
+
scope: 'edge';
|
|
989
|
+
from: StateType$1;
|
|
990
|
+
to: StateType$1;
|
|
991
|
+
action?: string;
|
|
992
|
+
} | {
|
|
993
|
+
scope: 'state';
|
|
994
|
+
state: StateType$1;
|
|
995
|
+
} | {
|
|
996
|
+
scope: 'action';
|
|
997
|
+
action: string;
|
|
998
|
+
} | {
|
|
999
|
+
scope: 'global';
|
|
1000
|
+
} | {
|
|
1001
|
+
scope: 'group';
|
|
1002
|
+
group: string;
|
|
1003
|
+
};
|
|
1004
|
+
/**
|
|
1005
|
+
* Kinds for FSL boundary hooks (`on enter/exit &group do 'X'` and the plain-
|
|
1006
|
+
* state analogue). These fire post-commit when a transition crosses the
|
|
1007
|
+
* subject's boundary and are not part of {@link HookDescription} (that union
|
|
1008
|
+
* covers only the programmatically-registered observational hooks), so the
|
|
1009
|
+
* registry widens its `kind` field with them.
|
|
1010
|
+
*/
|
|
1011
|
+
declare type HookBoundaryKind = 'group enter' | 'group exit' | 'state enter' | 'state exit';
|
|
1012
|
+
/**
|
|
1013
|
+
* One row of the generated uniform observational-hook registry. `kind` is
|
|
1014
|
+
* either an original {@link HookDescription} discriminator (e.g. `'entry'`,
|
|
1015
|
+
* `'post named'`) or a {@link HookBoundaryKind} for an FSL boundary hook,
|
|
1016
|
+
* `phase` is the {@link HookPhase} the hook runs in, and `target` is the
|
|
1017
|
+
* normalized {@link HookTarget} it is bound to. The triple
|
|
1018
|
+
* `(kind, target, phase)` is the registry key the spec calls for.
|
|
1019
|
+
*/
|
|
1020
|
+
declare type HookRegistryEntry = {
|
|
1021
|
+
kind: HookDescription<unknown>['kind'] | HookBoundaryKind;
|
|
1022
|
+
phase: HookPhase;
|
|
1023
|
+
target: HookTarget;
|
|
1024
|
+
};
|
|
1025
|
+
/**
|
|
1026
|
+
* Query for {@link Machine.has_hook} / {@link Machine.hooks_on}. A bare
|
|
1027
|
+
* string is read as a state name; an `{ from, to, action? }` object is read
|
|
1028
|
+
* as an edge (optionally a named edge); an `{ action }` object is read as a
|
|
1029
|
+
* named action; a `{ group }` object is read as a named state group. This
|
|
1030
|
+
* mirrors the spec's `hooks_on(state)` / `hooks_on(from→to)` /
|
|
1031
|
+
* `hooks_on(action)` / `hooks_on(&group)` set with one parameter shape.
|
|
1032
|
+
*/
|
|
1033
|
+
declare type HookQuery = StateType$1 | {
|
|
1034
|
+
from: StateType$1;
|
|
1035
|
+
to: StateType$1;
|
|
1036
|
+
action?: string;
|
|
1037
|
+
} | {
|
|
1038
|
+
action: string;
|
|
1039
|
+
} | {
|
|
1040
|
+
group: string;
|
|
1041
|
+
};
|
|
1042
|
+
/**
|
|
1043
|
+
* Richer hook return value used when a hook needs to do more than just
|
|
1044
|
+
* accept or veto a transition. `pass` is the required accept/veto flag
|
|
1045
|
+
* (kept non-optional so that returning a stray object doesn't accidentally
|
|
1046
|
+
* veto everything). The optional `state` overrides the destination state,
|
|
1047
|
+
* `data` overrides the data observed by other hooks in the same chain,
|
|
1048
|
+
* and `next_data` overrides the data committed after the transition.
|
|
1049
|
+
*/
|
|
1050
|
+
declare type HookComplexResult<mDT> = {
|
|
1051
|
+
pass: boolean;
|
|
1052
|
+
state?: StateType$1;
|
|
1053
|
+
data?: mDT;
|
|
1054
|
+
next_data?: mDT;
|
|
1055
|
+
};
|
|
1056
|
+
/**
|
|
1057
|
+
* Return value from a {@link HookHandler}. May be a plain boolean to
|
|
1058
|
+
* accept (`true`/`undefined`/`void`) or veto (`false`) the transition, or
|
|
1059
|
+
* a {@link HookComplexResult} that additionally rewrites the next state
|
|
1060
|
+
* and/or the next data payload.
|
|
1061
|
+
*/
|
|
1062
|
+
declare type HookResult<mDT> = true | false | undefined | void | HookComplexResult<mDT>;
|
|
1063
|
+
/**
|
|
1064
|
+
* Context object passed to every {@link HookHandler}. `data` is the
|
|
1065
|
+
* data payload as it stands before the transition, and `next_data` is
|
|
1066
|
+
* the payload that will be committed if the transition is accepted —
|
|
1067
|
+
* handlers may inspect or mutate the latter via a
|
|
1068
|
+
* {@link HookComplexResult} return value.
|
|
1069
|
+
*/
|
|
1070
|
+
declare type HookContext<mDT> = {
|
|
1071
|
+
data: mDT;
|
|
1072
|
+
next_data: mDT;
|
|
1073
|
+
};
|
|
1074
|
+
/**
|
|
1075
|
+
* Context object passed to "everything" hooks ({@link EverythingHookHandler}
|
|
1076
|
+
* and {@link PostEverythingHookHandler}). Extends the usual
|
|
1077
|
+
* {@link HookContext} with `hook_name`, which identifies which specific
|
|
1078
|
+
* hook fired so a single handler can route on it.
|
|
1079
|
+
*/
|
|
1080
|
+
declare type EverythingHookContext<mDT> = HookContext<mDT> & {
|
|
1081
|
+
hook_name: string;
|
|
1082
|
+
};
|
|
1083
|
+
/**
|
|
1084
|
+
* Signature of a pre-transition hook handler. Receives the current and
|
|
1085
|
+
* proposed-next data payloads via a {@link HookContext} and returns a
|
|
1086
|
+
* {@link HookResult}: a falsy result vetoes the transition, a truthy
|
|
1087
|
+
* result allows it, and a {@link HookComplexResult} can additionally
|
|
1088
|
+
* rewrite the next state or next data.
|
|
1089
|
+
*/
|
|
1090
|
+
declare type HookHandler<mDT> = (hook_context: HookContext<mDT>) => HookResult<mDT>;
|
|
1091
|
+
/**
|
|
1092
|
+
* Signature of a post-transition hook handler. Invoked after a successful
|
|
1093
|
+
* transition has been committed; the return value is ignored (the
|
|
1094
|
+
* transition cannot be undone).
|
|
1095
|
+
*/
|
|
1096
|
+
declare type PostHookHandler<mDT> = (hook_context: HookContext<mDT>) => void;
|
|
1097
|
+
/**
|
|
1098
|
+
* Signature of an "everything" pre-transition hook handler. Like
|
|
1099
|
+
* {@link HookHandler} but receives an {@link EverythingHookContext} so the
|
|
1100
|
+
* handler can dispatch on `hook_name`.
|
|
1101
|
+
*/
|
|
1102
|
+
declare type EverythingHookHandler<mDT> = (hook_context: EverythingHookContext<mDT>) => HookResult<mDT>;
|
|
1103
|
+
/**
|
|
1104
|
+
* Signature of an "everything" post-transition hook handler. Like
|
|
1105
|
+
* {@link PostHookHandler} but receives an {@link EverythingHookContext}.
|
|
1106
|
+
* The return value is ignored.
|
|
1107
|
+
*/
|
|
1108
|
+
declare type PostEverythingHookHandler<mDT> = (hook_context: EverythingHookContext<mDT>) => void;
|
|
1109
|
+
/**
|
|
1110
|
+
* Bounded history of recently-visited states paired with the data payload
|
|
1111
|
+
* observed in each. Backed by `circular_buffer_js`, so the oldest entry
|
|
1112
|
+
* is dropped silently once the configured capacity is exceeded.
|
|
1113
|
+
*/
|
|
1114
|
+
declare type JssmHistory<mDT> = circular_buffer<[StateType$1, mDT]>;
|
|
1115
|
+
/**
|
|
1116
|
+
* Pluggable random-number-generator function shape. Must return a value
|
|
1117
|
+
* in `[0, 1)` exactly as `Math.random` does. Supplied via the
|
|
1118
|
+
* `rng_seed`-aware machine configuration so that stochastic models can be
|
|
1119
|
+
* made reproducible.
|
|
1120
|
+
*/
|
|
1121
|
+
declare type JssmRng = () => number;
|
|
1122
|
+
/**
|
|
1123
|
+
* All event names that {@link Machine.on} accepts. These are observation
|
|
1124
|
+
* events fired by the machine in addition to (not in place of) the hook
|
|
1125
|
+
* system. Hooks intercept; events observe.
|
|
1126
|
+
*
|
|
1127
|
+
* @see Machine.on
|
|
1128
|
+
*/
|
|
1129
|
+
declare type JssmEventName = 'transition' | 'rejection' | 'action' | 'entry' | 'exit' | 'terminal' | 'complete' | 'error' | 'data-change' | 'override' | 'timeout' | 'hook-registration' | 'hook-removal';
|
|
1130
|
+
/**
|
|
1131
|
+
* Detail payload fired with a `transition` event. Carries the resolved
|
|
1132
|
+
* source and target, the action name (if the transition was driven by an
|
|
1133
|
+
* action), the data observed before and after the change, the edge kind,
|
|
1134
|
+
* and whether the call was a forced transition.
|
|
1135
|
+
*/
|
|
1136
|
+
declare type JssmTransitionEventDetail<mDT> = {
|
|
1137
|
+
from: StateType$1;
|
|
1138
|
+
to: StateType$1;
|
|
1139
|
+
action?: StateType$1;
|
|
1140
|
+
data: mDT;
|
|
1141
|
+
next_data?: mDT;
|
|
1142
|
+
trans_type: string | undefined;
|
|
1143
|
+
forced: boolean;
|
|
1144
|
+
};
|
|
1145
|
+
/**
|
|
1146
|
+
* Detail payload fired with a `rejection` event. Carries the resolved
|
|
1147
|
+
* source and target plus an indication of who rejected the transition
|
|
1148
|
+
* and why. `reason` is `'invalid'` when no edge existed, `'hook'` when
|
|
1149
|
+
* a hook handler vetoed; `hook_name` is set when `reason` is `'hook'`.
|
|
1150
|
+
*/
|
|
1151
|
+
declare type JssmRejectionEventDetail<mDT> = {
|
|
1152
|
+
from: StateType$1;
|
|
1153
|
+
to: StateType$1;
|
|
1154
|
+
action?: StateType$1;
|
|
1155
|
+
data: mDT;
|
|
1156
|
+
next_data?: mDT;
|
|
1157
|
+
reason: 'invalid' | 'hook';
|
|
1158
|
+
hook_name?: string;
|
|
1159
|
+
forced: boolean;
|
|
1160
|
+
};
|
|
1161
|
+
/**
|
|
1162
|
+
* Detail payload fired with an `action` event. Fires when an action is
|
|
1163
|
+
* attempted, before transition validation runs.
|
|
1164
|
+
*/
|
|
1165
|
+
declare type JssmActionEventDetail<mDT> = {
|
|
1166
|
+
action: StateType$1;
|
|
1167
|
+
from: StateType$1;
|
|
1168
|
+
to?: StateType$1;
|
|
1169
|
+
data: mDT;
|
|
1170
|
+
next_data?: mDT;
|
|
1171
|
+
};
|
|
1172
|
+
/**
|
|
1173
|
+
* Detail payload fired with an `entry` event. `state` is the entered
|
|
1174
|
+
* state. `from` is the predecessor state, if any. `action` is the
|
|
1175
|
+
* action that drove the entry, if any.
|
|
1176
|
+
*/
|
|
1177
|
+
declare type JssmEntryEventDetail<mDT> = {
|
|
1178
|
+
state: StateType$1;
|
|
1179
|
+
from?: StateType$1;
|
|
1180
|
+
action?: StateType$1;
|
|
1181
|
+
data: mDT;
|
|
1182
|
+
};
|
|
1183
|
+
/**
|
|
1184
|
+
* Detail payload fired with an `exit` event. `state` is the exited
|
|
1185
|
+
* state. `to` is the next state, if any. `action` is the action that
|
|
1186
|
+
* drove the exit, if any.
|
|
1187
|
+
*/
|
|
1188
|
+
declare type JssmExitEventDetail<mDT> = {
|
|
1189
|
+
state: StateType$1;
|
|
1190
|
+
to?: StateType$1;
|
|
1191
|
+
action?: StateType$1;
|
|
1192
|
+
data: mDT;
|
|
1193
|
+
};
|
|
1194
|
+
/**
|
|
1195
|
+
* Detail payload fired with a `terminal` event. Indicates that the
|
|
1196
|
+
* machine has reached a state with no outgoing edges.
|
|
1197
|
+
*/
|
|
1198
|
+
declare type JssmTerminalEventDetail<mDT> = {
|
|
1199
|
+
state: StateType$1;
|
|
1200
|
+
data: mDT;
|
|
1201
|
+
};
|
|
1202
|
+
/**
|
|
1203
|
+
* Detail payload fired with a `complete` event. Indicates that the
|
|
1204
|
+
* machine has reached a FSL `complete` state.
|
|
1205
|
+
*/
|
|
1206
|
+
declare type JssmCompleteEventDetail<mDT> = {
|
|
1207
|
+
state: StateType$1;
|
|
1208
|
+
data: mDT;
|
|
1209
|
+
};
|
|
1210
|
+
/**
|
|
1211
|
+
* Detail payload fired with an `error` event. Wraps an exception caught
|
|
1212
|
+
* while running an event handler; `source_event` and `source_detail`
|
|
1213
|
+
* identify the event whose handler threw, and `handler` is the offending
|
|
1214
|
+
* function so consumers can correlate / blame.
|
|
1215
|
+
*/
|
|
1216
|
+
declare type JssmErrorEventDetail = {
|
|
1217
|
+
error: unknown;
|
|
1218
|
+
source_event: JssmEventName;
|
|
1219
|
+
source_detail: unknown;
|
|
1220
|
+
handler: Function;
|
|
1221
|
+
};
|
|
1222
|
+
/**
|
|
1223
|
+
* Detail payload fired with a `data-change` event. Fires whenever the
|
|
1224
|
+
* machine's data payload is replaced. `old_data` is the value before the
|
|
1225
|
+
* change; `new_data` is the value after.
|
|
1226
|
+
*/
|
|
1227
|
+
declare type JssmDataChangeEventDetail<mDT> = {
|
|
1228
|
+
from?: StateType$1;
|
|
1229
|
+
to?: StateType$1;
|
|
1230
|
+
action?: StateType$1;
|
|
1231
|
+
old_data: mDT;
|
|
1232
|
+
new_data: mDT;
|
|
1233
|
+
cause: 'transition' | 'override';
|
|
1234
|
+
};
|
|
1235
|
+
/**
|
|
1236
|
+
* Detail payload fired with an `override` event. Distinguishes a forced
|
|
1237
|
+
* state replacement from a normal transition.
|
|
1238
|
+
*/
|
|
1239
|
+
declare type JssmOverrideEventDetail<mDT> = {
|
|
1240
|
+
from: StateType$1;
|
|
1241
|
+
to: StateType$1;
|
|
1242
|
+
old_data: mDT;
|
|
1243
|
+
new_data?: mDT;
|
|
1244
|
+
};
|
|
1245
|
+
/**
|
|
1246
|
+
* Detail payload fired with a `timeout` event. Fires when a configured
|
|
1247
|
+
* `after` clause causes an automatic transition.
|
|
1248
|
+
*/
|
|
1249
|
+
declare type JssmTimeoutEventDetail = {
|
|
1250
|
+
from: StateType$1;
|
|
1251
|
+
to: StateType$1;
|
|
1252
|
+
after_time: number;
|
|
1253
|
+
};
|
|
1254
|
+
/**
|
|
1255
|
+
* Detail payload fired with `hook-registration` and `hook-removal` events.
|
|
1256
|
+
* Mirrors the {@link HookDescription} so inspector tools can mirror the
|
|
1257
|
+
* current hook set.
|
|
1258
|
+
*/
|
|
1259
|
+
declare type JssmHookLifecycleEventDetail<mDT> = {
|
|
1260
|
+
description: HookDescription<mDT>;
|
|
1261
|
+
};
|
|
1262
|
+
/**
|
|
1263
|
+
* Mapped type from {@link JssmEventName} to the corresponding detail
|
|
1264
|
+
* payload. Drives the discriminated-union typing of {@link Machine.on},
|
|
1265
|
+
* so `e.action` and friends only exist where they're meaningful.
|
|
1266
|
+
*/
|
|
1267
|
+
declare type JssmEventDetailMap<mDT> = {
|
|
1268
|
+
'transition': JssmTransitionEventDetail<mDT>;
|
|
1269
|
+
'rejection': JssmRejectionEventDetail<mDT>;
|
|
1270
|
+
'action': JssmActionEventDetail<mDT>;
|
|
1271
|
+
'entry': JssmEntryEventDetail<mDT>;
|
|
1272
|
+
'exit': JssmExitEventDetail<mDT>;
|
|
1273
|
+
'terminal': JssmTerminalEventDetail<mDT>;
|
|
1274
|
+
'complete': JssmCompleteEventDetail<mDT>;
|
|
1275
|
+
'error': JssmErrorEventDetail;
|
|
1276
|
+
'data-change': JssmDataChangeEventDetail<mDT>;
|
|
1277
|
+
'override': JssmOverrideEventDetail<mDT>;
|
|
1278
|
+
'timeout': JssmTimeoutEventDetail;
|
|
1279
|
+
'hook-registration': JssmHookLifecycleEventDetail<mDT>;
|
|
1280
|
+
'hook-removal': JssmHookLifecycleEventDetail<mDT>;
|
|
1281
|
+
};
|
|
1282
|
+
/**
|
|
1283
|
+
* Filter accepted by {@link Machine.on} / {@link Machine.once} for an
|
|
1284
|
+
* individual event name. Only events whose detail key matches every
|
|
1285
|
+
* filter entry fire the handler. Events that don't list a filter key in
|
|
1286
|
+
* v1 take no filter properties.
|
|
1287
|
+
*/
|
|
1288
|
+
declare type JssmEventFilterMap<mDT> = {
|
|
1289
|
+
'transition': {
|
|
1290
|
+
from?: StateType$1;
|
|
1291
|
+
to?: StateType$1;
|
|
1292
|
+
};
|
|
1293
|
+
'rejection': Record<string, never>;
|
|
1294
|
+
'action': Record<string, never>;
|
|
1295
|
+
'entry': {
|
|
1296
|
+
state?: StateType$1;
|
|
1297
|
+
};
|
|
1298
|
+
'exit': {
|
|
1299
|
+
state?: StateType$1;
|
|
1300
|
+
};
|
|
1301
|
+
'terminal': Record<string, never>;
|
|
1302
|
+
'complete': Record<string, never>;
|
|
1303
|
+
'error': Record<string, never>;
|
|
1304
|
+
'data-change': Record<string, never>;
|
|
1305
|
+
'override': Record<string, never>;
|
|
1306
|
+
'timeout': Record<string, never>;
|
|
1307
|
+
'hook-registration': Record<string, never>;
|
|
1308
|
+
'hook-removal': Record<string, never>;
|
|
1309
|
+
};
|
|
1310
|
+
/**
|
|
1311
|
+
* Per-event filter object (as passed to {@link Machine.on}). Use
|
|
1312
|
+
* `JssmEventDetailMap<mDT>[Ev]` to find the matching detail type.
|
|
1313
|
+
* @typeparam mDT The type of the machine data member.
|
|
1314
|
+
* @typeparam Ev The event name.
|
|
1315
|
+
*/
|
|
1316
|
+
declare type JssmEventFilter<mDT, Ev extends JssmEventName> = JssmEventFilterMap<mDT>[Ev];
|
|
1317
|
+
/**
|
|
1318
|
+
* Per-event handler signature. Receives a detail object typed by event
|
|
1319
|
+
* name, so `e.action` (etc.) only exist where they're meaningful.
|
|
1320
|
+
* @typeparam mDT The type of the machine data member.
|
|
1321
|
+
* @typeparam Ev The event name.
|
|
1322
|
+
*/
|
|
1323
|
+
declare type JssmEventHandler<mDT, Ev extends JssmEventName> = (detail: JssmEventDetailMap<mDT>[Ev]) => void;
|
|
1324
|
+
/**
|
|
1325
|
+
* Function returned by {@link Machine.on} and {@link Machine.once} that
|
|
1326
|
+
* removes the subscription. Calling it more than once is a no-op.
|
|
1327
|
+
*/
|
|
1328
|
+
declare type JssmUnsubscribe = () => void;
|
|
1329
|
+
|
|
1330
|
+
/**
|
|
1331
|
+
* String interning support for the jssm machine internals.
|
|
1332
|
+
*
|
|
1333
|
+
* State and action names are interned to dense integer ids at machine
|
|
1334
|
+
* construction so that per-transition dispatch can use numeric map keys
|
|
1335
|
+
* (integer hashing) instead of repeated string-keyed lookups. Internal
|
|
1336
|
+
* machinery only — deliberately not re-exported from the `jssm` public
|
|
1337
|
+
* surface, so the public API is unchanged.
|
|
1338
|
+
*
|
|
1339
|
+
* @internal
|
|
1340
|
+
*/
|
|
1341
|
+
/**
|
|
1342
|
+
* A string↔integer bimap. Assigns dense ids (0, 1, 2, …) in first-seen
|
|
1343
|
+
* order; lookups are O(1) both directions. Grows monotonically — there is
|
|
1344
|
+
* no removal, matching machine semantics (states and actions are fixed
|
|
1345
|
+
* after construction; late interning only happens for never-matching
|
|
1346
|
+
* lookups such as hook registrations naming unknown states).
|
|
1347
|
+
*
|
|
1348
|
+
* @example
|
|
1349
|
+
* const i = new Interner();
|
|
1350
|
+
* i.intern('red'); // 0
|
|
1351
|
+
* i.intern('green'); // 1
|
|
1352
|
+
* i.intern('red'); // 0 (idempotent)
|
|
1353
|
+
* i.id_of('green'); // 1
|
|
1354
|
+
* i.name_of(0); // 'red'
|
|
1355
|
+
*
|
|
1356
|
+
* @see pair_key
|
|
1357
|
+
*/
|
|
1358
|
+
declare class Interner {
|
|
1359
|
+
private readonly ids;
|
|
1360
|
+
private readonly names;
|
|
1361
|
+
constructor();
|
|
1362
|
+
/**
|
|
1363
|
+
* Return the id for `name`, assigning the next dense id if the name has
|
|
1364
|
+
* not been seen before.
|
|
1365
|
+
*
|
|
1366
|
+
* @param name - The string to intern.
|
|
1367
|
+
* @returns The (possibly newly assigned) integer id.
|
|
1368
|
+
*
|
|
1369
|
+
* @example
|
|
1370
|
+
* interner.intern('red'); // 0 on first call, 0 on every later call
|
|
1371
|
+
*/
|
|
1372
|
+
intern(name: string): number;
|
|
1373
|
+
/**
|
|
1374
|
+
* Return the id for `name` without interning, or `undefined` when the
|
|
1375
|
+
* name has never been interned. This is the hot-path probe for
|
|
1376
|
+
* user-supplied names.
|
|
1377
|
+
*
|
|
1378
|
+
* @param name - The string to look up.
|
|
1379
|
+
*
|
|
1380
|
+
* @example
|
|
1381
|
+
* interner.id_of('mauve'); // undefined — never interned
|
|
1382
|
+
*/
|
|
1383
|
+
id_of(name: string): number | undefined;
|
|
1384
|
+
/**
|
|
1385
|
+
* Return the name for `id`, or `undefined` for an id never assigned.
|
|
1386
|
+
*
|
|
1387
|
+
* @param id - The integer id to invert.
|
|
1388
|
+
*
|
|
1389
|
+
* @example
|
|
1390
|
+
* interner.name_of(0); // 'red'
|
|
1391
|
+
*/
|
|
1392
|
+
name_of(id: number): string | undefined;
|
|
1393
|
+
/** The count of distinct interned names. */
|
|
1394
|
+
get size(): number;
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
declare type StateType = string;
|
|
1398
|
+
|
|
1399
|
+
/**
|
|
1400
|
+
* Internal record holding a single registered event subscription: the
|
|
1401
|
+
* handler, its optional filter, and a flag for `once` semantics. Not
|
|
1402
|
+
* exported.
|
|
1403
|
+
*
|
|
1404
|
+
* @internal
|
|
1405
|
+
*/
|
|
1406
|
+
declare type JssmEventEntry<mDT, Ev extends JssmEventName> = {
|
|
1407
|
+
handler: JssmEventHandler<mDT, Ev>;
|
|
1408
|
+
filter?: JssmEventFilter<mDT, Ev>;
|
|
1409
|
+
once: boolean;
|
|
1410
|
+
};
|
|
1411
|
+
declare class Machine<mDT> {
|
|
1412
|
+
_state: StateType;
|
|
1413
|
+
_states: Map<StateType, JssmGenericState>;
|
|
1414
|
+
_edges: Array<JssmTransition<StateType, mDT>>;
|
|
1415
|
+
_edge_map: Map<StateType, Map<StateType, number>>;
|
|
1416
|
+
_outbound_edge_ids: Map<StateType, Array<number>>;
|
|
1417
|
+
_named_transitions: Map<StateType, number>;
|
|
1418
|
+
_actions: Map<StateType, Map<StateType, number>>;
|
|
1419
|
+
_reverse_actions: Map<StateType, Map<StateType, number>>;
|
|
1420
|
+
_reverse_action_targets: Map<StateType, Map<StateType, number>>;
|
|
1421
|
+
_state_interner: Interner;
|
|
1422
|
+
_action_interner: Interner;
|
|
1423
|
+
_state_id: number;
|
|
1424
|
+
_edge_id_by_pair: Map<number, number>;
|
|
1425
|
+
_edge_id_by_action_pair: Map<number, number>;
|
|
1426
|
+
_edge_to_ids: Array<number>;
|
|
1427
|
+
_start_states: Set<StateType>;
|
|
1428
|
+
_end_states: Set<StateType>;
|
|
1429
|
+
_failed_outputs: Set<StateType>;
|
|
1430
|
+
_machine_author?: Array<string>;
|
|
1431
|
+
_machine_comment?: string;
|
|
1432
|
+
_machine_contributor?: Array<string>;
|
|
1433
|
+
_machine_definition?: string;
|
|
1434
|
+
_machine_language?: string;
|
|
1435
|
+
_machine_license?: string;
|
|
1436
|
+
_machine_name?: string;
|
|
1437
|
+
_machine_version?: string;
|
|
1438
|
+
_npm_name?: string;
|
|
1439
|
+
_default_size?: JssmDefaultSize;
|
|
1440
|
+
_fsl_version?: string;
|
|
1441
|
+
_raw_state_declaration?: Array<Object>;
|
|
1442
|
+
_state_declarations: Map<StateType, JssmStateDeclaration>;
|
|
1443
|
+
_data?: mDT;
|
|
1444
|
+
_instance_name: string;
|
|
1445
|
+
_rng_seed: number;
|
|
1446
|
+
_rng: JssmRng;
|
|
1447
|
+
_graph_layout: JssmLayout;
|
|
1448
|
+
_dot_preamble: string;
|
|
1449
|
+
_default_transition_config: JssmTransitionConfig | undefined;
|
|
1450
|
+
_default_graph_config: JssmGraphConfig | undefined;
|
|
1451
|
+
_arrange_declaration: Array<Array<StateType>>;
|
|
1452
|
+
_arrange_start_declaration: Array<Array<StateType>>;
|
|
1453
|
+
_arrange_end_declaration: Array<Array<StateType>>;
|
|
1454
|
+
_oarrange_declaration: Array<Array<StateType>>;
|
|
1455
|
+
_farrange_declaration: Array<Array<StateType>>;
|
|
1456
|
+
_themes: FslTheme[];
|
|
1457
|
+
_flow: FslDirection;
|
|
1458
|
+
_has_hooks: boolean;
|
|
1459
|
+
_has_basic_hooks: boolean;
|
|
1460
|
+
_has_named_hooks: boolean;
|
|
1461
|
+
_has_entry_hooks: boolean;
|
|
1462
|
+
_has_exit_hooks: boolean;
|
|
1463
|
+
_has_after_hooks: boolean;
|
|
1464
|
+
_has_global_action_hooks: boolean;
|
|
1465
|
+
_has_transition_hooks: boolean;
|
|
1466
|
+
_has_forced_transitions: boolean;
|
|
1467
|
+
_hooks: Map<number, HookHandler<mDT>>;
|
|
1468
|
+
_named_hooks: Map<number, Map<number, HookHandler<mDT>>>;
|
|
1469
|
+
_entry_hooks: Map<number, HookHandler<mDT>>;
|
|
1470
|
+
_exit_hooks: Map<number, HookHandler<mDT>>;
|
|
1471
|
+
_after_hooks: Map<string, HookHandler<mDT>>;
|
|
1472
|
+
_global_action_hooks: Map<number, HookHandler<mDT>>;
|
|
1473
|
+
_any_action_hook: HookHandler<mDT> | undefined;
|
|
1474
|
+
_standard_transition_hook: HookHandler<mDT> | undefined;
|
|
1475
|
+
_main_transition_hook: HookHandler<mDT> | undefined;
|
|
1476
|
+
_forced_transition_hook: HookHandler<mDT> | undefined;
|
|
1477
|
+
_any_transition_hook: HookHandler<mDT> | undefined;
|
|
1478
|
+
_has_post_hooks: boolean;
|
|
1479
|
+
_has_post_basic_hooks: boolean;
|
|
1480
|
+
_has_post_named_hooks: boolean;
|
|
1481
|
+
_has_post_entry_hooks: boolean;
|
|
1482
|
+
_has_post_exit_hooks: boolean;
|
|
1483
|
+
_has_post_global_action_hooks: boolean;
|
|
1484
|
+
_has_post_transition_hooks: boolean;
|
|
1485
|
+
_code_allows_override: JssmAllowsOverride;
|
|
1486
|
+
_config_allows_override: JssmAllowsOverride;
|
|
1487
|
+
_allow_islands: JssmAllowIslands;
|
|
1488
|
+
_editor_config?: JssmEditorConfig;
|
|
1489
|
+
_post_hooks: Map<number, HookHandler<mDT>>;
|
|
1490
|
+
_post_named_hooks: Map<number, Map<number, HookHandler<mDT>>>;
|
|
1491
|
+
_post_entry_hooks: Map<number, HookHandler<mDT>>;
|
|
1492
|
+
_post_exit_hooks: Map<number, HookHandler<mDT>>;
|
|
1493
|
+
_post_global_action_hooks: Map<number, HookHandler<mDT>>;
|
|
1494
|
+
_post_any_action_hook: HookHandler<mDT> | undefined;
|
|
1495
|
+
_post_standard_transition_hook: HookHandler<mDT> | undefined;
|
|
1496
|
+
_post_main_transition_hook: HookHandler<mDT> | undefined;
|
|
1497
|
+
_post_forced_transition_hook: HookHandler<mDT> | undefined;
|
|
1498
|
+
_post_any_transition_hook: HookHandler<mDT> | undefined;
|
|
1499
|
+
_pre_everything_hook: EverythingHookHandler<mDT> | undefined;
|
|
1500
|
+
_everything_hook: EverythingHookHandler<mDT> | undefined;
|
|
1501
|
+
_pre_post_everything_hook: PostEverythingHookHandler<mDT> | undefined;
|
|
1502
|
+
_post_everything_hook: PostEverythingHookHandler<mDT> | undefined;
|
|
1503
|
+
_property_keys: Set<string>;
|
|
1504
|
+
_default_properties: Map<string, any>;
|
|
1505
|
+
_state_properties: Map<string, any>;
|
|
1506
|
+
_required_properties: Set<string>;
|
|
1507
|
+
_state_property_first_state: Map<string, StateType>;
|
|
1508
|
+
_history: JssmHistory<mDT>;
|
|
1509
|
+
_history_length: number;
|
|
1510
|
+
_state_style: JssmStateConfig;
|
|
1511
|
+
_active_state_style: JssmStateConfig;
|
|
1512
|
+
_hooked_state_style: JssmStateConfig;
|
|
1513
|
+
_terminal_state_style: JssmStateConfig;
|
|
1514
|
+
_start_state_style: JssmStateConfig;
|
|
1515
|
+
_end_state_style: JssmStateConfig;
|
|
1516
|
+
_group_registry: JssmGroupRegistry;
|
|
1517
|
+
_group_metadata: Map<string, JssmStateConfig>;
|
|
1518
|
+
_group_hooks: JssmGroupHooks;
|
|
1519
|
+
_state_hooks: JssmStateHooks;
|
|
1520
|
+
_state_to_groups: Map<StateType, Set<string>>;
|
|
1521
|
+
_group_order: string[];
|
|
1522
|
+
_static_state_config_cache: Map<StateType, JssmStateConfig>;
|
|
1523
|
+
_state_labels: Map<string, string>;
|
|
1524
|
+
_time_source: () => number;
|
|
1525
|
+
_create_started: number;
|
|
1526
|
+
_created: number;
|
|
1527
|
+
_after_mapping: Map<string, [string, number]>;
|
|
1528
|
+
_timeout_source: (Function: any, number: any) => number;
|
|
1529
|
+
_clear_timeout_source: (h: any) => void;
|
|
1530
|
+
_timeout_handle: number | undefined;
|
|
1531
|
+
_timeout_target: string | undefined;
|
|
1532
|
+
_timeout_target_time: number | undefined;
|
|
1533
|
+
_event_handlers: Map<JssmEventName, Set<JssmEventEntry<any, any>>>;
|
|
1534
|
+
_event_listener_count: number;
|
|
1535
|
+
_firing_error: boolean;
|
|
1536
|
+
_boundary_depth: number;
|
|
1537
|
+
_boundary_depth_limit: number;
|
|
1538
|
+
constructor({ start_states, end_states, failed_outputs, initial_state, start_states_no_enforce, complete, transitions, machine_author, machine_comment, machine_contributor, machine_definition, machine_language, machine_license, machine_name, machine_version, npm_name, default_size, state_declaration, property_definition, state_property, fsl_version, dot_preamble, arrange_declaration, arrange_start_declaration, arrange_end_declaration, oarrange_declaration, farrange_declaration, theme, flow, graph_layout, instance_name, history, boundary_depth_limit, data, default_state_config, default_active_state_config, default_hooked_state_config, default_terminal_state_config, default_start_state_config, default_end_state_config, default_transition_config, default_graph_config, group_registry, group_metadata, group_hooks, state_hooks, allows_override, config_allows_override, allow_islands, editor_config, rng_seed, time_source, timeout_source, clear_timeout_source }: JssmGenericConfig<StateType, mDT>);
|
|
1539
|
+
/********
|
|
1540
|
+
*
|
|
1541
|
+
* Internal method for fabricating states. Not meant for external use.
|
|
1542
|
+
*
|
|
1543
|
+
* @internal
|
|
1544
|
+
*
|
|
1545
|
+
*/
|
|
1546
|
+
_new_state(state_config: JssmGenericState): StateType;
|
|
1547
|
+
/*********
|
|
1548
|
+
*
|
|
1549
|
+
* Get the current state of a machine.
|
|
1550
|
+
*
|
|
1551
|
+
* ```typescript
|
|
1552
|
+
* import * as jssm from 'jssm';
|
|
1553
|
+
*
|
|
1554
|
+
* const lswitch = jssm.from('on <=> off;');
|
|
1555
|
+
* console.log( lswitch.state() ); // 'on'
|
|
1556
|
+
*
|
|
1557
|
+
* lswitch.transition('off');
|
|
1558
|
+
* console.log( lswitch.state() ); // 'off'
|
|
1559
|
+
* ```
|
|
1560
|
+
*
|
|
1561
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
1562
|
+
*
|
|
1563
|
+
* @returns The current state name.
|
|
1564
|
+
*
|
|
1565
|
+
*/
|
|
1566
|
+
state(): StateType;
|
|
1567
|
+
/*********
|
|
1568
|
+
*
|
|
1569
|
+
* Get the label for a given state, if any; return `undefined` otherwise.
|
|
1570
|
+
*
|
|
1571
|
+
* ```typescript
|
|
1572
|
+
* import * as jssm from 'jssm';
|
|
1573
|
+
*
|
|
1574
|
+
* const lswitch = jssm.from('a -> b; state a: { label: "Foo!"; };');
|
|
1575
|
+
* console.log( lswitch.label_for('a') ); // 'Foo!'
|
|
1576
|
+
* console.log( lswitch.label_for('b') ); // undefined
|
|
1577
|
+
* ```
|
|
1578
|
+
*
|
|
1579
|
+
* See also {@link display_text}.
|
|
1580
|
+
*
|
|
1581
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
1582
|
+
*
|
|
1583
|
+
* @param state The state to get the label for.
|
|
1584
|
+
*
|
|
1585
|
+
* @returns The label string, or `undefined` if no label is set.
|
|
1586
|
+
*
|
|
1587
|
+
*/
|
|
1588
|
+
label_for(state: StateType): string;
|
|
1589
|
+
/*********
|
|
1590
|
+
*
|
|
1591
|
+
* Get whatever the node should show as text.
|
|
1592
|
+
*
|
|
1593
|
+
* Currently, this means to get the label for a given state, if any;
|
|
1594
|
+
* otherwise to return the node's name. However, this definition is expected
|
|
1595
|
+
* to grow with time, and it is currently considered ill-advised to manually
|
|
1596
|
+
* parse this text.
|
|
1597
|
+
*
|
|
1598
|
+
* See also {@link label_for}.
|
|
1599
|
+
*
|
|
1600
|
+
* ```typescript
|
|
1601
|
+
* import * as jssm from 'jssm';
|
|
1602
|
+
*
|
|
1603
|
+
* const lswitch = jssm.from('a -> b; state a: { label: "Foo!"; };');
|
|
1604
|
+
* console.log( lswitch.display_text('a') ); // 'Foo!'
|
|
1605
|
+
* console.log( lswitch.display_text('b') ); // 'b'
|
|
1606
|
+
* ```
|
|
1607
|
+
*
|
|
1608
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
1609
|
+
*
|
|
1610
|
+
* @param state The state to get display text for.
|
|
1611
|
+
*
|
|
1612
|
+
* @returns The label if one exists, otherwise the state's name.
|
|
1613
|
+
*
|
|
1614
|
+
*/
|
|
1615
|
+
display_text(state: StateType): string;
|
|
1616
|
+
/*********
|
|
1617
|
+
*
|
|
1618
|
+
* Get the current data of a machine.
|
|
1619
|
+
*
|
|
1620
|
+
* ```typescript
|
|
1621
|
+
* import * as jssm from 'jssm';
|
|
1622
|
+
*
|
|
1623
|
+
* const lswitch = jssm.from('on <=> off;', {data: 1});
|
|
1624
|
+
* console.log( lswitch.data() ); // 1
|
|
1625
|
+
* ```
|
|
1626
|
+
*
|
|
1627
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
1628
|
+
*
|
|
1629
|
+
* @returns A deep clone of the machine's current data value.
|
|
1630
|
+
*
|
|
1631
|
+
*/
|
|
1632
|
+
data(): mDT;
|
|
1633
|
+
/**
|
|
1634
|
+
* The machine's current data by REFERENCE — no clone. The public
|
|
1635
|
+
* {@link Machine.data} contract is a deep clone per call (a mutation
|
|
1636
|
+
* boundary for external consumers, and deliberately untouched); that clone
|
|
1637
|
+
* is `structuredClone` of the whole data value, which same-package
|
|
1638
|
+
* read-only consumers — the fsl-bind and fsl-data-inspector panels, which
|
|
1639
|
+
* read one dotted path or serialize per transition — should not pay on
|
|
1640
|
+
* every event. Callers MUST NOT mutate the returned value or store it
|
|
1641
|
+
* beyond the current tick; anything crossing a trust boundary must use
|
|
1642
|
+
* {@link Machine.data} instead.
|
|
1643
|
+
*
|
|
1644
|
+
* ```typescript
|
|
1645
|
+
* const m = jssm.from('on <=> off;', { data: { a: { b: 1 } } });
|
|
1646
|
+
* m._data_ref().a.b; // 1, zero-copy
|
|
1647
|
+
* ```
|
|
1648
|
+
*
|
|
1649
|
+
* @returns The live data value; treat as read-only.
|
|
1650
|
+
*
|
|
1651
|
+
* @see Machine.data
|
|
1652
|
+
* @internal
|
|
1653
|
+
*/
|
|
1654
|
+
_data_ref(): mDT;
|
|
1655
|
+
/*********
|
|
1656
|
+
*
|
|
1657
|
+
* Get the current value of a given property name. Checks the current
|
|
1658
|
+
* state's properties first, then falls back to the global default.
|
|
1659
|
+
* Returns `undefined` if neither exists. For a throwing variant, see
|
|
1660
|
+
* {@link strict_prop}.
|
|
1661
|
+
*
|
|
1662
|
+
* ```typescript
|
|
1663
|
+
* const m = sm`property color default "grey"; a -> b;
|
|
1664
|
+
* state b: { property color "blue"; };`;
|
|
1665
|
+
*
|
|
1666
|
+
* m.prop('color'); // 'grey' (default, because state is 'a')
|
|
1667
|
+
* m.go('b');
|
|
1668
|
+
* m.prop('color'); // 'blue' (state 'b' overrides the default)
|
|
1669
|
+
* m.prop('size'); // undefined (no such property)
|
|
1670
|
+
* ```
|
|
1671
|
+
*
|
|
1672
|
+
* @param name The relevant property name to look up.
|
|
1673
|
+
*
|
|
1674
|
+
* @returns The value behind the prop name, or `undefined` if not defined.
|
|
1675
|
+
*
|
|
1676
|
+
*/
|
|
1677
|
+
prop(name: string): any;
|
|
1678
|
+
/*********
|
|
1679
|
+
*
|
|
1680
|
+
* Get the current value of a given property name. If missing on the state
|
|
1681
|
+
* and without a global default, throws a {@link JssmError}, unlike
|
|
1682
|
+
* {@link prop}, which would return `undefined` instead.
|
|
1683
|
+
*
|
|
1684
|
+
* ```typescript
|
|
1685
|
+
* const m = sm`property color default "grey"; a -> b;`;
|
|
1686
|
+
*
|
|
1687
|
+
* m.strict_prop('color'); // 'grey'
|
|
1688
|
+
* m.strict_prop('size'); // throws JssmError
|
|
1689
|
+
* ```
|
|
1690
|
+
*
|
|
1691
|
+
* @param name The relevant property name to look up.
|
|
1692
|
+
*
|
|
1693
|
+
* @returns The value behind the prop name.
|
|
1694
|
+
*
|
|
1695
|
+
* @throws {JssmError} If the property is not defined on the current state
|
|
1696
|
+
* and has no default.
|
|
1697
|
+
*
|
|
1698
|
+
*/
|
|
1699
|
+
strict_prop(name: string): any;
|
|
1700
|
+
/*********
|
|
1701
|
+
*
|
|
1702
|
+
* Get the current value of every prop, as an object. If no current definition
|
|
1703
|
+
* exists for a prop — that is, if the prop was defined without a default and
|
|
1704
|
+
* the current state also doesn't define the prop — then that prop will be listed
|
|
1705
|
+
* in the returned object with a value of `undefined`.
|
|
1706
|
+
*
|
|
1707
|
+
* ```typescript
|
|
1708
|
+
* const traffic_light = sm`
|
|
1709
|
+
*
|
|
1710
|
+
* property can_go default true;
|
|
1711
|
+
* property hesitate default true;
|
|
1712
|
+
* property stop_first default false;
|
|
1713
|
+
*
|
|
1714
|
+
* Off -> Red => Green => Yellow => Red;
|
|
1715
|
+
* [Red Yellow Green] ~> [Off FlashingRed];
|
|
1716
|
+
* FlashingRed -> Red;
|
|
1717
|
+
*
|
|
1718
|
+
* state Red: { property: stop_first true; property: can_go false; };
|
|
1719
|
+
* state Off: { property: stop_first true; };
|
|
1720
|
+
* state FlashingRed: { property: stop_first true; };
|
|
1721
|
+
* state Green: { property: hesitate false; };
|
|
1722
|
+
*
|
|
1723
|
+
* `;
|
|
1724
|
+
*
|
|
1725
|
+
* traffic_light.state(); // Off
|
|
1726
|
+
* traffic_light.props(); // { can_go: true, hesitate: true, stop_first: true }
|
|
1727
|
+
*
|
|
1728
|
+
* traffic_light.go('Red');
|
|
1729
|
+
* traffic_light.props(); // { can_go: false, hesitate: true, stop_first: true }
|
|
1730
|
+
*
|
|
1731
|
+
* traffic_light.go('Green');
|
|
1732
|
+
* traffic_light.props(); // { can_go: true, hesitate: false, stop_first: false }
|
|
1733
|
+
* ```
|
|
1734
|
+
*
|
|
1735
|
+
* @returns An object mapping every known property name to its current value
|
|
1736
|
+
* (or `undefined` if the property has no default and the current state
|
|
1737
|
+
* doesn't define it).
|
|
1738
|
+
*
|
|
1739
|
+
*/
|
|
1740
|
+
props(): object;
|
|
1741
|
+
/*********
|
|
1742
|
+
*
|
|
1743
|
+
* Check whether a given string is a known property's name.
|
|
1744
|
+
*
|
|
1745
|
+
* ```typescript
|
|
1746
|
+
* const example = sm`property foo default 1; a->b;`;
|
|
1747
|
+
*
|
|
1748
|
+
* example.known_prop('foo'); // true
|
|
1749
|
+
* example.known_prop('bar'); // false
|
|
1750
|
+
* ```
|
|
1751
|
+
*
|
|
1752
|
+
* @param prop_name The relevant property name to look up
|
|
1753
|
+
*
|
|
1754
|
+
*/
|
|
1755
|
+
known_prop(prop_name: string): boolean;
|
|
1756
|
+
/*********
|
|
1757
|
+
*
|
|
1758
|
+
* List all known property names. If you'd also like values, use
|
|
1759
|
+
* {@link props} instead. The order of the properties is not defined, and
|
|
1760
|
+
* the properties generally will not be sorted.
|
|
1761
|
+
*
|
|
1762
|
+
* ```typescript
|
|
1763
|
+
* const m = sm`property color default "grey"; property size default 1; a -> b;`;
|
|
1764
|
+
*
|
|
1765
|
+
* m.known_props(); // ['color', 'size']
|
|
1766
|
+
* ```
|
|
1767
|
+
*
|
|
1768
|
+
* @returns An array of all property name strings defined on this machine.
|
|
1769
|
+
*
|
|
1770
|
+
*/
|
|
1771
|
+
known_props(): string[];
|
|
1772
|
+
/********
|
|
1773
|
+
*
|
|
1774
|
+
* Check whether a given state is a valid start state (either because it was
|
|
1775
|
+
* explicitly named as such, or because it was the first mentioned state.)
|
|
1776
|
+
*
|
|
1777
|
+
* ```typescript
|
|
1778
|
+
* import { sm, is_start_state } from 'jssm';
|
|
1779
|
+
*
|
|
1780
|
+
* const example = sm`a -> b;`;
|
|
1781
|
+
*
|
|
1782
|
+
* console.log( final_test.is_start_state('a') ); // true
|
|
1783
|
+
* console.log( final_test.is_start_state('b') ); // false
|
|
1784
|
+
*
|
|
1785
|
+
* const example = sm`start_states: [a b]; a -> b;`;
|
|
1786
|
+
*
|
|
1787
|
+
* console.log( final_test.is_start_state('a') ); // true
|
|
1788
|
+
* console.log( final_test.is_start_state('b') ); // true
|
|
1789
|
+
* ```
|
|
1790
|
+
*
|
|
1791
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
1792
|
+
*
|
|
1793
|
+
* @param whichState The name of the state to check
|
|
1794
|
+
*
|
|
1795
|
+
*/
|
|
1796
|
+
is_start_state(whichState: StateType): boolean;
|
|
1797
|
+
/********
|
|
1798
|
+
*
|
|
1799
|
+
* Check whether a given state is a valid start state (either because it was
|
|
1800
|
+
* explicitly named as such, or because it was the first mentioned state.)
|
|
1801
|
+
*
|
|
1802
|
+
* ```typescript
|
|
1803
|
+
* import { sm, is_end_state } from 'jssm';
|
|
1804
|
+
*
|
|
1805
|
+
* const example = sm`a -> b;`;
|
|
1806
|
+
*
|
|
1807
|
+
* console.log( final_test.is_start_state('a') ); // false
|
|
1808
|
+
* console.log( final_test.is_start_state('b') ); // true
|
|
1809
|
+
*
|
|
1810
|
+
* const example = sm`end_states: [a b]; a -> b;`;
|
|
1811
|
+
*
|
|
1812
|
+
* console.log( final_test.is_start_state('a') ); // true
|
|
1813
|
+
* console.log( final_test.is_start_state('b') ); // true
|
|
1814
|
+
* ```
|
|
1815
|
+
*
|
|
1816
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
1817
|
+
*
|
|
1818
|
+
* @param whichState The name of the state to check
|
|
1819
|
+
*
|
|
1820
|
+
*/
|
|
1821
|
+
is_end_state(whichState: StateType): boolean;
|
|
1822
|
+
/********
|
|
1823
|
+
*
|
|
1824
|
+
* Get the set of states declared as failure outputs for this machine.
|
|
1825
|
+
* Returns an array of state labels, or an empty array when none were
|
|
1826
|
+
* declared. A state in this list means the machine is in a failure
|
|
1827
|
+
* condition when it occupies that state.
|
|
1828
|
+
*
|
|
1829
|
+
* @see {@link is_failed_output} to test a single state
|
|
1830
|
+
* @see {@link is_failed} to test the current state
|
|
1831
|
+
*
|
|
1832
|
+
*/
|
|
1833
|
+
failed_outputs(): Array<StateType>;
|
|
1834
|
+
/********
|
|
1835
|
+
*
|
|
1836
|
+
* Check whether a given state is declared as a failure output.
|
|
1837
|
+
*
|
|
1838
|
+
* @param whichState The name of the state to check
|
|
1839
|
+
*
|
|
1840
|
+
* @see {@link failed_outputs} for the full failure-output set
|
|
1841
|
+
* @see {@link is_failed} to test the current state
|
|
1842
|
+
*
|
|
1843
|
+
*/
|
|
1844
|
+
is_failed_output(whichState: StateType): boolean;
|
|
1845
|
+
/********
|
|
1846
|
+
*
|
|
1847
|
+
* Check whether the machine is currently in a failure state — that is,
|
|
1848
|
+
* whether its current state is one of the declared `failed_outputs`.
|
|
1849
|
+
*
|
|
1850
|
+
* @see {@link failed_outputs} for the full failure-output set
|
|
1851
|
+
* @see {@link is_failed_output} to test an arbitrary state
|
|
1852
|
+
*
|
|
1853
|
+
*/
|
|
1854
|
+
is_failed(): boolean;
|
|
1855
|
+
/********
|
|
1856
|
+
*
|
|
1857
|
+
* Check whether a given state is final (either has no exits or is marked
|
|
1858
|
+
* `complete`.)
|
|
1859
|
+
*
|
|
1860
|
+
* ```typescript
|
|
1861
|
+
* import { sm, state_is_final } from 'jssm';
|
|
1862
|
+
*
|
|
1863
|
+
* const final_test = sm`first -> second;`;
|
|
1864
|
+
*
|
|
1865
|
+
* console.log( final_test.state_is_final('first') ); // false
|
|
1866
|
+
* console.log( final_test.state_is_final('second') ); // true
|
|
1867
|
+
* ```
|
|
1868
|
+
*
|
|
1869
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
1870
|
+
*
|
|
1871
|
+
* @param whichState The name of the state to check for finality
|
|
1872
|
+
*
|
|
1873
|
+
*/
|
|
1874
|
+
state_is_final(whichState: StateType): boolean;
|
|
1875
|
+
/********
|
|
1876
|
+
*
|
|
1877
|
+
* Check whether the current state is final (either has no exits or is marked
|
|
1878
|
+
* `complete`.)
|
|
1879
|
+
*
|
|
1880
|
+
* ```typescript
|
|
1881
|
+
* import { sm, is_final } from 'jssm';
|
|
1882
|
+
*
|
|
1883
|
+
* const final_test = sm`first -> second;`;
|
|
1884
|
+
*
|
|
1885
|
+
* console.log( final_test.is_final() ); // false
|
|
1886
|
+
* state.transition('second');
|
|
1887
|
+
* console.log( final_test.is_final() ); // true
|
|
1888
|
+
* ```
|
|
1889
|
+
*
|
|
1890
|
+
*/
|
|
1891
|
+
is_final(): boolean;
|
|
1892
|
+
/********
|
|
1893
|
+
*
|
|
1894
|
+
* Serialize the current machine, including all defining state but not the
|
|
1895
|
+
* machine string, to a structure. This means you will need the machine
|
|
1896
|
+
* string to recreate (to not waste repeated space;) if you want the machine
|
|
1897
|
+
* string embedded, call {@link serialize_with_string} instead.
|
|
1898
|
+
*
|
|
1899
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
1900
|
+
*
|
|
1901
|
+
* @param comment An optional comment string to embed in the serialized
|
|
1902
|
+
* output for identification or debugging.
|
|
1903
|
+
*
|
|
1904
|
+
* @returns A {@link JssmSerialization} object containing the machine's
|
|
1905
|
+
* current state, data, and timestamp.
|
|
1906
|
+
*
|
|
1907
|
+
*/
|
|
1908
|
+
serialize(comment?: string | undefined): JssmSerialization<mDT>;
|
|
1909
|
+
/** Get the graph layout direction (e.g. `'LR'`, `'TB'`). Set via the
|
|
1910
|
+
* FSL `graph_layout` directive.
|
|
1911
|
+
* @returns The layout string, or the default if not set.
|
|
1912
|
+
*/
|
|
1913
|
+
graph_layout(): string;
|
|
1914
|
+
/** Get the Graphviz DOT preamble string, injected before the graph body
|
|
1915
|
+
* during visualization. Set via the FSL `dot_preamble` directive.
|
|
1916
|
+
* @returns The preamble string.
|
|
1917
|
+
*/
|
|
1918
|
+
dot_preamble(): string;
|
|
1919
|
+
/** Get the consolidated `transition: {}` default-config block: the ordered,
|
|
1920
|
+
* de-duplicated `{ key, value }[]` list of edge-default style items compiled
|
|
1921
|
+
* from a `transition: {}` block (e.g. `transition: { color: blue; }`). The
|
|
1922
|
+
* viz layer projects this onto a Graphviz `edge [ … ]` default statement so
|
|
1923
|
+
* every edge inherits it.
|
|
1924
|
+
*
|
|
1925
|
+
* ```typescript
|
|
1926
|
+
* import { sm } from 'jssm';
|
|
1927
|
+
* sm`a -> b; transition: { color: blue; };`.default_transition_config();
|
|
1928
|
+
* // [ { key: 'color', value: '#0000ffff' } ]
|
|
1929
|
+
* ```
|
|
1930
|
+
*
|
|
1931
|
+
* @returns The transition-config item list, or `undefined` if the machine
|
|
1932
|
+
* declared no `transition: {}` block.
|
|
1933
|
+
* @see default_graph_config
|
|
1934
|
+
*/
|
|
1935
|
+
default_transition_config(): JssmTransitionConfig | undefined;
|
|
1936
|
+
/** Get the consolidated `graph: {}` default-config block: the ordered,
|
|
1937
|
+
* de-duplicated `{ key, value }[]` list of graph-scope style items. The
|
|
1938
|
+
* compiler folds the deprecated top-level graph keywords
|
|
1939
|
+
* (`graph_bg_color` → `background-color`, plus `graph_layout`, `theme`,
|
|
1940
|
+
* `flow`, `dot_preamble`) into this list first, then lets an explicit
|
|
1941
|
+
* `graph: {}` block win on key conflict. The viz layer projects the
|
|
1942
|
+
* graph-meaningful keys onto graph-scope Graphviz attributes (e.g.
|
|
1943
|
+
* `background-color` → `bgcolor`).
|
|
1944
|
+
*
|
|
1945
|
+
* ```typescript
|
|
1946
|
+
* import { sm } from 'jssm';
|
|
1947
|
+
* sm`a -> b; graph: { background-color: #ffffff; };`.default_graph_config();
|
|
1948
|
+
* // [ { key: 'background-color', value: '#ffffffff' } ]
|
|
1949
|
+
* ```
|
|
1950
|
+
*
|
|
1951
|
+
* @returns The graph-config item list, or `undefined` if the machine has no
|
|
1952
|
+
* graph config (no `graph: {}` block and no deprecated graph keyword).
|
|
1953
|
+
* @see default_transition_config
|
|
1954
|
+
*/
|
|
1955
|
+
default_graph_config(): JssmGraphConfig | undefined;
|
|
1956
|
+
/** Get the machine's author list. Set via the FSL `machine_author` directive.
|
|
1957
|
+
* @returns An array of author name strings.
|
|
1958
|
+
*/
|
|
1959
|
+
machine_author(): Array<string>;
|
|
1960
|
+
/** Get the machine's comment string. Set via the FSL `machine_comment` directive.
|
|
1961
|
+
* @returns The comment string.
|
|
1962
|
+
*/
|
|
1963
|
+
machine_comment(): string;
|
|
1964
|
+
/** Get the machine's contributor list. Set via the FSL `machine_contributor` directive.
|
|
1965
|
+
* @returns An array of contributor name strings.
|
|
1966
|
+
*/
|
|
1967
|
+
machine_contributor(): Array<string>;
|
|
1968
|
+
/** Get the machine's definition string. Set via the FSL `machine_definition` directive.
|
|
1969
|
+
* @returns The definition string.
|
|
1970
|
+
*/
|
|
1971
|
+
machine_definition(): string;
|
|
1972
|
+
/** Get the machine's natural language as an ISO 639-1 code. Set via the FSL
|
|
1973
|
+
* `machine_language` directive, which accepts a language name or code, or a
|
|
1974
|
+
* BCP-47 tag whose region subtag is dropped (`en-us` -> `en`). Unrecognized
|
|
1975
|
+
* values resolve to `undefined`.
|
|
1976
|
+
* @returns The ISO 639-1 language code (e.g. `'en'`), or `undefined` if the
|
|
1977
|
+
* supplied value did not resolve to a known language.
|
|
1978
|
+
*/
|
|
1979
|
+
machine_language(): string;
|
|
1980
|
+
/** Get the machine's license string. Set via the FSL `machine_license` directive.
|
|
1981
|
+
* @returns The license string.
|
|
1982
|
+
*/
|
|
1983
|
+
machine_license(): string;
|
|
1984
|
+
/** Get the machine's name. Set via the FSL `machine_name` directive.
|
|
1985
|
+
* @returns The machine name string.
|
|
1986
|
+
*/
|
|
1987
|
+
machine_name(): string;
|
|
1988
|
+
/** The editor/panel defaults declared in the FSL `editor: {}` block, or
|
|
1989
|
+
* `undefined` when none was given. Read by the all-widgets web control
|
|
1990
|
+
* (fsl#1334) — `panels` drives `request` panel mode.
|
|
1991
|
+
*
|
|
1992
|
+
* @returns `{ stochastic_run_count?, panels? }`, or `undefined`.
|
|
1993
|
+
*
|
|
1994
|
+
* @example
|
|
1995
|
+
* const m = sm`editor: { panels: [history]; }; a -> b;`;
|
|
1996
|
+
* m.editor_config(); // => { panels: ['history'] }
|
|
1997
|
+
*/
|
|
1998
|
+
editor_config(): JssmEditorConfig | undefined;
|
|
1999
|
+
/** Get the npm package name associated with the machine. Set via the FSL `npm_name` directive.
|
|
2000
|
+
* Returns `undefined` when not present.
|
|
2001
|
+
* @returns The npm package name string, or `undefined`.
|
|
2002
|
+
* @see machine_name
|
|
2003
|
+
*/
|
|
2004
|
+
npm_name(): string;
|
|
2005
|
+
/** Get the render-size hint for the machine's visualization. Set via the
|
|
2006
|
+
* FSL `default_size` directive. Returns `undefined` when not present.
|
|
2007
|
+
*
|
|
2008
|
+
* The three FSL forms each produce a different subset of fields:
|
|
2009
|
+
*
|
|
2010
|
+
* - `default_size: 800;` → `{ width: 800 }`
|
|
2011
|
+
* - `default_size: 800 600;` → `{ width: 800, height: 600 }`
|
|
2012
|
+
* - `default_size: height 600;` → `{ height: 600 }`
|
|
2013
|
+
*
|
|
2014
|
+
* This is a hint, not a hard constraint. Renderers may ignore it.
|
|
2015
|
+
*
|
|
2016
|
+
* @returns The size-hint object, or `undefined` if not set.
|
|
2017
|
+
* @see npm_name
|
|
2018
|
+
*/
|
|
2019
|
+
default_size(): JssmDefaultSize | undefined;
|
|
2020
|
+
/** Get the machine's version string. Set via the FSL `machine_version` directive.
|
|
2021
|
+
* @returns The version string.
|
|
2022
|
+
*/
|
|
2023
|
+
machine_version(): string;
|
|
2024
|
+
/** Get the raw state declaration objects as parsed from the FSL source.
|
|
2025
|
+
* @returns An array of raw state declaration objects.
|
|
2026
|
+
*/
|
|
2027
|
+
raw_state_declarations(): Array<Object>;
|
|
2028
|
+
/** Get the processed state declaration for a specific state.
|
|
2029
|
+
* @param which - The state to look up.
|
|
2030
|
+
* @returns The {@link JssmStateDeclaration} for the given state.
|
|
2031
|
+
*/
|
|
2032
|
+
state_declaration(which: StateType): JssmStateDeclaration;
|
|
2033
|
+
/** Get all processed state declarations as a Map.
|
|
2034
|
+
* @returns A `Map` from state name to {@link JssmStateDeclaration}.
|
|
2035
|
+
*/
|
|
2036
|
+
state_declarations(): Map<StateType, JssmStateDeclaration>;
|
|
2037
|
+
/** Get the FSL language version this machine was compiled under.
|
|
2038
|
+
* @returns The FSL version string.
|
|
2039
|
+
*/
|
|
2040
|
+
fsl_version(): string;
|
|
2041
|
+
/** Get the complete internal state of the machine as a serializable
|
|
2042
|
+
* structure. Includes actions, edges, edge map, named transitions,
|
|
2043
|
+
* reverse actions, current state, and states map.
|
|
2044
|
+
* @returns A {@link JssmMachineInternalState} snapshot.
|
|
2045
|
+
*/
|
|
2046
|
+
machine_state(): JssmMachineInternalState<mDT>;
|
|
2047
|
+
/*********
|
|
2048
|
+
*
|
|
2049
|
+
* List all the states known by the machine. Please note that the order of
|
|
2050
|
+
* these states is not guaranteed.
|
|
2051
|
+
*
|
|
2052
|
+
* ```typescript
|
|
2053
|
+
* import * as jssm from 'jssm';
|
|
2054
|
+
*
|
|
2055
|
+
* const lswitch = jssm.from('on <=> off;');
|
|
2056
|
+
* console.log( lswitch.states() ); // ['on', 'off']
|
|
2057
|
+
* ```
|
|
2058
|
+
*
|
|
2059
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
2060
|
+
*
|
|
2061
|
+
* @returns An array of all state names in the machine.
|
|
2062
|
+
*
|
|
2063
|
+
*/
|
|
2064
|
+
states(): Array<StateType>;
|
|
2065
|
+
/** Get the internal state descriptor for a given state name.
|
|
2066
|
+
* @param whichState - The state to look up.
|
|
2067
|
+
* @returns The {@link JssmGenericState} descriptor.
|
|
2068
|
+
* @throws {JssmError} If the state does not exist.
|
|
2069
|
+
*/
|
|
2070
|
+
state_for(whichState: StateType): JssmGenericState;
|
|
2071
|
+
/*********
|
|
2072
|
+
*
|
|
2073
|
+
* Check whether the machine knows a given state.
|
|
2074
|
+
*
|
|
2075
|
+
* ```typescript
|
|
2076
|
+
* import * as jssm from 'jssm';
|
|
2077
|
+
*
|
|
2078
|
+
* const lswitch = jssm.from('on <=> off;');
|
|
2079
|
+
*
|
|
2080
|
+
* console.log( lswitch.has_state('off') ); // true
|
|
2081
|
+
* console.log( lswitch.has_state('dance') ); // false
|
|
2082
|
+
* ```
|
|
2083
|
+
*
|
|
2084
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
2085
|
+
*
|
|
2086
|
+
* @param whichState The state to be checked for existence.
|
|
2087
|
+
*
|
|
2088
|
+
* @returns `true` if the state exists, `false` otherwise.
|
|
2089
|
+
*
|
|
2090
|
+
*/
|
|
2091
|
+
has_state(whichState: StateType): boolean;
|
|
2092
|
+
/*********
|
|
2093
|
+
*
|
|
2094
|
+
* Lists all edges of a machine.
|
|
2095
|
+
*
|
|
2096
|
+
* ```typescript
|
|
2097
|
+
* import { sm } from 'jssm';
|
|
2098
|
+
*
|
|
2099
|
+
* const lswitch = sm`on 'toggle' <=> 'toggle' off;`;
|
|
2100
|
+
*
|
|
2101
|
+
* lswitch.list_edges();
|
|
2102
|
+
* [
|
|
2103
|
+
* {
|
|
2104
|
+
* from: 'on',
|
|
2105
|
+
* to: 'off',
|
|
2106
|
+
* kind: 'main',
|
|
2107
|
+
* forced_only: false,
|
|
2108
|
+
* main_path: true,
|
|
2109
|
+
* action: 'toggle'
|
|
2110
|
+
* },
|
|
2111
|
+
* {
|
|
2112
|
+
* from: 'off',
|
|
2113
|
+
* to: 'on',
|
|
2114
|
+
* kind: 'main',
|
|
2115
|
+
* forced_only: false,
|
|
2116
|
+
* main_path: true,
|
|
2117
|
+
* action: 'toggle'
|
|
2118
|
+
* }
|
|
2119
|
+
* ]
|
|
2120
|
+
* ```
|
|
2121
|
+
*
|
|
2122
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
2123
|
+
*
|
|
2124
|
+
* @returns An array of all {@link JssmTransition} edge objects.
|
|
2125
|
+
*
|
|
2126
|
+
*/
|
|
2127
|
+
list_edges(): Array<JssmTransition<StateType, mDT>>;
|
|
2128
|
+
/** Get the map of named transitions (transitions with explicit names).
|
|
2129
|
+
* @returns A `Map` from transition name to edge index.
|
|
2130
|
+
*/
|
|
2131
|
+
list_named_transitions(): Map<StateType, number>;
|
|
2132
|
+
/** List all distinct action names defined anywhere in the machine.
|
|
2133
|
+
* @returns An array of action name strings.
|
|
2134
|
+
*/
|
|
2135
|
+
list_actions(): Array<StateType>;
|
|
2136
|
+
/** Whether any actions are defined on this machine.
|
|
2137
|
+
* @returns `true` if the machine has at least one action.
|
|
2138
|
+
*/
|
|
2139
|
+
get uses_actions(): boolean;
|
|
2140
|
+
/** Whether any forced (`~>`) transitions exist in this machine.
|
|
2141
|
+
* @returns `true` if at least one forced transition is defined.
|
|
2142
|
+
*/
|
|
2143
|
+
get uses_forced_transitions(): boolean;
|
|
2144
|
+
/*********
|
|
2145
|
+
*
|
|
2146
|
+
* Check if the code that built the machine allows overriding state and data.
|
|
2147
|
+
*
|
|
2148
|
+
* @returns The override permission from the FSL source code.
|
|
2149
|
+
*
|
|
2150
|
+
*/
|
|
2151
|
+
get code_allows_override(): JssmAllowsOverride;
|
|
2152
|
+
/*********
|
|
2153
|
+
*
|
|
2154
|
+
* Check if the machine config allows overriding state and data.
|
|
2155
|
+
*
|
|
2156
|
+
* @returns The override permission from the runtime config.
|
|
2157
|
+
*
|
|
2158
|
+
*/
|
|
2159
|
+
get config_allows_override(): JssmAllowsOverride;
|
|
2160
|
+
/*********
|
|
2161
|
+
*
|
|
2162
|
+
* Check if a machine allows overriding state and data. Resolves the
|
|
2163
|
+
* combined effect of code and config permissions — config may not be
|
|
2164
|
+
* less strict than code.
|
|
2165
|
+
*
|
|
2166
|
+
* @returns The effective override permission.
|
|
2167
|
+
*
|
|
2168
|
+
*/
|
|
2169
|
+
get allows_override(): JssmAllowsOverride;
|
|
2170
|
+
/*********
|
|
2171
|
+
*
|
|
2172
|
+
* Return the effective island policy for this machine. `true` means
|
|
2173
|
+
* disconnected components are allowed (the default), `false` requires a
|
|
2174
|
+
* single connected component, and `'with_start'` allows islands only when
|
|
2175
|
+
* every component contains at least one start state.
|
|
2176
|
+
*
|
|
2177
|
+
* @returns The island policy stored in the machine.
|
|
2178
|
+
*
|
|
2179
|
+
*/
|
|
2180
|
+
get allow_islands(): JssmAllowIslands;
|
|
2181
|
+
/** List all available theme names.
|
|
2182
|
+
* @returns An array of theme name strings.
|
|
2183
|
+
*/
|
|
2184
|
+
all_themes(): FslTheme[];
|
|
2185
|
+
/** List the character ranges accepted by the FSL grammar in any but the
|
|
2186
|
+
* first position of a state name (atom). Each entry is an inclusive
|
|
2187
|
+
* `{from, to}` range of single Unicode characters.
|
|
2188
|
+
*
|
|
2189
|
+
* @returns An array of `{from, to}` inclusive character ranges.
|
|
2190
|
+
*
|
|
2191
|
+
* @example
|
|
2192
|
+
* import { sm } from 'jssm';
|
|
2193
|
+
* const m = sm`a -> b;`;
|
|
2194
|
+
* m.all_state_name_chars().some(r => '+' >= r.from && '+' <= r.to); // => true
|
|
2195
|
+
*/
|
|
2196
|
+
all_state_name_chars(): ReadonlyArray<{
|
|
2197
|
+
from: string;
|
|
2198
|
+
to: string;
|
|
2199
|
+
}>;
|
|
2200
|
+
/** List the character ranges accepted by the FSL grammar in the first
|
|
2201
|
+
* position of a state name (atom). Narrower than
|
|
2202
|
+
* {@link all_state_name_chars}: notably omits `+`, `(`, `)`, `&`, `#`, `@`.
|
|
2203
|
+
*
|
|
2204
|
+
* @returns An array of `{from, to}` inclusive character ranges.
|
|
2205
|
+
*
|
|
2206
|
+
* @example
|
|
2207
|
+
* import { sm } from 'jssm';
|
|
2208
|
+
* const m = sm`a -> b;`;
|
|
2209
|
+
* m.all_state_name_first_chars().some(r => '+' >= r.from && '+' <= r.to); // => false
|
|
2210
|
+
*/
|
|
2211
|
+
all_state_name_first_chars(): ReadonlyArray<{
|
|
2212
|
+
from: string;
|
|
2213
|
+
to: string;
|
|
2214
|
+
}>;
|
|
2215
|
+
/** List the character ranges accepted inside a single-quoted FSL action
|
|
2216
|
+
* label without escaping. Space is allowed; the apostrophe `'` is
|
|
2217
|
+
* explicitly excluded since it terminates the label.
|
|
2218
|
+
*
|
|
2219
|
+
* @returns An array of `{from, to}` inclusive character ranges.
|
|
2220
|
+
*
|
|
2221
|
+
* @example
|
|
2222
|
+
* import { sm } from 'jssm';
|
|
2223
|
+
* const m = sm`a -> b;`;
|
|
2224
|
+
* m.all_action_label_chars().some(r => ' ' >= r.from && ' ' <= r.to); // => true
|
|
2225
|
+
* m.all_action_label_chars().some(r => "'" >= r.from && "'" <= r.to); // => false
|
|
2226
|
+
*/
|
|
2227
|
+
all_action_label_chars(): ReadonlyArray<{
|
|
2228
|
+
from: string;
|
|
2229
|
+
to: string;
|
|
2230
|
+
}>;
|
|
2231
|
+
/** Get the active theme(s) for this machine. Always stored as an array
|
|
2232
|
+
* internally; the union return type exists for setter compatibility.
|
|
2233
|
+
* @returns The current theme or array of themes.
|
|
2234
|
+
*/
|
|
2235
|
+
get themes(): FslTheme | FslTheme[];
|
|
2236
|
+
/** Set the active theme(s). Accepts a single theme name or an array.
|
|
2237
|
+
* @param to - A theme name or array of theme names to apply.
|
|
2238
|
+
*/
|
|
2239
|
+
set themes(to: FslTheme | FslTheme[]);
|
|
2240
|
+
/** Get the flow direction for graph layout (e.g. `'right'`, `'down'`).
|
|
2241
|
+
* Set via the FSL `flow` directive.
|
|
2242
|
+
* @returns The current flow direction.
|
|
2243
|
+
*/
|
|
2244
|
+
flow(): FslDirection;
|
|
2245
|
+
/** Look up a transition's edge index by source and target state names.
|
|
2246
|
+
* @param from - Source state name.
|
|
2247
|
+
* @param to - Target state name.
|
|
2248
|
+
* @returns The edge index in the edges array, or `undefined` if no
|
|
2249
|
+
* such transition exists.
|
|
2250
|
+
*/
|
|
2251
|
+
get_transition_by_state_names(from: StateType, to: StateType): number;
|
|
2252
|
+
/** Look up the full transition object for a given source→target pair.
|
|
2253
|
+
* @param from - Source state name.
|
|
2254
|
+
* @param to - Target state name.
|
|
2255
|
+
* @returns The {@link JssmTransition} object, or `undefined` if none exists.
|
|
2256
|
+
*/
|
|
2257
|
+
lookup_transition_for(from: StateType, to: StateType): JssmTransition<StateType, mDT>;
|
|
2258
|
+
/********
|
|
2259
|
+
*
|
|
2260
|
+
* List all transitions attached to the current state, sorted by entrance and
|
|
2261
|
+
* exit. The order of each sublist is not defined. A node could appear in
|
|
2262
|
+
* both lists.
|
|
2263
|
+
*
|
|
2264
|
+
* ```typescript
|
|
2265
|
+
* import { sm } from 'jssm';
|
|
2266
|
+
*
|
|
2267
|
+
* const light = sm`red 'next' -> green 'next' -> yellow 'next' -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
|
|
2268
|
+
*
|
|
2269
|
+
* light.state(); // 'red'
|
|
2270
|
+
* light.list_transitions(); // { entrances: [ 'yellow', 'off' ], exits: [ 'green', 'off' ] }
|
|
2271
|
+
* ```
|
|
2272
|
+
*
|
|
2273
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
2274
|
+
*
|
|
2275
|
+
* @param whichState The state whose transitions to have listed
|
|
2276
|
+
*
|
|
2277
|
+
*/
|
|
2278
|
+
list_transitions(whichState?: StateType): JssmTransitionList;
|
|
2279
|
+
/********
|
|
2280
|
+
*
|
|
2281
|
+
* List all entrances attached to the current state. Please note that the
|
|
2282
|
+
* order of the list is not defined. This list includes both unforced and
|
|
2283
|
+
* forced entrances; if this isn't desired, consider
|
|
2284
|
+
* {@link list_unforced_entrances} or {@link list_forced_entrances} as
|
|
2285
|
+
* appropriate.
|
|
2286
|
+
*
|
|
2287
|
+
* ```typescript
|
|
2288
|
+
* import { sm } from 'jssm';
|
|
2289
|
+
*
|
|
2290
|
+
* const light = sm`red 'next' -> green 'next' -> yellow 'next' -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
|
|
2291
|
+
*
|
|
2292
|
+
* light.state(); // 'red'
|
|
2293
|
+
* light.list_entrances(); // [ 'yellow', 'off' ]
|
|
2294
|
+
* ```
|
|
2295
|
+
*
|
|
2296
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
2297
|
+
*
|
|
2298
|
+
* @param whichState The state whose entrances to have listed
|
|
2299
|
+
*
|
|
2300
|
+
*/
|
|
2301
|
+
list_entrances(whichState?: StateType): Array<StateType>;
|
|
2302
|
+
/********
|
|
2303
|
+
*
|
|
2304
|
+
* List all exits attached to the current state. Please note that the order
|
|
2305
|
+
* of the list is not defined. This list includes both unforced and forced
|
|
2306
|
+
* exits; if this isn't desired, consider {@link list_unforced_exits} or
|
|
2307
|
+
* {@link list_forced_exits} as appropriate.
|
|
2308
|
+
*
|
|
2309
|
+
* ```typescript
|
|
2310
|
+
* import { sm } from 'jssm';
|
|
2311
|
+
*
|
|
2312
|
+
* const light = sm`red 'next' -> green 'next' -> yellow 'next' -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
|
|
2313
|
+
*
|
|
2314
|
+
* light.state(); // 'red'
|
|
2315
|
+
* light.list_exits(); // [ 'green', 'off' ]
|
|
2316
|
+
* ```
|
|
2317
|
+
*
|
|
2318
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
2319
|
+
*
|
|
2320
|
+
* @param whichState The state whose exits to have listed
|
|
2321
|
+
*
|
|
2322
|
+
*/
|
|
2323
|
+
list_exits(whichState?: StateType): Array<StateType>;
|
|
2324
|
+
/** Get the transitions available from a state for use by the probabilistic
|
|
2325
|
+
* walk system.
|
|
2326
|
+
*
|
|
2327
|
+
* If any exit declares a `probability`, only those probability-bearing
|
|
2328
|
+
* exits are returned, so that non-probability peers cannot dilute the
|
|
2329
|
+
* declared distribution. If no exit declares a `probability`, every
|
|
2330
|
+
* legal (non-forced) exit is returned, which `weighted_rand_select`
|
|
2331
|
+
* treats as equal weight. Forced-only exits (`~>`) are always excluded,
|
|
2332
|
+
* since they cannot be taken by an ordinary `transition()` call.
|
|
2333
|
+
*
|
|
2334
|
+
* Fixes StoneCypher/fsl#1325, in which the function previously returned
|
|
2335
|
+
* every exit unconditionally — including forced-only exits and exits
|
|
2336
|
+
* with no `probability`, which distorted the weighted distribution.
|
|
2337
|
+
*
|
|
2338
|
+
* @param whichState - The state to inspect.
|
|
2339
|
+
* @returns An array of {@link JssmTransition} edges exiting the state,
|
|
2340
|
+
* filtered as described above. May be empty.
|
|
2341
|
+
* @throws {JssmError} If the state does not exist.
|
|
2342
|
+
*/
|
|
2343
|
+
probable_exits_for(whichState: StateType): Array<JssmTransition<StateType, mDT>>;
|
|
2344
|
+
/** Take a single random transition from the current state, weighted by
|
|
2345
|
+
* edge probabilities.
|
|
2346
|
+
* @returns `true` if a transition was taken, `false` otherwise.
|
|
2347
|
+
*/
|
|
2348
|
+
probabilistic_transition(): boolean;
|
|
2349
|
+
/** Take `n` consecutive probabilistic transitions and return the sequence
|
|
2350
|
+
* of states visited (before each transition).
|
|
2351
|
+
* @param n - Number of steps to walk.
|
|
2352
|
+
* @returns An array of state names visited during the walk.
|
|
2353
|
+
*/
|
|
2354
|
+
probabilistic_walk(n: number): Array<StateType>;
|
|
2355
|
+
/** Take `n` probabilistic steps and return a histograph of how many times
|
|
2356
|
+
* each state was visited.
|
|
2357
|
+
* @param n - Number of steps to walk.
|
|
2358
|
+
* @returns A `Map` from state name to visit count.
|
|
2359
|
+
*/
|
|
2360
|
+
probabilistic_histo_walk(n: number): Map<StateType, number>;
|
|
2361
|
+
/** One non-destructive weighted-random walk over the graph from `start`.
|
|
2362
|
+
*
|
|
2363
|
+
* Reads the graph and advances the PRNG only — it never calls
|
|
2364
|
+
* {@link Machine.transition}, so it fires no hooks, mutates no machine
|
|
2365
|
+
* state, and touches no `data`. A state with no probabilistic exits
|
|
2366
|
+
* (a terminal, or a forced-only `~>` state) ends the walk.
|
|
2367
|
+
*
|
|
2368
|
+
* @param start - State to begin the walk from.
|
|
2369
|
+
* @param max_steps - Maximum transitions before the walk is step-capped.
|
|
2370
|
+
* @param exit_memo - Per-run-set cache of {@link Machine.probable_exits_for}
|
|
2371
|
+
* results. The graph is immutable after construction, so a state's
|
|
2372
|
+
* probable exits never change; sharing one memo across a generator's
|
|
2373
|
+
* runs collapses runs×steps re-derivations (two array allocations and an
|
|
2374
|
+
* exit rescan per step) to one per distinct state. The memo only reuses
|
|
2375
|
+
* the derived arrays — RNG draw order is untouched, so seeded walks
|
|
2376
|
+
* reproduce exactly.
|
|
2377
|
+
* @returns The {@link JssmStochasticRun} for this walk.
|
|
2378
|
+
*/
|
|
2379
|
+
private _stochastic_one_walk;
|
|
2380
|
+
/** Lazily yield one {@link JssmStochasticRun} at a time.
|
|
2381
|
+
*
|
|
2382
|
+
* In `montecarlo` mode (default) yields `runs` independent walks from the
|
|
2383
|
+
* current state, each ending at a terminal or after `max_steps`. In
|
|
2384
|
+
* `steady_state` mode yields exactly one walk of `max_steps` steps. This
|
|
2385
|
+
* is the lazy engine behind {@link Machine.stochastic_summary}; the
|
|
2386
|
+
* fsl-stochastic panel drives it across animation frames.
|
|
2387
|
+
*
|
|
2388
|
+
* Passing `seed` reseeds the machine for reproducible runs. Unlike
|
|
2389
|
+
* {@link Machine.stochastic_summary}, the generator does NOT restore the
|
|
2390
|
+
* prior seed afterward — a direct caller's machine is left reseeded.
|
|
2391
|
+
*
|
|
2392
|
+
* @param opts - {@link JssmStochasticOptions}.
|
|
2393
|
+
* @returns A generator of per-run results.
|
|
2394
|
+
*
|
|
2395
|
+
* @example
|
|
2396
|
+
* const m = sm`a 'go' -> b 'go' -> c;`;
|
|
2397
|
+
* [...m.stochastic_runs({ runs: 2, seed: 1 })].length; // => 2
|
|
2398
|
+
*/
|
|
2399
|
+
stochastic_runs(opts?: JssmStochasticOptions): Generator<JssmStochasticRun>;
|
|
2400
|
+
/** Run many weighted-random walks and return aggregate statistics.
|
|
2401
|
+
*
|
|
2402
|
+
* Honors `%` transition probabilities (via the existing probabilistic
|
|
2403
|
+
* machinery). Non-destructive: the machine's current state and
|
|
2404
|
+
* {@link Machine.rng_seed} are restored before returning, so calling this
|
|
2405
|
+
* never perturbs the live machine. `montecarlo` mode (default) reports
|
|
2406
|
+
* per-run `path_lengths`, `terminal_reached`, and `capped`; `steady_state`
|
|
2407
|
+
* mode runs one long walk and omits those fields.
|
|
2408
|
+
*
|
|
2409
|
+
* Timing (`after`) decorations and data-guard conditions are not modeled
|
|
2410
|
+
* by this sampler; it walks the probabilistic graph topology.
|
|
2411
|
+
*
|
|
2412
|
+
* @param opts - {@link JssmStochasticOptions}. `runs` defaults to the
|
|
2413
|
+
* machine's declared `editor: { stochastic_run_count }` (fsl#1334) when
|
|
2414
|
+
* present, otherwise {@link STOCHASTIC_DEFAULT_RUNS}.
|
|
2415
|
+
* @returns A {@link JssmStochasticSummary}.
|
|
2416
|
+
*
|
|
2417
|
+
* @see Machine.stochastic_runs
|
|
2418
|
+
* @see Machine.probabilistic_walk
|
|
2419
|
+
* @see Machine.editor_config
|
|
2420
|
+
*
|
|
2421
|
+
* @example
|
|
2422
|
+
* const m = sm`a 'go' -> b 'go' -> c;`;
|
|
2423
|
+
* const s = m.stochastic_summary({ runs: 100, seed: 1 });
|
|
2424
|
+
* s.terminal_reached; // => 100
|
|
2425
|
+
*/
|
|
2426
|
+
stochastic_summary(opts?: JssmStochasticOptions): JssmStochasticSummary;
|
|
2427
|
+
/********
|
|
2428
|
+
*
|
|
2429
|
+
* List all actions available from this state. Please note that the order of
|
|
2430
|
+
* the actions is not guaranteed.
|
|
2431
|
+
*
|
|
2432
|
+
* ```typescript
|
|
2433
|
+
* import { sm } from 'jssm';
|
|
2434
|
+
*
|
|
2435
|
+
* const machine = sm`
|
|
2436
|
+
* red 'next' -> green 'next' -> yellow 'next' -> red;
|
|
2437
|
+
* [red yellow green] 'shutdown' ~> off 'start' -> red;
|
|
2438
|
+
* `;
|
|
2439
|
+
*
|
|
2440
|
+
* console.log( machine.state() ); // logs 'red'
|
|
2441
|
+
* console.log( machine.actions() ); // logs ['next', 'shutdown']
|
|
2442
|
+
*
|
|
2443
|
+
* machine.action('next'); // true
|
|
2444
|
+
* console.log( machine.state() ); // logs 'green'
|
|
2445
|
+
* console.log( machine.actions() ); // logs ['next', 'shutdown']
|
|
2446
|
+
*
|
|
2447
|
+
* machine.action('shutdown'); // true
|
|
2448
|
+
* console.log( machine.state() ); // logs 'off'
|
|
2449
|
+
* console.log( machine.actions() ); // logs ['start']
|
|
2450
|
+
*
|
|
2451
|
+
* machine.action('start'); // true
|
|
2452
|
+
* console.log( machine.state() ); // logs 'red'
|
|
2453
|
+
* console.log( machine.actions() ); // logs ['next', 'shutdown']
|
|
2454
|
+
* ```
|
|
2455
|
+
*
|
|
2456
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
2457
|
+
*
|
|
2458
|
+
* @param whichState The state whose actions to list. Defaults to the
|
|
2459
|
+
* current state.
|
|
2460
|
+
*
|
|
2461
|
+
* @returns An array of action names available from the given state.
|
|
2462
|
+
*
|
|
2463
|
+
*/
|
|
2464
|
+
actions(whichState?: StateType): Array<StateType>;
|
|
2465
|
+
/********
|
|
2466
|
+
*
|
|
2467
|
+
* List all states that have a specific action attached. Please note that
|
|
2468
|
+
* the order of the states is not guaranteed.
|
|
2469
|
+
*
|
|
2470
|
+
* ```typescript
|
|
2471
|
+
* import { sm } from 'jssm';
|
|
2472
|
+
*
|
|
2473
|
+
* const machine = sm`
|
|
2474
|
+
* red 'next' -> green 'next' -> yellow 'next' -> red;
|
|
2475
|
+
* [red yellow green] 'shutdown' ~> off 'start' -> red;
|
|
2476
|
+
* `;
|
|
2477
|
+
*
|
|
2478
|
+
* console.log( machine.list_states_having_action('next') ); // ['red', 'green', 'yellow']
|
|
2479
|
+
* console.log( machine.list_states_having_action('start') ); // ['off']
|
|
2480
|
+
* ```
|
|
2481
|
+
*
|
|
2482
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
2483
|
+
*
|
|
2484
|
+
* @param whichState The action to be checked for associated states
|
|
2485
|
+
*
|
|
2486
|
+
*/
|
|
2487
|
+
list_states_having_action(whichState: StateType): Array<StateType>;
|
|
2488
|
+
/** List all action names available as exits from a given state.
|
|
2489
|
+
*
|
|
2490
|
+
* Returns the empty array (does not throw) when `whichState` exists but has
|
|
2491
|
+
* no action-named exits — including terminal states, states whose only
|
|
2492
|
+
* exits are plain `->` transitions, and states in machines that use no
|
|
2493
|
+
* actions at all. Only nonexistent states cause a throw.
|
|
2494
|
+
*
|
|
2495
|
+
* @param whichState - The state to inspect. Defaults to the current state.
|
|
2496
|
+
* @returns An array of action name strings, possibly empty.
|
|
2497
|
+
* @throws {JssmError} If the state does not exist.
|
|
2498
|
+
*
|
|
2499
|
+
* @example
|
|
2500
|
+
* const m = sm`a 'go' -> b; b -> c;`;
|
|
2501
|
+
* m.list_exit_actions('a'); // => ['go']
|
|
2502
|
+
* m.list_exit_actions('b'); // => []
|
|
2503
|
+
* m.list_exit_actions('c'); // => []
|
|
2504
|
+
* expect(() => m.list_exit_actions('z')).toThrow();
|
|
2505
|
+
*/
|
|
2506
|
+
list_exit_actions(whichState?: StateType): Array<StateType>;
|
|
2507
|
+
/** List all action exits from a state with their probabilities.
|
|
2508
|
+
* @param whichState - The state to inspect. Defaults to the current state.
|
|
2509
|
+
* @returns An array of `{ action, probability }` objects.
|
|
2510
|
+
* @throws {JssmError} If the state does not exist.
|
|
2511
|
+
*/
|
|
2512
|
+
probable_action_exits(whichState?: StateType): Array<any>;
|
|
2513
|
+
/** Check whether a state has no incoming transitions (unreachable after start).
|
|
2514
|
+
* @param whichState - The state to check.
|
|
2515
|
+
* @returns `true` if the state has zero entrances.
|
|
2516
|
+
* @throws {JssmError} If the state does not exist.
|
|
2517
|
+
*/
|
|
2518
|
+
is_unenterable(whichState: StateType): boolean;
|
|
2519
|
+
/** Check whether any state in the machine is unenterable.
|
|
2520
|
+
* @returns `true` if at least one state has no incoming transitions.
|
|
2521
|
+
*/
|
|
2522
|
+
has_unenterables(): boolean;
|
|
2523
|
+
/** Check whether the current state is terminal (has no exits).
|
|
2524
|
+
* @returns `true` if the current state has zero exits.
|
|
2525
|
+
*/
|
|
2526
|
+
is_terminal(): boolean;
|
|
2527
|
+
/** Check whether a specific state is terminal (has no exits).
|
|
2528
|
+
* @param whichState - The state to check.
|
|
2529
|
+
* @returns `true` if the state has zero exits.
|
|
2530
|
+
* @throws {JssmError} If the state does not exist.
|
|
2531
|
+
*/
|
|
2532
|
+
state_is_terminal(whichState: StateType): boolean;
|
|
2533
|
+
/** Check whether any state in the machine is terminal.
|
|
2534
|
+
* @returns `true` if at least one state has no exits.
|
|
2535
|
+
*/
|
|
2536
|
+
has_terminals(): boolean;
|
|
2537
|
+
/********
|
|
2538
|
+
*
|
|
2539
|
+
* Reports whether the machine's CURRENT state is a transitive member of a
|
|
2540
|
+
* named group. Membership is deep: a state counts as in `groupName` if it
|
|
2541
|
+
* belongs to that group directly, or via any nested (`&child`) or spread
|
|
2542
|
+
* (`...&child`) sub-group, at any depth. An undeclared group simply has no
|
|
2543
|
+
* members, so this returns `false` rather than throwing.
|
|
2544
|
+
*
|
|
2545
|
+
* ```typescript
|
|
2546
|
+
* import { sm } from 'jssm';
|
|
2547
|
+
*
|
|
2548
|
+
* const m = sm`&busy : [working]; idle 'go' -> working;`;
|
|
2549
|
+
* m.isIn('busy'); // false — current state is 'idle'
|
|
2550
|
+
* m.action('go');
|
|
2551
|
+
* m.isIn('busy'); // true — current state is now 'working'
|
|
2552
|
+
* m.isIn('nonesuch'); // false — undeclared group has no members
|
|
2553
|
+
* ```
|
|
2554
|
+
*
|
|
2555
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
2556
|
+
*
|
|
2557
|
+
* @param groupName The group to test the current state against.
|
|
2558
|
+
*
|
|
2559
|
+
* @returns `true` if the current state is a transitive member of `groupName`.
|
|
2560
|
+
*
|
|
2561
|
+
* @see groupsOf
|
|
2562
|
+
* @see statesIn
|
|
2563
|
+
*
|
|
2564
|
+
*/
|
|
2565
|
+
isIn(groupName: string): boolean;
|
|
2566
|
+
/********
|
|
2567
|
+
*
|
|
2568
|
+
* Lists every group that transitively contains a given state. Membership is
|
|
2569
|
+
* deep — direct, nested, and spread sub-group containment all count — and the
|
|
2570
|
+
* result is the precomputed inverse-index entry for the state, so the lookup
|
|
2571
|
+
* is constant-time. A state that belongs to no group (or a state name that
|
|
2572
|
+
* appears in no group) yields an empty `Set`.
|
|
2573
|
+
*
|
|
2574
|
+
* ```typescript
|
|
2575
|
+
* import { sm } from 'jssm';
|
|
2576
|
+
*
|
|
2577
|
+
* const m = sm`&inner : [a]; &outer : [&inner b]; a -> b;`;
|
|
2578
|
+
* m.groupsOf('a'); // Set { 'inner', 'outer' } — deep through &inner
|
|
2579
|
+
* m.groupsOf('b'); // Set { 'outer' }
|
|
2580
|
+
* m.groupsOf('z'); // Set {} — not in any group
|
|
2581
|
+
* ```
|
|
2582
|
+
*
|
|
2583
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
2584
|
+
*
|
|
2585
|
+
* @param state The state whose containing groups are wanted.
|
|
2586
|
+
*
|
|
2587
|
+
* @returns A `Set` of every group name transitively containing `state`;
|
|
2588
|
+
* empty when `state` belongs to no group.
|
|
2589
|
+
*
|
|
2590
|
+
* @see isIn
|
|
2591
|
+
* @see groups
|
|
2592
|
+
*
|
|
2593
|
+
*/
|
|
2594
|
+
groupsOf(state: StateType): Set<string>;
|
|
2595
|
+
/********
|
|
2596
|
+
*
|
|
2597
|
+
* Lists all declared group names, in source declaration order. The order
|
|
2598
|
+
* matches the order the `&group : [ … ];` declarations appear in the FSL, and
|
|
2599
|
+
* is the same order used to break depth-specificity ties in the config
|
|
2600
|
+
* cascade. Machines that declare no groups return an empty array.
|
|
2601
|
+
*
|
|
2602
|
+
* ```typescript
|
|
2603
|
+
* import { sm } from 'jssm';
|
|
2604
|
+
*
|
|
2605
|
+
* const m = sm`&first : [a]; &second : [b]; a -> b;`;
|
|
2606
|
+
* m.groups(); // [ 'first', 'second' ]
|
|
2607
|
+
* ```
|
|
2608
|
+
*
|
|
2609
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
2610
|
+
*
|
|
2611
|
+
* @returns The declared group names, in declaration order.
|
|
2612
|
+
*
|
|
2613
|
+
* @see groupsOf
|
|
2614
|
+
* @see statesIn
|
|
2615
|
+
*
|
|
2616
|
+
*/
|
|
2617
|
+
groups(): string[];
|
|
2618
|
+
/********
|
|
2619
|
+
*
|
|
2620
|
+
* Lists every state that is a transitive member of a named group — the
|
|
2621
|
+
* flattened membership of the group, descending through nested and spread
|
|
2622
|
+
* sub-groups, in member-declaration order.
|
|
2623
|
+
*
|
|
2624
|
+
* ```typescript
|
|
2625
|
+
* import { sm } from 'jssm';
|
|
2626
|
+
*
|
|
2627
|
+
* const m = sm`&inner : [a b]; &outer : [&inner c]; a -> b -> c;`;
|
|
2628
|
+
* m.statesIn('outer'); // [ 'a', 'b', 'c' ]
|
|
2629
|
+
* m.statesIn('inner'); // [ 'a', 'b' ]
|
|
2630
|
+
* ```
|
|
2631
|
+
*
|
|
2632
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
2633
|
+
*
|
|
2634
|
+
* @param groupName The group whose transitive member states are wanted.
|
|
2635
|
+
*
|
|
2636
|
+
* @returns The transitive member states of `groupName`, in declaration order.
|
|
2637
|
+
*
|
|
2638
|
+
* @throws {JssmError} If `groupName` is not a declared group.
|
|
2639
|
+
*
|
|
2640
|
+
* @see groups
|
|
2641
|
+
* @see groupsOf
|
|
2642
|
+
*
|
|
2643
|
+
*/
|
|
2644
|
+
statesIn(groupName: string): Array<StateType>;
|
|
2645
|
+
/** Check whether the current state is complete (every exit has an action).
|
|
2646
|
+
* @returns `true` if the current state is complete.
|
|
2647
|
+
*/
|
|
2648
|
+
is_complete(): boolean;
|
|
2649
|
+
/** Check whether a specific state is complete (every exit has an action).
|
|
2650
|
+
* @param whichState - The state to check.
|
|
2651
|
+
* @returns `true` if the state is complete.
|
|
2652
|
+
* @throws {JssmError} If the state does not exist.
|
|
2653
|
+
*/
|
|
2654
|
+
state_is_complete(whichState: StateType): boolean;
|
|
2655
|
+
/** Check whether any state in the machine is complete.
|
|
2656
|
+
* @returns `true` if at least one state is complete.
|
|
2657
|
+
*/
|
|
2658
|
+
has_completes(): boolean;
|
|
2659
|
+
/**
|
|
2660
|
+
* Subscribe to a typed observation event. Hooks (`set_hook` and friends)
|
|
2661
|
+
* intercept and may cancel a transition; events fire alongside the same
|
|
2662
|
+
* state-machine moments but cannot influence the outcome. This is the
|
|
2663
|
+
* surface most users actually want for "tell me when state changes".
|
|
2664
|
+
*
|
|
2665
|
+
* Handlers run synchronously, in registration order. A throwing handler
|
|
2666
|
+
* does not block subsequent handlers — its exception is caught and
|
|
2667
|
+
* re-emitted as an `error` event whose detail names the original event
|
|
2668
|
+
* and the offending handler.
|
|
2669
|
+
*
|
|
2670
|
+
* ```typescript
|
|
2671
|
+
* const m = sm`a -> b -> c;`;
|
|
2672
|
+
*
|
|
2673
|
+
* m.on('transition', e => console.log(`${e.from} -> ${e.to}`));
|
|
2674
|
+
* m.on('entry', { state: 'b' }, e => console.log(`entered ${e.state}`));
|
|
2675
|
+
*
|
|
2676
|
+
* const off = m.on('transition', () => {});
|
|
2677
|
+
* off(); // unsubscribe
|
|
2678
|
+
* ```
|
|
2679
|
+
*
|
|
2680
|
+
* @typeparam Ev The event name (drives the detail type).
|
|
2681
|
+
* @param name The event name to subscribe to.
|
|
2682
|
+
* @param filterOrFn Either a filter object or, when calling the no-filter
|
|
2683
|
+
* form, the handler itself.
|
|
2684
|
+
* @param maybeFn The handler, when a filter object was supplied.
|
|
2685
|
+
* @returns A function that unsubscribes when called.
|
|
2686
|
+
*
|
|
2687
|
+
* @see Machine.off
|
|
2688
|
+
* @see Machine.once
|
|
2689
|
+
*/
|
|
2690
|
+
on<Ev extends JssmEventName>(name: Ev, handler: JssmEventHandler<mDT, Ev>): JssmUnsubscribe;
|
|
2691
|
+
on<Ev extends JssmEventName>(name: Ev, filter: JssmEventFilter<mDT, Ev>, handler: JssmEventHandler<mDT, Ev>): JssmUnsubscribe;
|
|
2692
|
+
/**
|
|
2693
|
+
* Subscribe to a typed observation event for one matching delivery, then
|
|
2694
|
+
* auto-remove. Accepts the same `(name, handler)` and `(name, filter,
|
|
2695
|
+
* handler)` shapes as {@link Machine.on}.
|
|
2696
|
+
*
|
|
2697
|
+
* ```typescript
|
|
2698
|
+
* m.once('terminal', e => console.log(`done at ${e.state}`));
|
|
2699
|
+
* ```
|
|
2700
|
+
*
|
|
2701
|
+
* @typeparam Ev The event name.
|
|
2702
|
+
* @param name The event name.
|
|
2703
|
+
* @param filterOrFn A filter object or the handler (no-filter form).
|
|
2704
|
+
* @param maybeFn The handler, when a filter was supplied.
|
|
2705
|
+
* @returns A function that unsubscribes early if called before the
|
|
2706
|
+
* handler has fired.
|
|
2707
|
+
*
|
|
2708
|
+
* @see Machine.on
|
|
2709
|
+
* @see Machine.off
|
|
2710
|
+
*/
|
|
2711
|
+
once<Ev extends JssmEventName>(name: Ev, handler: JssmEventHandler<mDT, Ev>): JssmUnsubscribe;
|
|
2712
|
+
once<Ev extends JssmEventName>(name: Ev, filter: JssmEventFilter<mDT, Ev>, handler: JssmEventHandler<mDT, Ev>): JssmUnsubscribe;
|
|
2713
|
+
/**
|
|
2714
|
+
* Remove a previously-registered event handler. Match is by reference —
|
|
2715
|
+
* the same function value passed to {@link Machine.on} or
|
|
2716
|
+
* {@link Machine.once}. Returns `true` if a subscription was found and
|
|
2717
|
+
* removed, `false` otherwise.
|
|
2718
|
+
*
|
|
2719
|
+
* ```typescript
|
|
2720
|
+
* const fn = (e: any) => console.log(e);
|
|
2721
|
+
* m.on('transition', fn);
|
|
2722
|
+
* m.off('transition', fn); // true
|
|
2723
|
+
* m.off('transition', fn); // false
|
|
2724
|
+
* ```
|
|
2725
|
+
*
|
|
2726
|
+
* @param name The event name.
|
|
2727
|
+
* @param handler The handler reference to remove.
|
|
2728
|
+
* @returns `true` if removed, `false` if no match was registered.
|
|
2729
|
+
*/
|
|
2730
|
+
off<Ev extends JssmEventName>(name: Ev, handler: JssmEventHandler<mDT, Ev>): boolean;
|
|
2731
|
+
/**
|
|
2732
|
+
* Remove one event-subscription entry from its set and keep
|
|
2733
|
+
* {@link Machine._event_listener_count} in sync. The count is decremented
|
|
2734
|
+
* only when the entry was actually present, so calling a stale unsubscribe
|
|
2735
|
+
* closure (or removing an already-fired `once` entry) is idempotent and
|
|
2736
|
+
* cannot drive the count negative.
|
|
2737
|
+
*
|
|
2738
|
+
* @param set The per-event-name subscription set.
|
|
2739
|
+
* @param entry The entry to remove.
|
|
2740
|
+
* @internal
|
|
2741
|
+
*/
|
|
2742
|
+
_unsubscribe_entry(set: Set<JssmEventEntry<any, any>>, entry: JssmEventEntry<any, any>): void;
|
|
2743
|
+
/**
|
|
2744
|
+
* Shared registration core used by {@link Machine.on} and
|
|
2745
|
+
* {@link Machine.once}. Normalizes the optional filter argument and
|
|
2746
|
+
* installs the entry into the per-event subscription set.
|
|
2747
|
+
*
|
|
2748
|
+
* @internal
|
|
2749
|
+
*/
|
|
2750
|
+
_subscribe<Ev extends JssmEventName>(name: Ev, filterOrFn: JssmEventFilter<mDT, Ev> | JssmEventHandler<mDT, Ev>, maybeFn: JssmEventHandler<mDT, Ev> | undefined, once: boolean): JssmUnsubscribe;
|
|
2751
|
+
/**
|
|
2752
|
+
* Invoke a single event-handler entry, respecting its filter, once-removal
|
|
2753
|
+
* semantics, and the error re-fire / recursion-guard logic. Extracted so
|
|
2754
|
+
* {@link _fire} can share identical behavior between the size-1 fast-path
|
|
2755
|
+
* and the general snapshotted loop.
|
|
2756
|
+
*
|
|
2757
|
+
* @param entry - The subscriber descriptor to invoke.
|
|
2758
|
+
* @param set - The live Set that owns `entry`; needed for once-removal.
|
|
2759
|
+
* @param name - The event name being dispatched (used in error re-fires).
|
|
2760
|
+
* @param detail - The event payload forwarded to the handler.
|
|
2761
|
+
*
|
|
2762
|
+
* @internal
|
|
2763
|
+
*/
|
|
2764
|
+
_fire_one<Ev extends JssmEventName>(entry: JssmEventEntry<mDT, Ev>, set: Set<JssmEventEntry<any, any>>, name: Ev, detail: JssmEventDetailMap<mDT>[Ev]): void;
|
|
2765
|
+
/**
|
|
2766
|
+
* Dispatch an event to every registered subscriber in registration
|
|
2767
|
+
* order. Filters are checked first; non-matching handlers are skipped
|
|
2768
|
+
* without invoking the handler. Exceptions thrown by a handler are
|
|
2769
|
+
* caught and re-emitted as an `error` event so subsequent handlers
|
|
2770
|
+
* still run.
|
|
2771
|
+
*
|
|
2772
|
+
* Re-entry into the `error` event itself is guarded — if an `error`
|
|
2773
|
+
* handler throws, the new exception is swallowed rather than rebroadcast
|
|
2774
|
+
* to avoid an infinite loop.
|
|
2775
|
+
*
|
|
2776
|
+
* When exactly one subscriber is registered the common case avoids the
|
|
2777
|
+
* `Array.from(set)` snapshot allocation by capturing the lone entry into a
|
|
2778
|
+
* local first — equivalent to a 1-element snapshot but allocation-free.
|
|
2779
|
+
* The general path still snapshots for re-entrancy safety.
|
|
2780
|
+
*
|
|
2781
|
+
* @internal
|
|
2782
|
+
*/
|
|
2783
|
+
/**
|
|
2784
|
+
* Whether at least one live subscriber is registered for `name`. Used by
|
|
2785
|
+
* the transition-commit observation block to skip building a detail
|
|
2786
|
+
* literal that {@link Machine._fire} would immediately discard — a panel
|
|
2787
|
+
* listening only to `'transition'` (fsl-bind, fsl-viz, fsl-info-panel)
|
|
2788
|
+
* previously paid for the exit/entry/data-change detail allocations on
|
|
2789
|
+
* every transition. Read at fire time, so a listener installed by a
|
|
2790
|
+
* pre-hook is still seen (#671).
|
|
2791
|
+
*
|
|
2792
|
+
* @param name The event name to probe.
|
|
2793
|
+
* @returns `true` when a subsequent `_fire(name, ...)` would reach at
|
|
2794
|
+
* least one handler.
|
|
2795
|
+
*
|
|
2796
|
+
* ```typescript
|
|
2797
|
+
* machine.on('transition', () => {});
|
|
2798
|
+
* machine._has_subscribers('transition'); // true
|
|
2799
|
+
* machine._has_subscribers('exit'); // false
|
|
2800
|
+
* ```
|
|
2801
|
+
*
|
|
2802
|
+
* @see Machine._fire
|
|
2803
|
+
* @internal
|
|
2804
|
+
*/
|
|
2805
|
+
_has_subscribers(name: JssmEventName): boolean;
|
|
2806
|
+
_fire<Ev extends JssmEventName>(name: Ev, detail: JssmEventDetailMap<mDT>[Ev]): void;
|
|
2807
|
+
/** Low-level hook registration. Installs a handler described by a
|
|
2808
|
+
* {@link HookDescription} into the appropriate internal map. Prefer the
|
|
2809
|
+
* convenience wrappers ({@link hook}, {@link hook_entry}, etc.) over
|
|
2810
|
+
* calling this directly.
|
|
2811
|
+
* @param HookDesc - A hook descriptor specifying kind, states, and handler.
|
|
2812
|
+
*/
|
|
2813
|
+
/**
|
|
2814
|
+
* Validate a {@link HookDescription} before registration. Every hook needs
|
|
2815
|
+
* a `handler` function, and each kind's identifying spatial fields
|
|
2816
|
+
* (`from`/`to`/`action`) must be exactly those `set_hook` reads for that
|
|
2817
|
+
* kind — present when required, absent otherwise. This turns a mis-shaped
|
|
2818
|
+
* descriptor into a thrown error instead of a silently dead hook keyed on
|
|
2819
|
+
* `undefined` (e.g. an `exit` hook handed `to` instead of `from`, #734).
|
|
2820
|
+
*
|
|
2821
|
+
* @param HookDesc - The descriptor about to be registered.
|
|
2822
|
+
* @throws JssmError if the kind is unknown, the handler is not a function, a
|
|
2823
|
+
* required field is missing, or an inapplicable field is present.
|
|
2824
|
+
*
|
|
2825
|
+
* @example
|
|
2826
|
+
* const m = sm`a -> b;`;
|
|
2827
|
+
* // an exit hook is keyed by `from`, so supplying `to` is rejected:
|
|
2828
|
+
* expect(() => m.set_hook({ kind: 'exit', to: 'a', handler: () => true })).toThrow();
|
|
2829
|
+
*/
|
|
2830
|
+
_validate_hook_description(HookDesc: HookDescription<mDT>): void;
|
|
2831
|
+
set_hook(HookDesc: HookDescription<mDT>): void;
|
|
2832
|
+
/**
|
|
2833
|
+
* Remove a previously-registered hook described by a
|
|
2834
|
+
* {@link HookDescription}. Match is by `kind` + identifying keys
|
|
2835
|
+
* (`from`/`to`/`action`/etc.), not by handler reference — there is one
|
|
2836
|
+
* hook per slot in the registry, so the description uniquely identifies
|
|
2837
|
+
* which one to clear. Fires a `hook-removal` event for inspector tools.
|
|
2838
|
+
*
|
|
2839
|
+
* This is the symmetric counterpart of {@link Machine.set_hook} for the
|
|
2840
|
+
* event-bridging use case (#638). Reasoning about hooks via observation
|
|
2841
|
+
* events requires being able to observe their disappearance too.
|
|
2842
|
+
*
|
|
2843
|
+
* ```typescript
|
|
2844
|
+
* const m = sm`a -> b;`;
|
|
2845
|
+
* const fn = () => true;
|
|
2846
|
+
* m.set_hook({ kind: 'hook', from: 'a', to: 'b', handler: fn });
|
|
2847
|
+
* m.remove_hook({ kind: 'hook', from: 'a', to: 'b', handler: fn });
|
|
2848
|
+
* ```
|
|
2849
|
+
*
|
|
2850
|
+
* @param HookDesc - A hook descriptor identifying the hook to remove.
|
|
2851
|
+
* @returns `true` if a hook was removed, `false` otherwise.
|
|
2852
|
+
*/
|
|
2853
|
+
remove_hook(HookDesc: HookDescription<mDT>): boolean;
|
|
2854
|
+
/** Register a pre-transition hook on a specific edge. Fires before
|
|
2855
|
+
* transitioning from `from` to `to`. If the handler returns `false`, the
|
|
2856
|
+
* transition is blocked.
|
|
2857
|
+
*
|
|
2858
|
+
* ```typescript
|
|
2859
|
+
* const m = sm`a -> b -> c;`;
|
|
2860
|
+
* m.hook('a', 'b', () => console.log('a->b'));
|
|
2861
|
+
* ```
|
|
2862
|
+
*
|
|
2863
|
+
* @param from - Source state name.
|
|
2864
|
+
* @param to - Target state name.
|
|
2865
|
+
* @param handler - Callback invoked before the transition.
|
|
2866
|
+
* @returns `this` for chaining.
|
|
2867
|
+
*/
|
|
2868
|
+
hook(from: string, to: string, handler: HookHandler<mDT>): Machine<mDT>;
|
|
2869
|
+
/** Register a pre-transition hook on a specific action-labeled edge.
|
|
2870
|
+
* @param from - Source state name.
|
|
2871
|
+
* @param to - Target state name.
|
|
2872
|
+
* @param action - The action label that triggers this hook.
|
|
2873
|
+
* @param handler - Callback invoked before the transition.
|
|
2874
|
+
* @returns `this` for chaining.
|
|
2875
|
+
*/
|
|
2876
|
+
hook_action(from: string, to: string, action: string, handler: HookHandler<mDT>): Machine<mDT>;
|
|
2877
|
+
/** Register a pre-transition hook on any edge triggered by a specific action.
|
|
2878
|
+
* @param action - The action name to hook.
|
|
2879
|
+
* @param handler - Callback invoked before any transition with this action.
|
|
2880
|
+
* @returns `this` for chaining.
|
|
2881
|
+
*/
|
|
2882
|
+
hook_global_action(action: string, handler: HookHandler<mDT>): Machine<mDT>;
|
|
2883
|
+
/** Register a pre-transition hook on any action-driven transition.
|
|
2884
|
+
* @param handler - Callback invoked before any action transition.
|
|
2885
|
+
* @returns `this` for chaining.
|
|
2886
|
+
*/
|
|
2887
|
+
hook_any_action(handler: HookHandler<mDT>): Machine<mDT>;
|
|
2888
|
+
/** Register a pre-transition hook on any standard (`->`) transition.
|
|
2889
|
+
* @param handler - Callback invoked before any legal transition.
|
|
2890
|
+
* @returns `this` for chaining.
|
|
2891
|
+
*/
|
|
2892
|
+
hook_standard_transition(handler: HookHandler<mDT>): Machine<mDT>;
|
|
2893
|
+
/** Register a pre-transition hook on any main-path (`=>`) transition.
|
|
2894
|
+
* @param handler - Callback invoked before any main transition.
|
|
2895
|
+
* @returns `this` for chaining.
|
|
2896
|
+
*/
|
|
2897
|
+
hook_main_transition(handler: HookHandler<mDT>): Machine<mDT>;
|
|
2898
|
+
/** Register a pre-transition hook on any forced (`~>`) transition.
|
|
2899
|
+
* @param handler - Callback invoked before any forced transition.
|
|
2900
|
+
* @returns `this` for chaining.
|
|
2901
|
+
*/
|
|
2902
|
+
hook_forced_transition(handler: HookHandler<mDT>): Machine<mDT>;
|
|
2903
|
+
/** Register a pre-transition hook on any transition regardless of kind.
|
|
2904
|
+
* @param handler - Callback invoked before every transition.
|
|
2905
|
+
* @returns `this` for chaining.
|
|
2906
|
+
*/
|
|
2907
|
+
hook_any_transition(handler: HookHandler<mDT>): Machine<mDT>;
|
|
2908
|
+
/** Register a hook that fires when entering a specific state.
|
|
2909
|
+
* @param to - The state being entered.
|
|
2910
|
+
* @param handler - Callback invoked on entry.
|
|
2911
|
+
* @returns `this` for chaining.
|
|
2912
|
+
*/
|
|
2913
|
+
hook_entry(to: string, handler: HookHandler<mDT>): Machine<mDT>;
|
|
2914
|
+
/** Register a hook that fires when leaving a specific state.
|
|
2915
|
+
* @param from - The state being exited.
|
|
2916
|
+
* @param handler - Callback invoked on exit.
|
|
2917
|
+
* @returns `this` for chaining.
|
|
2918
|
+
*/
|
|
2919
|
+
hook_exit(from: string, handler: HookHandler<mDT>): Machine<mDT>;
|
|
2920
|
+
/** Register a hook that fires when a state's `after` timer elapses — the
|
|
2921
|
+
* delay-over companion to `a after 5s -> b;` style time transitions. It
|
|
2922
|
+
* does NOT fire when the state is entered or left by ordinary dispatch;
|
|
2923
|
+
* use {@link hook_entry} / {@link hook_exit} for those. (Versions through
|
|
2924
|
+
* 5.143.28 also spuriously fired it on entering the state, the jssm side
|
|
2925
|
+
* of StoneCypher/fsl#1327.)
|
|
2926
|
+
* @param from - The state whose `after` timer is being watched.
|
|
2927
|
+
* @param handler - Callback invoked when the timer fires, just before the
|
|
2928
|
+
* timed transition is taken; informational — its outcome
|
|
2929
|
+
* cannot reject the transition.
|
|
2930
|
+
* @returns `this` for chaining.
|
|
2931
|
+
*
|
|
2932
|
+
* @example
|
|
2933
|
+
* const m = sm`a after 1000 -> b; a -> c; c -> a;`;
|
|
2934
|
+
* let calls = 0;
|
|
2935
|
+
* m.hook_after('a', () => { calls += 1; });
|
|
2936
|
+
* m.go('c');
|
|
2937
|
+
* m.go('a');
|
|
2938
|
+
* // ordinary dispatch never fires it; only the timer elapsing does:
|
|
2939
|
+
* calls; // => 0
|
|
2940
|
+
* m.clear_state_timeout();
|
|
2941
|
+
*
|
|
2942
|
+
* @see hook_entry
|
|
2943
|
+
* @see hook_exit
|
|
2944
|
+
* @see set_state_timeout
|
|
2945
|
+
*/
|
|
2946
|
+
hook_after(from: string, handler: HookHandler<mDT>): Machine<mDT>;
|
|
2947
|
+
/** Post-transition hook on a specific edge. Fires after the transition
|
|
2948
|
+
* from `from` to `to` has completed. Cannot block the transition.
|
|
2949
|
+
* @param from - Source state name.
|
|
2950
|
+
* @param to - Target state name.
|
|
2951
|
+
* @param handler - Callback invoked after the transition.
|
|
2952
|
+
* @returns `this` for chaining.
|
|
2953
|
+
*/
|
|
2954
|
+
post_hook(from: string, to: string, handler: HookHandler<mDT>): Machine<mDT>;
|
|
2955
|
+
/** Post-transition hook on a specific action-labeled edge.
|
|
2956
|
+
* @param from - Source state name.
|
|
2957
|
+
* @param to - Target state name.
|
|
2958
|
+
* @param action - The action label.
|
|
2959
|
+
* @param handler - Callback invoked after the transition.
|
|
2960
|
+
* @returns `this` for chaining.
|
|
2961
|
+
*/
|
|
2962
|
+
post_hook_action(from: string, to: string, action: string, handler: HookHandler<mDT>): Machine<mDT>;
|
|
2963
|
+
/** Post-transition hook on any edge triggered by a specific action.
|
|
2964
|
+
* @param action - The action name.
|
|
2965
|
+
* @param handler - Callback invoked after any transition with this action.
|
|
2966
|
+
* @returns `this` for chaining.
|
|
2967
|
+
*/
|
|
2968
|
+
post_hook_global_action(action: string, handler: HookHandler<mDT>): Machine<mDT>;
|
|
2969
|
+
/** Post-transition hook on any action-driven transition.
|
|
2970
|
+
* @param handler - Callback invoked after any action transition.
|
|
2971
|
+
* @returns `this` for chaining.
|
|
2972
|
+
*/
|
|
2973
|
+
post_hook_any_action(handler: HookHandler<mDT>): Machine<mDT>;
|
|
2974
|
+
/** Post-transition hook on any standard (`->`) transition.
|
|
2975
|
+
* @param handler - Callback invoked after any legal transition.
|
|
2976
|
+
* @returns `this` for chaining.
|
|
2977
|
+
*/
|
|
2978
|
+
post_hook_standard_transition(handler: HookHandler<mDT>): Machine<mDT>;
|
|
2979
|
+
/** Post-transition hook on any main-path (`=>`) transition.
|
|
2980
|
+
* @param handler - Callback invoked after any main transition.
|
|
2981
|
+
* @returns `this` for chaining.
|
|
2982
|
+
*/
|
|
2983
|
+
post_hook_main_transition(handler: HookHandler<mDT>): Machine<mDT>;
|
|
2984
|
+
/** Post-transition hook on any forced (`~>`) transition.
|
|
2985
|
+
* @param handler - Callback invoked after any forced transition.
|
|
2986
|
+
* @returns `this` for chaining.
|
|
2987
|
+
*/
|
|
2988
|
+
post_hook_forced_transition(handler: HookHandler<mDT>): Machine<mDT>;
|
|
2989
|
+
/** Post-transition hook on any transition regardless of kind.
|
|
2990
|
+
* @param handler - Callback invoked after every transition.
|
|
2991
|
+
* @returns `this` for chaining.
|
|
2992
|
+
*/
|
|
2993
|
+
post_hook_any_transition(handler: HookHandler<mDT>): Machine<mDT>;
|
|
2994
|
+
/** Post-transition hook that fires after entering a specific state.
|
|
2995
|
+
* @param to - The state that was entered.
|
|
2996
|
+
* @param handler - Callback invoked after entry.
|
|
2997
|
+
* @returns `this` for chaining.
|
|
2998
|
+
*/
|
|
2999
|
+
post_hook_entry(to: string, handler: HookHandler<mDT>): Machine<mDT>;
|
|
3000
|
+
/** Post-transition hook that fires after leaving a specific state.
|
|
3001
|
+
* @param from - The state that was exited.
|
|
3002
|
+
* @param handler - Callback invoked after exit.
|
|
3003
|
+
* @returns `this` for chaining.
|
|
3004
|
+
*/
|
|
3005
|
+
post_hook_exit(from: string, handler: HookHandler<mDT>): Machine<mDT>;
|
|
3006
|
+
/** Register a pre-transition hook that fires **before** all other pre-hooks
|
|
3007
|
+
* on every transition. If the handler returns `false`, the transition is
|
|
3008
|
+
* blocked. The handler receives an {@link EverythingHookContext} whose
|
|
3009
|
+
* `hook_name` is `'pre everything'`.
|
|
3010
|
+
*
|
|
3011
|
+
* ```typescript
|
|
3012
|
+
* const m = sm`a -> b -> c;`;
|
|
3013
|
+
* m.hook_pre_everything(({ hook_name }) => {
|
|
3014
|
+
* console.log(`${hook_name} fired`);
|
|
3015
|
+
* return true;
|
|
3016
|
+
* });
|
|
3017
|
+
* ```
|
|
3018
|
+
*
|
|
3019
|
+
* @param handler - Callback invoked before all other pre-hooks.
|
|
3020
|
+
* @returns `this` for chaining.
|
|
3021
|
+
*/
|
|
3022
|
+
hook_pre_everything(handler: EverythingHookHandler<mDT>): Machine<mDT>;
|
|
3023
|
+
/** Register a pre-transition hook that fires **after** all other pre-hooks
|
|
3024
|
+
* on every transition. If the handler returns `false`, the transition is
|
|
3025
|
+
* blocked. The handler receives an {@link EverythingHookContext} whose
|
|
3026
|
+
* `hook_name` is `'everything'`.
|
|
3027
|
+
*
|
|
3028
|
+
* ```typescript
|
|
3029
|
+
* const m = sm`a -> b -> c;`;
|
|
3030
|
+
* m.hook_everything(({ hook_name }) => {
|
|
3031
|
+
* console.log(`${hook_name} fired`);
|
|
3032
|
+
* return true;
|
|
3033
|
+
* });
|
|
3034
|
+
* ```
|
|
3035
|
+
*
|
|
3036
|
+
* @param handler - Callback invoked after all other pre-hooks.
|
|
3037
|
+
* @returns `this` for chaining.
|
|
3038
|
+
*/
|
|
3039
|
+
hook_everything(handler: EverythingHookHandler<mDT>): Machine<mDT>;
|
|
3040
|
+
/** Register a post-transition hook that fires **after** all other
|
|
3041
|
+
* post-hooks on every transition. Cannot block the transition. The
|
|
3042
|
+
* handler receives an {@link EverythingHookContext} whose `hook_name` is
|
|
3043
|
+
* `'post everything'`.
|
|
3044
|
+
*
|
|
3045
|
+
* ```typescript
|
|
3046
|
+
* const m = sm`a -> b -> c;`;
|
|
3047
|
+
* m.hook_post_everything(({ hook_name }) => {
|
|
3048
|
+
* console.log(`${hook_name} fired`);
|
|
3049
|
+
* });
|
|
3050
|
+
* ```
|
|
3051
|
+
*
|
|
3052
|
+
* @param handler - Callback invoked after all other post-hooks.
|
|
3053
|
+
* @returns `this` for chaining.
|
|
3054
|
+
*/
|
|
3055
|
+
hook_post_everything(handler: PostEverythingHookHandler<mDT>): Machine<mDT>;
|
|
3056
|
+
/** Register a post-transition hook that fires **before** all other
|
|
3057
|
+
* post-hooks on every transition. Cannot block the transition. The
|
|
3058
|
+
* handler receives an {@link EverythingHookContext} whose `hook_name` is
|
|
3059
|
+
* `'pre post everything'`.
|
|
3060
|
+
*
|
|
3061
|
+
* ```typescript
|
|
3062
|
+
* const m = sm`a -> b -> c;`;
|
|
3063
|
+
* m.hook_pre_post_everything(({ hook_name }) => {
|
|
3064
|
+
* console.log(`${hook_name} fired`);
|
|
3065
|
+
* });
|
|
3066
|
+
* ```
|
|
3067
|
+
*
|
|
3068
|
+
* @param handler - Callback invoked before all other post-hooks.
|
|
3069
|
+
* @returns `this` for chaining.
|
|
3070
|
+
*/
|
|
3071
|
+
hook_pre_post_everything(handler: PostEverythingHookHandler<mDT>): Machine<mDT>;
|
|
3072
|
+
/** Get the current RNG seed used for probabilistic transitions.
|
|
3073
|
+
* @returns The numeric seed value.
|
|
3074
|
+
*/
|
|
3075
|
+
get rng_seed(): number;
|
|
3076
|
+
/** Set the RNG seed. Pass `undefined` to reseed from the current time.
|
|
3077
|
+
* Resets the internal PRNG so subsequent probabilistic operations use the
|
|
3078
|
+
* new seed.
|
|
3079
|
+
* @param to - The seed value, or `undefined` for time-based seeding.
|
|
3080
|
+
*/
|
|
3081
|
+
set rng_seed(to: number | undefined);
|
|
3082
|
+
/** Get all edges between two states (there can be multiple with
|
|
3083
|
+
* different actions).
|
|
3084
|
+
* @param from - Source state name.
|
|
3085
|
+
* @param to - Target state name.
|
|
3086
|
+
* @returns An array of matching {@link JssmTransition} objects.
|
|
3087
|
+
*/
|
|
3088
|
+
edges_between(from: string, to: string): JssmTransition<StateType, mDT>[];
|
|
3089
|
+
/*********
|
|
3090
|
+
*
|
|
3091
|
+
* Replace the current state and data with no regard to the graph.
|
|
3092
|
+
*
|
|
3093
|
+
* ```typescript
|
|
3094
|
+
* import { sm } from 'jssm';
|
|
3095
|
+
*
|
|
3096
|
+
* const machine = sm`a -> b -> c;`;
|
|
3097
|
+
* console.log( machine.state() ); // 'a'
|
|
3098
|
+
*
|
|
3099
|
+
* machine.go('b');
|
|
3100
|
+
* machine.go('c');
|
|
3101
|
+
* console.log( machine.state() ); // 'c'
|
|
3102
|
+
*
|
|
3103
|
+
* machine.override('a');
|
|
3104
|
+
* console.log( machine.state() ); // 'a'
|
|
3105
|
+
* ```
|
|
3106
|
+
*
|
|
3107
|
+
*/
|
|
3108
|
+
override(newState: StateType, newData?: mDT | undefined): void;
|
|
3109
|
+
/*********
|
|
3110
|
+
*
|
|
3111
|
+
* Fire a `'rejection'` event caused by a hook vetoing a pending transition.
|
|
3112
|
+
* Extracted from the per-call closures inside {@link transition_impl} so
|
|
3113
|
+
* that it is allocated once at class-definition time rather than on every
|
|
3114
|
+
* hooked transition.
|
|
3115
|
+
*
|
|
3116
|
+
* @param hook_name Name of the hook that rejected (e.g. `'exit'`).
|
|
3117
|
+
* @param fromState State the machine was in when the transition was
|
|
3118
|
+
* attempted; used as the `from` field of the rejection event.
|
|
3119
|
+
* @param newState State that would have been entered had the hook
|
|
3120
|
+
* passed; used as the `to` field of the rejection event.
|
|
3121
|
+
* @param fromAction Action name when the transition was initiated by an
|
|
3122
|
+
* action call; `undefined` for plain state transitions.
|
|
3123
|
+
* @param oldData Machine data at the moment the transition was
|
|
3124
|
+
* attempted, before any hook mutations.
|
|
3125
|
+
* @param newData The `next_data` value passed to the transition call.
|
|
3126
|
+
* @param wasForced Whether the transition was attempted via
|
|
3127
|
+
* `force_transition`.
|
|
3128
|
+
*
|
|
3129
|
+
* @see transition_impl
|
|
3130
|
+
* @see _fire
|
|
3131
|
+
*
|
|
3132
|
+
* @internal
|
|
3133
|
+
*
|
|
3134
|
+
*/
|
|
3135
|
+
_fire_hook_rejection(hook_name: string, fromState: StateType, newState: StateType, fromAction: StateType | undefined, oldData: mDT, newData: mDT | undefined, wasForced: boolean): void;
|
|
3136
|
+
/*********
|
|
3137
|
+
*
|
|
3138
|
+
* Fire the FSL boundary-hook actions for a single, already-committed state
|
|
3139
|
+
* change. In FSL, `do` is a synonym for `action`, so `on enter &g do 'X';`
|
|
3140
|
+
* means "when the machine crosses INTO group `g`, dispatch machine action
|
|
3141
|
+
* `X`" — and likewise `on exit` / plain-state subjects. This is the runtime
|
|
3142
|
+
* that fires those parked hooks.
|
|
3143
|
+
*
|
|
3144
|
+
* Crossing semantics (statechart convention — exits before enters):
|
|
3145
|
+
*
|
|
3146
|
+
* 1. `prev_groups` / `next_groups` are the deep (transitive) group sets of
|
|
3147
|
+
* the old and new states, from `_state_to_groups`.
|
|
3148
|
+
* 2. **Exits** fire first: every group in `prev_groups \ next_groups` with an
|
|
3149
|
+
* `onExit`, plus the plain `prev_state`'s `onExit` (when the state name
|
|
3150
|
+
* actually changed).
|
|
3151
|
+
* 3. **Enters** fire next: every group in `next_groups \ prev_groups` with an
|
|
3152
|
+
* `onEnter`, plus the plain `next_state`'s `onEnter` (when the state name
|
|
3153
|
+
* changed).
|
|
3154
|
+
* 4. A group present in BOTH sets is a transition *within* that group and
|
|
3155
|
+
* fires neither of its boundary hooks. `prev_state === next_state` fires
|
|
3156
|
+
* nothing at all.
|
|
3157
|
+
* 5. "Fire its action" is `this.action(label)`. If that action is not valid
|
|
3158
|
+
* from the current state, `action` is a safe no-op (returns `false`) — an
|
|
3159
|
+
* inapplicable boundary action never throws.
|
|
3160
|
+
* 6. Multi-membership and nesting both fan out naturally: a state in groups
|
|
3161
|
+
* A and B fires both; crossing an inner and an outer boundary fires both
|
|
3162
|
+
* levels.
|
|
3163
|
+
*
|
|
3164
|
+
* Because firing an action can drive a further transition (which crosses
|
|
3165
|
+
* more boundaries, which fires more actions), this is a bounded
|
|
3166
|
+
* run-to-completion: `_boundary_depth` tracks the live cascade depth and a
|
|
3167
|
+
* cascade deeper than `_boundary_depth_limit` throws a {@link JssmError}
|
|
3168
|
+
* rather than overflowing the stack or hanging. The limit defaults to 100
|
|
3169
|
+
* and is configurable via the `boundary_depth_limit` constructor option.
|
|
3170
|
+
*
|
|
3171
|
+
* @param prev_state The state the machine was in before this commit.
|
|
3172
|
+
* @param next_state The state the machine is in now (already committed).
|
|
3173
|
+
*
|
|
3174
|
+
* @throws {JssmError} If cascaded boundary firing exceeds `_boundary_depth_limit`
|
|
3175
|
+
* (a probable infinite loop).
|
|
3176
|
+
*
|
|
3177
|
+
* @see action
|
|
3178
|
+
* @see transition_impl
|
|
3179
|
+
*
|
|
3180
|
+
* @internal
|
|
3181
|
+
*
|
|
3182
|
+
*/
|
|
3183
|
+
_fire_boundary_actions(prev_state: StateType, next_state: StateType): void;
|
|
3184
|
+
/*********
|
|
3185
|
+
*
|
|
3186
|
+
* Shared transition core used by {@link transition}, {@link force_transition},
|
|
3187
|
+
* and {@link action}. Runs validation, fires the full hook pipeline (pre-
|
|
3188
|
+
* everything, any-action, after, any-transition, exit, named, basic,
|
|
3189
|
+
* edge-type, entry, everything), commits the new state if nothing
|
|
3190
|
+
* rejected, and returns whether the transition succeeded.
|
|
3191
|
+
*
|
|
3192
|
+
* Not meant for external use. Call one of the public wrappers instead:
|
|
3193
|
+
* - `transition` for an ordinary legal transition
|
|
3194
|
+
* - `force_transition` to bypass the legality check
|
|
3195
|
+
* - `action` to dispatch by action name rather than target state
|
|
3196
|
+
*
|
|
3197
|
+
* @remarks
|
|
3198
|
+
* Known sharp edges, carried over from the original `// TODO` comments:
|
|
3199
|
+
* - The forced-ness behavior needs to be cleaned up a lot here.
|
|
3200
|
+
* - The callbacks are not fully correct across the forced / action / plain
|
|
3201
|
+
* cases and should be revisited.
|
|
3202
|
+
* - When multiple edges exist between two states with different `kind`
|
|
3203
|
+
* values, only the first edge's kind is used to pick the edge-type hook.
|
|
3204
|
+
*
|
|
3205
|
+
* @typeparam mDT The type of the machine data member; usually omitted.
|
|
3206
|
+
*
|
|
3207
|
+
* @param newStateOrAction The target state name (for a plain or forced
|
|
3208
|
+
* transition) or the action name (when `wasAction` is true).
|
|
3209
|
+
*
|
|
3210
|
+
* @param newData Optional replacement machine data to install alongside
|
|
3211
|
+
* the transition. Hooks may further override this via complex results.
|
|
3212
|
+
*
|
|
3213
|
+
* @param wasForced `true` if the caller invoked `force_transition`, in
|
|
3214
|
+
* which case legality is checked against `valid_force_transition` rather
|
|
3215
|
+
* than `valid_transition`.
|
|
3216
|
+
*
|
|
3217
|
+
* @param wasAction `true` if the caller invoked `action`, in which case
|
|
3218
|
+
* `newStateOrAction` is an action name and the target state is looked up
|
|
3219
|
+
* via the current action edge.
|
|
3220
|
+
*
|
|
3221
|
+
* @returns `true` if the transition was valid and every hook passed;
|
|
3222
|
+
* `false` if the transition was invalid or any hook rejected.
|
|
3223
|
+
*
|
|
3224
|
+
* @internal
|
|
3225
|
+
*
|
|
3226
|
+
*/
|
|
3227
|
+
transition_impl(newStateOrAction: StateType, newData: mDT | undefined, wasForced: boolean, wasAction: boolean): boolean;
|
|
3228
|
+
/** If the current state has an `after` timeout configured, schedule it.
|
|
3229
|
+
* Called internally after each transition.
|
|
3230
|
+
*/
|
|
3231
|
+
auto_set_state_timeout(): void;
|
|
3232
|
+
/*********
|
|
3233
|
+
*
|
|
3234
|
+
* Get a truncated history of the recent states and data of the machine.
|
|
3235
|
+
* Turned off by default; configure with `.from('...', {data: 5})` by length,
|
|
3236
|
+
* or set `.history_length` at runtime.
|
|
3237
|
+
*
|
|
3238
|
+
* History *does not contain the current state*. If you want that, call
|
|
3239
|
+
* `.history_inclusive` instead.
|
|
3240
|
+
*
|
|
3241
|
+
* ```typescript
|
|
3242
|
+
* const foo = jssm.from(
|
|
3243
|
+
* "a 'next' -> b 'next' -> c 'next' -> d 'next' -> e;",
|
|
3244
|
+
* { history: 3 }
|
|
3245
|
+
* );
|
|
3246
|
+
*
|
|
3247
|
+
* foo.action('next');
|
|
3248
|
+
* foo.action('next');
|
|
3249
|
+
* foo.action('next');
|
|
3250
|
+
* foo.action('next');
|
|
3251
|
+
*
|
|
3252
|
+
* foo.history; // [ ['b',undefined], ['c',undefined], ['d',undefined] ]
|
|
3253
|
+
* ```
|
|
3254
|
+
*
|
|
3255
|
+
* Notice that the machine's current state, `e`, is not in the returned list.
|
|
3256
|
+
*
|
|
3257
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
3258
|
+
*
|
|
3259
|
+
*/
|
|
3260
|
+
get history(): [string, mDT][];
|
|
3261
|
+
/*********
|
|
3262
|
+
*
|
|
3263
|
+
* Get a truncated history of the recent states and data of the machine,
|
|
3264
|
+
* including the current state. Turned off by default; configure with
|
|
3265
|
+
* `.from('...', {data: 5})` by length, or set `.history_length` at runtime.
|
|
3266
|
+
*
|
|
3267
|
+
* History inclusive contains the current state. If you only want past
|
|
3268
|
+
* states, call `.history` instead.
|
|
3269
|
+
*
|
|
3270
|
+
* The list returned will be one longer than the history buffer kept, as the
|
|
3271
|
+
* history buffer kept gets the current state added to it to produce this
|
|
3272
|
+
* list.
|
|
3273
|
+
*
|
|
3274
|
+
* ```typescript
|
|
3275
|
+
* const foo = jssm.from(
|
|
3276
|
+
* "a 'next' -> b 'next' -> c 'next' -> d 'next' -> e;",
|
|
3277
|
+
* { history: 3 }
|
|
3278
|
+
* );
|
|
3279
|
+
*
|
|
3280
|
+
* foo.action('next');
|
|
3281
|
+
* foo.action('next');
|
|
3282
|
+
* foo.action('next');
|
|
3283
|
+
* foo.action('next');
|
|
3284
|
+
*
|
|
3285
|
+
* foo.history_inclusive; // [ ['b',undefined], ['c',undefined], ['d',undefined], ['e',undefined] ]
|
|
3286
|
+
* ```
|
|
3287
|
+
*
|
|
3288
|
+
* Notice that the machine's current state, `e`, is in the returned list.
|
|
3289
|
+
*
|
|
3290
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
3291
|
+
*
|
|
3292
|
+
*/
|
|
3293
|
+
get history_inclusive(): [string, mDT][];
|
|
3294
|
+
/*********
|
|
3295
|
+
*
|
|
3296
|
+
* Find out how long a history this machine is keeping. Defaults to zero.
|
|
3297
|
+
* Settable directly.
|
|
3298
|
+
*
|
|
3299
|
+
* ```typescript
|
|
3300
|
+
* const foo = jssm.from("a -> b;");
|
|
3301
|
+
* foo.history_length; // 0
|
|
3302
|
+
*
|
|
3303
|
+
* const bar = jssm.from("a -> b;", { history: 3 });
|
|
3304
|
+
* foo.history_length; // 3
|
|
3305
|
+
* foo.history_length = 5;
|
|
3306
|
+
* foo.history_length; // 5
|
|
3307
|
+
* ```
|
|
3308
|
+
*
|
|
3309
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
3310
|
+
*
|
|
3311
|
+
*/
|
|
3312
|
+
get history_length(): number;
|
|
3313
|
+
set history_length(to: number);
|
|
3314
|
+
/********
|
|
3315
|
+
*
|
|
3316
|
+
* Instruct the machine to complete an action. Synonym for {@link do}.
|
|
3317
|
+
*
|
|
3318
|
+
* ```typescript
|
|
3319
|
+
* const light = sm`red 'next' -> green 'next' -> yellow 'next' -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
|
|
3320
|
+
*
|
|
3321
|
+
* light.state(); // 'red'
|
|
3322
|
+
* light.action('next'); // true
|
|
3323
|
+
* light.state(); // 'green'
|
|
3324
|
+
* ```
|
|
3325
|
+
*
|
|
3326
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
3327
|
+
*
|
|
3328
|
+
* @param actionName The action to engage
|
|
3329
|
+
*
|
|
3330
|
+
* @param newData The data change to insert during the action
|
|
3331
|
+
*
|
|
3332
|
+
* @returns `true` if the action was valid and the transition occurred,
|
|
3333
|
+
* `false` otherwise.
|
|
3334
|
+
*
|
|
3335
|
+
*/
|
|
3336
|
+
action(actionName: StateType, newData?: mDT): boolean;
|
|
3337
|
+
/********
|
|
3338
|
+
*
|
|
3339
|
+
* Get the standard style for a single state. ***Does not*** include
|
|
3340
|
+
* composition from an applied theme, or things from the underlying base
|
|
3341
|
+
* stylesheet; only the modifications applied by this machine.
|
|
3342
|
+
*
|
|
3343
|
+
* ```typescript
|
|
3344
|
+
* const light = sm`a -> b;`;
|
|
3345
|
+
* console.log(light.standard_state_style);
|
|
3346
|
+
* // {}
|
|
3347
|
+
*
|
|
3348
|
+
* const light = sm`a -> b; state: { shape: circle; };`;
|
|
3349
|
+
* console.log(light.standard_state_style);
|
|
3350
|
+
* // { shape: 'circle' }
|
|
3351
|
+
* ```
|
|
3352
|
+
*
|
|
3353
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
3354
|
+
*
|
|
3355
|
+
* @returns The {@link JssmStateConfig} for standard states.
|
|
3356
|
+
*
|
|
3357
|
+
*/
|
|
3358
|
+
get standard_state_style(): JssmStateConfig;
|
|
3359
|
+
/********
|
|
3360
|
+
*
|
|
3361
|
+
* Get the hooked state style. ***Does not*** include
|
|
3362
|
+
* composition from an applied theme, or things from the underlying base
|
|
3363
|
+
* stylesheet; only the modifications applied by this machine.
|
|
3364
|
+
*
|
|
3365
|
+
* The hooked style is only applied to nodes which have a named hook in the
|
|
3366
|
+
* graph. Open hooks set through the external API aren't graphed, because
|
|
3367
|
+
* that would be literally every node.
|
|
3368
|
+
*
|
|
3369
|
+
* ```typescript
|
|
3370
|
+
* const light = sm`a -> b;`;
|
|
3371
|
+
* console.log(light.hooked_state_style);
|
|
3372
|
+
* // {}
|
|
3373
|
+
*
|
|
3374
|
+
* const light = sm`a -> b; hooked_state: { shape: circle; };`;
|
|
3375
|
+
* console.log(light.hooked_state_style);
|
|
3376
|
+
* // { shape: 'circle' }
|
|
3377
|
+
* ```
|
|
3378
|
+
*
|
|
3379
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
3380
|
+
*
|
|
3381
|
+
* @returns The {@link JssmStateConfig} for hooked states.
|
|
3382
|
+
*
|
|
3383
|
+
*/
|
|
3384
|
+
get hooked_state_style(): JssmStateConfig;
|
|
3385
|
+
/********
|
|
3386
|
+
*
|
|
3387
|
+
* Get the start state style. ***Does not*** include composition from an
|
|
3388
|
+
* applied theme, or things from the underlying base stylesheet; only the
|
|
3389
|
+
* modifications applied by this machine.
|
|
3390
|
+
*
|
|
3391
|
+
* Start states are defined by the directive `start_states`, or in absentia,
|
|
3392
|
+
* are the first mentioned state.
|
|
3393
|
+
*
|
|
3394
|
+
* ```typescript
|
|
3395
|
+
* const light = sm`a -> b;`;
|
|
3396
|
+
* console.log(light.start_state_style);
|
|
3397
|
+
* // {}
|
|
3398
|
+
*
|
|
3399
|
+
* const light = sm`a -> b; start_state: { shape: circle; };`;
|
|
3400
|
+
* console.log(light.start_state_style);
|
|
3401
|
+
* // { shape: 'circle' }
|
|
3402
|
+
* ```
|
|
3403
|
+
*
|
|
3404
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
3405
|
+
*
|
|
3406
|
+
* @returns The {@link JssmStateConfig} for start states.
|
|
3407
|
+
*
|
|
3408
|
+
*/
|
|
3409
|
+
get start_state_style(): JssmStateConfig;
|
|
3410
|
+
/********
|
|
3411
|
+
*
|
|
3412
|
+
* Get the end state style. ***Does not*** include
|
|
3413
|
+
* composition from an applied theme, or things from the underlying base
|
|
3414
|
+
* stylesheet; only the modifications applied by this machine.
|
|
3415
|
+
*
|
|
3416
|
+
* End states are defined in the directive `end_states`, and are distinct
|
|
3417
|
+
* from terminal states. End states are voluntary successful endpoints for a
|
|
3418
|
+
* process. Terminal states are states that cannot be exited. By example,
|
|
3419
|
+
* most error states are terminal states, but not end states. Also, since
|
|
3420
|
+
* some end states can be exited and are determined by hooks, such as
|
|
3421
|
+
* recursive or iterative nodes, there is such a thing as an end state that
|
|
3422
|
+
* is not a terminal state.
|
|
3423
|
+
*
|
|
3424
|
+
* ```typescript
|
|
3425
|
+
* const light = sm`a -> b;`;
|
|
3426
|
+
* console.log(light.standard_state_style);
|
|
3427
|
+
* // {}
|
|
3428
|
+
*
|
|
3429
|
+
* const light = sm`a -> b; end_state: { shape: circle; };`;
|
|
3430
|
+
* console.log(light.standard_state_style);
|
|
3431
|
+
* // { shape: 'circle' }
|
|
3432
|
+
* ```
|
|
3433
|
+
*
|
|
3434
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
3435
|
+
*
|
|
3436
|
+
* @returns The {@link JssmStateConfig} for end states.
|
|
3437
|
+
*
|
|
3438
|
+
*/
|
|
3439
|
+
get end_state_style(): JssmStateConfig;
|
|
3440
|
+
/********
|
|
3441
|
+
*
|
|
3442
|
+
* Get the terminal state style. ***Does not*** include
|
|
3443
|
+
* composition from an applied theme, or things from the underlying base
|
|
3444
|
+
* stylesheet; only the modifications applied by this machine.
|
|
3445
|
+
*
|
|
3446
|
+
* Terminal state styles are automatically determined by the machine. Any
|
|
3447
|
+
* state without a valid exit transition is terminal.
|
|
3448
|
+
*
|
|
3449
|
+
* ```typescript
|
|
3450
|
+
* const light = sm`a -> b;`;
|
|
3451
|
+
* console.log(light.terminal_state_style);
|
|
3452
|
+
* // {}
|
|
3453
|
+
*
|
|
3454
|
+
* const light = sm`a -> b; terminal_state: { shape: circle; };`;
|
|
3455
|
+
* console.log(light.terminal_state_style);
|
|
3456
|
+
* // { shape: 'circle' }
|
|
3457
|
+
* ```
|
|
3458
|
+
*
|
|
3459
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
3460
|
+
*
|
|
3461
|
+
* @returns The {@link JssmStateConfig} for terminal states.
|
|
3462
|
+
*
|
|
3463
|
+
*/
|
|
3464
|
+
get terminal_state_style(): JssmStateConfig;
|
|
3465
|
+
/********
|
|
3466
|
+
*
|
|
3467
|
+
* Get the style for the active state. ***Does not*** include
|
|
3468
|
+
* composition from an applied theme, or things from the underlying base
|
|
3469
|
+
* stylesheet; only the modifications applied by this machine.
|
|
3470
|
+
*
|
|
3471
|
+
* ```typescript
|
|
3472
|
+
* const light = sm`a -> b;`;
|
|
3473
|
+
* console.log(light.active_state_style);
|
|
3474
|
+
* // {}
|
|
3475
|
+
*
|
|
3476
|
+
* const light = sm`a -> b; active_state: { shape: circle; };`;
|
|
3477
|
+
* console.log(light.active_state_style);
|
|
3478
|
+
* // { shape: 'circle' }
|
|
3479
|
+
* ```
|
|
3480
|
+
*
|
|
3481
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
3482
|
+
*
|
|
3483
|
+
* @returns The {@link JssmStateConfig} for the active state.
|
|
3484
|
+
*
|
|
3485
|
+
*/
|
|
3486
|
+
get active_state_style(): JssmStateConfig;
|
|
3487
|
+
/********
|
|
3488
|
+
*
|
|
3489
|
+
* Generate the uniform observational-hook registry — every currently
|
|
3490
|
+
* registered hook projected onto a normalized `(kind, target, phase)` row
|
|
3491
|
+
* (megaspec §12, → #1357). The registry is *generated* on demand by
|
|
3492
|
+
* walking the concrete per-kind storage tables rather than maintained as a
|
|
3493
|
+
* second copy, so it can never drift from the tables {@link Machine.set_hook}
|
|
3494
|
+
* actually dispatches into. It is the single source of truth behind the
|
|
3495
|
+
* introspection accessors ({@link Machine.has_hook}, {@link Machine.hooks_on})
|
|
3496
|
+
* and the `hooked_state` viz styling.
|
|
3497
|
+
*
|
|
3498
|
+
* Targets are normalized: edge hooks become `{ scope: 'edge', from, to }`
|
|
3499
|
+
* (named hooks add `action`), entry/exit/after become `{ scope: 'state' }`,
|
|
3500
|
+
* global-action hooks become `{ scope: 'action' }`, and the `any-*`,
|
|
3501
|
+
* transition-class, and `everything` observers become `{ scope: 'global' }`.
|
|
3502
|
+
*
|
|
3503
|
+
* ```typescript
|
|
3504
|
+
* const m = sm`a 'go' -> b;`;
|
|
3505
|
+
* m.hook_entry('b', () => true);
|
|
3506
|
+
* m.hook_registry();
|
|
3507
|
+
* // => [ { kind: 'entry', phase: 'pre', target: { scope: 'state', state: 'b' } } ]
|
|
3508
|
+
* ```
|
|
3509
|
+
*
|
|
3510
|
+
* @returns Every registered hook as a {@link HookRegistryEntry}, in a stable
|
|
3511
|
+
* table-walk order (pre-phase tables first, then post-phase).
|
|
3512
|
+
*
|
|
3513
|
+
*/
|
|
3514
|
+
hook_registry(): HookRegistryEntry[];
|
|
3515
|
+
/********
|
|
3516
|
+
*
|
|
3517
|
+
* Does a single registry entry reference the state `state`? An entry
|
|
3518
|
+
* references a state when it is a `'state'`-scoped hook on that state, or an
|
|
3519
|
+
* `'edge'`-scoped hook whose `from` or `to` is that state. `'action'`- and
|
|
3520
|
+
* `'global'`-scoped entries reference no particular state. This is the
|
|
3521
|
+
* predicate behind both per-state introspection and the `hooked_state`
|
|
3522
|
+
* styling layer.
|
|
3523
|
+
*
|
|
3524
|
+
* @param entry The registry entry to test.
|
|
3525
|
+
* @param state The state name to test membership of.
|
|
3526
|
+
* @returns `true` when the entry observes that state.
|
|
3527
|
+
*
|
|
3528
|
+
*/
|
|
3529
|
+
private static _entry_touches_state;
|
|
3530
|
+
/********
|
|
3531
|
+
*
|
|
3532
|
+
* Does a single registry entry match a `{ from, to, action? }` edge query?
|
|
3533
|
+
* Only `'edge'`-scoped entries can match. When the query omits `action`
|
|
3534
|
+
* the entry's action (if any) is ignored; when the query supplies `action`
|
|
3535
|
+
* it must match exactly.
|
|
3536
|
+
*
|
|
3537
|
+
* @param entry The registry entry to test.
|
|
3538
|
+
* @param from The edge origin to match.
|
|
3539
|
+
* @param to The edge destination to match.
|
|
3540
|
+
* @param action Optional named action to match exactly.
|
|
3541
|
+
* @returns `true` when the entry observes that edge.
|
|
3542
|
+
*
|
|
3543
|
+
*/
|
|
3544
|
+
private static _entry_matches_edge;
|
|
3545
|
+
/********
|
|
3546
|
+
*
|
|
3547
|
+
* Does a single registry entry match an action name? Both `'action'`-scoped
|
|
3548
|
+
* hooks (global-action hooks) and named-edge hooks carrying that action
|
|
3549
|
+
* count as matches.
|
|
3550
|
+
*
|
|
3551
|
+
* @param entry The registry entry to test.
|
|
3552
|
+
* @param action The action name to match.
|
|
3553
|
+
* @returns `true` when the entry observes that action.
|
|
3554
|
+
*
|
|
3555
|
+
*/
|
|
3556
|
+
private static _entry_matches_action;
|
|
3557
|
+
/********
|
|
3558
|
+
*
|
|
3559
|
+
* Does a single registry entry match a named state group? Only
|
|
3560
|
+
* `'group'`-scoped entries (FSL group-boundary hooks) match. Group hooks
|
|
3561
|
+
* are matched by group name only — they deliberately do not propagate to
|
|
3562
|
+
* member states, so a member-state query never returns them.
|
|
3563
|
+
*
|
|
3564
|
+
* @param entry The registry entry to test.
|
|
3565
|
+
* @param group The group name to match.
|
|
3566
|
+
* @returns `true` when the entry observes that group's boundary.
|
|
3567
|
+
*
|
|
3568
|
+
*/
|
|
3569
|
+
private static _entry_matches_group;
|
|
3570
|
+
/********
|
|
3571
|
+
*
|
|
3572
|
+
* Return every registry entry observing the given target (megaspec §12).
|
|
3573
|
+
* The `query` selects the target shape:
|
|
3574
|
+
*
|
|
3575
|
+
* - a bare **state name** matches entry/exit/after hooks on that state, its
|
|
3576
|
+
* state-boundary hooks, and every edge hook touching it (`from` or `to`),
|
|
3577
|
+
* - a `{ from, to, action? }` **edge** matches edge hooks on that
|
|
3578
|
+
* transition (optionally narrowed to the named action),
|
|
3579
|
+
* - a `{ action }` **action** matches global-action and named-edge hooks
|
|
3580
|
+
* carrying that action,
|
|
3581
|
+
* - a `{ group }` **group** matches that group's boundary hooks (group hooks
|
|
3582
|
+
* are matched by name only and do not propagate to member states).
|
|
3583
|
+
*
|
|
3584
|
+
* ```typescript
|
|
3585
|
+
* const m = sm`a 'go' -> b;`;
|
|
3586
|
+
* m.hook_entry('b', () => true);
|
|
3587
|
+
* m.hooks_on('b').length; // 1
|
|
3588
|
+
* m.hooks_on({ from: 'a', to: 'b' }); // [] (no edge hook registered)
|
|
3589
|
+
* ```
|
|
3590
|
+
*
|
|
3591
|
+
* @param query The {@link HookQuery} naming the target to inspect.
|
|
3592
|
+
* @returns The matching {@link HookRegistryEntry} rows (possibly empty).
|
|
3593
|
+
*
|
|
3594
|
+
*/
|
|
3595
|
+
hooks_on(query: HookQuery): HookRegistryEntry[];
|
|
3596
|
+
/********
|
|
3597
|
+
*
|
|
3598
|
+
* Is at least one observational hook bound to the given target (megaspec
|
|
3599
|
+
* §12)? The `query` is read exactly as in {@link Machine.hooks_on}. An
|
|
3600
|
+
* optional `phase` narrows the test to pre- or post-transition hooks only;
|
|
3601
|
+
* omitted, either phase satisfies it.
|
|
3602
|
+
*
|
|
3603
|
+
* ```typescript
|
|
3604
|
+
* const m = sm`a -> b;`;
|
|
3605
|
+
* m.has_hook('b'); // false
|
|
3606
|
+
* m.hook_entry('b', () => true);
|
|
3607
|
+
* m.has_hook('b'); // true
|
|
3608
|
+
* m.has_hook('b', 'post'); // false (the entry hook is pre-phase)
|
|
3609
|
+
* ```
|
|
3610
|
+
*
|
|
3611
|
+
* @param query The {@link HookQuery} naming the target to inspect.
|
|
3612
|
+
* @param phase Optional {@link HookPhase} to restrict the test to.
|
|
3613
|
+
* @returns `true` when a matching hook exists.
|
|
3614
|
+
*
|
|
3615
|
+
*/
|
|
3616
|
+
has_hook(query: HookQuery, phase?: HookPhase): boolean;
|
|
3617
|
+
/********
|
|
3618
|
+
*
|
|
3619
|
+
* Does the given state carry any observational hook — i.e. should it receive
|
|
3620
|
+
* the `hooked_state` viz styling? True when an entry/exit/after hook is
|
|
3621
|
+
* bound to the state, any edge hook touches it, or the state has its own
|
|
3622
|
+
* boundary hook. Group-boundary hooks do *not* count here — they are
|
|
3623
|
+
* matched by group only and never propagate to member states. Powers the
|
|
3624
|
+
* `hooked` styling layer in {@link Machine.resolve_state_config}; replaces
|
|
3625
|
+
* the long-stubbed `has_hooks` placeholder (megaspec §12).
|
|
3626
|
+
*
|
|
3627
|
+
* ```typescript
|
|
3628
|
+
* const m = sm`a -> b;`;
|
|
3629
|
+
* m.state_has_hooks('a'); // false
|
|
3630
|
+
* m.hook_exit('a', () => true);
|
|
3631
|
+
* m.state_has_hooks('a'); // true
|
|
3632
|
+
* ```
|
|
3633
|
+
*
|
|
3634
|
+
* @param state The state to test.
|
|
3635
|
+
* @returns `true` when the state is observed by at least one hook.
|
|
3636
|
+
*
|
|
3637
|
+
*/
|
|
3638
|
+
state_has_hooks(state: StateType): boolean;
|
|
3639
|
+
/********
|
|
3640
|
+
*
|
|
3641
|
+
* Returns the list of resolved theme implementations for this machine, in
|
|
3642
|
+
* the order they should layer (outer/base-most first). Each declared theme
|
|
3643
|
+
* name is mapped through {@link theme_mapping}; unknown names are skipped.
|
|
3644
|
+
*
|
|
3645
|
+
* The list is reversed relative to declaration order to match the historical
|
|
3646
|
+
* layering of {@link style_for}: a later-declared theme layers under an
|
|
3647
|
+
* earlier-declared one.
|
|
3648
|
+
*
|
|
3649
|
+
* @returns The resolved {@link JssmBaseTheme} stack, base-most first.
|
|
3650
|
+
*
|
|
3651
|
+
* @internal
|
|
3652
|
+
*
|
|
3653
|
+
*/
|
|
3654
|
+
_resolved_themes(): JssmBaseTheme[];
|
|
3655
|
+
/********
|
|
3656
|
+
*
|
|
3657
|
+
* Reads the condensed per-state style fields (`color`, `shape`, …) out of a
|
|
3658
|
+
* state's declaration into a fresh {@link JssmStateConfig} — the tier-5
|
|
3659
|
+
* "`state foo : { … }`" contribution of the config cascade. A state with no
|
|
3660
|
+
* declaration yields an all-`undefined` config (which contributes nothing
|
|
3661
|
+
* once folded with {@link merge_state_config}).
|
|
3662
|
+
*
|
|
3663
|
+
* @param state The state whose per-state declared style is wanted.
|
|
3664
|
+
*
|
|
3665
|
+
* @returns The per-state style config (fields may be `undefined`).
|
|
3666
|
+
*
|
|
3667
|
+
* @internal
|
|
3668
|
+
*
|
|
3669
|
+
*/
|
|
3670
|
+
_individual_state_config(state: StateType): JssmStateConfig;
|
|
3671
|
+
/********
|
|
3672
|
+
*
|
|
3673
|
+
* Orders the groups a state belongs to by nesting depth for the config
|
|
3674
|
+
* cascade — outermost first, innermost last — so that, folded in order,
|
|
3675
|
+
* the innermost (nearest / smallest {@link membership_distance}) group's
|
|
3676
|
+
* metadata wins. Equal-distance groups are ordered by group declaration
|
|
3677
|
+
* order, so a later-declared group of the same depth wins the tie.
|
|
3678
|
+
*
|
|
3679
|
+
* Concretely: groups are sorted by descending membership distance (largest
|
|
3680
|
+
* distance applied first / wins least), and for equal distances by
|
|
3681
|
+
* ascending declaration index (later index applied last / wins most).
|
|
3682
|
+
*
|
|
3683
|
+
* @param state The state whose containing groups are being ordered.
|
|
3684
|
+
*
|
|
3685
|
+
* @returns The containing group names, ordered for outer→inner folding
|
|
3686
|
+
* (the last entry wins).
|
|
3687
|
+
*
|
|
3688
|
+
* @internal
|
|
3689
|
+
*
|
|
3690
|
+
*/
|
|
3691
|
+
_groups_by_depth(state: StateType): string[];
|
|
3692
|
+
/********
|
|
3693
|
+
*
|
|
3694
|
+
* Folds the static tiers 1–5 of the unified config cascade for a state, plus
|
|
3695
|
+
* — when `active` is set — the active-state THEME layers, which historically
|
|
3696
|
+
* sit just below the per-state config so that a `state foo : { … }` block
|
|
3697
|
+
* still overrides a theme's `active` styling. The user `active_state : { … }`
|
|
3698
|
+
* overlay (tier 6) is NOT applied here; it is layered on top by
|
|
3699
|
+
* {@link resolve_state_config} so it wins over per-state config.
|
|
3700
|
+
*
|
|
3701
|
+
* Tiers, folded least-specific → most-specific with {@link merge_state_config}
|
|
3702
|
+
* (later wins, never throwing on a cross-tier key collision):
|
|
3703
|
+
*
|
|
3704
|
+
* 1. theme defaults — `base_theme.state`, then each selected theme's
|
|
3705
|
+
* `.state` block.
|
|
3706
|
+
* 2. `default_state_config` (the implicit `state : { … }` root over every
|
|
3707
|
+
* state).
|
|
3708
|
+
* 3. static per-kind defaults selected by structural kind — terminal,
|
|
3709
|
+
* then start, then end — each contributing its `base_theme.<kind>`,
|
|
3710
|
+
* selected themes' `.<kind>`, and the machine's `default_<kind>_state_config`.
|
|
3711
|
+
* When `active`, the active-state theme layers (`base_theme.active` and
|
|
3712
|
+
* each selected theme's `.active`) are folded here too.
|
|
3713
|
+
* 4. group metadata, depth-ordered outer→inner (see {@link _groups_by_depth}),
|
|
3714
|
+
* each group's RAW `{ declarations }` already condensed at construction.
|
|
3715
|
+
* 5. the per-state `state foo : { … }` config.
|
|
3716
|
+
*
|
|
3717
|
+
* @param state The state to resolve config for.
|
|
3718
|
+
* @param active Whether to include the active-state theme layers (true only
|
|
3719
|
+
* for the machine's currently-occupied state).
|
|
3720
|
+
*
|
|
3721
|
+
* @returns The composited tiers-1–5 {@link JssmStateConfig} for the state.
|
|
3722
|
+
*
|
|
3723
|
+
* @internal
|
|
3724
|
+
*
|
|
3725
|
+
*/
|
|
3726
|
+
_compose_state_config(state: StateType, active: boolean): JssmStateConfig;
|
|
3727
|
+
/********
|
|
3728
|
+
*
|
|
3729
|
+
* Resolves the full unified style/config cascade for a state — the runtime
|
|
3730
|
+
* successor to the ad-hoc layer merge {@link style_for} used to perform.
|
|
3731
|
+
*
|
|
3732
|
+
* For any state OTHER than the current one, this returns the memoized static
|
|
3733
|
+
* resolution (tiers 1–5; see {@link _compose_state_config}) — theme →
|
|
3734
|
+
* `default_state_config` → per-kind defaults → depth-ordered group metadata →
|
|
3735
|
+
* per-state config. The cache is keyed by state and never invalidated, since
|
|
3736
|
+
* those tiers do not depend on which state is current.
|
|
3737
|
+
*
|
|
3738
|
+
* For the machine's CURRENTLY-occupied state the result is recomputed each
|
|
3739
|
+
* call (never cached) and additionally carries the dynamic `active_state`
|
|
3740
|
+
* layers: the active-state THEME layers fold in just below the per-state
|
|
3741
|
+
* config (tier 3-active), and the user `active_state : { … }` overlay folds
|
|
3742
|
+
* in LAST (tier 6), on top of everything, so it wins over per-state config.
|
|
3743
|
+
* Every fold uses {@link merge_state_config}, so a key set at a lower tier is
|
|
3744
|
+
* overridden — never rejected — by a higher one.
|
|
3745
|
+
*
|
|
3746
|
+
* ```typescript
|
|
3747
|
+
* import { sm } from 'jssm';
|
|
3748
|
+
*
|
|
3749
|
+
* const m = sm`&busy : [working]; idle 'go' -> working; state &busy : { color: orange; };`;
|
|
3750
|
+
* m.resolve_state_config('working').color; // '#ffa500ff' — from group &busy
|
|
3751
|
+
* ```
|
|
3752
|
+
*
|
|
3753
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
3754
|
+
*
|
|
3755
|
+
* @param state The state to compute the composite config for.
|
|
3756
|
+
*
|
|
3757
|
+
* @returns The fully composited {@link JssmStateConfig} for the state,
|
|
3758
|
+
* including the active overlay when the state is current.
|
|
3759
|
+
*
|
|
3760
|
+
* @see style_for
|
|
3761
|
+
*
|
|
3762
|
+
*/
|
|
3763
|
+
resolve_state_config(state: StateType): JssmStateConfig;
|
|
3764
|
+
/********
|
|
3765
|
+
*
|
|
3766
|
+
* Gets the composite style for a specific node — the public viz entry point,
|
|
3767
|
+
* now a thin wrapper over the unified config cascade in
|
|
3768
|
+
* {@link resolve_state_config}.
|
|
3769
|
+
*
|
|
3770
|
+
* The order of composition runs least-specific to most-specific: theme
|
|
3771
|
+
* defaults, then the `default_state_config` root, then per-kind defaults
|
|
3772
|
+
* (terminal, start, end), then depth-ordered group metadata (inner groups
|
|
3773
|
+
* winning over outer), then the per-state config, and finally — for the
|
|
3774
|
+
* current state only — the active overlay. Last wins at every tier.
|
|
3775
|
+
*
|
|
3776
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
3777
|
+
*
|
|
3778
|
+
* @param state The state to compute the composite style for.
|
|
3779
|
+
*
|
|
3780
|
+
* @returns The fully composited {@link JssmStateConfig} for the given state.
|
|
3781
|
+
*
|
|
3782
|
+
* @see resolve_state_config
|
|
3783
|
+
*
|
|
3784
|
+
*/
|
|
3785
|
+
style_for(state: StateType): JssmStateConfig;
|
|
3786
|
+
/********
|
|
3787
|
+
*
|
|
3788
|
+
* Instruct the machine to complete an action. Synonym for {@link action}.
|
|
3789
|
+
*
|
|
3790
|
+
* ```typescript
|
|
3791
|
+
* const light = sm`
|
|
3792
|
+
* off 'start' -> red;
|
|
3793
|
+
* red 'next' -> green 'next' -> yellow 'next' -> red;
|
|
3794
|
+
* [red yellow green] 'shutdown' ~> off;
|
|
3795
|
+
* `;
|
|
3796
|
+
*
|
|
3797
|
+
* light.state(); // 'off'
|
|
3798
|
+
* light.do('start'); // true
|
|
3799
|
+
* light.state(); // 'red'
|
|
3800
|
+
* light.do('next'); // true
|
|
3801
|
+
* light.state(); // 'green'
|
|
3802
|
+
* light.do('next'); // true
|
|
3803
|
+
* light.state(); // 'yellow'
|
|
3804
|
+
* light.do('dance'); // !! false - no such action
|
|
3805
|
+
* light.state(); // 'yellow'
|
|
3806
|
+
* light.do('start'); // !! false - yellow does not have the action start
|
|
3807
|
+
* light.state(); // 'yellow'
|
|
3808
|
+
* ```
|
|
3809
|
+
*
|
|
3810
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
3811
|
+
*
|
|
3812
|
+
* @param actionName The action to engage
|
|
3813
|
+
*
|
|
3814
|
+
* @param newData The data change to insert during the action
|
|
3815
|
+
*
|
|
3816
|
+
* @returns `true` if the action was valid and the transition occurred,
|
|
3817
|
+
* `false` otherwise.
|
|
3818
|
+
*
|
|
3819
|
+
*/
|
|
3820
|
+
do(actionName: StateType, newData?: mDT): boolean;
|
|
3821
|
+
/********
|
|
3822
|
+
*
|
|
3823
|
+
* Instruct the machine to complete a transition. Synonym for {@link go}.
|
|
3824
|
+
*
|
|
3825
|
+
* ```typescript
|
|
3826
|
+
* const light = sm`
|
|
3827
|
+
* off 'start' -> red;
|
|
3828
|
+
* red 'next' -> green 'next' -> yellow 'next' -> red;
|
|
3829
|
+
* [red yellow green] 'shutdown' ~> off;
|
|
3830
|
+
* `;
|
|
3831
|
+
*
|
|
3832
|
+
* light.state(); // 'off'
|
|
3833
|
+
* light.go('red'); // true
|
|
3834
|
+
* light.state(); // 'red'
|
|
3835
|
+
* light.go('green'); // true
|
|
3836
|
+
* light.state(); // 'green'
|
|
3837
|
+
* light.go('blue'); // !! false - no such state
|
|
3838
|
+
* light.state(); // 'green'
|
|
3839
|
+
* light.go('red'); // !! false - green may not go directly to red, only to yellow
|
|
3840
|
+
* light.state(); // 'green'
|
|
3841
|
+
* ```
|
|
3842
|
+
*
|
|
3843
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
3844
|
+
*
|
|
3845
|
+
* @param newState The state to switch to
|
|
3846
|
+
*
|
|
3847
|
+
* @param newData The data change to insert during the transition
|
|
3848
|
+
*
|
|
3849
|
+
* @returns `true` if the transition was legal and occurred, `false` otherwise.
|
|
3850
|
+
*
|
|
3851
|
+
*/
|
|
3852
|
+
transition(newState: StateType, newData?: mDT): boolean;
|
|
3853
|
+
/********
|
|
3854
|
+
*
|
|
3855
|
+
* Instruct the machine to complete a transition. Synonym for {@link transition}.
|
|
3856
|
+
*
|
|
3857
|
+
* ```typescript
|
|
3858
|
+
* const light = sm`red -> green -> yellow -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
|
|
3859
|
+
*
|
|
3860
|
+
* light.state(); // 'red'
|
|
3861
|
+
* light.go('green'); // true
|
|
3862
|
+
* light.state(); // 'green'
|
|
3863
|
+
* ```
|
|
3864
|
+
*
|
|
3865
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
3866
|
+
*
|
|
3867
|
+
* @param newState The state to switch to
|
|
3868
|
+
*
|
|
3869
|
+
* @param newData The data change to insert during the transition
|
|
3870
|
+
*
|
|
3871
|
+
* @returns `true` if the transition was legal and occurred, `false` otherwise.
|
|
3872
|
+
*
|
|
3873
|
+
*/
|
|
3874
|
+
go(newState: StateType, newData?: mDT): boolean;
|
|
3875
|
+
/********
|
|
3876
|
+
*
|
|
3877
|
+
* Instruct the machine to complete a forced transition (which will reject if
|
|
3878
|
+
* called with a normal {@link transition} call.)
|
|
3879
|
+
*
|
|
3880
|
+
* ```typescript
|
|
3881
|
+
* const light = sm`red -> green -> yellow -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
|
|
3882
|
+
*
|
|
3883
|
+
* light.state(); // 'red'
|
|
3884
|
+
* light.transition('off'); // false
|
|
3885
|
+
* light.state(); // 'red'
|
|
3886
|
+
* light.force_transition('off'); // true
|
|
3887
|
+
* light.state(); // 'off'
|
|
3888
|
+
* ```
|
|
3889
|
+
*
|
|
3890
|
+
* @typeparam mDT The type of the machine data member; usually omitted
|
|
3891
|
+
*
|
|
3892
|
+
* @param newState The state to switch to
|
|
3893
|
+
*
|
|
3894
|
+
* @param newData The data change to insert during the transition
|
|
3895
|
+
*
|
|
3896
|
+
* @returns `true` if a transition (forced or otherwise) existed and occurred,
|
|
3897
|
+
* `false` otherwise.
|
|
3898
|
+
*
|
|
3899
|
+
*/
|
|
3900
|
+
force_transition(newState: StateType, newData?: mDT): boolean;
|
|
3901
|
+
/** Get the edge index for an action from the current state.
|
|
3902
|
+
* Interned dispatch: resolves via the numeric (action, from) index —
|
|
3903
|
+
* unknown action names miss without throwing.
|
|
3904
|
+
* @param action - The action name.
|
|
3905
|
+
* @returns The edge index, or `undefined` if the action is not available.
|
|
3906
|
+
*/
|
|
3907
|
+
current_action_for(action: StateType): number;
|
|
3908
|
+
/** Get the full transition object for an action from the current state.
|
|
3909
|
+
* @param action - The action name.
|
|
3910
|
+
* @returns The {@link JssmTransition} object.
|
|
3911
|
+
* @throws {JssmError} If the action is not available from the current state.
|
|
3912
|
+
*/
|
|
3913
|
+
current_action_edge_for(action: StateType): JssmTransition<StateType, mDT>;
|
|
3914
|
+
/** Check whether an action is available from the current state.
|
|
3915
|
+
* @param action - The action name to check.
|
|
3916
|
+
* @param _newData - Reserved for future data validation.
|
|
3917
|
+
* @returns `true` if the action can be taken.
|
|
3918
|
+
*/
|
|
3919
|
+
valid_action(action: StateType, _newData?: mDT): boolean;
|
|
3920
|
+
/** Check whether a transition to a given state is legal (non-forced) from
|
|
3921
|
+
* the current state.
|
|
3922
|
+
* @param newState - The target state.
|
|
3923
|
+
* @param _newData - Reserved for future data validation.
|
|
3924
|
+
* @returns `true` if the transition is legal.
|
|
3925
|
+
*/
|
|
3926
|
+
valid_transition(newState: StateType, _newData?: mDT): boolean;
|
|
3927
|
+
/** Check whether a forced transition to a given state exists from the
|
|
3928
|
+
* current state.
|
|
3929
|
+
* @param newState - The target state.
|
|
3930
|
+
* @param _newData - Reserved for future data validation.
|
|
3931
|
+
* @returns `true` if a forced (or any) transition exists.
|
|
3932
|
+
*/
|
|
3933
|
+
valid_force_transition(newState: StateType, _newData?: mDT): boolean;
|
|
3934
|
+
/** Get the instance name of this machine, if one was assigned at creation.
|
|
3935
|
+
* @returns The instance name string, or `undefined`.
|
|
3936
|
+
*/
|
|
3937
|
+
instance_name(): string | undefined;
|
|
3938
|
+
/** Get the creation date of this machine as a `Date` object.
|
|
3939
|
+
* @returns A `Date` representing when the machine was created.
|
|
3940
|
+
*/
|
|
3941
|
+
get creation_date(): Date;
|
|
3942
|
+
/** Get the creation timestamp (milliseconds since epoch).
|
|
3943
|
+
* @returns The timestamp as a number.
|
|
3944
|
+
*/
|
|
3945
|
+
get creation_timestamp(): number;
|
|
3946
|
+
/** Get the timestamp when construction began (before parsing).
|
|
3947
|
+
* @returns The start-of-construction timestamp as a number.
|
|
3948
|
+
*/
|
|
3949
|
+
get create_start_time(): number;
|
|
3950
|
+
/** Schedule an automatic transition to `next_state` after `after_time`
|
|
3951
|
+
* milliseconds. Only one timeout may be active at a time.
|
|
3952
|
+
* @param next_state - The state to transition to when the timer fires.
|
|
3953
|
+
* @param after_time - Delay in milliseconds.
|
|
3954
|
+
* @throws {JssmError} If a timeout is already pending.
|
|
3955
|
+
*/
|
|
3956
|
+
set_state_timeout(next_state: StateType, after_time: number): void;
|
|
3957
|
+
/** Cancel any pending state timeout. Safe to call when no timeout is active.
|
|
3958
|
+
*/
|
|
3959
|
+
clear_state_timeout(): void;
|
|
3960
|
+
/** Get the configured `after` timeout for a given state, if any.
|
|
3961
|
+
* @param which_state - The state to look up.
|
|
3962
|
+
* @returns A `[targetState, delayMs]` tuple, or `undefined` if no timeout
|
|
3963
|
+
* is configured for that state.
|
|
3964
|
+
*/
|
|
3965
|
+
state_timeout_for(which_state: StateType): [StateType, number] | undefined;
|
|
3966
|
+
/** Get the configured `after` timeout for the current state, if any.
|
|
3967
|
+
* @returns A `[targetState, delayMs]` tuple, or `undefined`.
|
|
3968
|
+
*/
|
|
3969
|
+
current_state_timeout(): [StateType, number] | undefined;
|
|
3970
|
+
/** Convenience method to create a new machine from a tagged template literal.
|
|
3971
|
+
* Equivalent to calling the top-level `sm` function.
|
|
3972
|
+
* @param template_strings - The template string array.
|
|
3973
|
+
* @param remainder - Interpolated values.
|
|
3974
|
+
* @returns A new {@link Machine} instance.
|
|
3975
|
+
*/
|
|
3976
|
+
sm(template_strings: TemplateStringsArray, ...remainder: any[]): Machine<mDT>;
|
|
3977
|
+
}
|
|
3978
|
+
|
|
3979
|
+
/**
|
|
3980
|
+
* Plan the frame sequence for an animated machine walk, as state names.
|
|
3981
|
+
*
|
|
3982
|
+
* With main-path edges (FSL `=>`, `main_path === true`): start at the
|
|
3983
|
+
* machine's current state — the start state for a freshly-constructed
|
|
3984
|
+
* machine, which is what the fence pipeline always passes — and follow
|
|
3985
|
+
* main-path edges in declaration order, stopping at the first revisited
|
|
3986
|
+
* state (the animation loops, so the cycle closes visually). Without any:
|
|
3987
|
+
* tour every edge in declaration order, emitting each edge's endpoints and
|
|
3988
|
+
* collapsing consecutive duplicates.
|
|
3989
|
+
*
|
|
3990
|
+
* This is presentation, not simulation — a tour's consecutive entries need
|
|
3991
|
+
* not be legal transitions, and no machine state is mutated.
|
|
3992
|
+
*
|
|
3993
|
+
* @example
|
|
3994
|
+
* plan_walk(sm`Red => Green => Yellow => Red;`); // ['Red', 'Green', 'Yellow']
|
|
3995
|
+
*
|
|
3996
|
+
* @see encode_gif
|
|
3997
|
+
*/
|
|
3998
|
+
declare function plan_walk(machine: Machine<unknown>): string[];
|
|
3999
|
+
|
|
4000
|
+
/**
|
|
4001
|
+
* Two-layer static FSL highlighter: the SAME `fslLanguage` stream grammar and
|
|
4002
|
+
* `fslSemanticSpans` parser overlay the CodeMirror editor uses, merged into
|
|
4003
|
+
* flat runs and (optionally) serialized to HTML. There is no third
|
|
4004
|
+
* tokenizer — this is the parity guarantee between the editor and any
|
|
4005
|
+
* static render (markdown fences, the cookbook, docs).
|
|
4006
|
+
*/
|
|
4007
|
+
/** One classified slice of highlighted FSL source. */
|
|
4008
|
+
interface HighlightRun {
|
|
4009
|
+
text: string;
|
|
4010
|
+
/** Space-separated classes: `fsl-tok-*` token layer, `fsl-sem-*` semantic layer. */
|
|
4011
|
+
classes: string;
|
|
4012
|
+
/** The state name, present exactly on semantic state-name runs. */
|
|
4013
|
+
state?: string;
|
|
4014
|
+
}
|
|
4015
|
+
/**
|
|
4016
|
+
* Tokenize FSL source through the SAME two layers the editor uses — the
|
|
4017
|
+
* `fslLanguage` stream grammar for token classes and `fslSemanticSpans` for
|
|
4018
|
+
* parser-derived roles — merged into flat runs whose concatenated text
|
|
4019
|
+
* reproduces the source byte-for-byte. Semantic classes overlay token
|
|
4020
|
+
* classes (both are kept).
|
|
4021
|
+
*
|
|
4022
|
+
* This is the parity guarantee: there is no third tokenizer, so static
|
|
4023
|
+
* output can never disagree with the editor.
|
|
4024
|
+
*
|
|
4025
|
+
* @param source FSL source text to classify.
|
|
4026
|
+
* @returns Flat, gap-free, order-preserving runs; `runs.map(r => r.text).join('')` is `source`.
|
|
4027
|
+
*
|
|
4028
|
+
* @example
|
|
4029
|
+
* highlight_fsl_runs('Red -> Green;').find(r => r.state === 'Red');
|
|
4030
|
+
* // { text: 'Red', classes: 'fsl-tok-variableName fsl-sem-state', state: 'Red' }
|
|
4031
|
+
*/
|
|
4032
|
+
declare function highlight_fsl_runs(source: string): HighlightRun[];
|
|
4033
|
+
/**
|
|
4034
|
+
* Render FSL source as highlighted HTML (`<pre class="fsl-code">` inner
|
|
4035
|
+
* content) using {@link highlight_fsl_runs}. Semantic state-name spans get
|
|
4036
|
+
* `data-state`; when `inline_colors` (default true) and the state appears in
|
|
4037
|
+
* `state_colors`, an inline `style="color:…"` ties the code block's state
|
|
4038
|
+
* names to the diagram's node colors with zero host CSS.
|
|
4039
|
+
*
|
|
4040
|
+
* @param source FSL source text to render.
|
|
4041
|
+
* @param opts.state_colors Maps a state name to its diagram fill color (e.g. from `extract_state_fills`).
|
|
4042
|
+
* @param opts.inline_colors Whether to emit inline `style="color:…"` for matched states. Defaults to `true`.
|
|
4043
|
+
* @returns HTML markup for the highlighted source; unclassed runs are emitted as escaped text with no wrapping span.
|
|
4044
|
+
*
|
|
4045
|
+
* @example
|
|
4046
|
+
* highlight_fsl_html('Red -> Green;', { state_colors: new Map([['Red', '#a00']]) });
|
|
4047
|
+
* // '…<span class="… fsl-sem-state" data-state="Red" style="color:#a00">Red</span>…'
|
|
4048
|
+
*/
|
|
4049
|
+
declare function highlight_fsl_html(source: string, opts?: {
|
|
4050
|
+
state_colors?: ReadonlyMap<string, string>;
|
|
4051
|
+
inline_colors?: boolean;
|
|
4052
|
+
}): string;
|
|
4053
|
+
|
|
4054
|
+
/**
|
|
4055
|
+
* Read each state's current fill color out of a graphviz-rendered machine
|
|
4056
|
+
* SVG, keyed by state name. States whose shape carries no `fill` attribute
|
|
4057
|
+
* are omitted.
|
|
4058
|
+
*
|
|
4059
|
+
* @param svg - SVG markup from the jssm viz pipeline (`fsl_to_svg_string`).
|
|
4060
|
+
*
|
|
4061
|
+
* @example
|
|
4062
|
+
* extract_state_fills(await fsl_to_svg_string('A -> B;')); // Map { 'A' => '#…', 'B' => '#…' }
|
|
4063
|
+
*
|
|
4064
|
+
* @see patch_state_fill
|
|
4065
|
+
*/
|
|
4066
|
+
declare function extract_state_fills(svg: string): Map<string, string>;
|
|
4067
|
+
/**
|
|
4068
|
+
* Return a copy of the SVG with the named state's first shape fill replaced.
|
|
4069
|
+
* The unmatched-state case returns the input unchanged (walk truncation and
|
|
4070
|
+
* render races surface as a missing highlight, never a throw).
|
|
4071
|
+
*
|
|
4072
|
+
* @param svg - SVG markup from the jssm viz pipeline.
|
|
4073
|
+
* @param state - State name as written in FSL (unescaped).
|
|
4074
|
+
* @param fill - Any SVG paint value, e.g. `'#ff9930'`.
|
|
4075
|
+
*
|
|
4076
|
+
* @example
|
|
4077
|
+
* patch_state_fill(svg, 'Red', '#ff9930'); // Red's node now renders orange
|
|
4078
|
+
*
|
|
4079
|
+
* @see extract_state_fills
|
|
4080
|
+
*/
|
|
4081
|
+
declare function patch_state_fill(svg: string, state: string, fill: string): string;
|
|
4082
|
+
|
|
4083
|
+
export { encode_gif, extract_state_fills, highlight_fsl_html, highlight_fsl_runs, lzw_encode, patch_state_fill, plan_walk, quantize, render_fence_gif, render_fence_html, transform_markdown };
|
|
4084
|
+
export type { FenceRenderOptions, GifFrame, GifOptions, GifRenderOptions, HighlightRun, Quantized };
|