onejs-core 0.3.5

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.
Files changed (63) hide show
  1. package/.gitattributes +2 -0
  2. package/.github/workflows/jsr.yml +19 -0
  3. package/.prettierrc +5 -0
  4. package/3rdparty/preact/LICENSE +21 -0
  5. package/3rdparty/preact/clone-element.ts +45 -0
  6. package/3rdparty/preact/compat/Children.ts +21 -0
  7. package/3rdparty/preact/compat/forwardRef.ts +49 -0
  8. package/3rdparty/preact/compat/index.ts +3 -0
  9. package/3rdparty/preact/compat/memo.ts +34 -0
  10. package/3rdparty/preact/compat/util.ts +38 -0
  11. package/3rdparty/preact/component.ts +235 -0
  12. package/3rdparty/preact/constants.ts +3 -0
  13. package/3rdparty/preact/create-context.ts +71 -0
  14. package/3rdparty/preact/create-element.ts +98 -0
  15. package/3rdparty/preact/diff/catch-error.ts +40 -0
  16. package/3rdparty/preact/diff/children.ts +355 -0
  17. package/3rdparty/preact/diff/index.ts +563 -0
  18. package/3rdparty/preact/diff/props.ts +174 -0
  19. package/3rdparty/preact/hooks/index.ts +536 -0
  20. package/3rdparty/preact/hooks/internal.d.ts +85 -0
  21. package/3rdparty/preact/hooks.d.ts +145 -0
  22. package/3rdparty/preact/index.ts +13 -0
  23. package/3rdparty/preact/internal.d.ts +155 -0
  24. package/3rdparty/preact/jsx-runtime/index.ts +80 -0
  25. package/3rdparty/preact/jsx.d.ts +1008 -0
  26. package/3rdparty/preact/options.ts +16 -0
  27. package/3rdparty/preact/preact.d.ts +317 -0
  28. package/3rdparty/preact/render.ts +76 -0
  29. package/3rdparty/preact/signals/index.ts +443 -0
  30. package/3rdparty/preact/signals/internal.d.ts +36 -0
  31. package/3rdparty/preact/signals-core/index.ts +663 -0
  32. package/3rdparty/preact/style.d.ts +205 -0
  33. package/3rdparty/preact/util.ts +29 -0
  34. package/@DO_NOT_CHANGE.txt +3 -0
  35. package/README.md +33 -0
  36. package/definitions/app.d.ts +52048 -0
  37. package/definitions/augments.d.ts +16 -0
  38. package/definitions/globals.d.ts +34 -0
  39. package/definitions/index.d.ts +9 -0
  40. package/definitions/jsx.d.ts +517 -0
  41. package/definitions/modules.d.ts +29 -0
  42. package/definitions/onejs.d.ts +164 -0
  43. package/definitions/preact.jsx.d.ts +7 -0
  44. package/definitions/proto-overrides.d.ts +13 -0
  45. package/definitions/puerts.d.ts +31 -0
  46. package/definitions/unity-engine.d.ts +23 -0
  47. package/hooks/eventful.ts +56 -0
  48. package/import-transform.mjs +42 -0
  49. package/index.ts +44 -0
  50. package/jsr.json +10 -0
  51. package/onejs-tw-config.cjs +188 -0
  52. package/package.json +9 -0
  53. package/preloads/inject.ts +44 -0
  54. package/styling/index.tsx +80 -0
  55. package/styling/utils/generateAlphabeticName.ts +21 -0
  56. package/styling/utils/generateComponentId.ts +6 -0
  57. package/styling/utils/hash.ts +46 -0
  58. package/switch.cjs +185 -0
  59. package/uss-transform-plugin.cjs +83 -0
  60. package/utils/color-palettes.ts +3 -0
  61. package/utils/color-parser.ts +249 -0
  62. package/utils/float-parser.ts +31 -0
  63. package/utils/index.ts +12 -0
