From 44388e5e6c206c272c9d2370b85235dee6a729bf Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 28 Sep 2022 08:55:29 -0700 Subject: [PATCH 1/2] Use microtask to flush the write buffer after input Fixes #4158 --- src/common/CoreTerminal.ts | 1 + src/common/input/WriteBuffer.ts | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts index d7cb0f7e..02a94392 100644 --- a/src/common/CoreTerminal.ts +++ b/src/common/CoreTerminal.ts @@ -132,6 +132,7 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal { this.register(forwardEvent(this._bufferService.onResize, this._onResize)); this.register(forwardEvent(this.coreService.onData, this._onData)); this.register(forwardEvent(this.coreService.onBinary, this._onBinary)); + this.register(this.coreService.onUserInput(() => this._writeBuffer.handleUserInput())); this.register(this.optionsService.onOptionChange(key => this._updateOptions(key))); this.register(this._bufferService.onScroll(event => { this._onScroll.fire({ position: this._bufferService.buffer.ydisp, source: ScrollSource.TERMINAL }); diff --git a/src/common/input/WriteBuffer.ts b/src/common/input/WriteBuffer.ts index 2cdf4e3c..1ac98b51 100644 --- a/src/common/input/WriteBuffer.ts +++ b/src/common/input/WriteBuffer.ts @@ -40,11 +40,16 @@ export class WriteBuffer { private _bufferOffset = 0; private _isSyncWriting = false; private _syncCalls = 0; + private _didUserInput = false; public get onWriteParsed(): IEvent { return this._onWriteParsed.event; } private _onWriteParsed = new EventEmitter(); constructor(private _action: (data: string | Uint8Array, promiseResult?: boolean) => void | Promise) { } + public handleUserInput(): void { + this._didUserInput = true; + } + /** * @deprecated Unreliable, to be removed soon. */ @@ -99,7 +104,15 @@ export class WriteBuffer { // schedule chunk processing for next event loop run if (!this._writeBuffer.length) { this._bufferOffset = 0; - queueMicrotask(() => this._innerWrite()); + // If this is the first write call after the user has done some input, + // parse it immediately in an upcoming microtask to minimize reduce input, + // otherwise schedule for the next event + if (this._didUserInput) { + this._didUserInput = false; + queueMicrotask(() => this._innerWrite()); + } else { + setTimeout(() => this._innerWrite()); + } } this._pendingData += data.length; From 34df17e36dc309171880bd996b8b37f412bbb4de Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 28 Sep 2022 09:51:28 -0700 Subject: [PATCH 2/2] Call innerWrite immediately over a microtask --- src/common/input/WriteBuffer.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/common/input/WriteBuffer.ts b/src/common/input/WriteBuffer.ts index 1ac98b51..4f316f24 100644 --- a/src/common/input/WriteBuffer.ts +++ b/src/common/input/WriteBuffer.ts @@ -104,15 +104,20 @@ export class WriteBuffer { // schedule chunk processing for next event loop run if (!this._writeBuffer.length) { this._bufferOffset = 0; + // If this is the first write call after the user has done some input, // parse it immediately in an upcoming microtask to minimize reduce input, // otherwise schedule for the next event if (this._didUserInput) { this._didUserInput = false; - queueMicrotask(() => this._innerWrite()); - } else { - setTimeout(() => this._innerWrite()); + this._pendingData += data.length; + this._writeBuffer.push(data); + this._callbacks.push(callback); + this._innerWrite(); + return; } + + setTimeout(() => this._innerWrite()); } this._pendingData += data.length;