small-state 0.0.0-stage → 0.3.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/dist/index.cjs ADDED
@@ -0,0 +1,1754 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let arktype = require("arktype");
3
+ //#endregion
4
+ //#region src/shared/utils.ts
5
+ function ensureArray(v) {
6
+ return Array.isArray(v) ? v : !v ? [] : [v];
7
+ }
8
+ function assertOrThrow(validCondition, msg) {
9
+ if (!validCondition) throw new Error(msg);
10
+ return true;
11
+ }
12
+ function reportUnhandledError(err) {
13
+ setTimeout(() => {
14
+ throw err;
15
+ });
16
+ }
17
+ function deepFreeze(obj) {
18
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") return obj;
19
+ try {
20
+ if (Array.isArray(obj)) obj.forEach((el) => deepFreeze(el));
21
+ else Object.keys(obj).forEach((key) => {
22
+ const prop = obj[key];
23
+ if (!Object.isFrozen(prop)) deepFreeze(prop);
24
+ });
25
+ return Object.freeze(obj);
26
+ } catch (error) {
27
+ console.error("Error occurred in deepFreeze:", error);
28
+ return obj;
29
+ }
30
+ }
31
+ function defineFixedProperty(obj, key, value, option) {
32
+ Object.defineProperty(obj, key, {
33
+ value,
34
+ ...option
35
+ });
36
+ }
37
+ function isPlainObject(obj) {
38
+ if (obj === null || typeof obj !== "object") return false;
39
+ const proto = Object.getPrototypeOf(obj);
40
+ return proto === Object.prototype || proto === null;
41
+ }
42
+ function parentPathOf(statePath) {
43
+ return statePath.slice(0, statePath.lastIndexOf("/"));
44
+ }
45
+ function splitStPath(statePath) {
46
+ if (statePath === "") return [];
47
+ if (statePath[0] !== "/") throw new Error(`path must start with '/': "${statePath}"`);
48
+ return statePath.slice(1).split("/");
49
+ }
50
+ //#endregion
51
+ //#region src/machine/arktype/arktype.internal.ts
52
+ const AnyFn = (0, arktype.type)("Function").narrow((f) => true);
53
+ const FunctionRecord = (0, arktype.type)({ "[string]": AnyFn });
54
+ const SingleRecord = (0, arktype.type)({ "[string]": "unknown" }).narrow((value) => Object.keys(value).length === 1);
55
+ const ActionElement = arktype.type.or(AnyFn, "string", SingleRecord);
56
+ //#endregion
57
+ //#region src/machine/arktype/ark_m_config.ts
58
+ const o_Types = (0, arktype.type)({
59
+ "+": "reject",
60
+ "context?": "unknown",
61
+ "events?": "unknown",
62
+ "emittable?": "unknown",
63
+ "input?": "unknown",
64
+ "output?": "unknown"
65
+ });
66
+ const MachineConfig = (0, arktype.type)({
67
+ "+": "reject",
68
+ "types?": o_Types,
69
+ "name?": "string",
70
+ "initialState?": "string",
71
+ "initContext?": AnyFn,
72
+ "output?": AnyFn,
73
+ "guards?": FunctionRecord,
74
+ "actions?": FunctionRecord,
75
+ "services?": "Record<string, unknown>"
76
+ });
77
+ //#endregion
78
+ //#region src/machine/m.types.ts
79
+ const EntrySymbol = Symbol("Entry");
80
+ const ExitSymbol = Symbol("Exit");
81
+ const SubStatesSymbol = Symbol("SubStates");
82
+ const ParallelSymbol = Symbol("Parallel");
83
+ const InvokeSymbol = Symbol("Invoke");
84
+ const SystemEventSymbol = Symbol("SystemEvent");
85
+ const MachineSymbol = Symbol("Machine");
86
+ //#endregion
87
+ //#region src/machine/arktype/ark_normalized.ts
88
+ const NormalizedActions = ActionElement.array();
89
+ const x_NormalizedTransitions = (0, arktype.type)({
90
+ "to?": "string",
91
+ "fullTo?": "string",
92
+ actions: NormalizedActions,
93
+ guards: NormalizedActions
94
+ }).array();
95
+ const x_InternalEvent = (0, arktype.type)({
96
+ "cond?": AnyFn,
97
+ transitions: x_NormalizedTransitions
98
+ });
99
+ const ChildMachine = (0, arktype.type)({
100
+ name: "string",
101
+ provide: AnyFn,
102
+ internal: {
103
+ [MachineSymbol]: "true",
104
+ initContext: AnyFn.or("undefined"),
105
+ output: AnyFn.or("undefined"),
106
+ guards: FunctionRecord,
107
+ actions: FunctionRecord,
108
+ services: FunctionRecord,
109
+ definition: "unknown",
110
+ topLvDefItem: {
111
+ events: (0, arktype.type)({ "[string]": x_NormalizedTransitions }),
112
+ internalEvents: (0, arktype.type)({ "[string]": x_InternalEvent })
113
+ },
114
+ stateCatalog: arktype.type.instanceOf(Map).as()
115
+ }
116
+ });
117
+ const o_NormalizedInvocations = (0, arktype.type)({
118
+ "+": "reject",
119
+ mainKey: "string",
120
+ "subKey?": "string|number",
121
+ "input?": AnyFn,
122
+ emittableETypesToListen: "string[]",
123
+ src: arktype.type.or({
124
+ type: "\"function\"",
125
+ value: AnyFn
126
+ }, {
127
+ type: "\"string\"",
128
+ value: "string"
129
+ }, {
130
+ type: "\"machine\"",
131
+ value: ChildMachine
132
+ })
133
+ }).array();
134
+ const NStateItemDef = (0, arktype.type)({
135
+ "+": "reject",
136
+ pPath: "string",
137
+ final: AnyFn.or("boolean"),
138
+ entryHooks: NormalizedActions.or("null"),
139
+ exitHooks: NormalizedActions.or("null"),
140
+ invocations: o_NormalizedInvocations,
141
+ internalEvents: { "[string]": x_InternalEvent },
142
+ events: { "[string]": x_NormalizedTransitions }
143
+ });
144
+ const SubStNormalizedDefinition = (0, arktype.type)([
145
+ {
146
+ "dType?": "\"normal\"",
147
+ initial: "string | undefined",
148
+ stateOf: { "[string]": {
149
+ def: NStateItemDef,
150
+ sub: "null | this"
151
+ } }
152
+ },
153
+ "|",
154
+ {
155
+ dType: "\"regions\"",
156
+ stateOf: { "[string]": {
157
+ def: NStateItemDef,
158
+ sub: "null | this"
159
+ } }
160
+ }
161
+ ]);
162
+ //#endregion
163
+ //#region src/machine/arktype/ark_stdef.ts
164
+ const x_ActionEffects = arktype.type.or(ActionElement, ActionElement.array());
165
+ const Transition = (0, arktype.type)({
166
+ "+": "reject",
167
+ "to?": "string",
168
+ "guard?": x_ActionEffects,
169
+ "actions?": x_ActionEffects
170
+ });
171
+ const OnFnReturn = (0, arktype.type)([
172
+ "string",
173
+ AnyFn,
174
+ arktype.type.or(Transition, Transition.array())
175
+ ]).readonly();
176
+ const EntryHookReturn = (0, arktype.type)([
177
+ arktype.type.unit(EntrySymbol),
178
+ AnyFn,
179
+ "null",
180
+ x_ActionEffects
181
+ ]).readonly();
182
+ const ExitHookReturn = (0, arktype.type)([
183
+ arktype.type.unit(ExitSymbol),
184
+ AnyFn,
185
+ "null",
186
+ x_ActionEffects
187
+ ]).readonly();
188
+ const o_StDefMetaInfo = (0, arktype.type)({
189
+ "+": "reject",
190
+ "final?": AnyFn.or("boolean")
191
+ });
192
+ const o_SubStatesNormalized = (0, arktype.type)([AnyFn, SubStNormalizedDefinition]).readonly();
193
+ const o_Invocation = (0, arktype.type)([
194
+ arktype.type.unit(InvokeSymbol),
195
+ AnyFn,
196
+ "null",
197
+ arktype.type.or(AnyFn, "string", ChildMachine),
198
+ {
199
+ "+": "reject",
200
+ "subKey?": "string | number",
201
+ "input?": AnyFn
202
+ },
203
+ OnFnReturn.array()
204
+ ]).readonly();
205
+ const StateDefinition = arktype.type.or(OnFnReturn, EntryHookReturn, ExitHookReturn, o_StDefMetaInfo, o_SubStatesNormalized, o_Invocation).array().or("null");
206
+ //#endregion
207
+ //#region src/machine/machine.ts
208
+ function entryHook(...actions) {
209
+ return [
210
+ EntrySymbol,
211
+ (() => null),
212
+ null,
213
+ actions
214
+ ];
215
+ }
216
+ function exitHook(...actions) {
217
+ return [
218
+ ExitSymbol,
219
+ (() => null),
220
+ null,
221
+ actions
222
+ ];
223
+ }
224
+ function on(eventType, config) {
225
+ return [
226
+ eventType,
227
+ (() => null),
228
+ config
229
+ ];
230
+ }
231
+ function subStates(statesDefinition, initialState) {
232
+ return [(() => SubStatesSymbol), transformNormalizedDefinition(statesDefinition, initialState)];
233
+ }
234
+ function parallel(parallelDefinition) {
235
+ return [(() => ParallelSymbol), transformParallelNormalizedDefinition()(parallelDefinition)];
236
+ }
237
+ function invoke(service, ...args) {
238
+ const [config, events] = (() => {
239
+ if (!args.length) return [{}, []];
240
+ if (Array.isArray(args[0])) return [{}, args];
241
+ const [first, ...rest] = args;
242
+ return [first, rest];
243
+ })();
244
+ return [
245
+ InvokeSymbol,
246
+ (() => null),
247
+ null,
248
+ service,
249
+ config,
250
+ events
251
+ ];
252
+ }
253
+ const o_getNormalizedStDefTemplate = () => ({
254
+ def: {
255
+ pPath: "",
256
+ final: false,
257
+ entryHooks: null,
258
+ exitHooks: null,
259
+ invocations: [],
260
+ internalEvents: {},
261
+ events: {}
262
+ },
263
+ sub: null
264
+ });
265
+ function o_normalizeTransitions(transitions) {
266
+ return transitions.map(({ actions, guard, ...rest }) => ({
267
+ actions: ensureArray(actions),
268
+ guards: ensureArray(guard),
269
+ ...rest
270
+ }));
271
+ }
272
+ function x_parseStDefItems(items, stateName) {
273
+ let { def, sub } = o_getNormalizedStDefTemplate();
274
+ if (!items?.length) {
275
+ def.final = !items;
276
+ return {
277
+ def,
278
+ sub
279
+ };
280
+ }
281
+ const _getPath = () => `${def.pPath}/${stateName}`;
282
+ for (const [i, item] of items.entries()) {
283
+ if (!Array.isArray(item)) {
284
+ if ("final" in item) {
285
+ const { final } = item;
286
+ def.final = typeof final === "function" ? final : !!final;
287
+ }
288
+ continue;
289
+ }
290
+ switch (typeof item?.[0]) {
291
+ case "string": {
292
+ const [eType, _, transitions] = item;
293
+ if (Object.hasOwn(def.events, eType) || Object.hasOwn(def.internalEvents, eType)) throw new Error(`createMachine: Duplicate event definition for event "${eType}", at "${stateName}"[${i}]`);
294
+ const mid = ensureArray(transitions);
295
+ if (!mid.length || mid.some((t) => !Object.keys(t).length)) throw new Error(`createMachine: on(eventType, config): Empty config is not allowed: on("${eType}", ${JSON.stringify(transitions)}), at "${stateName}"[${i}]`);
296
+ const nTransitions = o_normalizeTransitions(mid);
297
+ switch (eType) {
298
+ case ":always:":
299
+ def.internalEvents[":always:"] = { transitions: nTransitions };
300
+ break;
301
+ case ":childDone:":
302
+ def.internalEvents[":childDone:"] = {
303
+ cond: ({ path }) => path === _getPath(),
304
+ transitions: nTransitions
305
+ };
306
+ break;
307
+ default: def.events[eType] = nTransitions;
308
+ }
309
+ break;
310
+ }
311
+ case "symbol":
312
+ switch (item[0]) {
313
+ case InvokeSymbol: {
314
+ const rawSrc = item[3];
315
+ const src = (() => {
316
+ switch (typeof rawSrc) {
317
+ case "object": return {
318
+ type: "machine",
319
+ value: rawSrc
320
+ };
321
+ case "function": return {
322
+ type: "function",
323
+ value: rawSrc
324
+ };
325
+ default: return {
326
+ type: "string",
327
+ value: rawSrc
328
+ };
329
+ }
330
+ })();
331
+ const { invocations, internalEvents } = def;
332
+ const emittableETypesToListen = [];
333
+ invocations.push({
334
+ ...item[4],
335
+ src,
336
+ emittableETypesToListen,
337
+ mainKey: ""
338
+ });
339
+ const suffixNum = invocations.length - 1;
340
+ let hasErrObserver = false;
341
+ for (const [j, [ivkEType, _, ivkTransitions]] of item[5].entries()) {
342
+ const transitions = ensureArray(ivkTransitions);
343
+ if (!transitions.length || transitions.some((t) => !Object.keys(t).length)) throw new Error(`createMachine: on(eventType, config): The 'config' argument is required, at state:"${stateName}"[${i}] > invoke events[${j}] event:"${ivkEType}"`);
344
+ const eType = `invoke/${ivkEType}[${suffixNum}]`;
345
+ if (Object.hasOwn(internalEvents, eType)) throw new Error(`createMachine: Duplicate event definition for event "${ivkEType}", at state:"${stateName}"[${i}] > invoke events[${j}]`);
346
+ internalEvents[eType] = {
347
+ cond: ({ path }) => path === _getPath(),
348
+ transitions: o_normalizeTransitions(transitions)
349
+ };
350
+ if (ivkEType === ":error:") hasErrObserver = true;
351
+ else if (ivkEType !== ":done:") emittableETypesToListen.push(ivkEType);
352
+ }
353
+ if (!hasErrObserver) internalEvents[`invoke/:error:[${suffixNum}]`] = {
354
+ cond: ({ path }) => path === _getPath(),
355
+ transitions: [{
356
+ guards: [],
357
+ actions: [({ e }) => {
358
+ throw e.error;
359
+ }]
360
+ }]
361
+ };
362
+ break;
363
+ }
364
+ case EntrySymbol:
365
+ def.entryHooks = ensureArray(item[3]);
366
+ break;
367
+ case ExitSymbol: def.exitHooks = ensureArray(item[3]);
368
+ }
369
+ break;
370
+ case "function": {
371
+ const subStDict = item[1];
372
+ if (sub) throw new Error(`createMachine: Duplicated subStates: at "${stateName}"[${i}] { ${Object.keys("stateOf" in subStDict ? subStDict.stateOf : {}).map((el) => `${el}:...`).join(", ")} }`);
373
+ sub = subStDict;
374
+ break;
375
+ }
376
+ default: throw new Error(`createMachine: Unexpected array[0] type: ${JSON.stringify(item?.[0])}`);
377
+ }
378
+ }
379
+ return {
380
+ def,
381
+ sub
382
+ };
383
+ }
384
+ function o_normalizeStates(stateDefOf) {
385
+ return Object.entries(stateDefOf).reduce((acc, [stKey, stDefs], i) => {
386
+ if (stKey.includes("/")) throw new Error(`createMachine: State names cannot contain the character "/": "${stKey}"`);
387
+ else if (Array.isArray(stDefs) || stDefs == null) try {
388
+ const { def, sub } = x_parseStDefItems(StateDefinition.assert(stDefs), stKey);
389
+ acc[stKey] = {
390
+ def,
391
+ sub
392
+ };
393
+ } catch (err) {
394
+ if (err instanceof Error) throw new Error(`createMachine:(at state "${stKey}") ${err.name}: ${err.message}`);
395
+ }
396
+ else throw new Error(`createMachine: Invalid state definition for state "${String(stKey)}". Expected an array but got ${typeof stDefs}.`);
397
+ return acc;
398
+ }, {});
399
+ }
400
+ function transformNormalizedDefinition(stateDefOf, initialState) {
401
+ const firstState = Object.keys(stateDefOf)?.[0];
402
+ return {
403
+ initial: !firstState ? void 0 : initialState && assertOrThrow(Object.hasOwn(stateDefOf, initialState), `createMachine: Invalid initialState: "${initialState}"`) ? initialState : firstState,
404
+ stateOf: o_normalizeStates(stateDefOf)
405
+ };
406
+ }
407
+ function transformParallelNormalizedDefinition() {
408
+ return (parallelDefinition) => {
409
+ return {
410
+ dType: "regions",
411
+ stateOf: Object.fromEntries(Object.entries(parallelDefinition).map(([regionName, rawDefinition]) => {
412
+ if (regionName.includes("/")) throw new Error(`createMachine: Parallel region state names cannot contain the character "/": "${regionName}"`);
413
+ const len = rawDefinition.length;
414
+ const leafDefOf = rawDefinition[len - 1] || {};
415
+ const { def } = x_parseStDefItems(rawDefinition[len - 2] || [], regionName);
416
+ return [regionName, {
417
+ def,
418
+ sub: transformNormalizedDefinition(leafDefOf, void 0)
419
+ }];
420
+ }))
421
+ };
422
+ };
423
+ }
424
+ function o_setPPathAndInvocationMainKeyThenAddCatalog(nStItemRecord, parent, addToCatalog, isRegion, addRegionPath) {
425
+ for (const [key, nState] of Object.entries(nStItemRecord)) {
426
+ const { def, sub } = nState;
427
+ def.pPath = parent;
428
+ const stPath = `${parent}/${key}`;
429
+ for (const [i, e] of def.invocations.entries()) e.mainKey = e.src.type === "string" ? e.src.value : `${stPath}[${i}]`;
430
+ addToCatalog(stPath, nState);
431
+ if (isRegion) addRegionPath(stPath);
432
+ if (sub) {
433
+ const isParallel = "dType" in sub && sub.dType === "regions";
434
+ o_setPPathAndInvocationMainKeyThenAddCatalog(sub.stateOf, stPath, addToCatalog, isParallel, addRegionPath);
435
+ }
436
+ }
437
+ }
438
+ function o_getTransitionFullPath(to, crrPath, pPath, stateCatalog) {
439
+ const pth = to[0] === "/" ? to : to.startsWith("./") ? `${crrPath}/${to.slice(2)}` : to.startsWith("../") ? `${pPath}/${to.slice(3)}` : "";
440
+ if (pth) return stateCatalog.has(pth) ? pth : "";
441
+ for (const pthFn of [() => `${crrPath}/${to}`, () => `${pPath}/${to}`]) {
442
+ const pth = pthFn();
443
+ if (stateCatalog.has(pth)) return pth;
444
+ }
445
+ return "";
446
+ }
447
+ function x_readyToValidateTransitionAndSetFullTo(stateCatalog, statePath, pPath, regionPaths) {
448
+ const ancestorRegion = regionPaths.find((regionPath) => pPath.startsWith(regionPath));
449
+ const parallelRoot = !ancestorRegion ? null : parentPathOf(ancestorRegion);
450
+ return (transitions, eType) => {
451
+ for (const transition of transitions) {
452
+ const { to } = transition;
453
+ if (!to) continue;
454
+ const tFullPath = o_getTransitionFullPath(to, statePath, pPath, stateCatalog);
455
+ if (!tFullPath) throw new Error(`createMachine: Invalid transition "${to}" in state "${statePath || "/"}" (on:"${eType}").`);
456
+ if (ancestorRegion && !tFullPath.startsWith(ancestorRegion) && tFullPath.startsWith(parallelRoot)) throw new Error(`createMachine: Transitions in a parallel state cannot target a different region: on('${eType}', ['${to}', ...]) in state "${statePath || "/"}".`);
457
+ transition.fullTo = tFullPath;
458
+ }
459
+ };
460
+ }
461
+ function o_validateTransitionAndSetFullTo(stateCatalog, regionPaths) {
462
+ stateCatalog.forEach(({ def }, statePath) => {
463
+ const { events, internalEvents, pPath } = def;
464
+ const _validateTransitionAndSetFullTo = x_readyToValidateTransitionAndSetFullTo(stateCatalog, statePath, pPath, regionPaths);
465
+ Object.entries(events).forEach(([eType, transitions]) => {
466
+ if (!transitions) return;
467
+ _validateTransitionAndSetFullTo(transitions, eType);
468
+ });
469
+ Object.entries(internalEvents).forEach(([eType, internalEvent]) => _validateTransitionAndSetFullTo(internalEvent.transitions, eType));
470
+ });
471
+ }
472
+ function getDefinitionAndCatalog(config, defineStates) {
473
+ {
474
+ const configOut = MachineConfig(config);
475
+ if (configOut instanceof arktype.type.errors) throw new Error(`createMachine: Invalid machine config: ${configOut.summary}`);
476
+ }
477
+ const rawDefinition = defineStates({
478
+ on,
479
+ entryHook,
480
+ exitHook,
481
+ subStates,
482
+ parallel,
483
+ invoke
484
+ });
485
+ const [stateDefDict, globalEvents] = Array.isArray(rawDefinition) ? [rawDefinition[rawDefinition.length - 1], rawDefinition[rawDefinition.length - 2]] : [rawDefinition, []];
486
+ {
487
+ const dType = stateDefDict === null ? "null" : typeof stateDefDict;
488
+ if (dType !== "object") throw new Error(`createMachine: Invalid state definition: Expected an object but got ${dType}.`);
489
+ if (Object.keys(stateDefDict).length === 0) throw new Error(`createMachine: No states in machine definition.`);
490
+ }
491
+ const { initial, stateOf } = transformNormalizedDefinition(stateDefDict, config.initialState);
492
+ const stateCatalog = /* @__PURE__ */ new Map();
493
+ const regionPaths = [];
494
+ o_setPPathAndInvocationMainKeyThenAddCatalog(stateOf, "", (stPath, state) => stateCatalog.set(stPath, state), false, (regionPath) => regionPaths.push(regionPath));
495
+ regionPaths.sort((a, b) => b.length - a.length);
496
+ o_validateTransitionAndSetFullTo(stateCatalog, regionPaths);
497
+ const { def: { events, internalEvents } } = x_parseStDefItems(globalEvents || [], "(root)");
498
+ {
499
+ const _validateTransitionAndSetFullTo = x_readyToValidateTransitionAndSetFullTo(stateCatalog, "", "", regionPaths);
500
+ Object.entries(events).forEach(([eType, transitions]) => {
501
+ if (!transitions) return;
502
+ _validateTransitionAndSetFullTo(transitions, eType);
503
+ });
504
+ Object.entries(internalEvents).forEach(([eType, internalEvent]) => _validateTransitionAndSetFullTo(internalEvent.transitions, eType));
505
+ }
506
+ return {
507
+ definition: {
508
+ initial,
509
+ stateOf
510
+ },
511
+ topLvDefItem: {
512
+ events,
513
+ internalEvents
514
+ },
515
+ stateCatalog,
516
+ regionPaths
517
+ };
518
+ }
519
+ function defServiceFn(fn) {
520
+ return fn;
521
+ }
522
+ function isMachine(v) {
523
+ if (!(v && typeof v === "object" && "internal" in v)) return false;
524
+ const { internal } = v;
525
+ return !!(internal && typeof internal === "object" && MachineSymbol in internal);
526
+ }
527
+ function makeMachine(config, defineStates) {
528
+ const { definition, topLvDefItem, stateCatalog } = getDefinitionAndCatalog(config, defineStates);
529
+ const { name, initContext, output, guards, actions, services } = config;
530
+ return deepFreeze({
531
+ name: name || "(machine)",
532
+ provide,
533
+ internal: {
534
+ [MachineSymbol]: true,
535
+ initContext,
536
+ output,
537
+ guards: guards || {},
538
+ actions: actions || {},
539
+ services: services || {},
540
+ definition,
541
+ topLvDefItem,
542
+ stateCatalog
543
+ }
544
+ });
545
+ }
546
+ function provide(implementations) {
547
+ const { internal } = this;
548
+ const { guards, actions, services } = internal;
549
+ return deepFreeze({
550
+ ...this,
551
+ internal: {
552
+ ...internal,
553
+ guards: {
554
+ ...guards,
555
+ ...implementations.guards
556
+ },
557
+ actions: {
558
+ ...actions,
559
+ ...implementations.actions
560
+ },
561
+ services: {
562
+ ...services,
563
+ ...implementations.services
564
+ }
565
+ }
566
+ });
567
+ }
568
+ //#endregion
569
+ //#region src/runtime/MailBox.ts
570
+ var MailBox = class {
571
+ #isActive = false;
572
+ #current = null;
573
+ #last = null;
574
+ #process;
575
+ #flush;
576
+ constructor(process, isAsync = false) {
577
+ this.#process = process;
578
+ this.#flush = isAsync ? this.#_flushAsync : this.#_flush;
579
+ }
580
+ start() {
581
+ this.#isActive = true;
582
+ this.#flush();
583
+ }
584
+ clear() {
585
+ if (this.#current) {
586
+ this.#current.next = null;
587
+ this.#last = this.#current;
588
+ }
589
+ }
590
+ enqueue(value, payload) {
591
+ const newElement = {
592
+ value,
593
+ payload,
594
+ next: null
595
+ };
596
+ if (this.#current) {
597
+ this.#last.next = newElement;
598
+ this.#last = newElement;
599
+ return;
600
+ }
601
+ this.#current = newElement;
602
+ this.#last = newElement;
603
+ if (this.#isActive) this.#flush();
604
+ }
605
+ #_flush() {
606
+ while (this.#current) {
607
+ const { value, payload } = this.#current;
608
+ this.#process(value, payload);
609
+ this.#current = this.#current.next;
610
+ }
611
+ this.#last = null;
612
+ }
613
+ async #_flushAsync() {
614
+ while (this.#current) {
615
+ const { value, payload } = this.#current;
616
+ await this.#process(value, payload);
617
+ this.#current = this.#current.next;
618
+ }
619
+ this.#last = null;
620
+ }
621
+ };
622
+ //#endregion
623
+ //#region src/runtime/runtime_utils.ts
624
+ function x_resolveActionElement(kind, type, implRecord, keyParams = void 0) {
625
+ switch (typeof type) {
626
+ case "function": return [type];
627
+ case "string":
628
+ if (!Object.hasOwn(implRecord, type)) throw new Error(`unknown ${kind} type: "${type}"`);
629
+ return [implRecord[type], keyParams];
630
+ case "object": {
631
+ const entries = Object.entries(type);
632
+ if (!(entries.length === 1 && isPlainObject(type))) throw new Error(`invalid ${kind} type: "${JSON.stringify(type)}"`);
633
+ const [key, val] = entries[0];
634
+ if (!Object.hasOwn(implRecord, key)) throw new Error(`unknown ${kind} type: "${key}"`);
635
+ return [implRecord[key], val];
636
+ }
637
+ default: throw new Error(`invalid ${kind} type: "${JSON.stringify(type)}"`);
638
+ }
639
+ }
640
+ function resolveGuardElement(type, machineGuards, keyParams = void 0) {
641
+ return x_resolveActionElement("Guard", type, machineGuards, keyParams);
642
+ }
643
+ function resolveActionElement(type, machineActions, keyParams = void 0) {
644
+ return x_resolveActionElement("Action", type, machineActions, keyParams);
645
+ }
646
+ const runtimeUtils = { makeFnBaseParam(context, event, input) {
647
+ return {
648
+ context,
649
+ c: context,
650
+ event,
651
+ e: event,
652
+ input
653
+ };
654
+ } };
655
+ function readyToEvalGuard(fnBaseParam, machineGuards) {
656
+ return (guard) => {
657
+ const [fn, params] = resolveGuardElement(guard, machineGuards);
658
+ return fn(fnBaseParam, typeof params !== "function" ? params : params(fnBaseParam));
659
+ };
660
+ }
661
+ function traverseStateRouteMatch(stateRoute, stPathSplitted) {
662
+ let focusedRoute = stateRoute;
663
+ let routeIdx = 0;
664
+ const len = stPathSplitted.length;
665
+ let i = 0;
666
+ for (; i < len; i++, routeIdx++) {
667
+ const sName = stPathSplitted[i];
668
+ const routeEl = focusedRoute[routeIdx];
669
+ if (!routeEl) return {
670
+ isExhausted: false,
671
+ endIdx: i,
672
+ remaining: [focusedRoute, routeIdx]
673
+ };
674
+ else if (typeof routeEl === "string") {
675
+ if (sName !== routeEl.valueOf()) return {
676
+ isExhausted: false,
677
+ endIdx: i,
678
+ remaining: [focusedRoute, routeIdx]
679
+ };
680
+ continue;
681
+ }
682
+ const { parallel, regions } = routeEl;
683
+ if (sName !== parallel) return {
684
+ isExhausted: false,
685
+ endIdx: i
686
+ };
687
+ i += 1;
688
+ if (i >= len) return {
689
+ isExhausted: true,
690
+ endIdx: i,
691
+ remaining: [
692
+ focusedRoute,
693
+ routeIdx,
694
+ true
695
+ ]
696
+ };
697
+ const regionRoute = regions[stPathSplitted[i]];
698
+ if (!regionRoute) return {
699
+ isExhausted: false,
700
+ endIdx: i
701
+ };
702
+ focusedRoute = regionRoute;
703
+ routeIdx = -1;
704
+ }
705
+ return {
706
+ isExhausted: true,
707
+ endIdx: i,
708
+ remaining: [focusedRoute, routeIdx]
709
+ };
710
+ }
711
+ //#endregion
712
+ //#region src/runtime/runtime_step.core.ts
713
+ function buildTransitionCandidate(transition, tIndex, firedIn, leaves) {
714
+ return {
715
+ transition,
716
+ tIndex,
717
+ firedIn,
718
+ leaves
719
+ };
720
+ }
721
+ const x_getStItemDef = (stPath, stateCatalog) => {
722
+ const stateItem = stateCatalog.get(stPath);
723
+ if (!stateItem) throw new Error(`Unknown state path "${stPath}"`);
724
+ return stateItem.def;
725
+ };
726
+ function o_deriveLowestCommonAncestor(model, leaves) {
727
+ let crrLeaves = leaves;
728
+ let bgn = 1;
729
+ let end = model.indexOf("/", bgn) + 1;
730
+ while (end) {
731
+ const needle = model.slice(bgn, end);
732
+ crrLeaves = crrLeaves.filter((pth) => pth.startsWith(needle, bgn));
733
+ if (!crrLeaves.length) break;
734
+ bgn = end;
735
+ end = model.indexOf("/", bgn) + 1;
736
+ }
737
+ return model.slice(0, bgn - 1);
738
+ }
739
+ function x_removeConflictedTransitions(tCandidates, activeParallels) {
740
+ if (tCandidates.length < 2 || !activeParallels.length) return tCandidates.map(({ transition, tIndex, leaves }) => {
741
+ const { fullTo } = transition;
742
+ return {
743
+ tIndex,
744
+ transition,
745
+ lca: !fullTo ? void 0 : o_deriveLowestCommonAncestor(fullTo, leaves)
746
+ };
747
+ });
748
+ const stateStayingTExecs = [];
749
+ const nonPExitedTExecs = [];
750
+ const accStChangingTExecDict = Object.create(null);
751
+ for (const tCand of tCandidates) {
752
+ const { transition, tIndex, leaves } = tCand;
753
+ const { fullTo } = transition;
754
+ if (!fullTo) {
755
+ stateStayingTExecs.push({
756
+ transition,
757
+ tIndex
758
+ });
759
+ continue;
760
+ }
761
+ const lca = o_deriveLowestCommonAncestor(fullTo, leaves);
762
+ const exitedParallel = (() => {
763
+ const idx = fullTo.indexOf("/", lca.length + 1);
764
+ const needle = idx == -1 ? fullTo : fullTo.slice(0, idx + 1);
765
+ const candidates = activeParallels.filter((p) => !p.startsWith(needle) && p.startsWith(lca));
766
+ return !candidates.length ? "" : candidates.reduce((a, b) => a.length <= b.length ? a : b);
767
+ })();
768
+ if (!exitedParallel) nonPExitedTExecs.push({
769
+ transition,
770
+ tIndex,
771
+ lca
772
+ });
773
+ else if (!(exitedParallel in accStChangingTExecDict)) accStChangingTExecDict[exitedParallel] = {
774
+ transition,
775
+ tIndex,
776
+ lca
777
+ };
778
+ }
779
+ const [tmp1, tmp2] = (() => {
780
+ const _adoptedParallels = [];
781
+ return [Object.entries(accStChangingTExecDict).sort(([pathA], [pathB]) => pathA > pathB ? 1 : -1).reduce((acc, [pth, tExec]) => {
782
+ if (!_adoptedParallels.some((parPath) => pth.startsWith(parPath))) {
783
+ _adoptedParallels.push(pth);
784
+ acc.push(tExec);
785
+ }
786
+ return acc;
787
+ }, []), nonPExitedTExecs.filter(({ lca }) => !_adoptedParallels.some((pth) => lca?.startsWith(pth)))];
788
+ })();
789
+ return [
790
+ ...stateStayingTExecs,
791
+ ...tmp1,
792
+ ...tmp2
793
+ ];
794
+ }
795
+ function o_findChildOrSelfTransition(stPath, stateRoute, childIdx, activeParallelSet, stateCatalog, findTransition, eType) {
796
+ const [childCandidates, cLeaves] = x_findDeepestTransitions(stateRoute, childIdx, stPath, activeParallelSet, stateCatalog, findTransition, eType);
797
+ if (childCandidates.length) return [childCandidates, []];
798
+ const result = findTransition(x_getStItemDef(stPath, stateCatalog), eType);
799
+ const leaves = cLeaves.length ? cLeaves : [stPath];
800
+ if (!result) return [[], leaves];
801
+ const { transition, tIndex } = result;
802
+ return [[buildTransitionCandidate(transition, tIndex, stPath, leaves)], []];
803
+ }
804
+ function x_findDeepestTransitions(stateRoute, idx, parentPath, activeParallelSet, stateCatalog, findTransition, eType = "") {
805
+ if (idx >= stateRoute.length) return [[], []];
806
+ const stateNameOrParallel = stateRoute[idx];
807
+ if (typeof stateNameOrParallel === "string") return o_findChildOrSelfTransition(`${parentPath}/${stateNameOrParallel}`, stateRoute, idx + 1, activeParallelSet, stateCatalog, findTransition, eType);
808
+ const { parallel, regions } = stateNameOrParallel;
809
+ const parallelRoot = `${parentPath}/${parallel}`;
810
+ activeParallelSet.add(parallelRoot);
811
+ const accTCandidates = [];
812
+ const accLeaves = [];
813
+ for (const key in regions) {
814
+ const [resultCandidates, resultLeaves] = o_findChildOrSelfTransition(`${parentPath}/${parallel}/${key}`, regions[key], 0, activeParallelSet, stateCatalog, findTransition, eType);
815
+ if (resultCandidates.length) accTCandidates.push(...resultCandidates);
816
+ if (resultLeaves.length) accLeaves.push(...resultLeaves);
817
+ }
818
+ if (accTCandidates.length) return [accTCandidates, []];
819
+ const result = findTransition(x_getStItemDef(parallelRoot, stateCatalog), eType);
820
+ if (!result) return [[], accLeaves];
821
+ const { transition, tIndex } = result;
822
+ return [[buildTransitionCandidate(transition, tIndex, parallelRoot, accLeaves)], []];
823
+ }
824
+ function o_unwrapSystemEvent(event) {
825
+ return !(SystemEventSymbol in event && event.payload) ? event : event.payload;
826
+ }
827
+ function o_evalActionParams(param, context, event, input) {
828
+ return typeof param !== "function" ? param : param(runtimeUtils.makeFnBaseParam(context, event, input));
829
+ }
830
+ function readyAction(origContext, rawEvent, input, machineGuards, machineActions, rtOutbound) {
831
+ const event = o_unwrapSystemEvent(rawEvent);
832
+ const { emit } = rtOutbound;
833
+ let context = deepFreeze(origContext);
834
+ let updateApplications = [];
835
+ let enqActions = [];
836
+ const update = (updates) => {
837
+ if (!updates || typeof updates !== "object") throw new Error(`RT"${rtOutbound.id}"> Invalid updates argument: ${JSON.stringify(updates)}`);
838
+ updateApplications.push(updates);
839
+ };
840
+ function applyUpdate() {
841
+ for (const updates of updateApplications) {
842
+ const partial = Object.entries(updates).reduce((acc, [key, val]) => {
843
+ acc[key] = typeof val === "function" ? val() : val;
844
+ return acc;
845
+ }, {});
846
+ context = {
847
+ ...context,
848
+ ...partial
849
+ };
850
+ }
851
+ if (!updateApplications.length) return;
852
+ context = deepFreeze(context);
853
+ updateApplications = [];
854
+ }
855
+ function check(type, ...args) {
856
+ const [fn, params] = resolveGuardElement(type, machineGuards, args?.[0]);
857
+ const fnBaseParam = runtimeUtils.makeFnBaseParam(context, event, input);
858
+ return fn(fnBaseParam, typeof params !== "function" ? params : params(fnBaseParam));
859
+ }
860
+ function sendTo(serviceName, ...args) {
861
+ const [subKey, sEvent] = args.length == 2 ? args : ["", args[0]];
862
+ const childKey = subKey || typeof subKey === "number" ? `${serviceName}:${subKey}` : serviceName;
863
+ if (!Object.hasOwn(rtOutbound.children, childKey)) throw new Error(`RT"${rtOutbound.id}"> Cannot send event to "${childKey}": child not found.`);
864
+ rtOutbound.children[childKey]?.send(sEvent);
865
+ }
866
+ let isProcessingQueue = false;
867
+ function enqueue(type, ...args) {
868
+ if (isProcessingQueue) throw new Error(`RT"${rtOutbound.id}"> Nested enqueue operations are not supported.`);
869
+ const [fn, params] = resolveActionElement(type, machineActions, args?.[0]);
870
+ enqActions.push({
871
+ fn,
872
+ params
873
+ });
874
+ }
875
+ let saveContext = origContext;
876
+ let saveFnBaseParam;
877
+ return {
878
+ makeFnBaseParam() {
879
+ if (!(context === saveContext && saveFnBaseParam)) {
880
+ saveContext = context;
881
+ saveFnBaseParam = runtimeUtils.makeFnBaseParam(context, event, input);
882
+ }
883
+ return saveFnBaseParam;
884
+ },
885
+ execAction(transitionAction, eventOverride) {
886
+ const bodies = resolveActionElement(transitionAction, machineActions);
887
+ const qEvent = !eventOverride ? event : o_unwrapSystemEvent(eventOverride);
888
+ if (bodies.length === 1) bodies[0]({
889
+ context,
890
+ c: context,
891
+ event: qEvent,
892
+ e: qEvent,
893
+ input,
894
+ update,
895
+ sendTo,
896
+ emit,
897
+ check,
898
+ enqueue
899
+ });
900
+ else {
901
+ const [fn, params] = bodies;
902
+ fn({
903
+ context,
904
+ c: context,
905
+ event: qEvent,
906
+ e: qEvent,
907
+ input,
908
+ update,
909
+ emit
910
+ }, o_evalActionParams(params, context, qEvent, input));
911
+ }
912
+ applyUpdate();
913
+ },
914
+ processQueue() {
915
+ isProcessingQueue = true;
916
+ try {
917
+ for (const { fn, params } of enqActions) {
918
+ fn({
919
+ context,
920
+ c: context,
921
+ event,
922
+ e: event,
923
+ input,
924
+ update,
925
+ emit
926
+ }, o_evalActionParams(params, context, event, input));
927
+ applyUpdate();
928
+ }
929
+ } finally {
930
+ enqActions = [];
931
+ isProcessingQueue = false;
932
+ }
933
+ },
934
+ getResult() {
935
+ return { context };
936
+ }
937
+ };
938
+ }
939
+ function o_readyToFindInternalEventTransition(fnBaseParam, machineGuards, internalEPayload) {
940
+ const _evalGuard = readyToEvalGuard(fnBaseParam, machineGuards);
941
+ return ({ internalEvents }, eType) => {
942
+ const internalEType = eType;
943
+ if (Object.hasOwn(internalEvents, internalEType)) {
944
+ const cond = internalEvents[internalEType].cond;
945
+ if (!cond || cond(internalEPayload)) {
946
+ const { transitions } = internalEvents[internalEType];
947
+ const tIndex = transitions.findIndex(({ guards }) => !guards.length || guards.every((e) => _evalGuard(e)));
948
+ if (tIndex != -1) return {
949
+ tIndex,
950
+ transition: transitions[tIndex]
951
+ };
952
+ }
953
+ }
954
+ };
955
+ }
956
+ function o_readyToFindTransitionByEvent(fnBaseParam, machineGuards) {
957
+ const _evalGuard = readyToEvalGuard(fnBaseParam, machineGuards);
958
+ return ({ events }, eType) => {
959
+ if (Object.hasOwn(events, eType)) {
960
+ const transitions = events[eType];
961
+ const tIndex = transitions.findIndex(({ guards }) => !guards.length || guards.every((e) => _evalGuard(e)));
962
+ if (tIndex != -1) return {
963
+ tIndex,
964
+ transition: transitions[tIndex]
965
+ };
966
+ }
967
+ };
968
+ }
969
+ function deriveEventTransition(eType, internalEPayload, fnBaseParam, crrStates, machineGuards, stateCatalog, topLvDefItem) {
970
+ const findTransition = internalEPayload ? o_readyToFindInternalEventTransition(fnBaseParam, machineGuards, internalEPayload) : o_readyToFindTransitionByEvent(fnBaseParam, machineGuards);
971
+ const activeParallelSet = /* @__PURE__ */ new Set();
972
+ const [tCandidates, cLeaves] = x_findDeepestTransitions(crrStates, 0, "", activeParallelSet, stateCatalog, findTransition, eType);
973
+ if (!tCandidates.length) {
974
+ const result = findTransition(topLvDefItem, eType);
975
+ if (result) {
976
+ const { transition, tIndex } = result;
977
+ tCandidates.push(buildTransitionCandidate(transition, tIndex, "/", cLeaves));
978
+ }
979
+ }
980
+ return x_removeConflictedTransitions(tCandidates, [...activeParallelSet].sort((a, b) => a > b ? -1 : 1));
981
+ }
982
+ function* o_genExitPaths(parent, stateRoute, idx, asRootpath = false) {
983
+ if (idx >= stateRoute.length) return;
984
+ const el = stateRoute[idx];
985
+ if (typeof el === "string") {
986
+ const pth = `${parent}/${el}`;
987
+ yield* o_genExitPaths(pth, stateRoute, idx + 1);
988
+ yield pth;
989
+ return;
990
+ }
991
+ const { parallel, regions } = el;
992
+ const rootPath = asRootpath ? parent : `${parent}/${parallel}`;
993
+ for (const regionName in regions) {
994
+ const pth = `${rootPath}/${regionName}`;
995
+ yield* o_genExitPaths(pth, regions[regionName], 0);
996
+ yield pth;
997
+ }
998
+ if (!asRootpath) yield rootPath;
999
+ }
1000
+ function* genExitPathsAndDeleteFromCrrStates(crrStates, lca, fullTo = ":DUMMY:") {
1001
+ const { remaining, isExhausted } = traverseStateRouteMatch(crrStates, splitStPath(lca));
1002
+ if (!isExhausted) throw new Error(`During transition to "${fullTo}", state "${lca}" is not found in ${JSON.stringify(crrStates)}`);
1003
+ const [stateRoute, startIdx, asRootpath] = remaining;
1004
+ yield* o_genExitPaths(lca, stateRoute, startIdx, asRootpath);
1005
+ if (!asRootpath) stateRoute.splice(startIdx);
1006
+ else if (typeof stateRoute[startIdx] === "object") stateRoute[startIdx].regions = {};
1007
+ else throw new Error(`Internal error: unexpected stateRoute: ${JSON.stringify(stateRoute)}, lca:${lca}`);
1008
+ }
1009
+ function oo_addSubStatesToDest(destinations, { initial, stateOf }) {
1010
+ if (!initial || initial in destinations) return destinations;
1011
+ destinations[initial] = Object.create(null);
1012
+ const { sub } = stateOf[initial];
1013
+ if (!sub) return destinations;
1014
+ else if (sub.dType === "regions") oo_addParallelToDestTree(destinations[initial], sub.stateOf);
1015
+ else oo_addSubStatesToDest(destinations[initial], sub);
1016
+ return destinations;
1017
+ }
1018
+ function oo_addParallelToDestTree(destinations, regionStItemOf, routeRegions) {
1019
+ for (const key in regionStItemOf) {
1020
+ if (key in destinations || routeRegions?.[key]?.length) continue;
1021
+ destinations[key] = Object.create(null);
1022
+ oo_addSubStatesToDest(destinations[key], regionStItemOf[key].sub);
1023
+ }
1024
+ }
1025
+ function* o_genStateEntryData(transitionDest, target, rIdx, stateDefinition) {
1026
+ const { stateOf } = stateDefinition;
1027
+ let isLeaf = true;
1028
+ for (const dKey in transitionDest) {
1029
+ isLeaf = false;
1030
+ const stDef = stateOf?.[dKey];
1031
+ if (!stDef) throw new Error(`Unknown state "${dKey}"`);
1032
+ const { def, sub } = stDef;
1033
+ const isParallel = sub?.dType === "regions";
1034
+ const childTree = transitionDest[dKey];
1035
+ if (rIdx >= 0) {
1036
+ if (isParallel) {
1037
+ const { route } = target;
1038
+ const el = route[rIdx];
1039
+ if (typeof el === "object" && "parallel" in el && el.parallel === dKey) {
1040
+ oo_addParallelToDestTree(childTree, sub.stateOf, el.regions);
1041
+ yield* o_genStateEntryData(childTree, {
1042
+ isRegions: true,
1043
+ regions: el.regions
1044
+ }, rIdx, sub);
1045
+ continue;
1046
+ }
1047
+ } else if (target.isRegions) {
1048
+ const { regions } = target;
1049
+ if (dKey in regions) {
1050
+ if (sub) yield* o_genStateEntryData(childTree, {
1051
+ isRegions: false,
1052
+ route: regions[dKey],
1053
+ isRegionChild: true
1054
+ }, 0, sub);
1055
+ continue;
1056
+ }
1057
+ } else {
1058
+ const { route } = target;
1059
+ if (route[rIdx]?.valueOf() === dKey) {
1060
+ if (sub) yield* o_genStateEntryData(childTree, {
1061
+ isRegions: false,
1062
+ route,
1063
+ isRegionChild: false
1064
+ }, rIdx + 1, sub);
1065
+ continue;
1066
+ }
1067
+ }
1068
+ }
1069
+ if (isParallel) {
1070
+ const regions = Object.create(null);
1071
+ const el = {
1072
+ parallel: dKey,
1073
+ regions
1074
+ };
1075
+ const { route, isRegionChild } = target;
1076
+ route.push(el);
1077
+ yield [def, {
1078
+ stateName: dKey,
1079
+ isRegionChild
1080
+ }];
1081
+ oo_addParallelToDestTree(childTree, sub.stateOf);
1082
+ yield* o_genStateEntryData(childTree, {
1083
+ isRegions: true,
1084
+ regions
1085
+ }, -1, sub);
1086
+ } else if (target.isRegions) {
1087
+ const route = [];
1088
+ target.regions[dKey] = route;
1089
+ yield [def, { stateName: dKey }];
1090
+ if (sub) yield* o_genStateEntryData(childTree, {
1091
+ isRegions: false,
1092
+ route,
1093
+ isRegionChild: true
1094
+ }, -1, sub);
1095
+ } else {
1096
+ const { route, isRegionChild } = target;
1097
+ route.push(dKey);
1098
+ yield [def, {
1099
+ stateName: dKey,
1100
+ isRegionChild
1101
+ }];
1102
+ if (sub) yield* o_genStateEntryData(childTree, {
1103
+ isRegions: false,
1104
+ route,
1105
+ isRegionChild: false
1106
+ }, -1, sub);
1107
+ }
1108
+ }
1109
+ if (isLeaf && "initial" in stateDefinition && stateDefinition.initial) yield* o_genStateEntryData(oo_addSubStatesToDest(Object.create(null), stateDefinition), target, -1, stateDefinition);
1110
+ }
1111
+ function* updateStateRouteForEntry(fullToSplittees, crrStates, stateDefinition) {
1112
+ yield* o_genStateEntryData((() => {
1113
+ const root = Object.create(null);
1114
+ for (const stateNames of fullToSplittees) {
1115
+ let focused = root;
1116
+ for (const stName of stateNames) {
1117
+ focused[stName] = focused[stName] || Object.create(null);
1118
+ focused = focused[stName];
1119
+ }
1120
+ }
1121
+ return root;
1122
+ })(), {
1123
+ isRegions: false,
1124
+ route: crrStates,
1125
+ isRegionChild: false
1126
+ }, 0, stateDefinition);
1127
+ }
1128
+ function launchInvocations(invocations, path, makeFnBaseParam, machineServices, rtOutbound) {
1129
+ const { enqueueEvent } = rtOutbound;
1130
+ const fnBaseParam = makeFnBaseParam();
1131
+ for (const [i, { input, mainKey, subKey, src, emittableETypesToListen }] of invocations.entries()) {
1132
+ const [srcType, srcValue] = (() => {
1133
+ const { type, value } = src;
1134
+ if (type !== "string") return [type, value];
1135
+ const service = machineServices[value];
1136
+ if (!service) throw new Error(`RT"${rtOutbound.id}"> invoke: Unknown src: "${value}"`);
1137
+ return [typeof service === "function" ? "function" : "machine", service];
1138
+ })();
1139
+ const childKey = subKey ? `${mainKey}:${subKey}` : mainKey;
1140
+ if (rtOutbound.children[childKey]) throw new Error(`RT"${rtOutbound.id}"> Service with ID '${childKey}' is already running.`);
1141
+ const onDone = (output) => enqueueEvent({
1142
+ type: `invoke/:done:[${i}]`,
1143
+ payload: {
1144
+ type: ":done:",
1145
+ output
1146
+ },
1147
+ [SystemEventSymbol]: true
1148
+ }, { path });
1149
+ const onError = (error) => {
1150
+ enqueueEvent({
1151
+ type: `invoke/:error:[${i}]`,
1152
+ payload: {
1153
+ type: ":error:",
1154
+ error
1155
+ },
1156
+ [SystemEventSymbol]: true
1157
+ }, { path });
1158
+ };
1159
+ const inputValue = input && typeof input === "function" ? input(fnBaseParam) : void 0;
1160
+ switch (srcType) {
1161
+ case "machine": {
1162
+ const childRt = makeRuntime(srcValue, {
1163
+ id: `${rtOutbound.id}/${childKey}`,
1164
+ input: () => inputValue
1165
+ });
1166
+ rtOutbound.children = {
1167
+ ...rtOutbound.children,
1168
+ [childKey]: childRt
1169
+ };
1170
+ childRt.subscribe(({ runtimeStatus, output }) => {
1171
+ if (runtimeStatus === "done") onDone(output);
1172
+ }, onError);
1173
+ for (const eType of emittableETypesToListen) childRt.onEmitted(eType, (emittedEvent) => {
1174
+ enqueueEvent({
1175
+ type: `invoke/${eType}[${i}]`,
1176
+ payload: emittedEvent,
1177
+ [SystemEventSymbol]: true
1178
+ }, { path });
1179
+ });
1180
+ childRt.start();
1181
+ break;
1182
+ }
1183
+ case "function": {
1184
+ const abortController = new AbortController();
1185
+ const { signal } = abortController;
1186
+ const emit = (emittedEvent) => {
1187
+ if (!(emittedEvent && typeof emittedEvent === "object" && emittableETypesToListen.includes(emittedEvent?.type))) throw new Error(`RT"${rtOutbound.id}"> Invalid emittedEvent: ${JSON.stringify(emittedEvent)}`);
1188
+ enqueueEvent({
1189
+ type: `invoke/${emittedEvent?.type}[${i}]`,
1190
+ payload: emittedEvent,
1191
+ [SystemEventSymbol]: true
1192
+ }, { path });
1193
+ };
1194
+ const listeners = /* @__PURE__ */ new Set();
1195
+ const listen = (listener) => {
1196
+ listeners.add(listener);
1197
+ };
1198
+ const child = {
1199
+ send(event) {
1200
+ listeners.forEach((listener) => listener(event));
1201
+ },
1202
+ stop() {
1203
+ abortController.abort();
1204
+ listeners.clear();
1205
+ }
1206
+ };
1207
+ rtOutbound.children = {
1208
+ ...rtOutbound.children,
1209
+ [childKey]: child
1210
+ };
1211
+ const result = (() => {
1212
+ try {
1213
+ return srcValue(inputValue, emit, listen, signal);
1214
+ } catch (error) {
1215
+ if (!signal.aborted) onError(error);
1216
+ }
1217
+ })();
1218
+ const _handleOutput = (output) => {
1219
+ if (typeof output === "function") {
1220
+ if (signal.aborted) output();
1221
+ else child.stop = () => {
1222
+ abortController.abort();
1223
+ listeners.clear();
1224
+ output();
1225
+ };
1226
+ } else if (!signal.aborted) onDone(output);
1227
+ };
1228
+ if (!(result instanceof Promise)) {
1229
+ _handleOutput(result);
1230
+ return;
1231
+ }
1232
+ result.then((output) => _handleOutput(output)).catch((error) => {
1233
+ if (!signal.aborted) onError(error);
1234
+ });
1235
+ break;
1236
+ }
1237
+ }
1238
+ }
1239
+ }
1240
+ function stopInvocations(invocations, rtOutbound) {
1241
+ const newChildren = { ...rtOutbound.children };
1242
+ for (const { mainKey, subKey } of invocations) {
1243
+ const key = subKey ? `${mainKey}:${subKey}` : mainKey;
1244
+ newChildren[key].stop();
1245
+ delete newChildren[key];
1246
+ }
1247
+ rtOutbound.children = newChildren;
1248
+ }
1249
+ function o_gatherAllChildrenOutputs(regions, parent, fnBaseParams, stateCatalog) {
1250
+ const output = {};
1251
+ for (const key in regions) {
1252
+ const regionChild = regions[key][0];
1253
+ if (!regionChild) continue;
1254
+ else if (typeof regionChild === "object") {
1255
+ const result = regionChild.output;
1256
+ if (!result) return null;
1257
+ output[key] = result;
1258
+ continue;
1259
+ }
1260
+ const { final } = x_getStItemDef(`${parent}/${key}/${regionChild}`, stateCatalog);
1261
+ if (!final) return null;
1262
+ if (typeof final === "function") output[key] = final(fnBaseParams);
1263
+ }
1264
+ return output;
1265
+ }
1266
+ function* genChildDoneEvents(reachedFinalStateData = [], fnBaseParams, crrStates, stateCatalog) {
1267
+ const accParallelRoots = /* @__PURE__ */ new Set();
1268
+ for (const [pPath, isRegionChild, final] of reachedFinalStateData) {
1269
+ if (!pPath) continue;
1270
+ if (isRegionChild) accParallelRoots.add(parentPathOf(pPath));
1271
+ else yield [{
1272
+ type: ":childDone:",
1273
+ output: typeof final === "function" ? final(fnBaseParams) : void 0
1274
+ }, { path: pPath }];
1275
+ }
1276
+ {
1277
+ const seen = /* @__PURE__ */ new Set();
1278
+ for (const parallelRoot of accParallelRoots) {
1279
+ let focusedPath = parentPathOf(parallelRoot);
1280
+ while (focusedPath) {
1281
+ if (seen.has(focusedPath)) break;
1282
+ seen.add(focusedPath);
1283
+ const item = stateCatalog.get(focusedPath);
1284
+ const pPath = item.def.pPath;
1285
+ if (item.sub?.dType === "regions") {
1286
+ accParallelRoots.add(focusedPath);
1287
+ focusedPath = pPath;
1288
+ continue;
1289
+ } else if (!pPath) break;
1290
+ const pItem = stateCatalog.get(pPath);
1291
+ if (pItem.sub?.dType !== "regions") break;
1292
+ accParallelRoots.add(pPath);
1293
+ focusedPath = pItem.def.pPath;
1294
+ }
1295
+ }
1296
+ }
1297
+ const parallelRoots = [...accParallelRoots].sort((a, b) => a > b ? -1 : 1);
1298
+ const last = parallelRoots.length - 1;
1299
+ for (const [i, parallelRoot] of parallelRoots.entries()) {
1300
+ const def = stateCatalog.get(parallelRoot)?.def;
1301
+ if (i >= last && !def?.internalEvents[":childDone:"]?.transitions.length) break;
1302
+ const { remaining, isExhausted } = traverseStateRouteMatch(crrStates, splitStPath(parallelRoot));
1303
+ if (!isExhausted) throw new Error(`Internal error: state "${parallelRoot}" is not found in current states.`);
1304
+ const [route, idx] = remaining;
1305
+ const parallelRouteEl = route[idx];
1306
+ const output = o_gatherAllChildrenOutputs(parallelRouteEl.regions, parallelRoot, fnBaseParams, stateCatalog);
1307
+ if (output) {
1308
+ parallelRouteEl.output = output;
1309
+ yield [{
1310
+ type: ":childDone:",
1311
+ output
1312
+ }, { path: parallelRoot }];
1313
+ }
1314
+ }
1315
+ }
1316
+ function o_readyToFindAlwaysTransition(fnBaseParam, machineGuards) {
1317
+ const _evalGuard = readyToEvalGuard(fnBaseParam, machineGuards);
1318
+ return ({ internalEvents }) => {
1319
+ const transitions = internalEvents[":always:"]?.transitions;
1320
+ if (transitions) {
1321
+ const tIndex = transitions.findIndex(({ guards }) => !guards.length || guards.every((e) => _evalGuard(e)));
1322
+ if (tIndex != -1) return {
1323
+ tIndex,
1324
+ transition: transitions[tIndex]
1325
+ };
1326
+ }
1327
+ };
1328
+ }
1329
+ function evalAlwaysEvent(fnBaseParam, crrStates, machineGuards, stateCatalog) {
1330
+ const findTransition = o_readyToFindAlwaysTransition(fnBaseParam, machineGuards);
1331
+ const activeParallelSet = /* @__PURE__ */ new Set();
1332
+ const [tCandidates] = x_findDeepestTransitions(crrStates, 0, "", activeParallelSet, stateCatalog, findTransition);
1333
+ return x_removeConflictedTransitions(tCandidates, [...activeParallelSet].sort((a, b) => a > b ? -1 : 1));
1334
+ }
1335
+ //#endregion
1336
+ //#region src/runtime/runtime_step.ts
1337
+ function execTExecActions(tExecs, actionRunner, errLocation, internalQueueEvent) {
1338
+ const { execAction, processQueue } = actionRunner;
1339
+ let i, tExec, action;
1340
+ try {
1341
+ for (tExec of tExecs) for ([i, action] of tExec.transition.actions.entries()) {
1342
+ execAction(action, internalQueueEvent);
1343
+ processQueue();
1344
+ }
1345
+ } catch (err) {
1346
+ const { lca, tIndex } = tExec;
1347
+ const msg = err instanceof Error ? err.message : String(err);
1348
+ console.error(`small-state: ${msg}`, {
1349
+ state: lca,
1350
+ location: `${errLocation}[${tIndex}], actions[${i}]`
1351
+ });
1352
+ throw err;
1353
+ }
1354
+ }
1355
+ function initRuntime(realContext, input, crrStates, machineInternal, rtOutbound, event = { type: ":init:" }) {
1356
+ const { definition, guards, actions } = machineInternal;
1357
+ const { initial } = definition;
1358
+ const actionRunner = readyAction(realContext, event, input, guards, actions, rtOutbound);
1359
+ const [hasTransitioned, doneEvent] = runMicrosteps([{
1360
+ transition: {
1361
+ to: initial,
1362
+ fullTo: `/${initial}`,
1363
+ guards: [],
1364
+ actions: []
1365
+ },
1366
+ tIndex: -1
1367
+ }], crrStates, actionRunner, machineInternal, rtOutbound);
1368
+ {
1369
+ const { context } = actionRunner.getResult();
1370
+ return {
1371
+ context,
1372
+ crrStates,
1373
+ hasTransitioned,
1374
+ doneEvent
1375
+ };
1376
+ }
1377
+ }
1378
+ function macrostep(eType, internalEPayload, crrStates, actionRunner, machineInternal, rtOutbound) {
1379
+ const { guards, stateCatalog, topLvDefItem } = machineInternal;
1380
+ const tExecs = deriveEventTransition(eType, internalEPayload, actionRunner.makeFnBaseParam(), crrStates, guards, stateCatalog, topLvDefItem);
1381
+ execTExecActions(tExecs, actionRunner, "transition");
1382
+ const [hasTransitioned, doneEvent] = runMicrosteps(tExecs, crrStates, actionRunner, machineInternal, rtOutbound);
1383
+ {
1384
+ const { context } = actionRunner.getResult();
1385
+ return {
1386
+ context,
1387
+ crrStates,
1388
+ hasTransitioned,
1389
+ doneEvent
1390
+ };
1391
+ }
1392
+ }
1393
+ function runMicrosteps(tExecs, crrStates, actionRunner, machineInternal, rtOutbound) {
1394
+ const internalQueue = [];
1395
+ let [hasTransitioned, doneEvent] = runExitAndEntryThenAlways(tExecs, crrStates, actionRunner, machineInternal, rtOutbound, internalQueue);
1396
+ const { guards, stateCatalog, topLvDefItem } = machineInternal;
1397
+ const { makeFnBaseParam } = actionRunner;
1398
+ while (internalQueue.length) {
1399
+ const [event, payload] = internalQueue.shift();
1400
+ const internalTExecs = deriveEventTransition(event.type, payload, makeFnBaseParam(), crrStates, guards, stateCatalog, topLvDefItem);
1401
+ execTExecActions(internalTExecs, actionRunner, event.type, event);
1402
+ [hasTransitioned, doneEvent] = runExitAndEntryThenAlways(internalTExecs, crrStates, actionRunner, machineInternal, rtOutbound, internalQueue) || hasTransitioned;
1403
+ }
1404
+ return [hasTransitioned, doneEvent];
1405
+ }
1406
+ function runExitAndEntryThenAlways(tExecs, crrStates, actionRunner, machineInternal, rtOutbound, internalQueue) {
1407
+ let [alwaysTExecs, hasTransitioned, doneEvent] = exitAndEntry(tExecs, crrStates, actionRunner, machineInternal, rtOutbound, internalQueue);
1408
+ let i = 0;
1409
+ while (alwaysTExecs.length) {
1410
+ let tmp;
1411
+ [alwaysTExecs, tmp, doneEvent] = exitAndEntry(alwaysTExecs, crrStates, actionRunner, machineInternal, rtOutbound, internalQueue);
1412
+ hasTransitioned ||= tmp;
1413
+ if (++i > 1e3) throw new Error(`RT"${rtOutbound.id}"> Maximum number of microsteps exceeded.`);
1414
+ }
1415
+ return [hasTransitioned, doneEvent];
1416
+ }
1417
+ function exitAndEntry(tExecs, crrStates, actionRunner, { guards, services, stateCatalog, definition }, rtOutbound, internalQueue) {
1418
+ let doneEvent;
1419
+ const { makeFnBaseParam, execAction, processQueue } = actionRunner;
1420
+ for (const { lca, transition } of tExecs) {
1421
+ if (lca === void 0) continue;
1422
+ {
1423
+ const exitPaths = genExitPathsAndDeleteFromCrrStates(crrStates, lca, transition.fullTo);
1424
+ let i, action;
1425
+ try {
1426
+ for (const pth of exitPaths) {
1427
+ const { def } = stateCatalog.get(pth);
1428
+ const { invocations, exitHooks } = def;
1429
+ if (exitHooks) for ([i, action] of exitHooks.entries()) {
1430
+ execAction(action);
1431
+ processQueue();
1432
+ }
1433
+ if (invocations.length) stopInvocations(invocations, rtOutbound);
1434
+ }
1435
+ } catch (err) {
1436
+ const msg = err instanceof Error ? err.message : String(err);
1437
+ console.error(`small-state: ${msg}`, {
1438
+ runtimeId: rtOutbound.id,
1439
+ state: lca,
1440
+ location: `exitHooks[${i}]`
1441
+ });
1442
+ throw err;
1443
+ }
1444
+ }
1445
+ }
1446
+ const stChangingTExecs = tExecs.filter(({ transition: { fullTo } }) => fullTo);
1447
+ if (stChangingTExecs.length) {
1448
+ const accReachedFinal = [];
1449
+ const fullToSplittees = stChangingTExecs.map(({ transition }) => splitStPath(transition.fullTo));
1450
+ const enteredStItemDefs = updateStateRouteForEntry(fullToSplittees, crrStates, definition);
1451
+ let i = 0, j, action;
1452
+ try {
1453
+ for (const [def, additional] of enteredStItemDefs) {
1454
+ const { invocations, entryHooks, final, pPath } = def;
1455
+ if (entryHooks) for ([j, action] of entryHooks.entries()) {
1456
+ execAction(action);
1457
+ processQueue();
1458
+ }
1459
+ if (invocations.length) launchInvocations(invocations, `${pPath}/${additional.stateName}`, makeFnBaseParam, services, rtOutbound);
1460
+ if (final) {
1461
+ if (!pPath) doneEvent = {
1462
+ type: ":done:",
1463
+ output: typeof final === "function" ? final(makeFnBaseParam()) : void 0
1464
+ };
1465
+ else accReachedFinal.push([
1466
+ pPath,
1467
+ additional.isRegionChild,
1468
+ final
1469
+ ]);
1470
+ }
1471
+ i += 1;
1472
+ }
1473
+ } catch (err) {
1474
+ const msg = err instanceof Error ? err.message : String(err);
1475
+ const pth = "/" + fullToSplittees[i]?.join("/");
1476
+ console.error(`small-state: ${msg}`, {
1477
+ runtimeId: rtOutbound.id,
1478
+ state: pth,
1479
+ location: `entryHooks[${j}]`
1480
+ });
1481
+ throw err;
1482
+ }
1483
+ internalQueue.push(...genChildDoneEvents(accReachedFinal, makeFnBaseParam(), crrStates, stateCatalog));
1484
+ }
1485
+ const alwaysTExecs = evalAlwaysEvent(makeFnBaseParam(), crrStates, guards, stateCatalog);
1486
+ execTExecActions(alwaysTExecs, actionRunner, ":always:");
1487
+ return [
1488
+ alwaysTExecs,
1489
+ !!stChangingTExecs.length,
1490
+ doneEvent
1491
+ ];
1492
+ }
1493
+ //#endregion
1494
+ //#region src/runtime/Runtime.ts
1495
+ function isRuntime(v) {
1496
+ return v instanceof Runtime;
1497
+ }
1498
+ function makeRuntime(machine, options) {
1499
+ return new Runtime(machine, options);
1500
+ }
1501
+ const STOP_EVENT = { type: "system/stop" };
1502
+ let idCounter = 0;
1503
+ var Runtime = class {
1504
+ id;
1505
+ machine;
1506
+ #machineInternal;
1507
+ #input;
1508
+ #realContext;
1509
+ #crrStates = [];
1510
+ #sentQueue = new MailBox(this.#processSentEvent.bind(this));
1511
+ #enqueueEvent = this.#sentQueue.enqueue.bind(this.#sentQueue);
1512
+ #outbound = {
1513
+ id: "",
1514
+ enqueueEvent: this.#enqueueEvent,
1515
+ emit: this.#_emit.bind(this),
1516
+ children: {}
1517
+ };
1518
+ #subscribers = /* @__PURE__ */ new Set();
1519
+ #emittedListeners = /* @__PURE__ */ new Map();
1520
+ #snapshot = {};
1521
+ get states() {
1522
+ return this.#snapshot.states;
1523
+ }
1524
+ get stateValue() {
1525
+ return this.#snapshot.stateValue;
1526
+ }
1527
+ get context() {
1528
+ return this.#snapshot.context;
1529
+ }
1530
+ get runtimeStatus() {
1531
+ return this.#snapshot.runtimeStatus;
1532
+ }
1533
+ get output() {
1534
+ return this.#snapshot.output;
1535
+ }
1536
+ getSnapshot() {
1537
+ return this.#snapshot;
1538
+ }
1539
+ constructor(machine, { id, input } = {}) {
1540
+ defineFixedProperty(this, "id", id || `${machine.name}:${idCounter++}`, { enumerable: true });
1541
+ defineFixedProperty(this, "machine", machine, { enumerable: true });
1542
+ this.#machineInternal = machine.internal;
1543
+ this.#input = input?.();
1544
+ this.#outbound.id = this.id;
1545
+ const { initContext } = machine.internal;
1546
+ const context = initContext ? initContext(this.#input) : null;
1547
+ this.#buildAndSetSnapshot(context, true, "notStarted")();
1548
+ }
1549
+ subscribe(onSnapshot, onError) {
1550
+ const subscriber = {
1551
+ onSnapshot,
1552
+ onError
1553
+ };
1554
+ this.#subscribers.add(subscriber);
1555
+ return () => {
1556
+ this.#subscribers.delete(subscriber);
1557
+ };
1558
+ }
1559
+ start() {
1560
+ if (this.runtimeStatus !== "notStarted") return this;
1561
+ const result = (() => {
1562
+ try {
1563
+ return initRuntime(this.#realContext, this.#input, this.#crrStates, this.#machineInternal, this.#outbound);
1564
+ } catch (err) {
1565
+ this.#handleError(err);
1566
+ }
1567
+ })();
1568
+ if (!result) return this;
1569
+ const { context, hasTransitioned, doneEvent } = result;
1570
+ this.#buildAndSetSnapshot(context, hasTransitioned, "active")(doneEvent);
1571
+ this.#sentQueue.start();
1572
+ return this;
1573
+ }
1574
+ send(event) {
1575
+ const eventObj = typeof event === "string" ? { type: event } : event;
1576
+ if (this.#snapshot.runtimeStatus !== "active") {
1577
+ console.warn(`RT"${this.id}"> Event "${eventObj.type}" was sent to non-active runtime: ${this.id}`);
1578
+ return this;
1579
+ }
1580
+ this.#enqueueEvent(eventObj);
1581
+ return this;
1582
+ }
1583
+ stop() {
1584
+ if (this.#snapshot.runtimeStatus !== "active") return this;
1585
+ this.#sentQueue.clear();
1586
+ this.#enqueueEvent(STOP_EVENT, {});
1587
+ return this;
1588
+ }
1589
+ onEmitted(emittedEventType, handler) {
1590
+ let listeners = this.#emittedListeners.get(emittedEventType);
1591
+ if (!listeners) {
1592
+ listeners = /* @__PURE__ */ new Set();
1593
+ this.#emittedListeners.set(emittedEventType, listeners);
1594
+ }
1595
+ const handlerWrapper = (emittedEvent) => handler(emittedEvent);
1596
+ listeners.add(handlerWrapper);
1597
+ return () => {
1598
+ listeners.delete(handlerWrapper);
1599
+ };
1600
+ }
1601
+ #processSentEvent(event, internalEPayload) {
1602
+ if (event === STOP_EVENT) {
1603
+ this.#dispose();
1604
+ return this.#buildAndSetSnapshot(this.#realContext, false, "stopped")();
1605
+ }
1606
+ const result = (() => {
1607
+ try {
1608
+ const { guards, actions } = this.#machineInternal;
1609
+ const actionRunner = readyAction(this.#realContext, event, this.#input, guards, actions, this.#outbound);
1610
+ return macrostep(event.type, internalEPayload, this.#crrStates, actionRunner, this.#machineInternal, this.#outbound);
1611
+ } catch (err) {
1612
+ this.#handleError(err);
1613
+ }
1614
+ })();
1615
+ if (!result) return;
1616
+ const { context, crrStates, hasTransitioned, doneEvent } = result;
1617
+ this.#crrStates = crrStates;
1618
+ this.#buildAndSetSnapshot(context, hasTransitioned)(doneEvent);
1619
+ }
1620
+ #dispose() {
1621
+ {
1622
+ const children = { ...this.#outbound.children };
1623
+ for (const id in children) {
1624
+ children[id].stop();
1625
+ delete children[id];
1626
+ }
1627
+ this.#outbound.children = children;
1628
+ }
1629
+ this.#sentQueue.clear();
1630
+ this.#subscribers.clear();
1631
+ this.#emittedListeners.clear();
1632
+ }
1633
+ #_emit(emittedEvent) {
1634
+ const listeners = this.#emittedListeners.get(emittedEvent.type);
1635
+ const wildcardListener = this.#emittedListeners.get("*");
1636
+ if (!(listeners || wildcardListener)) return;
1637
+ for (const handler of [...listeners || [], ...wildcardListener || []]) try {
1638
+ handler(emittedEvent);
1639
+ } catch (err) {
1640
+ reportUnhandledError(err);
1641
+ }
1642
+ }
1643
+ #buildAndSetSnapshot(newRealContext, hasTransitioned, runtimeStatus) {
1644
+ const oldSnapshot = this.#snapshot;
1645
+ const crrStates = this.#crrStates;
1646
+ const states = !hasTransitioned ? oldSnapshot.states : !crrStates.length ? [] : makeStateList(this.#crrStates);
1647
+ let { context } = oldSnapshot;
1648
+ const contextUpdated = newRealContext !== this.#realContext;
1649
+ if (contextUpdated) {
1650
+ this.#realContext = newRealContext;
1651
+ context = !newRealContext ? newRealContext : Object.entries(newRealContext).reduce((acc, [k, v]) => {
1652
+ if (!k.startsWith("_")) acc[k] = v;
1653
+ return acc;
1654
+ }, {});
1655
+ }
1656
+ return (doneEvent) => {
1657
+ if (!(hasTransitioned || contextUpdated || runtimeStatus)) return;
1658
+ const { stateCatalog, output } = this.#machineInternal;
1659
+ const isCompleted = !!(doneEvent || states.length && states.every((stPath) => stateCatalog.get(stPath)?.def.final));
1660
+ this.#snapshot = {
1661
+ runtimeId: this.id,
1662
+ states,
1663
+ get stateValue() {
1664
+ return states.length <= 1 ? states[0] : states;
1665
+ },
1666
+ context,
1667
+ c: context,
1668
+ runtimeStatus: isCompleted ? "done" : runtimeStatus || oldSnapshot.runtimeStatus,
1669
+ output: !(isCompleted && output) ? void 0 : output(runtimeUtils.makeFnBaseParam(newRealContext, doneEvent || {
1670
+ type: ":done:",
1671
+ output: void 0
1672
+ }, this.#input)),
1673
+ error: void 0,
1674
+ _children: this.#outbound.children,
1675
+ _runtime: this
1676
+ };
1677
+ Object.defineProperty(this.#snapshot, "_runtime", { enumerable: false });
1678
+ {
1679
+ const snapshot = this.#snapshot;
1680
+ for (const { onSnapshot } of this.#subscribers) {
1681
+ if (!onSnapshot) continue;
1682
+ try {
1683
+ onSnapshot(snapshot, oldSnapshot);
1684
+ } catch (err) {
1685
+ reportUnhandledError(err);
1686
+ }
1687
+ }
1688
+ }
1689
+ if (isCompleted) this.#dispose();
1690
+ };
1691
+ }
1692
+ #handleError(err) {
1693
+ this.#snapshot = {
1694
+ ...this.#snapshot,
1695
+ runtimeStatus: "error",
1696
+ error: err
1697
+ };
1698
+ let shouldReport = !this.#subscribers.size;
1699
+ for (const { onError } of this.#subscribers) {
1700
+ shouldReport ||= !onError;
1701
+ try {
1702
+ onError?.(err);
1703
+ } catch (err2) {
1704
+ reportUnhandledError(err2);
1705
+ }
1706
+ }
1707
+ this.#dispose();
1708
+ if (shouldReport) reportUnhandledError(err);
1709
+ }
1710
+ };
1711
+ function makeStateList(stateRoute, idx = 0, parent = "") {
1712
+ if (idx >= stateRoute.length) return [parent];
1713
+ const el = stateRoute[idx];
1714
+ if (typeof el === "string") return makeStateList(stateRoute, idx + 1, `${parent}/${el}`);
1715
+ const { parallel, regions } = el;
1716
+ const ret = [];
1717
+ for (const key in regions) ret.push(...makeStateList(regions[key], 0, `${parent}/${parallel}/${key}`));
1718
+ return ret;
1719
+ }
1720
+ //#endregion
1721
+ //#region src/tools/waitFor.ts
1722
+ async function waitFor(runtime, cond, options) {
1723
+ if (runtime.runtimeStatus === "notStarted") throw new Error(`RT"${runtime.id}" is not started.`);
1724
+ return new Promise((resolve, reject) => {
1725
+ let done = false;
1726
+ let unsubscribe;
1727
+ const dispose = () => {
1728
+ clearTimeout(timeoutId);
1729
+ done = true;
1730
+ unsubscribe?.();
1731
+ };
1732
+ const check = (snapshot) => {
1733
+ if (!cond(snapshot)) return;
1734
+ dispose();
1735
+ resolve(snapshot);
1736
+ };
1737
+ const timeoutId = !options?.timeout ? void 0 : setTimeout(() => {
1738
+ dispose();
1739
+ reject(`waitFor: timeout of ${options.timeout} ms exceeded`);
1740
+ }, options.timeout);
1741
+ check(runtime.getSnapshot());
1742
+ if (done) return;
1743
+ unsubscribe = runtime.subscribe((snapshot) => {
1744
+ check(snapshot);
1745
+ });
1746
+ });
1747
+ }
1748
+ //#endregion
1749
+ exports.defServiceFn = defServiceFn;
1750
+ exports.isMachine = isMachine;
1751
+ exports.isRuntime = isRuntime;
1752
+ exports.makeMachine = makeMachine;
1753
+ exports.makeRuntime = makeRuntime;
1754
+ exports.waitFor = waitFor;