diff --git a/doc/api/errors.md b/doc/api/errors.md index 9f82d9706c1..0298c2b1e22 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -2325,6 +2325,17 @@ compiled with ICU support. A non-context-aware native addon was loaded in a process that disallows them. + + +### `ERR_OPERATION_FAILED` + + + +An operation failed. This is typically used to signal the general failure +of an asynchronous operation. + ### `ERR_OUT_OF_RANGE` @@ -2407,6 +2418,42 @@ Accessing `Object.prototype.__proto__` has been forbidden using [`Object.setPrototypeOf`][] should be used to get and set the prototype of an object. + + +### `ERR_QUIC_CONNECTION_FAILED` + + + +> Stability: 1 - Experimental + +Establishing a QUIC connection failed. + + + +### `ERR_QUIC_ENDPOINT_CLOSED` + + + +> Stability: 1 - Experimental + +A QUIC Endpoint closed with an error. + + + +### `ERR_QUIC_OPEN_STREAM_FAILED` + + + +> Stability: 1 - Experimental + +Opening a QUIC stream failed. + ### `ERR_REQUIRE_CYCLE_MODULE` @@ -2990,6 +3037,16 @@ try { } ``` + + +### `ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING` + + + +Type stripping is not supported for files descendent of a `node_modules` directory. + ### `ERR_USE_AFTER_CLOSE` @@ -3636,17 +3693,6 @@ error indicates that the idle loop has failed to stop. A Node.js API was called in an unsupported manner, such as `Buffer.write(string, encoding, offset[, length])`. - - -### `ERR_OPERATION_FAILED` - - - -An operation failed. This is typically used to signal the general failure -of an asynchronous operation. - ### `ERR_OUTOFMEMORY` @@ -3670,42 +3716,6 @@ removed: v10.0.0 The `node:repl` module was unable to parse data from the REPL history file. - - -### `ERR_QUIC_CONNECTION_FAILED` - - - -> Stability: 1 - Experimental - -Establishing a QUIC connection failed. - - - -### `ERR_QUIC_ENDPOINT_CLOSED` - - - -> Stability: 1 - Experimental - -A QUIC Endpoint closed with an error. - - - -### `ERR_QUIC_OPEN_STREAM_FAILED` - - - -> Stability: 1 - Experimental - -Opening a QUIC stream failed. - ### `ERR_SOCKET_CANNOT_SEND` @@ -4097,16 +4107,6 @@ The public key in the certificate SubjectPublicKeyInfo could not be read. An error occurred trying to allocate memory. This should never happen. - - -#### `ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING` - - - -Type stripping is not supported for files descendent of a `node_modules` directory. - [ES Module]: esm.md [ICU]: intl.md#internationalization-support [JSON Web Key Elliptic Curve Registry]: https://www.iana.org/assignments/jose/jose.xhtml#web-key-elliptic-curve diff --git a/test/parallel/test-eslint-documented-errors.js b/test/parallel/test-eslint-documented-errors.js index 03131306d7d..1759c786fd0 100644 --- a/test/parallel/test-eslint-documented-errors.js +++ b/test/parallel/test-eslint-documented-errors.js @@ -27,11 +27,6 @@ new RuleTester().run('documented-errors', rule, { message: `"${invalidCode}" is not documented in doc/api/errors.md`, line: 2 }, - { - message: - `doc/api/errors.md does not have an anchor for "${invalidCode}"`, - line: 2 - }, ] }, ] diff --git a/tools/eslint-rules/documented-errors.js b/tools/eslint-rules/documented-errors.js index 17bd2221097..39021d973f2 100644 --- a/tools/eslint-rules/documented-errors.js +++ b/tools/eslint-rules/documented-errors.js @@ -4,35 +4,85 @@ const fs = require('fs'); const path = require('path'); const { isDefiningError } = require('./rules-utils.js'); -const doc = fs.readFileSync(path.resolve(__dirname, '../../doc/api/errors.md'), - 'utf8'); +// Load the errors documentation file once +const docPath = path.resolve(__dirname, '../../doc/api/errors.md'); +const doc = fs.readFileSync(docPath, 'utf8'); -function isInDoc(code) { - return doc.includes(`### \`${code}\``); -} - -function includesAnchor(code) { - return doc.includes(``); -} - -function errorForNode(node) { - return node.expression.arguments[0].value; +// Helper function to parse errors documentation and return a Map +function getErrorsInDoc() { + const lines = doc.split('\n'); + let currentHeader; + const errors = new Map(); + const codePattern = /^### `([^`]+)`$/; + const anchorPattern = /^<\/a>$/; + + function parse(line, legacy) { + const error = { legacy }; + let code; + + const codeMatch = line.match(codePattern); + if (codeMatch) { + error.header = true; + code = codeMatch[1]; + } + + const anchorMatch = line.match(anchorPattern); + if (anchorMatch) { + error.anchor = true; + code ??= anchorMatch[1]; + } + + if (!code) return; + + // If the code already exists in the Map, merge the new error data + errors.set(code, { + ...errors.get(code), + ...error, + }); + } + + for (const line of lines) { + 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); + } + + return errors; } +// Main rule export module.exports = { - create: function(context) { + create(context) { + const errors = getErrorsInDoc(); return { - ExpressionStatement: function(node) { - if (!isDefiningError(node) || !errorForNode(node)) return; - const code = errorForNode(node); - if (!isInDoc(code)) { - const message = `"${code}" is not documented in doc/api/errors.md`; - context.report({ node, message }); + ExpressionStatement(node) { + if (!isDefiningError(node)) return; + + 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) { + context.report({ + node, + message: `"${code}" is not documented in doc/api/errors.md`, + }); + if (!err) return; } - if (!includesAnchor(code)) { - const message = - `doc/api/errors.md does not have an anchor for "${code}"`; - context.report({ node, message }); + + if (!err.anchor) { + context.report({ + node, + message: `doc/api/errors.md does not have an anchor for "${code}"`, + }); + } + + if (err.legacy) { + context.report({ + node, + message: `"${code}" is marked as legacy, yet it is used in lib/.`, + }); } }, };