@actuallab/fusion 12.1.62

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,706 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ComputeContext: () => ComputeContext,
24
+ ComputeFunction: () => ComputeFunction,
25
+ Computed: () => Computed,
26
+ ComputedRegistry: () => ComputedRegistry,
27
+ ComputedState: () => ComputedState,
28
+ ConsistencyState: () => ConsistencyState,
29
+ FixedDelayer: () => FixedDelayer,
30
+ MutableState: () => MutableState,
31
+ State: () => State,
32
+ StateBoundComputed: () => StateBoundComputed,
33
+ UIActionTracker: () => UIActionTracker,
34
+ UIUpdateDelayer: () => UIUpdateDelayer,
35
+ computeContextKey: () => computeContextKey,
36
+ computeMethod: () => computeMethod,
37
+ defaultUpdateDelayer: () => defaultUpdateDelayer,
38
+ getInstanceId: () => getInstanceId,
39
+ getMethodsMeta: () => getMethodsMeta,
40
+ uiActions: () => uiActions,
41
+ wrapComputeMethod: () => wrapComputeMethod
42
+ });
43
+ module.exports = __toCommonJS(index_exports);
44
+
45
+ // src/computed-input.ts
46
+ var _nextInstanceId = 0;
47
+ var _instanceIds = /* @__PURE__ */ new WeakMap();
48
+ function getInstanceId(instance) {
49
+ let id = _instanceIds.get(instance);
50
+ if (id === void 0) {
51
+ id = ++_nextInstanceId;
52
+ _instanceIds.set(instance, id);
53
+ }
54
+ return id;
55
+ }
56
+
57
+ // src/computed.ts
58
+ var import_core2 = require("@actuallab/core");
59
+
60
+ // src/computed-registry.ts
61
+ var ComputedRegistry = class _ComputedRegistry {
62
+ static _entries = /* @__PURE__ */ new Map();
63
+ static _finalization = new FinalizationRegistry((key) => {
64
+ _ComputedRegistry._entries.delete(key);
65
+ });
66
+ static get size() {
67
+ return _ComputedRegistry._entries.size;
68
+ }
69
+ static get(key) {
70
+ const ref = _ComputedRegistry._entries.get(key);
71
+ if (ref === void 0) return void 0;
72
+ const computed = ref.deref();
73
+ if (computed === void 0) {
74
+ _ComputedRegistry._entries.delete(key);
75
+ return void 0;
76
+ }
77
+ return computed;
78
+ }
79
+ static register(computed) {
80
+ const key = computed.input;
81
+ _ComputedRegistry._entries.set(key, new WeakRef(computed));
82
+ _ComputedRegistry._finalization.register(computed, key, computed);
83
+ }
84
+ static unregister(computed) {
85
+ const key = computed.input;
86
+ _ComputedRegistry._entries.delete(key);
87
+ _ComputedRegistry._finalization.unregister(computed);
88
+ }
89
+ };
90
+
91
+ // src/compute-context.ts
92
+ var import_core = require("@actuallab/core");
93
+ var computeContextKey = new import_core.AsyncContextKey("ComputeContext", void 0);
94
+ var ComputeContext = class {
95
+ computed;
96
+ _isCapturing = true;
97
+ constructor(computed) {
98
+ this.computed = computed;
99
+ }
100
+ get isCapturing() {
101
+ return this._isCapturing;
102
+ }
103
+ stopCapturing() {
104
+ this._isCapturing = false;
105
+ }
106
+ captureDependency(dependency) {
107
+ if (!this._isCapturing) return;
108
+ this.computed.addDependency(dependency);
109
+ }
110
+ /** Resolve ComputeContext from an AsyncContext (or current). */
111
+ static from(ctx) {
112
+ return import_core.AsyncContext.from(ctx)?.get(computeContextKey);
113
+ }
114
+ };
115
+
116
+ // src/computed.ts
117
+ var _nextVersion = 0;
118
+ var ConsistencyState = /* @__PURE__ */ ((ConsistencyState2) => {
119
+ ConsistencyState2[ConsistencyState2["Computing"] = 0] = "Computing";
120
+ ConsistencyState2[ConsistencyState2["Consistent"] = 1] = "Consistent";
121
+ ConsistencyState2[ConsistencyState2["Invalidated"] = 2] = "Invalidated";
122
+ return ConsistencyState2;
123
+ })(ConsistencyState || {});
124
+ var Computed = class _Computed {
125
+ /** Delay before auto-invalidating a Computed that holds an error result. 0 = disabled. */
126
+ static errorAutoInvalidateDelay = 1e3;
127
+ /** Capture the Computed backing a computation — works with both local and RPC compute methods. */
128
+ static async capture(fn) {
129
+ const captureComputed = new _Computed("__capture__");
130
+ const captureCtx = new ComputeContext(captureComputed);
131
+ const asyncCtx = import_core2.AsyncContext.getOrCreate().with(computeContextKey, captureCtx);
132
+ await asyncCtx.run(fn);
133
+ const deps = captureComputed.dependencies;
134
+ if (deps.size === 0)
135
+ throw new Error("No Computed was captured \u2014 fn must call a compute function.");
136
+ return deps.values().next().value;
137
+ }
138
+ input;
139
+ _version;
140
+ _state;
141
+ _output;
142
+ _dependencies = /* @__PURE__ */ new Set();
143
+ _dependants = /* @__PURE__ */ new Map();
144
+ onInvalidated = new import_core2.EventHandlerSet();
145
+ _renewer;
146
+ constructor(input, renewer) {
147
+ this.input = input;
148
+ this._renewer = renewer;
149
+ this._version = ++_nextVersion;
150
+ this._state = 0 /* Computing */;
151
+ }
152
+ get version() {
153
+ return this._version;
154
+ }
155
+ get output() {
156
+ if (this._output === void 0) throw new Error("Computed has no output yet.");
157
+ return this._output;
158
+ }
159
+ get hasValue() {
160
+ return this.output.hasValue;
161
+ }
162
+ get hasError() {
163
+ return this.output.hasError;
164
+ }
165
+ get value() {
166
+ return this.output.value;
167
+ }
168
+ get error() {
169
+ return this.output.error;
170
+ }
171
+ get valueOrUndefined() {
172
+ return this.output.valueOrUndefined;
173
+ }
174
+ get state() {
175
+ return this._state;
176
+ }
177
+ get isConsistent() {
178
+ return this._state === 1 /* Consistent */;
179
+ }
180
+ get dependencies() {
181
+ return this._dependencies;
182
+ }
183
+ update() {
184
+ if (this._state === 1 /* Consistent */) return this;
185
+ const latest = this._latest();
186
+ if (latest?.isConsistent) return latest;
187
+ if (this._renewer !== void 0) return this._renewer();
188
+ throw new Error("Cannot recompute: Computed is invalidated and has no renewer.");
189
+ }
190
+ _latest() {
191
+ return ComputedRegistry.get(this.input);
192
+ }
193
+ use(asyncContext) {
194
+ const ctx = ComputeContext.from(asyncContext);
195
+ const updated = this.update();
196
+ if (updated instanceof Promise) {
197
+ return updated.then((c) => {
198
+ ctx?.captureDependency(c);
199
+ return c.value;
200
+ });
201
+ }
202
+ ctx?.captureDependency(updated);
203
+ return updated.value;
204
+ }
205
+ useInconsistent(asyncContext) {
206
+ ComputeContext.from(asyncContext)?.captureDependency(this);
207
+ return this.value;
208
+ }
209
+ setOutput(output) {
210
+ if (this._state !== 0 /* Computing */)
211
+ throw new Error("Cannot set output on a non-computing Computed.");
212
+ this._output = output instanceof import_core2.Result ? output : (0, import_core2.result)(output);
213
+ this._state = 1 /* Consistent */;
214
+ this._register();
215
+ if (this._output.hasError && _Computed.errorAutoInvalidateDelay > 0)
216
+ setTimeout(() => this.invalidate(), _Computed.errorAutoInvalidateDelay);
217
+ }
218
+ _register() {
219
+ ComputedRegistry.register(this);
220
+ }
221
+ _unregister() {
222
+ ComputedRegistry.unregister(this);
223
+ }
224
+ invalidate() {
225
+ if (this._state === 2 /* Invalidated */) return;
226
+ this._state = 2 /* Invalidated */;
227
+ this._dependencies.clear();
228
+ for (const [, ref] of this._dependants) {
229
+ const dependant = ref.deref();
230
+ if (dependant != null) dependant.invalidate();
231
+ }
232
+ this._dependants.clear();
233
+ this.onInvalidated.trigger();
234
+ this.onInvalidated.clear();
235
+ this._unregister();
236
+ }
237
+ whenInvalidated(abortSignal) {
238
+ if (this._state === 2 /* Invalidated */)
239
+ return Promise.resolve();
240
+ const ps = new import_core2.PromiseSource();
241
+ const handler = () => ps.resolve(void 0);
242
+ this.onInvalidated.add(handler);
243
+ if (abortSignal !== void 0 && !abortSignal.aborted) {
244
+ abortSignal.addEventListener("abort", () => {
245
+ this.onInvalidated.remove(handler);
246
+ ps.reject(abortSignal.reason);
247
+ }, { once: true });
248
+ }
249
+ return ps.promise;
250
+ }
251
+ addDependency(dependency) {
252
+ this._dependencies.add(dependency);
253
+ dependency._dependants.set(this._version, new WeakRef(this));
254
+ }
255
+ };
256
+ var StateBoundComputed = class extends Computed {
257
+ constructor(state, renewer) {
258
+ super(state, renewer);
259
+ }
260
+ _latest() {
261
+ return this.input.computed;
262
+ }
263
+ _register() {
264
+ }
265
+ _unregister() {
266
+ }
267
+ };
268
+
269
+ // src/compute-function.ts
270
+ var import_core3 = require("@actuallab/core");
271
+ var RS = "";
272
+ function defaultArgToString(arg) {
273
+ return JSON.stringify(arg) ?? "undefined";
274
+ }
275
+ var _nextFunctionId = 0;
276
+ var ComputeFunction = class {
277
+ methodName;
278
+ id;
279
+ argToString = defaultArgToString;
280
+ _impl;
281
+ _locks = /* @__PURE__ */ new Map();
282
+ constructor(methodName, impl) {
283
+ this.methodName = methodName;
284
+ this.id = `${methodName}[${++_nextFunctionId}]`;
285
+ this._impl = impl;
286
+ }
287
+ /** Build a string key for the given instance and arguments. */
288
+ buildKey(instance, args) {
289
+ let key = String(getInstanceId(instance)) + RS + this.id;
290
+ for (const arg of args) {
291
+ key += RS + this.argToString(arg);
292
+ }
293
+ return key;
294
+ }
295
+ async invoke(instance, args, prevComputed) {
296
+ const asyncCtx = import_core3.AsyncContext.fromArgs(args);
297
+ const callerComputeCtx = asyncCtx?.get(computeContextKey);
298
+ const argsWithoutCtx = asyncCtx?.stripFromArgs(args) ?? args;
299
+ const key = this.buildKey(instance, argsWithoutCtx);
300
+ const existing = ComputedRegistry.get(key);
301
+ if (existing?.isConsistent) {
302
+ callerComputeCtx?.captureDependency(existing);
303
+ return existing;
304
+ }
305
+ let lock = this._locks.get(key);
306
+ if (lock === void 0) {
307
+ lock = new import_core3.AsyncLock();
308
+ this._locks.set(key, lock);
309
+ }
310
+ const computed = await lock.run(async () => {
311
+ const cached = ComputedRegistry.get(key);
312
+ if (cached?.isConsistent) return cached;
313
+ let newComputed;
314
+ const renewer = prevComputed?._renewer ?? (() => this.invoke(instance, argsWithoutCtx, newComputed));
315
+ newComputed = new Computed(key, renewer);
316
+ const childComputeCtx = new ComputeContext(newComputed);
317
+ const childAsyncCtx = (asyncCtx ?? import_core3.AsyncContext.empty).with(computeContextKey, childComputeCtx);
318
+ let fnResult;
319
+ try {
320
+ const value = childAsyncCtx.run(() => this._impl.call(instance, ...argsWithoutCtx));
321
+ const resolved = value instanceof Promise ? await value : value;
322
+ fnResult = (0, import_core3.result)(resolved);
323
+ } catch (e) {
324
+ fnResult = (0, import_core3.errorResult)(e);
325
+ }
326
+ newComputed.setOutput(fnResult);
327
+ return newComputed;
328
+ });
329
+ callerComputeCtx?.captureDependency(computed);
330
+ return computed;
331
+ }
332
+ };
333
+
334
+ // src/compute-method.ts
335
+ var METHODS_META = /* @__PURE__ */ Symbol.for("actuallab.methods");
336
+ function getMethodsMeta(cls) {
337
+ return cls[Symbol.metadata]?.[METHODS_META];
338
+ }
339
+ function computeMethod(target, context) {
340
+ const methodName = String(context.name);
341
+ const methods = context.metadata[METHODS_META] ??= {};
342
+ methods[methodName] = { ...methods[methodName], compute: true, argCount: target.length };
343
+ const cf = new ComputeFunction(methodName, target);
344
+ const replacement = function(...allArgs) {
345
+ return cf.invoke(this, allArgs).then((c) => c.value);
346
+ };
347
+ context.addInitializer(function() {
348
+ const instance = this;
349
+ const boundMethod = (...allArgs) => {
350
+ return cf.invoke(instance, allArgs).then((c) => c.value);
351
+ };
352
+ boundMethod.invalidate = (...args) => {
353
+ const key = cf.buildKey(instance, args);
354
+ ComputedRegistry.get(key)?.invalidate();
355
+ };
356
+ this[methodName] = boundMethod;
357
+ });
358
+ return replacement;
359
+ }
360
+ function wrapComputeMethod(fn) {
361
+ const syntheticInstance = {};
362
+ const methodName = fn.name || "anonymous";
363
+ const cf = new ComputeFunction(methodName, fn);
364
+ const wrapped = (...allArgs) => {
365
+ return cf.invoke(syntheticInstance, allArgs).then((c) => c.value);
366
+ };
367
+ wrapped.invalidate = (...args) => {
368
+ const key = cf.buildKey(syntheticInstance, args);
369
+ ComputedRegistry.get(key)?.invalidate();
370
+ };
371
+ return wrapped;
372
+ }
373
+
374
+ // src/update-delayer.ts
375
+ var FixedDelayer = class _FixedDelayer {
376
+ static zero = () => Promise.resolve();
377
+ static _cache = /* @__PURE__ */ new Map();
378
+ static get(ms) {
379
+ if (ms <= 0) return _FixedDelayer.zero;
380
+ let delayer = _FixedDelayer._cache.get(ms);
381
+ if (delayer === void 0) {
382
+ delayer = new _FixedDelayer(ms).delay;
383
+ _FixedDelayer._cache.set(ms, delayer);
384
+ }
385
+ return delayer;
386
+ }
387
+ ms;
388
+ delay;
389
+ constructor(ms) {
390
+ this.ms = ms;
391
+ this.delay = ms > 1e4 ? (abortSignal) => new Promise((resolve, reject) => {
392
+ const timer = setTimeout(resolve, this.ms);
393
+ if (abortSignal === void 0) return;
394
+ if (abortSignal.aborted) {
395
+ clearTimeout(timer);
396
+ reject(abortSignal.reason);
397
+ return;
398
+ }
399
+ abortSignal.addEventListener("abort", () => {
400
+ clearTimeout(timer);
401
+ reject(abortSignal.reason);
402
+ }, { once: true });
403
+ }) : () => new Promise((resolve) => setTimeout(resolve, this.ms));
404
+ }
405
+ };
406
+ var defaultUpdateDelayer = FixedDelayer.get(1e3 / 60);
407
+
408
+ // src/ui-action-tracker.ts
409
+ var import_core4 = require("@actuallab/core");
410
+ var UIActionTracker = class {
411
+ _activeCount = 0;
412
+ changed = new import_core4.EventHandlerSet();
413
+ errors = [];
414
+ get isActive() {
415
+ return this._activeCount > 0;
416
+ }
417
+ /** Run a command silently — errors are added to the error list but not thrown. */
418
+ async run(fn) {
419
+ this._activeCount++;
420
+ this.changed.trigger();
421
+ try {
422
+ await fn();
423
+ } catch (e) {
424
+ this.errors.push(e);
425
+ } finally {
426
+ this._activeCount--;
427
+ await new Promise((r) => setTimeout(r, 50));
428
+ this.changed.trigger();
429
+ }
430
+ }
431
+ /** Call a command and return the result — errors are added to the error list AND thrown. */
432
+ async call(fn) {
433
+ this._activeCount++;
434
+ this.changed.trigger();
435
+ try {
436
+ return await fn();
437
+ } catch (e) {
438
+ this.errors.push(e);
439
+ throw e;
440
+ } finally {
441
+ this._activeCount--;
442
+ await new Promise((r) => setTimeout(r, 50));
443
+ this.changed.trigger();
444
+ }
445
+ }
446
+ dismissError(index) {
447
+ if (index >= 0 && index < this.errors.length) {
448
+ this.errors.splice(index, 1);
449
+ this.changed.trigger();
450
+ }
451
+ }
452
+ };
453
+ var uiActions = new UIActionTracker();
454
+
455
+ // src/ui-update-delayer.ts
456
+ var UIUpdateDelayer = class _UIUpdateDelayer {
457
+ static _cache = /* @__PURE__ */ new Map();
458
+ static get(ms) {
459
+ if (ms <= 0) return FixedDelayer.zero;
460
+ let delayer = _UIUpdateDelayer._cache.get(ms);
461
+ if (delayer !== void 0) return delayer;
462
+ const t = uiActions;
463
+ delayer = (abortSignal) => {
464
+ if (t.isActive)
465
+ return Promise.resolve();
466
+ return new Promise((resolve, reject) => {
467
+ const timer = setTimeout(resolve, ms);
468
+ const onChanged = () => {
469
+ if (t.isActive) {
470
+ clearTimeout(timer);
471
+ t.changed.remove(onChanged);
472
+ resolve();
473
+ }
474
+ };
475
+ t.changed.add(onChanged);
476
+ if (abortSignal !== void 0) {
477
+ if (abortSignal.aborted) {
478
+ clearTimeout(timer);
479
+ t.changed.remove(onChanged);
480
+ reject(abortSignal.reason);
481
+ return;
482
+ }
483
+ abortSignal.addEventListener("abort", () => {
484
+ clearTimeout(timer);
485
+ t.changed.remove(onChanged);
486
+ reject(abortSignal.reason);
487
+ }, { once: true });
488
+ }
489
+ });
490
+ };
491
+ _UIUpdateDelayer._cache.set(ms, delayer);
492
+ return delayer;
493
+ }
494
+ };
495
+
496
+ // src/state.ts
497
+ var import_core5 = require("@actuallab/core");
498
+ var State = class {
499
+ _computed;
500
+ _updateIndex = 0;
501
+ _lastNonErrorValue;
502
+ _whenUpdatedSource = null;
503
+ get updateIndex() {
504
+ return this._updateIndex;
505
+ }
506
+ get lastNonErrorValue() {
507
+ return this._lastNonErrorValue;
508
+ }
509
+ get hasValue() {
510
+ return this._computed.hasValue;
511
+ }
512
+ get hasError() {
513
+ return this._computed.hasError;
514
+ }
515
+ get value() {
516
+ return this._computed.value;
517
+ }
518
+ get error() {
519
+ return this._computed.error;
520
+ }
521
+ get valueOrUndefined() {
522
+ return this._computed.valueOrUndefined;
523
+ }
524
+ get output() {
525
+ return this._computed.output;
526
+ }
527
+ get computed() {
528
+ return this._computed;
529
+ }
530
+ use(asyncContext) {
531
+ return this._computed.use(asyncContext);
532
+ }
533
+ useInconsistent(asyncContext) {
534
+ return this._computed.useInconsistent(asyncContext);
535
+ }
536
+ update() {
537
+ return this._computed.update();
538
+ }
539
+ recompute() {
540
+ this._computed.invalidate();
541
+ return this.update();
542
+ }
543
+ whenInvalidated() {
544
+ return this._computed.whenInvalidated();
545
+ }
546
+ whenUpdated() {
547
+ return (this._whenUpdatedSource ??= new import_core5.PromiseSource()).promise;
548
+ }
549
+ whenFirstTimeUpdated() {
550
+ return this._updateIndex > 0 ? import_core5.resolvedVoidPromise : this.whenUpdated();
551
+ }
552
+ _initialize(output, renewer) {
553
+ this._computed = new StateBoundComputed(this, renewer);
554
+ this._computed.setOutput(output);
555
+ this._lastNonErrorValue = this._computed.valueOrUndefined;
556
+ }
557
+ _update(computed, output) {
558
+ computed.setOutput(output);
559
+ this._computed = computed;
560
+ if (computed.hasValue)
561
+ this._lastNonErrorValue = computed.value;
562
+ this._updateIndex++;
563
+ this._whenUpdatedSource?.resolve(void 0);
564
+ this._whenUpdatedSource = null;
565
+ }
566
+ };
567
+
568
+ // src/computed-state.ts
569
+ var import_core6 = require("@actuallab/core");
570
+ var ComputedState = class extends State {
571
+ _computer;
572
+ _updateDelayer;
573
+ _disposeController;
574
+ _cancelDelaySource = new import_core6.PromiseSource();
575
+ _renewer;
576
+ _hasOutput = false;
577
+ constructor(computer, options) {
578
+ super();
579
+ this._computer = computer;
580
+ this._updateDelayer = options?.updateDelayer ?? defaultUpdateDelayer;
581
+ this._disposeController = new AbortController();
582
+ this._renewer = async () => {
583
+ const whenUpdated = this.whenUpdated();
584
+ this._cancelDelaySource.resolve(void 0);
585
+ await whenUpdated;
586
+ return this._computed;
587
+ };
588
+ if (options?.initialOutput !== void 0 || options?.initialValue !== void 0) {
589
+ this._initialize(options.initialOutput ?? options.initialValue, this._renewer);
590
+ this._hasOutput = true;
591
+ }
592
+ void this._updateCycle();
593
+ }
594
+ get hasValue() {
595
+ if (!this._hasOutput && this._updateIndex === 0) return false;
596
+ return this._computed.hasValue;
597
+ }
598
+ get hasError() {
599
+ if (!this._hasOutput && this._updateIndex === 0) return false;
600
+ return this._computed.hasError;
601
+ }
602
+ get value() {
603
+ if (!this._hasOutput && this._updateIndex === 0) throw new Error("ComputedState has no value yet.");
604
+ if (this._computed.hasValue) return this._computed.value;
605
+ if (this._lastNonErrorValue !== void 0) return this._lastNonErrorValue;
606
+ throw new Error("ComputedState has no value yet.");
607
+ }
608
+ get error() {
609
+ if (!this._hasOutput && this._updateIndex === 0) return void 0;
610
+ return this._computed.error;
611
+ }
612
+ get valueOrUndefined() {
613
+ if (!this._hasOutput && this._updateIndex === 0) return void 0;
614
+ return this._computed.valueOrUndefined ?? this._lastNonErrorValue;
615
+ }
616
+ get output() {
617
+ if (!this._hasOutput && this._updateIndex === 0) throw new Error("ComputedState has no output yet.");
618
+ return this._computed.output;
619
+ }
620
+ get computed() {
621
+ if (!this._hasOutput && this._updateIndex === 0) throw new Error("ComputedState has not been computed yet.");
622
+ return this._computed;
623
+ }
624
+ get isDisposed() {
625
+ return this._disposeController.signal.aborted;
626
+ }
627
+ dispose() {
628
+ if (!this.isDisposed)
629
+ this._disposeController.abort();
630
+ }
631
+ async _updateCycle() {
632
+ const disposeSignal = this._disposeController.signal;
633
+ try {
634
+ while (!disposeSignal.aborted) {
635
+ const computed = new StateBoundComputed(this, this._renewer);
636
+ const computeCtx = new ComputeContext(computed);
637
+ const asyncCtx = (import_core6.AsyncContext.current ?? import_core6.AsyncContext.empty).with(computeContextKey, computeCtx);
638
+ let output;
639
+ try {
640
+ const value = asyncCtx.run(() => this._computer());
641
+ const resolved = value instanceof Promise ? await value : value;
642
+ output = (0, import_core6.result)(resolved);
643
+ } catch (e) {
644
+ output = (0, import_core6.errorResult)(e);
645
+ }
646
+ this._update(computed, output);
647
+ if (this._cancelDelaySource.isCompleted)
648
+ this._cancelDelaySource = new import_core6.PromiseSource();
649
+ try {
650
+ await computed.whenInvalidated(disposeSignal);
651
+ } catch {
652
+ return;
653
+ }
654
+ await Promise.race([
655
+ this._updateDelayer(disposeSignal),
656
+ this._cancelDelaySource.promise
657
+ ]);
658
+ }
659
+ } catch (e) {
660
+ }
661
+ }
662
+ };
663
+
664
+ // src/mutable-state.ts
665
+ var import_core7 = require("@actuallab/core");
666
+ var MutableState = class extends State {
667
+ _renewer = () => {
668
+ const computed = new StateBoundComputed(this, this._renewer);
669
+ this._update(computed, this._computed.output);
670
+ return computed;
671
+ };
672
+ constructor(initialOutput) {
673
+ super();
674
+ this._initialize(initialOutput, this._renewer);
675
+ }
676
+ use(asyncContext) {
677
+ return this._computed.use(asyncContext);
678
+ }
679
+ set(output) {
680
+ this._computed.invalidate();
681
+ this._update(new StateBoundComputed(this, this._renewer), output);
682
+ }
683
+ };
684
+ // Annotate the CommonJS export names for ESM import in node:
685
+ 0 && (module.exports = {
686
+ ComputeContext,
687
+ ComputeFunction,
688
+ Computed,
689
+ ComputedRegistry,
690
+ ComputedState,
691
+ ConsistencyState,
692
+ FixedDelayer,
693
+ MutableState,
694
+ State,
695
+ StateBoundComputed,
696
+ UIActionTracker,
697
+ UIUpdateDelayer,
698
+ computeContextKey,
699
+ computeMethod,
700
+ defaultUpdateDelayer,
701
+ getInstanceId,
702
+ getMethodsMeta,
703
+ uiActions,
704
+ wrapComputeMethod
705
+ });
706
+ //# sourceMappingURL=index.cjs.map