@esportsplus/reactivity 0.14.3 → 0.16.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.
@@ -4,7 +4,7 @@ type ReactiveArray<T extends unknown[]> = Prettify<Infer<T> & {
4
4
  clear: () => void;
5
5
  dispose: () => void;
6
6
  dispatch: <K extends keyof Events<T[number]>, V>(event: K, value?: V) => void;
7
- map: <R>(fn: (this: ReactiveArray<T>, value: T[number], i: number) => R, i?: number, n?: number) => R[];
7
+ map: <R>(fn: (this: ReactiveArray<T>, value: T[number], i: number) => R) => R[];
8
8
  on: <K extends keyof Events<T[number]>>(event: K, listener: Listener<Events<T[number]>[K]>) => void;
9
9
  once: <K extends keyof Events<T[number]>>(event: K, listener: Listener<Events<T[number]>[K]>) => void;
10
10
  }>;
@@ -60,7 +60,7 @@ declare const _default: <T>(data: T[]) => {
60
60
  clear: () => void;
61
61
  dispose: () => void;
62
62
  dispatch: <K extends keyof Events<T_1[number]>, V>(event: K, value?: V | undefined) => void;
63
- map: <R>(fn: (this: any, value: T, i: number) => R, i?: number, n?: number) => R[];
63
+ map: <R>(fn: (this: any, value: T, i: number) => R) => R[];
64
64
  on: <K extends keyof Events<T_1[number]>>(event: K, listener: Listener<Events<T>[K]>) => void;
65
65
  once: <K extends keyof Events<T_1[number]>>(event: K, listener: Listener<Events<T>[K]>) => void;
66
66
  };
@@ -77,7 +77,7 @@ declare const _default: <T>(data: T[]) => {
77
77
  };
78
78
  some: (predicate: (value: Infer<T>, index: number, array: Infer<T>[]) => unknown, thisArg?: any) => boolean;
79
79
  forEach: (callbackfn: (value: Infer<T>, index: number, array: Infer<T>[]) => void, thisArg?: any) => void;
80
- map: (<U>(callbackfn: (value: Infer<T>, index: number, array: Infer<T>[]) => U, thisArg?: any) => U[]) & (<R>(fn: (this: any, value: T, i: number) => R, i?: number, n?: number) => R[]);
80
+ map: (<U>(callbackfn: (value: Infer<T>, index: number, array: Infer<T>[]) => U, thisArg?: any) => U[]) & (<R>(fn: (this: any, value: T, i: number) => R) => R[]);
81
81
  filter: {
82
82
  <S extends Infer<T>>(predicate: (value: Infer<T>, index: number, array: Infer<T>[]) => value is S, thisArg?: any): S[];
83
83
  (predicate: (value: Infer<T>, index: number, array: Infer<T>[]) => unknown, thisArg?: any): Infer<T>[];
@@ -101,7 +101,7 @@ declare const _default: <T>(data: T[]) => {
101
101
  clear: () => void;
102
102
  dispose: () => void;
103
103
  dispatch: <K extends keyof Events<T_1[number]>, V>(event: K, value?: V | undefined) => void;
104
- map: <R>(fn: (this: any, value: T, i: number) => R, i?: number, n?: number) => R[];
104
+ map: <R>(fn: (this: any, value: T, i: number) => R) => R[];
105
105
  on: <K extends keyof Events<T_1[number]>>(event: K, listener: Listener<Events<T>[K]>) => void;
106
106
  once: <K extends keyof Events<T_1[number]>>(event: K, listener: Listener<Events<T>[K]>) => void;
107
107
  };
@@ -109,7 +109,7 @@ declare const _default: <T>(data: T[]) => {
109
109
  clear: () => void;
110
110
  dispose: () => void;
111
111
  dispatch: <K extends keyof Events<T_1[number]>, V>(event: K, value?: V | undefined) => void;
112
- map: <R>(fn: (this: any, value: T, i: number) => R, i?: number, n?: number) => R[];
112
+ map: <R>(fn: (this: any, value: T, i: number) => R) => R[];
113
113
  on: <K extends keyof Events<T_1[number]>>(event: K, listener: Listener<Events<T>[K]>) => void;
114
114
  once: <K extends keyof Events<T_1[number]>>(event: K, listener: Listener<Events<T>[K]>) => void;
115
115
  };
@@ -37,16 +37,9 @@ function dispose(data) {
37
37
  cleanup(item);
38
38
  }
39
39
  }
