forked from angular/angular
-
Notifications
You must be signed in to change notification settings - Fork 0
/
signal.ts
71 lines (61 loc) · 2.21 KB
/
signal.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {createSignal, SIGNAL, SignalGetter, SignalNode, signalSetFn, signalUpdateFn} from '@angular/core/primitives/signals';
import {Signal, ValueEqualityFn} from './api';
/**
* A `Signal` with a value that can be mutated via a setter interface.
*/
export interface WritableSignal<T> extends Signal<T> {
/**
* Directly set the signal to a new value, and notify any dependents.
*/
set(value: T): void;
/**
* Update the value of the signal based on its current value, and
* notify any dependents.
*/
update(updateFn: (value: T) => T): void;
/**
* Returns a readonly version of this signal. Readonly signals can be accessed to read their value
* but can't be changed using set, update or mutate methods. The readonly signals do _not_ have
* any built-in mechanism that would prevent deep-mutation of their value.
*/
asReadonly(): Signal<T>;
}
/**
* Options passed to the `signal` creation function.
*/
export interface CreateSignalOptions<T> {
/**
* A comparison function which defines equality for signal values.
*/
equal?: ValueEqualityFn<T>;
}
/**
* Create a `Signal` that can be set or updated directly.
*/
export function signal<T>(initialValue: T, options?: CreateSignalOptions<T>): WritableSignal<T> {
const signalFn = createSignal(initialValue) as SignalGetter<T>& WritableSignal<T>;
const node = signalFn[SIGNAL];
if (options?.equal) {
node.equal = options.equal;
}
signalFn.set = (newValue: T) => signalSetFn(node, newValue);
signalFn.update = (updateFn: (value: T) => T) => signalUpdateFn(node, updateFn);
signalFn.asReadonly = signalAsReadonlyFn.bind(signalFn as any) as () => Signal<T>;
return signalFn as WritableSignal<T>;
}
function signalAsReadonlyFn<T>(this: SignalGetter<T>): Signal<T> {
const node = this[SIGNAL] as SignalNode<T>& {readonlyFn?: Signal<T>};
if (node.readonlyFn === undefined) {
const readonlyFn = () => this();
(readonlyFn as any)[SIGNAL] = node;
node.readonlyFn = readonlyFn as Signal<T>;
}
return node.readonlyFn;
}