tools: force common be required before any other modules

PR-URL: https://github.com/nodejs/node/pull/27650
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
This commit is contained in:
ZYSzys 2019-05-12 15:11:13 +08:00
parent 618fcbd125
commit dcc5e51e1c
52 changed files with 194 additions and 66 deletions

View File

@ -22,6 +22,7 @@ rules:
node-core/number-isnan: error
## common module is mandatory in tests
node-core/required-modules: [error, common]
node-core/require-common-first: error
node-core/no-duplicate-requires: off
# Global scoped methods and vars

View File

@ -1,6 +1,6 @@
'use strict';
const assert = require('assert');
require('../common');
const assert = require('assert');
/**
* Checks the expected invocations against the invocations that actually

View File

@ -1,8 +1,8 @@
'use strict';
require('../common');
const assert = require('assert');
const util = require('util');
require('../common');
function findInGraph(graph, type, n) {
let found = 0;

View File

@ -386,7 +386,7 @@ thread.
The `ArrayStream` module provides a simple `Stream` that pushes elements from
a given array.
<!-- eslint-disable no-undef, node-core/required-modules -->
<!-- eslint-disable no-undef, node-core/require-common-first, node-core/required-modules -->
```js
const ArrayStream = require('../common/arraystream');
const stream = new ArrayStream();
@ -402,7 +402,7 @@ require a particular action to be taken after a given number of completed
tasks (for instance, shutting down an HTTP server after a specific number of
requests). The Countdown will fail the test if the remainder did not reach 0.
<!-- eslint-disable strict, node-core/required-modules -->
<!-- eslint-disable strict, node-core/require-common-first, node-core/required-modules -->
```js
const Countdown = require('../common/countdown');
@ -574,7 +574,7 @@ one listed below. (`heap.validateSnapshotNodes(...)` is a shortcut for
Create a heap dump and an embedder graph copy and validate occurrences.
<!-- eslint-disable no-undef, node-core/required-modules -->
<!-- eslint-disable no-undef, node-core/require-common-first, node-core/required-modules -->
```js
validateSnapshotNodes('TLSWRAP', [
{
@ -592,7 +592,7 @@ validateSnapshotNodes('TLSWRAP', [
The `hijackstdio` module provides utility functions for temporarily redirecting
`stdout` and `stderr` output.
<!-- eslint-disable no-undef, node-core/required-modules -->
<!-- eslint-disable no-undef, node-core/require-common-first, node-core/required-modules -->
```js
const { hijackStdout, restoreStdout } = require('../common/hijackstdio');
@ -638,7 +638,7 @@ original state after calling [`hijackstdio.hijackStdOut()`][].
The http2.js module provides a handful of utilities for creating mock HTTP/2
frames for testing of HTTP/2 endpoints
<!-- eslint-disable no-unused-vars, node-core/required-modules -->
<!-- eslint-disable no-unused-vars, node-core/require-common-first, node-core/required-modules -->
```js
const http2 = require('../common/http2');
```
@ -648,7 +648,7 @@ const http2 = require('../common/http2');
The `http2.Frame` is a base class that creates a `Buffer` containing a
serialized HTTP/2 frame header.
<!-- eslint-disable no-undef, node-core/required-modules -->
<!-- eslint-disable no-undef, node-core/require-common-first, node-core/required-modules -->
```js
// length is a 24-bit unsigned integer
// type is an 8-bit unsigned integer identifying the frame type
@ -667,7 +667,7 @@ The serialized `Buffer` may be retrieved using the `frame.data` property.
The `http2.DataFrame` is a subclass of `http2.Frame` that serializes a `DATA`
frame.
<!-- eslint-disable no-undef, node-core/required-modules -->
<!-- eslint-disable no-undef, node-core/require-common-first, node-core/required-modules -->
```js
// id is the 32-bit stream identifier
// payload is a Buffer containing the DATA payload
@ -684,7 +684,7 @@ socket.write(frame.data);
The `http2.HeadersFrame` is a subclass of `http2.Frame` that serializes a
`HEADERS` frame.
<!-- eslint-disable no-undef, node-core/required-modules -->
<!-- eslint-disable no-undef, node-core/require-common-first, node-core/required-modules -->
```js
// id is the 32-bit stream identifier
// payload is a Buffer containing the HEADERS payload (see either
@ -702,7 +702,7 @@ socket.write(frame.data);
The `http2.SettingsFrame` is a subclass of `http2.Frame` that serializes an
empty `SETTINGS` frame.
<!-- eslint-disable no-undef, node-core/required-modules -->
<!-- eslint-disable no-undef, node-core/require-common-first, node-core/required-modules -->
```js
// ack is a boolean indicating whether or not to set the ACK flag.
const frame = new http2.SettingsFrame(ack);
@ -715,7 +715,7 @@ socket.write(frame.data);
Set to a `Buffer` instance that contains a minimal set of serialized HTTP/2
request headers to be used as the payload of a `http2.HeadersFrame`.
<!-- eslint-disable no-undef, node-core/required-modules -->
<!-- eslint-disable no-undef, node-core/require-common-first, node-core/required-modules -->
```js
const frame = new http2.HeadersFrame(1, http2.kFakeRequestHeaders, 0, true);
@ -727,7 +727,7 @@ socket.write(frame.data);
Set to a `Buffer` instance that contains a minimal set of serialized HTTP/2
response headers to be used as the payload a `http2.HeadersFrame`.
<!-- eslint-disable no-undef, node-core/required-modules -->
<!-- eslint-disable no-undef, node-core/require-common-first, node-core/required-modules -->
```js
const frame = new http2.HeadersFrame(1, http2.kFakeResponseHeaders, 0, true);
@ -739,7 +739,7 @@ socket.write(frame.data);
Set to a `Buffer` containing the preamble bytes an HTTP/2 client must send
upon initial establishment of a connection.
<!-- eslint-disable no-undef, node-core/required-modules -->
<!-- eslint-disable no-undef, node-core/require-common-first, node-core/required-modules -->
```js
socket.write(http2.kClientMagic);
```

View File

@ -1,4 +1,4 @@
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
'use strict';
const { Stream } = require('stream');

View File

@ -1,4 +1,4 @@
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
'use strict';

View File

@ -1,4 +1,4 @@
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
'use strict';

View File

@ -1,4 +1,4 @@
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
'use strict';
const assert = require('assert');

View File

@ -1,4 +1,4 @@
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
'use strict';
const { Duplex } = require('stream');
const assert = require('assert');

View File

@ -1,4 +1,4 @@
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
'use strict';
const path = require('path');

View File

@ -1,4 +1,4 @@
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
'use strict';
const assert = require('assert');
const util = require('util');

View File

@ -1,4 +1,4 @@
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
'use strict';
// Hijack stdout and stderr

View File

@ -1,4 +1,4 @@
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
'use strict';
// An HTTP/2 testing tool used to create mock frames for direct testing

View File

@ -19,7 +19,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
/* eslint-disable node-core/required-modules, node-core/crypto-check */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
/* eslint-disable node-core/crypto-check */
'use strict';
const process = global.process; // Some tests tamper with the process global.
const path = require('path');

