@xterm/xterm 6.1.0-beta.28 → 6.1.0-beta.281

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.
Files changed (181) hide show
  1. package/README.md +62 -38
  2. package/css/xterm.css +29 -22
  3. package/lib/xterm.js +1 -1
  4. package/lib/xterm.js.map +1 -1
  5. package/lib/xterm.mjs +8 -34
  6. package/lib/xterm.mjs.map +4 -4
  7. package/package.json +56 -45
  8. package/src/browser/AccessibilityManager.ts +18 -13
  9. package/src/browser/Clipboard.ts +8 -5
  10. package/src/browser/ColorContrastCache.ts +3 -3
  11. package/src/browser/CoreBrowserTerminal.ts +179 -348
  12. package/src/browser/Dom.ts +178 -0
  13. package/src/browser/Linkifier.ts +14 -14
  14. package/src/browser/OscLinkProvider.ts +86 -18
  15. package/src/browser/RenderDebouncer.ts +7 -9
  16. package/src/browser/TimeBasedDebouncer.ts +12 -5
  17. package/src/browser/Types.ts +16 -14
  18. package/src/browser/Viewport.ts +58 -23
  19. package/src/browser/decorations/BufferDecorationRenderer.ts +3 -3
  20. package/src/browser/decorations/ColorZoneStore.ts +1 -1
  21. package/src/browser/decorations/OverviewRulerRenderer.ts +36 -20
  22. package/src/browser/input/CompositionHelper.ts +47 -11
  23. package/src/browser/input/Mouse.ts +5 -9
  24. package/src/browser/input/MoveToCell.ts +3 -3
  25. package/src/browser/public/Terminal.ts +33 -36
  26. package/src/browser/renderer/dom/DomRenderer.ts +265 -89
  27. package/src/browser/renderer/dom/DomRendererRowFactory.ts +34 -27
  28. package/src/browser/renderer/dom/WidthCache.ts +57 -55
  29. package/src/browser/renderer/shared/Constants.ts +7 -0
  30. package/src/browser/renderer/shared/RendererUtils.ts +1 -1
  31. package/src/browser/renderer/shared/SelectionRenderModel.ts +2 -2
  32. package/src/browser/renderer/shared/TextBlinkStateManager.ts +97 -0
  33. package/src/browser/renderer/shared/Types.ts +10 -4
  34. package/src/browser/scrollable/abstractScrollbar.ts +300 -0
  35. package/src/browser/scrollable/fastDomNode.ts +126 -0
  36. package/src/browser/scrollable/globalPointerMoveMonitor.ts +90 -0
  37. package/src/browser/scrollable/horizontalScrollbar.ts +85 -0
  38. package/src/browser/scrollable/mouseEvent.ts +292 -0
  39. package/src/browser/scrollable/scrollable.ts +486 -0
  40. package/src/browser/scrollable/scrollableElement.ts +581 -0
  41. package/src/browser/scrollable/scrollableElementOptions.ts +161 -0
  42. package/src/browser/scrollable/scrollbarArrow.ts +110 -0
  43. package/src/browser/scrollable/scrollbarState.ts +246 -0
  44. package/src/browser/scrollable/scrollbarVisibilityController.ts +113 -0
  45. package/src/browser/scrollable/touch.ts +485 -0
  46. package/src/browser/scrollable/verticalScrollbar.ts +143 -0
  47. package/src/browser/scrollable/widget.ts +23 -0
  48. package/src/browser/selection/SelectionModel.ts +1 -1
  49. package/src/browser/services/CharSizeService.ts +4 -4
  50. package/src/browser/services/CharacterJoinerService.ts +13 -11
  51. package/src/browser/services/CoreBrowserService.ts +7 -5
  52. package/src/browser/services/KeyboardService.ts +67 -0
  53. package/src/browser/services/LinkProviderService.ts +3 -3
  54. package/src/browser/services/MouseCoordsService.ts +47 -0
  55. package/src/browser/services/MouseService.ts +619 -23
  56. package/src/browser/services/RenderService.ts +33 -21
  57. package/src/browser/services/SelectionService.ts +72 -54
  58. package/src/browser/services/Services.ts +44 -21
  59. package/src/browser/services/ThemeService.ts +9 -9
  60. package/src/common/Async.ts +141 -0
  61. package/src/common/CircularList.ts +24 -3
  62. package/src/common/Color.ts +13 -5
  63. package/src/common/CoreTerminal.ts +61 -35
  64. package/src/common/Event.ts +118 -0
  65. package/src/common/InputHandler.ts +286 -105
  66. package/src/common/Lifecycle.ts +113 -0
  67. package/src/common/Platform.ts +15 -5
  68. package/src/common/SortedList.ts +8 -4
  69. package/src/common/StringBuilder.ts +67 -0
  70. package/src/common/TaskQueue.ts +17 -8
  71. package/src/common/Types.ts +68 -206
  72. package/src/common/Version.ts +1 -1
  73. package/src/common/WindowsMode.ts +2 -2
  74. package/src/common/buffer/AttributeData.ts +3 -2
  75. package/src/common/buffer/Buffer.ts +47 -32
  76. package/src/common/buffer/BufferLine.ts +175 -100
  77. package/src/common/buffer/BufferLineStringCache.ts +69 -0
  78. package/src/common/buffer/BufferReflow.ts +7 -4
  79. package/src/common/buffer/BufferSet.ts +13 -9
  80. package/src/common/buffer/CellData.ts +61 -4
  81. package/src/common/buffer/Constants.ts +13 -13
  82. package/src/common/buffer/Marker.ts +4 -4
  83. package/src/common/buffer/Types.ts +153 -3
  84. package/src/common/data/Charsets.ts +4 -7
  85. package/src/common/data/EscapeSequences.ts +71 -70
  86. package/src/common/input/Keyboard.ts +17 -10
  87. package/src/common/input/KittyKeyboard.ts +526 -0
  88. package/src/common/input/TextDecoder.ts +3 -3
  89. package/src/common/input/UnicodeV6.ts +3 -2
  90. package/src/common/input/Win32InputMode.ts +297 -0
  91. package/src/common/input/WriteBuffer.ts +108 -39
  92. package/src/common/input/XParseColor.ts +2 -2
  93. package/src/common/parser/ApcParser.ts +196 -0
  94. package/src/common/parser/Constants.ts +14 -4
  95. package/src/common/parser/DcsParser.ts +15 -16
  96. package/src/common/parser/EscapeSequenceParser.ts +214 -72
  97. package/src/common/parser/OscParser.ts +14 -15
  98. package/src/common/parser/Params.ts +31 -12
  99. package/src/common/parser/Types.ts +40 -30
  100. package/src/common/public/BufferApiView.ts +3 -3
  101. package/src/common/public/BufferLineApiView.ts +4 -4
  102. package/src/common/public/BufferNamespaceApi.ts +5 -5
  103. package/src/common/public/ParserApi.ts +5 -2
  104. package/src/common/public/UnicodeApi.ts +1 -1
  105. package/src/common/services/BufferService.ts +17 -13
  106. package/src/common/services/CharsetService.ts +6 -2
  107. package/src/common/services/CoreService.ts +23 -10
  108. package/src/common/services/DecorationService.ts +260 -15
  109. package/src/common/services/InstantiationService.ts +2 -2
  110. package/src/common/services/LogService.ts +2 -32
  111. package/src/common/services/{CoreMouseService.ts → MouseStateService.ts} +22 -133
  112. package/src/common/services/OptionsService.ts +17 -7
  113. package/src/common/services/OscLinkService.ts +3 -2
  114. package/src/common/services/ServiceRegistry.ts +14 -8
  115. package/src/common/services/Services.ts +54 -50
  116. package/src/common/services/UnicodeService.ts +6 -11
  117. package/typings/xterm.d.ts +329 -34
  118. package/src/common/Clone.ts +0 -23
  119. package/src/common/TypedArrayUtils.ts +0 -17
  120. package/src/vs/base/browser/browser.ts +0 -141
  121. package/src/vs/base/browser/canIUse.ts +0 -49
  122. package/src/vs/base/browser/dom.ts +0 -2369
  123. package/src/vs/base/browser/fastDomNode.ts +0 -316
  124. package/src/vs/base/browser/globalPointerMoveMonitor.ts +0 -112
  125. package/src/vs/base/browser/iframe.ts +0 -135
  126. package/src/vs/base/browser/keyboardEvent.ts +0 -213
  127. package/src/vs/base/browser/mouseEvent.ts +0 -229
  128. package/src/vs/base/browser/touch.ts +0 -372
  129. package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +0 -303
  130. package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +0 -114
  131. package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +0 -720
  132. package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +0 -165
  133. package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +0 -114
  134. package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +0 -243
  135. package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +0 -118
  136. package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +0 -116
  137. package/src/vs/base/browser/ui/widget.ts +0 -57
  138. package/src/vs/base/browser/window.ts +0 -14
  139. package/src/vs/base/common/arrays.ts +0 -887
  140. package/src/vs/base/common/arraysFind.ts +0 -202
  141. package/src/vs/base/common/assert.ts +0 -71
  142. package/src/vs/base/common/async.ts +0 -1992
  143. package/src/vs/base/common/cancellation.ts +0 -148
  144. package/src/vs/base/common/charCode.ts +0 -450
  145. package/src/vs/base/common/collections.ts +0 -140
  146. package/src/vs/base/common/decorators.ts +0 -130
  147. package/src/vs/base/common/equals.ts +0 -146
  148. package/src/vs/base/common/errors.ts +0 -303
  149. package/src/vs/base/common/event.ts +0 -1778
  150. package/src/vs/base/common/functional.ts +0 -32
  151. package/src/vs/base/common/hash.ts +0 -316
  152. package/src/vs/base/common/iterator.ts +0 -159
  153. package/src/vs/base/common/keyCodes.ts +0 -526
  154. package/src/vs/base/common/keybindings.ts +0 -284
  155. package/src/vs/base/common/lazy.ts +0 -47
  156. package/src/vs/base/common/lifecycle.ts +0 -801
  157. package/src/vs/base/common/linkedList.ts +0 -142
  158. package/src/vs/base/common/map.ts +0 -202
  159. package/src/vs/base/common/numbers.ts +0 -98
  160. package/src/vs/base/common/observable.ts +0 -76
  161. package/src/vs/base/common/observableInternal/api.ts +0 -31
  162. package/src/vs/base/common/observableInternal/autorun.ts +0 -281
  163. package/src/vs/base/common/observableInternal/base.ts +0 -489
  164. package/src/vs/base/common/observableInternal/debugName.ts +0 -145
  165. package/src/vs/base/common/observableInternal/derived.ts +0 -428
  166. package/src/vs/base/common/observableInternal/lazyObservableValue.ts +0 -146
  167. package/src/vs/base/common/observableInternal/logging.ts +0 -328
  168. package/src/vs/base/common/observableInternal/promise.ts +0 -209
  169. package/src/vs/base/common/observableInternal/utils.ts +0 -610
  170. package/src/vs/base/common/platform.ts +0 -281
  171. package/src/vs/base/common/scrollable.ts +0 -522
  172. package/src/vs/base/common/sequence.ts +0 -34
  173. package/src/vs/base/common/stopwatch.ts +0 -43
  174. package/src/vs/base/common/strings.ts +0 -557
  175. package/src/vs/base/common/symbols.ts +0 -9
  176. package/src/vs/base/common/uint.ts +0 -59
  177. package/src/vs/patches/nls.ts +0 -90
  178. package/src/vs/typings/base-common.d.ts +0 -20
  179. package/src/vs/typings/require.d.ts +0 -42
  180. package/src/vs/typings/vscode-globals-nls.d.ts +0 -36
  181. package/src/vs/typings/vscode-globals-product.d.ts +0 -33
