@xterm/xterm 5.6.0-beta.99 → 6.0.0

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.
package/package.json CHANGED
@@ -1,13 +1,16 @@
1
1
  {
2
2
  "name": "@xterm/xterm",
3
3
  "description": "Full xterm terminal, in your browser",
4
- "version": "5.6.0-beta.99",
4
+ "version": "6.0.0",
5
5
  "main": "lib/xterm.js",
6
6
  "module": "lib/xterm.mjs",
7
7
  "style": "css/xterm.css",
8
8
  "types": "typings/xterm.d.ts",
9
9
  "repository": "https://github.com/xtermjs/xterm.js",
10
10
  "license": "MIT",
11
+ "workspaces": [
12
+ "addons/*"
13
+ ],
11
14
  "keywords": [
12
15
  "cli",
13
16
  "command-line",
@@ -25,8 +28,6 @@
25
28
  ],
26
29
  "scripts": {
27
30
  "setup": "npm run build",
28
- "presetup": "npm run install-addons",
29
- "install-addons": "node ./bin/install-addons.js",
30
31
  "start": "node demo/start",
31
32
  "build": "npm run tsc",
32
33
  "watch": "npm run tsc-watch",
@@ -42,6 +43,7 @@
42
43
  "test": "npm run test-unit",
43
44
  "posttest": "npm run lint",
44
45
  "lint": "eslint -c .eslintrc.json --max-warnings 0 --ext .ts src/ addons/",
46
+ "lint-fix": "eslint -c .eslintrc.json --fix --ext .ts src/ addons/",
45
47
  "lint-api": "eslint --no-eslintrc -c .eslintrc.json.typings --max-warnings 0 --no-ignore --ext .d.ts typings/",
46
48
  "test-unit": "node ./bin/test_unit.js",
47
49
  "test-unit-coverage": "node ./bin/test_unit.js --coverage",
@@ -73,7 +75,6 @@
73
75
  "@types/deep-equal": "^1.0.1",
74
76
  "@types/express": "4",
75
77
  "@types/express-ws": "^3.0.1",
76
- "@types/glob": "^7.2.0",
77
78
  "@types/jsdom": "^16.2.13",
78
79
  "@types/mocha": "^9.0.0",
79
80
  "@types/node": "^18.16.0",
@@ -86,16 +87,15 @@
86
87
  "chai": "^4.3.4",
87
88
  "cross-env": "^7.0.3",
88
89
  "deep-equal": "^2.0.5",
89
- "esbuild": "^0.23.0",
90
+ "esbuild": "~0.25.2",
90
91
  "eslint": "^8.56.0",
91
92
  "eslint-plugin-jsdoc": "^46.9.1",
92
93
  "express": "^4.19.2",
93
94
  "express-ws": "^5.0.2",
94
- "glob": "^7.2.0",
95
95
  "jsdom": "^18.0.1",
96
96
  "mocha": "^10.1.0",
97
97
  "mustache": "^4.2.0",
98
- "node-pty": "^1.1.0-beta31",
98
+ "node-pty": "1.1.0-beta19",
99
99
  "nyc": "^15.1.0",
100
100
  "source-map-loader": "^3.0.0",
101
101
  "source-map-support": "^0.5.20",
@@ -107,5 +107,5 @@
107
107
  "ws": "^8.2.3",
108
108
  "xterm-benchmark": "^0.3.1"
109
109
  },
110
- "commit": "a260f7d2889142d6566a66cb9856a07050dea611"
110
+ "commit": "f447274f430fd22513f6adbf9862d19524471c04"
111
111
  }
@@ -185,7 +185,7 @@ export class AccessibilityManager extends Disposable {
185
185
  const element = this._rowElements[i];
186
186
  if (element) {
187
187
  if (lineData.length === 0) {
188
- element.innerText = '\u00a0';
188
+ element.textContent = '\u00a0';
189
189
  this._rowColumns.set(element, [0, 1]);
190
190
  } else {
191
191
  element.textContent = lineData;
@@ -532,7 +532,13 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
532
532
  this.textarea!.focus();
533
533
  this.textarea!.select();
534
534
  }));
