Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 0 additions & 38 deletions src/vs/platform/terminal/common/terminalProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
60 changes: 8 additions & 52 deletions src/vs/platform/terminal/node/terminalProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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<string, PosixShellType>([
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down
41 changes: 0 additions & 41 deletions src/vs/platform/terminal/test/common/terminalProcess.test.ts

This file was deleted.

Loading