@esportsplus/reactivity 0.33.0 → 0.36.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.
- package/README.md +9 -7
- package/bench/reactive/array.bench.ts +17 -17
- package/build/compiler/array.d.ts +2 -2
- package/build/compiler/array.js +12 -54
- package/build/compiler/constants.d.ts +4 -4
- package/build/compiler/constants.js +20 -4
- package/build/compiler/index.js +25 -38
- package/build/compiler/object.d.ts +2 -2
- package/build/compiler/object.js +10 -21
- package/build/compiler/plugins/vite.d.ts +4 -2
- package/build/compiler/primitives.d.ts +6 -2
- package/build/compiler/primitives.js +35 -42
- package/build/compiler/types.d.ts +3 -1
- package/build/constants.d.ts +2 -2
- package/build/constants.js +2 -2
- package/build/reactive/array.d.ts +1 -1
- package/build/reactive/array.js +26 -15
- package/build/reactive/index.js +5 -14
- package/build/reactive/object.js +1 -1
- package/build/system.d.ts +10 -13
- package/build/system.js +105 -83
- package/build/types.d.ts +2 -7
- package/package.json +5 -5
- package/pnpm-workspace.yaml +3 -0
- package/src/compiler/array.ts +14 -64
- package/src/compiler/constants.ts +21 -5
- package/src/compiler/index.ts +39 -70
- package/src/compiler/object.ts +12 -29
- package/src/compiler/primitives.ts +55 -53
- package/src/compiler/types.ts +4 -1
- package/src/constants.ts +4 -4
- package/src/reactive/array.ts +33 -17
- package/src/reactive/index.ts +5 -17
- package/src/reactive/object.ts +1 -1
- package/src/system.ts +138 -101
- package/src/types.ts +2 -9
- package/test/async-computed.test.ts +2 -2
- package/test/compiler/compiler.test.ts +40 -23
- package/test/effects.test.ts +37 -1
- package/test/lib/uncaught.ts +26 -0
- package/test/reactive/array.test.ts +169 -99
- package/test/reactive/nested.test.ts +14 -14
- package/test/reactive/objects.test.ts +1 -1
- package/test/reactive/reactive.test.ts +49 -0
- package/test/system.test.ts +130 -22
|
@@ -1,22 +1,5 @@
|
|
|
1
1
|
import { ts } from '@esportsplus/typescript';
|
|
2
|
-
import { NAMESPACE, TYPES } from './constants.js';
|
|
3
|
-
const COMPOUND_OPERATORS = new Map([
|
|
4
|
-
[ts.SyntaxKind.AmpersandAmpersandEqualsToken, '&&'],
|
|
5
|
-
[ts.SyntaxKind.AmpersandEqualsToken, '&'],
|
|
6
|
-
[ts.SyntaxKind.AsteriskAsteriskEqualsToken, '**'],
|
|
7
|
-
[ts.SyntaxKind.AsteriskEqualsToken, '*'],
|
|
8
|
-
[ts.SyntaxKind.BarBarEqualsToken, '||'],
|
|
9
|
-
[ts.SyntaxKind.BarEqualsToken, '|'],
|
|
10
|
-
[ts.SyntaxKind.CaretEqualsToken, '^'],
|
|
11
|
-
[ts.SyntaxKind.GreaterThanGreaterThanEqualsToken, '>>'],
|
|
12
|
-
[ts.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken, '>>>'],
|
|
13
|
-
[ts.SyntaxKind.LessThanLessThanEqualsToken, '<<'],
|
|
14
|
-
[ts.SyntaxKind.MinusEqualsToken, '-'],
|
|
15
|
-
[ts.SyntaxKind.PercentEqualsToken, '%'],
|
|
16
|
-
[ts.SyntaxKind.PlusEqualsToken, '+'],
|
|
17
|
-
[ts.SyntaxKind.QuestionQuestionEqualsToken, '??'],
|
|
18
|
-
[ts.SyntaxKind.SlashEqualsToken, '/']
|
|
19
|
-
]);
|
|
2
|
+
import { COMPOUND_OPERATORS, NAMESPACE, TYPES } from './constants.js';
|
|
20
3
|
function inScope(reference, binding) {
|
|
21
4
|
let current = reference;
|
|
22
5
|
while (current) {
|
|
@@ -27,9 +10,34 @@ function inScope(reference, binding) {
|
|
|
27
10
|
}
|
|
28
11
|
return false;
|
|
29
12
|
}
|
|
13
|
+
function isScope(node) {
|
|
14
|
+
return ts.isArrowFunction(node) ||
|
|
15
|
+
ts.isBlock(node) ||
|
|
16
|
+
ts.isCatchClause(node) ||
|
|
17
|
+
ts.isForInStatement(node) ||
|
|
18
|
+
ts.isForOfStatement(node) ||
|
|
19
|
+
ts.isForStatement(node) ||
|
|
20
|
+
ts.isFunctionDeclaration(node) ||
|
|
21
|
+
ts.isFunctionExpression(node) ||
|
|
22
|
+
ts.isSourceFile(node);
|
|
23
|
+
}
|
|
24
|
+
function scopeOf(node) {
|
|
25
|
+
let current = node.parent, depth = 0, scope = node.getSourceFile();
|
|
26
|
+
while (current) {
|
|
27
|
+
if (isScope(current)) {
|
|
28
|
+
if (scope === node.getSourceFile() && !ts.isSourceFile(current)) {
|
|
29
|
+
scope = current;
|
|
30
|
+
}
|
|
31
|
+
depth++;
|
|
32
|
+
}
|
|
33
|
+
current = current.parent;
|
|
34
|
+
}
|
|
35
|
+
return { depth, scope };
|
|
36
|
+
}
|
|
30
37
|
function visit(ctx, node) {
|
|
31
38
|
if (ctx.isReactiveCall(node)) {
|
|
32
39
|
let call = node;
|
|
40
|
+
ctx.calls.push(call);
|
|
33
41
|
if (call.arguments.length > 0) {
|
|
34
42
|
let arg = call.arguments[0], classification = TYPES.Signal;
|
|
35
43
|
if (ts.isArrowFunction(arg) || ts.isFunctionExpression(arg)) {
|
|
@@ -37,7 +45,7 @@ function visit(ctx, node) {
|
|
|
37
45
|
}
|
|
38
46
|
else {
|
|
39
47
|
let unwrapped = arg;
|
|
40
|
-
while (ts.isAsExpression(unwrapped) || ts.isParenthesizedExpression(unwrapped) || ts.
|
|
48
|
+
while (ts.isAsExpression(unwrapped) || ts.isParenthesizedExpression(unwrapped) || ts.isTypeAssertion(unwrapped)) {
|
|
41
49
|
unwrapped = unwrapped.expression;
|
|
42
50
|
}
|
|
43
51
|
if (ts.isArrayLiteralExpression(unwrapped) || ts.isObjectLiteralExpression(unwrapped)) {
|
|
@@ -48,7 +56,7 @@ function visit(ctx, node) {
|
|
|
48
56
|
generate: () => `${NAMESPACE}.reactive`,
|
|
49
57
|
node: call.expression
|
|
50
58
|
});
|
|
51
|
-
|
|
59
|
+
node.forEachChild(n => visit(ctx, n));
|
|
52
60
|
return;
|
|
53
61
|
}
|
|
54
62
|
}
|
|
@@ -64,25 +72,9 @@ function visit(ctx, node) {
|
|
|
64
72
|
varname = call.parent.left.text;
|
|
65
73
|
}
|
|
66
74
|
if (varname) {
|
|
67
|
-
let
|
|
68
|
-
while (current) {
|
|
69
|
-
if (ts.isArrowFunction(current) ||
|
|
70
|
-
ts.isBlock(current) ||
|
|
71
|
-
ts.isForInStatement(current) ||
|
|
72
|
-
ts.isForOfStatement(current) ||
|
|
73
|
-
ts.isForStatement(current) ||
|
|
74
|
-
ts.isFunctionDeclaration(current) ||
|
|
75
|
-
ts.isFunctionExpression(current) ||
|
|
76
|
-
ts.isSourceFile(current)) {
|
|
77
|
-
scope = current;
|
|
78
|
-
}
|
|
79
|
-
current = current.parent;
|
|
80
|
-
}
|
|
81
|
-
if (!scope) {
|
|
82
|
-
scope = call.getSourceFile();
|
|
83
|
-
}
|
|
75
|
+
let { depth, scope } = scopeOf(call);
|
|
84
76
|
ctx.bindings.set(varname, classification);
|
|
85
|
-
ctx.scopedBindings.push({ name: varname, scope, type: classification });
|
|
77
|
+
ctx.scopedBindings.push({ depth, name: varname, scope, type: classification });
|
|
86
78
|
}
|
|
87
79
|
ctx.replacements.push({
|
|
88
80
|
generate: () => classification === TYPES.Computed
|
|
@@ -97,13 +89,13 @@ function visit(ctx, node) {
|
|
|
97
89
|
node.parent &&
|
|
98
90
|
!(ts.isVariableDeclaration(node.parent) && node.parent.name === node)) {
|
|
99
91
|
if (ts.isPropertyAccessExpression(node.parent) && node.parent.name === node) {
|
|
100
|
-
|
|
92
|
+
node.forEachChild(n => visit(ctx, n));
|
|
101
93
|
return;
|
|
102
94
|
}
|
|
103
95
|
let bindings = ctx.scopedBindings, binding, name = node.text;
|
|
104
96
|
for (let i = 0, n = bindings.length; i < n; i++) {
|
|
105
97
|
let b = bindings[i];
|
|
106
|
-
if (b.name === name && inScope(node, b)) {
|
|
98
|
+
if (b.name === name && (!binding || b.depth >= binding.depth) && inScope(node, b)) {
|
|
107
99
|
binding = b;
|
|
108
100
|
}
|
|
109
101
|
}
|
|
@@ -178,11 +170,12 @@ function visit(ctx, node) {
|
|
|
178
170
|
}
|
|
179
171
|
}
|
|
180
172
|
}
|
|
181
|
-
|
|
173
|
+
node.forEachChild(n => visit(ctx, n));
|
|
182
174
|
}
|
|
183
175
|
export default (sourceFile, bindings, isReactiveCall) => {
|
|
184
176
|
let ctx = {
|
|
185
177
|
bindings,
|
|
178
|
+
calls: [],
|
|
186
179
|
isReactiveCall,
|
|
187
180
|
replacements: [],
|
|
188
181
|
scopedBindings: [],
|
|
@@ -190,5 +183,5 @@ export default (sourceFile, bindings, isReactiveCall) => {
|
|
|
190
183
|
tmpCounter: 0
|
|
191
184
|
};
|
|
192
185
|
visit(ctx, sourceFile);
|
|
193
|
-
return ctx.replacements;
|
|
186
|
+
return { calls: ctx.calls, replacements: ctx.replacements };
|
|
194
187
|
};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { ts } from '@esportsplus/typescript';
|
|
1
2
|
import { TYPES } from './constants.js';
|
|
2
3
|
type Bindings = Map<string, TYPES>;
|
|
3
|
-
|
|
4
|
+
type IsReactiveCall = (node: ts.Node) => node is ts.CallExpression;
|
|
5
|
+
export type { Bindings, IsReactiveCall };
|
package/build/constants.d.ts
CHANGED
|
@@ -3,11 +3,11 @@ declare const PACKAGE_NAME = "@esportsplus/reactivity";
|
|
|
3
3
|
declare const REACTIVE_ARRAY: unique symbol;
|
|
4
4
|
declare const REACTIVE_OBJECT: unique symbol;
|
|
5
5
|
declare const SIGNAL: unique symbol;
|
|
6
|
+
declare const STABILIZER_DEFERRED = 4;
|
|
6
7
|
declare const STABILIZER_IDLE = 0;
|
|
7
8
|
declare const STABILIZER_RESCHEDULE = 1;
|
|
8
9
|
declare const STABILIZER_RUNNING = 2;
|
|
9
10
|
declare const STABILIZER_SCHEDULED = 3;
|
|
10
|
-
declare const STATE_NONE = 0;
|
|
11
11
|
declare const STATE_CHECK: number;
|
|
12
12
|
declare const STATE_DIRTY: number;
|
|
13
13
|
declare const STATE_RECOMPUTING: number;
|
|
@@ -16,4 +16,4 @@ declare const STATE_COMPUTED: number;
|
|
|
16
16
|
declare const STATE_ERROR: number;
|
|
17
17
|
declare const STATE_EFFECT: number;
|
|
18
18
|
declare const STATE_NOTIFY_MASK: number;
|
|
19
|
-
export { COMPUTED, PACKAGE_NAME, REACTIVE_ARRAY, REACTIVE_OBJECT, SIGNAL, STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED, STATE_CHECK, STATE_COMPUTED, STATE_DIRTY, STATE_EFFECT, STATE_ERROR, STATE_IN_HEAP,
|
|
19
|
+
export { COMPUTED, PACKAGE_NAME, REACTIVE_ARRAY, REACTIVE_OBJECT, SIGNAL, STABILIZER_DEFERRED, STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED, STATE_CHECK, STATE_COMPUTED, STATE_DIRTY, STATE_EFFECT, STATE_ERROR, STATE_IN_HEAP, STATE_NOTIFY_MASK, STATE_RECOMPUTING };
|
package/build/constants.js
CHANGED
|
@@ -3,11 +3,11 @@ const PACKAGE_NAME = '@esportsplus/reactivity';
|
|
|
3
3
|
const REACTIVE_ARRAY = Symbol('reactivity.reactive.array');
|
|
4
4
|
const REACTIVE_OBJECT = Symbol('reactivity.reactive.object');
|
|
5
5
|
const SIGNAL = Symbol('reactivity.signal');
|
|
6
|
+
const STABILIZER_DEFERRED = 4;
|
|
6
7
|
const STABILIZER_IDLE = 0;
|
|
7
8
|
const STABILIZER_RESCHEDULE = 1;
|
|
8
9
|
const STABILIZER_RUNNING = 2;
|
|
9
10
|
const STABILIZER_SCHEDULED = 3;
|
|
10
|
-
const STATE_NONE = 0;
|
|
11
11
|
const STATE_CHECK = 1 << 0;
|
|
12
12
|
const STATE_DIRTY = 1 << 1;
|
|
13
13
|
const STATE_RECOMPUTING = 1 << 2;
|
|
@@ -16,4 +16,4 @@ const STATE_COMPUTED = 1 << 4;
|
|
|
16
16
|
const STATE_ERROR = 1 << 5;
|
|
17
17
|
const STATE_EFFECT = 1 << 6;
|
|
18
18
|
const STATE_NOTIFY_MASK = (STATE_CHECK | STATE_DIRTY);
|
|
19
|
-
export { COMPUTED, PACKAGE_NAME, REACTIVE_ARRAY, REACTIVE_OBJECT, SIGNAL, STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED, STATE_CHECK, STATE_COMPUTED, STATE_DIRTY, STATE_EFFECT, STATE_ERROR, STATE_IN_HEAP,
|
|
19
|
+
export { COMPUTED, PACKAGE_NAME, REACTIVE_ARRAY, REACTIVE_OBJECT, SIGNAL, STABILIZER_DEFERRED, STABILIZER_IDLE, STABILIZER_RESCHEDULE, STABILIZER_RUNNING, STABILIZER_SCHEDULED, STATE_CHECK, STATE_COMPUTED, STATE_DIRTY, STATE_EFFECT, STATE_ERROR, STATE_IN_HEAP, STATE_NOTIFY_MASK, STATE_RECOMPUTING };
|
|
@@ -40,7 +40,7 @@ type Listeners<T> = {
|
|
|
40
40
|
declare class ReactiveArray<T> extends Array<T> {
|
|
41
41
|
private _length;
|
|
42
42
|
listeners: Listeners<T>;
|
|
43
|
-
constructor(
|
|
43
|
+
constructor(items?: readonly T[]);
|
|
44
44
|
static get [Symbol.species](): ArrayConstructor;
|
|
45
45
|
get $length(): number;
|
|
46
46
|
set $length(value: number);
|
package/build/reactive/array.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isArray } from '@esportsplus/utilities';
|
|
2
|
-
import { REACTIVE_ARRAY } from '../constants.js';
|
|
2
|
+
import { PACKAGE_NAME, REACTIVE_ARRAY } from '../constants.js';
|
|
3
3
|
import { read, signal, write } from '../system.js';
|
|
4
4
|
import { isReactiveObject } from './object.js';
|
|
5
5
|
function dispose(value) {
|
|
@@ -10,9 +10,13 @@ function dispose(value) {
|
|
|
10
10
|
class ReactiveArray extends Array {
|
|
11
11
|
_length;
|
|
12
12
|
listeners = {};
|
|
13
|
-
constructor(
|
|
14
|
-
super(
|
|
15
|
-
|
|
13
|
+
constructor(items) {
|
|
14
|
+
super();
|
|
15
|
+
let n = items ? items.length : 0;
|
|
16
|
+
for (let i = 0; i < n; i++) {
|
|
17
|
+
this[i] = items[i];
|
|
18
|
+
}
|
|
19
|
+
this._length = signal(n);
|
|
16
20
|
}
|
|
17
21
|
static get [Symbol.species]() {
|
|
18
22
|
return Array;
|
|
@@ -37,6 +41,7 @@ class ReactiveArray extends Array {
|
|
|
37
41
|
write(this._length, i + 1);
|
|
38
42
|
}
|
|
39
43
|
this.dispatch('set', { index: i, item: value });
|
|
44
|
+
dispose(prev);
|
|
40
45
|
}
|
|
41
46
|
clear() {
|
|
42
47
|
this.dispose();
|
|
@@ -69,7 +74,7 @@ class ReactiveArray extends Array {
|
|
|
69
74
|
if (!listeners) {
|
|
70
75
|
return;
|
|
71
76
|
}
|
|
72
|
-
let dirty = false;
|
|
77
|
+
let dirty = false, errors = null;
|
|
73
78
|
for (let i = 0, n = listeners.length; i < n; i++) {
|
|
74
79
|
let listener = listeners[i];
|
|
75
80
|
if (listener === null) {
|
|
@@ -82,9 +87,10 @@ class ReactiveArray extends Array {
|
|
|
82
87
|
listeners[i] = null;
|
|
83
88
|
}
|
|
84
89
|
}
|
|
85
|
-
catch {
|
|
90
|
+
catch (e) {
|
|
86
91
|
dirty = true;
|
|
87
92
|
listeners[i] = null;
|
|
93
|
+
(errors ??= []).push(e);
|
|
88
94
|
}
|
|
89
95
|
}
|
|
90
96
|
if (dirty) {
|
|
@@ -92,6 +98,14 @@ class ReactiveArray extends Array {
|
|
|
92
98
|
listeners.pop();
|
|
93
99
|
}
|
|
94
100
|
}
|
|
101
|
+
if (errors !== null) {
|
|
102
|
+
let error = errors.length === 1
|
|
103
|
+
? errors[0]
|
|
104
|
+
: new AggregateError(errors, `${PACKAGE_NAME}: dispatch produced multiple errors`);
|
|
105
|
+
queueMicrotask(() => {
|
|
106
|
+
throw error;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
95
109
|
}
|
|
96
110
|
dispose() {
|
|
97
111
|
while (this.length) {
|
|
@@ -169,20 +183,17 @@ class ReactiveArray extends Array {
|
|
|
169
183
|
super.sort(fn);
|
|
170
184
|
let buckets = new Map(), order = new Array(n);
|
|
171
185
|
for (let i = 0; i < n; i++) {
|
|
172
|
-
let value = before[i],
|
|
173
|
-
if (
|
|
174
|
-
buckets.set(value, [i]);
|
|
186
|
+
let value = before[i], bucket = buckets.get(value);
|
|
187
|
+
if (bucket === undefined) {
|
|
188
|
+
buckets.set(value, { indices: [i], next: 0 });
|
|
175
189
|
}
|
|
176
190
|
else {
|
|
177
|
-
|
|
191
|
+
bucket.indices.push(i);
|
|
178
192
|
}
|
|
179
193
|
}
|
|
180
194
|
for (let i = 0; i < n; i++) {
|
|
181
|
-
let
|
|
182
|
-
order[i] =
|
|
183
|
-
if (list.length > 1) {
|
|
184
|
-
list.pop();
|
|
185
|
-
}
|
|
195
|
+
let bucket = buckets.get(this[i]);
|
|
196
|
+
order[i] = bucket.indices[bucket.next++];
|
|
186
197
|
}
|
|
187
198
|
this.dispatch('sort', { order });
|
|
188
199
|
}
|
package/build/reactive/index.js
CHANGED
|
@@ -4,25 +4,16 @@ import { PACKAGE_NAME } from '../constants.js';
|
|
|
4
4
|
import { ReactiveArray } from './array.js';
|
|
5
5
|
import { ReactiveObject } from './object.js';
|
|
6
6
|
function reactive(input) {
|
|
7
|
-
let
|
|
8
|
-
let response;
|
|
7
|
+
let value = root(() => {
|
|
9
8
|
if (isObject(input)) {
|
|
10
|
-
|
|
9
|
+
return new ReactiveObject(input);
|
|
11
10
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
if (response) {
|
|
16
|
-
if (root.disposables) {
|
|
17
|
-
dispose = true;
|
|
18
|
-
}
|
|
19
|
-
return response;
|
|
11
|
+
if (isArray(input)) {
|
|
12
|
+
return new ReactiveArray(input);
|
|
20
13
|
}
|
|
21
14
|
throw new Error(`${PACKAGE_NAME}: 'reactive' received invalid input - ${JSON.stringify(input)}`);
|
|
22
15
|
});
|
|
23
|
-
|
|
24
|
-
onCleanup(() => value.dispose());
|
|
25
|
-
}
|
|
16
|
+
onCleanup(() => value.dispose());
|
|
26
17
|
return value;
|
|
27
18
|
}
|
|
28
19
|
export default reactive;
|
package/build/reactive/object.js
CHANGED
package/build/system.d.ts
CHANGED
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
import { Computed, ComputedResult, Settled, Signal } from './types.js';
|
|
2
2
|
declare const batch: <T>(fn: () => T) => T;
|
|
3
|
-
declare
|
|
4
|
-
|
|
5
|
-
invalidate<T>(c: Computed<T>)
|
|
6
|
-
}
|
|
3
|
+
declare function computed<T>(fn: Computed<T>['fn'], equals?: ((a: Settled<T>, b: Settled<T>) => boolean) | null): ComputedResult<T>;
|
|
4
|
+
declare namespace computed {
|
|
5
|
+
var invalidate: <T>(c: Computed<T>) => void;
|
|
6
|
+
}
|
|
7
7
|
declare const dispose: <T>(computed: Computed<T>) => void;
|
|
8
|
-
declare const effect: <T>(fn: Computed<T>[
|
|
8
|
+
declare const effect: <T>(fn: Computed<T>['fn'], apply?: (value: T, prev: T | undefined) => void) => () => void;
|
|
9
9
|
declare const flush: () => void;
|
|
10
10
|
declare const isComputed: (value: unknown) => value is Computed<unknown>;
|
|
11
11
|
declare const isSignal: (value: unknown) => value is Signal<unknown>;
|
|
12
12
|
declare const onCleanup: (fn: VoidFunction) => typeof fn;
|
|
13
13
|
declare const peek: <T>(node: Signal<T> | Computed<T>) => T;
|
|
14
14
|
declare const read: <T>(node: Signal<T> | Computed<T>) => T;
|
|
15
|
-
declare const root:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
<T>(value: T, equals?: ((a: T, b: T) => boolean) | null): Signal<T>;
|
|
21
|
-
selector<T>(node: Signal<T>, key: T): boolean;
|
|
22
|
-
};
|
|
15
|
+
declare const root: <T>(fn: ((dispose: VoidFunction) => T) | (() => T)) => T;
|
|
16
|
+
declare function signal<T>(value: T, equals?: ((a: T, b: T) => boolean) | null): Signal<T>;
|
|
17
|
+
declare namespace signal {
|
|
18
|
+
var selector: <T>(node: Signal<T>, key: T) => boolean;
|
|
19
|
+
}
|
|
23
20
|
declare const untrack: <T>(fn: () => T) => T;
|
|
24
21
|
declare const write: <T>(signal: Signal<T>, value: T) => void;
|
|
25
22
|
export { batch, computed, dispose, effect, flush, isComputed, isSignal, onCleanup, peek, read, root, signal, untrack, write };
|