src: add --disable-warning option

Co-authored-by: Geoffrey Booth <webadmin@geoffreybooth.com>
Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/50661
Fixes: https://github.com/nodejs/node/issues/30810
Fixes: https://github.com/nodejs/node/issues/47478
Fixes: https://github.com/nodejs/node/issues/46862
Fixes: https://github.com/nodejs/node/issues/40940
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Richard Lau <rlau@redhat.com>
This commit is contained in:
Ethan Arrowood 2023-11-21 13:30:02 -07:00 committed by GitHub
parent a76f3913a5
commit a0b66383f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 260 additions and 0 deletions

View File

@ -443,6 +443,57 @@ Affects the default output directory of:
* [`--heap-prof-dir`][]
* [`--redirect-warnings`][]
### `--disable-warning=code-or-type`
> Stability: 1.1 - Active development
<!-- YAML
added: REPLACEME
-->
Disable specific process warnings by `code` or `type`.
Warnings emitted from [`process.emitWarning()`][emit_warning] may contain a
`code` and a `type`. This option will not-emit warnings that have a matching
`code` or `type`.
List of [deprecation warnings][].
The Node.js core warning types are: `DeprecationWarning` and
`ExperimentalWarning`
For example, the following script will not emit
[DEP0025 `require('node:sys')`][DEP0025 warning] when executed with
`node --disable-warning=DEP0025`:
```mjs
import sys from 'node:sys';
```
```cjs
const sys = require('node:sys');
```
For example, the following script will emit the
[DEP0025 `require('node:sys')`][DEP0025 warning], but not any Experimental
Warnings (such as
[ExperimentalWarning: `vm.measureMemory` is an experimental feature][]
in <=v21) when executed with `node --disable-warning=ExperimentalWarnings`:
```mjs
import sys from 'node:sys';
import vm from 'node:vm';
vm.measureMemory();
```
```cjs
const sys = require('node:sys');
const vm = require('node:vm');
vm.measureMemory();
```
### `--disable-proto=mode`
<!-- YAML
@ -2327,6 +2378,7 @@ Node.js options that are allowed are:
* `--conditions`, `-C`
* `--diagnostic-dir`
* `--disable-proto`
* `--disable-warning`
* `--dns-result-order`
* `--enable-fips`
* `--enable-network-family-autoselection`
@ -2779,7 +2831,9 @@ done
[CommonJS]: modules.md
[CommonJS module]: modules.md
[CustomEvent Web API]: https://dom.spec.whatwg.org/#customevent
[DEP0025 warning]: deprecations.md#dep0025-requirenodesys
[ECMAScript module]: esm.md#modules-ecmascript-modules
[ExperimentalWarning: `vm.measureMemory` is an experimental feature]: vm.md#vmmeasurememoryoptions
[Fetch API]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
[File System Permissions]: permissions.md#file-system-permissions
[Module customization hooks]: module.md#customization-hooks
@ -2835,6 +2889,7 @@ done
[context-aware]: addons.md#context-aware-addons
[debugger]: debugger.md
[debugging security implications]: https://nodejs.org/en/docs/guides/debugging-getting-started/#security-implications
[deprecation warnings]: deprecations.md#list-of-deprecated-apis
[emit_warning]: process.md#processemitwarningwarning-options
[environment_variables]: #environment-variables
[filtering tests by name]: test.md#filtering-tests-by-name

View File

