90 lines
2.0 KiB
JavaScript
90 lines
2.0 KiB
JavaScript
|
'use strict';
|
||
|
const {methodCallSelector, STATIC_REQUIRE_SELECTOR} = require('./selectors/index.js');
|
||
|
|
||
|
const MESSAGE_ID = 'no-process-exit';
|
||
|
const messages = {
|
||
|
[MESSAGE_ID]: 'Only use `process.exit()` in CLI apps. Throw an error instead.',
|
||
|
};
|
||
|
|
||
|
const importWorkerThreadsSelector = [
|
||
|
// `require('worker_threads')`
|
||
|
[
|
||
|
STATIC_REQUIRE_SELECTOR,
|
||
|
'[arguments.0.value="worker_threads"]',
|
||
|
].join(''),
|
||
|
// `import workerThreads from 'worker_threads'`
|
||
|
[
|
||
|
'ImportDeclaration',
|
||
|
'[source.type="Literal"]',
|
||
|
'[source.value="worker_threads"]',
|
||
|
].join(''),
|
||
|
].join(', ');
|
||
|
const processOnOrOnceCallSelector = methodCallSelector({
|
||
|
object: 'process',
|
||
|
methods: ['on', 'once'],
|
||
|
minimumArguments: 1,
|
||
|
});
|
||
|
const processExitCallSelector = methodCallSelector({
|
||
|
object: 'process',
|
||
|
method: 'exit',
|
||
|
});
|
||
|
|
||
|
/** @param {import('eslint').Rule.RuleContext} context */
|
||
|
const create = context => {
|
||
|
const startsWithHashBang = context.getSourceCode().lines[0].indexOf('#!') === 0;
|
||
|
|
||
|
if (startsWithHashBang) {
|
||
|
return {};
|
||
|
}
|
||
|
|
||
|
let processEventHandler;
|
||
|
|
||
|
// Only report if it's outside an worker thread context. See #328.
|
||
|
let requiredWorkerThreadsModule = false;
|
||
|
const problemNodes = [];
|
||
|
|
||
|
return {
|
||
|
// Check `worker_threads` require / import
|
||
|
[importWorkerThreadsSelector]() {
|
||
|
requiredWorkerThreadsModule = true;
|
||
|
},
|
||
|
// Check `process.on` / `process.once` call
|
||
|
[processOnOrOnceCallSelector](node) {
|
||
|
processEventHandler = node;
|
||
|
},
|
||
|
// Check `process.exit` call
|
||
|
[processExitCallSelector](node) {
|
||
|
if (!processEventHandler) {
|
||
|
problemNodes.push(node);
|
||
|
}
|
||
|
},
|
||
|
'CallExpression:exit'(node) {
|
||
|
if (node === processEventHandler) {
|
||
|
processEventHandler = undefined;
|
||
|
}
|
||
|
},
|
||
|
* 'Program:exit'() {
|
||
|
if (!requiredWorkerThreadsModule) {
|
||
|
for (const node of problemNodes) {
|
||
|
yield {
|
||
|
node,
|
||
|
messageId: MESSAGE_ID,
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
};
|
||
|
};
|
||
|
|
||
|
/** @type {import('eslint').Rule.RuleModule} */
|
||
|
module.exports = {
|
||
|
create,
|
||
|
meta: {
|
||
|
type: 'suggestion',
|
||
|
docs: {
|
||
|
description: 'Disallow `process.exit()`.',
|
||
|
},
|
||
|
messages,
|
||
|
},
|
||
|
};
|