@xterm/xterm 6.1.0-beta.19 → 6.1.0-beta.191

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