@esportsplus/reactivity 0.11.7 → 0.12.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.
@@ -1,4 +1,7 @@
1
- declare const REACTIVE: unique symbol;
1
+ declare const COMPUTED: unique symbol;
2
+ declare const REACTIVE_ARRAY: unique symbol;
3
+ declare const REACTIVE_OBJECT: unique symbol;
4
+ declare const SIGNAL: unique symbol;
2
5
  declare const STABILIZER_IDLE = 0;
3
6
  declare const STABILIZER_RESCHEDULE = 1;
4
7
  declare const STABILIZER_RUNNING = 2;
@@ -8,4 +11,4 @@ declare const STATE_CHECK: number;
8
11
  declare const STATE_DIRTY: number;
9
12
  declare const STATE_RECOMPUTING: number;
10
13
  declare const STATE_IN_HEAP: number;
11
- export { REACTIVE, STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING };
14
+ export { COMPUTED, REACTIVE_ARRAY, REACTIVE_OBJECT, SIGNAL, STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING };
@@ -1,4 +1,7 @@
1
- const REACTIVE = Symbol('reactive');
1
+ const COMPUTED = Symbol('computed');
2
+ const REACTIVE_ARRAY = Symbol('reactive.array');
3
+ const REACTIVE_OBJECT = Symbol('reactive.object');
4
+ const SIGNAL = Symbol('signal');
2
5
  const STABILIZER_IDLE = 0;
3
6
  const STABILIZER_RESCHEDULE = 1;
4
7
  const STABILIZER_RUNNING = 2;
@@ -8,4 +11,4 @@ const STATE_CHECK = 1 << 0;
8
11
  const STATE_DIRTY = 1 << 1;
9
12
  const STATE_RECOMPUTING = 1 << 2;
10
13
  const STATE_IN_HEAP = 1 << 3;
11
- export { REACTIVE, STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING };
14
+ export { COMPUTED, REACTIVE_ARRAY, REACTIVE_OBJECT, SIGNAL, STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING };
package/build/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export { default as reactive } from './reactive/index.js';
2
+ export { STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED } from './constants.js';
2
3
  export * from './system.js';
3
4
  export * from './types.js';
package/build/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export { default as reactive } from './reactive/index.js';
2
+ export { STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED } from './constants.js';
2
3
  export * from './system.js';
3
4
  export * from './types.js';
@@ -1,6 +1,6 @@
1
+ import { REACTIVE_ARRAY } from '../constants.js';
1
2
  import { Computed, Infer } from '../types.js';
2
3
  import { ReactiveObject } from './object.js';
3
- import { Disposable } from './disposable.js';
4
4
  type API<T> = Infer<T>[] & ReactiveArray<T>;