@@ -0,0 +1,663 @@
1
+ function cycleDetected(): never {
2
+ throw new Error("Cycle detected");
3
+ }
4
+
5
+ // Flags for Computed and Effect.
6
+ const RUNNING = 1 << 0;
7
+ const NOTIFIED = 1 << 1;
8
+ const OUTDATED = 1 << 2;
9
+ const DISPOSED = 1 << 3;
10
+ const HAS_ERROR = 1 << 4;
11
+ const TRACKING = 1 << 5;
12
+
13
+ // A linked list node used to track dependencies (sources) and dependents (targets).
14
+ // Also used to remember the source's last version number that the target saw.
15
+ type Node = {
16
+ // A source whose value the target depends on.
17
+ _source: Signal;
18
+ _prevSource?: Node;
19
+ _nextSource?: Node;
20
+
21
+ // A target that depends on the source and should be notified when the source changes.
22
+ _target: Computed | Effect;
23
+ _prevTarget?: Node;
24
+ _nextTarget?: Node;
25
+
26
+ // The version number of the source that target has last seen. We use version numbers
27
+ // instead of storing the source value, because source values can take arbitrary amount
28
+ // of memory, and computeds could hang on to them forever because they're lazily evaluated.
29
+ // Use the special value -1 to mark potentially unused but recyclable nodes.
30
+ _version: number;
31
+
32
+ // Used to remember & roll back the source's previous `._node` value when entering &
33
+ // exiting a new evaluation context.
34
+ _rollbackNode?: Node;
35
+ };
36
+
37
+ function startBatch() {
38
+ batchDepth++;
39
+ }
40
+
41
+ function endBatch() {
42
+ if (batchDepth > 1) {
43
+ batchDepth--;
44
+ return;
45
+ }
46
+
47
+ let error: unknown;
48
+ let hasError = false;
49
+
50
+ while (batchedEffect !== undefined) {
51
+ let effect: Effect | undefined = batchedEffect;
52
+ batchedEffect = undefined;
53
+
54
+ batchIteration++;
55
+
56
+ while (effect !== undefined) {
57
+ const next: Effect | undefined = effect._nextBatchedEffect;
58
+ effect._nextBatchedEffect = undefined;
59
+ effect._flags &= ~NOTIFIED;
60
+
61
+ if (!(effect._flags & DISPOSED) && needsToRecompute(effect)) {
62
+ try {
63
+ effect._callback();
64
+ } catch (err) {
65
+ if (!hasError) {
66
+ error = err;
67
+ hasError = true;
68
+ }
69
+ }
70
+ }
71
+ effect = next;
72
+ }
73
+ }
74
+ batchIteration = 0;
75
+ batchDepth--;
76
+
77
+ if (hasError) {
78
+ throw error;
79
+ }
80
+ }
81
+
82
+ function batch<T>(callback: () => T): T {
83
+ if (batchDepth > 0) {
84
+ return callback();
85
+ }
86
+ /*@__INLINE__**/ startBatch();
87
+ try {
88
+ return callback();
89
+ } finally {
90
+ endBatch();
91
+ }
92
+ }
93
+
94
+ // Currently evaluated computed or effect.
95
+ let evalContext: Computed | Effect | undefined = undefined;
96
+
97
+ // Effects collected into a batch.
98
+ let batchedEffect: Effect | undefined = undefined;
99
+ let batchDepth = 0;
100
+ let batchIteration = 0;
101
+
102
+ // A global version number for signals, used for fast-pathing repeated
103
+ // computed.peek()/computed.value calls when nothing has changed globally.
104
+ let globalVersion = 0;
105
+
106
+ function addDependency(signal: Signal): Node | undefined {
107
+ if (evalContext === undefined) {
108
+ return undefined;
109
+ }
110
+
111
+ let node = signal._node;
112
+ if (node === undefined || node._target !== evalContext) {
113
+ // `signal` is a new dependency. Create a new node dependency node, move it
114
+ // to the front of the current context's dependency list.
115
+ node = {
116
+ _version: 0,
117
+ _source: signal,
118
+ _prevSource: undefined,
119
+ _nextSource: evalContext._sources,
120
+ _target: evalContext,
121
+ _prevTarget: undefined,
122
+ _nextTarget: undefined,
123
+ _rollbackNode: node,
124
+ };
125
+ evalContext._sources = node;
126
+ signal._node = node;
127
+
128
+ // Subscribe to change notifications from this dependency if we're in an effect
129
+ // OR evaluating a computed signal that in turn has subscribers.
130
+ if (evalContext._flags & TRACKING) {
131
+ signal._subscribe(node);
132
+ }
133
+ return node;
134
+ } else if (node._version === -1) {
135
+ // `signal` is an existing dependency from a previous evaluation. Reuse it.
136
+ node._version = 0;
137
+
138
+ // If `node` is not already the current head of the dependency list (i.e.
139
+ // there is a previous node in the list), then make `node` the new head.
140
+ if (node._prevSource !== undefined) {
141
+ node._prevSource._nextSource = node._nextSource;
142
+ if (node._nextSource !== undefined) {
143
+ node._nextSource._prevSource = node._prevSource;
144
+ }
145
+ node._prevSource = undefined;
146
+ node._nextSource = evalContext._sources;
147
+ // evalCotext._sources must be !== undefined (and !== node), because
148
+ // `node` was originally pointing to some previous node.
149
+ evalContext._sources!._prevSource = node;
150
+ evalContext._sources = node;
151
+ }
152
+
153
+ // We can assume that the currently evaluated effect / computed signal is already
154
+ // subscribed to change notifications from `signal` if needed.
155
+ return node;
156
+ }
157
+ return undefined;
158
+ }
159
+
160
+ declare class Signal<T = any> {
161
+ /** @internal */
162
+ _value: unknown;
163
+
164
+ /** @internal
165
+ * Version numbers should always be >= 0, because the special value -1 is used
166
+ * by Nodes to signify potentially unused but recyclable notes.
167
+ */
168
+ _version: number;
169
+
170
+ /** @internal */
171
+ _node?: Node;
172
+
173
+ /** @internal */
174
+ _targets?: Node;
175
+
176
+ constructor(value?: T);
177
+
178
+ /** @internal */
179
+ _refresh(): boolean;
180
+
181
+ /** @internal */
182
+ _subscribe(node: Node): void;
183
+
184
+ /** @internal */
185
+ _unsubscribe(node: Node): void;
186
+
187
+ subscribe(fn: (value: T) => void): () => void;
188
+
189
+ valueOf(): T;
190
+
191
+ toString(): string;
192
+
193
+ peek(): T;
194
+
195
+ get value(): T;
196
+ set value(value: T);
197
+ }
198
+
199
+ /** @internal */
200
+ function Signal(this: Signal, value?: unknown) {
201
+ this._value = value;
202
+ this._version = 0;
203
+ this._node = undefined;
204
+ this._targets = undefined;
205
+ }
206
+
207
+ Signal.prototype._refresh = function () {
208
+ return true;
209
+ };
210
+
211
+ Signal.prototype._subscribe = function (node) {
212
+ if (this._targets !== node && node._prevTarget === undefined) {
213
+ node._nextTarget = this._targets;
214
+ if (this._targets !== undefined) {
215
+ this._targets._prevTarget = node;
216
+ }
217
+ this._targets = node;
218
+ }
219
+ };
220
+
221
+ Signal.prototype._unsubscribe = function (node) {
222
+ const prev = node._prevTarget;
223
+ const next = node._nextTarget;
224
+ if (prev !== undefined) {
225
+ prev._nextTarget = next;
226
+ node._prevTarget = undefined;
227
+ }
228
+ if (next !== undefined) {
229
+ next._prevTarget = prev;
230
+ node._nextTarget = undefined;
231
+ }
232
+ if (node === this._targets) {
233
+ this._targets = next;
234
+ }
235
+ };
236
+
237
+ Signal.prototype.subscribe = function (fn) {
238
+ const signal = this;
239
+ return effect(function (this: Effect) {
240
+ const value = signal.value;
241
+ const flag = this._flags & TRACKING;
242
+ this._flags &= ~TRACKING;
243
+ try {
244
+ fn(value);
245
+ } finally {
246
+ this._flags |= flag;
247
+ }
248
+ });
249
+ };
250
+
251
+ Signal.prototype.valueOf = function () {
252
+ return this.value;
253
+ };
254
+
255
+ Signal.prototype.toString = function () {
256
+ return this.value + "";
257
+ };
258
+
259
+ Signal.prototype.peek = function () {
260
+ return this._value;
261
+ };
262
+
263
+ Object.defineProperty(Signal.prototype, "value", {
264
+ get() {
265
+ const node = addDependency(this);
266
+ if (node !== undefined) {
267
+ node._version = this._version;
268
+ }
269
+ return this._value;
270
+ },
271
+ set(value) {
272
+ if (value !== this._value) {
273
+ if (batchIteration > 100) {
274
+ cycleDetected();
275
+ }
276
+
277
+ this._value = value;
278
+ this._version++;
279
+ globalVersion++;
280
+
281
+ /**@__INLINE__*/ startBatch();
282
+ try {
283
+ for (
284
+ let node = this._targets;
285
+ node !== undefined;
286
+ node = node._nextTarget
287
+ ) {
288
+ node._target._notify();
289
+ }
290
+ } finally {
291
+ endBatch();
292
+ }
293
+ }
294
+ },
295
+ });
296
+
297
+ function signal<T>(value: T): Signal<T> {
298
+ return new Signal(value);
299
+ }
300
+
301
+ function needsToRecompute(target: Computed | Effect): boolean {
302
+ // Check the dependencies for changed values. The dependency list is already
303
+ // in order of use. Therefore if multiple dependencies have changed values, only
304
+ // the first used dependency is re-evaluated at this point.
305
+ for (
306
+ let node = target._sources;
307
+ node !== undefined;
308
+ node = node._nextSource
309
+ ) {
310
+ // If there's a new version of the dependency before or after refreshing,
311
+ // or the dependency has something blocking it from refreshing at all (e.g. a
312
+ // dependency cycle), then we need to recompute.
313
+ if (
314
+ node._source._version !== node._version ||
315
+ !node._source._refresh() ||
316
+ node._source._version !== node._version
317
+ ) {
318
+ return true;
319
+ }
320
+ }
321
+ // If none of the dependencies have changed values since last recompute then the
322
+ // there's no need to recompute.
323
+ return false;
324
+ }
325
+
326
+ function prepareSources(target: Computed | Effect) {
327
+ for (
328
+ let node = target._sources;
329
+ node !== undefined;
330
+ node = node._nextSource
331
+ ) {
332
+ const rollbackNode = node._source._node;
333
+ if (rollbackNode !== undefined) {
334
+ node._rollbackNode = rollbackNode;
335
+ }
336
+ node._source._node = node;
337
+ node._version = -1;
338
+ }
339
+ }
340
+
341
+ function cleanupSources(target: Computed | Effect) {
342
+ // At this point target._sources is a mishmash of current & former dependencies.
343
+ // The current dependencies are also in a reverse order of use.
344
+ // Therefore build a new, reverted list of dependencies containing only the current
345
+ // dependencies in a proper order of use.
346
+ // Drop former dependencies from the list and unsubscribe from their change notifications.
347
+
348
+ let node = target._sources;
349
+ let sources: any = undefined;
350
+ while (node !== undefined) {
351
+ const next = node._nextSource;
352
+ if (node._version === -1) {
353
+ node._source._unsubscribe(node);
354
+ node._nextSource = undefined;
355
+ } else {
356
+ if (sources !== undefined) {
357
+ sources._prevSource = node;
358
+ }
359
+ node._prevSource = undefined;
360
+ node._nextSource = sources;
361
+ sources = node;
362
+ }
363
+
364
+ node._source._node = node._rollbackNode;
365
+ if (node._rollbackNode !== undefined) {
366
+ node._rollbackNode = undefined;
367
+ }
368
+ node = next;
369
+ }
370
+ target._sources = sources;
371
+ }
372
+
373
+ declare class Computed<T = any> extends Signal<T> {
374
+ _compute: () => T;
375
+ _sources?: Node;
376
+ _globalVersion: number;
377
+ _flags: number;
378
+
379
+ constructor(compute: () => T);
380
+
381
+ _notify(): void;
382
+ get value(): T;
383
+ }
384
+
385
+ function Computed(this: Computed, compute: () => unknown) {
386
+ Signal.call(this, undefined);
387
+
388
+ this._compute = compute;
389
+ this._sources = undefined;
390
+ this._globalVersion = globalVersion - 1;
391
+ this._flags = OUTDATED;
392
+ }
393
+
394
+ Computed.prototype = new Signal() as unknown as Computed;
395
+
396
+ (Computed.prototype as any)._refresh = function () {
397
+ this._flags &= ~NOTIFIED;
398
+
399
+ if (this._flags & RUNNING) {
400
+ return false;
401
+ }
402
+
403
+ // If this computed signal has subscribed to updates from its dependencies
404
+ // (TRACKING flag set) and none of them have notified about changes (OUTDATED
405
+ // flag not set), then the computed value can't have changed.
406
+ if ((this._flags & (OUTDATED | TRACKING)) === TRACKING) {
407
+ return true;
408
+ }
409
+ this._flags &= ~OUTDATED;
410
+
411
+ if (this._globalVersion === globalVersion) {
412
+ return true;
413
+ }
414
+ this._globalVersion = globalVersion;
415
+
416
+ // Mark this computed signal running before checking the dependencies for value
417
+ // changes, so that the RUNNIN flag can be used to notice cyclical dependencies.
418
+ this._flags |= RUNNING;
419
+ if (this._version > 0 && !needsToRecompute(this)) {
420
+ this._flags &= ~RUNNING;
421
+ return true;
422
+ }
423
+
424
+ const prevContext = evalContext;
425
+ try {
426
+ prepareSources(this);
427
+ evalContext = this;
428
+ const value = this._compute();
429
+ if (
430
+ this._flags & HAS_ERROR ||
431
+ this._value !== value ||
432
+ this._version === 0
433
+ ) {
434
+ this._value = value;
435
+ this._flags &= ~HAS_ERROR;
436
+ this._version++;
437
+ }
438
+ } catch (err) {
439
+ this._value = err;
440
+ this._flags |= HAS_ERROR;
441
+ this._version++;
442
+ }
443
+ evalContext = prevContext;
444
+ cleanupSources(this);
445
+ this._flags &= ~RUNNING;
446
+ return true;
447
+ };
448
+
449
+ (Computed.prototype as any)._subscribe = function (node) {
450
+ if (this._targets === undefined) {
451
+ this._flags |= OUTDATED | TRACKING;
452
+
453
+ // A computed signal subscribes lazily to its dependencies when the it
454
+ // gets its first subscriber.
455
+ for (
456
+ let node = this._sources;
457
+ node !== undefined;
458
+ node = node._nextSource
459
+ ) {
460
+ node._source._subscribe(node);
461
+ }
462
+ }
463
+ Signal.prototype._subscribe.call(this, node);
464
+ };
465
+
466
+ (Computed.prototype as any)._unsubscribe = function (node) {
467
+ Signal.prototype._unsubscribe.call(this, node);
468
+
469
+ // Computed signal unsubscribes from its dependencies from it loses its last subscriber.
470
+ if (this._targets === undefined) {
471
+ this._flags &= ~TRACKING;
472
+
473
+ for (
474
+ let node = this._sources;
475
+ node !== undefined;
476
+ node = node._nextSource
477
+ ) {
478
+ node._source._unsubscribe(node);
479
+ }
480
+ }
481
+ };
482
+
483
+ (Computed.prototype as any)._notify = function () {
484
+ if (!(this._flags & NOTIFIED)) {
485
+ this._flags |= OUTDATED | NOTIFIED;
486
+
487
+ for (
488
+ let node = this._targets;
489
+ node !== undefined;
490
+ node = node._nextTarget
491
+ ) {
492
+ node._target._notify();
493
+ }
494
+ }
495
+ };
496
+
497
+ (Computed.prototype as any).peek = function () {
498
+ if (!this._refresh()) {
499
+ cycleDetected();
500
+ }
501
+ if (this._flags & HAS_ERROR) {
502
+ throw this._value;
503
+ }
504
+ return this._value;
505
+ };
506
+
507
+ Object.defineProperty(Computed.prototype, "value", {
508
+ get() {
509
+ if (this._flags & RUNNING) {
510
+ cycleDetected();
511
+ }
512
+ const node = addDependency(this);
513
+ this._refresh();
514
+ if (node !== undefined) {
515
+ node._version = this._version;
516
+ }
517
+ if (this._flags & HAS_ERROR) {
518
+ throw this._value;
519
+ }
520
+ return this._value;
521
+ },
522
+ });
523
+
524
+ interface ReadonlySignal<T = any> extends Signal<T> {
525
+ readonly value: T;
526
+ }
527
+
528
+ function computed<T>(compute: () => T): ReadonlySignal<T> {
529
+ // @ts-ignore
530
+ return new Computed(compute);
531
+ }
532
+
533
+ function cleanupEffect(effect: Effect) {
534
+ const cleanup = effect._cleanup;
535
+ effect._cleanup = undefined;
536
+
537
+ if (typeof cleanup === "function") {
538
+ /*@__INLINE__**/ startBatch();
539
+
540
+ // Run cleanup functions always outside of any context.
541
+ const prevContext = evalContext;
542
+ evalContext = undefined;
543
+ try {
544
+ cleanup();
545
+ } catch (err) {
546
+ effect._flags &= ~RUNNING;
547
+ effect._flags |= DISPOSED;
548
+ disposeEffect(effect);
549
+ throw err;
550
+ } finally {
551
+ evalContext = prevContext;
552
+ endBatch();
553
+ }
554
+ }
555
+ }
556
+
557
+ function disposeEffect(effect: Effect) {
558
+ for (
559
+ let node = effect._sources;
560
+ node !== undefined;
561
+ node = node._nextSource
562
+ ) {
563
+ node._source._unsubscribe(node);
564
+ }
565
+ effect._compute = undefined;
566
+ effect._sources = undefined;
567
+
568
+ cleanupEffect(effect);
569
+ }
570
+
571
+ function endEffect(this: Effect, prevContext?: Computed | Effect) {
572
+ if (evalContext !== this) {
573
+ throw new Error("Out-of-order effect");
574
+ }
575
+ cleanupSources(this);
576
+ evalContext = prevContext;
577
+
578
+ this._flags &= ~RUNNING;
579
+ if (this._flags & DISPOSED) {
580
+ disposeEffect(this);
581
+ }
582
+ endBatch();
583
+ }
584
+
585
+ declare class Effect {
586
+ _compute?: () => unknown;
587
+ _cleanup?: unknown;
588
+ _sources?: Node;
589
+ _nextBatchedEffect?: Effect;
590
+ _flags: number;
591
+
592
+ constructor(compute: () => void);
593
+
594
+ _callback(): void;
595
+ _start(): () => void;
596
+ _notify(): void;
597
+ _dispose(): void;
598
+ }
599
+
600
+ function Effect(this: Effect, compute: () => void) {
601
+ this._compute = compute;
602
+ this._cleanup = undefined;
603
+ this._sources = undefined;
604
+ this._nextBatchedEffect = undefined;
605
+ this._flags = TRACKING;
606
+ }
607
+
608
+ Effect.prototype._callback = function () {
609
+ const finish = this._start();
610
+ try {
611
+ if (!(this._flags & DISPOSED) && this._compute !== undefined) {
612
+ this._cleanup = this._compute();
613
+ }
614
+ } finally {
615
+ finish();
616
+ }
617
+ };
618
+
619
+ Effect.prototype._start = function () {
620
+ if (this._flags & RUNNING) {
621
+ cycleDetected();
622
+ }
623
+ this._flags |= RUNNING;
624
+ this._flags &= ~DISPOSED;
625
+ cleanupEffect(this);
626
+ prepareSources(this);
627
+
628
+ /*@__INLINE__**/ startBatch();
629
+ const prevContext = evalContext;
630
+ evalContext = this;
631
+ return endEffect.bind(this, prevContext);
632
+ };
633
+
634
+ Effect.prototype._notify = function () {
635
+ if (!(this._flags & NOTIFIED)) {
636
+ this._flags |= NOTIFIED;
637
+ this._nextBatchedEffect = batchedEffect;
638
+ batchedEffect = this;
639
+ }
640
+ };
641
+
642
+ Effect.prototype._dispose = function () {
643
+ this._flags |= DISPOSED;
644
+
645
+ if (!(this._flags & RUNNING)) {
646
+ disposeEffect(this);
647
+ }
648
+ };
649
+
650
+ function effect(compute: () => unknown): () => void {
651
+ const effect = new Effect(compute);
652
+ try {
653
+ effect._callback();
654
+ } catch (err) {
655
+ effect._dispose();
656
+ throw err;
657
+ }
658
+ // Return a bound function instead of a wrapper like `() => effect._dispose()`,
659
+ // because bound functions seem to be just as fast and take up a lot less memory.
660
+ return effect._dispose.bind(effect);
661
+ }
662
+
663
+ export { signal, computed, effect, batch, Signal, type ReadonlySignal };