Fix async in terminal ext host and custom pty impl terminals
Fixes #129240
This commit is contained in:
parent
b9c8788542
commit
5b5766d77d
|
@ -669,7 +669,7 @@ import { assertNoRpc } from '../utils';
|
|||
});
|
||||
|
||||
suite('environmentVariableCollection', () => {
|
||||
test('should have collection variables apply to terminals immediately after setting', async (done) => {
|
||||
test('should have collection variables apply to terminals immediately after setting', (done) => {
|
||||
// Text to match on before passing the test
|
||||
const expectedText = [
|
||||
'~a2~',
|
||||
|
@ -697,7 +697,7 @@ import { assertNoRpc } from '../utils';
|
|||
collection.replace('A', '~a2~');
|
||||
collection.append('B', '~b2~');
|
||||
collection.prepend('C', '~c2~');
|
||||
const terminal = await window.createTerminal({
|
||||
const terminal = window.createTerminal({
|
||||
env: {
|
||||
A: 'a1',
|
||||
B: 'b1',
|
||||
|
@ -714,7 +714,7 @@ import { assertNoRpc } from '../utils';
|
|||
terminal.sendText('echo $C');
|
||||
});
|
||||
|
||||
test('should have collection variables apply to environment variables that don\'t exist', async (done) => {
|
||||
test('should have collection variables apply to environment variables that don\'t exist', (done) => {
|
||||
// Text to match on before passing the test
|
||||
const expectedText = [
|
||||
'~a2~',
|
||||
|
@ -742,7 +742,7 @@ import { assertNoRpc } from '../utils';
|
|||
collection.replace('A', '~a2~');
|
||||
collection.append('B', '~b2~');
|
||||
collection.prepend('C', '~c2~');
|
||||
const terminal = await window.createTerminal({
|
||||
const terminal = window.createTerminal({
|
||||
env: {
|
||||
A: null,
|
||||
B: null,
|
||||
|
@ -759,7 +759,7 @@ import { assertNoRpc } from '../utils';
|
|||
terminal.sendText('echo $C');
|
||||
});
|
||||
|
||||
test('should respect clearing entries', async (done) => {
|
||||
test('should respect clearing entries', (done) => {
|
||||
// Text to match on before passing the test
|
||||
const expectedText = [
|
||||
'~a1~',
|
||||
|
@ -786,7 +786,7 @@ import { assertNoRpc } from '../utils';
|
|||
collection.replace('A', '~a2~');
|
||||
collection.replace('B', '~a2~');
|
||||
collection.clear();
|
||||
const terminal = await window.createTerminal({
|
||||
const terminal = window.createTerminal({
|
||||
env: {
|
||||
A: '~a1~',
|
||||
B: '~b1~'
|
||||
|
@ -800,7 +800,7 @@ import { assertNoRpc } from '../utils';
|
|||
terminal.sendText('echo $B');
|
||||
});
|
||||
|
||||
test('should respect deleting entries', async (done) => {
|
||||
test('should respect deleting entries', (done) => {
|
||||
// Text to match on before passing the test
|
||||
const expectedText = [
|
||||
'~a1~',
|
||||
|
@ -827,7 +827,7 @@ import { assertNoRpc } from '../utils';
|
|||
collection.replace('A', '~a2~');
|
||||
collection.replace('B', '~b2~');
|
||||
collection.delete('A');
|
||||
const terminal = await window.createTerminal({
|
||||
const terminal = window.createTerminal({
|
||||
env: {
|
||||
A: '~a1~',
|
||||
B: '~b2~'
|
||||
|
|
|
@ -30,7 +30,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
|||
* to a numeric terminal id (an id generated on the renderer side)
|
||||
* This comes in play only when dealing with terminals created on the extension host side
|
||||
*/
|
||||
private _extHostTerminalIds = new Map<string, number>();
|
||||
private _extHostTerminals = new Map<string, Promise<ITerminalInstance>>();
|
||||
private readonly _toDispose = new DisposableStore();
|
||||
private readonly _terminalProcessProxies = new Map<number, ITerminalProcessExtHostProxy>();
|
||||
private readonly _profileProviders = new Map<string, IDisposable>();
|
||||
|
@ -109,19 +109,11 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
|||
this._proxy.$acceptDefaultProfile(...await Promise.all([defaultProfile, defaultAutomationProfile]));
|
||||
}
|
||||
|
||||
private _getTerminalId(id: TerminalIdentifier): number | undefined {
|
||||
if (typeof id === 'number') {
|
||||
return id;
|
||||
private async _getTerminalInstance(id: TerminalIdentifier): Promise<ITerminalInstance | undefined> {
|
||||
if (typeof id === 'string') {
|
||||
return this._extHostTerminals.get(id);
|
||||
}
|
||||
return this._extHostTerminalIds.get(id);
|
||||
}
|
||||
|
||||
private _getTerminalInstance(id: TerminalIdentifier): ITerminalInstance | undefined {
|
||||
const rendererId = this._getTerminalId(id);
|
||||
if (typeof rendererId === 'number') {
|
||||
return this._terminalService.getInstanceFromId(rendererId);
|
||||
}
|
||||
return undefined;
|
||||
return this._terminalService.getInstanceFromId(id);
|
||||
}
|
||||
|
||||
public async $createTerminal(extHostTerminalId: string, launchConfig: TerminalLaunchConfig): Promise<void> {
|
||||
|
@ -141,29 +133,31 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
|||
customPtyImplementation: launchConfig.isExtensionCustomPtyTerminal
|
||||
? (id, cols, rows) => new TerminalProcessExtHostProxy(id, cols, rows, this._terminalService)
|
||||
: undefined,
|
||||
extHostTerminalId: extHostTerminalId,
|
||||
extHostTerminalId,
|
||||
isFeatureTerminal: launchConfig.isFeatureTerminal,
|
||||
isExtensionOwnedTerminal: launchConfig.isExtensionOwnedTerminal,
|
||||
useShellEnvironment: launchConfig.useShellEnvironment
|
||||
};
|
||||
let terminal: ITerminalInstance | undefined;
|
||||
if (launchConfig.isSplitTerminal) {
|
||||
const activeInstance = this._terminalService.getInstanceHost(launchConfig.target).activeInstance;
|
||||
if (activeInstance) {
|
||||
terminal = withNullAsUndefined(await this._terminalService.splitInstance(activeInstance, shellLaunchConfig));
|
||||
this._extHostTerminals.set(extHostTerminalId, new Promise(async r => {
|
||||
let terminal: ITerminalInstance | undefined;
|
||||
if (launchConfig.isSplitTerminal) {
|
||||
const activeInstance = this._terminalService.getInstanceHost(launchConfig.target).activeInstance;
|
||||
if (activeInstance) {
|
||||
terminal = withNullAsUndefined(await this._terminalService.splitInstance(activeInstance, shellLaunchConfig));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!terminal) {
|
||||
terminal = await this._terminalService.createTerminal({
|
||||
config: shellLaunchConfig,
|
||||
target: launchConfig.target
|
||||
});
|
||||
}
|
||||
this._extHostTerminalIds.set(extHostTerminalId, terminal.instanceId);
|
||||
if (!terminal) {
|
||||
terminal = await this._terminalService.createTerminal({
|
||||
config: shellLaunchConfig,
|
||||
target: launchConfig.target
|
||||
});
|
||||
}
|
||||
r(terminal);
|
||||
}));
|
||||
}
|
||||
|
||||
public $show(id: TerminalIdentifier, preserveFocus: boolean): void {
|
||||
const terminalInstance = this._getTerminalInstance(id);
|
||||
public async $show(id: TerminalIdentifier, preserveFocus: boolean): Promise<void> {
|
||||
const terminalInstance = await this._getTerminalInstance(id);
|
||||
if (terminalInstance) {
|
||||
this._terminalService.setActiveInstance(terminalInstance);
|
||||
if (terminalInstance.target === TerminalLocation.Editor) {
|
||||
|
@ -174,20 +168,21 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
|
|||
}
|
||||
}
|
||||
|
||||
public $hide(id: TerminalIdentifier): void {
|
||||
const rendererId = this._getTerminalId(id);
|
||||
const instance = this._terminalService.activeInstance;
|
||||
if (instance && instance.instanceId === rendererId && instance.target !== TerminalLocation.Editor) {
|
||||
public async $hide(id: TerminalIdentifier): Promise<void> {
|
||||
const instanceToHide = await this._getTerminalInstance(id);
|
||||
const activeInstance = this._terminalService.activeInstance;
|
||||
if (activeInstance && activeInstance.instanceId === instanceToHide?.instanceId && activeInstance.target !== TerminalLocation.Editor) {
|
||||
this._terminalGroupService.hidePanel();
|
||||
}
|
||||
}
|
||||
|
||||
public $dispose(id: TerminalIdentifier): void {
|
||||
this._getTerminalInstance(id)?.dispose();
|
||||
public async $dispose(id: TerminalIdentifier): Promise<void> {
|
||||
(await this._getTerminalInstance(id))?.dispose();
|
||||
}
|
||||
|
||||
public $sendText(id: TerminalIdentifier, text: string, addNewLine: boolean): void {
|
||||
this._getTerminalInstance(id)?.sendText(text, addNewLine);
|
||||
public async $sendText(id: TerminalIdentifier, text: string, addNewLine: boolean): Promise<void> {
|
||||
const instance = await this._getTerminalInstance(id);
|
||||
await instance?.sendText(text, addNewLine);
|
||||
}
|
||||
|
||||
public $startSendingDataEvents(): void {
|
||||
|
|
|
@ -618,7 +618,7 @@ export interface ITerminalInstance {
|
|||
* required to run a command in the terminal. The character(s) added are \n or \r\n
|
||||
* depending on the platform. This defaults to `true`.
|
||||
*/
|
||||
sendText(text: string, addNewLine: boolean): void;
|
||||
sendText(text: string, addNewLine: boolean): Promise<void>;
|
||||
|
||||
/** Scroll the terminal buffer down 1 line. */
|
||||
scrollDownLine(): void;
|
||||
|
|
|
@ -229,8 +229,9 @@ export class TerminalService implements ITerminalService {
|
|||
lifecycleService.onWillShutdown(e => this._onWillShutdown(e));
|
||||
|
||||
this._configurationService.onDidChangeConfiguration(async e => {
|
||||
if (e.affectsConfiguration(TerminalSettingPrefix.DefaultProfile + this._getPlatformKey()) ||
|
||||
e.affectsConfiguration(TerminalSettingPrefix.Profiles + this._getPlatformKey()) ||
|
||||
const platformKey = await this._getPlatformKey();
|
||||
if (e.affectsConfiguration(TerminalSettingPrefix.DefaultProfile + platformKey) ||
|
||||
e.affectsConfiguration(TerminalSettingPrefix.Profiles + platformKey) ||
|
||||
e.affectsConfiguration(TerminalSettingId.UseWslProfiles)) {
|
||||
this._refreshAvailableProfiles();
|
||||
}
|
||||
|
@ -957,7 +958,6 @@ export class TerminalService implements ITerminalService {
|
|||
return; // Should never happen
|
||||
} else if ('id' in value.profile) {
|
||||
// extension contributed profile
|
||||
console.log(value.profile.title);
|
||||
await this._configurationService.updateValue(`terminal.integrated.defaultProfile.${platformKey}`, value.profile.title, ConfigurationTarget.USER);
|
||||
|
||||
this._registerContributedProfile(value.profile.extensionIdentifier, value.profile.id, value.profile.title, {
|
||||
|
@ -1067,7 +1067,7 @@ export class TerminalService implements ITerminalService {
|
|||
return { label, description: profile.path, profile, buttons };
|
||||
}
|
||||
|
||||
private _convertProfileToShellLaunchConfig(shellLaunchConfigOrProfile?: IShellLaunchConfig | ITerminalProfile | IExtensionTerminalProfile, cwd?: string | URI): IShellLaunchConfig {
|
||||
private _convertProfileToShellLaunchConfig(shellLaunchConfigOrProfile?: IShellLaunchConfig | ITerminalProfile, cwd?: string | URI): IShellLaunchConfig {
|
||||
if (shellLaunchConfigOrProfile && 'profileName' in shellLaunchConfigOrProfile) {
|
||||
const profile = shellLaunchConfigOrProfile;
|
||||
if (!profile.path) {
|
||||
|
@ -1084,8 +1084,8 @@ export class TerminalService implements ITerminalService {
|
|||
};
|
||||
}
|
||||
|
||||
// Shell launch config was provided
|
||||
if (shellLaunchConfigOrProfile && 'cwd' in shellLaunchConfigOrProfile) {
|
||||
// A shell launch config was provided
|
||||
if (shellLaunchConfigOrProfile) {
|
||||
if (cwd) {
|
||||
shellLaunchConfigOrProfile.cwd = cwd;
|
||||
}
|
||||
|
@ -1109,11 +1109,27 @@ export class TerminalService implements ITerminalService {
|
|||
}
|
||||
|
||||
async createTerminal(options?: ICreateTerminalOptions): Promise<ITerminalInstance> {
|
||||
const shellLaunchConfig = this._convertProfileToShellLaunchConfig(options?.config || options);
|
||||
const config = options?.config;
|
||||
const shellLaunchConfig = config && 'extensionIdentifier' in config
|
||||
? {}
|
||||
: this._convertProfileToShellLaunchConfig(config || {});
|
||||
|
||||
const contributedDefaultProfile = await this._getContributedDefaultProfile(shellLaunchConfig);
|
||||
if (contributedDefaultProfile) {
|
||||
await this.createContributedTerminalProfile(contributedDefaultProfile.extensionIdentifier, contributedDefaultProfile.id, { isSplitTerminal: false, icon: contributedDefaultProfile.icon });
|
||||
// Get the contributed profile if it was provided
|
||||
let contributedProfile = config && 'extensionIdentifier' in config ? config : undefined;
|
||||
|
||||
// Get the default profile as a contributed profile if it exists
|
||||
if (!contributedProfile && !options) {
|
||||
contributedProfile = await this._getContributedDefaultProfile(shellLaunchConfig);
|
||||
}
|
||||
|
||||
// Launch the contributed profile
|
||||
if (contributedProfile) {
|
||||
// TODO: createContributedTerminalProfile should be private if we want all terminal creation to go through createTerminal
|
||||
await this.createContributedTerminalProfile(contributedProfile.extensionIdentifier, contributedProfile.id, {
|
||||
isSplitTerminal: false,
|
||||
icon: contributedProfile.icon
|
||||
});
|
||||
// TODO: The extension terminal may be created in the editor area
|
||||
return this._terminalGroupService.instances[this._terminalGroupService.instances.length - 1];
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue