@xterm/xterm 6.1.0-beta.16 → 6.1.0-beta.161

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 (155) hide show
  1. package/README.md +27 -28
  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 +28 -17
  8. package/src/browser/AccessibilityManager.ts +6 -3
  9. package/src/browser/CoreBrowserTerminal.ts +142 -62
  10. package/src/browser/Dom.ts +178 -0
  11. package/src/browser/Linkifier.ts +3 -3
  12. package/src/browser/OscLinkProvider.ts +3 -1
  13. package/src/browser/RenderDebouncer.ts +2 -2
  14. package/src/browser/TimeBasedDebouncer.ts +2 -2
  15. package/src/browser/Types.ts +12 -11
  16. package/src/browser/Viewport.ts +40 -17
  17. package/src/browser/decorations/BufferDecorationRenderer.ts +1 -1
  18. package/src/browser/decorations/OverviewRulerRenderer.ts +15 -16
  19. package/src/browser/input/CompositionHelper.ts +10 -1
  20. package/src/browser/public/Terminal.ts +24 -27
  21. package/src/browser/renderer/dom/DomRenderer.ts +128 -8
  22. package/src/browser/renderer/dom/DomRendererRowFactory.ts +19 -13
  23. package/src/browser/renderer/dom/WidthCache.ts +54 -52
  24. package/src/browser/renderer/shared/Constants.ts +7 -0
  25. package/src/browser/renderer/shared/TextBlinkStateManager.ts +97 -0
  26. package/src/browser/renderer/shared/Types.ts +8 -2
  27. package/src/browser/scrollable/abstractScrollbar.ts +300 -0
  28. package/src/browser/scrollable/fastDomNode.ts +126 -0
  29. package/src/browser/scrollable/globalPointerMoveMonitor.ts +90 -0
  30. package/src/browser/scrollable/horizontalScrollbar.ts +85 -0
  31. package/src/browser/scrollable/mouseEvent.ts +292 -0
  32. package/src/browser/scrollable/scrollable.ts +486 -0
  33. package/src/browser/scrollable/scrollableElement.ts +579 -0
  34. package/src/browser/scrollable/scrollableElementOptions.ts +161 -0
  35. package/src/browser/scrollable/scrollbarArrow.ts +110 -0
  36. package/src/browser/scrollable/scrollbarState.ts +246 -0
  37. package/src/browser/scrollable/scrollbarVisibilityController.ts +113 -0
  38. package/src/browser/scrollable/touch.ts +481 -0
  39. package/src/browser/scrollable/verticalScrollbar.ts +143 -0
  40. package/src/browser/scrollable/widget.ts +23 -0
  41. package/src/browser/services/CharSizeService.ts +2 -2
  42. package/src/browser/services/CoreBrowserService.ts +4 -4
  43. package/src/browser/services/KeyboardService.ts +67 -0
  44. package/src/browser/services/LinkProviderService.ts +1 -1
  45. package/src/browser/services/MouseService.ts +2 -1
  46. package/src/browser/services/RenderService.ts +22 -15
  47. package/src/browser/services/SelectionService.ts +12 -4
  48. package/src/browser/services/Services.ts +24 -15
  49. package/src/browser/services/ThemeService.ts +2 -2
  50. package/src/common/Async.ts +105 -0
  51. package/src/common/CircularList.ts +2 -2
  52. package/src/common/Color.ts +8 -0
  53. package/src/common/CoreTerminal.ts +21 -11
  54. package/src/common/Event.ts +118 -0
  55. package/src/common/InputHandler.ts +244 -24
  56. package/src/common/Lifecycle.ts +113 -0
  57. package/src/common/Platform.ts +13 -3
  58. package/src/common/SortedList.ts +7 -3
  59. package/src/common/TaskQueue.ts +9 -3
  60. package/src/common/Types.ts +27 -7
  61. package/src/common/Version.ts +9 -0
  62. package/src/common/buffer/Buffer.ts +20 -14
  63. package/src/common/buffer/BufferLine.ts +4 -5
  64. package/src/common/buffer/BufferSet.ts +7 -6
  65. package/src/common/buffer/CellData.ts +57 -0
  66. package/src/common/buffer/Marker.ts +2 -2
  67. package/src/common/buffer/Types.ts +6 -2
  68. package/src/common/data/EscapeSequences.ts +71 -70
  69. package/src/common/input/Keyboard.ts +7 -6
  70. package/src/common/input/KittyKeyboard.ts +491 -0
  71. package/src/common/input/Win32InputMode.ts +297 -0
  72. package/src/common/input/WriteBuffer.ts +34 -2
  73. package/src/common/input/XParseColor.ts +2 -2
  74. package/src/common/parser/ApcParser.ts +245 -0
  75. package/src/common/parser/Constants.ts +22 -4
  76. package/src/common/parser/DcsParser.ts +5 -5
  77. package/src/common/parser/EscapeSequenceParser.ts +75 -22
  78. package/src/common/parser/OscParser.ts +5 -5
  79. package/src/common/parser/Types.ts +34 -1
  80. package/src/common/public/BufferLineApiView.ts +2 -2
  81. package/src/common/public/BufferNamespaceApi.ts +2 -2
  82. package/src/common/public/ParserApi.ts +3 -0
  83. package/src/common/services/BufferService.ts +8 -5
  84. package/src/common/services/CharsetService.ts +4 -0
  85. package/src/common/services/CoreMouseService.ts +2 -2
  86. package/src/common/services/CoreService.ts +18 -4
  87. package/src/common/services/DecorationService.ts +24 -8
  88. package/src/common/services/LogService.ts +1 -31
  89. package/src/common/services/OptionsService.ts +13 -4
  90. package/src/common/services/Services.ts +39 -16
  91. package/src/common/services/UnicodeService.ts +1 -1
  92. package/typings/xterm.d.ts +319 -35
  93. package/src/common/TypedArrayUtils.ts +0 -17
  94. package/src/vs/base/browser/browser.ts +0 -141
  95. package/src/vs/base/browser/canIUse.ts +0 -49
  96. package/src/vs/base/browser/dom.ts +0 -2369
  97. package/src/vs/base/browser/fastDomNode.ts +0 -316
  98. package/src/vs/base/browser/globalPointerMoveMonitor.ts +0 -112
  99. package/src/vs/base/browser/iframe.ts +0 -135
  100. package/src/vs/base/browser/keyboardEvent.ts +0 -213
  101. package/src/vs/base/browser/mouseEvent.ts +0 -229
  102. package/src/vs/base/browser/touch.ts +0 -372
  103. package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +0 -303
  104. package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +0 -114
  105. package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +0 -720
  106. package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +0 -165
  107. package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +0 -114
  108. package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +0 -243
  109. package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +0 -118
  110. package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +0 -116
  111. package/src/vs/base/browser/ui/widget.ts +0 -57
  112. package/src/vs/base/browser/window.ts +0 -14
  113. package/src/vs/base/common/arrays.ts +0 -887
  114. package/src/vs/base/common/arraysFind.ts +0 -202
  115. package/src/vs/base/common/assert.ts +0 -71
  116. package/src/vs/base/common/async.ts +0 -1992
  117. package/src/vs/base/common/cancellation.ts +0 -148
  118. package/src/vs/base/common/charCode.ts +0 -450
  119. package/src/vs/base/common/collections.ts +0 -140
  120. package/src/vs/base/common/decorators.ts +0 -130
  121. package/src/vs/base/common/equals.ts +0 -146
  122. package/src/vs/base/common/errors.ts +0 -303
  123. package/src/vs/base/common/event.ts +0 -1778
  124. package/src/vs/base/common/functional.ts +0 -32
  125. package/src/vs/base/common/hash.ts +0 -316
  126. package/src/vs/base/common/iterator.ts +0 -159
  127. package/src/vs/base/common/keyCodes.ts +0 -526
  128. package/src/vs/base/common/keybindings.ts +0 -284
  129. package/src/vs/base/common/lazy.ts +0 -47
  130. package/src/vs/base/common/lifecycle.ts +0 -801
  131. package/src/vs/base/common/linkedList.ts +0 -142
  132. package/src/vs/base/common/map.ts +0 -202
  133. package/src/vs/base/common/numbers.ts +0 -98
  134. package/src/vs/base/common/observable.ts +0 -76
  135. package/src/vs/base/common/observableInternal/api.ts +0 -31
  136. package/src/vs/base/common/observableInternal/autorun.ts +0 -281
  137. package/src/vs/base/common/observableInternal/base.ts +0 -489
  138. package/src/vs/base/common/observableInternal/debugName.ts +0 -145
  139. package/src/vs/base/common/observableInternal/derived.ts +0 -428
  140. package/src/vs/base/common/observableInternal/lazyObservableValue.ts +0 -146
  141. package/src/vs/base/common/observableInternal/logging.ts +0 -328
  142. package/src/vs/base/common/observableInternal/promise.ts +0 -209
  143. package/src/vs/base/common/observableInternal/utils.ts +0 -610
  144. package/src/vs/base/common/platform.ts +0 -281
  145. package/src/vs/base/common/scrollable.ts +0 -522
  146. package/src/vs/base/common/sequence.ts +0 -34
  147. package/src/vs/base/common/stopwatch.ts +0 -43
  148. package/src/vs/base/common/strings.ts +0 -557
  149. package/src/vs/base/common/symbols.ts +0 -9
  150. package/src/vs/base/common/uint.ts +0 -59
  151. package/src/vs/patches/nls.ts +0 -90
  152. package/src/vs/typings/base-common.d.ts +0 -20
  153. package/src/vs/typings/require.d.ts +0 -42
  154. package/src/vs/typings/vscode-globals-nls.d.ts +0 -36
  155. 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
- }