Skip to content

Commit e030dd7

Browse files
devsnektargos
authored andcommittedJul 14, 2018
tools: add no-duplicate-requires rule
PR-URL: #21712 Reviewed-By: Richard Lau <[email protected]> Reviewed-By: Tiancheng "Timothy" Gu <[email protected]> Reviewed-By: Weijia Wang <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Jon Moss <[email protected]>
1 parent 3096ee5 commit e030dd7

File tree

8 files changed

+116
-11
lines changed

8 files changed

+116
-11
lines changed
 

‎.eslintrc.js

+2
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ module.exports = {
9898
'no-dupe-class-members': 'error',
9999
'no-dupe-keys': 'error',
100100
'no-duplicate-case': 'error',
101+
'no-duplicate-imports': 'error',
101102
'no-empty-character-class': 'error',
102103
'no-ex-assign': 'error',
103104
'no-extra-boolean-cast': 'error',
@@ -246,6 +247,7 @@ module.exports = {
246247

247248
// Custom rules from eslint-plugin-node-core
248249
'node-core/no-unescaped-regexp-dot': 'error',
250+
'node-core/no-duplicate-requires': 'error',
249251
},
250252
globals: {
251253
Atomics: false,

‎benchmark/streams/creation.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
'use strict';
22
const common = require('../common.js');
3-
const Duplex = require('stream').Duplex;
4-
const Readable = require('stream').Readable;
5-
const Transform = require('stream').Transform;
6-
const Writable = require('stream').Writable;
3+
const {
4+
Duplex,
5+
Readable,
6+
Transform,
7+
Writable,
8+
} = require('stream');
79

810
const bench = common.createBenchmark(main, {
911
n: [50e6],

‎doc/api/worker_threads.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ For example:
286286
```js
287287
const assert = require('assert');
288288
const {
289-
Worker, MessageChannel, MessagePort, isMainThread
289+
Worker, MessageChannel, MessagePort, isMainThread, parentPort
290290
} = require('worker_threads');
291291
if (isMainThread) {
292292
const worker = new Worker(__filename);
@@ -296,7 +296,7 @@ if (isMainThread) {
296296
console.log('received:', value);
297297
});
298298
} else {
299-
require('worker_threads').once('message', (value) => {
299+
parentPort.once('message', (value) => {
300300
assert(value.hereIsYourPort instanceof MessagePort);
301301
value.hereIsYourPort.postMessage('the worker is sending this');
302302
value.hereIsYourPort.close();

‎lib/internal/http2/core.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,12 @@ const { kIncomingMessage } = require('_http_common');
2424
const { kServerResponse } = require('_http_server');
2525
const { StreamWrap } = require('_stream_wrap');
2626

27-
const { defaultTriggerAsyncIdScope } = require('internal/async_hooks');
28-
const { async_id_symbol } = require('internal/async_hooks').symbols;
27+
const {
28+
defaultTriggerAsyncIdScope,
29+
symbols: {
30+
async_id_symbol,
31+
},
32+
} = require('internal/async_hooks');
2933
const { internalBinding } = require('internal/bootstrap/loaders');
3034
const {
3135
codes: {

‎lib/internal/modules/esm/translators.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ const fs = require('fs');
1414
const { _makeLong } = require('path');
1515
const { SafeMap } = require('internal/safe_globals');
1616
const { URL } = require('url');
17-
const util = require('util');
18-
const debug = util.debuglog('esm');
19-
const readFileAsync = util.promisify(fs.readFile);
17+
const { debuglog, promisify } = require('util');
18+
const readFileAsync = promisify(fs.readFile);
2019
const readFileSync = fs.readFileSync;
2120
const StringReplace = Function.call.bind(String.prototype.replace);
2221
const JsonParse = JSON.parse;
2322

23+
const debug = debuglog('esm');
24+
2425
const translators = new SafeMap();
2526
module.exports = translators;
2627

‎test/.eslintrc.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ rules:
1818
node-core/number-isnan: error
1919
## common module is mandatory in tests
2020
node-core/required-modules: [error, common]
21+
node-core/no-duplicate-requires: off
2122

2223
no-restricted-syntax:
2324
# Config copied from .eslintrc.js
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
5+
common.skipIfEslintMissing();
6+
7+
const { RuleTester } = require('../../tools/node_modules/eslint');
8+
const rule = require('../../tools/eslint-rules/no-duplicate-requires');
9+
10+
new RuleTester().run('no-duplicate-requires', rule, {
11+
valid: [
12+
{
13+
code: 'require("a"); require("b"); (function() { require("a"); });',
14+
},
15+
{
16+
code: 'require(a); require(a);',
17+
},
18+
],
19+
invalid: [
20+
{
21+
code: 'require("a"); require("a");',
22+
errors: [{ message: '\'a\' require is duplicated.' }],
23+
},
24+
],
25+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* @fileoverview Ensure modules are not required twice at top level of a module
3+
* @author devsnek
4+
*/
5+
'use strict';
6+
7+
//------------------------------------------------------------------------------
8+
// Rule Definition
9+
//------------------------------------------------------------------------------
10+
11+
12+
function isString(node) {
13+
return node && node.type === 'Literal' && typeof node.value === 'string';
14+
}
15+
16+
function isRequireCall(node) {
17+
return node.callee.type === 'Identifier' && node.callee.name === 'require';
18+
}
19+
20+
function isTopLevel(node) {
21+
do {
22+
if (node.type === 'FunctionDeclaration' ||
23+
node.type === 'FunctionExpression' ||
24+
node.type === 'ArrowFunctionExpression' ||
25+
node.type === 'ClassBody' ||
26+
node.type === 'MethodDefinition') {
27+
return false;
28+
}
29+
} while (node = node.parent);
30+
return true;
31+
}
32+
33+
module.exports = (context) => {
34+
if (context.parserOptions.sourceType === 'module') {
35+
return {};
36+
}
37+
38+
function getRequiredModuleNameFromCall(node) {
39+
// node has arguments and first argument is string
40+
if (node.arguments.length && isString(node.arguments[0])) {
41+
return node.arguments[0].value.trim();
42+
}
43+
44+
return undefined;
45+
}
46+
47+
const required = new Set();
48+
49+
const rules = {
50+
CallExpression: (node) => {
51+
if (isRequireCall(node) && isTopLevel(node)) {
52+
const moduleName = getRequiredModuleNameFromCall(node);
53+
if (moduleName === undefined) {
54+
return;
55+
}
56+
if (required.has(moduleName)) {
57+
context.report(
58+
node,
59+
'\'{{moduleName}}\' require is duplicated.',
60+
{ moduleName }
61+
);
62+
} else {
63+
required.add(moduleName);
64+
}
65+
}
66+
},
67+
};
68+
69+
return rules;
70+
};

0 commit comments

Comments
 (0)
Please sign in to comment.