535
- this._register(this._onScroll.event(() => this._selectionService!.refresh()));
535
+ this._register(Event.any(
536
+ this._onScroll.event,
537
+ this._inputHandler.onScroll
538
+ )(() => {
539
+ this._selectionService!.refresh();
540
+ this._viewport?.queueSync();
541
+ }));
536
542
 
537
543
  this._register(this._instantiationService.createInstance(BufferDecorationRenderer, this.screenElement));
538
544
  this._register(addDisposableListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
@@ -640,6 +646,14 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
640
646
  if (deltaY === 0) {
641
647
  return false;
642
648
  }
649
+ const lines = self.coreMouseService.consumeWheelEvent(
650
+ ev as WheelEvent,
651
+ self._renderService?.dimensions?.device?.cell?.height,
652
+ self._coreBrowserService?.dpr
653
+ );
654
+ if (lines === 0) {
655
+ return false;
656
+ }
643
657
  action = deltaY < 0 ? CoreMouseAction.UP : CoreMouseAction.DOWN;
644
658
  but = CoreMouseButton.WHEEL;
645
659
  break;
@@ -811,6 +825,15 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
811
825
  return false;
812
826
  }
813
827
 
828
+ const lines = self.coreMouseService.consumeWheelEvent(
829
+ ev as WheelEvent,
830
+ self._renderService?.dimensions?.device?.cell?.height,
831
+ self._coreBrowserService?.dpr
832
+ );
833
+ if (lines === 0) {
834
+ return this.cancel(ev, true);
835
+ }
836
+
814
837
  // Construct and send sequences
815
838
  const sequence = C0.ESC + (this.coreService.decPrivateModes.applicationCursorKeys ? 'O' : '[') + (ev.deltaY < 0 ? 'A' : 'B');
816
839
  this.coreService.triggerDataEvent(sequence, true);
