diff --git a/node/mock-task.ts b/node/mock-task.ts index 633a7dc44..4aa986dea 100644 --- a/node/mock-task.ts +++ b/node/mock-task.ts @@ -1,4 +1,3 @@ -import Q = require('q'); import path = require('path'); import fs = require('fs'); import task = require('./task'); @@ -331,7 +330,7 @@ export function mv(source: string, dest: string, force: boolean, continueOnError //----------------------------------------------------- // Exec convenience wrapper //----------------------------------------------------- -export function exec(tool: string, args: any, options?: trm.IExecOptions): Q.Promise { +export function exec(tool: string, args: any, options?: trm.IExecOptions): Promise { var toolPath = which(tool, true); var tr: trm.ToolRunner = this.tool(toolPath); if (args) { diff --git a/node/mock-toolrunner.ts b/node/mock-toolrunner.ts index 8f5a3380a..8a83caf4b 100644 --- a/node/mock-toolrunner.ts +++ b/node/mock-toolrunner.ts @@ -1,4 +1,3 @@ -import Q = require('q'); import os = require('os'); import events = require('events'); import ma = require('./mock-answer'); @@ -268,107 +267,8 @@ export class ToolRunner extends events.EventEmitter { * @deprecated use `execAsync` instead * @returns a promise with return code. */ - public exec(options?: IExecOptions): Q.Promise { - var defer = Q.defer(); - - this._debug('exec tool: ' + this.toolPath); - this._debug('Arguments:'); - this.args.forEach((arg) => { - this._debug(' ' + arg); - }); - - var success = true; - options = options || {}; - - var ops: IExecOptions = { - cwd: options.cwd || process.cwd(), - env: options.env || process.env, - silent: options.silent || false, - outStream: options.outStream || process.stdout, - errStream: options.errStream || process.stderr, - failOnStdErr: options.failOnStdErr || false, - ignoreReturnCode: options.ignoreReturnCode || false, - windowsVerbatimArguments: options.windowsVerbatimArguments - }; - - var argString = this.args.join(' ') || ''; - var cmdString = this.toolPath; - if (argString) { - cmdString += (' ' + argString); - } - - // Using split/join to replace the temp path - cmdString = this.ignoreTempPath(cmdString); - - if (!ops.silent) { - if(this.pipeOutputToTool) { - var pipeToolArgString = this.pipeOutputToTool.args.join(' ') || ''; - var pipeToolCmdString = this.ignoreTempPath(this.pipeOutputToTool.toolPath); - if(pipeToolArgString) { - pipeToolCmdString += (' ' + pipeToolArgString); - } - - cmdString += ' | ' + pipeToolCmdString; - } - - ops.outStream.write('[command]' + cmdString + os.EOL); - } - - // TODO: filter process.env - var res = mock.getResponse('exec', cmdString, debug); - if (res.stdout) { - this.emit('stdout', res.stdout); - if (!ops.silent) { - ops.outStream.write(res.stdout + os.EOL); - } - const stdLineArray = res.stdout.split(os.EOL); - for (const line of stdLineArray.slice(0, -1)) { - this.emit('stdline', line); - } - if(stdLineArray.length > 0 && stdLineArray[stdLineArray.length - 1].length > 0) { - this.emit('stdline', stdLineArray[stdLineArray.length - 1]); - } - } - - if (res.stderr) { - this.emit('stderr', res.stderr); - - success = !ops.failOnStdErr; - if (!ops.silent) { - var s = ops.failOnStdErr ? ops.errStream : ops.outStream; - s.write(res.stderr + os.EOL); - } - const stdErrArray = res.stderr.split(os.EOL); - for (const line of stdErrArray.slice(0, -1)) { - this.emit('errline', line); - } - if (stdErrArray.length > 0 && stdErrArray[stdErrArray.length - 1].length > 0) { - this.emit('errline', stdErrArray[stdErrArray.length - 1]); - } - } - - - var code = res.code; - - if (!ops.silent) { - ops.outStream.write('rc:' + res.code + os.EOL); - } - - if (code != 0 && !ops.ignoreReturnCode) { - success = false; - } - - if (!ops.silent) { - ops.outStream.write('success:' + success + os.EOL); - } - if (success) { - defer.resolve(code); - } - else { - defer.reject(new Error(this.toolPath + ' failed with return code: ' + code)); - } - - return >defer.promise; + public exec(options?: IExecOptions): Promise { + return this.execAsync(options); } // diff --git a/node/package-lock.json b/node/package-lock.json index 01c3085b1..2b50089d7 100644 --- a/node/package-lock.json +++ b/node/package-lock.json @@ -32,12 +32,6 @@ "integrity": "sha1-cUcXaFJ3TsTW3WJoA4iK32uZn+s=", "dev": true }, - "@types/q": { - "version": "1.5.8", - "resolved": "https://pkgs.dev.azure.com/mseng/PipelineTools/_packaging/PipelineTools_PublicPackages/npm/registry/@types/q/-/q-1.5.8.tgz", - "integrity": "sha1-lfbGoI8q2Gi6Iw6tHS1/e+PbODc=", - "dev": true - }, "@types/semver": { "version": "7.5.8", "resolved": "https://pkgs.dev.azure.com/mseng/PipelineTools/_packaging/PipelineTools_PublicPackages/npm/registry/@types/semver/-/semver-7.5.8.tgz", @@ -674,11 +668,6 @@ "integrity": "sha1-O6ODNzNkbZ0+SZWUbBNlpn+wekI=", "dev": true }, - "q": { - "version": "1.5.1", - "resolved": "https://pkgs.dev.azure.com/mseng/PipelineTools/_packaging/PipelineTools_PublicPackages/npm/registry/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" - }, "randombytes": { "version": "2.1.0", "resolved": "https://pkgs.dev.azure.com/mseng/PipelineTools/_packaging/PipelineTools_PublicPackages/npm/registry/randombytes/-/randombytes-2.1.0.tgz", diff --git a/node/package.json b/node/package.json index 3073e290d..a6b526564 100644 --- a/node/package.json +++ b/node/package.json @@ -30,7 +30,6 @@ "adm-zip": "^0.5.10", "minimatch": "3.0.5", "nodejs-file-downloader": "^4.11.1", - "q": "^1.5.1", "semver": "^5.7.2", "shelljs": "^0.8.5", "uuid": "^3.0.1" @@ -39,7 +38,6 @@ "@types/minimatch": "3.0.3", "@types/mocha": "^9.1.1", "@types/node": "^16.11.39", - "@types/q": "^1.5.4", "@types/semver": "^7.3.4", "@types/shelljs": "^0.8.8", "mocha": "^9.2.2", diff --git a/node/task.ts b/node/task.ts index 7c11beb9a..81d715908 100644 --- a/node/task.ts +++ b/node/task.ts @@ -1,4 +1,3 @@ -import Q = require('q'); import shell = require('shelljs'); import childProcess = require('child_process'); import fs = require('fs'); @@ -1534,7 +1533,7 @@ export function execAsync(tool: string, args: any, options?: trm.IExecOptions): * @param options optional exec options. See IExecOptions * @returns number */ -export function exec(tool: string, args: any, options?: trm.IExecOptions): Q.Promise { +export function exec(tool: string, args: any, options?: trm.IExecOptions): Promise { let tr: trm.ToolRunner = this.tool(tool); if (args) { if (args instanceof Array) { diff --git a/node/toolrunner.ts b/node/toolrunner.ts index 17e102610..2826c01a9 100644 --- a/node/toolrunner.ts +++ b/node/toolrunner.ts @@ -1,4 +1,3 @@ -import Q = require('q'); import os = require('os'); import events = require('events'); import child = require('child_process'); @@ -799,203 +798,201 @@ export class ToolRunner extends events.EventEmitter { }); } - private execWithPiping(pipeOutputToTool: ToolRunner, options?: IExecOptions): Q.Promise { - var defer = Q.defer(); + private execWithPiping(pipeOutputToTool: ToolRunner, options?: IExecOptions): Promise { + return new Promise((resolve, reject) => { + this._debug('exec tool: ' + this.toolPath); + this._debug('arguments:'); + this.args.forEach((arg) => { + this._debug(' ' + arg); + }); - this._debug('exec tool: ' + this.toolPath); - this._debug('arguments:'); - this.args.forEach((arg) => { - this._debug(' ' + arg); - }); + let success = true; + const optionsNonNull = this._cloneExecOptions(options); - let success = true; - const optionsNonNull = this._cloneExecOptions(options); + if (!optionsNonNull.silent) { + optionsNonNull.outStream!.write(this._getCommandString(optionsNonNull) + os.EOL); + } - if (!optionsNonNull.silent) { - optionsNonNull.outStream!.write(this._getCommandString(optionsNonNull) + os.EOL); - } + let cp: child.ChildProcess; + let toolPath: string = pipeOutputToTool.toolPath; + let toolPathFirst: string; + let successFirst = true; + let returnCodeFirst: number; + let fileStream: fs.WriteStream | null; + let waitingEvents: number = 0; // number of process or stream events we are waiting on to complete + let returnCode: number = 0; + let error: any; - let cp: child.ChildProcess; - let toolPath: string = pipeOutputToTool.toolPath; - let toolPathFirst: string; - let successFirst = true; - let returnCodeFirst: number; - let fileStream: fs.WriteStream | null; - let waitingEvents: number = 0; // number of process or stream events we are waiting on to complete - let returnCode: number = 0; - let error: any; + toolPathFirst = this.toolPath; - toolPathFirst = this.toolPath; + // Following node documentation example from this link on how to pipe output of one process to another + // https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options - // Following node documentation example from this link on how to pipe output of one process to another - // https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options + //start the child process for both tools + waitingEvents++; + var cpFirst = child.spawn( + this._getSpawnFileName(optionsNonNull), + this._getSpawnArgs(optionsNonNull), + this._getSpawnOptions(optionsNonNull)); - //start the child process for both tools - waitingEvents++; - var cpFirst = child.spawn( - this._getSpawnFileName(optionsNonNull), - this._getSpawnArgs(optionsNonNull), - this._getSpawnOptions(optionsNonNull)); + waitingEvents++; + cp = child.spawn( + pipeOutputToTool._getSpawnFileName(optionsNonNull), + pipeOutputToTool._getSpawnArgs(optionsNonNull), + pipeOutputToTool._getSpawnOptions(optionsNonNull)); - waitingEvents++; - cp = child.spawn( - pipeOutputToTool._getSpawnFileName(optionsNonNull), - pipeOutputToTool._getSpawnArgs(optionsNonNull), - pipeOutputToTool._getSpawnOptions(optionsNonNull)); + fileStream = this.pipeOutputToFile ? fs.createWriteStream(this.pipeOutputToFile) : null; + if (fileStream) { + waitingEvents++; + fileStream.on('finish', () => { + waitingEvents--; //file write is complete + fileStream = null; + if (waitingEvents == 0) { + if (error) { + return reject(error); + } else { + return resolve(returnCode); + } + } + }); + fileStream.on('error', (err: Error) => { + waitingEvents--; //there were errors writing to the file, write is done + this._debug(`Failed to pipe output of ${toolPathFirst} to file ${this.pipeOutputToFile}. Error = ${err}`); + fileStream = null; + if (waitingEvents == 0) { + if (error) { + return reject(error); + } else { + return resolve(returnCode); + } + } + }); + } - fileStream = this.pipeOutputToFile ? fs.createWriteStream(this.pipeOutputToFile) : null; - if (fileStream) { - waitingEvents++; - fileStream.on('finish', () => { - waitingEvents--; //file write is complete - fileStream = null; - if (waitingEvents == 0) { - if (error) { - defer.reject(error); - } else { - defer.resolve(returnCode); + //pipe stdout of first tool to stdin of second tool + cpFirst.stdout?.on('data', (data: Buffer) => { + try { + if (fileStream) { + fileStream.write(data); } + cp.stdin?.write(data); + } catch (err) { + this._debug('Failed to pipe output of ' + toolPathFirst + ' to ' + toolPath); + this._debug(toolPath + ' might have exited due to errors prematurely. Verify the arguments passed are valid.'); + } + }); + cpFirst.stderr?.on('data', (data: Buffer) => { + if (fileStream) { + fileStream.write(data); + } + successFirst = !optionsNonNull.failOnStdErr; + if (!optionsNonNull.silent) { + var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream! : optionsNonNull.outStream!; + s.write(data); } }); - fileStream.on('error', (err: Error) => { - waitingEvents--; //there were errors writing to the file, write is done - this._debug(`Failed to pipe output of ${toolPathFirst} to file ${this.pipeOutputToFile}. Error = ${err}`); - fileStream = null; + cpFirst.on('error', (err: Error) => { + waitingEvents--; //first process is complete with errors + if (fileStream) { + fileStream.end(); + } + cp.stdin?.end(); + error = new Error(toolPathFirst + ' failed. ' + err.message); if (waitingEvents == 0) { - if (error) { - defer.reject(error); - } else { - defer.resolve(returnCode); - } + return reject(error); } }); - } - - //pipe stdout of first tool to stdin of second tool - cpFirst.stdout?.on('data', (data: Buffer) => { - try { + cpFirst.on('close', (code: number, signal: any) => { + waitingEvents--; //first process is complete + if (code != 0 && !optionsNonNull.ignoreReturnCode) { + successFirst = false; + returnCodeFirst = code; + returnCode = returnCodeFirst; + } + this._debug('success of first tool:' + successFirst); if (fileStream) { - fileStream.write(data); + fileStream.end(); } - cp.stdin?.write(data); - } catch (err) { - this._debug('Failed to pipe output of ' + toolPathFirst + ' to ' + toolPath); - this._debug(toolPath + ' might have exited due to errors prematurely. Verify the arguments passed are valid.'); - } - }); - cpFirst.stderr?.on('data', (data: Buffer) => { - if (fileStream) { - fileStream.write(data); - } - successFirst = !optionsNonNull.failOnStdErr; - if (!optionsNonNull.silent) { - var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream! : optionsNonNull.outStream!; - s.write(data); - } - }); - cpFirst.on('error', (err: Error) => { - waitingEvents--; //first process is complete with errors - if (fileStream) { - fileStream.end(); - } - cp.stdin?.end(); - error = new Error(toolPathFirst + ' failed. ' + err.message); - if (waitingEvents == 0) { - defer.reject(error); - } - }); - cpFirst.on('close', (code: number, signal: any) => { - waitingEvents--; //first process is complete - if (code != 0 && !optionsNonNull.ignoreReturnCode) { - successFirst = false; - returnCodeFirst = code; - returnCode = returnCodeFirst; - } - this._debug('success of first tool:' + successFirst); - if (fileStream) { - fileStream.end(); - } - cp.stdin?.end(); - if (waitingEvents == 0) { - if (error) { - defer.reject(error); - } else { - defer.resolve(returnCode); + cp.stdin?.end(); + if (waitingEvents == 0) { + if (error) { + return reject(error); + } else { + return resolve(returnCode); + } } - } - }); + }); - let stdLineBuffer = ''; - cp.stdout?.on('data', (data: Buffer) => { - this.emit('stdout', data); + let stdLineBuffer = ''; + cp.stdout?.on('data', (data: Buffer) => { + this.emit('stdout', data); - if (!optionsNonNull.silent) { - optionsNonNull.outStream!.write(data); - } + if (!optionsNonNull.silent) { + optionsNonNull.outStream!.write(data); + } - stdLineBuffer = this._processLineBuffer(data, stdLineBuffer, (line: string) => { - this.emit('stdline', line); + stdLineBuffer = this._processLineBuffer(data, stdLineBuffer, (line: string) => { + this.emit('stdline', line); + }); }); - }); - let errLineBuffer = ''; - cp.stderr?.on('data', (data: Buffer) => { - this.emit('stderr', data); + let errLineBuffer = ''; + cp.stderr?.on('data', (data: Buffer) => { + this.emit('stderr', data); - success = !optionsNonNull.failOnStdErr; - if (!optionsNonNull.silent) { - var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream! : optionsNonNull.outStream!; - s.write(data); - } + success = !optionsNonNull.failOnStdErr; + if (!optionsNonNull.silent) { + var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream! : optionsNonNull.outStream!; + s.write(data); + } - errLineBuffer = this._processLineBuffer(data, errLineBuffer, (line: string) => { - this.emit('errline', line); + errLineBuffer = this._processLineBuffer(data, errLineBuffer, (line: string) => { + this.emit('errline', line); + }); }); - }); - cp.on('error', (err: Error) => { - waitingEvents--; //process is done with errors - error = new Error(toolPath + ' failed. ' + err.message); - if (waitingEvents == 0) { - defer.reject(error); - } - }); + cp.on('error', (err: Error) => { + waitingEvents--; //process is done with errors + error = new Error(toolPath + ' failed. ' + err.message); + if (waitingEvents == 0) { + return reject(error); + } + }); - cp.on('close', (code: number, signal: any) => { - waitingEvents--; //process is complete - this._debug('rc:' + code); - returnCode = code; + cp.on('close', (code: number, signal: any) => { + waitingEvents--; //process is complete + this._debug('rc:' + code); + returnCode = code; - if (stdLineBuffer.length > 0) { - this.emit('stdline', stdLineBuffer); - } + if (stdLineBuffer.length > 0) { + this.emit('stdline', stdLineBuffer); + } - if (errLineBuffer.length > 0) { - this.emit('errline', errLineBuffer); - } + if (errLineBuffer.length > 0) { + this.emit('errline', errLineBuffer); + } - if (code != 0 && !optionsNonNull.ignoreReturnCode) { - success = false; - } + if (code != 0 && !optionsNonNull.ignoreReturnCode) { + success = false; + } - this._debug('success:' + success); + this._debug('success:' + success); - if (!successFirst) { //in the case output is piped to another tool, check exit code of both tools - error = new Error(toolPathFirst + ' failed with return code: ' + returnCodeFirst); - } else if (!success) { - error = new Error(toolPath + ' failed with return code: ' + code); - } + if (!successFirst) { //in the case output is piped to another tool, check exit code of both tools + error = new Error(toolPathFirst + ' failed with return code: ' + returnCodeFirst); + } else if (!success) { + error = new Error(toolPath + ' failed with return code: ' + code); + } - if (waitingEvents == 0) { - if (error) { - defer.reject(error); - } else { - defer.resolve(returnCode); + if (waitingEvents == 0) { + if (error) { + return reject(error); + } else { + return resolve(returnCode); + } } - } + }); }); - - return >defer.promise; } /** @@ -1213,127 +1210,127 @@ export class ToolRunner extends events.EventEmitter { * @param options optional exec options. See IExecOptions * @returns number */ - public exec(options?: IExecOptions): Q.Promise { + public exec(options?: IExecOptions): Promise { if (this.pipeOutputToTool) { return this.execWithPiping(this.pipeOutputToTool, options); } - var defer = Q.defer(); - - this._debug('exec tool: ' + this.toolPath); - this._debug('arguments:'); - this.args.forEach((arg) => { - this._debug(' ' + arg); - }); - - const optionsNonNull = this._cloneExecOptions(options); - if (!optionsNonNull.silent) { - optionsNonNull.outStream!.write(this._getCommandString(optionsNonNull) + os.EOL); - } - - let state = new ExecState(optionsNonNull, this.toolPath); - state.on('debug', (message: string) => { - this._debug(message); - }); + return new Promise((resolve, reject) => { + this._debug('exec tool: ' + this.toolPath); + this._debug('arguments:'); + this.args.forEach((arg) => { + this._debug(' ' + arg); + }); - let stdLineBuffer = ''; - let errLineBuffer = ''; - state.on('done', (error: Error, exitCode: number) => { - if (stdLineBuffer.length > 0) { - this.emit('stdline', stdLineBuffer); + const optionsNonNull = this._cloneExecOptions(options); + if (!optionsNonNull.silent) { + optionsNonNull.outStream!.write(this._getCommandString(optionsNonNull) + os.EOL); } - if (errLineBuffer.length > 0) { - this.emit('errline', errLineBuffer); - } + let state = new ExecState(optionsNonNull, this.toolPath); + state.on('debug', (message: string) => { + this._debug(message); + }); - if (cp) { - cp.removeAllListeners(); - } + let stdLineBuffer = ''; + let errLineBuffer = ''; + state.on('done', (error: Error, exitCode: number) => { + if (stdLineBuffer.length > 0) { + this.emit('stdline', stdLineBuffer); + } - if (error) { - defer.reject(error); - } - else { - defer.resolve(exitCode); - } - }); + if (errLineBuffer.length > 0) { + this.emit('errline', errLineBuffer); + } + if (cp) { + cp.removeAllListeners(); + } - // Edge case when the node itself cant's spawn and emit event - let cp: child.ChildProcess; - try { - cp = child.spawn(this._getSpawnFileName(options), this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(options)); - } catch (error) { - state.processError = error.message; - state.processExited = true; - state.processClosed = true; - state.CheckComplete(); + if (error) { + return reject(error); + } + else { + return resolve(exitCode); + } + }); - return defer.promise; - } - this.childProcess = cp; - // it is possible for the child process to end its last line without a new line. - // because stdout is buffered, this causes the last line to not get sent to the parent - // stream. Adding this event forces a flush before the child streams are closed. - cp.stdout?.on('finish', () => { - if (!optionsNonNull.silent) { - optionsNonNull.outStream!.write(os.EOL); + // Edge case when the node itself cant's spawn and emit event + let cp: child.ChildProcess; + try { + cp = child.spawn(this._getSpawnFileName(options), this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(options)); + } catch (error) { + state.processError = error.message; + state.processExited = true; + state.processClosed = true; + state.CheckComplete(); + + return Promise.resolve(); } - }); - cp.stdout?.on('data', (data: Buffer) => { - this.emit('stdout', data); + this.childProcess = cp; + // it is possible for the child process to end its last line without a new line. + // because stdout is buffered, this causes the last line to not get sent to the parent + // stream. Adding this event forces a flush before the child streams are closed. + cp.stdout?.on('finish', () => { + if (!optionsNonNull.silent) { + optionsNonNull.outStream!.write(os.EOL); + } + }); - if (!optionsNonNull.silent) { - optionsNonNull.outStream!.write(data); - } + cp.stdout?.on('data', (data: Buffer) => { + this.emit('stdout', data); - stdLineBuffer = this._processLineBuffer(data, stdLineBuffer, (line: string) => { - this.emit('stdline', line); + if (!optionsNonNull.silent) { + optionsNonNull.outStream!.write(data); + } + + stdLineBuffer = this._processLineBuffer(data, stdLineBuffer, (line: string) => { + this.emit('stdline', line); + }); }); - }); - cp.stderr?.on('data', (data: Buffer) => { - state.processStderr = true; - this.emit('stderr', data); + cp.stderr?.on('data', (data: Buffer) => { + state.processStderr = true; + this.emit('stderr', data); - if (!optionsNonNull.silent) { - var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream! : optionsNonNull.outStream!; - s.write(data); - } + if (!optionsNonNull.silent) { + var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream! : optionsNonNull.outStream!; + s.write(data); + } - errLineBuffer = this._processLineBuffer(data, errLineBuffer, (line: string) => { - this.emit('errline', line); + errLineBuffer = this._processLineBuffer(data, errLineBuffer, (line: string) => { + this.emit('errline', line); + }); }); - }); - cp.on('error', (err: Error) => { - state.processError = err.message; - state.processExited = true; - state.processClosed = true; - state.CheckComplete(); - }); + cp.on('error', (err: Error) => { + state.processError = err.message; + state.processExited = true; + state.processClosed = true; + state.CheckComplete(); + }); - // Do not write debug logs here. Sometimes stdio not closed yet and you can damage user output commands. - cp.on('exit', (code: number | null, signal: NodeJS.Signals | null) => { - state.processExitCode = code; - state.processExitSignal = signal; - state.processExited = true; - state.CheckComplete() - }); + // Do not write debug logs here. Sometimes stdio not closed yet and you can damage user output commands. + cp.on('exit', (code: number | null, signal: NodeJS.Signals | null) => { + state.processExitCode = code; + state.processExitSignal = signal; + state.processExited = true; + state.CheckComplete() + }); - cp.on('close', (code: number | null, signal: NodeJS.Signals | null) => { - state.processCloseCode = code; - state.processCloseSignal = signal; - state.processClosed = true; - state.processExited = true; - state.CheckComplete(); - }); + cp.on('close', (code: number | null, signal: NodeJS.Signals | null) => { + state.processCloseCode = code; + state.processCloseSignal = signal; + state.processClosed = true; + state.processExited = true; + state.CheckComplete(); + }); - return defer.promise; + return Promise.resolve(); + }); } /**