@esportsplus/reactivity 0.5.0 → 0.6.1

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,10 +1,13 @@
1
- import { Reactive } from '../types.js';
2
- type Guard<T> = T extends {
1
+ import array from './array.js';
2
+ import object from './object.js';
3
+ import promise from './promise.js';
4
+ type API<T> = T extends (...args: infer A) => Promise<infer R> ? ReturnType<typeof promise<A, Promise<R>>> : T extends Record<PropertyKey, unknown> ? ReturnType<typeof object<T>> : T extends unknown[] ? ReturnType<typeof array<T>> : never;
5
+ type Guard<T> = T extends (...args: unknown[]) => Promise<unknown> ? T : T extends {
3
6
  dispose: any;
4
7
  } | {
5
8
  signals: any;
6
9
  } ? {
7
10
  never: '[ dispose, signals ] are reserved keys';
8
11
  } : T extends Record<PropertyKey, unknown> | unknown[] ? T : never;
9
- declare const _default: <T>(data: Guard<T>) => Reactive<T>;
12
+ declare const _default: <T>(data: Guard<T>) => API<T>;
10
13
  export default _default;
@@ -1,16 +1,16 @@
1
- import { isArray, isObject } from '@esportsplus/utilities';
2
- import { default as array } from './array.js';
3
- import { default as object } from './object.js';
1
+ import { isArray, isObject, isPromise } from '@esportsplus/utilities';
2
+ import array from './array.js';
3
+ import object from './object.js';
4
+ import promise from './promise.js';
4
5
  export default (data) => {
5
- let value;
6
6
  if (isArray(data)) {
7
- value = array(data);
7
+ return array(data);
8
8
  }
9
9
  else if (isObject(data)) {
10
- value = object(data);
10
+ return object(data);
11
11
  }
12
- else {
13
- throw new Error(`@esportsplus/reactivity: 'reactive' received invalid input - ${JSON.stringify(data)}`);
12
+ else if (isPromise(data)) {
13
+ return promise(data);
14
14
  }
15
- return value;
15
+ throw new Error(`@esportsplus/reactivity: 'reactive' received invalid input - ${JSON.stringify(data)}`);
16
16
  };
@@ -5,7 +5,7 @@ type API<T extends Record<PropertyKey, unknown>> = Prettify<{
5
5
  [K in keyof T]: Infer<T[K]>;
6
6
  }> & ReactiveObject<T>;
7
7
  declare class ReactiveObject<T extends Record<PropertyKey, unknown>> extends Disposable {
8
- private signals;
8
+ private disposable;
9
9
  constructor(data: T);
10
10
  dispose(): void;
11
11
  }
@@ -1,59 +1,69 @@
1
- import { defineProperty, isArray, isFunction, isInstanceOf, isObject } from '@esportsplus/utilities';
1
+ import { defineProperty, isArray, isAsyncFunction, isFunction, isInstanceOf, isObject } from '@esportsplus/utilities';
2
2
  import array from './array.js';
3
- import { computed, dispose, isComputed, read, signal } from '../signal.js';
3
+ import { computed, dispose, read, signal } from '../signal.js';
4
4
  import { Disposable } from './disposable.js';
5
+ import promise from './promise.js';
5
6
  let { set } = signal;
6
7
  class ReactiveObject extends Disposable {
7
- signals = {};
8
+ disposable = {};
8
9
  constructor(data) {
9
10
  super();
10
- let signals = this.signals, triggers = {};
11
+ let disposable = this.disposable, triggers = {};
11
12
  for (let key in data) {
12
13
  let value = data[key];
13
14
  if (isArray(value)) {
14
- let s = signals[key] = array(value), t = triggers[key] = signal(false);
15
+ let a = disposable[key] = array(value), t = triggers[key] = signal(false);
15
16
  defineProperty(this, key, {
16
17
  enumerable: true,
17
18
  get() {
18
19
  read(t);
19
- return s;
20
+ return a;
20
21
  },
21
22
  set(v) {
22
23
  set(t, !!t.value);
23
- s = signals[key] = array(v);
24
+ a = disposable[key] = array(v);
25
+ }
26
+ });
27
+ }
28
+ if (isAsyncFunction(value)) {
29
+ let p = promise(value);
30
+ defineProperty(this, key, {
31
+ enumerable: true,
32
+ get() {
33
+ return p;
24
34
  }
25
35
  });
26
36
  }
27
37
  else if (isFunction(value)) {
28
- let s = signals[key] = computed(value);
38
+ let c = disposable[key] = computed(value);
29
39
  defineProperty(this, key, {
30
40
  enumerable: true,
31
41
  get() {
32
- return read(s);
42
+ return read(c);
33
43
  }
34
44
  });
35
45
  }
36
46
  else if (isObject(value)) {
37
- let s = signals[key] = new ReactiveObject(value), t = triggers[key] = signal(false);
47
+ let o = disposable[key] = new ReactiveObject(value), t = triggers[key] = signal(false);
38
48
  defineProperty(this, key, {
39
49
  enumerable: true,
40
50
  get() {
41
51
  read(t);
42
- return s;
52
+ return o;
43
53
  },
44
54
  set(v) {
45
55
  set(t, !!t.value);
46
- s = signals[key] = new ReactiveObject(v);
56
+ o = disposable[key] = new ReactiveObject(v);
47
57
  }
48
58
  });
49
59
  }
50
60
  else {
51
- let s = signals[key] = signal(value);
61
+ let s = signal(value);
52
62
  defineProperty(this, key, {
53
63
  enumerable: true,
54
64
  get() {
55
65
  if (s === undefined) {
56
- s = signals[key] = signal(value);
66
+ s = signal(value);
57
67
  }
58
68
  return read(s);
59
69
  },
@@ -65,16 +75,16 @@ class ReactiveObject extends Disposable {
65
75
  }
66
76
  }
67
77
  dispose() {
68
- for (let key in this.signals) {
69
- let value = this.signals[key];
78
+ for (let key in this.disposable) {
79
+ let value = this.disposable[key];
70
80
  if (isInstanceOf(value, Disposable)) {
71
81
  value.dispose();
72
82
  }
73
- else if (isComputed(value)) {
83
+ else {
74
84
  dispose(value);
75
85
  }
76
86
  }
77
- this.signals = {};
87
+ this.disposable = {};
78
88
  }
79
89
  }
80
90
  export default function object(input) {
@@ -0,0 +1,13 @@
1
+ import CustomFunction from '@esportsplus/custom-function';
2
+ declare class ReactivePromise<A extends unknown[], R extends Promise<unknown>> extends CustomFunction {
3
+ private arguments;
4
+ private okay;
5
+ private response;
6
+ stop: boolean | null;
7
+ constructor(fn: (...args: A) => R);
8
+ get data(): Awaited<R> | null;
9
+ get input(): A | null;
10
+ get ok(): boolean | null;
11
+ }
12
+ declare const _default: <A extends unknown[], R extends Promise<unknown>>(fn: (...args: A) => R) => ReactivePromise<A, R>;
13
+ export default _default;
@@ -0,0 +1,48 @@
1
+ import CustomFunction from '@esportsplus/custom-function';
2
+ import { read, root, signal } from '../signal.js';
3
+ let { set } = signal;
4
+ class ReactivePromise extends CustomFunction {
5
+ arguments;
6
+ okay;
7
+ response;
8
+ stop = null;
9
+ constructor(fn) {
10
+ super((...args) => {
11
+ this.stop = null;
12
+ set(this.arguments, args);
13
+ set(this.okay, null);
14
+ return root(() => {
15
+ return fn(...args)
16
+ .then((value) => {
17
+ if (this.stop === true) {
18
+ return;
19
+ }
20
+ set(this.response, value);
21
+ set(this.okay, true);
22
+ })
23
+ .catch(() => {
24
+ if (this.stop === true) {
25
+ return;
26
+ }
27
+ set(this.response, null);
28
+ set(this.okay, false);
29
+ });
30
+ });
31
+ });
32
+ this.response = signal(null);
33
+ this.arguments = signal(null);
34
+ this.okay = signal(null);
35
+ }
36
+ get data() {
37
+ return read(this.response);
38
+ }
39
+ get input() {
40
+ return read(this.arguments);
41
+ }
42
+ get ok() {
43
+ return read(this.okay);
44
+ }
45
+ }
46
+ export default (fn) => {
47
+ return new ReactivePromise(fn);
48
+ };
package/build/signal.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Computed, Signal } from './types.js';
2
2
  declare const computed: <T>(fn: Computed<T>["fn"]) => Computed<T>;
3
- declare const dispose: (el: Computed<unknown>) => void;
3
+ declare const dispose: <T>(el: Computed<T>) => void;
4
4
  declare const isComputed: (value: unknown) => value is Computed<unknown>;
5
5
  declare const isReactive: (value: unknown) => value is Computed<unknown> | Signal<unknown>;
6
6
  declare const isSignal: (value: unknown) => value is Signal<unknown>;
@@ -9,7 +9,7 @@ declare const read: <T>(el: Signal<T> | Computed<T>) => T;
9
9
  declare const root: <T>(fn: () => T) => T;
10
10
  declare const signal: {
11
11
  <T>(value: T): Signal<T>;
12
- set(el: Signal<unknown>, v: unknown): void;
12
+ set<T>(el: Signal<T>, v: T): void;
13
13
  };
14
14
  declare const stabilize: () => void;
15
15
  export { computed, dispose, isComputed, isReactive, isSignal, oncleanup, read, root, signal, stabilize };
package/build/signal.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { isArray, isObject } from '@esportsplus/utilities';
2
2
  import { REACTIVE, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RECOMPUTING } from './constants.js';
3
- let context = null, dirtyHeap = new Array(2000), maxDirty = 0, markedHeap = false, minDirty = 0;
3
+ let dirtyHeap = new Array(2000), maxDirty = 0, markedHeap = false, minDirty = 0, observer = null;
4
4
  function cleanup(node) {
5
5
  if (!node.cleanup) {
6
6
  return;
@@ -125,8 +125,8 @@ function recompute(el, del) {
125
125
  el.prevHeap = el;
126
126
  }
127
127
  cleanup(el);
128
- let oldcontext = context, ok = true, value;
129
- context = el;
128
+ let o = observer, ok = true, value;
129
+ observer = el;
130
130
  el.depsTail = null;
131
131
  el.state = STATE_RECOMPUTING;
132
132
  try {
@@ -135,7 +135,7 @@ function recompute(el, del) {
135
135
  catch (e) {
136
136
  ok = false;
137
137
  }
138
- context = oldcontext;
138
+ observer = o;
139
139
  el.state = STATE_NONE;
140
140
  let depsTail = el.depsTail, toRemove = depsTail !== null ? depsTail.nextDep : el.deps;
141
141
  if (toRemove !== null) {
@@ -212,16 +212,16 @@ const computed = (fn) => {
212
212
  value: undefined,
213
213
  };
214
214
  self.prevHeap = self;
215
- if (context) {
216
- if (context.depsTail === null) {
217
- self.height = context.height;
215
+ if (observer) {
216
+ if (observer.depsTail === null) {
217
+ self.height = observer.height;
218
218
  recompute(self, false);
219
219
  }
220
220
  else {
221
- self.height = context.height + 1;
221
+ self.height = observer.height + 1;
222
222
  insertIntoHeap(self);
223
223
  }
224
- link(self, context);
224
+ link(self, observer);
225
225
  }
226
226
  else {
227
227
  recompute(self, false);
@@ -247,10 +247,10 @@ const isSignal = (value) => {
247
247
  return isObject(value) && REACTIVE in value && 'fn' in value === false;
248
248
  };
249
249
  const oncleanup = (fn) => {
250
- if (!context) {
250
+ if (!observer) {
251
251
  return fn;
252
252
  }
253
- let node = context;
253
+ let node = observer;
254
254
  if (!node.cleanup) {
255
255
  node.cleanup = fn;
256
256
  }
@@ -263,12 +263,12 @@ const oncleanup = (fn) => {
263
263
  return fn;
264
264
  };
265
265
  const read = (el) => {
266
- if (context) {
267
- link(el, context);
266
+ if (observer) {
267
+ link(el, observer);
268
268
  if ('fn' in el) {
269
269
  let height = el.height;
270
- if (height >= context.height) {
271
- context.height = height + 1;
270
+ if (height >= observer.height) {
271
+ observer.height = height + 1;
272
272
  }
273
273
  if (height >= minDirty ||
274
274
  el.state & (STATE_DIRTY | STATE_CHECK)) {
@@ -280,10 +280,10 @@ const read = (el) => {
280
280
  return el.value;
281
281
  };
282
282
  const root = (fn) => {
283
- let c = context;
284
- context = null;
283
+ let o = observer;
284
+ observer = null;
285
285
  let value = fn();
286
- context = c;
286
+ observer = o;
287
287
  return value;
288
288
  };
289
289
  const signal = (value) => {
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.5.0",
15
+ "version": "0.6.1",
16
16
  "scripts": {
17
17
  "build": "tsc && tsc-alias",
18
18
  "-": "-"
@@ -1,29 +1,38 @@
1
- import { isArray, isObject } from '@esportsplus/utilities';
2
- import { Reactive } from '~/types';
3
- import { default as array } from './array';
4
- import { default as object } from './object';
1
+ import { isArray, isObject, isPromise } from '@esportsplus/utilities';
2
+ import array from './array';
3
+ import object from './object';
4
+ import promise from './promise';
5
5
 
6
6
 
7
- type Guard<T> =
8
- T extends { dispose: any } | { signals: any }
9
- ? { never: '[ dispose, signals ] are reserved keys' }
10
- : T extends Record<PropertyKey, unknown> | unknown[]
11
- ? T
12
- : never;
7
+ type API<T> =
8
+ T extends (...args: infer A) => Promise<infer R>
9
+ ? ReturnType<typeof promise<A, Promise<R>>>
10
+ : T extends Record<PropertyKey, unknown>
11
+ ? ReturnType<typeof object<T>>
12
+ : T extends unknown[]
13
+ ? ReturnType<typeof array<T>>
14
+ : never;
13
15
 
16
+ type Guard<T> =
17
+ T extends (...args: unknown[]) => Promise<unknown>
18
+ ? T
19
+ : T extends { dispose: any } | { signals: any }
20
+ ? { never: '[ dispose, signals ] are reserved keys' }
21
+ : T extends Record<PropertyKey, unknown> | unknown[]
22
+ ? T
23
+ : never;
14
24
 
15
- export default <T>(data: Guard<T>) => {
16
- let value;
17
25
 
26
+ export default <T>(data: Guard<T>): API<T> => {
18
27
  if (isArray(data)) {
19
- value = array(data);
28
+ return array(data) as API<T>;
20
29
  }
21
30
  else if (isObject(data)) {
22
- value = object(data as { [K in keyof T]: T[K] });
31
+ return object(data) as API<T>;
23
32
  }
24
- else {
25
- throw new Error(`@esportsplus/reactivity: 'reactive' received invalid input - ${JSON.stringify(data)}`);
33
+ else if (isPromise(data)) {
34
+ return promise(data) as API<T>;
26
35
  }
27
36
 
28
- return value as Reactive<T>;
37
+ throw new Error(`@esportsplus/reactivity: 'reactive' received invalid input - ${JSON.stringify(data)}`);
29
38
  };
@@ -1,8 +1,9 @@
1
- import { defineProperty, isArray, isFunction, isInstanceOf, isObject, Prettify } from '@esportsplus/utilities';
1
+ import { defineProperty, isArray, isAsyncFunction, isFunction, isInstanceOf, isObject, Prettify } from '@esportsplus/utilities';
2
2
  import array, { ReactiveArray } from './array';
3
- import { computed, dispose, isComputed, read, signal } from '~/signal';
3
+ import { computed, dispose, read, signal } from '~/signal';
4
4
  import { Computed, Infer, Signal } from '~/types';
5
5
  import { Disposable } from './disposable';
6
+ import promise from './promise';
6
7
 
7
8
 
8
9
  type API<T extends Record<PropertyKey, unknown>> = Prettify<{ [K in keyof T]: Infer<T[K]> }> & ReactiveObject<T>;
@@ -12,71 +13,81 @@ let { set } = signal;
12
13
 
13
14
 
14
15
  class ReactiveObject<T extends Record<PropertyKey, unknown>> extends Disposable {
15
- private signals: Record<
16
+ private disposable: Record<
16
17
  PropertyKey,
17
- Computed<any> | ReactiveArray<any> | ReactiveObject<any> | Signal<any>
18
+ Computed<any> | ReactiveArray<any> | ReactiveObject<any>
18
19
  > = {};
19
20
 
20
21
 
21
22
  constructor(data: T) {
22
23
  super();
23
24
 
24
- let signals = this.signals,
25
+ let disposable = this.disposable,
25
26
  triggers: Record<string, Signal<boolean>> = {};
26
27
 
27
28
  for (let key in data) {
28
29
  let value = data[key];
29
30
 
30
31
  if (isArray(value)) {
31
- let s = signals[key] = array(value),
32
+ let a = disposable[key] = array(value),
32
33
  t = triggers[key] = signal(false);
33
34
 
34
35
  defineProperty(this, key, {
35
36
  enumerable: true,
36
37
  get() {
37
38
  read(t);
38
- return s;
39
+ return a;
39
40
  },
40
41
  set(v: typeof value) {
41
42
  set(t, !!t.value);
42
- s = signals[key] = array(v);
43
+ a = disposable[key] = array(v);
44
+ }
45
+ });
46
+ }
47
+ if (isAsyncFunction(value)) {
48
+ let p = promise(value);
49
+
50
+ defineProperty(this, key, {
51
+ enumerable: true,
52
+ get() {
53
+ return p;
43
54
  }
44
55
  });
45
56
  }
46
57
  else if (isFunction(value)) {
47
- let s = signals[key] = computed(value as Computed<T>['fn']);
58
+ let c = disposable[key] = computed(value as Computed<T>['fn']);
48
59
 
49
60
  defineProperty(this, key, {
50
61
  enumerable: true,
51
62
  get() {
52
- return read(s as Computed<T>);
63
+ return read(c as Computed<T>);
53
64
  }
54
65
  });
55
66
  }
56
67
  else if (isObject(value)) {
57
- let s = signals[key] = new ReactiveObject(value),
68
+ let o = disposable[key] = new ReactiveObject(value),
58
69
  t = triggers[key] = signal(false);
59
70
 
60
71
  defineProperty(this, key, {
61
72
  enumerable: true,
62
73
  get() {
63
74
  read(t);
64
- return s;
75
+ return o;
65
76
  },
66
77
  set(v: typeof value) {
67
78
  set(t, !!t.value);
68
- s = signals[key] = new ReactiveObject(v);
79
+ o = disposable[key] = new ReactiveObject(v);
69
80
  }
70
81
  });
71
82
  }
72
83
  else {
73
- let s = signals[key] = signal(value);
84
+ let s = signal(value);
74
85
 
75
86
  defineProperty(this, key, {
76
87
  enumerable: true,
77
88
  get() {
78
89
  if (s === undefined) {
79
- s = signals[key] = signal(value);
90
+ s = signal(value);
80
91
  }
81
92
 
82
93
  return read(s as Signal<typeof value>);
@@ -91,18 +102,18 @@ class ReactiveObject<T extends Record<PropertyKey, unknown>> extends Disposable
91
102
 
92
103
 
93
104
  dispose() {
94
- for (let key in this.signals) {
95
- let value = this.signals[key];
105
+ for (let key in this.disposable) {
106
+ let value = this.disposable[key];
96
107
 
97
108
  if (isInstanceOf(value, Disposable)) {
98
109
  value.dispose();
99
110
  }
100
- else if (isComputed(value)) {
111
+ else {
101
112
  dispose(value);
102
113
  }
103
114
  }
104
115
 
105
- this.signals = {};
116
+ this.disposable = {};
106
117
  }
107
118
  }
108
119
 
@@ -0,0 +1,67 @@
1
+ import CustomFunction from '@esportsplus/custom-function';
2
+ import { read, root, signal } from '~/signal';
3
+ import { Signal } from '~/types';
4
+
5
+
6
+ let { set } = signal;
7
+
8
+
9
+ class ReactivePromise<A extends unknown[], R extends Promise<unknown>> extends CustomFunction {
10
+ private arguments: Signal<A | null>;
11
+ private okay: Signal<boolean | null>;
12
+ private response: Signal<Awaited<R> | null>;
13
+
14
+ stop: boolean | null = null;
15
+
16
+
17
+ constructor(fn: (...args: A) => R) {
18
+ super((...args: A) => {
19
+ this.stop = null;
20
+
21
+ set(this.arguments, args);
22
+ set(this.okay, null);
23
+
24
+ return root(() => {
25
+ return fn(...args)
26
+ .then((value) => {
27
+ if (this.stop === true) {
28
+ return;
29
+ }
30
+
31
+ set(this.response, value as Awaited<R>);
32
+ set(this.okay, true);
33
+ })
34
+ .catch(() => {
35
+ if (this.stop === true) {
36
+ return;
37
+ }
38
+
39
+ set(this.response, null);
40
+ set(this.okay, false);
41
+ });
42
+ });
43
+ });
44
+
45
+ this.response = signal(null);
46
+ this.arguments = signal(null);
47
+ this.okay = signal(null);
48
+ }
49
+
50
+
51
+ get data() {
52
+ return read(this.response);
53
+ }
54
+
55
+ get input() {
56
+ return read(this.arguments);
57
+ }
58
+
59
+ get ok() {
60
+ return read(this.okay);
61
+ }
62
+ }
63
+
64
+
65
+ export default <A extends unknown[], R extends Promise<unknown>>(fn: (...args: A) => R) => {
66
+ return new ReactivePromise(fn);
67
+ };
package/src/signal.ts CHANGED
@@ -3,14 +3,14 @@ import { REACTIVE, STATE_CHECK, STATE_DIRTY, STATE_IN_HEAP, STATE_NONE, STATE_RE
3
3
  import { Computed, Link, Signal, } from './types';
4
4
 
5
5
 
6
- let context: Computed<unknown> | null = null,
7
- dirtyHeap: (Computed<unknown> | undefined)[] = new Array(2000),
6
+ let dirtyHeap: (Computed<unknown> | undefined)[] = new Array(2000),
8
7
  maxDirty = 0,
9
8
  markedHeap = false,
10
- minDirty = 0;
9
+ minDirty = 0,
10
+ observer: Computed<unknown> | null = null;
11
11
 
12
12
 
13
- function cleanup(node: Computed<unknown>): void {
13
+ function cleanup<T>(node: Computed<T>): void {
14
14
  if (!node.cleanup) {
15
15
  return;
16
16
  }
@@ -27,7 +27,7 @@ function cleanup(node: Computed<unknown>): void {
27
27
  node.cleanup = null;
28
28
  }
29
29
 
30
- function deleteFromHeap(n: Computed<unknown>) {
30
+ function deleteFromHeap<T>(n: Computed<T>) {
31
31
  let state = n.state;
32
32
 
33
33
  if (!(state & STATE_IN_HEAP)) {
@@ -60,7 +60,7 @@ function deleteFromHeap(n: Computed<unknown>) {
60
60
  n.prevHeap = n;
61
61
  }
62
62
 
63
- function insertIntoHeap(n: Computed<unknown>) {
63
+ function insertIntoHeap<T>(n: Computed<T>) {
64
64
  let state = n.state;
65
65
 
66
66
  if (state & STATE_IN_HEAP) {
@@ -94,7 +94,7 @@ function insertIntoHeap(n: Computed<unknown>) {
94
94
  }
95
95
 
96
96
  // https://github.com/stackblitz/alien-signals/blob/v2.0.3/src/system.ts#L52
97
- function link(dep: Signal<unknown> | Computed<unknown>, sub: Computed<unknown>) {
97
+ function link<T>(dep: Signal<T> | Computed<T>, sub: Computed<T>) {
98
98
  let prevDep = sub.depsTail;
99
99
 
100
100
  if (prevDep !== null && prevDep.dep === dep) {
@@ -152,7 +152,7 @@ function markHeap() {
152
152
  }
153
153
  }
154
154
 
155
- function markNode(el: Computed<unknown>, newState = STATE_DIRTY) {
155
+ function markNode<T>(el: Computed<T>, newState = STATE_DIRTY) {
156
156
  let state = el.state;
157
157
 
158
158
  if ((state & (STATE_CHECK | STATE_DIRTY)) >= newState) {
@@ -166,7 +166,7 @@ function markNode(el: Computed<unknown>, newState = STATE_DIRTY) {
166
166
  }
167
167
  }
168
168
 
169
- function recompute(el: Computed<unknown>, del: boolean) {
169
+ function recompute<T>(el: Computed<T>, del: boolean) {
170
170
  if (del) {
171
171
  deleteFromHeap(el);
172
172
  }
@@ -177,11 +177,11 @@ function recompute(el: Computed<unknown>, del: boolean) {
177
177
 
178
178
  cleanup(el);
179
179
 
180
- let oldcontext = context,
180
+ let o = observer,
181
181
  ok = true,
182
182
  value;
183
183
 
184
- context = el;
184
+ observer = el;
185
185
  el.depsTail = null;
186
186
  el.state = STATE_RECOMPUTING;
187
187
 
@@ -192,7 +192,7 @@ function recompute(el: Computed<unknown>, del: boolean) {
192
192
  ok = false;
193
193
  }
194
194
 
195
- context = oldcontext;
195
+ observer = o;
196
196
  el.state = STATE_NONE;
197
197
 
198
198
  let depsTail = el.depsTail as Link | null,
@@ -213,7 +213,7 @@ function recompute(el: Computed<unknown>, del: boolean) {
213
213
  }
214
214
 
215
215
  if (ok && value !== el.value) {
216
- el.value = value;
216
+ el.value = value as T;
217
217
 
218
218
  for (let s = el.subs; s !== null; s = s.nextSub) {
219
219
  let o = s.sub,
@@ -256,7 +256,7 @@ function unlink(link: Link): Link | null {
256
256
  return nextDep;
257
257
  }
258
258
 
259
- function update(el: Computed<unknown>): void {
259
+ function update<T>(el: Computed<T>): void {
260
260
  if (el.state & STATE_CHECK) {
261
261
  for (let d = el.deps; d; d = d.nextDep) {
262
262
  let dep = d.dep;
@@ -297,17 +297,17 @@ const computed = <T>(fn: Computed<T>['fn']): Computed<T> => {
297
297
 
298
298
  self.prevHeap = self;
299
299
 
300
- if (context) {
301
- if (context.depsTail === null) {
302
- self.height = context.height;
300
+ if (observer) {
301
+ if (observer.depsTail === null) {
302
+ self.height = observer.height;
303
303
  recompute(self, false);
304
304
  }
305
305
  else {
306
- self.height = context.height + 1;
306
+ self.height = observer.height + 1;
307
307
  insertIntoHeap(self);
308
308
  }
309
309
 
310
- link(self, context);
310
+ link(self, observer);
311
311
  }
312
312
  else {
313
313
  recompute(self, false);
@@ -316,7 +316,7 @@ const computed = <T>(fn: Computed<T>['fn']): Computed<T> => {
316
316
  return self;
317
317
  };
318
318
 
319
- const dispose = (el: Computed<unknown>) => {
319
+ const dispose = <T>(el: Computed<T>) => {
320
320
  deleteFromHeap(el);
321
321
 
322
322
  let dep = el.deps;
@@ -343,11 +343,11 @@ const isSignal = (value: unknown): value is Signal<unknown> => {
343
343
  };
344
344
 
345
345
  const oncleanup = (fn: VoidFunction): typeof fn => {
346
- if (!context) {
346
+ if (!observer) {
347
347
  return fn;
348
348
  }
349
349
 
350
- let node = context;
350
+ let node = observer;
351
351
 
352
352
  if (!node.cleanup) {
353
353
  node.cleanup = fn;
@@ -363,14 +363,14 @@ const oncleanup = (fn: VoidFunction): typeof fn => {
363
363
  };
364
364
 
365
365
  const read = <T>(el: Signal<T> | Computed<T>): T => {
366
- if (context) {
367
- link(el, context);
366
+ if (observer) {
367
+ link(el, observer);
368
368
 
369
369
  if ('fn' in el) {
370
370
  let height = el.height;
371
371
 
372
- if (height >= context.height) {
373
- context.height = height + 1;
372
+ if (height >= observer.height) {
373
+ observer.height = height + 1;
374
374
  }
375
375
 
376
376
  if (
@@ -387,13 +387,13 @@ const read = <T>(el: Signal<T> | Computed<T>): T => {
387
387
  };
388
388
 
389
389
  const root = <T>(fn: () => T) => {
390
- let c = context;
390
+ let o = observer;
391
391
 
392
- context = null;
392
+ observer = null;
393
393
 
394
394
  let value = fn();
395
395
 
396
- context = c;
396
+ observer = o;
397
397
 
398
398
  return value;
399
399
  };
@@ -407,7 +407,7 @@ const signal = <T>(value: T): Signal<T> => {
407
407
  };
408
408
  };
409
409
 
410
- signal.set = (el: Signal<unknown>, v: unknown) => {
410
+ signal.set = <T>(el: Signal<T>, v: T) => {
411
411
  if (el.value === v) {
412
412
  return;
413
413
  }