Comparing version 1.0.0 to 1.1.0-beta1
@@ -34,3 +34,2 @@ "use strict"; | ||
this._innerPid = 0; | ||
this._innerPidHandle = 0; | ||
if (this._useConpty === undefined || this._useConpty === true) { | ||
@@ -87,3 +86,2 @@ this._useConpty = this._getWindowsBuildNumber() >= 18309; | ||
this._innerPid = term.innerPid; | ||
this._innerPidHandle = term.innerPidHandle; | ||
} | ||
@@ -177,6 +175,5 @@ // Not available on windows. | ||
else { | ||
this._ptyNative.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. | ||
// Because pty.kill closes the handle, it will kill most processes by itself. | ||
// Process IDs can be reused as soon as all handles to them are | ||
// dropped, so we want to immediately kill the entire console process list. | ||
// If we do not force kill all processes here, node servers in particular | ||
@@ -186,2 +183,3 @@ // seem to become detached and remain running (see | ||
var processList = this._ptyNative.getProcessList(this._pid); | ||
this._ptyNative.kill(this._pid, this._innerPid); | ||
processList.forEach(function (pid) { | ||
@@ -218,3 +216,4 @@ try { | ||
} | ||
return this._ptyNative.getExitCode(this._innerPidHandle); | ||
var winptyExitCode = this._ptyNative.getExitCode(this._innerPid); | ||
return winptyExitCode === -1 ? undefined : winptyExitCode; | ||
}, | ||
@@ -221,0 +220,0 @@ enumerable: false, |
@@ -87,118 +87,120 @@ "use strict"; | ||
if (process.platform === 'win32') { | ||
describe('WindowsTerminal', function () { | ||
describe('kill', function () { | ||
it('should not crash parent process', function (done) { | ||
var term = new windowsTerminal_1.WindowsTerminal('cmd.exe', [], {}); | ||
term.kill(); | ||
// Add done call to deferred function queue to ensure the kill call has completed | ||
term._defer(done); | ||
}); | ||
it('should kill the process tree', function (done) { | ||
this.timeout(5000); | ||
var term = new windowsTerminal_1.WindowsTerminal('cmd.exe', [], {}); | ||
// Start sub-processes | ||
term.write('powershell.exe\r'); | ||
term.write('notepad.exe\r'); | ||
term.write('node.exe\r'); | ||
pollForProcessTreeSize(term.pid, 4, 500, 5000).then(function (list) { | ||
assert.strictEqual(list[0].name.toLowerCase(), 'cmd.exe'); | ||
assert.strictEqual(list[1].name.toLowerCase(), 'powershell.exe'); | ||
assert.strictEqual(list[2].name.toLowerCase(), 'notepad.exe'); | ||
assert.strictEqual(list[3].name.toLowerCase(), 'node.exe'); | ||
[true, false].forEach(function (useConpty) { | ||
describe("WindowsTerminal (useConpty = " + useConpty + ")", function () { | ||
describe('kill', function () { | ||
it('should not crash parent process', function (done) { | ||
var term = new windowsTerminal_1.WindowsTerminal('cmd.exe', [], { useConpty: useConpty }); | ||
term.kill(); | ||
var desiredState = {}; | ||
desiredState[list[0].pid] = false; | ||
desiredState[list[1].pid] = false; | ||
desiredState[list[2].pid] = true; | ||
desiredState[list[3].pid] = false; | ||
pollForProcessState(desiredState).then(function () { | ||
// Kill notepad before done | ||
process.kill(list[2].pid); | ||
done(); | ||
// Add done call to deferred function queue to ensure the kill call has completed | ||
term._defer(done); | ||
}); | ||
it('should kill the process tree', function (done) { | ||
this.timeout(5000); | ||
var term = new windowsTerminal_1.WindowsTerminal('cmd.exe', [], { useConpty: useConpty }); | ||
// Start sub-processes | ||
term.write('powershell.exe\r'); | ||
term.write('notepad.exe\r'); | ||
term.write('node.exe\r'); | ||
pollForProcessTreeSize(term.pid, 4, 500, 5000).then(function (list) { | ||
assert.strictEqual(list[0].name.toLowerCase(), 'cmd.exe'); | ||
assert.strictEqual(list[1].name.toLowerCase(), 'powershell.exe'); | ||
assert.strictEqual(list[2].name.toLowerCase(), 'notepad.exe'); | ||
assert.strictEqual(list[3].name.toLowerCase(), 'node.exe'); | ||
term.kill(); | ||
var desiredState = {}; | ||
desiredState[list[0].pid] = false; | ||
desiredState[list[1].pid] = false; | ||
desiredState[list[2].pid] = true; | ||
desiredState[list[3].pid] = false; | ||
pollForProcessState(desiredState).then(function () { | ||
// Kill notepad before done | ||
process.kill(list[2].pid); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('resize', function () { | ||
it('should throw a non-native exception when resizing an invalid value', function () { | ||
var term = new windowsTerminal_1.WindowsTerminal('cmd.exe', [], {}); | ||
assert.throws(function () { return term.resize(-1, -1); }); | ||
assert.throws(function () { return term.resize(0, 0); }); | ||
assert.doesNotThrow(function () { return term.resize(1, 1); }); | ||
describe('resize', function () { | ||
it('should throw a non-native exception when resizing an invalid value', function () { | ||
var term = new windowsTerminal_1.WindowsTerminal('cmd.exe', [], { useConpty: useConpty }); | ||
assert.throws(function () { return term.resize(-1, -1); }); | ||
assert.throws(function () { return term.resize(0, 0); }); | ||
assert.doesNotThrow(function () { return term.resize(1, 1); }); | ||
}); | ||
it('should throw a non-native exception when resizing a killed terminal', function (done) { | ||
var term = new windowsTerminal_1.WindowsTerminal('cmd.exe', [], { useConpty: useConpty }); | ||
term._defer(function () { | ||
term.on('exit', function () { | ||
assert.throws(function () { return term.resize(1, 1); }); | ||
done(); | ||
}); | ||
term.destroy(); | ||
}); | ||
}); | ||
}); | ||
it('should throw an non-native exception when resizing a killed terminal', function (done) { | ||
var term = new windowsTerminal_1.WindowsTerminal('cmd.exe', [], {}); | ||
term._defer(function () { | ||
describe('Args as CommandLine', function () { | ||
it('should not fail running a file containing a space in the path', function (done) { | ||
var spaceFolder = path.resolve(__dirname, '..', 'fixtures', 'space folder'); | ||
if (!fs.existsSync(spaceFolder)) { | ||
fs.mkdirSync(spaceFolder); | ||
} | ||
var cmdCopiedPath = path.resolve(spaceFolder, 'cmd.exe'); | ||
var data = fs.readFileSync(process.env.windir + "\\System32\\cmd.exe"); | ||
fs.writeFileSync(cmdCopiedPath, data); | ||
if (!fs.existsSync(cmdCopiedPath)) { | ||
// Skip test if git bash isn't installed | ||
return; | ||
} | ||
var term = new windowsTerminal_1.WindowsTerminal(cmdCopiedPath, '/c echo "hello world"', { useConpty: useConpty }); | ||
var result = ''; | ||
term.on('data', function (data) { | ||
result += data; | ||
}); | ||
term.on('exit', function () { | ||
assert.throws(function () { return term.resize(1, 1); }); | ||
assert.ok(result.indexOf('hello world') >= 1); | ||
done(); | ||
}); | ||
term.destroy(); | ||
}); | ||
}); | ||
}); | ||
describe('Args as CommandLine', function () { | ||
it('should not fail running a file containing a space in the path', function (done) { | ||
var spaceFolder = path.resolve(__dirname, '..', 'fixtures', 'space folder'); | ||
if (!fs.existsSync(spaceFolder)) { | ||
fs.mkdirSync(spaceFolder); | ||
} | ||
var cmdCopiedPath = path.resolve(spaceFolder, 'cmd.exe'); | ||
var data = fs.readFileSync(process.env.windir + "\\System32\\cmd.exe"); | ||
fs.writeFileSync(cmdCopiedPath, data); | ||
if (!fs.existsSync(cmdCopiedPath)) { | ||
// Skip test if git bash isn't installed | ||
return; | ||
} | ||
var term = new windowsTerminal_1.WindowsTerminal(cmdCopiedPath, '/c echo "hello world"', {}); | ||
var result = ''; | ||
term.on('data', function (data) { | ||
result += data; | ||
describe('env', function () { | ||
it('should set environment variables of the shell', function (done) { | ||
var term = new windowsTerminal_1.WindowsTerminal('cmd.exe', '/C echo %FOO%', { env: { FOO: 'BAR' } }); | ||
var result = ''; | ||
term.on('data', function (data) { | ||
result += data; | ||
}); | ||
term.on('exit', function () { | ||
assert.ok(result.indexOf('BAR') >= 0); | ||
done(); | ||
}); | ||
}); | ||
term.on('exit', function () { | ||
assert.ok(result.indexOf('hello world') >= 1); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
describe('env', function () { | ||
it('should set environment variables of the shell', function (done) { | ||
var term = new windowsTerminal_1.WindowsTerminal('cmd.exe', '/C echo %FOO%', { env: { FOO: 'BAR' } }); | ||
var result = ''; | ||
term.on('data', function (data) { | ||
result += data; | ||
describe('On close', function () { | ||
it('should return process zero exit codes', function (done) { | ||
var term = new windowsTerminal_1.WindowsTerminal('cmd.exe', '/C exit', { useConpty: useConpty }); | ||
term.on('exit', function (code) { | ||
assert.strictEqual(code, 0); | ||
done(); | ||
}); | ||
}); | ||
term.on('exit', function () { | ||
assert.ok(result.indexOf('BAR') >= 0); | ||
done(); | ||
it('should return process non-zero exit codes', function (done) { | ||
var term = new windowsTerminal_1.WindowsTerminal('cmd.exe', '/C exit 2', { useConpty: useConpty }); | ||
term.on('exit', function (code) { | ||
assert.strictEqual(code, 2); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('On close', function () { | ||
it('should return process zero exit codes', function (done) { | ||
var term = new windowsTerminal_1.WindowsTerminal('cmd.exe', '/C exit'); | ||
term.on('exit', function (code) { | ||
assert.equal(code, 0); | ||
done(); | ||
describe('Write', function () { | ||
it('should accept input', function (done) { | ||
var term = new windowsTerminal_1.WindowsTerminal('cmd.exe', '', { useConpty: useConpty }); | ||
term.write('exit\r'); | ||
term.on('exit', function () { | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('should return process non-zero exit codes', function (done) { | ||
var term = new windowsTerminal_1.WindowsTerminal('cmd.exe', '/C exit 2'); | ||
term.on('exit', function (code) { | ||
assert.equal(code, 2); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
describe('winpty', function () { | ||
it('should accept input', function (done) { | ||
var term = new windowsTerminal_1.WindowsTerminal('cmd.exe', '', { useConpty: false }); | ||
term.write('exit\r'); | ||
term.on('exit', function () { | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
} | ||
//# sourceMappingURL=windowsTerminal.test.js.map |
@@ -7,3 +7,3 @@ { | ||
}, | ||
"version": "1.0.0", | ||
"version": "1.1.0-beta1", | ||
"license": "MIT", | ||
@@ -10,0 +10,0 @@ "main": "./lib/index.js", |
@@ -15,6 +15,6 @@ /** | ||
startProcess(file: string, commandLine: string, env: string[], cwd: string, cols: number, rows: number, debug: boolean): IWinptyProcess; | ||
resize(processHandle: number, cols: number, rows: number): void; | ||
kill(pid: number, innerPidHandle: number): void; | ||
resize(pid: number, cols: number, rows: number): void; | ||
kill(pid: number, innerPid: number): void; | ||
getProcessList(pid: number): number[]; | ||
getExitCode(innerPidHandle: number): number; | ||
getExitCode(innerPid: number): number; | ||
} | ||
@@ -44,3 +44,2 @@ | ||
innerPid: number; | ||
innerPidHandle: number; | ||
} | ||
@@ -47,0 +46,0 @@ |
@@ -34,3 +34,2 @@ /** | ||
private _innerPid: number = 0; | ||
private _innerPidHandle: number = 0; | ||
private _closeTimeout: NodeJS.Timer | undefined; | ||
@@ -109,3 +108,2 @@ private _exitCode: number | undefined; | ||
this._innerPid = (term as IWinptyProcess).innerPid; | ||
this._innerPidHandle = (term as IWinptyProcess).innerPidHandle; | ||
} | ||
@@ -179,6 +177,5 @@ | ||
} 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. | ||
// Because pty.kill closes the handle, it will kill most processes by itself. | ||
// Process IDs can be reused as soon as all handles to them are | ||
// dropped, so we want to immediately kill the entire console process list. | ||
// If we do not force kill all processes here, node servers in particular | ||
@@ -188,2 +185,3 @@ // seem to become detached and remain running (see | ||
const processList: number[] = (this._ptyNative as IWinptyNative).getProcessList(this._pid); | ||
(this._ptyNative as IWinptyNative).kill(this._pid, this._innerPid); | ||
processList.forEach(pid => { | ||
@@ -219,3 +217,4 @@ try { | ||
} | ||
return (this._ptyNative as IWinptyNative).getExitCode(this._innerPidHandle); | ||
const winptyExitCode = (this._ptyNative as IWinptyNative).getExitCode(this._innerPid); | ||
return winptyExitCode === -1 ? undefined : winptyExitCode; | ||
} | ||
@@ -222,0 +221,0 @@ |
@@ -91,121 +91,123 @@ /** | ||
if (process.platform === 'win32') { | ||
describe('WindowsTerminal', () => { | ||
describe('kill', () => { | ||
it('should not crash parent process', (done) => { | ||
const term = new WindowsTerminal('cmd.exe', [], {}); | ||
term.kill(); | ||
// Add done call to deferred function queue to ensure the kill call has completed | ||
(<any>term)._defer(done); | ||
}); | ||
it('should kill the process tree', function (done: Mocha.Done): void { | ||
this.timeout(5000); | ||
const term = new WindowsTerminal('cmd.exe', [], {}); | ||
// Start sub-processes | ||
term.write('powershell.exe\r'); | ||
term.write('notepad.exe\r'); | ||
term.write('node.exe\r'); | ||
pollForProcessTreeSize(term.pid, 4, 500, 5000).then(list => { | ||
assert.strictEqual(list[0].name.toLowerCase(), 'cmd.exe'); | ||
assert.strictEqual(list[1].name.toLowerCase(), 'powershell.exe'); | ||
assert.strictEqual(list[2].name.toLowerCase(), 'notepad.exe'); | ||
assert.strictEqual(list[3].name.toLowerCase(), 'node.exe'); | ||
[true, false].forEach((useConpty) => { | ||
describe(`WindowsTerminal (useConpty = ${useConpty})`, () => { | ||
describe('kill', () => { | ||
it('should not crash parent process', (done) => { | ||
const term = new WindowsTerminal('cmd.exe', [], { useConpty }); | ||
term.kill(); | ||
const desiredState: IProcessState = {}; | ||
desiredState[list[0].pid] = false; | ||
desiredState[list[1].pid] = false; | ||
desiredState[list[2].pid] = true; | ||
desiredState[list[3].pid] = false; | ||
pollForProcessState(desiredState).then(() => { | ||
// Kill notepad before done | ||
process.kill(list[2].pid); | ||
done(); | ||
// Add done call to deferred function queue to ensure the kill call has completed | ||
(<any>term)._defer(done); | ||
}); | ||
it('should kill the process tree', function (done: Mocha.Done): void { | ||
this.timeout(5000); | ||
const term = new WindowsTerminal('cmd.exe', [], { useConpty }); | ||
// Start sub-processes | ||
term.write('powershell.exe\r'); | ||
term.write('notepad.exe\r'); | ||
term.write('node.exe\r'); | ||
pollForProcessTreeSize(term.pid, 4, 500, 5000).then(list => { | ||
assert.strictEqual(list[0].name.toLowerCase(), 'cmd.exe'); | ||
assert.strictEqual(list[1].name.toLowerCase(), 'powershell.exe'); | ||
assert.strictEqual(list[2].name.toLowerCase(), 'notepad.exe'); | ||
assert.strictEqual(list[3].name.toLowerCase(), 'node.exe'); | ||
term.kill(); | ||
const desiredState: IProcessState = {}; | ||
desiredState[list[0].pid] = false; | ||
desiredState[list[1].pid] = false; | ||
desiredState[list[2].pid] = true; | ||
desiredState[list[3].pid] = false; | ||
pollForProcessState(desiredState).then(() => { | ||
// Kill notepad before done | ||
process.kill(list[2].pid); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('resize', () => { | ||
it('should throw a non-native exception when resizing an invalid value', () => { | ||
const term = new WindowsTerminal('cmd.exe', [], {}); | ||
assert.throws(() => term.resize(-1, -1)); | ||
assert.throws(() => term.resize(0, 0)); | ||
assert.doesNotThrow(() => term.resize(1, 1)); | ||
}); | ||
it('should throw an non-native exception when resizing a killed terminal', (done) => { | ||
const term = new WindowsTerminal('cmd.exe', [], {}); | ||
(<any>term)._defer(() => { | ||
term.on('exit', () => { | ||
assert.throws(() => term.resize(1, 1)); | ||
done(); | ||
describe('resize', () => { | ||
it('should throw a non-native exception when resizing an invalid value', () => { | ||
const term = new WindowsTerminal('cmd.exe', [], { useConpty }); | ||
assert.throws(() => term.resize(-1, -1)); | ||
assert.throws(() => term.resize(0, 0)); | ||
assert.doesNotThrow(() => term.resize(1, 1)); | ||
}); | ||
it('should throw a non-native exception when resizing a killed terminal', (done) => { | ||
const term = new WindowsTerminal('cmd.exe', [], { useConpty }); | ||
(<any>term)._defer(() => { | ||
term.on('exit', () => { | ||
assert.throws(() => term.resize(1, 1)); | ||
done(); | ||
}); | ||
term.destroy(); | ||
}); | ||
term.destroy(); | ||
}); | ||
}); | ||
}); | ||
describe('Args as CommandLine', () => { | ||
it('should not fail running a file containing a space in the path', (done) => { | ||
const spaceFolder = path.resolve(__dirname, '..', 'fixtures', 'space folder'); | ||
if (!fs.existsSync(spaceFolder)) { | ||
fs.mkdirSync(spaceFolder); | ||
} | ||
describe('Args as CommandLine', () => { | ||
it('should not fail running a file containing a space in the path', (done) => { | ||
const spaceFolder = path.resolve(__dirname, '..', 'fixtures', 'space folder'); | ||
if (!fs.existsSync(spaceFolder)) { | ||
fs.mkdirSync(spaceFolder); | ||
} | ||
const cmdCopiedPath = path.resolve(spaceFolder, 'cmd.exe'); | ||
const data = fs.readFileSync(`${process.env.windir}\\System32\\cmd.exe`); | ||
fs.writeFileSync(cmdCopiedPath, data); | ||
const cmdCopiedPath = path.resolve(spaceFolder, 'cmd.exe'); | ||
const data = fs.readFileSync(`${process.env.windir}\\System32\\cmd.exe`); | ||
fs.writeFileSync(cmdCopiedPath, data); | ||
if (!fs.existsSync(cmdCopiedPath)) { | ||
// Skip test if git bash isn't installed | ||
return; | ||
} | ||
const term = new WindowsTerminal(cmdCopiedPath, '/c echo "hello world"', {}); | ||
let result = ''; | ||
term.on('data', (data) => { | ||
result += data; | ||
if (!fs.existsSync(cmdCopiedPath)) { | ||
// Skip test if git bash isn't installed | ||
return; | ||
} | ||
const term = new WindowsTerminal(cmdCopiedPath, '/c echo "hello world"', { useConpty }); | ||
let result = ''; | ||
term.on('data', (data) => { | ||
result += data; | ||
}); | ||
term.on('exit', () => { | ||
assert.ok(result.indexOf('hello world') >= 1); | ||
done(); | ||
}); | ||
}); | ||
term.on('exit', () => { | ||
assert.ok(result.indexOf('hello world') >= 1); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
describe('env', () => { | ||
it('should set environment variables of the shell', (done) => { | ||
const term = new WindowsTerminal('cmd.exe', '/C echo %FOO%', { env: { FOO: 'BAR' }}); | ||
let result = ''; | ||
term.on('data', (data) => { | ||
result += data; | ||
describe('env', () => { | ||
it('should set environment variables of the shell', (done) => { | ||
const term = new WindowsTerminal('cmd.exe', '/C echo %FOO%', { env: { FOO: 'BAR' }}); | ||
let result = ''; | ||
term.on('data', (data) => { | ||
result += data; | ||
}); | ||
term.on('exit', () => { | ||
assert.ok(result.indexOf('BAR') >= 0); | ||
done(); | ||
}); | ||
}); | ||
term.on('exit', () => { | ||
assert.ok(result.indexOf('BAR') >= 0); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
describe('On close', () => { | ||
it('should return process zero exit codes', (done) => { | ||
const term = new WindowsTerminal('cmd.exe', '/C exit'); | ||
term.on('exit', (code) => { | ||
assert.equal(code, 0); | ||
done(); | ||
describe('On close', () => { | ||
it('should return process zero exit codes', (done) => { | ||
const term = new WindowsTerminal('cmd.exe', '/C exit', { useConpty }); | ||
term.on('exit', (code) => { | ||
assert.strictEqual(code, 0); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('should return process non-zero exit codes', (done) => { | ||
const term = new WindowsTerminal('cmd.exe', '/C exit 2'); | ||
term.on('exit', (code) => { | ||
assert.equal(code, 2); | ||
done(); | ||
it('should return process non-zero exit codes', (done) => { | ||
const term = new WindowsTerminal('cmd.exe', '/C exit 2', { useConpty }); | ||
term.on('exit', (code) => { | ||
assert.strictEqual(code, 2); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('winpty', () => { | ||
it('should accept input', (done) => { | ||
const term = new WindowsTerminal('cmd.exe', '', { useConpty: false }); | ||
term.write('exit\r'); | ||
term.on('exit', () => { | ||
done(); | ||
describe('Write', () => { | ||
it('should accept input', (done) => { | ||
const term = new WindowsTerminal('cmd.exe', '', { useConpty }); | ||
term.write('exit\r'); | ||
term.on('exit', () => { | ||
done(); | ||
}); | ||
}); | ||
@@ -212,0 +214,0 @@ }); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1148494
4467
1