diff --git a/src/vs/platform/terminal/common/terminalProcess.ts b/src/vs/platform/terminal/common/terminalProcess.ts index 917db9710d872..28408eef7103b 100644 --- a/src/vs/platform/terminal/common/terminalProcess.ts +++ b/src/vs/platform/terminal/common/terminalProcess.ts @@ -69,41 +69,3 @@ export interface ReplayEntry { rows: number; data: string; } - -const enum Constants { - /** - * Writing large amounts of data can be corrupted for some reason, after looking into this is - * appears to be a race condition around writing to the FD which may be based on how powerful - * the hardware is. The workaround for this is to space out when large amounts of data is being - * written to the terminal. See https://github.com/microsoft/vscode/issues/38137 - */ - WriteMaxChunkSize = 50, -} - -/** - * Splits incoming pty data into chunks to try prevent data corruption that could occur when pasting - * large amounts of data. - */ -export function chunkInput(data: string): string[] { - const chunks: string[] = []; - let nextChunkStartIndex = 0; - for (let i = 0; i < data.length - 1; i++) { - if ( - // If the max chunk size is reached - i - nextChunkStartIndex + 1 >= Constants.WriteMaxChunkSize || - // If the next character is ESC, send the pending data to avoid splitting the escape - // sequence. - data[i + 1] === '\x1b' - ) { - chunks.push(data.substring(nextChunkStartIndex, i + 1)); - nextChunkStartIndex = i + 1; - // Skip the next character as the chunk would be a single character - i++; - } - } - // Push final chunk - if (nextChunkStartIndex !== data.length) { - chunks.push(data.substring(nextChunkStartIndex)); - } - return chunks; -} diff --git a/src/vs/platform/terminal/node/terminalProcess.ts b/src/vs/platform/terminal/node/terminalProcess.ts index e6deacd6b4dd6..3ba834a84d71c 100644 --- a/src/vs/platform/terminal/node/terminalProcess.ts +++ b/src/vs/platform/terminal/node/terminalProcess.ts @@ -20,7 +20,6 @@ import { ChildProcessMonitor } from './childProcessMonitor.js'; import { getShellIntegrationInjection, getWindowsBuildNumber, IShellIntegrationConfigInjection } from './terminalEnvironment.js'; import { WindowsShellHelper } from './windowsShellHelper.js'; import { IPty, IPtyForkOptions, IWindowsPtyForkOptions, spawn } from 'node-pty'; -import { chunkInput } from '../common/terminalProcess.js'; import { isNumber } from '../../../base/common/types.js'; const enum ShutdownConstants { @@ -57,15 +56,6 @@ const enum Constants { * interval. */ KillSpawnSpacingDuration = 50, - /** - * How long to wait between chunk writes. - */ - WriteInterval = 5, -} - -interface IWriteObject { - data: string; - isBinary: boolean; } const posixShellTypeMap = new Map([ @@ -113,8 +103,6 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess private _windowsShellHelper: WindowsShellHelper | undefined; private _childProcessMonitor: ChildProcessMonitor | undefined; private _titleInterval: Timeout | undefined; - private _writeQueue: IWriteObject[] = []; - private _writeTimeout: Timeout | undefined; private _delayedResizer: DelayedResizer | undefined; private readonly _initialCwd: string; private readonly _ptyOptions: IPtyForkOptions | IWindowsPtyForkOptions; @@ -471,13 +459,15 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess } input(data: string, isBinary: boolean = false): void { - if (this._store.isDisposed || !this._ptyProcess) { - return; + this._logService.trace('node-pty.IPty#write', data, isBinary); + if (isBinary) { + // TODO: node-pty's write should accept a Buffer, needs https://github.com/microsoft/node-pty/pull/812 + // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any + this._ptyProcess!.write(Buffer.from(data, 'binary') as any); + } else { + this._ptyProcess!.write(data); } - this._writeQueue.push(...chunkInput(data).map(e => { - return { isBinary, data: e }; - })); - this._startWrite(); + this._childProcessMonitor?.handleInput(); } sendSignal(signal: string): void { @@ -522,40 +512,6 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess } } - private _startWrite(): void { - // Don't write if it's already queued of is there is nothing to write - if (this._writeTimeout !== undefined || this._writeQueue.length === 0) { - return; - } - - this._doWrite(); - - // Don't queue more writes if the queue is empty - if (this._writeQueue.length === 0) { - this._writeTimeout = undefined; - return; - } - - // Queue the next write - this._writeTimeout = setTimeout(() => { - this._writeTimeout = undefined; - this._startWrite(); - }, Constants.WriteInterval); - } - - private _doWrite(): void { - const object = this._writeQueue.shift()!; - this._logService.trace('node-pty.IPty#write', object.data); - if (object.isBinary) { - // TODO: node-pty's write should accept a Buffer, needs https://github.com/microsoft/node-pty/pull/812 - // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any - this._ptyProcess!.write(Buffer.from(object.data, 'binary') as any); - } else { - this._ptyProcess!.write(object.data); - } - this._childProcessMonitor?.handleInput(); - } - resize(cols: number, rows: number): void { if (this._store.isDisposed) { return; diff --git a/src/vs/platform/terminal/test/common/terminalProcess.test.ts b/src/vs/platform/terminal/test/common/terminalProcess.test.ts deleted file mode 100644 index 4d4ef97709c9f..0000000000000 --- a/src/vs/platform/terminal/test/common/terminalProcess.test.ts +++ /dev/null @@ -1,41 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { deepStrictEqual } from 'assert'; -import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js'; -import { chunkInput } from '../../common/terminalProcess.js'; - -suite('platform - terminalProcess', () => { - ensureNoDisposablesAreLeakedInTestSuite(); - suite('chunkInput', () => { - test('single chunk', () => { - deepStrictEqual(chunkInput('foo bar'), ['foo bar']); - }); - test('multi chunk', () => { - deepStrictEqual(chunkInput('foo'.repeat(50)), [ - 'foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofo', - 'ofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoof', - 'oofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo' - ]); - }); - test('small data with escapes', () => { - deepStrictEqual(chunkInput('foo \x1b[30mbar'), [ - 'foo ', - '\x1b[30mbar' - ]); - }); - test('large data with escapes', () => { - deepStrictEqual(chunkInput('foofoofoofoo\x1b[30mbarbarbarbarbar\x1b[0m'.repeat(3)), [ - 'foofoofoofoo', - '\x1B[30mbarbarbarbarbar', - '\x1B[0mfoofoofoofoo', - '\x1B[30mbarbarbarbarbar', - '\x1B[0mfoofoofoofoo', - '\x1B[30mbarbarbarbarbar', - '\x1B[0m' - ]); - }); - }); -});