@ -6,8 +6,13 @@ const {
ErrorPrototypeToString,
ErrorCaptureStackTrace,
String,
SafeSet,
} = primordials;
const {
getOptionValue,
} = require('internal/options');
const assert = require('internal/assert');
const {
codes: {
@ -89,8 +94,21 @@ function doEmitWarning(warning) {
process.emit('warning', warning);
}
let disableWarningSet;
function onWarning(warning) {
if (!disableWarningSet) {
disableWarningSet = new SafeSet();
const disableWarningValues = getOptionValue('--disable-warning');
for (let i = 0; i < disableWarningValues.length; i++) {
disableWarningSet.add(disableWarningValues[i]);
}
}
if ((warning?.code && disableWarningSet.has(warning.code)) ||
(warning?.name && disableWarningSet.has(warning.name))) return;
if (!(warning instanceof Error)) return;
const isDeprecation = warning.name === 'DeprecationWarning';
if (isDeprecation && process.noDeprecation) return;
const trace = process.traceProcessWarnings ||

View File

@ -527,6 +527,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
&EnvironmentOptions::warnings,
kAllowedInEnvvar,
true);
AddOption("--disable-warning",
"silence specific process warnings",
&EnvironmentOptions::disable_warnings,
kAllowedInEnvvar);
AddOption("--force-context-aware",
"disable loading non-context-aware addons",
&EnvironmentOptions::force_context_aware,

View File

@ -139,6 +139,7 @@ class EnvironmentOptions : public Options {
bool allow_native_addons = true;
bool global_search_paths = true;
bool warnings = true;
std::vector<std::string> disable_warnings;
bool force_context_aware = false;
bool pending_deprecation = false;
bool preserve_symlinks = false;

View File

@ -0,0 +1,4 @@
'use strict';
const path = require('node:path');
const { Worker } = require('node:worker_threads');
new Worker(path.join(__dirname, './disable-warning.js'));

15
test/fixtures/disable-warning.js vendored Normal file
View File

@ -0,0 +1,15 @@
'use strict';
process.emitWarning('Deprecation Warning 1', {
code: 'DEP1',
type: 'DeprecationWarning'
});
process.emitWarning('Deprecation Warning 2', {
code: 'DEP2',
type: 'DeprecationWarning'
});
process.emitWarning('Experimental Warning', {
type: 'ExperimentalWarning'
});

View File

@ -0,0 +1,163 @@
import { spawnPromisified } from '../common/index.mjs';
import * as fixtures from '../common/fixtures.mjs';
import { describe, it } from 'node:test';
import assert from 'node:assert';
const fixturePath = fixtures.path('disable-warning.js');
const fixturePathWorker = fixtures.path('disable-warning-worker.js');
const dep1Message = /\(node:\d+\) \[DEP1\] DeprecationWarning/;
const dep2Message = /\(node:\d+\) \[DEP2\] DeprecationWarning/;
const experimentalWarningMessage = /\(node:\d+\) ExperimentalWarning/;
describe('process warnings', { concurrency: true }, () => {
it('should emit all warnings by default', async () => {
const { stdout, stderr, code, signal } = await spawnPromisified(process.execPath, [
fixturePath,
]);
assert.strictEqual(stdout, '');
assert.match(stderr, dep1Message);
assert.match(stderr, dep2Message);
assert.match(stderr, experimentalWarningMessage);
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
});
describe('--no-warnings', { concurrency: true }, () => {
it('should silence all warnings by default', async () => {
const { stdout, stderr, code, signal } = await spawnPromisified(process.execPath, [
'--no-warnings',
fixturePath,
]);
assert.strictEqual(stdout, '');
assert.doesNotMatch(stderr, dep1Message);
assert.doesNotMatch(stderr, dep2Message);
assert.doesNotMatch(stderr, experimentalWarningMessage);
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
});
});
describe('--no-deprecation', { concurrency: true }, () => {
it('should silence all deprecation warnings', async () => {
const { stdout, stderr, code, signal } = await spawnPromisified(process.execPath, [
'--no-deprecation',
fixturePath,
]);
assert.strictEqual(stdout, '');
assert.doesNotMatch(stderr, dep1Message);
assert.doesNotMatch(stderr, dep2Message);
assert.match(stderr, experimentalWarningMessage);
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
});
});
describe('--disable-warning', { concurrency: true }, () => {
it('should silence deprecation warning DEP1', async () => {
const { stdout, stderr, code, signal } = await spawnPromisified(process.execPath, [
'--disable-warning=DEP1',
fixturePath,
]);
assert.strictEqual(stdout, '');
assert.doesNotMatch(stderr, dep1Message);
assert.match(stderr, dep2Message);
assert.match(stderr, experimentalWarningMessage);
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
});
it('should silence deprecation warnings DEP1 and DEP2', async () => {
const { stdout, stderr, code, signal } = await spawnPromisified(process.execPath, [
'--disable-warning=DEP1',
'--disable-warning=DEP2',
fixturePath,
]);
assert.strictEqual(stdout, '');
assert.doesNotMatch(stderr, dep1Message);
assert.doesNotMatch(stderr, dep2Message);
assert.match(stderr, experimentalWarningMessage);
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
});
it('should silence all deprecation warnings using type DeprecationWarning', async () => {
const { stdout, stderr, code, signal } = await spawnPromisified(process.execPath, [
'--disable-warning=DeprecationWarning',
fixturePath,
]);
assert.strictEqual(stdout, '');
assert.doesNotMatch(stderr, dep1Message);
assert.doesNotMatch(stderr, dep2Message);
assert.match(stderr, experimentalWarningMessage);
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
});
it('should silence all experimental warnings using type ExperimentalWarning', async () => {
const { stdout, stderr, code, signal } = await spawnPromisified(process.execPath, [
'--disable-warning=ExperimentalWarning',
fixturePath,
]);
assert.strictEqual(stdout, '');
assert.match(stderr, dep1Message);
assert.match(stderr, dep2Message);
assert.doesNotMatch(stderr, experimentalWarningMessage);
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
});
it('should pass down option to worker', async () => {
const { stdout, stderr, code, signal } = await spawnPromisified(process.execPath, [
'--disable-warning=DEP2',
fixturePathWorker,
]);
assert.strictEqual(stdout, '');
assert.match(stderr, dep1Message);
assert.doesNotMatch(stderr, dep2Message);
assert.match(stderr, experimentalWarningMessage);
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
});
it('should not support a comma separated list', async () => {
const { stdout, stderr, code, signal } = await spawnPromisified(process.execPath, [
'--disable-warning=DEP1,DEP2',
fixturePathWorker,
]);
assert.strictEqual(stdout, '');
assert.match(stderr, dep1Message);
assert.match(stderr, dep2Message);
assert.match(stderr, experimentalWarningMessage);
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
});
it('should be specifiable in NODE_OPTIONS', async () => {
const { stdout, stderr, code, signal } = await spawnPromisified(process.execPath, [
fixturePath,
], {
env: {
...process.env,
NODE_OPTIONS: '--disable-warning=DEP2'
}
});
assert.strictEqual(stdout, '');
assert.match(stderr, dep1Message);
assert.doesNotMatch(stderr, dep2Message);
assert.match(stderr, experimentalWarningMessage);
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
});
});
});