View File

@ -1,5 +1,5 @@
// Flags: --experimental-modules
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
import { createRequireFromPath } from 'module';
import { fileURLToPath as toPath } from 'url';

View File

@ -1,4 +1,4 @@
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
'use strict';
// Utilities for internet-related tests

View File

@ -1,4 +1,4 @@
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
'use strict';
const assert = require('assert');
const fs = require('fs');

View File

@ -1,4 +1,5 @@
/* eslint-disable node-core/required-modules, node-core/crypto-check */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
/* eslint-disable node-core/crypto-check */
'use strict';
const crypto = require('crypto');

View File

@ -1,4 +1,4 @@
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
'use strict';
const fs = require('fs');

View File

@ -1,4 +1,4 @@
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
'use strict';
const assert = require('assert');

View File

@ -1,5 +1,5 @@
// Flags: --experimental-modules --loader ./test/fixtures/es-module-loaders/example-loader.mjs
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
import assert from 'assert';
import ok from '../fixtures/es-modules/test-esm-ok.mjs';

View File

@ -1,5 +1,5 @@
// Flags: --experimental-modules --loader ./test/fixtures/es-module-loaders/loader-with-dep.mjs
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
import '../fixtures/es-modules/test-esm-ok.mjs';
// We just test that this module doesn't fail loading

View File

@ -1,3 +1,3 @@
// Flags: --experimental-modules --loader ./test/fixtures/es-module-loaders/not-found-assert-loader.mjs
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
import './not-found.js';

View File

@ -1,3 +1,3 @@
// Flags: --experimental-modules --loader ./test/fixtures/es-module-loaders/not-found-assert-loader.mjs
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
import './not-found.mjs';

View File

@ -1,5 +1,5 @@
// Flags: --experimental-modules --loader ./test/fixtures/es-module-loaders/js-loader.mjs
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
import { namedExport } from '../fixtures/es-module-loaders/js-as-esm.js';
import assert from 'assert';
import ok from '../fixtures/es-modules/test-esm-ok.mjs';

View File

