diff --git a/doc/api/errors.md b/doc/api/errors.md index 1866ef333706a6..e0b8796c1e6803 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -956,12 +956,6 @@ added: v15.0.0 An invalid JSON Web Key was provided. - - -### `ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE` - -The given crypto key object's type is invalid for the attempted operation. - ### `ERR_CRYPTO_INVALID_KEYLEN` @@ -992,6 +986,12 @@ added: v15.0.0 An invalid key type was provided. + + +### `ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE` + +The given crypto key object's type is invalid for the attempted operation. + ### `ERR_CRYPTO_INVALID_MESSAGELEN` @@ -1140,6 +1140,23 @@ added: The [debugger][] timed out waiting for the required host/port to be free. + + +### `ERR_DIR_CLOSED` + +The [`fs.Dir`][] was previously closed. + + + +### `ERR_DIR_CONCURRENT_OPERATION` + + + +A synchronous read or close call was attempted on an [`fs.Dir`][] which has +ongoing asynchronous operations. + ### `ERR_DLOPEN_DISABLED` @@ -1162,23 +1179,6 @@ added: v15.0.0 A call to `process.dlopen()` failed. - - -### `ERR_DIR_CLOSED` - -The [`fs.Dir`][] was previously closed. - - - -### `ERR_DIR_CONCURRENT_OPERATION` - - - -A synchronous read or close call was attempted on an [`fs.Dir`][] which has -ongoing asynchronous operations. - ### `ERR_DNS_SET_SERVERS_FAILED` @@ -1295,19 +1295,6 @@ added: v16.7.0 When using [`fs.cp()`][], `src` or `dest` pointed to an invalid path. - - -### `ERR_HTTP_BODY_NOT_ALLOWED` - -An error is thrown when writing to an HTTP response which does not allow -contents. - - - -### `ERR_HTTP_CONTENT_LENGTH_MISMATCH` - -Response body size doesn't match with the specified content-length header value. - ### `ERR_FS_CP_FIFO_PIPE` @@ -1373,49 +1360,6 @@ Path is a directory. An attempt has been made to read a file whose size is larger than the maximum allowed size for a `Buffer`. - - -### `ERR_HTTP_HEADERS_SENT` - -An attempt was made to add more headers after the headers had already been sent. - - - -### `ERR_HTTP_INVALID_HEADER_VALUE` - -An invalid HTTP header value was specified. - - - -### `ERR_HTTP_INVALID_STATUS_CODE` - -Status code was outside the regular status code range (100-999). - - - -### `ERR_HTTP_REQUEST_TIMEOUT` - -The client has not sent the entire request within the allowed time. - - - -### `ERR_HTTP_SOCKET_ASSIGNED` - -The given [`ServerResponse`][] was already assigned a socket. - - - -### `ERR_HTTP_SOCKET_ENCODING` - -Changing the socket encoding is not allowed per [RFC 7230 Section 3][]. - - - -### `ERR_HTTP_TRAILER_INVALID` - -The `Trailer` header was set even though the transfer encoding does not support -that. - ### `ERR_HTTP2_ALTSVC_INVALID_ORIGIN` @@ -1462,13 +1406,6 @@ A non-specific HTTP/2 error has occurred. New HTTP/2 Streams may not be opened after the `Http2Session` has received a `GOAWAY` frame from the connected peer. - - -### `ERR_HTTP2_HEADER_SINGLE_VALUE` - -Multiple values were provided for an HTTP/2 header field that was required to -have only a single value. - ### `ERR_HTTP2_HEADERS_AFTER_RESPOND` @@ -1481,6 +1418,13 @@ An additional headers was specified after an HTTP/2 response was initiated. An attempt was made to send multiple response headers. + + +### `ERR_HTTP2_HEADER_SINGLE_VALUE` + +Multiple values were provided for an HTTP/2 header field that was required to +have only a single value. + ### `ERR_HTTP2_INFO_STATUS_NOT_ALLOWED` @@ -1738,34 +1682,90 @@ is set for the `Http2Stream`. `http2.connect()` was passed a URL that uses any protocol other than `http:` or `https:`. + + +### `ERR_HTTP_BODY_NOT_ALLOWED` + +An error is thrown when writing to an HTTP response which does not allow +contents. + + + +### `ERR_HTTP_CONTENT_LENGTH_MISMATCH` + +Response body size doesn't match with the specified content-length header value. + + + +### `ERR_HTTP_HEADERS_SENT` + +An attempt was made to add more headers after the headers had already been sent. + + + +### `ERR_HTTP_INVALID_HEADER_VALUE` + +An invalid HTTP header value was specified. + + + +### `ERR_HTTP_INVALID_STATUS_CODE` + +Status code was outside the regular status code range (100-999). + + + +### `ERR_HTTP_REQUEST_TIMEOUT` + +The client has not sent the entire request within the allowed time. + + + +### `ERR_HTTP_SOCKET_ASSIGNED` + +The given [`ServerResponse`][] was already assigned a socket. + + + +### `ERR_HTTP_SOCKET_ENCODING` + +Changing the socket encoding is not allowed per [RFC 7230 Section 3][]. + + + +### `ERR_HTTP_TRAILER_INVALID` + +The `Trailer` header was set even though the transfer encoding does not support +that. + ### `ERR_ILLEGAL_CONSTRUCTOR` An attempt was made to construct an object using a non-public constructor. - + -### `ERR_IMPORT_ATTRIBUTE_TYPE_INCOMPATIBLE` +### `ERR_IMPORT_ATTRIBUTE_MISSING` -An import `type` attribute was provided, but the specified module is of a -different type. +An import attribute is missing, preventing the specified module to be imported. - + -### `ERR_IMPORT_ATTRIBUTE_MISSING` +### `ERR_IMPORT_ATTRIBUTE_TYPE_INCOMPATIBLE` -An import attribute is missing, preventing the specified module to be imported. +An import `type` attribute was provided, but the specified module is of a +different type. @@ -2283,6 +2283,12 @@ function. An error occurred while attempting to retrieve the JavaScript `undefined` value. + + +### `ERR_NON_CONTEXT_AWARE_DISABLED` + +A non-context-aware native addon was loaded in a process that disallows them. + ### `ERR_NOT_BUILDING_SNAPSHOT` @@ -2324,12 +2330,6 @@ OpenSSL crypto support. An attempt was made to use features that require [ICU][], but Node.js was not compiled with ICU support. - - -### `ERR_NON_CONTEXT_AWARE_DISABLED` - -A non-context-aware native addon was loaded in a process that disallows them. - ### `ERR_OPERATION_FAILED` @@ -2459,6 +2459,19 @@ added: REPLACEME Opening a QUIC stream failed. + + +### `ERR_REQUIRE_ASYNC_MODULE` + +> Stability: 1 - Experimental + +When trying to `require()` a [ES Module][], the module turns out to be asynchronous. +That is, it contains top-level await. + +To see where the top-level await is, use +`--experimental-print-required-tla` (this would execute the modules +before looking for the top-level awaits). + ### `ERR_REQUIRE_CYCLE_MODULE` @@ -2474,19 +2487,6 @@ To avoid the cycle, the `require()` call involved in a cycle should not happen at the top-level of either an ES Module (via `createRequire()`) or a CommonJS module, and should be done lazily in an inner function. - - -### `ERR_REQUIRE_ASYNC_MODULE` - -> Stability: 1 - Experimental - -When trying to `require()` a [ES Module][], the module turns out to be asynchronous. -That is, it contains top-level await. - -To see where the top-level await is, use -`--experimental-print-required-tla` (this would execute the modules -before looking for the top-level awaits). - ### `ERR_REQUIRE_ESM` @@ -3022,6 +3022,16 @@ import 'package-name'; // supported `import` with URL schemes other than `file` and `data` is unsupported. + + +### `ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING` + + + +Type stripping is not supported for files descendent of a `node_modules` directory. + ### `ERR_UNSUPPORTED_RESOLVE_REQUEST` @@ -3042,16 +3052,6 @@ try { } ``` - - -### `ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING` - - - -Type stripping is not supported for files descendent of a `node_modules` directory. - ### `ERR_USE_AFTER_CLOSE` @@ -3067,18 +3067,18 @@ An attempt was made to use something that was already closed. While using the Performance Timing API (`perf_hooks`), no valid performance entry types are found. - - -### `ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING_FLAG` - -A dynamic import callback was invoked without `--experimental-vm-modules`. - ### `ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING` A dynamic import callback was not specified. + + +### `ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING_FLAG` + +A dynamic import callback was invoked without `--experimental-vm-modules`. + ### `ERR_VM_MODULE_ALREADY_LINKED` @@ -3164,25 +3164,6 @@ The `Worker` initialization failed. The `execArgv` option passed to the `Worker` constructor contains invalid flags. - - -### `ERR_WORKER_NOT_RUNNING` - -An operation failed because the `Worker` instance is not currently running. - - - -### `ERR_WORKER_OUT_OF_MEMORY` - -The `Worker` instance terminated because it reached its memory limit. - - - -### `ERR_WORKER_PATH` - -The path for the main script of a worker is neither an absolute path -nor a relative path starting with `./` or `../`. - ### `ERR_WORKER_MESSAGING_ERRORED` @@ -3231,6 +3212,25 @@ added: v22.5.0 Sending a message via [`postMessageToThread()`][] timed out. + + +### `ERR_WORKER_NOT_RUNNING` + +An operation failed because the `Worker` instance is not currently running. + + + +### `ERR_WORKER_OUT_OF_MEMORY` + +The `Worker` instance terminated because it reached its memory limit. + + + +### `ERR_WORKER_PATH` + +The path for the main script of a worker is neither an absolute path +nor a relative path starting with `./` or `../`. + ### `ERR_WORKER_UNSERIALIZABLE_ERROR` @@ -3249,6 +3249,21 @@ The requested functionality is not supported in worker threads. Creation of a [`zlib`][] object failed due to incorrect configuration. + + +### `HPE_CHUNK_EXTENSIONS_OVERFLOW` + + + +Too much data was received for a chunk extensions. In order to protect against +malicious or malconfigured clients, if more than 16 KiB of data is received +then an `Error` with this code will be emitted. + ### `HPE_HEADER_OVERFLOW` @@ -3268,21 +3283,6 @@ malconfigured clients, if more than `maxHeaderSize` of HTTP header data is recei HTTP parsing will abort without a request or response object being created, and an `Error` with this code will be emitted. - - -### `HPE_CHUNK_EXTENSIONS_OVERFLOW` - - - -Too much data was received for a chunk extensions. In order to protect against -malicious or malconfigured clients, if more than 16 KiB of data is received -then an `Error` with this code will be emitted. - ### `HPE_UNEXPECTED_CONTENT_LENGTH` @@ -3326,6 +3326,16 @@ removed: v12.5.0 The value passed to `postMessage()` contained an object that is not supported for transferring. + + +### `ERR_CPU_USAGE` + + + +The native call from `process.cpuUsage` could not be processed. + ### `ERR_CRYPTO_HASH_DIGEST_NO_UTF16` @@ -3433,6 +3443,45 @@ removed: v10.0.0 Used when an invalid character is found in an HTTP response status message (reason phrase). + + +### `ERR_IMPORT_ASSERTION_TYPE_FAILED` + + + +An import assertion has failed, preventing the specified module to be imported. + + + +### `ERR_IMPORT_ASSERTION_TYPE_MISSING` + + + +An import assertion is missing, preventing the specified module to be imported. + + + +### `ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED` + + + +An import attribute is not supported by this version of Node.js. + ### `ERR_INDEX_OUT_OF_RANGE` @@ -3492,45 +3541,6 @@ changes: An invalid transfer object was passed to `postMessage()`. - - -### `ERR_IMPORT_ASSERTION_TYPE_FAILED` - - - -An import assertion has failed, preventing the specified module to be imported. - - - -### `ERR_IMPORT_ASSERTION_TYPE_MISSING` - - - -An import assertion is missing, preventing the specified module to be imported. - - - -### `ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED` - - - -An import attribute is not supported by this version of Node.js. - ### `ERR_MANIFEST_ASSERT_INTEGRITY` @@ -3860,12 +3870,6 @@ removed: v10.0.0 Used when a given value is out of the accepted range. - - -### `ERR_VM_MODULE_NOT_LINKED` - -The module must be successfully linked before instantiation. - ### `ERR_VM_MODULE_LINKING_ERRORED` @@ -3879,6 +3883,12 @@ removed: The linker function returned a module for which linking has failed. + + +### `ERR_VM_MODULE_NOT_LINKED` + +The module must be successfully linked before instantiation. + ### `ERR_WORKER_UNSUPPORTED_EXTENSION` @@ -3903,16 +3913,6 @@ removed: v10.0.0 Used when an attempt is made to use a `zlib` object after it has already been closed. - - -### `ERR_CPU_USAGE` - - - -The native call from `process.cpuUsage` could not be processed. - ## OpenSSL Error Codes diff --git a/tools/eslint-rules/documented-errors.js b/tools/eslint-rules/documented-errors.js index 39021d973f2413..bb13880016328a 100644 --- a/tools/eslint-rules/documented-errors.js +++ b/tools/eslint-rules/documented-errors.js @@ -1,5 +1,6 @@ 'use strict'; +const assert = require('assert'); const fs = require('fs'); const path = require('path'); const { isDefiningError } = require('./rules-utils.js'); @@ -12,48 +13,55 @@ const doc = fs.readFileSync(docPath, 'utf8'); function getErrorsInDoc() { const lines = doc.split('\n'); let currentHeader; - const errors = new Map(); + const errors = new Set(); + const legacyErrors = new Set(); const codePattern = /^### `([^`]+)`$/; const anchorPattern = /^<\/a>$/; - function parse(line, legacy) { - const error = { legacy }; - let code; + let previousAnchor; - const codeMatch = line.match(codePattern); - if (codeMatch) { - error.header = true; - code = codeMatch[1]; - } - - const anchorMatch = line.match(anchorPattern); + function parse(line, legacy, lineNumber) { + const anchorMatch = anchorPattern.exec(line); if (anchorMatch) { - error.anchor = true; - code ??= anchorMatch[1]; + const code = anchorMatch[1]; + if (previousAnchor != null && previousAnchor > code) { + throw new Error(`Unordered error anchor in ${docPath}:${lineNumber}`, { cause: `${previousAnchor} ≤ ${code}` }); + } + previousAnchor = code; + return; } - if (!code) return; + const codeMatch = codePattern.exec(line); + if (codeMatch == null) return; - // If the code already exists in the Map, merge the new error data - errors.set(code, { - ...errors.get(code), - ...error, - }); + const code = codeMatch[1]; + if (previousAnchor == null) { + throw new Error(`Missing error anchor in ${docPath}:${lineNumber}`, { cause: code }); + } + assert.strictEqual(code, previousAnchor, `Error anchor do not match with error code in ${docPath}:${lineNumber}`); + + if (legacy && errors.has(code)) { + throw new Error(`Error is documented both as legacy and non-legacy in ${docPath}:${lineNumber}`, { cause: code }); + } + (legacy ? legacyErrors : errors).add(code); } + let lineNumber = 0; for (const line of lines) { + lineNumber++; if (line.startsWith('## ')) currentHeader = line.substring(3); - if (currentHeader === 'Node.js error codes') parse(line, false); - if (currentHeader === 'Legacy Node.js error codes') parse(line, true); + if (currentHeader === 'Node.js error codes') parse(line, false, lineNumber); + if (line === '## Legacy Node.js error codes') previousAnchor = null; + if (currentHeader === 'Legacy Node.js error codes') parse(line, true, lineNumber); } - return errors; + return { errors, legacyErrors }; } // Main rule export module.exports = { create(context) { - const errors = getErrorsInDoc(); + const { errors, legacyErrors } = getErrorsInDoc(); return { ExpressionStatement(node) { if (!isDefiningError(node)) return; @@ -61,27 +69,15 @@ module.exports = { const code = node.expression.arguments?.[0]?.value; if (!code) return; - const err = errors.get(code); // Use Map's get method to retrieve the error - - if (!err || !err.header) { + if (legacyErrors.has(code)) { context.report({ node, - message: `"${code}" is not documented in doc/api/errors.md`, - }); - if (!err) return; - } - - if (!err.anchor) { - context.report({ - node, - message: `doc/api/errors.md does not have an anchor for "${code}"`, + message: `"${code}" is marked as legacy, yet it is used in lib/.`, }); - } - - if (err.legacy) { + } else if (!errors.has(code)) { context.report({ node, - message: `"${code}" is marked as legacy, yet it is used in lib/.`, + message: `"${code}" is not documented in doc/api/errors.md`, }); } },