X-Git-Url: https://git.josue.xyz/?p=VSoRC%2F.git;a=blobdiff_plain;f=node_modules%2Fnode-pty%2Fsrc%2FwindowsPtyAgent.ts;fp=node_modules%2Fnode-pty%2Fsrc%2FwindowsPtyAgent.ts;h=0000000000000000000000000000000000000000;hp=cf8b65db61edb88f8b0ee78be5ca38e7b8f65e59;hb=5e96dd57ddd883604e87f62bdddcb111c63a6e1a;hpb=acb5f682a2b75b972710cabd81658f63071324b0 diff --git a/node_modules/node-pty/src/windowsPtyAgent.ts b/node_modules/node-pty/src/windowsPtyAgent.ts deleted file mode 100644 index cf8b65d..0000000 --- a/node_modules/node-pty/src/windowsPtyAgent.ts +++ /dev/null @@ -1,313 +0,0 @@ -/** - * Copyright (c) 2012-2015, Christopher Jeffrey, Peter Sunde (MIT License) - * Copyright (c) 2016, Daniel Imms (MIT License). - * Copyright (c) 2018, Microsoft Corporation (MIT License). - */ - -import * as os from 'os'; -import * as path from 'path'; -import { Socket } from 'net'; -import { ArgvOrCommandLine } from './types'; -import { fork } from 'child_process'; - -let conptyNative: IConptyNative; -let winptyNative: IWinptyNative; - -/** - * The amount of time to wait for additional data after the conpty shell process has exited before - * shutting down the socket. The timer will be reset if a new data event comes in after the timer - * has started. - */ -const FLUSH_DATA_INTERVAL = 20; - -/** - * This agent sits between the WindowsTerminal class and provides a common interface for both conpty - * and winpty. - */ -export class WindowsPtyAgent { - private _inSocket: Socket; - private _outSocket: Socket; - private _pid: number; - private _innerPid: number; - private _innerPidHandle: number; - private _closeTimeout: NodeJS.Timer; - private _exitCode: number | undefined; - - private _fd: any; - private _pty: number; - private _ptyNative: IConptyNative | IWinptyNative; - - public get inSocket(): Socket { return this._inSocket; } - public get outSocket(): Socket { return this._outSocket; } - public get fd(): any { return this._fd; } - public get innerPid(): number { return this._innerPid; } - public get pty(): number { return this._pty; } - - constructor( - file: string, - args: ArgvOrCommandLine, - env: string[], - cwd: string, - cols: number, - rows: number, - debug: boolean, - private _useConpty: boolean | undefined, - conptyInheritCursor: boolean = false - ) { - if (this._useConpty === undefined || this._useConpty === true) { - this._useConpty = this._getWindowsBuildNumber() >= 18309; - } - if (this._useConpty) { - if (!conptyNative) { - try { - conptyNative = require('../build/Release/conpty.node'); - } catch (outerError) { - try { - conptyNative = require('../build/Debug/conpty.node'); - } catch (innerError) { - console.error('innerError', innerError); - // Re-throw the exception from the Release require if the Debug require fails as well - throw outerError; - } - } - } - } else { - if (!winptyNative) { - try { - winptyNative = require('../build/Release/pty.node'); - } catch (outerError) { - try { - winptyNative = require('../build/Debug/pty.node'); - } catch (innerError) { - console.error('innerError', innerError); - // Re-throw the exception from the Release require if the Debug require fails as well - throw outerError; - } - } - } - } - this._ptyNative = this._useConpty ? conptyNative : winptyNative; - - // Sanitize input variable. - cwd = path.resolve(cwd); - - // Compose command line - const commandLine = argsToCommandLine(file, args); - - // Open pty session. - let term: IConptyProcess | IWinptyProcess; - if (this._useConpty) { - term = (this._ptyNative as IConptyNative).startProcess(file, cols, rows, debug, this._generatePipeName(), conptyInheritCursor); - } else { - term = (this._ptyNative as IWinptyNative).startProcess(file, commandLine, env, cwd, cols, rows, debug); - this._pid = (term as IWinptyProcess).pid; - this._innerPid = (term as IWinptyProcess).innerPid; - this._innerPidHandle = (term as IWinptyProcess).innerPidHandle; - } - - // Not available on windows. - this._fd = term.fd; - - // Generated incremental number that has no real purpose besides using it - // as a terminal id. - this._pty = term.pty; - - // Create terminal pipe IPC channel and forward to a local unix socket. - this._outSocket = new Socket(); - this._outSocket.setEncoding('utf8'); - this._outSocket.connect(term.conout, () => { - // TODO: Emit event on agent instead of socket? - - // Emit ready event. - this._outSocket.emit('ready_datapipe'); - }); - - this._inSocket = new Socket(); - this._inSocket.setEncoding('utf8'); - this._inSocket.connect(term.conin); - // TODO: Wait for ready event? - - if (this._useConpty) { - const connect = (this._ptyNative as IConptyNative).connect(this._pty, commandLine, cwd, env, c => this._$onProcessExit(c) -); - this._innerPid = connect.pid; - } - } - - public resize(cols: number, rows: number): void { - if (this._useConpty) { - if (this._exitCode !== undefined) { - throw new Error('Cannot resize a pty that has already exited'); - } - this._ptyNative.resize(this._pty, cols, rows); - return; - } - this._ptyNative.resize(this._pid, cols, rows); - } - - public kill(): void { - this._inSocket.readable = false; - this._inSocket.writable = false; - this._outSocket.readable = false; - this._outSocket.writable = false; - // Tell the agent to kill the pty, this releases handles to the process - if (this._useConpty) { - this._getConsoleProcessList().then(consoleProcessList => { - consoleProcessList.forEach((pid: number) => { - try { - process.kill(pid); - } catch (e) { - // Ignore if process cannot be found (kill ESRCH error) - } - }); - (this._ptyNative as IConptyNative).kill(this._pty); - }); - } else { - (this._ptyNative as IWinptyNative).kill(this._pid, this._innerPidHandle); - // Since pty.kill closes the handle it will kill most processes by itself - // and process IDs can be reused as soon as all handles to them are - // dropped, we want to immediately kill the entire console process list. - // If we do not force kill all processes here, node servers in particular - // seem to become detached and remain running (see - // Microsoft/vscode#26807). - const processList: number[] = (this._ptyNative as IWinptyNative).getProcessList(this._pid); - processList.forEach(pid => { - try { - process.kill(pid); - } catch (e) { - // Ignore if process cannot be found (kill ESRCH error) - } - }); - } - } - - private _getConsoleProcessList(): Promise { - return new Promise(resolve => { - const agent = fork(path.join(__dirname, 'conpty_console_list_agent'), [ this._innerPid.toString() ]); - agent.on('message', message => { - clearTimeout(timeout); - resolve(message.consoleProcessList); - }); - const timeout = setTimeout(() => { - // Something went wrong, just send back the shell PID - agent.kill(); - resolve([ this._innerPid ]); - }, 5000); - }); - } - - public get exitCode(): number { - if (this._useConpty) { - return this._exitCode; - } - return (this._ptyNative as IWinptyNative).getExitCode(this._innerPidHandle); - } - - private _getWindowsBuildNumber(): number { - const osVersion = (/(\d+)\.(\d+)\.(\d+)/g).exec(os.release()); - let buildNumber: number = 0; - if (osVersion && osVersion.length === 4) { - buildNumber = parseInt(osVersion[3]); - } - return buildNumber; - } - - private _generatePipeName(): string { - return `conpty-${Math.random() * 10000000}`; - } - - /** - * Triggered from the native side when a contpy process exits. - */ - private _$onProcessExit(exitCode: number): void { - this._exitCode = exitCode; - this._flushDataAndCleanUp(); - this._outSocket.on('data', () => this._flushDataAndCleanUp()); - } - - private _flushDataAndCleanUp(): void { - if (this._closeTimeout) { - clearTimeout(this._closeTimeout); - } - this._closeTimeout = setTimeout(() => this._cleanUpProcess(), FLUSH_DATA_INTERVAL); - } - - private _cleanUpProcess(): void { - this._inSocket.readable = false; - this._inSocket.writable = false; - this._outSocket.readable = false; - this._outSocket.writable = false; - this._outSocket.destroy(); - } -} - -// Convert argc/argv into a Win32 command-line following the escaping convention -// documented on MSDN (e.g. see CommandLineToArgvW documentation). Copied from -// winpty project. -export function argsToCommandLine(file: string, args: ArgvOrCommandLine): string { - if (isCommandLine(args)) { - if (args.length === 0) { - return file; - } - return `${argsToCommandLine(file, [])} ${args}`; - } - const argv = [file]; - Array.prototype.push.apply(argv, args); - let result = ''; - for (let argIndex = 0; argIndex < argv.length; argIndex++) { - if (argIndex > 0) { - result += ' '; - } - const arg = argv[argIndex]; - // if it is empty or it contains whitespace and is not already quoted - const hasLopsidedEnclosingQuote = xOr((arg[0] !== '"'), (arg[arg.length - 1] !== '"')); - const hasNoEnclosingQuotes = ((arg[0] !== '"') && (arg[arg.length - 1] !== '"')); - const quote = - arg === '' || - (arg.indexOf(' ') !== -1 || - arg.indexOf('\t') !== -1) && - ((arg.length > 1) && - (hasLopsidedEnclosingQuote || hasNoEnclosingQuotes)); - if (quote) { - result += '\"'; - } - let bsCount = 0; - for (let i = 0; i < arg.length; i++) { - const p = arg[i]; - if (p === '\\') { - bsCount++; - } else if (p === '"') { - result += repeatText('\\', bsCount * 2 + 1); - result += '"'; - bsCount = 0; - } else { - result += repeatText('\\', bsCount); - bsCount = 0; - result += p; - } - } - if (quote) { - result += repeatText('\\', bsCount * 2); - result += '\"'; - } else { - result += repeatText('\\', bsCount); - } - } - return result; -} - -function isCommandLine(args: ArgvOrCommandLine): args is string { - return typeof args === 'string'; -} - -function repeatText(text: string, count: number): string { - let result = ''; - for (let i = 0; i < count; i++) { - result += text; - } - return result; -} - -function xOr(arg1: boolean, arg2: boolean): boolean { - return ((arg1 && !arg2) || (!arg1 && arg2)); -}