40
- function map(data, proxy, fn, i, n) {
41
- if (i === undefined) {
42
- i = 0;
43
- }
44
- if (n === undefined) {
45
- n = data.length;
46
- }
47
- n = Math.min(n, data.length);
48
- let values = new Array(n - i);
49
- for (; i < n; i++) {
40
+ function map(data, proxy, fn) {
41
+ let n = data.length, values = new Array(n);
42
+ for (let i = 0; i < n; i++) {
50
43
  values[i] = fn.call(proxy, data[i], i);
51
44
  }
52
45
  return values;
@@ -170,8 +163,8 @@ export default (data) => {
170
163
  dispose(data);
171
164
  return proxy;
172
165
  },
173
- map: (fn, i, n) => {
174
- return map(data, proxy, fn, i, n);
166
+ map: (fn) => {
167
+ return map(data, proxy, fn);
175
168
  },
176
169
  on: (event, listener) => {
177
170
  on(listeners, event, listener);
@@ -3,20 +3,24 @@ import { onCleanup, root } from '../system.js';
3
3
  import array from './array.js';
4
4
  import object from './object.js';
5
5
  export default (input) => {
6
- let value;
7
- return root(() => {
6
+ let dispose = false, value = root(() => {
7
+ let response;
8
8
  if (isArray(input)) {
9
- value = array(input);
9
+ response = array(input);
10
10
  }
11
11
  else if (isObject(input)) {
12
- value = object(input);
12
+ response = object(input);
13
13
  }
14
- if (value) {
14
+ if (response) {
15
15
  if (root.disposables) {
16
- onCleanup(() => value.dispose());
16
+ dispose = true;
17
17
  }
18
- return value;
18
+ return response;
19
19
  }
20
20
  throw new Error(`@esportsplus/reactivity: 'reactive' received invalid input - ${JSON.stringify(input)}`);
21
21
  });
22
+ if (dispose) {
23
+ onCleanup(() => value.dispose());
24
+ }
25
+ return value;
22
26
  };
package/build/system.d.ts CHANGED
@@ -7,7 +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: {
10
- <T>(fn: () => T): T;
10
+ <T>(fn: (dispose?: VoidFunction) => T): T;
11
11
  disposables: number;
12
12
  };
13
13
  declare const set: <T>(signal: Signal<T>, value: T) => void;
package/build/system.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { isArray, isObject } from '@esportsplus/utilities';
2
2
  import { COMPUTED, SIGNAL, STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_NOTIFY_MASK, STATE_RECOMPUTING } from './constants.js';
3
- let depth = 0, heap = new Array(64), heap_i = 0, heap_n = 0, microtask = queueMicrotask, notified = false, observer = null, stabilizer = STABILIZER_IDLE, version = 0;
3
+ let depth = 0, heap = new Array(64), heap_i = 0, heap_n = 0, microtask = queueMicrotask, notified = false, observer = null, scope = null, stabilizer = STABILIZER_IDLE, version = 0;
4
4
  function cleanup(computed) {
5
5
  if (!computed.cleanup) {
6
6
  return;
@@ -262,6 +262,9 @@ const computed = (fn) => {
262
262
  else {
263
263
  recompute(self, false);
264
264
  root.disposables++;
265
+ if (scope) {
266
+ onCleanup(() => dispose(self));
267
+ }
265
268
  }
266
269
  return self;
267
270
  };
@@ -289,18 +292,19 @@ const isSignal = (value) => {
289
292
  return isObject(value) && SIGNAL in value;
290
293
  };
291
294
  const onCleanup = (fn) => {
292
- if (!observer) {
295
+ let parent = observer || scope;
296
+ if (!parent) {
293
297
  return fn;
294
298
  }
295
- let cleanup = observer.cleanup;
299
+ let cleanup = parent.cleanup;
296
300
  if (!cleanup) {
297
- observer.cleanup = fn;
301
+ parent.cleanup = fn;
298
302
  }
299
303
  else if (isArray(cleanup)) {
300
304
  cleanup.push(fn);
301
305
  }
302
306
  else {
303
- observer.cleanup = [cleanup, fn];
307
+ parent.cleanup = [cleanup, fn];
304
308
  }
305
309
  return fn;
306
310
  };
@@ -328,12 +332,14 @@ const read = (node) => {
328
332
  return node.value;
329
333
  };
330
334
  const root = (fn) => {
331
- let d = root.disposables, o = observer;
335
+ let d = root.disposables, o = observer, s = scope, self = null, tracking = fn.length;
332
336
  observer = null;
333
337
  root.disposables = 0;
334
- let value = fn();
338
+ scope = tracking ? (self = { cleanup: null }) : null;
339
+ let value = fn(tracking ? () => dispose(self) : undefined);
335
340
  observer = o;
336
341
  root.disposables = d;
342
+ scope = s;
337
343
  return value;
338
344
  };
339
345
  root.disposables = 0;
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.14.3",
15
+ "version": "0.16.0",
16
16
  "scripts": {
17
17
  "build": "tsc && tsc-alias",
18
18
  "-": "-"
@@ -9,7 +9,7 @@ type ReactiveArray<T extends unknown[]> = Prettify<
9
9
  clear: () => void;
10
10
  dispose: () => void;
11
11
  dispatch: <K extends keyof Events<T[number]>, V>(event: K, value?: V) => void;
12
- map: <R>(fn: (this: ReactiveArray<T>, value: T[number], i: number) => R, i?: number, n?: number) => R[];
12
+ map: <R>(fn: (this: ReactiveArray<T>, value: T[number], i: number) => R) => R[];
13
13
  on: <K extends keyof Events<T[number]>>(event: K, listener: Listener<Events<T[number]>[K]>) => void;
14
14
  once: <K extends keyof Events<T[number]>>(event: K, listener: Listener<Events<T[number]>[K]>) => void;
15
15
  }
@@ -99,23 +99,12 @@ function dispose<T>(data: T[]) {
99
99
  function map<T, R>(
100
100
  data: T[],
101
101
  proxy: ReactiveArray<typeof data>,
102
- fn: (this: ReactiveArray<typeof data>, value: T, i: number) => R,
103
- i?: number,
104
- n?: number
102
+ fn: (this: ReactiveArray<typeof data>, value: T, i: number) => R
105
103
  ) {
106
- if (i === undefined) {
107
- i = 0;
108
- }
109
-
110
- if (n === undefined) {
111
- n = data.length;
112
- }
113
-
114
- n = Math.min(n, data.length);
115
-
116
- let values: R[] = new Array(n - i);
104
+ let n = data.length,
105
+ values: R[] = new Array(n);
117
106
 
118
- for (; i < n; i++) {
107
+ for (let i = 0; i < n; i++) {
119
108
  values[i] = fn.call(proxy, data[i], i);
120
109
  }
121
110
 
@@ -270,12 +259,8 @@ export default <T>(data: T[]) => {
270
259
  dispose(data);
271
260
  return proxy;
272
261
  },
273
- map: <R>(
274
- fn: (this: ReactiveArray<typeof data>, value: T, i: number) => R,
275
- i?: number,
276
- n?: number
277
- ) => {
278
- return map(data, proxy, fn, i, n);
262
+ map: <R>(fn: (this: ReactiveArray<typeof data>, value: T, i: number) => R) => {
263
+ return map(data, proxy, fn);
279
264
  },
280
265
  on: <K extends keyof Events<T>>(event: K, listener: Listener<Events<T>[K]>) => {
281
266
  on(listeners, event, listener);
@@ -20,24 +20,31 @@ type Input<T> =
20
20
 
21
21
 
22
22
  export default <T>(input: Input<T>): API<T> => {
23
- let value: API<T> | undefined;
24
-
25
- return root(() => {
26
- if (isArray(input)) {
27
- value = array(input) as API<T>;
28
- }
29
- else if (isObject(input)) {
30
- value = object(input) as API<T>;
31
- }
32
-
33
- if (value) {
34
- if (root.disposables) {
35
- onCleanup(() => value!.dispose());
23
+ let dispose = false,
24
+ value = root(() => {
25
+ let response: API<T> | undefined;
26
+
27
+ if (isArray(input)) {
28
+ response = array(input) as API<T>;
29
+ }
30
+ else if (isObject(input)) {
31
+ response = object(input) as API<T>;
32
+ }
33
+
34
+ if (response) {
35
+ if (root.disposables) {
36
+ dispose = true;
37
+ }
38
+
39
+ return response;
36
40
  }
37
41
 
38
- return value;
39
- }
42
+ throw new Error(`@esportsplus/reactivity: 'reactive' received invalid input - ${JSON.stringify(input)}`);
43
+ });
44
+
45
+ if (dispose) {
46
+ onCleanup(() => value.dispose());
47
+ }
40
48
 
41
- throw new Error(`@esportsplus/reactivity: 'reactive' received invalid input - ${JSON.stringify(input)}`);
42
- });
49
+ return value;
43
50
  };
package/src/system.ts CHANGED
@@ -14,6 +14,7 @@ let depth = 0,
14
14
  microtask = queueMicrotask,
15
15
  notified = false,
16
16
  observer: Computed<unknown> | null = null,
17
+ scope: Computed<unknown> | null = null,
17
18
  stabilizer = STABILIZER_IDLE,
18
19
  version = 0;
19
20
 
@@ -370,6 +371,10 @@ const computed = <T>(fn: Computed<T>['fn']): Computed<T> => {
370
371
  else {
371
372
  recompute(self, false);
372
373
  root.disposables++;
374
+
375
+ if (scope) {
376
+ onCleanup(() => dispose(self));
377
+ }
373
378
  }
374
379
 
375
380
  return self;
@@ -408,20 +413,22 @@ const isSignal = (value: unknown): value is Signal<unknown> => {
408
413
  };
409
414
 
410
415
  const onCleanup = (fn: VoidFunction): typeof fn => {
411
- if (!observer) {
416
+ let parent = observer || scope;
417
+
418
+ if (!parent) {
412
419
  return fn;
413
420
  }
414
421
 
415
- let cleanup = observer.cleanup;
422
+ let cleanup = parent.cleanup;
416
423
 
417
424
  if (!cleanup) {
418
- observer.cleanup = fn;
425
+ parent.cleanup = fn;
419
426
  }
420
427
  else if (isArray(cleanup)) {
421
428
  cleanup.push(fn);
422
429
  }
423
430
  else {
424
- observer.cleanup = [cleanup, fn];
431
+ parent.cleanup = [cleanup, fn];
425
432
  }
426
433
 
427
434
  return fn;
@@ -457,17 +464,22 @@ const read = <T>(node: Signal<T> | Computed<T>): T => {
457
464
  return node.value;
458
465
  };
459
466
 
460
- const root = <T>(fn: () => T) => {
467
+ const root = <T>(fn: (dispose?: VoidFunction) => T) => {
461
468
  let d = root.disposables,
462
- o = observer;
469
+ o = observer,
470
+ s = scope,
471
+ self: Computed<unknown> | null = null,
472
+ tracking = fn.length;
463
473
 
464
474
  observer = null;
465
475
  root.disposables = 0;
476
+ scope = tracking ? (self = { cleanup: null } as Computed<unknown>) : null;
466
477
 
467
- let value = fn();
478
+ let value = fn( tracking ? () => dispose(self!) : undefined);
468
479
 
469
480
  observer = o;
470
481
  root.disposables = d;
482
+ scope = s;
471
483
 
472
484
  return value;
473
485
  };