Sync unicode version with persistent terminal processes

Fixes #116113
This commit is contained in:
Daniel Imms 2021-08-17 07:06:13 -07:00
parent f7e4c0aa9e
commit 3a902162b4
19 changed files with 155 additions and 35 deletions

View file

@ -200,6 +200,7 @@ export interface IPtyService {
cwd: string,
cols: number,
rows: number,
unicodeVersion: '6' | '11',
env: IProcessEnvironment,
executableEnv: IProcessEnvironment,
windowsEnableConpty: boolean,
@ -223,6 +224,7 @@ export interface IPtyService {
getCwd(id: number): Promise<string>;
getLatency(id: number): Promise<number>;
acknowledgeDataEvent(id: number, charCount: number): Promise<void>;
setUnicodeVersion(id: number, version: '6' | '11'): Promise<void>;
processBinary(id: number, data: string): Promise<void>;
/** Confirm the process is _not_ an orphan. */
orphanQuestionReply(id: number): Promise<void>;
@ -485,6 +487,12 @@ export interface ITerminalChildProcess {
*/
acknowledgeDataEvent(charCount: number): void;
/**
* Sets the unicode version for the process, this drives the size of some characters in the
* xterm-headless instance.
*/
setUnicodeVersion(version: '6' | '11'): Promise<void>;
getInitialCwd(): Promise<string>;
getCwd(): Promise<string>;
getLatency(): Promise<number>;

View file

@ -20,7 +20,8 @@ export interface IRemoteTerminalProcessReplayEvent {
export interface ITerminalSerializer {
handleData(data: string): void;
handleResize(cols: number, rows: number): void;
generateReplayEvent(): IPtyHostProcessReplayEvent;
generateReplayEvent(): Promise<IPtyHostProcessReplayEvent>;
setUnicodeVersion?(version: '6' | '11'): void;
}
export class TerminalRecorder implements ITerminalSerializer {
@ -82,7 +83,7 @@ export class TerminalRecorder implements ITerminalSerializer {
}
}
generateReplayEvent(): IPtyHostProcessReplayEvent {
generateReplayEventSync(): IPtyHostProcessReplayEvent {
// normalize entries to one element per data array
this._entries.forEach((entry) => {
if (entry.data.length > 0) {
@ -93,4 +94,8 @@ export class TerminalRecorder implements ITerminalSerializer {
events: this._entries.map(entry => ({ cols: entry.cols, rows: entry.rows, data: entry.data[0] ?? '' }))
};
}
async generateReplayEvent(): Promise<IPtyHostProcessReplayEvent> {
return this.generateReplayEventSync();
}
}

View file

@ -178,9 +178,9 @@ export class PtyHostService extends Disposable implements IPtyService {
super.dispose();
}
async createProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, env: IProcessEnvironment, executableEnv: IProcessEnvironment, windowsEnableConpty: boolean, shouldPersist: boolean, workspaceId: string, workspaceName: string): Promise<number> {
async createProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, unicodeVersion: '6' | '11', env: IProcessEnvironment, executableEnv: IProcessEnvironment, windowsEnableConpty: boolean, shouldPersist: boolean, workspaceId: string, workspaceName: string): Promise<number> {
const timeout = setTimeout(() => this._handleUnresponsiveCreateProcess(), HeartbeatConstants.CreateProcessTimeout);
const id = await this._proxy.createProcess(shellLaunchConfig, cwd, cols, rows, env, executableEnv, windowsEnableConpty, shouldPersist, workspaceId, workspaceName);
const id = await this._proxy.createProcess(shellLaunchConfig, cwd, cols, rows, unicodeVersion, env, executableEnv, windowsEnableConpty, shouldPersist, workspaceId, workspaceName);
clearTimeout(timeout);
lastPtyId = Math.max(lastPtyId, id);
return id;
@ -221,6 +221,9 @@ export class PtyHostService extends Disposable implements IPtyService {
acknowledgeDataEvent(id: number, charCount: number): Promise<void> {
return this._proxy.acknowledgeDataEvent(id, charCount);
}
setUnicodeVersion(id: number, version: '6' | '11'): Promise<void> {
return this._proxy.setUnicodeVersion(id, version);
}
getInitialCwd(id: number): Promise<string> {
return this._proxy.getInitialCwd(id);
}

View file

@ -16,7 +16,8 @@ import { IProcessDataEvent, IProcessReadyEvent, IPtyService, IRawTerminalInstanc
import { TerminalDataBufferer } from 'vs/platform/terminal/common/terminalDataBuffering';
import { escapeNonWindowsPath } from 'vs/platform/terminal/common/terminalEnvironment';
import { Terminal as XtermTerminal } from 'xterm-headless';
import { SerializeAddon } from 'xterm-addon-serialize';
import type { SerializeAddon as XtermSerializeAddon } from 'xterm-addon-serialize';
import type { Unicode11Addon as XtermUnicode11Addon } from 'xterm-addon-unicode11';
import { IGetTerminalLayoutInfoArgs, IProcessDetails, IPtyHostProcessReplayEvent, ISetTerminalLayoutInfoArgs, ITerminalTabLayoutInfoDto } from 'vs/platform/terminal/common/terminalProcess';
import { ITerminalSerializer, TerminalRecorder } from 'vs/platform/terminal/common/terminalRecorder';
import { getWindowsBuildNumber } from 'vs/platform/terminal/node/terminalEnvironment';
@ -24,6 +25,9 @@ import { TerminalProcess } from 'vs/platform/terminal/node/terminalProcess';
type WorkspaceId = string;
let SerializeAddon: typeof XtermSerializeAddon;
let Unicode11Addon: typeof XtermUnicode11Addon;
export class PtyService extends Disposable implements IPtyService {
declare readonly _serviceBrand: undefined;
@ -102,6 +106,7 @@ export class PtyService extends Disposable implements IPtyService {
cwd: string,
cols: number,
rows: number,
unicodeVersion: '6' | '11',
env: IProcessEnvironment,
executableEnv: IProcessEnvironment,
windowsEnableConpty: boolean,
@ -125,7 +130,7 @@ export class PtyService extends Disposable implements IPtyService {
if (process.onDidChangeHasChildProcesses) {
process.onDidChangeHasChildProcesses(event => this._onProcessDidChangeHasChildProcesses.fire({ id, event }));
}
const persistentProcess = new PersistentTerminalProcess(id, process, workspaceId, workspaceName, shouldPersist, cols, rows, this._reconnectConstants, this._logService, shellLaunchConfig.icon);
const persistentProcess = new PersistentTerminalProcess(id, process, workspaceId, workspaceName, shouldPersist, cols, rows, unicodeVersion, this._reconnectConstants, this._logService, shellLaunchConfig.icon);
process.onProcessExit(() => {
persistentProcess.dispose();
this._ptys.delete(id);
@ -204,6 +209,9 @@ export class PtyService extends Disposable implements IPtyService {
async acknowledgeDataEvent(id: number, charCount: number): Promise<void> {
return this._throwIfNoPty(id).acknowledgeDataEvent(charCount);
}
async setUnicodeVersion(id: number, version: '6' | '11'): Promise<void> {
return this._throwIfNoPty(id).setUnicodeVersion(version);
}
async getLatency(id: number): Promise<number> {
return 0;
}
@ -364,6 +372,7 @@ export class PersistentTerminalProcess extends Disposable {
readonly shouldPersistTerminal: boolean,
cols: number,
rows: number,
unicodeVersion: '6' | '11',
reconnectConstants: IReconnectConstants,
private readonly _logService: ILogService,
private _icon?: TerminalIcon,
@ -376,7 +385,8 @@ export class PersistentTerminalProcess extends Disposable {
this._serializer = new XtermSerializer(
cols,
rows,
reconnectConstants.scrollback
reconnectConstants.scrollback,
unicodeVersion
);
} else {
this._serializer = new TerminalRecorder(cols, rows);
@ -463,6 +473,10 @@ export class PersistentTerminalProcess extends Disposable {
this._bufferer.flushBuffer(this._persistentProcessId);
return this._terminalProcess.resize(cols, rows);
}
setUnicodeVersion(version: '6' | '11'): void {
this._serializer.setUnicodeVersion?.(version);
// TODO: Pass in unicode version in ctor
}
acknowledgeDataEvent(charCount: number): void {
if (this._inReplay) {
return;
@ -479,8 +493,8 @@ export class PersistentTerminalProcess extends Disposable {
return this._terminalProcess.getLatency();
}
triggerReplay(): void {
const ev = this._serializer.generateReplayEvent();
async triggerReplay(): Promise<void> {
const ev = await this._serializer.generateReplayEvent();
let dataLength = 0;
for (const e of ev.events) {
dataLength += e.data.length;
@ -543,8 +557,16 @@ export class PersistentTerminalProcess extends Disposable {
class XtermSerializer implements ITerminalSerializer {
private _xterm: XtermTerminal;
constructor(cols: number, rows: number, scrollback: number) {
private _unicodeAddon?: XtermUnicode11Addon;
constructor(
cols: number,
rows: number,
scrollback: number,
unicodeVersion: '6' | '11'
) {
this._xterm = new XtermTerminal({ cols, rows, scrollback });
this.setUnicodeVersion(unicodeVersion);
}
handleData(data: string): void {
@ -555,8 +577,8 @@ class XtermSerializer implements ITerminalSerializer {
this._xterm.resize(cols, rows);
}
generateReplayEvent(): IPtyHostProcessReplayEvent {
const serialize = new SerializeAddon();
async generateReplayEvent(): Promise<IPtyHostProcessReplayEvent> {
const serialize = new (await this._getSerializeConstructor());
this._xterm.loadAddon(serialize);
const serialized = serialize.serialize(this._xterm.getOption('scrollback'));
return {
@ -569,6 +591,34 @@ class XtermSerializer implements ITerminalSerializer {
]
};
}
async setUnicodeVersion(version: '6' | '11'): Promise<void> {
if (this._xterm.unicode.activeVersion === version) {
return;
}
if (version === '11') {
this._unicodeAddon = new (await this._getUnicode11Constructor());
this._xterm.loadAddon(this._unicodeAddon);
} else {
this._unicodeAddon?.dispose();
this._unicodeAddon = undefined;
}
this._xterm.unicode.activeVersion = version;
}
async _getUnicode11Constructor(): Promise<typeof Unicode11Addon> {
if (!Unicode11Addon) {
Unicode11Addon = (await import('xterm-addon-unicode11')).Unicode11Addon;
}
return Unicode11Addon;
}
async _getSerializeConstructor(): Promise<typeof SerializeAddon> {
if (!SerializeAddon) {
SerializeAddon = (await import('xterm-addon-serialize')).SerializeAddon;
}
return SerializeAddon;
}
}
function printTime(ms: number): string {

View file

@ -470,6 +470,10 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
}
}
async setUnicodeVersion(version: '6' | '11'): Promise<void> {
// No-op
}
getInitialCwd(): Promise<string> {
return Promise.resolve(this._initialCwd);
}

View file

@ -7,44 +7,44 @@ import * as assert from 'assert';
import { ReplayEntry } from 'vs/platform/terminal/common/terminalProcess';
import { TerminalRecorder } from 'vs/platform/terminal/common/terminalRecorder';
function eventsEqual(recorder: TerminalRecorder, expected: ReplayEntry[]) {
const actual = recorder.generateReplayEvent().events;
async function eventsEqual(recorder: TerminalRecorder, expected: ReplayEntry[]) {
const actual = (await recorder.generateReplayEvent()).events;
for (let i = 0; i < expected.length; i++) {
assert.deepStrictEqual(actual[i], expected[i]);
}
}
suite('TerminalRecorder', () => {
test('should record dimensions', () => {
test('should record dimensions', async () => {
const recorder = new TerminalRecorder(1, 2);
eventsEqual(recorder, [
await eventsEqual(recorder, [
{ cols: 1, rows: 2, data: '' }
]);
recorder.handleData('a');
recorder.handleResize(3, 4);
eventsEqual(recorder, [
await eventsEqual(recorder, [
{ cols: 1, rows: 2, data: 'a' },
{ cols: 3, rows: 4, data: '' }
]);
});
test('should ignore resize events without data', () => {
test('should ignore resize events without data', async () => {
const recorder = new TerminalRecorder(1, 2);
eventsEqual(recorder, [
await eventsEqual(recorder, [
{ cols: 1, rows: 2, data: '' }
]);
recorder.handleResize(3, 4);
eventsEqual(recorder, [
await eventsEqual(recorder, [
{ cols: 3, rows: 4, data: '' }
]);
});
test('should record data and combine it into the previous resize event', () => {
test('should record data and combine it into the previous resize event', async () => {
const recorder = new TerminalRecorder(1, 2);
recorder.handleData('a');
recorder.handleData('b');
recorder.handleResize(3, 4);
recorder.handleData('c');
recorder.handleData('d');
eventsEqual(recorder, [
await eventsEqual(recorder, [
{ cols: 1, rows: 2, data: 'ab' },
{ cols: 3, rows: 4, data: 'cd' }
]);

View file

@ -263,7 +263,7 @@ export class ExtHostPseudoterminal implements ITerminalChildProcess {
}
async processBinary(data: string): Promise<void> {
// No-op, processBinary is not supported in extextion owned terminals.
// No-op, processBinary is not supported in extension owned terminals.
}
acknowledgeDataEvent(charCount: number): void {
@ -271,6 +271,10 @@ export class ExtHostPseudoterminal implements ITerminalChildProcess {
// implemented it will need new pause and resume VS Code APIs.
}
async setUnicodeVersion(version: '6' | '11'): Promise<void> {
// No-op, xterm-headless isn't used for extension owned terminals.
}
getInitialCwd(): Promise<string> {
return Promise.resolve('');
}

View file

@ -112,6 +112,10 @@ export class RemotePty extends Disposable implements ITerminalChildProcess {
});
}
async setUnicodeVersion(version: '6' | '11'): Promise<void> {
return this._remoteTerminalChannel.setUnicodeVersion(this._id, version);
}
async getInitialCwd(): Promise<string> {
await this._startBarrier.wait();
return this._remoteTerminalChannel.getInitialCwd(this._id);

View file

@ -22,7 +22,6 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
import { RemotePty } from 'vs/workbench/contrib/terminal/browser/remotePty';
import { IRemoteTerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { ICompleteTerminalConfiguration, RemoteTerminalChannelClient, REMOTE_TERMINAL_CHANNEL_NAME } from 'vs/workbench/contrib/terminal/common/remoteTerminalChannel';
import { ITerminalConfigHelper } from 'vs/workbench/contrib/terminal/common/terminal';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
@ -173,7 +172,7 @@ export class RemoteTerminalService extends Disposable implements IRemoteTerminal
return this._remoteTerminalChannel.acceptDetachInstanceReply(requestId, persistentProcessId);
}
async createProcess(shellLaunchConfig: IShellLaunchConfig, configuration: ICompleteTerminalConfiguration, activeWorkspaceRootUri: URI | undefined, cols: number, rows: number, shouldPersist: boolean, configHelper: ITerminalConfigHelper): Promise<ITerminalChildProcess> {
async createProcess(shellLaunchConfig: IShellLaunchConfig, configuration: ICompleteTerminalConfiguration, activeWorkspaceRootUri: URI | undefined, cols: number, rows: number, unicodeVersion: '6' | '11', shouldPersist: boolean): Promise<ITerminalChildProcess> {
if (!this._remoteTerminalChannel) {
throw new Error(`Cannot create remote terminal when there is no remote!`);
}
@ -200,6 +199,7 @@ export class RemoteTerminalService extends Disposable implements IRemoteTerminal
shouldPersist,
cols,
rows,
unicodeVersion
);
const pty = new RemotePty(result.persistentTerminalId, shouldPersist, this._remoteTerminalChannel, this._remoteAgentService, this._logService);
this._ptys.set(result.persistentTerminalId, pty);

View file

@ -320,7 +320,15 @@ export interface ITerminalFindHost {
}
export interface IRemoteTerminalService extends IOffProcessTerminalService {
createProcess(shellLaunchConfig: IShellLaunchConfig, configuration: ICompleteTerminalConfiguration, activeWorkspaceRootUri: URI | undefined, cols: number, rows: number, shouldPersist: boolean, configHelper: ITerminalConfigHelper): Promise<ITerminalChildProcess>;
createProcess(
shellLaunchConfig: IShellLaunchConfig,
configuration: ICompleteTerminalConfiguration,
activeWorkspaceRootUri: URI | undefined,
cols: number,
rows: number,
unicodeVersion: '6' | '11',
shouldPersist: boolean
): Promise<ITerminalChildProcess>;
}
/**

View file

@ -1575,7 +1575,10 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
this._xtermUnicode11 = new Addon();
this._xterm.loadAddon(this._xtermUnicode11);
}
this._xterm.unicode.activeVersion = this._configHelper.config.unicodeVersion;
if (this._xterm.unicode.activeVersion !== this._configHelper.config.unicodeVersion) {
this._xterm.unicode.activeVersion = this._configHelper.config.unicodeVersion;
this._processManager.setUnicodeVersion(this._configHelper.config.unicodeVersion);
}
}
updateAccessibilitySupport(): void {

View file

@ -124,6 +124,10 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal
// Flow control is disabled for extension terminals
}
async setUnicodeVersion(version: '6' | '11'): Promise<void> {
// No-op
}
async processBinary(data: string): Promise<void> {
// Disabled for extension terminals
this._onBinary.fire(data);

View file

@ -267,7 +267,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
'terminal.integrated.cwd': this._configurationService.getValue(TerminalSettingId.Cwd) as string,
'terminal.integrated.detectLocale': terminalConfig.detectLocale
};
newProcess = await this._remoteTerminalService.createProcess(shellLaunchConfig, configuration, activeWorkspaceRootUri, cols, rows, shouldPersist, this._configHelper);
newProcess = await this._remoteTerminalService.createProcess(shellLaunchConfig, configuration, activeWorkspaceRootUri, cols, rows, this._configHelper.config.unicodeVersion, shouldPersist);
}
if (!this._isDisposed) {
this._setupPtyHostListeners(this._remoteTerminalService);
@ -430,7 +430,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
const useConpty = this._configHelper.config.windowsEnableConpty && !isScreenReaderModeEnabled;
const shouldPersist = this._configHelper.config.enablePersistentSessions && !shellLaunchConfig.isFeatureTerminal;
return await localTerminalService.createProcess(shellLaunchConfig, initialCwd, cols, rows, env, useConpty, shouldPersist);
return await localTerminalService.createProcess(shellLaunchConfig, initialCwd, cols, rows, this._configHelper.config.unicodeVersion, env, useConpty, shouldPersist);
}
private _setupPtyHostListeners(offProcessTerminalService: IOffProcessTerminalService) {
@ -492,6 +492,10 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
return this.ptyProcessReady.then(() => this._resize(cols, rows));
}
async setUnicodeVersion(version: '6' | '11'): Promise<void> {
return this._process?.setUnicodeVersion(version);
}
private _resize(cols: number, rows: number) {
if (!this._process) {
return;
@ -756,6 +760,6 @@ class SeamlessRelaunchDataFilter extends Disposable {
}
private _getDataFromRecorder(recorder: TerminalRecorder): string {
return recorder.generateReplayEvent().events.filter(e => !!e.data).map(e => e.data).join('');
return recorder.generateReplayEventSync().events.filter(e => !!e.data).map(e => e.data).join('');
}
}

View file

@ -62,6 +62,7 @@ export interface ICreateTerminalProcessArguments {
shouldPersistTerminal: boolean;
cols: number;
rows: number;
unicodeVersion: '6' | '11';
resolverEnv: { [key: string]: string | null; } | undefined
}
@ -141,7 +142,7 @@ export class RemoteTerminalChannelClient {
return this._channel.call('$restartPtyHost', []);
}
async createProcess(shellLaunchConfig: IShellLaunchConfigDto, configuration: ICompleteTerminalConfiguration, activeWorkspaceRootUri: URI | undefined, shouldPersistTerminal: boolean, cols: number, rows: number): Promise<ICreateTerminalProcessResult> {
async createProcess(shellLaunchConfig: IShellLaunchConfigDto, configuration: ICompleteTerminalConfiguration, activeWorkspaceRootUri: URI | undefined, shouldPersistTerminal: boolean, cols: number, rows: number, unicodeVersion: '6' | '11'): Promise<ICreateTerminalProcessResult> {
// Be sure to first wait for the remote configuration
await this._configurationService.whenRemoteConfigurationLoaded();
@ -196,6 +197,7 @@ export class RemoteTerminalChannelClient {
shouldPersistTerminal,
cols,
rows,
unicodeVersion,
resolverEnv
};
return await this._channel.call<ICreateTerminalProcessResult>('$createProcess', args);
@ -231,6 +233,9 @@ export class RemoteTerminalChannelClient {
acknowledgeDataEvent(id: number, charCount: number): Promise<void> {
return this._channel.call('$acknowledgeDataEvent', [id, charCount]);
}
setUnicodeVersion(id: number, version: '6' | '11'): Promise<void> {
return this._channel.call('$setUnicodeVersion', [id, version]);
}
shutdown(id: number, immediate: boolean): Promise<void> {
return this._channel.call('$shutdown', [id, immediate]);
}

View file

@ -101,7 +101,16 @@ export interface IOffProcessTerminalService {
export const ILocalTerminalService = createDecorator<ILocalTerminalService>('localTerminalService');
export interface ILocalTerminalService extends IOffProcessTerminalService {
createProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, env: IProcessEnvironment, windowsEnableConpty: boolean, shouldPersist: boolean): Promise<ITerminalChildProcess>;
createProcess(
shellLaunchConfig: IShellLaunchConfig,
cwd: string,
cols: number,
rows: number,
unicodeVersion: '6' | '11',
env: IProcessEnvironment,
windowsEnableConpty: boolean,
shouldPersist: boolean
): Promise<ITerminalChildProcess>;
}
export type FontWeight = 'normal' | 'bold' | number;
@ -293,6 +302,7 @@ export interface ITerminalProcessManager extends IDisposable {
setDimensions(cols: number, rows: number): Promise<void>;
setDimensions(cols: number, rows: number, sync: false): Promise<void>;
setDimensions(cols: number, rows: number, sync: true): void;
setUnicodeVersion(version: '6' | '11'): Promise<void>;
acknowledgeDataEvent(charCount: number): void;
processBinary(data: string): void;

View file

@ -86,6 +86,9 @@ export class LocalPty extends Disposable implements ITerminalChildProcess {
}
this._localPtyService.acknowledgeDataEvent(this.id, charCount);
}
setUnicodeVersion(version: '6' | '11'): Promise<void> {
return this._localPtyService.setUnicodeVersion(this.id, version);
}
handleData(e: string | IProcessDataEvent) {
this._onProcessData.fire(e);

View file

@ -146,9 +146,9 @@ export class LocalTerminalService extends Disposable implements ILocalTerminalSe
await this._localPtyService.updateIcon(id, icon, color);
}
async createProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, env: IProcessEnvironment, windowsEnableConpty: boolean, shouldPersist: boolean): Promise<ITerminalChildProcess> {
async createProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, unicodeVersion: '6' | '11', env: IProcessEnvironment, windowsEnableConpty: boolean, shouldPersist: boolean): Promise<ITerminalChildProcess> {
const executableEnv = await this._shellEnvironmentService.getShellEnv();
const id = await this._localPtyService.createProcess(shellLaunchConfig, cwd, cols, rows, env, executableEnv, windowsEnableConpty, shouldPersist, this._getWorkspaceId(), this._getWorkspaceName());
const id = await this._localPtyService.createProcess(shellLaunchConfig, cwd, cols, rows, unicodeVersion, env, executableEnv, windowsEnableConpty, shouldPersist, this._getWorkspaceId(), this._getWorkspaceName());
const pty = this._instantiationService.createInstance(LocalPty, id, shouldPersist);
this._ptys.set(id, pty);
return pty;

View file

@ -203,6 +203,10 @@ class TestOutputProcess extends Disposable implements ITerminalChildProcess {
public acknowledgeDataEvent(): void {
// no-op, flow control not currently implemented
}
public setUnicodeVersion(): Promise<void> {
// no-op
return Promise.resolve();
}
public getInitialCwd(): Promise<string> {
return Promise.resolve('');

View file

@ -1667,7 +1667,7 @@ export class TestLocalTerminalService implements ILocalTerminalService {
onDidMoveWindowInstance = Event.None;
onDidRequestDetach = Event.None;
async createProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, env: IProcessEnvironment, windowsEnableConpty: boolean, shouldPersist: boolean): Promise<ITerminalChildProcess> { return new TestTerminalChildProcess(shouldPersist); }
async createProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, unicodeVersion: '6' | '11', env: IProcessEnvironment, windowsEnableConpty: boolean, shouldPersist: boolean): Promise<ITerminalChildProcess> { return new TestTerminalChildProcess(shouldPersist); }
async attachToProcess(id: number): Promise<ITerminalChildProcess | undefined> { throw new Error('Method not implemented.'); }
async listProcesses(): Promise<IProcessDetails[]> { throw new Error('Method not implemented.'); }
getDefaultSystemShell(osOverride?: OperatingSystem): Promise<string> { throw new Error('Method not implemented.'); }
@ -1703,6 +1703,7 @@ class TestTerminalChildProcess implements ITerminalChildProcess {
input(data: string): void { }
resize(cols: number, rows: number): void { }
acknowledgeDataEvent(charCount: number): void { }
async setUnicodeVersion(version: '6' | '11'): Promise<void> { }
async getInitialCwd(): Promise<string> { return ''; }
async getCwd(): Promise<string> { return ''; }
async getLatency(): Promise<number> { return 0; }