@@ -45,7 +45,7 @@ export class TimeBasedDebouncer implements IRenderDebouncer {
45
45
 
46
46
  // Only refresh if the time since last refresh is above a threshold, otherwise wait for
47
47
  // enough time to pass before refreshing again.
48
- const refreshRequestTime: number = Date.now();
48
+ const refreshRequestTime: number = performance.now();
49
49
  if (refreshRequestTime - this._lastRefreshMs >= this._debounceThresholdMS) {
50
50
  // Enough time has lapsed since the last refresh; refresh immediately
51
51
  this._lastRefreshMs = refreshRequestTime;
@@ -57,7 +57,7 @@ export class TimeBasedDebouncer implements IRenderDebouncer {
57
57
  this._additionalRefreshRequested = true;
58
58
 
59
59
  this._refreshTimeoutID = window.setTimeout(() => {
60
- this._lastRefreshMs = Date.now();
60
+ this._lastRefreshMs = performance.now();
61
61
  this._innerRefresh();
62
62
  this._additionalRefreshRequested = false;
63
63
  this._refreshTimeoutID = undefined; // No longer need to clear the timeout
@@ -93,8 +93,13 @@ export class Viewport extends Disposable {
93
93
  ].join('\n');
94
94
  }));
95
95
 
96
- this._register(this._bufferService.onResize(() => this._queueSync()));
97
- this._register(this._bufferService.buffers.onBufferActivate(() => this._queueSync()));
96
+ this._register(this._bufferService.onResize(() => this.queueSync()));
97
+ this._register(this._bufferService.buffers.onBufferActivate(() => {
98
+ // Reset _latestYDisp when switching buffers to prevent stale scroll position
99
+ // from alt buffer contaminating normal buffer scroll position
100
+ this._latestYDisp = undefined;
101
+ this.queueSync();
102
+ }));
98
103
  this._register(this._bufferService.onScroll(() => this._sync()));
99
104
 
100
105
  this._register(this._scrollableElement.onScroll(e => this._handleScroll(e)));
@@ -126,7 +131,7 @@ export class Viewport extends Disposable {
126
131
  };
127
132
  }
128
133
 
129
- private _queueSync(ydisp?: number): void {
134
+ public queueSync(ydisp?: number): void {
130
135
  // Update state
131
136
  if (ydisp !== undefined) {
132
137
  this._latestYDisp = ydisp;
@@ -157,7 +162,7 @@ export class Viewport extends Disposable {
157
162
  });
158
163
  this._suppressOnScrollHandler = false;
159
164
 
160
- // If ydisp has been changed by some other copmonent (input/buffer), then stop animating smooth
165
+ // If ydisp has been changed by some other component (input/buffer), then stop animating smooth
161
166
  // scroll and scroll there immediately.
162
167
  if (ydisp !== this._latestYDisp) {
163
168
  this._scrollableElement.setScrollPosition({
@@ -199,7 +199,9 @@ function bufferLine(
199
199
  let currentRow = startRow;
200
200
  let bufferStr = '';
201
201
 
202
- while (currentCol !== endCol || currentRow !== endRow) {
202
+ while ((currentCol !== endCol || currentRow !== endRow) &&
203
+ currentRow >= 0 &&
204
+ currentRow < bufferService.buffer.lines.length) {
203
205
  currentCol += forward ? 1 : -1;
204
206
 
205
207
  if (forward && currentCol > bufferService.cols - 1) {
@@ -123,6 +123,7 @@ export class Terminal extends Disposable implements ITerminalApi {
123
123
  originMode: m.origin,
124
124
  reverseWraparoundMode: m.reverseWraparound,
125
125
  sendFocusMode: m.sendFocus,
126
+ synchronizedOutputMode: m.synchronizedOutput,
126
127
  wraparoundMode: m.wraparound
127
128
  };
128
129
  }
@@ -9,7 +9,7 @@ import { IRenderDimensions, IRenderer } from 'browser/renderer/shared/Types';
9
9
  import { ICharSizeService, ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services';
10
10
  import { Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
11
11
  import { DebouncedIdleTask } from 'common/TaskQueue';
12
- import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services';
12
+ import { IBufferService, ICoreService, IDecorationService, IOptionsService } from 'common/services/Services';
13
13
  import { Emitter } from 'vs/base/common/event';
14
14
 
15
15
  interface ISelectionState {
@@ -18,6 +18,10 @@ interface ISelectionState {
18
18
  columnSelectMode: boolean;
19
19
  }
20
20
 
21
+ const enum Constants {
22
+ SYNCHRONIZED_OUTPUT_TIMEOUT_MS = 1000
23
+ }
24
+
21
25
  export class RenderService extends Disposable implements IRenderService {
22
26
  public serviceBrand: undefined;
23
27
 
@@ -32,6 +36,7 @@ export class RenderService extends Disposable implements IRenderService {
32
36
  private _needsSelectionRefresh: boolean = false;
33
37
  private _canvasWidth: number = 0;
34
38
  private _canvasHeight: number = 0;
39
+ private _syncOutputHandler: SynchronizedOutputHandler;
35
40
  private _selectionState: ISelectionState = {
36
41
  start: undefined,
37
42
  end: undefined,
@@ -52,23 +57,31 @@ export class RenderService extends Disposable implements IRenderService {
52
57
  constructor(
53
58
  private _rowCount: number,
54
59
  screenElement: HTMLElement,
55
- @IOptionsService optionsService: IOptionsService,
60
+ @IOptionsService private readonly _optionsService: IOptionsService,
56
61
  @ICharSizeService private readonly _charSizeService: ICharSizeService,
62
+ @ICoreService private readonly _coreService: ICoreService,
57
63
  @IDecorationService decorationService: IDecorationService,
58
64
  @IBufferService bufferService: IBufferService,
59
- @ICoreBrowserService coreBrowserService: ICoreBrowserService,
65
+ @ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService,
60
66
  @IThemeService themeService: IThemeService
61
67
  ) {
62
68
  super();
63
69
 
64
- this._renderDebouncer = new RenderDebouncer((start, end) => this._renderRows(start, end), coreBrowserService);
70
+ this._renderDebouncer = new RenderDebouncer((start, end) => this._renderRows(start, end), this._coreBrowserService);
65
71
  this._register(this._renderDebouncer);
66
72
 
67
- this._register(coreBrowserService.onDprChange(() => this.handleDevicePixelRatioChange()));
73
+ this._syncOutputHandler = new SynchronizedOutputHandler(
74
+ this._coreBrowserService,
75
+ this._coreService,
76
+ () => this._fullRefresh()
77
+ );
78
+ this._register(toDisposable(() => this._syncOutputHandler.dispose()));
79
+
80
+ this._register(this._coreBrowserService.onDprChange(() => this.handleDevicePixelRatioChange()));
68
81
 
69
82
  this._register(bufferService.onResize(() => this._fullRefresh()));
70
83
  this._register(bufferService.buffers.onBufferActivate(() => this._renderer.value?.clear()));
71
- this._register(optionsService.onOptionChange(() => this._handleOptionsChanged()));
84
+ this._register(this._optionsService.onOptionChange(() => this._handleOptionsChanged()));
72
85
  this._register(this._charSizeService.onCharSizeChange(() => this.handleCharSizeChanged()));
73
86
 
74
87
  // Do a full refresh whenever any decoration is added or removed. This may not actually result
@@ -78,7 +91,7 @@ export class RenderService extends Disposable implements IRenderService {
78
91
  this._register(decorationService.onDecorationRemoved(() => this._fullRefresh()));
79
92
 
80
93
  // Clear the renderer when the a change that could affect glyphs occurs
81
- this._register(optionsService.onMultipleOptionChange([
94
+ this._register(this._optionsService.onMultipleOptionChange([
82
95
  'customGlyphs',
83
96
  'drawBoldTextInBrightColors',
84
97
  'letterSpacing',
@@ -96,15 +109,15 @@ export class RenderService extends Disposable implements IRenderService {
96
109
  }));
97
110
 
98
111
  // Refresh the cursor line when the cursor changes
99
- this._register(optionsService.onMultipleOptionChange([
112
+ this._register(this._optionsService.onMultipleOptionChange([
100
113
  'cursorBlink',
101
114
  'cursorStyle'
102
115
  ], () => this.refreshRows(bufferService.buffer.y, bufferService.buffer.y, true)));
103
116
 
104
117
  this._register(themeService.onChangeColors(() => this._fullRefresh()));
105
118
 
106
- this._registerIntersectionObserver(coreBrowserService.window, screenElement);
107
- this._register(coreBrowserService.onWindowChange((w) => this._registerIntersectionObserver(w, screenElement)));
119
+ this._registerIntersectionObserver(this._coreBrowserService.window, screenElement);
120
+ this._register(this._coreBrowserService.onWindowChange((w) => this._registerIntersectionObserver(w, screenElement)));
108
121
  }
109
122
 
110
123
  private _registerIntersectionObserver(w: Window & typeof globalThis, screenElement: HTMLElement): void {
@@ -137,6 +150,18 @@ export class RenderService extends Disposable implements IRenderService {
137
150
  this._needsFullRefresh = true;
138
151
  return;
139
152
  }
153
+
154
+ if (this._coreService.decPrivateModes.synchronizedOutput) {
155
+ this._syncOutputHandler.bufferRows(start, end);
156
+ return;
157
+ }
158
+
159
+ const buffered = this._syncOutputHandler.flush();
160
+ if (buffered) {
161
+ start = Math.min(start, buffered.start);
162
+ end = Math.max(end, buffered.end);
163
+ }
164
+
140
165
  if (!isRedrawOnly) {
141
166
  this._isNextRenderRedrawOnly = false;
142
167
  }
@@ -148,6 +173,13 @@ export class RenderService extends Disposable implements IRenderService {
148
173
  return;
149
174
  }
150
175
 
176
+ // Skip rendering if synchronized output mode is enabled. This check must happen here
177
+ // (in addition to refreshRows) to handle renders that were queued before the mode was enabled.
178
+ if (this._coreService.decPrivateModes.synchronizedOutput) {
179
+ this._syncOutputHandler.bufferRows(start, end);
180
+ return;
181
+ }
182
+
151
183
  // Since this is debounced, a resize event could have happened between the time a refresh was
152
184
  // requested and when this triggers. Clamp the values of start and end to ensure they're valid
153
185
  // given the current viewport state.
@@ -283,3 +315,62 @@ export class RenderService extends Disposable implements IRenderService {
283
315
  this._renderer.value?.clear();
284
316
  }
285
317
  }
318
+
319
+ /**
320
+ * Buffers row refresh requests during synchronized output mode (DEC mode 2026).
321
+ * When the mode is disabled, the accumulated row range is flushed for rendering.
322
+ * A safety timeout ensures rendering occurs even if the end sequence is not received.
323
+ */
324
+ class SynchronizedOutputHandler {
325
+ private _start: number = 0;
326
+ private _end: number = 0;
327
+ private _timeout: number | undefined;
328
+ private _isBuffering: boolean = false;
329
+
330
+ constructor(
331
+ private readonly _coreBrowserService: ICoreBrowserService,
332
+ private readonly _coreService: ICoreService,
333
+ private readonly _onTimeout: () => void
334
+ ) {}
335
+
336
+ public bufferRows(start: number, end: number): void {
337
+ if (!this._isBuffering) {
338
+ this._start = start;
339
+ this._end = end;
340
+ this._isBuffering = true;
341
+ } else {
342
+ this._start = Math.min(this._start, start);
343
+ this._end = Math.max(this._end, end);
344
+ }
345
+
346
+ if (this._timeout === undefined) {
347
+ this._timeout = this._coreBrowserService.window.setTimeout(() => {
348
+ this._timeout = undefined;
349
+ this._coreService.decPrivateModes.synchronizedOutput = false;
350
+ this._onTimeout();
351
+ }, Constants.SYNCHRONIZED_OUTPUT_TIMEOUT_MS);
352
+ }
353
+ }
354
+
355
+ public flush(): { start: number, end: number } | undefined {
356
+ if (this._timeout !== undefined) {
357
+ this._coreBrowserService.window.clearTimeout(this._timeout);
358
+ this._timeout = undefined;
359
+ }
360
+
361
+ if (!this._isBuffering) {
362
+ return undefined;
363
+ }
364
+
365
+ const result = { start: this._start, end: this._end };
366
+ this._isBuffering = false;
367
+ return result;
368
+ }
369
+
370
+ public dispose(): void {
371
+ if (this._timeout !== undefined) {
372
+ this._coreBrowserService.window.clearTimeout(this._timeout);
373
+ this._timeout = undefined;
374
+ }
375
+ }
376
+ }
@@ -152,6 +152,14 @@ export class SelectionService extends Disposable implements ISelectionService {
152
152
  this._register(toDisposable(() => {
153
153
  this._removeMouseDownListeners();
154
154
  }));
155
+
156
+ // Clear selection when resizing vertically. This experience could be improved, this is the
157
+ // simple option to fix the buggy behavior. https://github.com/xtermjs/xterm.js/issues/5300
158
+ this._register(this._bufferService.onResize(e => {
159
+ if (e.rowsChanged) {
160
+ this.clearSelection();
161
+ }
162
+ }));
155
163
  }
156
164
 
157
165
  public reset(): void {
@@ -445,7 +445,10 @@ export class InputHandler extends Disposable implements IInputHandler {
445
445
 
446
446
  // Log debug data, the log level gate is to prevent extra work in this hot path
447
447
  if (this._logService.logLevel <= LogLevelEnum.DEBUG) {
448
- this._logService.debug(`parsing data${typeof data === 'string' ? ` "${data}"` : ` "${Array.prototype.map.call(data, e => String.fromCharCode(e)).join('')}"`}`, typeof data === 'string'
448
+ this._logService.debug(`parsing data ${typeof data === 'string' ? ` "${data}"` : ` "${Array.prototype.map.call(data, e => String.fromCharCode(e)).join('')}"`}`);
449
+ }
450
+ if (this._logService.logLevel === LogLevelEnum.TRACE) {
451
+ this._logService.trace(`parsing data (codes)`, typeof data === 'string'
449
452
  ? data.split('').map(e => e.charCodeAt(0))
450
453
  : data
451
454
  );
@@ -606,7 +609,7 @@ export class InputHandler extends Disposable implements IInputHandler {
606
609
  // since an empty cell is only set by fullwidth chars
607
610
  bufferRow.addCodepointToCell(this._activeBuffer.x - offset,
608
611
  code, chWidth);
609
- for (let delta = chWidth - oldWidth; --delta >= 0; ) {
612
+ for (let delta = chWidth - oldWidth; --delta >= 0;) {
610
613
  bufferRow.setCellFromCodepoint(this._activeBuffer.x++, 0, 0, curAttr);
611
614
  }
612
615
  continue;
@@ -1220,12 +1223,27 @@ export class InputHandler extends Disposable implements IInputHandler {
1220
1223
  this._dirtyRowTracker.markDirty(0);
1221
1224
  break;
1222
1225
  case 2:
1223
- j = this._bufferService.rows;
1224
- this._dirtyRowTracker.markDirty(j - 1);
1225
- while (j--) {
1226
- this._resetBufferLine(j, respectProtect);
1226
+ if (this._optionsService.rawOptions.scrollOnEraseInDisplay) {
1227
+ j = this._bufferService.rows;
1228
+ this._dirtyRowTracker.markRangeDirty(0, j - 1);
1229
+ while (j--) {
1230
+ const currentLine = this._activeBuffer.lines.get(this._activeBuffer.ybase + j);
1231
+ if (currentLine?.getTrimmedLength()) {
1232
+ break;
1233
+ }
1234
+ }
1235
+ for (; j >= 0; j--) {
1236
+ this._bufferService.scroll(this._eraseAttrData());
1237
+ }
1238
+ }
1239
+ else {
1240
+ j = this._bufferService.rows;
1241
+ this._dirtyRowTracker.markDirty(j - 1);
1242
+ while (j--) {
1243
+ this._resetBufferLine(j, respectProtect);
1244
+ }
1245
+ this._dirtyRowTracker.markDirty(0);
1227
1246
  }
1228
- this._dirtyRowTracker.markDirty(0);
1229
1247
  break;
1230
1248
  case 3:
1231
1249
  // Clear scrollback (everything not in viewport)
@@ -1607,7 +1625,7 @@ export class InputHandler extends Disposable implements IInputHandler {
1607
1625
  const text = bufferRow.getString(x);
1608
1626
  const data = new Uint32Array(text.length * length);
1609
1627
  let idata = 0;
1610
- for (let itext = 0; itext < text.length; ) {
1628
+ for (let itext = 0; itext < text.length;) {
1611
1629
  const ch = text.codePointAt(itext) || 0;
1612
1630
  data[idata++] = ch;
1613
1631
  itext += ch > 0xffff ? 2 : 1;
@@ -1951,6 +1969,9 @@ export class InputHandler extends Disposable implements IInputHandler {
1951
1969
  case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste)
1952
1970
  this._coreService.decPrivateModes.bracketedPasteMode = true;
1953
1971
  break;
1972
+ case 2026: // synchronized output (https://github.com/contour-terminal/vt-extensions/blob/master/synchronized-output.md)
1973
+ this._coreService.decPrivateModes.synchronizedOutput = true;
1974
+ break;
1954
1975
  }
1955
1976
  }
1956
1977
  return true;
@@ -2179,6 +2200,10 @@ export class InputHandler extends Disposable implements IInputHandler {
2179
2200
  case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste)
2180
2201
  this._coreService.decPrivateModes.bracketedPasteMode = false;
2181
2202
  break;
2203
+ case 2026: // synchronized output (https://github.com/contour-terminal/vt-extensions/blob/master/synchronized-output.md)
2204
+ this._coreService.decPrivateModes.synchronizedOutput = false;
2205
+ this._onRequestRefreshRows.fire(undefined);
2206
+ break;
2182
2207
  }
2183
2208
  }
2184
2209
  return true;
@@ -2273,6 +2298,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2273
2298
  if (p === 1048) return f(p, V.SET); // xterm always returns SET here
2274
2299
  if (p === 47 || p === 1047 || p === 1049) return f(p, b2v(active === alt));
2275
2300
  if (p === 2004) return f(p, b2v(dm.bracketedPasteMode));
2301
+ if (p === 2026) return f(p, b2v(dm.synchronizedOutput));
2276
2302
  return f(p, V.NOT_RECOGNIZED);
2277
2303
  }
2278
2304
 
@@ -74,14 +74,14 @@ abstract class TaskQueue implements ITaskQueue {
74
74
  let lastDeadlineRemaining = deadline.timeRemaining();
75
75
  let deadlineRemaining = 0;
76
76
  while (this._i < this._tasks.length) {
77
- taskDuration = Date.now();
77
+ taskDuration = performance.now();
78
78
  if (!this._tasks[this._i]()) {
79
79
  this._i++;
80
80
  }
81
- // other than performance.now, Date.now might not be stable (changes on wall clock changes),
82
- // this is not an issue here as a clock change during a short running task is very unlikely
83
- // in case it still happened and leads to negative duration, simply assume 1 msec
84
- taskDuration = Math.max(1, Date.now() - taskDuration);
81
+ // other than performance.now, performance.now might not be stable (changes on wall clock
82
+ // changes), this is not an issue here as a clock change during a short running task is very
83
+ // unlikely in case it still happened and leads to negative duration, simply assume 1 msec
84
+ taskDuration = Math.max(1, performance.now() - taskDuration);
85
85
  longestTask = Math.max(taskDuration, longestTask);
86
86
  // Guess the following task will take a similar time to the longest task in this batch, allow
87
87
  // additional room to try avoid exceeding the deadline
@@ -116,9 +116,9 @@ export class PriorityTaskQueue extends TaskQueue {
116
116
  }
117
117
 
118
118
  private _createDeadline(duration: number): ITaskDeadline {
119
- const end = Date.now() + duration;
119
+ const end = performance.now() + duration;
120
120
  return {
121
- timeRemaining: () => Math.max(0, end - Date.now())
121
+ timeRemaining: () => Math.max(0, end - performance.now())
122
122
  };
123
123
  }
124
124
  }
@@ -273,6 +273,7 @@ export interface IDecPrivateModes {
273
273
  origin: boolean;
274
274
  reverseWraparound: boolean;
275
275
  sendFocus: boolean;
276
+ synchronizedOutput: boolean;
276
277
  wraparound: boolean; // defaults: xterm - true, vt100 - false
277
278
  }
278
279
 
@@ -320,37 +320,7 @@ export class Buffer implements IBuffer {
320
320
  if (toRemove.length > 0) {
321
321
  const newLayoutResult = reflowLargerCreateNewLayout(this.lines, toRemove);
322
322
  reflowLargerApplyNewLayout(this.lines, newLayoutResult.layout);
323
-
324
- // For conpty, it has its own copy of the buffer _without scrollback_ internally. Its behavior
325
- // when reflowing larger is to insert empty lines at the bottom of the buffer as when lines
326
- // unwrap conpty's view cannot pull scrollback down, so it adds empty lines at the end.
327
- let removedInViewport = 0;
328
- const isWindowsMode = this._optionsService.rawOptions.windowsMode || this._optionsService.rawOptions.windowsPty.backend !== undefined || this._optionsService.rawOptions.windowsPty.buildNumber !== undefined;
329
- if (isWindowsMode) {
330
- for (let i = (toRemove.length / 2) - 1; i >= 0; i--) {
331
- if (toRemove[i * 2 + 0] > this.ybase + removedInViewport) {
332
- removedInViewport += toRemove[i * 2 + 1];
333
- }
334
- }
335
- }
336
-
337
323
  this._reflowLargerAdjustViewport(newCols, newRows, newLayoutResult.countRemoved);
338
-
339
- // Apply empty lines for any removed in viewport for conpty.
340
- if (isWindowsMode) {
341
- if (removedInViewport > 0) {
342
- for (let i = 0; i < removedInViewport; i++) {
343
- // Just add the new missing rows on Windows as conpty reprints the screen with it's
344
- // view of the world. Once a line enters scrollback for conpty it remains there
345
- this.lines.push(new BufferLine(newCols, this.getNullCell(DEFAULT_ATTR_DATA)));
346
- }
347
- if (this.ybase === this.ydisp) {
348
- this.ydisp += removedInViewport;
349
- }
350
- this.ybase += removedInViewport;
351
- this.y -= removedInViewport;
352
- }
353
- }
354
324
  }
355
325
  }
356
326
 
@@ -382,7 +352,7 @@ export class Buffer implements IBuffer {
382
352
  const nullCell = this.getNullCell(DEFAULT_ATTR_DATA);
383
353
  // Gather all BufferLines that need to be inserted into the Buffer here so that they can be
384
354
  // batched up and only committed once
385
- const toInsert: { start: number, newLines: IBufferLine[] }[] = [];
355
+ const toInsert = [];
386
356
  let countToInsert = 0;
387
357
  // Go backwards as many lines may be trimmed and this will avoid considering them
388
358
  for (let y = this.lines.length - 1; y >= 0; y--) {
@@ -497,20 +467,6 @@ export class Buffer implements IBuffer {
497
467
  this.savedY = Math.min(this.savedY + linesToAdd, this.ybase + newRows - 1);
498
468
  }
499
469
 
500
- // For conpty, it has its own copy of the buffer _without scrollback_ internally. Its behavior
501
- // when reflowing smaller is to reflow all lines inside the viewport, and removing empty or
502
- // whitespace only lines from the bottom, until non-whitespace is hit in order to prevent
503
- // content from being pushed into the scrollback.
504
- let addedInViewport = 0;
505
- const isWindowsMode = this._optionsService.rawOptions.windowsMode || this._optionsService.rawOptions.windowsPty.backend !== undefined || this._optionsService.rawOptions.windowsPty.buildNumber !== undefined;
506
- if (isWindowsMode) {
507
- for (let i = toInsert.length - 1; i >= 0; i--) {
508
- if (toInsert[i].start > this.ybase + addedInViewport) {
509
- addedInViewport += toInsert[i].newLines.length;
510
- }
511
- }
512
- }
513
-
514
470
  // Rearrange lines in the buffer if there are any insertions, this is done at the end rather
515
471
  // than earlier so that it's a single O(n) pass through the buffer, instead of O(n^2) from many
516
472
  // costly calls to CircularList.splice.
@@ -564,35 +520,6 @@ export class Buffer implements IBuffer {
564
520
  this.lines.onTrimEmitter.fire(amountToTrim);
565
521
  }
566
522
  }
567
-
568
- // Apply empty lines to remove calculated earlier for conpty.
569
- if (isWindowsMode) {
570
- if (addedInViewport > 0) {
571
- let emptyLinesAtBottom = 0;
572
- for (let i = this.lines.length - 1; i >= this.ybase + this.y; i--) {
573
- const line = this.lines.get(i) as BufferLine;
574
- if (line.isWrapped || line.getTrimmedLength() > 0) {
575
- break;
576
- }
577
- emptyLinesAtBottom++;
578
- }
579
- const emptyLinesToRemove = Math.min(addedInViewport, emptyLinesAtBottom);
580
- if (emptyLinesToRemove > 0) {
581
- for (let i = 0; i < emptyLinesToRemove; i++) {
582
- this.lines.pop();
583
- }
584
- if (this.ybase === this.ydisp) {
585
- this.ydisp -= emptyLinesToRemove;
586
- }
587
- this.ybase -= emptyLinesToRemove;
588
- this.y += emptyLinesToRemove;
589
- this.lines.onDeleteEmitter.fire({
590
- index: this.lines.length - emptyLinesToRemove,
591
- amount: emptyLinesToRemove
592
- });
593
- }
594
- }
595
- }
596
523
  }
597
524
 
598
525
  /**