@@ -1,610 +0,0 @@
1
- /*---------------------------------------------------------------------------------------------
2
- * Copyright (c) Microsoft Corporation. All rights reserved.
3
- * Licensed under the MIT License. See License.txt in the project root for license information.
4
- *--------------------------------------------------------------------------------------------*/
5
-
6
- import { Event } from 'vs/base/common/event';
7
- import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
8
- import { autorun, autorunOpts } from 'vs/base/common/observableInternal/autorun';
9
- import { BaseObservable, ConvenientObservable, IObservable, IObserver, IReader, ITransaction, _setKeepObserved, _setRecomputeInitiallyAndOnChange, observableValue, subtransaction, transaction } from 'vs/base/common/observableInternal/base';
10
- import { DebugNameData, IDebugNameData, DebugOwner, getDebugName, } from 'vs/base/common/observableInternal/debugName';
11
- import { derived, derivedOpts } from 'vs/base/common/observableInternal/derived';
12
- import { getLogger } from 'vs/base/common/observableInternal/logging';
13
- import { IValueWithChangeEvent } from '../event';
14
- import { BugIndicatingError } from 'vs/base/common/errors';
15
- import { EqualityComparer, strictEquals } from 'vs/base/common/equals';
16
-
17
- /**
18
- * Represents an efficient observable whose value never changes.
19
- */
20
- export function constObservable<T>(value: T): IObservable<T> {
21
- return new ConstObservable(value);
22
- }
23
-
24
- class ConstObservable<T> extends ConvenientObservable<T, void> {
25
- constructor(private readonly value: T) {
26
- super();
27
- }
28
-
29
- public override get debugName(): string {
30
- return this.toString();
31
- }
32
-
33
- public get(): T {
34
- return this.value;
35
- }
36
- public addObserver(observer: IObserver): void {
37
- // NO OP
38
- }
39
- public removeObserver(observer: IObserver): void {
40
- // NO OP
41
- }
42
-
43
- override toString(): string {
44
- return `Const: ${this.value}`;
45
- }
46
- }
47
-
48
-
49
- export function observableFromPromise<T>(promise: Promise<T>): IObservable<{ value?: T }> {
50
- const observable = observableValue<{ value?: T }>('promiseValue', {});
51
- promise.then((value) => {
52
- observable.set({ value }, undefined);
53
- });
54
- return observable;
55
- }
56
-
57
-
58
- export function observableFromEvent<T, TArgs = unknown>(
59
- owner: DebugOwner,
60
- event: Event<TArgs>,
61
- getValue: (args: TArgs | undefined) => T,
62
- ): IObservable<T>;
63
- export function observableFromEvent<T, TArgs = unknown>(
64
- event: Event<TArgs>,
65
- getValue: (args: TArgs | undefined) => T,
66
- ): IObservable<T>;
67
- export function observableFromEvent(...args:
68
- [owner: DebugOwner, event: Event<any>, getValue: (args: any | undefined) => any]
69
- | [event: Event<any>, getValue: (args: any | undefined) => any]
70
- ): IObservable<any> {
71
- let owner;
72
- let event;
73
- let getValue;
74
- if (args.length === 3) {
75
- [owner, event, getValue] = args;
76
- } else {
77
- [event, getValue] = args;
78
- }
79
- return new FromEventObservable(
80
- new DebugNameData(owner, undefined, getValue),
81
- event,
82
- getValue,
83
- () => FromEventObservable.globalTransaction,
84
- strictEquals
85
- );
86
- }
87
-
88
- export function observableFromEventOpts<T, TArgs = unknown>(
89
- options: IDebugNameData & {
90
- equalsFn?: EqualityComparer<T>;
91
- },
92
- event: Event<TArgs>,
93
- getValue: (args: TArgs | undefined) => T,
94
- ): IObservable<T> {
95
- return new FromEventObservable(
96
- new DebugNameData(options.owner, options.debugName, options.debugReferenceFn ?? getValue),
97
- event,
98
- getValue, () => FromEventObservable.globalTransaction, options.equalsFn ?? strictEquals
99
- );
100
- }
101
-
102
- export class FromEventObservable<TArgs, T> extends BaseObservable<T> {
103
- public static globalTransaction: ITransaction | undefined;
104
-
105
- private value: T | undefined;
106
- private hasValue = false;
107
- private subscription: IDisposable | undefined;
108
-
109
- constructor(
110
- private readonly _debugNameData: DebugNameData,
111
- private readonly event: Event<TArgs>,
112
- public readonly _getValue: (args: TArgs | undefined) => T,
113
- private readonly _getTransaction: () => ITransaction | undefined,
114
- private readonly _equalityComparator: EqualityComparer<T>
115
- ) {
116
- super();
117
- }
118
-
119
- private getDebugName(): string | undefined {
120
- return this._debugNameData.getDebugName(this);
121
- }
122
-
123
- public get debugName(): string {
124
- const name = this.getDebugName();
125
- return 'From Event' + (name ? `: ${name}` : '');
126
- }
127
-
128
- protected override onFirstObserverAdded(): void {
129
- this.subscription = this.event(this.handleEvent);
130
- }
131
-
132
- private readonly handleEvent = (args: TArgs | undefined) => {
133
- const newValue = this._getValue(args);
134
- const oldValue = this.value;
135
-
136
- const didChange = !this.hasValue || !(this._equalityComparator(oldValue!, newValue));
137
- let didRunTransaction = false;
138
-
139
- if (didChange) {
140
- this.value = newValue;
141
-
142
- if (this.hasValue) {
143
- didRunTransaction = true;
144
- subtransaction(
145
- this._getTransaction(),
146
- (tx) => {
147
- getLogger()?.handleFromEventObservableTriggered(this, { oldValue, newValue, change: undefined, didChange, hadValue: this.hasValue });
148
-
149
- for (const o of this.observers) {
150
- tx.updateObserver(o, this);
151
- o.handleChange(this, undefined);
152
- }
153
- },
154
- () => {
155
- const name = this.getDebugName();
156
- return 'Event fired' + (name ? `: ${name}` : '');
157
- }
158
- );
159
- }
160
- this.hasValue = true;
161
- }
162
-
163
- if (!didRunTransaction) {
164
- getLogger()?.handleFromEventObservableTriggered(this, { oldValue, newValue, change: undefined, didChange, hadValue: this.hasValue });
165
- }
166
- };
167
-
168
- protected override onLastObserverRemoved(): void {
169
- this.subscription!.dispose();
170
- this.subscription = undefined;
171
- this.hasValue = false;
172
- this.value = undefined;
173
- }
174
-
175
- public get(): T {
176
- if (this.subscription) {
177
- if (!this.hasValue) {
178
- this.handleEvent(undefined);
179
- }
180
- return this.value!;
181
- } else {
182
- // no cache, as there are no subscribers to keep it updated
183
- const value = this._getValue(undefined);
184
- return value;
185
- }
186
- }
187
- }
188
-
189
- export namespace observableFromEvent {
190
- export const Observer = FromEventObservable;
191
-
192
- export function batchEventsGlobally(tx: ITransaction, fn: () => void): void {
193
- let didSet = false;
194
- if (FromEventObservable.globalTransaction === undefined) {
195
- FromEventObservable.globalTransaction = tx;
196
- didSet = true;
197
- }
198
- try {
199
- fn();
200
- } finally {
201
- if (didSet) {
202
- FromEventObservable.globalTransaction = undefined;
203
- }
204
- }
205
- }
206
- }
207
-
208
- export function observableSignalFromEvent(
209
- debugName: string,
210
- event: Event<any>
211
- ): IObservable<void> {
212
- return new FromEventObservableSignal(debugName, event);
213
- }
214
-
215
- class FromEventObservableSignal extends BaseObservable<void> {
216
- private subscription: IDisposable | undefined;
217
-
218
- constructor(
219
- public readonly debugName: string,
220
- private readonly event: Event<any>,
221
- ) {
222
- super();
223
- }
224
-
225
- protected override onFirstObserverAdded(): void {
226
- this.subscription = this.event(this.handleEvent);
227
- }
228
-
229
- private readonly handleEvent = () => {
230
- transaction(
231
- (tx) => {
232
- for (const o of this.observers) {
233
- tx.updateObserver(o, this);
234
- o.handleChange(this, undefined);
235
- }
236
- },
237
- () => this.debugName
238
- );
239
- };
240
-
241
- protected override onLastObserverRemoved(): void {
242
- this.subscription!.dispose();
243
- this.subscription = undefined;
244
- }
245
-
246
- public override get(): void {
247
- // NO OP
248
- }
249
- }
250
-
251
- /**
252
- * Creates a signal that can be triggered to invalidate observers.
253
- * Signals don't have a value - when they are triggered they indicate a change.
254
- * However, signals can carry a delta that is passed to observers.
255
- */
256
- export function observableSignal<TDelta = void>(debugName: string): IObservableSignal<TDelta>;
257
- export function observableSignal<TDelta = void>(owner: object): IObservableSignal<TDelta>;
258
- export function observableSignal<TDelta = void>(debugNameOrOwner: string | object): IObservableSignal<TDelta> {
259
- if (typeof debugNameOrOwner === 'string') {
260
- return new ObservableSignal<TDelta>(debugNameOrOwner);
261
- } else {
262
- return new ObservableSignal<TDelta>(undefined, debugNameOrOwner);
263
- }
264
- }
265
-
266
- export interface IObservableSignal<TChange> extends IObservable<void, TChange> {
267
- trigger(tx: ITransaction | undefined, change: TChange): void;
268
- }
269
-
270
- class ObservableSignal<TChange> extends BaseObservable<void, TChange> implements IObservableSignal<TChange> {
271
- public get debugName() {
272
- return new DebugNameData(this._owner, this._debugName, undefined).getDebugName(this) ?? 'Observable Signal';
273
- }
274
-
275
- public override toString(): string {
276
- return this.debugName;
277
- }
278
-
279
- constructor(
280
- private readonly _debugName: string | undefined,
281
- private readonly _owner?: object,
282
- ) {
283
- super();
284
- }
285
-
286
- public trigger(tx: ITransaction | undefined, change: TChange): void {
287
- if (!tx) {
288
- transaction(tx => {
289
- this.trigger(tx, change);
290
- }, () => `Trigger signal ${this.debugName}`);
291
- return;
292
- }
293
-
294
- for (const o of this.observers) {
295
- tx.updateObserver(o, this);
296
- o.handleChange(this, change);
297
- }
298
- }
299
-
300
- public override get(): void {
301
- // NO OP
302
- }
303
- }
304
-
305
- /**
306
- * @deprecated Use `debouncedObservable2` instead.
307
- */
308
- export function debouncedObservable<T>(observable: IObservable<T>, debounceMs: number, disposableStore: DisposableStore): IObservable<T | undefined> {
309
- const debouncedObservable = observableValue<T | undefined>('debounced', undefined);
310
-
311
- let timeout: any = undefined;
312
-
313
- disposableStore.add(autorun(reader => {
314
- /** @description debounce */
315
- const value = observable.read(reader);
316
-
317
- if (timeout) {
318
- clearTimeout(timeout);
319
- }
320
- timeout = setTimeout(() => {
321
- transaction(tx => {
322
- debouncedObservable.set(value, tx);
323
- });
324
- }, debounceMs);
325
-
326
- }));
327
-
328
- return debouncedObservable;
329
- }
330
-
331
- /**
332
- * Creates an observable that debounces the input observable.
333
- */
334
- export function debouncedObservable2<T>(observable: IObservable<T>, debounceMs: number): IObservable<T> {
335
- let hasValue = false;
336
- let lastValue: T | undefined;
337
-
338
- let timeout: any = undefined;
339
-
340
- return observableFromEvent<T, void>(cb => {
341
- const d = autorun(reader => {
342
- const value = observable.read(reader);
343
-
344
- if (!hasValue) {
345
- hasValue = true;
346
- lastValue = value;
347
- } else {
348
- if (timeout) {
349
- clearTimeout(timeout);
350
- }
351
- timeout = setTimeout(() => {
352
- lastValue = value;
353
- cb();
354
- }, debounceMs);
355
- }
356
- });
357
- return {
358
- dispose() {
359
- d.dispose();
360
- hasValue = false;
361
- lastValue = undefined;
362
- },
363
- };
364
- }, () => {
365
- if (hasValue) {
366
- return lastValue!;
367
- } else {
368
- return observable.get();
369
- }
370
- });
371
- }
372
-
373
- export function wasEventTriggeredRecently(event: Event<any>, timeoutMs: number, disposableStore: DisposableStore): IObservable<boolean> {
374
- const observable = observableValue('triggeredRecently', false);
375
-
376
- let timeout: any = undefined;
377
-
378
- disposableStore.add(event(() => {
379
- observable.set(true, undefined);
380
-
381
- if (timeout) {
382
- clearTimeout(timeout);
383
- }
384
- timeout = setTimeout(() => {
385
- observable.set(false, undefined);
386
- }, timeoutMs);
387
- }));
388
-
389
- return observable;
390
- }
391
-
392
- /**
393
- * This makes sure the observable is being observed and keeps its cache alive.
394
- */
395
- export function keepObserved<T>(observable: IObservable<T>): IDisposable {
396
- const o = new KeepAliveObserver(false, undefined);
397
- observable.addObserver(o);
398
- return toDisposable(() => {
399
- observable.removeObserver(o);
400
- });
401
- }
402
-
403
- _setKeepObserved(keepObserved);
404
-
405
- /**
406
- * This converts the given observable into an autorun.
407
- */
408
- export function recomputeInitiallyAndOnChange<T>(observable: IObservable<T>, handleValue?: (value: T) => void): IDisposable {
409
- const o = new KeepAliveObserver(true, handleValue);
410
- observable.addObserver(o);
411
- if (handleValue) {
412
- handleValue(observable.get());
413
- } else {
414
- observable.reportChanges();
415
- }
416
-
417
- return toDisposable(() => {
418
- observable.removeObserver(o);
419
- });
420
- }
421
-
422
- _setRecomputeInitiallyAndOnChange(recomputeInitiallyAndOnChange);
423
-
424
- export class KeepAliveObserver implements IObserver {
425
- private _counter = 0;
426
-
427
- constructor(
428
- private readonly _forceRecompute: boolean,
429
- private readonly _handleValue: ((value: any) => void) | undefined,
430
- ) { }
431
-
432
- beginUpdate<T>(observable: IObservable<T, void>): void {
433
- this._counter++;
434
- }
435
-
436
- endUpdate<T>(observable: IObservable<T, void>): void {
437
- this._counter--;
438
- if (this._counter === 0 && this._forceRecompute) {
439
- if (this._handleValue) {
440
- this._handleValue(observable.get());
441
- } else {
442
- observable.reportChanges();
443
- }
444
- }
445
- }
446
-
447
- handlePossibleChange<T>(observable: IObservable<T, unknown>): void {
448
- // NO OP
449
- }
450
-
451
- handleChange<T, TChange>(observable: IObservable<T, TChange>, change: TChange): void {
452
- // NO OP
453
- }
454
- }
455
-
456
- export function derivedObservableWithCache<T>(owner: DebugOwner, computeFn: (reader: IReader, lastValue: T | undefined) => T): IObservable<T> {
457
- let lastValue: T | undefined = undefined;
458
- const observable = derivedOpts({ owner, debugReferenceFn: computeFn }, reader => {
459
- lastValue = computeFn(reader, lastValue);
460
- return lastValue;
461
- });
462
- return observable;
463
- }
464
-
465
- export function derivedObservableWithWritableCache<T>(owner: object, computeFn: (reader: IReader, lastValue: T | undefined) => T): IObservable<T>
466
- & { clearCache(transaction: ITransaction): void; setCache(newValue: T | undefined, tx: ITransaction | undefined): void } {
467
- let lastValue: T | undefined = undefined;
468
- const onChange = observableSignal('derivedObservableWithWritableCache');
469
- const observable = derived(owner, reader => {
470
- onChange.read(reader);
471
- lastValue = computeFn(reader, lastValue);
472
- return lastValue;
473
- });
474
- return Object.assign(observable, {
475
- clearCache: (tx: ITransaction) => {
476
- lastValue = undefined;
477
- onChange.trigger(tx);
478
- },
479
- setCache: (newValue: T | undefined, tx: ITransaction | undefined) => {
480
- lastValue = newValue;
481
- onChange.trigger(tx);
482
- }
483
- });
484
- }
485
-
486
- /**
487
- * When the items array changes, referential equal items are not mapped again.
488
- */
489
- export function mapObservableArrayCached<TIn, TOut, TKey = TIn>(owner: DebugOwner, items: IObservable<readonly TIn[]>, map: (input: TIn, store: DisposableStore) => TOut, keySelector?: (input: TIn) => TKey): IObservable<readonly TOut[]> {
490
- let m = new ArrayMap(map, keySelector);
491
- const self = derivedOpts({
492
- debugReferenceFn: map,
493
- owner,
494
- onLastObserverRemoved: () => {
495
- m.dispose();
496
- m = new ArrayMap(map);
497
- }
498
- }, (reader) => {
499
- m.setItems(items.read(reader));
500
- return m.getItems();
501
- });
502
- return self;
503
- }
504
-
505
- class ArrayMap<TIn, TOut, TKey> implements IDisposable {
506
- private readonly _cache = new Map<TKey, { out: TOut; store: DisposableStore }>();
507
- private _items: TOut[] = [];
508
- constructor(
509
- private readonly _map: (input: TIn, store: DisposableStore) => TOut,
510
- private readonly _keySelector?: (input: TIn) => TKey,
511
- ) {
512
- }
513
-
514
- public dispose(): void {
515
- this._cache.forEach(entry => entry.store.dispose());
516
- this._cache.clear();
517
- }
518
-
519
- public setItems(items: readonly TIn[]): void {
520
- const newItems: TOut[] = [];
521
- const itemsToRemove = new Set(this._cache.keys());
522
-
523
- for (const item of items) {
524
- const key = this._keySelector ? this._keySelector(item) : item as unknown as TKey;
525
-
526
- let entry = this._cache.get(key);
527
- if (!entry) {
528
- const store = new DisposableStore();
529
- const out = this._map(item, store);
530
- entry = { out, store };
531
- this._cache.set(key, entry);
532
- } else {
533
- itemsToRemove.delete(key);
534
- }
535
- newItems.push(entry.out);
536
- }
537
-
538
- for (const item of itemsToRemove) {
539
- const entry = this._cache.get(item)!;
540
- entry.store.dispose();
541
- this._cache.delete(item);
542
- }
543
-
544
- this._items = newItems;
545
- }
546
-
547
- public getItems(): TOut[] {
548
- return this._items;
549
- }
550
- }
551
-
552
- export class ValueWithChangeEventFromObservable<T> implements IValueWithChangeEvent<T> {
553
- constructor(public readonly observable: IObservable<T>) {
554
- }
555
-
556
- get onDidChange(): Event<void> {
557
- return Event.fromObservableLight(this.observable);
558
- }
559
-
560
- get value(): T {
561
- return this.observable.get();
562
- }
563
- }
564
-
565
- export function observableFromValueWithChangeEvent<T>(owner: DebugOwner, value: IValueWithChangeEvent<T>): IObservable<T> {
566
- if (value instanceof ValueWithChangeEventFromObservable) {
567
- return value.observable;
568
- }
569
- return observableFromEvent(owner, value.onDidChange, () => value.value);
570
- }
571
-
572
- /**
573
- * Creates an observable that has the latest changed value of the given observables.
574
- * Initially (and when not observed), it has the value of the last observable.
575
- * When observed and any of the observables change, it has the value of the last changed observable.
576
- * If multiple observables change in the same transaction, the last observable wins.
577
- */
578
- export function latestChangedValue<T extends IObservable<any>[]>(owner: DebugOwner, observables: T): IObservable<ReturnType<T[number]['get']>> {
579
- if (observables.length === 0) {
580
- throw new BugIndicatingError();
581
- }
582
-
583
- let hasLastChangedValue = false;
584
- let lastChangedValue: any = undefined;
585
-
586
- const result = observableFromEvent<any, void>(owner, cb => {
587
- const store = new DisposableStore();
588
- for (const o of observables) {
589
- store.add(autorunOpts({ debugName: () => getDebugName(result, new DebugNameData(owner, undefined, undefined)) + '.updateLastChangedValue' }, reader => {
590
- hasLastChangedValue = true;
591
- lastChangedValue = o.read(reader);
592
- cb();
593
- }));
594
- }
595
- store.add({
596
- dispose() {
597
- hasLastChangedValue = false;
598
- lastChangedValue = undefined;
599
- },
600
- });
601
- return store;
602
- }, () => {
603
- if (hasLastChangedValue) {
604
- return lastChangedValue;
605
- } else {
606
- return observables[observables.length - 1].get();
607
- }
608
- });
609
- return result;
610
- }