Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/util/vs/base/common/observableInternal/base.ts
13406 views
1
//!!! DO NOT modify, this file was COPIED from 'microsoft/vscode'
2
3
/*---------------------------------------------------------------------------------------------
4
* Copyright (c) Microsoft Corporation. All rights reserved.
5
* Licensed under the MIT License. See License.txt in the project root for license information.
6
*--------------------------------------------------------------------------------------------*/
7
8
import { DisposableStore, onUnexpectedError } from './commonFacade/deps';
9
10
/**
11
* Represents an observable value.
12
*
13
* @template T The type of the values the observable can hold.
14
*/
15
// This interface exists so that, for example for string observables,
16
// typescript renders the type as `IObservable<string>` instead of `IObservable<string, unknown>`.
17
export interface IObservable<T> extends IObservableWithChange<T, unknown> { }
18
19
/**
20
* Represents an observable value.
21
*
22
* @template T The type of the values the observable can hold.
23
* @template TChange The type used to describe value changes
24
* (usually `void` and only used in advanced scenarios).
25
* While observers can miss temporary values of an observable,
26
* they will receive all change values (as long as they are subscribed)!
27
*/
28
export interface IObservableWithChange<T, TChange = unknown> {
29
/**
30
* Returns the current value.
31
*
32
* Calls {@link IObserver.handleChange} if the observable notices that the value changed.
33
* Must not be called from {@link IObserver.handleChange}!
34
*/
35
get(): T;
36
37
/**
38
* Forces the observable to check for changes and report them.
39
*
40
* Has the same effect as calling {@link IObservable.get}, but does not force the observable
41
* to actually construct the value, e.g. if change deltas are used.
42
* Calls {@link IObserver.handleChange} if the observable notices that the value changed.
43
* Must not be called from {@link IObserver.handleChange}!
44
*/
45
reportChanges(): void;
46
47
/**
48
* Adds the observer to the set of subscribed observers.
49
* This method is idempotent.
50
*/
51
addObserver(observer: IObserver): void;
52
53
/**
54
* Removes the observer from the set of subscribed observers.
55
* This method is idempotent.
56
*/
57
removeObserver(observer: IObserver): void;
58
59
// #region These members have a standard implementation and are only part of the interface for convenience.
60
61
/**
62
* Reads the current value and subscribes the reader to this observable.
63
*
64
* Calls {@link IReader.readObservable} if a reader is given, otherwise {@link IObservable.get}
65
* (see {@link ConvenientObservable.read} for the implementation).
66
*/
67
read(reader: IReader | undefined): T;
68
69
/**
70
* Makes sure this value is computed eagerly.
71
*/
72
recomputeInitiallyAndOnChange(store: DisposableStore, handleValue?: (value: T) => void): IObservable<T>;
73
74
/**
75
* Makes sure this value is cached.
76
*/
77
keepObserved(store: DisposableStore): IObservable<T>;
78
79
/**
80
* Creates a derived observable that depends on this observable.
81
* Use the reader to read other observables
82
* (see {@link ConvenientObservable.map} for the implementation).
83
*/
84
map<TNew>(fn: (value: T, reader: IReader) => TNew): IObservable<TNew>;
85
map<TNew>(owner: object, fn: (value: T, reader: IReader) => TNew): IObservable<TNew>;
86
87
flatten<TNew>(this: IObservable<IObservable<TNew>>): IObservable<TNew>;
88
89
/**
90
* ONLY FOR DEBUGGING!
91
* Logs computations of this derived.
92
*/
93
log(): IObservableWithChange<T, TChange>;
94
95
/**
96
* A human-readable name for debugging purposes.
97
*/
98
readonly debugName: string;
99
100
/**
101
* This property captures the type of the change object. Do not use it at runtime!
102
*/
103
readonly TChange: TChange;
104
105
// #endregion
106
}
107
108
/**
109
* Represents an observer that can be subscribed to an observable.
110
*
111
* If an observer is subscribed to an observable and that observable didn't signal
112
* a change through one of the observer methods, the observer can assume that the
113
* observable didn't change.
114
* If an observable reported a possible change, {@link IObservable.reportChanges} forces
115
* the observable to report an actual change if there was one.
116
*/
117
export interface IObserver {
118
/**
119
* Signals that the given observable might have changed and a transaction potentially modifying that observable started.
120
* Before the given observable can call this method again, is must call {@link IObserver.endUpdate}.
121
*
122
* Implementations must not get/read the value of other observables, as they might not have received this event yet!
123
* The method {@link IObservable.reportChanges} can be used to force the observable to report the changes.
124
*/
125
beginUpdate<T>(observable: IObservable<T>): void;
126
127
/**
128
* Signals that the transaction that potentially modified the given observable ended.
129
* This is a good place to react to (potential) changes.
130
*/
131
endUpdate<T>(observable: IObservable<T>): void;
132
133
/**
134
* Signals that the given observable might have changed.
135
* The method {@link IObservable.reportChanges} can be used to force the observable to report the changes.
136
*
137
* Implementations must not get/read the value of other observables, as they might not have received this event yet!
138
* The change should be processed lazily or in {@link IObserver.endUpdate}.
139
*/
140
handlePossibleChange<T>(observable: IObservable<T>): void;
141
142
/**
143
* Signals that the given {@link observable} changed.
144
*
145
* Implementations must not get/read the value of other observables, as they might not have received this event yet!
146
* The change should be processed lazily or in {@link IObserver.endUpdate}.
147
*
148
* @param change Indicates how or why the value changed.
149
*/
150
handleChange<T, TChange>(observable: IObservableWithChange<T, TChange>, change: TChange): void;
151
}
152
153
/**
154
* A reader allows code to track what it depends on, so the caller knows when the computed value or produced side-effect is no longer valid.
155
* Use `derived(reader => ...)` to turn code that needs a reader into an observable value.
156
*/
157
export interface IReader {
158
/**
159
* Reads the value of an observable and subscribes to it.
160
*/
161
readObservable<T>(observable: IObservableWithChange<T, any>): T;
162
}
163
164
export interface ISettable<T, TChange = void> {
165
/**
166
* Sets the value of the observable.
167
* Use a transaction to batch multiple changes (with a transaction, observers only react at the end of the transaction).
168
*
169
* @param transaction When given, value changes are handled on demand or when the transaction ends.
170
* @param change Describes how or why the value changed.
171
*/
172
set(value: T, transaction: ITransaction | undefined, change: TChange): void;
173
}
174
175
export interface ITransaction {
176
/**
177
* Calls {@link Observer.beginUpdate} immediately
178
* and {@link Observer.endUpdate} when the transaction ends.
179
*/
180
updateObserver(observer: IObserver, observable: IObservableWithChange<any, any>): void;
181
}
182
183
/**
184
* This function is used to indicate that the caller recovered from an error that indicates a bug.
185
*/
186
export function handleBugIndicatingErrorRecovery(message: string) {
187
const err = new Error('BugIndicatingErrorRecovery: ' + message);
188
onUnexpectedError(err);
189
console.error('recovered from an error that indicates a bug', err);
190
}
191
192
/**
193
* A settable observable.
194
*/
195
export interface ISettableObservable<T, TChange = void> extends IObservableWithChange<T, TChange>, ISettable<T, TChange> {
196
}
197
198
export interface IReaderWithStore extends IReader {
199
/**
200
* Items in this store get disposed just before the observable recomputes/reruns or when it becomes unobserved.
201
*/
202
get store(): DisposableStore;
203
204
/**
205
* Items in this store get disposed just after the observable recomputes/reruns or when it becomes unobserved.
206
* This is important if the current run needs the undisposed result from the last run.
207
*
208
* Warning: Items in this store might still get disposed before dependents (that read the now disposed value in the past) are recomputed with the new (undisposed) value!
209
* A clean solution for this is ref counting.
210
*/
211
get delayedStore(): DisposableStore;
212
}
213
214