mirror of
https://github.com/electron/electron.git
synced 2026-05-02 03:00:22 -04:00
fix: align process.exit() behavior in main process with Node.js
This commit is contained in:
@@ -72,8 +72,17 @@ if (process.platform === 'win32') {
|
||||
}
|
||||
}
|
||||
|
||||
// Map process.exit to app.exit, which quits gracefully.
|
||||
process.exit = app.exit as () => never;
|
||||
// Map process.exit to app.exit, which quits gracefully. When called without
|
||||
// an explicit code, fall back to process.exitCode like Node.js does.
|
||||
process.exit = ((code: number | string | undefined | null) => {
|
||||
// Refs https://github.com/nodejs/node/blob/fc192ee030ee076b948ce7d9d72cba6c101989b8/lib/internal/process/per_thread.js#L229-L252
|
||||
if (code !== undefined) {
|
||||
// Node.js handles any string to number conversion here for us
|
||||
process.exitCode = code;
|
||||
}
|
||||
|
||||
app.exit(process.exitCode || 0);
|
||||
}) as typeof process.exit;
|
||||
|
||||
// Load the RPC server.
|
||||
require('@electron/internal/browser/rpc-server');
|
||||
|
||||
@@ -17,7 +17,14 @@ import {
|
||||
spawn
|
||||
} from './lib/codesign-helpers';
|
||||
import { withTempDirectory } from './lib/fs-helpers';
|
||||
import { getRemoteContext, ifdescribe, ifit, itremote, useRemoteContext } from './lib/spec-helpers';
|
||||
import {
|
||||
getRemoteContext,
|
||||
ifdescribe,
|
||||
ifit,
|
||||
itremote,
|
||||
startRemoteControlApp,
|
||||
useRemoteContext
|
||||
} from './lib/spec-helpers';
|
||||
|
||||
const mainFixturesPath = path.resolve(__dirname, 'fixtures');
|
||||
|
||||
@@ -586,9 +593,115 @@ describe('node feature', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('process.exit', () => {
|
||||
it('exits with exit code zero when called without an argument', async () => {
|
||||
const rc = await startRemoteControlApp();
|
||||
rc.remotely(() => {
|
||||
setImmediate(() => process.exit());
|
||||
}).catch(() => {});
|
||||
const [code] = await once(rc.process, 'exit');
|
||||
expect(code).to.equal(0);
|
||||
});
|
||||
|
||||
it('uses process.exitCode when called without an argument', async () => {
|
||||
const rc = await startRemoteControlApp();
|
||||
rc.remotely(() => {
|
||||
process.exitCode = 42;
|
||||
setImmediate(() => process.exit());
|
||||
}).catch(() => {});
|
||||
const [code] = await once(rc.process, 'exit');
|
||||
expect(code).to.equal(42);
|
||||
});
|
||||
|
||||
it('overrides process.exitCode when called with an argument', async () => {
|
||||
const rc = await startRemoteControlApp();
|
||||
rc.remotely(() => {
|
||||
process.exitCode = 42;
|
||||
setImmediate(() => process.exit(11));
|
||||
}).catch(() => {});
|
||||
const [code] = await once(rc.process, 'exit');
|
||||
expect(code).to.equal(11);
|
||||
});
|
||||
|
||||
it('can be called with a null argument', async () => {
|
||||
const rc = await startRemoteControlApp();
|
||||
rc.remotely(() => {
|
||||
setImmediate(() => process.exit(null));
|
||||
}).catch(() => {});
|
||||
const [code] = await once(rc.process, 'exit');
|
||||
expect(code).to.equal(0);
|
||||
});
|
||||
|
||||
it('can be called with a number argument', async () => {
|
||||
const rc = await startRemoteControlApp();
|
||||
rc.remotely(() => {
|
||||
setImmediate(() => process.exit(7));
|
||||
}).catch(() => {});
|
||||
const [code] = await once(rc.process, 'exit');
|
||||
expect(code).to.equal(7);
|
||||
});
|
||||
|
||||
it('throws with an invalid number argument', async () => {
|
||||
const rc = await startRemoteControlApp();
|
||||
let stdout = '';
|
||||
rc.process.stdout!.on('data', (d) => {
|
||||
stdout += d.toString();
|
||||
});
|
||||
rc.remotely(() => {
|
||||
setImmediate(() => {
|
||||
try {
|
||||
process.exit(4.2);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
process.exit(99);
|
||||
}
|
||||
});
|
||||
}).catch(() => {});
|
||||
const [code] = await once(rc.process, 'exit');
|
||||
expect(code).to.equal(99);
|
||||
expect(stdout).to.match(
|
||||
/RangeError \[ERR_OUT_OF_RANGE\]: The value of "code" is out of range. It must be an integer./
|
||||
);
|
||||
});
|
||||
|
||||
it('can be called with a string argument', async () => {
|
||||
const rc = await startRemoteControlApp();
|
||||
rc.remotely(() => {
|
||||
setImmediate(() => process.exit('12'));
|
||||
}).catch(() => {});
|
||||
const [code] = await once(rc.process, 'exit');
|
||||
expect(code).to.equal(12);
|
||||
});
|
||||
|
||||
it('throws with an invalid string argument', async () => {
|
||||
const rc = await startRemoteControlApp();
|
||||
let stdout = '';
|
||||
rc.process.stdout!.on('data', (d) => {
|
||||
stdout += d.toString();
|
||||
});
|
||||
rc.remotely(() => {
|
||||
setImmediate(() => {
|
||||
try {
|
||||
process.exit('invalid');
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
process.exit(99);
|
||||
}
|
||||
});
|
||||
}).catch(() => {});
|
||||
const [code] = await once(rc.process, 'exit');
|
||||
expect(code).to.equal(99);
|
||||
expect(stdout).to.match(/TypeError \[ERR_INVALID_ARG_TYPE\]/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('process.stdout', () => {
|
||||
useRemoteContext();
|
||||
|
||||
it('is a real Node stream', () => {
|
||||
expect((process.stdout as any)._type).to.not.be.undefined();
|
||||
});
|
||||
|
||||
itremote('does not throw an exception when accessed', () => {
|
||||
expect(() => process.stdout).to.not.throw();
|
||||
});
|
||||
@@ -923,12 +1036,6 @@ describe('node feature', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('process.stdout', () => {
|
||||
it('is a real Node stream', () => {
|
||||
expect((process.stdout as any)._type).to.not.be.undefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('fs.readFile', () => {
|
||||
it('can accept a FileHandle as the Path argument', async () => {
|
||||
const filePathForHandle = path.resolve(mainFixturesPath, 'dogs-running.txt');
|
||||
|
||||
Reference in New Issue
Block a user