Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 (#6381)

* Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973

* disable strict null check
This commit is contained in:
Anthony Dresser
2019-07-15 22:35:46 -07:00
committed by GitHub
parent f720ec642f
commit 0b7e7ddbf9
2406 changed files with 59140 additions and 35464 deletions

View File

@@ -11,9 +11,12 @@ import * as fs from 'fs';
import { Event, Emitter } from 'vs/base/common/event';
import { getWindowsBuildNumber } from 'vs/workbench/contrib/terminal/node/terminal';
import { IDisposable } from 'vs/base/common/lifecycle';
import { IShellLaunchConfig, ITerminalChildProcess } from 'vs/workbench/contrib/terminal/common/terminal';
import { IShellLaunchConfig, ITerminalChildProcess, SHELL_PATH_INVALID_EXIT_CODE, SHELL_PATH_DIRECTORY_EXIT_CODE, SHELL_CWD_INVALID_EXIT_CODE } from 'vs/workbench/contrib/terminal/common/terminal';
import { exec } from 'child_process';
import { ILogService } from 'vs/platform/log/common/log';
import { stat } from 'vs/base/node/pfs';
import { findExecutable } from 'vs/workbench/contrib/terminal/node/terminalEnvironment';
import { URI } from 'vs/base/common/uri';
export class TerminalProcess implements ITerminalChildProcess, IDisposable {
private _exitCode: number;
@@ -29,8 +32,8 @@ export class TerminalProcess implements ITerminalChildProcess, IDisposable {
public get onProcessData(): Event<string> { return this._onProcessData.event; }
private readonly _onProcessExit = new Emitter<number>();
public get onProcessExit(): Event<number> { return this._onProcessExit.event; }
private readonly _onProcessIdReady = new Emitter<number>();
public get onProcessIdReady(): Event<number> { return this._onProcessIdReady.event; }
private readonly _onProcessReady = new Emitter<{ pid: number, cwd: string }>();
public get onProcessReady(): Event<{ pid: number, cwd: string }> { return this._onProcessReady.event; }
private readonly _onProcessTitleChanged = new Emitter<string>();
public get onProcessTitleChanged(): Event<string> { return this._onProcessTitleChanged.event; }
@@ -54,14 +57,7 @@ export class TerminalProcess implements ITerminalChildProcess, IDisposable {
this._initialCwd = cwd;
// Only use ConPTY when the client is non WoW64 (see #72190) and the Windows build number is at least 18309 (for
// stability/performance reasons)
const is32ProcessOn64Windows = process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432');
const useConpty = windowsEnableConpty &&
process.platform === 'win32' &&
!is32ProcessOn64Windows &&
getWindowsBuildNumber() >= 18309;
const useConpty = windowsEnableConpty && process.platform === 'win32' && getWindowsBuildNumber() >= 18309;
const options: pty.IPtyForkOptions | pty.IWindowsPtyForkOptions = {
name: shellName,
cwd,
@@ -72,16 +68,43 @@ export class TerminalProcess implements ITerminalChildProcess, IDisposable {
conptyInheritCursor: true
};
// TODO: Need to verify whether executable is on $PATH, otherwise things like cmd.exe will break
// fs.stat(shellLaunchConfig.executable!, (err) => {
// if (err && err.code === 'ENOENT') {
// this._exitCode = SHELL_PATH_INVALID_EXIT_CODE;
// this._queueProcessExit();
// this._processStartupComplete = Promise.resolve(undefined);
// return;
// }
this.setupPtyProcess(shellLaunchConfig, options);
// });
const cwdVerification = stat(cwd).then(async stat => {
if (!stat.isDirectory()) {
return Promise.reject(SHELL_CWD_INVALID_EXIT_CODE);
}
}, async err => {
if (err && err.code === 'ENOENT') {
// So we can include in the error message the specified CWD
shellLaunchConfig.cwd = cwd;
return Promise.reject(SHELL_CWD_INVALID_EXIT_CODE);
}
});
const exectuableVerification = stat(shellLaunchConfig.executable!).then(async stat => {
if (!stat.isFile() && !stat.isSymbolicLink()) {
return Promise.reject(stat.isDirectory() ? SHELL_PATH_DIRECTORY_EXIT_CODE : SHELL_PATH_INVALID_EXIT_CODE);
}
}, async (err) => {
if (err && err.code === 'ENOENT') {
let cwd = shellLaunchConfig.cwd instanceof URI ? shellLaunchConfig.cwd.path : shellLaunchConfig.cwd!;
const executable = await findExecutable(shellLaunchConfig.executable!, cwd);
if (!executable) {
return Promise.reject(SHELL_PATH_INVALID_EXIT_CODE);
}
}
});
Promise.all([cwdVerification, exectuableVerification]).then(() => {
this.setupPtyProcess(shellLaunchConfig, options);
}).catch((exitCode: number) => {
return this._launchFailed(exitCode);
});
}
private _launchFailed(exitCode: number): void {
this._exitCode = exitCode;
this._queueProcessExit();
this._processStartupComplete = Promise.resolve(undefined);
}
private setupPtyProcess(shellLaunchConfig: IShellLaunchConfig, options: pty.IPtyForkOptions): void {
@@ -90,7 +113,7 @@ export class TerminalProcess implements ITerminalChildProcess, IDisposable {
const ptyProcess = pty.spawn(shellLaunchConfig.executable!, args, options);
this._ptyProcess = ptyProcess;
this._processStartupComplete = new Promise<void>(c => {
this.onProcessIdReady(() => c());
this.onProcessReady(() => c());
});
ptyProcess.on('data', data => {
this._onProcessData.fire(data);
@@ -118,7 +141,7 @@ export class TerminalProcess implements ITerminalChildProcess, IDisposable {
this._titleInterval = null;
this._onProcessData.dispose();
this._onProcessExit.dispose();
this._onProcessIdReady.dispose();
this._onProcessReady.dispose();
this._onProcessTitleChanged.dispose();
}
@@ -169,7 +192,7 @@ export class TerminalProcess implements ITerminalChildProcess, IDisposable {
}
private _sendProcessId(ptyProcess: pty.IPty) {
this._onProcessIdReady.fire(ptyProcess.pid);
this._onProcessReady.fire({ pid: ptyProcess.pid, cwd: this._initialCwd });
}
private _sendProcessTitle(ptyProcess: pty.IPty): void {
@@ -200,6 +223,9 @@ export class TerminalProcess implements ITerminalChildProcess, IDisposable {
if (this._isDisposed) {
return;
}
if (typeof cols !== 'number' || typeof rows !== 'number' || isNaN(cols) || isNaN(rows)) {
return;
}
// Ensure that cols and rows are always >= 1, this prevents a native
// exception in winpty.
if (this._ptyProcess) {