@ -1,6 +1,6 @@
// Flags: --experimental-modules
import cjs from '../fixtures/baz.js';
import '../common/index.mjs';
import cjs from '../fixtures/baz.js';
import { message } from '../fixtures/es-modules/message.mjs';
import assert from 'assert';

View File

@ -1,7 +1,6 @@
'use strict';
const fs = require('fs');
const common = require('../../common');
const fs = require('fs');
const assert = require('assert');
// Addon is referenced through the eval expression in testFile

View File

@ -1,8 +1,8 @@
'use strict';
const common = require('../common');
const child_process = require('child_process');
const assert = require('assert');
const common = require('../common');
if (process.env.NODE_PENDING_DEPRECATION)
common.skip('test does not work when NODE_PENDING_DEPRECATION is set');

View File

@ -1,9 +1,9 @@
// Flags: --no-warnings
'use strict';
const common = require('../common');
const vm = require('vm');
const assert = require('assert');
const common = require('../common');
if (new Error().stack.includes('node_modules'))
common.skip('test does not work when inside `node_modules` directory');

View File

@ -1,6 +1,6 @@
'use strict';
const assert = require('assert');
const common = require('../common');
const assert = require('assert');
const b = Buffer.from('abcdef');
const buf_a = Buffer.from('a');

View File

@ -6,12 +6,12 @@
// caused the third argument (`options`) to be ignored.
// See https://github.com/nodejs/node/issues/24912.
const assert = require('assert');
const { spawn } = require('child_process');
const common = require('../common');
const tmpdir = require('../common/tmpdir');
const assert = require('assert');
const { spawn } = require('child_process');
tmpdir.refresh();
const command = common.isWindows ? 'cd' : 'pwd';

View File

@ -6,12 +6,12 @@
// caused the third argument (`options`) to be ignored.
// See https://github.com/nodejs/node/issues/24912.
const assert = require('assert');
const { spawnSync } = require('child_process');
const common = require('../common');
const tmpdir = require('../common/tmpdir');
const assert = require('assert');
const { spawnSync } = require('child_process');
const command = common.isWindows ? 'cd' : 'pwd';
const options = { cwd: tmpdir.path };

View File

@ -1,7 +1,7 @@
'use strict';
const assert = require('assert');
const common = require('../common');
const assert = require('assert');
const dgram = require('dgram');
const fork = require('child_process').fork;

View File

@ -0,0 +1,27 @@
'use strict';
const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');
common.skipIfEslintMissing();
const RuleTester = require('../../tools/node_modules/eslint').RuleTester;
const rule = require('../../tools/eslint-rules/require-common-first');
new RuleTester().run('require-common-first', rule, {
valid: [
{
code: 'require("common")\n' +
'require("assert")'
}
],
invalid: [
{
code: 'require("assert")\n' +
'require("common")',
errors: [{ message: 'Mandatory module "common" must be loaded ' +
'before any other modules.' }]
}
]
});

View File

@ -1,4 +1,4 @@
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
'use strict';

View File

