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