5
5
  type Events<T> = {
6
6
  pop: {
@@ -27,19 +27,21 @@ type Events<T> = {
27
27
  items: Item<T>[];
28
28
  };
29
29
  };
30
- type Item<T> = Computed<T> | API<T> | ReactiveObject<T extends Record<PropertyKey, unknown> ? T : never> | T;
30
+ type Item<T> = T | Computed<T> | API<T> | ReactiveObject<T extends Record<PropertyKey, unknown> ? T : never>;
31
31
  type Listener<V> = {
32
32
  once?: boolean;
33
33
  (value: V): void;
34
34
  };
35
35
  type Value<T> = T extends Record<PropertyKey, unknown> ? ReactiveObject<T> : T extends Array<infer U> ? API<U> : T;
36
- declare class ReactiveArray<T> extends Disposable {
36
+ declare class ReactiveArray<T> {
37
+ [REACTIVE_ARRAY]: boolean;
37
38
  private data;
38
39
  private listeners;
39
40
  private proxy;
40
41
  constructor(data: Item<T>[], proxy: API<T>);
41
42
  get length(): number;
42
43
  set length(n: number);
44
+ private cleanup;
43
45
  at(i: number): T | API<T> | ReactiveObject<T extends Record<PropertyKey, unknown> ? T : never>;
44
46
  dispatch<K extends keyof Events<T>, V>(event: K, value?: V): void;
45
47
  dispose(): void;
@@ -54,5 +56,7 @@ declare class ReactiveArray<T> extends Disposable {
54
56
  splice(start: number, deleteCount?: number, ...input: T[]): Item<T>[];
55
57
  unshift(...input: T[]): number;
56
58
  }
59
+ declare const isReactiveArray: (value: any) => value is ReactiveArray<any>;
57
60
  export default function array<T>(input: T[]): API<T>;
61
+ export { isReactiveArray };
58
62
  export type { API as ReactiveArray };
@@ -1,13 +1,13 @@
1
- import { isFunction, isInstanceOf, isNumber, isObject } from '@esportsplus/utilities';
2
- import { computed, dispose, isComputed, read } from '../system.js';
3
- import object from './object.js';
4
- import { Disposable } from './disposable.js';
5
- class ReactiveArray extends Disposable {
1
+ import { isFunction, isNumber, isObject } from '@esportsplus/utilities';
2
+ import { REACTIVE_ARRAY } from '../constants.js';
3
+ import { computed, dispose, isComputed, onCleanup, read, root } from '../system.js';
4
+ import object, { isReactiveObject } from './object.js';
5
+ class ReactiveArray {
6
+ [REACTIVE_ARRAY] = true;
6
7
  data;
7
8
  listeners = null;
8
9
  proxy;
9
10
  constructor(data, proxy) {
10
- super();
11
11
  this.data = data;
12
12
  this.proxy = proxy;
13
13
  }
@@ -20,6 +20,14 @@ class ReactiveArray extends Disposable {
20
20
  }
21
21
  this.splice(n);
22
22
  }
23
+ cleanup(item) {
24
+ if (isReactiveObject(item)) {
25
+ item.dispose();
26
+ }
27
+ else if (isComputed(item)) {
28
+ dispose(item);
29
+ }
30
+ }
23
31
  at(i) {
24
32
  let value = this.data[i];
25
33
  if (isComputed(value)) {
@@ -49,17 +57,9 @@ class ReactiveArray extends Disposable {
49
57
  }
50
58
  }
51
59
  dispose() {
52
- let data = this.data;
53
- for (let i = 0, n = data.length; i < n; i++) {
54
- let value = data[i];
55
- if (isInstanceOf(value, Disposable)) {
56
- value.dispose();
57
- }
58
- else if (isComputed(value)) {
59
- dispose(value);
60
- }
60
+ for (let i = 0, n = this.data.length; i < n; i++) {
61
+ this.cleanup(this.data[i]);
61
62
  }
62
- this.listeners = null;
63
63
  }
64
64
  map(fn, i, n) {
65
65
  let { data, proxy } = this, values = [];
@@ -103,9 +103,7 @@ class ReactiveArray extends Disposable {
103
103
  pop() {
104
104
  let item = this.data.pop();
105
105
  if (item !== undefined) {
106
- if (isComputed(item)) {
107
- dispose(item);
108
- }
106
+ this.cleanup(item);
109
107
  this.dispatch('pop', { item });
110
108
  }
111
109
  return item;
@@ -123,9 +121,7 @@ class ReactiveArray extends Disposable {
123
121
  shift() {
124
122
  let item = this.data.shift();
125
123
  if (item !== undefined) {
126
- if (isComputed(item)) {
127
- dispose(item);
128
- }
124
+ this.cleanup(item);
129
125
  this.dispatch('shift', { item });
130
126
  }
131
127
  return item;
@@ -139,10 +135,7 @@ class ReactiveArray extends Disposable {
139
135
  let items = factory(input), removed = this.data.splice(start, deleteCount, ...items);
140
136
  if (items.length > 0 || removed.length > 0) {
141
137
  for (let i = 0, n = removed.length; i < n; i++) {
142
- let item = removed[i];
143
- if (isComputed(item)) {
144
- dispose(item);
145
- }
138
+ this.cleanup(removed[i]);
146
139
  }
147
140
  this.dispatch('splice', {
148
141
  deleteCount,
@@ -174,39 +167,41 @@ function factory(input) {
174
167
  }
175
168
  return items;
176
169
  }
170
+ const isReactiveArray = (value) => {
171
+ return isObject(value) && REACTIVE_ARRAY in value;
172
+ };
177
173
  export default function array(input) {
178
- let proxy = new Proxy({}, {
179
- get(_, key) {
180
- if (isNumber(key)) {
181
- let value = wrapped[key];
182
- if (isComputed(value)) {
183
- return read(value);
174
+ let { array, proxy } = root(() => {
175
+ let proxy = new Proxy({}, {
176
+ get(_, key) {
177
+ if (isNumber(key)) {
178
+ let value = wrapped[key];
179
+ if (isComputed(value)) {
180
+ return read(value);
181
+ }
182
+ return value;
184
183
  }
185
- return value;
186
- }
187
- else if (key in a) {
188
- return a[key];
189
- }
190
- return wrapped[key];
191
- },
192
- set(_, key, value) {
193
- if (isNumber(key)) {
194
- let host = wrapped[key];
195
- if (host === undefined || !isComputed(host)) {
196
- a.splice(key, 1, value);
184
+ else if (key in array) {
185
+ return array[key];
197
186
  }
198
- else {
199
- return false;
187
+ return wrapped[key];
188
+ },
189
+ set(_, key, value) {
190
+ if (isNumber(key)) {
191
+ array.splice(key, 1, value);
192
+ return true;
200
193
  }
201
- return true;
202
- }
203
- else if (key === 'length') {
204
- return a.length = value;
194
+ else if (key === 'length') {
195
+ return array.length = value;
196
+ }
197
+ return false;
205
198
  }
206
- return false;
207
- }
208
- }), wrapped = factory(input);
209
- let a = new ReactiveArray(wrapped, proxy);
199
+ }), wrapped = factory(input);
200
+ let array = new ReactiveArray(wrapped, proxy);
201
+ return { array, proxy };
202
+ });
203
+ onCleanup(() => array.dispose());
210
204
  return proxy;
211
205
  }
212
206
  ;
207
+ export { isReactiveArray };
@@ -3,10 +3,7 @@ import object from './object.js';
3
3
  type API<T> = T extends Record<PropertyKey, unknown> ? ReturnType<typeof object<T>> : T extends unknown[] ? ReturnType<typeof array<T>> : never;
4
4
  type Input<T> = T extends {
5
5
  dispose: any;
6
- } | {
7
- signals: any;
8
- } ? {
9
- never: '[ dispose, signals ] are reserved keys';
10
- } : T extends Record<PropertyKey, unknown> | unknown[] ? T : never;
11
- declare const _default: <T>(input: Input<T>) => API<T>;
6
+ } ? never : T extends Record<PropertyKey, unknown> ? T : T extends unknown[] ? Input<T[number]>[] : never;
7
+ declare const _default: <T extends Record<PropertyKey, unknown> | unknown[]>(input: Input<T>) => API<T>;
12
8
  export default _default;
9
+ export type { Input };
@@ -1,13 +1,15 @@
1
1
  import { Prettify } from '@esportsplus/utilities';
2
2
  import { Infer } from '../types.js';
3
- import { Disposable } from './disposable.js';
3
+ import { REACTIVE_OBJECT } from '../constants.js';
4
4
  type API<T extends Record<PropertyKey, unknown>> = Prettify<{
5
5
  [K in keyof T]: Infer<T[K]>;
6
6
  }> & ReactiveObject<T>;
7
- declare class ReactiveObject<T extends Record<PropertyKey, unknown>> extends Disposable {
8
- private disposable;
7
+ declare class ReactiveObject<T extends Record<PropertyKey, unknown>> {
8
+ [REACTIVE_OBJECT]: boolean;
9
9
  constructor(data: T);
10
10
  dispose(): void;
11
11
  }
12
- export default function object<T extends Record<PropertyKey, unknown>>(input: T): API<T>;
12
+ declare const isReactiveObject: (value: any) => value is ReactiveObject<any>;
13
+ export default function object<T extends Record<PropertyKey, unknown>>(input: T): ReactiveObject<T>;
14
+ export { isReactiveObject };
13
15
  export type { API as ReactiveObject };
@@ -1,26 +1,18 @@
1
- import { defineProperty, isArray, isFunction, isInstanceOf, isPromise } from '@esportsplus/utilities';
2
- import array from './array.js';
3
- import { computed, dispose, effect, read, root, signal } from '../system.js';
4
- import { Disposable } from './disposable.js';
5
- let { set } = signal;
6
- class ReactiveObject extends Disposable {
7
- disposable = {};
1
+ import { defineProperty, isArray, isFunction, isObject, isPromise } from '@esportsplus/utilities';
2
+ import { computed, dispose, effect, isComputed, onCleanup, read, root, set, signal } from '../system.js';
3
+ import { REACTIVE_OBJECT } from '../constants.js';
4
+ import array, { isReactiveArray } from './array.js';
5
+ class ReactiveObject {
6
+ [REACTIVE_OBJECT] = true;
8
7
  constructor(data) {
9
- super();
10
- let disposable = this.disposable, triggers = {};
11
8
  for (let key in data) {
12
9
  let value = data[key];
13
10
  if (isArray(value)) {
14
- let a = disposable[key] = array(value), t = triggers[key] = signal(false);
11
+ let a = array(value);
15
12
  defineProperty(this, key, {
16
13
  enumerable: true,
17
14
  get() {
18
- read(t);
19
15
  return a;
20
- },
21
- set(v) {
22
- a = disposable[key] = array(v);
23
- set(t, !!t.value);
24
16
  }
25
17
  });
26
18
  }
@@ -31,7 +23,7 @@ class ReactiveObject extends Disposable {
31
23
  get() {
32
24
  if (c === undefined) {
33
25
  root(() => {
34
- c = disposable[key] = computed(value);
26
+ c = computed(value);
35
27
  if (isPromise(c.value)) {
36
28
  let factory = c, version = 0;
37
29
  c = signal(undefined);
@@ -66,19 +58,25 @@ class ReactiveObject extends Disposable {
66
58
  }
67
59
  }
68
60
  dispose() {
69
- for (let key in this.disposable) {
70
- let value = this.disposable[key];
71
- if (isInstanceOf(value, Disposable)) {
61
+ let value;
62
+ for (let key in this) {
63
+ value = this[key];
64
+ if (isReactiveArray(value) || isReactiveObject(value)) {
72
65
  value.dispose();
73
66
  }
74
- else {
67
+ else if (isComputed(value)) {
75
68
  dispose(value);
76
69
  }
77
70
  }
78
- this.disposable = {};
79
71
  }
80
72
  }
73
+ const isReactiveObject = (value) => {
74
+ return isObject(value) && REACTIVE_OBJECT in value;
75
+ };
81
76
  export default function object(input) {
82
- return new ReactiveObject(input);
77
+ let object = root(() => new ReactiveObject(input));
78
+ onCleanup(() => object.dispose());
79
+ return object;
83
80
  }
84
81
  ;
82
+ export { isReactiveObject };
package/build/system.d.ts CHANGED
@@ -7,8 +7,7 @@ declare const isSignal: (value: unknown) => value is Signal<unknown>;
7
7
  declare const onCleanup: (fn: VoidFunction) => typeof fn;
8
8
  declare const read: <T>(node: Signal<T> | Computed<T>) => T;
9
9
  declare const root: <T>(fn: () => T) => T;
10
- declare const signal: {
11
- <T>(value: T): Signal<T>;
12
- set<T>(signal: Signal<T>, value: T): void;
13
- };
14
- export { computed, dispose, effect, isComputed, isSignal, onCleanup, read, root, signal };
10
+ declare const set: <T>(signal: Signal<T>, value: T) => void;
11
+ declare const signal: <T>(value: T) => Signal<T>;
12
+ export { computed, dispose, effect, isComputed, isSignal, onCleanup, read, root, set, signal };
13
+ export type { Computed, Signal };
package/build/system.js CHANGED
@@ -1,13 +1,13 @@
1
- import { isArray, isObject } from '@esportsplus/utilities';
2
- import { REACTIVE, STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING } from './constants.js';
3
- let depth = 0, heap = new Array(2000), index = 0, length = 0, notified = false, observer = null, scheduler = queueMicrotask, stabilizer = STABILIZER_IDLE, version = 0;
1
+ import { isArray, isObject, } from '@esportsplus/utilities';
2
+ import { COMPUTED, SIGNAL, STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING } from './constants.js';
3
+ let depth = 0, heap = new Array(2048), index = 0, length = 0, microtask = queueMicrotask, notified = false, observer = null, stabilizer = STABILIZER_IDLE, version = 0;
4
4
  function cleanup(node) {
5
5
  if (!node.cleanup) {
6
6
  return;
7
7
  }
8
8
  let cleanup = node.cleanup;
9
9
  if (isArray(cleanup)) {
10
- for (let i = 0; i < cleanup.length; i++) {
10
+ for (let i = 0, n = cleanup.length; i < n; i++) {
11
11
  cleanup[i]();
12
12
  }
13
13
  }
@@ -58,7 +58,7 @@ function insertIntoHeap(computed) {
58
58
  if (height > length) {
59
59
  length = height;
60
60
  if (height >= heap.length) {
61
- heap.length *= 1.5;
61
+ heap.length = Math.round(heap.length * 1.5);
62
62
  }
63
63
  }
64
64
  }
@@ -165,31 +165,31 @@ function recompute(computed, del) {
165
165
  function schedule() {
166
166
  if (stabilizer === STABILIZER_IDLE && !depth) {
167
167
  stabilizer = STABILIZER_SCHEDULED;
168
- scheduler(stabilize);
168
+ microtask(stabilize);
169
169
  }
170
170
  else if (stabilizer === STABILIZER_RUNNING) {
171
171
  stabilizer = STABILIZER_RESCHEDULE;
172
172
  }
173
173
  }
174
174
  function stabilize() {
175
- root(() => {
176
- stabilizer = STABILIZER_RUNNING;
177
- for (index = 0; index <= length; index++) {
178
- let computed = heap[index];
179
- heap[index] = undefined;
180
- while (computed !== undefined) {
181
- let next = computed.nextHeap;
182
- recompute(computed, false);
183
- computed = next;
184
- }
185
- }
186
- if (stabilizer === STABILIZER_RESCHEDULE) {
187
- scheduler(stabilize);
188
- }
189
- else {
190
- stabilizer = STABILIZER_IDLE;
175
+ let o = observer;
176
+ stabilizer = STABILIZER_RUNNING;
177
+ for (index = 0; index <= length; index++) {
178
+ let computed = heap[index];
179
+ heap[index] = undefined;
180
+ while (computed !== undefined) {
181
+ let next = computed.nextHeap;
182
+ recompute(computed, false);
183
+ computed = next;
191
184
  }
192
- });
185
+ }
186
+ observer = o;
187
+ if (stabilizer === STABILIZER_RESCHEDULE) {
188
+ microtask(stabilize);
189
+ }
190
+ else {
191
+ stabilizer = STABILIZER_IDLE;
192
+ }
193
193
  }
194
194
  function unlink(link) {
195
195
  let { dep, nextDep, nextSub, prevSub } = link;
@@ -202,11 +202,8 @@ function unlink(link) {
202
202
  if (prevSub !== null) {
203
203
  prevSub.nextSub = nextSub;
204
204
  }
205
- else {
206
- dep.subs = nextSub;
207
- if (nextSub === null && 'fn' in dep) {
208
- dispose(dep);
209
- }
205
+ else if ((dep.subs = nextSub) === null && 'fn' in dep) {
206
+ dispose(dep);
210
207
  }
211
208
  return nextDep;
212
209
  }
@@ -216,9 +213,9 @@ function update(computed) {
216
213
  let dep = link.dep;
217
214
  if ('fn' in dep) {
218
215
  update(dep);
219
- }
220
- if (computed.state & STATE_DIRTY) {
221
- break;
216
+ if (computed.state & STATE_DIRTY) {
217
+ break;
218
+ }
222
219
  }
223
220
  }
224
221
  }
@@ -229,7 +226,7 @@ function update(computed) {
229
226
  }
230
227
  const computed = (fn) => {
231
228
  let self = {
232
- [REACTIVE]: true,
229
+ [COMPUTED]: true,
233
230
  cleanup: null,
234
231
  deps: null,
235
232
  depsTail: null,
@@ -254,6 +251,7 @@ const computed = (fn) => {
254
251
  schedule();
255
252
  }
256
253
  link(self, observer);
254
+ onCleanup(() => dispose(self));
257
255
  }
258
256
  else {
259
257
  recompute(self, false);
@@ -276,24 +274,23 @@ const effect = (fn) => {
276
274
  };
277
275
  };
278
276
  const isComputed = (value) => {
279
- return isObject(value) && REACTIVE in value && 'fn' in value;
277
+ return isObject(value) && COMPUTED in value;
280
278
  };
281
279
  const isSignal = (value) => {
282
- return isObject(value) && REACTIVE in value && 'fn' in value === false;
280
+ return isObject(value) && SIGNAL in value;
283
281
  };
284
282
  const onCleanup = (fn) => {
285
283
  if (!observer) {
286
284
  return fn;
287
285
  }
288
- let node = observer;
289
- if (!node.cleanup) {
290
- node.cleanup = fn;
286
+ if (!observer.cleanup) {
287
+ observer.cleanup = fn;
291
288
  }
292
- else if (isArray(node.cleanup)) {
293
- node.cleanup.push(fn);
289
+ else if (isArray(observer.cleanup)) {
290
+ observer.cleanup.push(fn);
294
291
  }
295
292
  else {
296
- node.cleanup = [node.cleanup, fn];
293
+ observer.cleanup = [observer.cleanup, fn];
297
294
  }
298
295
  return fn;
299
296
  };
@@ -328,15 +325,7 @@ const root = (fn) => {
328
325
  observer = o;
329
326
  return value;
330
327
  };
331
- const signal = (value) => {
332
- return {
333
- [REACTIVE]: true,
334
- subs: null,
335
- subsTail: null,
336
- value,
337
- };
338
- };
339
- signal.set = (signal, value) => {
328
+ const set = (signal, value) => {
340
329
  if (signal.value === value) {
341
330
  return;
342
331
  }
@@ -350,4 +339,12 @@ signal.set = (signal, value) => {
350
339
  }
351
340
  schedule();
352
341
  };
353
- export { computed, dispose, effect, isComputed, isSignal, onCleanup, read, root, signal };
342
+ const signal = (value) => {
343
+ return {
344
+ [SIGNAL]: true,
345
+ subs: null,
346
+ subsTail: null,
347
+ value,
348
+ };
349
+ };
350
+ export { computed, dispose, effect, isComputed, isSignal, onCleanup, read, root, set, signal };
package/build/types.d.ts CHANGED
@@ -1,17 +1,19 @@
1
- import { REACTIVE, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING } from './constants.js';
2
- import { onCleanup } from './system.js';
1
+ import { COMPUTED, SIGNAL, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING } from './constants.js';
3
2
  import { ReactiveArray } from './reactive/array.js';
4
3
  import { ReactiveObject } from './reactive/object.js';
5
- interface Computed<T> extends Signal<T> {
6
- [REACTIVE]: true;
4
+ interface Computed<T> {
5
+ [COMPUTED]: true;
7
6
  cleanup: VoidFunction | VoidFunction[] | null;
8
7
  deps: Link | null;
9
8
  depsTail: Link | null;
10
- fn: (oc?: typeof onCleanup) => T;
9
+ fn: (onCleanup?: (fn: VoidFunction) => typeof fn) => T;
11
10
  height: number;
12
11
  nextHeap: Computed<unknown> | undefined;
13
12
  prevHeap: Computed<unknown>;
14
13
  state: typeof STATE_CHECK | typeof STATE_DIRTY | typeof STATE_IN_HEAP | typeof STATE_NONE | typeof STATE_RECOMPUTING;
14
+ subs: Link | null;
15
+ subsTail: Link | null;
16
+ value: T;
15
17
  }
16
18
  type Infer<T> = T extends (...args: unknown[]) => Promise<infer R> ? R | undefined : T extends (...args: any[]) => infer R ? R : T extends (infer U)[] ? ReactiveArray<U> : T extends ReactiveObject<any> ? T : T extends Record<PropertyKey, unknown> ? {
17
19
  [K in keyof T]: T[K];
@@ -26,7 +28,7 @@ interface Link {
26
28
  }
27
29
  type Reactive<T> = T extends Record<PropertyKey, unknown> ? ReactiveObject<T> : ReactiveArray<T>;
28
30
  type Signal<T> = {
29
- [REACTIVE]: true;
31
+ [SIGNAL]: true;
30
32
  subs: Link | null;
31
33
  subsTail: Link | null;
32
34
  value: T;
package/build/types.js CHANGED
@@ -1 +1 @@
1
- import { REACTIVE } from './constants.js';
1
+ import { COMPUTED, SIGNAL } from './constants.js';
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "private": false,
13
13
  "type": "module",
14
14
  "types": "build/index.d.ts",
15
- "version": "0.11.7",
15
+ "version": "0.12.0",
16
16
  "scripts": {
17
17
  "build": "tsc && tsc-alias",
18
18
  "-": "-"
package/src/constants.ts CHANGED
@@ -1,4 +1,10 @@
1
- const REACTIVE = Symbol('reactive');
1
+ const COMPUTED = Symbol('computed');
2
+
3
+ const REACTIVE_ARRAY = Symbol('reactive.array');
4
+
5
+ const REACTIVE_OBJECT = Symbol('reactive.object');
6
+
7
+ const SIGNAL = Symbol('signal');
2
8
 
3
9
 
4
10
  const STABILIZER_IDLE = 0;
@@ -22,7 +28,10 @@ const STATE_IN_HEAP = 1 << 3;
22
28
 
23
29
 
24
30
  export {
25
- REACTIVE,
31
+ COMPUTED,
32
+ REACTIVE_ARRAY,
33
+ REACTIVE_OBJECT,
34
+ SIGNAL,
26
35
  STABILIZER_IDLE,
27
36
  STABILIZER_RESCHEDULE,
28
37
  STABILIZER_RUNNING,
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export { default as reactive } from './reactive';
2
+ export { STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED } from './constants';
2
3
  export * from './system';
3
4
  export * from './types';
@@ -1,8 +1,8 @@
1
- import { isFunction, isInstanceOf, isNumber, isObject } from '@esportsplus/utilities';
2
- import { computed, dispose, isComputed, read } from '~/system';
1
+ import { isFunction, isNumber, isObject } from '@esportsplus/utilities';
2
+ import { REACTIVE_ARRAY } from '~/constants';
3
+ import { computed, dispose, isComputed, onCleanup, read, root } from '~/system';
3
4
  import { Computed, Infer } from '~/types';
4
- import object, { ReactiveObject } from './object';
5
- import { Disposable } from './disposable';
5
+ import object, { isReactiveObject, ReactiveObject } from './object';
6
6
 
7
7
 
8
8
  type API<T> = Infer<T>[] & ReactiveArray<T>;
@@ -33,7 +33,7 @@ type Events<T> = {
33
33
  };
34
34
  };
35
35
 
36
- type Item<T> = Computed<T> | API<T> | ReactiveObject<T extends Record<PropertyKey, unknown> ? T : never> | T;
36
+ type Item<T> = T | Computed<T> | API<T> | ReactiveObject< T extends Record<PropertyKey, unknown> ? T : never >;
37
37
 
38
38
  type Listener<V> = {
39
39
  once?: boolean;
@@ -48,15 +48,15 @@ type Value<T> =
48
48
  : T;
49
49
 
50
50
 
51
- class ReactiveArray<T> extends Disposable {
51
+ class ReactiveArray<T> {
52
+ [REACTIVE_ARRAY] = true;
53
+
52
54
  private data: Item<T>[];
53
55
  private listeners: Record<string, (Listener<any> | null)[]> | null = null;
54
56
  private proxy: API<T>;
55
57
 
56
58
 
57
59
  constructor(data: Item<T>[], proxy: API<T>) {
58
- super();
59
-
60
60
  this.data = data;
61
61
  this.proxy = proxy;
62
62
  }
@@ -75,6 +75,16 @@ class ReactiveArray<T> extends Disposable {
75
75
  }
76
76
 
77
77
 
78
+ private cleanup(item: Item<T>) {
79
+ if (isReactiveObject(item)) {
80
+ item.dispose();
81
+ }
82
+ else if (isComputed(item)) {
83
+ dispose(item);
84
+ }
85
+ }
86
+
87
+
78
88
  at(i: number) {
79
89
  let value = this.data[i];
80
90
 
@@ -113,20 +123,9 @@ class ReactiveArray<T> extends Disposable {
113
123
  }
114
124
 
115
125
  dispose() {
116
- let data = this.data;
117
-
118
- for (let i = 0, n = data.length; i < n; i++) {
119
- let value = data[i];
120
-
121
- if (isInstanceOf(value, Disposable)) {
122
- value.dispose();
123
- }
124
- else if (isComputed(value)) {
125
- dispose(value);
126
- }
126
+ for (let i = 0, n = this.data.length; i < n; i++) {
127
+ this.cleanup(this.data[i]);
127
128
  }
128
-
129
- this.listeners = null;
130
129
  }
131
130
 
132
131
  map<R>(
@@ -194,10 +193,7 @@ class ReactiveArray<T> extends Disposable {
194
193
  let item = this.data.pop();
195
194
 
196
195
  if (item !== undefined) {
197
- if (isComputed(item)) {
198
- dispose(item);
199
- }
200
-
196
+ this.cleanup(item);
201
197
  this.dispatch('pop', { item });
202
198
  }
203
199
 
@@ -224,10 +220,7 @@ class ReactiveArray<T> extends Disposable {
224
220
  let item = this.data.shift();
225
221
 
226
222
  if (item !== undefined) {
227
- if (isComputed(item)) {
228
- dispose(item);
229
- }
230
-
223
+ this.cleanup(item);
231
224
  this.dispatch('shift', { item });
232
225
  }
233
226
 
@@ -250,11 +243,7 @@ class ReactiveArray<T> extends Disposable {
250
243
 
251
244
  if (items.length > 0 || removed.length > 0) {
252
245
  for (let i = 0, n = removed.length; i < n; i++) {
253
- let item = removed[i];
254
-
255
- if (isComputed(item)) {
256
- dispose(item);
257
- }
246
+ this.cleanup(removed[i]);
258
247
  }
259
248
 
260
249
  this.dispatch('splice', {
@@ -299,48 +288,52 @@ function factory<T>(input: T[]) {
299
288
  }
300
289
 
301
290
 
302
- export default function array<T>(input: T[]) {
303
- let proxy = new Proxy({}, {
304
- get(_: any, key: any) {
305
- if (isNumber(key)) {
306
- let value = wrapped[key];
307
-
308
- if (isComputed(value)) {
309
- return read(value);
310
- }
291
+ const isReactiveArray = (value: any): value is ReactiveArray<any> => {
292
+ return isObject(value) && REACTIVE_ARRAY in value;
293
+ };
311
294
 
312
- return value;
313
- }
314
- else if (key in a) {
315
- return a[key as keyof typeof a];
316
- }
317
295
 
318
- return wrapped[key];
319
- },
320
- set(_: any, key: any, value: any) {
321
- if (isNumber(key)) {
322
- let host = wrapped[key];
296
+ export default function array<T>(input: T[]) {
297
+ let { array, proxy } = root(() => {
298
+ let proxy = new Proxy({}, {
299
+ get(_: any, key: any) {
300
+ if (isNumber(key)) {
301
+ let value = wrapped[key];
302
+
303
+ if (isComputed(value)) {
304
+ return read(value);
305
+ }
306
+
307
+ return value;
308
+ }
309
+ else if (key in array) {
310
+ return array[key as keyof typeof array];
311
+ }
312
+
313
+ return wrapped[key];
314
+ },
315
+ set(_: any, key: any, value: any) {
316
+ if (isNumber(key)) {
317
+ array.splice(key, 1, value);
318
+ return true;
319
+ }
320
+ else if (key === 'length') {
321
+ return array.length = value;
322
+ }
323
323
 
324
- if (host === undefined || !isComputed(host)) {
325
- a.splice(key, 1, value);
326
- }
327
- else {
328
324
  return false;
329
325
  }
326
+ }) as API<T>,
327
+ wrapped = factory(input);
330
328
 
331
- return true;
332
- }
333
- else if (key === 'length') {
334
- return a.length = value;
335
- }
329
+ let array = new ReactiveArray(wrapped, proxy);
336
330
 
337
- return false;
338
- }
339
- }) as API<T>,
340
- wrapped = factory(input);
331
+ return { array, proxy };
332
+ });
341
333
 
342
- let a = new ReactiveArray(wrapped, proxy);
334
+ onCleanup(() => array.dispose());
343
335
 
344
336
  return proxy;
345
337
  };
338
+ export { isReactiveArray };
346
339
  export type { API as ReactiveArray };
@@ -11,14 +11,16 @@ type API<T> =
11
11
  : never;
12
12
 
13
13
  type Input<T> =
14
- T extends { dispose: any } | { signals: any }
15
- ? { never: '[ dispose, signals ] are reserved keys' }
16
- : T extends Record<PropertyKey, unknown> | unknown[]
17
- ? T
14
+ T extends { dispose: any }
15
+ ? never
16
+ : T extends Record<PropertyKey, unknown>
17
+ ? T
18
+ : T extends unknown[]
19
+ ? Input<T[number]>[]
18
20
  : never;
19
21
 
20
22
 
21
- export default <T>(input: Input<T>): API<T> => {
23
+ export default <T extends Record<PropertyKey, unknown> | unknown[]>(input: Input<T>): API<T> => {
22
24
  if (isArray(input)) {
23
25
  return array(input) as API<T>;
24
26
  }
@@ -27,4 +29,5 @@ export default <T>(input: Input<T>): API<T> => {
27
29
  }
28
30
 
29
31
  throw new Error(`@esportsplus/reactivity: 'reactive' received invalid input - ${JSON.stringify(input)}`);
30
- };
32
+ };
33
+ export type { Input };
@@ -1,45 +1,27 @@
1
- import { defineProperty, isArray, isFunction, isInstanceOf, isPromise, Prettify } from '@esportsplus/utilities';
2
- import array, { ReactiveArray } from './array';
3
- import { computed, dispose, effect, read, root, signal } from '~/system';
1
+ import { defineProperty, isArray, isFunction, isObject, isPromise, Prettify } from '@esportsplus/utilities';
2
+ import { computed, dispose, effect, isComputed, onCleanup, read, root, set, signal } from '~/system';
4
3
  import { Computed, Infer, Signal } from '~/types';
5
- import { Disposable } from './disposable';
4
+ import { REACTIVE_OBJECT } from '~/constants';
5
+ import array, { isReactiveArray } from './array';
6
6
 
7
7
 
8
8
  type API<T extends Record<PropertyKey, unknown>> = Prettify<{ [K in keyof T]: Infer<T[K]> }> & ReactiveObject<T>;
9
9
 
10
10
 
11
- let { set } = signal;
12
-
13
-
14
- class ReactiveObject<T extends Record<PropertyKey, unknown>> extends Disposable {
15
- private disposable: Record<
16
- PropertyKey,
17
- Computed<any> | ReactiveArray<any> | ReactiveObject<any>
18
- > = {};
19
-
11
+ class ReactiveObject<T extends Record<PropertyKey, unknown>> {
12
+ [REACTIVE_OBJECT] = true;
20
13
 
21
14
  constructor(data: T) {
22
- super();
23
-
24
- let disposable = this.disposable,
25
- triggers: Record<string, Signal<boolean>> = {};
26
-
27
15
  for (let key in data) {
28
16
  let value = data[key];
29
17
 
30
18
  if (isArray(value)) {
31
- let a = disposable[key] = array(value),
32
- t = triggers[key] = signal(false);
19
+ let a = array(value);
33
20
 
34
21
  defineProperty(this, key, {
35
22
  enumerable: true,
36
23
  get() {
37
- read(t);
38
24
  return a;
39
- },
40
- set(v: typeof value) {
41
- a = disposable[key] = array(v);
42
- set(t, !!t.value);
43
25
  }
44
26
  });
45
27
  }
@@ -51,7 +33,7 @@ class ReactiveObject<T extends Record<PropertyKey, unknown>> extends Disposable
51
33
  get() {
52
34
  if (c === undefined) {
53
35
  root(() => {
54
- c = disposable[key] = computed(value as Computed<T[typeof key]>['fn']);
36
+ c = computed(value as Computed<T[typeof key]>['fn']);
55
37
 
56
38
  if (isPromise(c.value)) {
57
39
  let factory = c,
@@ -67,7 +49,7 @@ class ReactiveObject<T extends Record<PropertyKey, unknown>> extends Disposable
67
49
  return;
68
50
  }
69
51
 
70
- set(c!, value);
52
+ set(c as Signal<typeof value>, value);
71
53
  });
72
54
  });
73
55
  }
@@ -96,23 +78,33 @@ class ReactiveObject<T extends Record<PropertyKey, unknown>> extends Disposable
96
78
 
97
79
 
98
80
  dispose() {
99
- for (let key in this.disposable) {
100
- let value = this.disposable[key];
81
+ let value;
82
+
83
+ for (let key in this) {
84
+ value = this[key];
101
85
 
102
- if (isInstanceOf(value, Disposable)) {
86
+ if (isReactiveArray(value) || isReactiveObject(value)) {
103
87
  value.dispose();
104
88
  }
105
- else {
89
+ else if (isComputed(value)) {
106
90
  dispose(value);
107
91
  }
108
92
  }
109
-
110
- this.disposable = {};
111
93
  }
112
94
  }
113
95
 
114
96
 
97
+ const isReactiveObject = (value: any): value is ReactiveObject<any> => {
98
+ return isObject(value) && REACTIVE_OBJECT in value;
99
+ };
100
+
101
+
115
102
  export default function object<T extends Record<PropertyKey, unknown>>(input: T) {
116
- return new ReactiveObject(input) as API<T>;
103
+ let object = root(() => new ReactiveObject<T>(input));
104
+
105
+ onCleanup(() => object.dispose());
106
+
107
+ return object;
117
108
  };
109
+ export { isReactiveObject };
118
110
  export type { API as ReactiveObject };
package/src/system.ts CHANGED
@@ -1,19 +1,19 @@
1
- import { isArray, isObject } from '@esportsplus/utilities';
1
+ import { isArray, isObject, } from '@esportsplus/utilities';
2
2
  import {
3
- REACTIVE,
3
+ COMPUTED, SIGNAL,
4
4
  STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED,
5
5
  STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING
6
6
  } from './constants';
7
- import { Computed, Link, Signal, } from './types';
7
+ import { Computed, Link, Signal } from './types';
8
8
 
9
9
 
10
10
  let depth = 0,
11
- heap: (Computed<unknown> | undefined)[] = new Array(2000),
11
+ heap: (Computed<unknown> | undefined)[] = new Array(2048),
12
12
  index = 0,
13
13
  length = 0,
14
+ microtask = queueMicrotask,
14
15
  notified = false,
15
16
  observer: Computed<unknown> | null = null,
16
- scheduler = queueMicrotask,
17
17
  stabilizer = STABILIZER_IDLE,
18
18
  version = 0;
19
19
 
@@ -26,7 +26,7 @@ function cleanup<T>(node: Computed<T>): void {
26
26
  let cleanup = node.cleanup;
27
27
 
28
28
  if (isArray(cleanup)) {
29
- for (let i = 0; i < cleanup.length; i++) {
29
+ for (let i = 0, n = cleanup.length; i < n; i++) {
30
30
  cleanup[i]();
31
31
  }
32
32
  }
@@ -98,7 +98,7 @@ function insertIntoHeap<T>(computed: Computed<T>) {
98
98
 
99
99
  // Simple auto adjust to avoid manual management within apps.
100
100
  if (height >= heap.length) {
101
- heap.length *= 1.5;
101
+ heap.length = Math.round(heap.length * 1.5);
102
102
  }
103
103
  }
104
104
  }
@@ -245,7 +245,7 @@ function recompute<T>(computed: Computed<T>, del: boolean) {
245
245
  function schedule() {
246
246
  if (stabilizer === STABILIZER_IDLE && !depth) {
247
247
  stabilizer = STABILIZER_SCHEDULED;
248
- scheduler(stabilize);
248
+ microtask(stabilize);
249
249
  }
250
250
  else if (stabilizer === STABILIZER_RUNNING) {
251
251
  stabilizer = STABILIZER_RESCHEDULE;
@@ -253,30 +253,32 @@ function schedule() {
253
253
  }
254
254
 
255
255
  function stabilize() {
256
- root(() => {
257
- stabilizer = STABILIZER_RUNNING;
256
+ let o = observer;
258
257
 
259
- for (index = 0; index <= length; index++) {
260
- let computed = heap[index];
258
+ stabilizer = STABILIZER_RUNNING;
261
259
 
262
- heap[index] = undefined;
260
+ for (index = 0; index <= length; index++) {
261
+ let computed = heap[index];
263
262
 
264
- while (computed !== undefined) {
265
- let next = computed.nextHeap;
263
+ heap[index] = undefined;
266
264
 
267
- recompute(computed, false);
265
+ while (computed !== undefined) {
266
+ let next = computed.nextHeap;
268
267
 
269
- computed = next;
270
- }
271
- }
268
+ recompute(computed, false);
272
269
 
273
- if (stabilizer === STABILIZER_RESCHEDULE) {
274
- scheduler(stabilize);
275
- }
276
- else {
277
- stabilizer = STABILIZER_IDLE;
270
+ computed = next;
278
271
  }
279
- });
272
+ }
273
+
274
+ observer = o;
275
+
276
+ if (stabilizer === STABILIZER_RESCHEDULE) {
277
+ microtask(stabilize);
278
+ }
279
+ else {
280
+ stabilizer = STABILIZER_IDLE;
281
+ }
280
282
  }
281
283
 
282
284
  // https://github.com/stackblitz/alien-signals/blob/v2.0.3/src/system.ts#L100
@@ -293,12 +295,8 @@ function unlink(link: Link): Link | null {
293
295
  if (prevSub !== null) {
294
296
  prevSub.nextSub = nextSub;
295
297
  }
296
- else {
297
- dep.subs = nextSub;
298
-
299
- if (nextSub === null && 'fn' in dep) {
300
- dispose(dep);
301
- }
298
+ else if ((dep.subs = nextSub) === null && 'fn' in dep) {
299
+ dispose(dep);
302
300
  }
303
301
 
304
302
  return nextDep;
@@ -311,10 +309,10 @@ function update<T>(computed: Computed<T>): void {
311
309
 
312
310
  if ('fn' in dep) {
313
311
  update(dep);
314
- }
315
312
 
316
- if (computed.state & STATE_DIRTY) {
317
- break;
313
+ if (computed.state & STATE_DIRTY) {
314
+ break;
315
+ }
318
316
  }
319
317
  }
320
318
  }
@@ -329,7 +327,7 @@ function update<T>(computed: Computed<T>): void {
329
327
 
330
328
  const computed = <T>(fn: Computed<T>['fn']): Computed<T> => {
331
329
  let self: Computed<T> = {
332
- [REACTIVE]: true,
330
+ [COMPUTED]: true,
333
331
  cleanup: null,
334
332
  deps: null,
335
333
  depsTail: null,
@@ -357,6 +355,7 @@ const computed = <T>(fn: Computed<T>['fn']): Computed<T> => {
357
355
  }
358
356
 
359
357
  link(self, observer);
358
+ onCleanup(() => dispose(self));
360
359
  }
361
360
  else {
362
361
  recompute(self, false);
@@ -388,11 +387,11 @@ const effect = <T>(fn: Computed<T>['fn']) => {
388
387
  };
389
388
 
390
389
  const isComputed = (value: unknown): value is Computed<unknown> => {
391
- return isObject(value) && REACTIVE in value && 'fn' in value;
390
+ return isObject(value) && COMPUTED in value;
392
391
  };
393
392
 
394
393
  const isSignal = (value: unknown): value is Signal<unknown> => {
395
- return isObject(value) && REACTIVE in value && 'fn' in value === false;
394
+ return isObject(value) && SIGNAL in value;
396
395
  };
397
396
 
398
397
  const onCleanup = (fn: VoidFunction): typeof fn => {
@@ -400,16 +399,14 @@ const onCleanup = (fn: VoidFunction): typeof fn => {
400
399
  return fn;
401
400
  }
402
401
 
403
- let node = observer;
404
-
405
- if (!node.cleanup) {
406
- node.cleanup = fn;
402
+ if (!observer.cleanup) {
403
+ observer.cleanup = fn;
407
404
  }
408
- else if (isArray(node.cleanup)) {
409
- node.cleanup.push(fn);
405
+ else if (isArray(observer.cleanup)) {
406
+ observer.cleanup.push(fn);
410
407
  }
411
408
  else {
412
- node.cleanup = [node.cleanup, fn];
409
+ observer.cleanup = [observer.cleanup, fn];
413
410
  }
414
411
 
415
412
  return fn;
@@ -460,16 +457,7 @@ const root = <T>(fn: () => T) => {
460
457
  return value;
461
458
  };
462
459
 
463
- const signal = <T>(value: T): Signal<T> => {
464
- return {
465
- [REACTIVE]: true,
466
- subs: null,
467
- subsTail: null,
468
- value,
469
- };
470
- };
471
-
472
- signal.set = <T>(signal: Signal<T>, value: T) => {
460
+ const set = <T>(signal: Signal<T>, value: T) => {
473
461
  if (signal.value === value) {
474
462
  return;
475
463
  }
@@ -488,6 +476,15 @@ signal.set = <T>(signal: Signal<T>, value: T) => {
488
476
  schedule();
489
477
  };
490
478
 
479
+ const signal = <T>(value: T): Signal<T> => {
480
+ return {
481
+ [SIGNAL]: true,
482
+ subs: null,
483
+ subsTail: null,
484
+ value,
485
+ };
486
+ };
487
+
491
488
 
492
489
  export {
493
490
  computed,
@@ -496,5 +493,6 @@ export {
496
493
  isComputed, isSignal,
497
494
  onCleanup,
498
495
  read, root,
499
- signal
500
- };
496
+ set, signal
497
+ };
498
+ export type { Computed, Signal };
package/src/types.ts CHANGED
@@ -1,15 +1,14 @@
1
- import { REACTIVE, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING } from './constants';
2
- import { onCleanup } from './system';
1
+ import { COMPUTED, SIGNAL, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING } from './constants';
3
2
  import { ReactiveArray } from './reactive/array';
4
3
  import { ReactiveObject } from './reactive/object';
5
4
 
6
5
 
7
- interface Computed<T> extends Signal<T> {
8
- [REACTIVE]: true;
6
+ interface Computed<T> {
7
+ [COMPUTED]: true;
9
8
  cleanup: VoidFunction | VoidFunction[] | null;
10
9
  deps: Link | null;
11
10
  depsTail: Link | null;
12
- fn: (oc?: typeof onCleanup) => T;
11
+ fn: (onCleanup?: (fn: VoidFunction) => typeof fn) => T;
13
12
  height: number;
14
13
  nextHeap: Computed<unknown> | undefined;
15
14
  prevHeap: Computed<unknown>;
@@ -19,6 +18,9 @@ interface Computed<T> extends Signal<T> {
19
18
  typeof STATE_IN_HEAP |
20
19
  typeof STATE_NONE |
21
20
  typeof STATE_RECOMPUTING;
21
+ subs: Link | null;
22
+ subsTail: Link | null;
23
+ value: T;
22
24
  }
23
25
 
24
26
  type Infer<T> =
@@ -48,7 +50,7 @@ type Reactive<T> = T extends Record<PropertyKey, unknown>
48
50
  : ReactiveArray<T>;
49
51
 
50
52
  type Signal<T> = {
51
- [REACTIVE]: true;
53
+ [SIGNAL]: true;
52
54
  subs: Link | null;
53
55
  subsTail: Link | null;
54
56
  value: T;
@@ -1,4 +0,0 @@
1
- declare class Disposable {
2
- dispose(): void;
3
- }
4
- export { Disposable };
@@ -1,6 +0,0 @@
1
- class Disposable {
2
- dispose() {
3
- throw new Error('@esportsplus/reactivity: Disposable should not be instantiated directly.');
4
- }
5
- }
6
- export { Disposable };
@@ -1,8 +0,0 @@
1
- class Disposable {
2
- dispose(): void {
3
- throw new Error('@esportsplus/reactivity: Disposable should not be instantiated directly.');
4
- }
5
- }
6
-
7
-
8
- export { Disposable };