@ -4,12 +4,13 @@
// not get fired again when the 'error' event handler throws
// an error.
const assert = require('assert');
const http = require('http');
const common = require('../common');
const { addresses } = require('../common/internet');
const { errorLookupMock } = require('../common/dns');
const assert = require('assert');
const http = require('http');
const host = addresses.INVALID_HOST;
const req = http.get({

View File

@ -1,8 +1,8 @@
'use strict';
const { expectsError, mustCall } = require('../common');
const assert = require('assert');
const { createServer, maxHeaderSize } = require('http');
const { createConnection } = require('net');
const { expectsError, mustCall } = require('../common');
const CRLF = '\r\n';
const DUMMY_HEADER_NAME = 'Cookie: ';

View File

@ -1,7 +1,7 @@
// Flags: --expose-internals
'use strict';
const common = require('../common');
const { internalBinding } = require('internal/test/binding');
const { getOptionValue } = require('internal/options');
@ -21,7 +21,6 @@ const binding =
internalBinding('http_parser') : internalBinding('http_parser_llhttp');
binding.HTTPParser = DummyParser;
const common = require('../common');
const assert = require('assert');
const { spawn } = require('child_process');
const { parsers } = require('_http_common');

View File

@ -1,10 +1,10 @@
'use strict';
const assert = require('assert');
const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');
const assert = require('assert');
const http2 = require('http2');
for (const chunkSequence of [

View File

@ -1,7 +1,7 @@
// Flags: --expose-internals
'use strict';
const { internalBinding } = require('internal/test/binding');
const common = require('../common');
const { internalBinding } = require('internal/test/binding');
const os = require('os');
const { hasSmallICU } = internalBinding('config');

View File

@ -1,3 +1,4 @@
/* eslint-disable node-core/require-common-first */
'use strict';
// Flags: --expose_internals

View File

@ -1,7 +1,7 @@
'use strict';
const assert = require('assert');
require('../common');
const assert = require('assert');
// Assert legit flags are allowed, and bogus flags are disallowed
{

View File

@ -1,7 +1,7 @@
// Flags: --expose-internals
'use strict';
const { internalBinding } = require('internal/test/binding');
require('../common');
const { internalBinding } = require('internal/test/binding');
const { PassThrough } = require('stream');
const readline = require('readline');
const assert = require('assert');

View File

@ -19,7 +19,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
/* eslint-disable node-core/required-modules */
/* eslint-disable node-core/require-common-first, node-core/required-modules */
'use strict';
Object.prototype.xadsadsdasasdxx = function() {

View File

@ -1,7 +1,7 @@
'use strict';
const { Readable } = require('stream');
const common = require('../common');
const { Readable } = require('stream');
let ticks = 18;
let expectedData = 19;

View File

@ -2,9 +2,9 @@
'use strict';
const { internalBinding } = require('internal/test/binding');
const common = require('../common');
const fixtures = require('../common/fixtures');
const { internalBinding } = require('internal/test/binding');
const assert = require('assert');
const v8 = require('v8');
const os = require('os');

View File

@ -1,6 +1,6 @@
'use strict';
const assert = require('assert');
const common = require('../common');
const assert = require('assert');
const { isMainThread, parentPort, Worker } = require('worker_threads');
// This test makes sure that we manipulate the references of

View File

@ -1,6 +1,6 @@
'use strict';
const assert = require('assert');
const common = require('../common');
const assert = require('assert');
const { Worker, isMainThread, parentPort } = require('worker_threads');
// Do not use isMainThread directly, otherwise the test would time out in case

View File

@ -1,7 +1,7 @@
'use strict';
const common = require('../common');
const path = require('path');
const assert = require('assert');
const common = require('../common');
const { Worker, isMainThread, parentPort } = require('worker_threads');
if (isMainThread) {

View File

@ -1,7 +1,7 @@
'use strict';
const common = require('../common');
const path = require('path');
const assert = require('assert');
const common = require('../common');
const { Worker, isMainThread, parentPort } = require('worker_threads');
if (isMainThread) {

View File

@ -1,7 +1,7 @@
'use strict';
const path = require('path');
const common = require('../common');
const path = require('path');
const assert = require('assert');
const { Worker } = require('worker_threads');

View File

@ -0,0 +1,98 @@
/**
* @fileoverview Require `common` module first in our tests.
*/
'use strict';
const path = require('path');
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
const requiredModule = 'common';
const isESM = context.parserOptions.sourceType === 'module';
const foundModules = [];
/**
* Function to check if a node is a string literal.
* @param {ASTNode} node The node to check.
* @returns {boolean} If the node is a string literal.
*/
function isString(node) {
return node && node.type === 'Literal' && typeof node.value === 'string';
}
/**
* Function to check if a node is a require call.
* @param {ASTNode} node The node to check.
* @returns {boolean} If the node is a require call.
*/
function isRequireCall(node) {
return node.callee.type === 'Identifier' && node.callee.name === 'require';
}
/**
* Function to check if the path is a module and return its name.
* @param {String} str The path to check
* @returns {String} module name
*/
function getModuleName(str) {
if (str === '../common/index.mjs') {
return 'common';
}
return path.basename(str);
}
/**
* Function to check if a node has an argument that is a module and
* return its name.
* @param {ASTNode} node The node to check
* @returns {undefined|String} module name or undefined
*/
function getModuleNameFromCall(node) {
// Node has arguments and first argument is string
if (node.arguments.length && isString(node.arguments[0])) {
return getModuleName(node.arguments[0].value.trim());
}
return undefined;
}
const rules = {
'Program:exit'(node) {
// The common module should be loaded in the first place.
const notLoadedFirst = foundModules.indexOf(requiredModule) !== 0;
if (notLoadedFirst) {
context.report(
node,
'Mandatory module "{{moduleName}}" must be loaded ' +
'before any other modules.',
{ moduleName: requiredModule }
);
}
}
};
if (isESM) {
rules.ImportDeclaration = (node) => {
const moduleName = getModuleName(node.source.value);
if (moduleName) {
foundModules.push(moduleName);
}
};
} else {
rules.CallExpression = (node) => {
if (isRequireCall(node)) {
const moduleName = getModuleNameFromCall(node);
if (moduleName) {
foundModules.push(moduleName);
}
}
};
}
return rules;
};