diff --git a/scripts/_lint-docs/lint-http-link.js b/scripts/_lint-docs/lint-http-link.js index 633f5321c..edc91a743 100644 --- a/scripts/_lint-docs/lint-http-link.js +++ b/scripts/_lint-docs/lint-http-link.js @@ -28,9 +28,9 @@ function checkKnownCorrectRequestFail(href, headers, status, body) { /** * Returns `undefined` if no error, a string if an error does occur. - * @param {(message?: string)} callback + * @param {(message?: string) => void} callback */ -function checkHttp(href, callback) { +function checkHttpInner(href, callback) { // Prefer https: > http: where possible, but allow http: when https: is inaccessible. const url = new URL(href) @@ -67,6 +67,39 @@ function checkHttp(href, callback) { }) } +// Kill the remaining duplication by using a global cache. +const urlCache = new Map() + +/** + * Returns `undefined` if no error, a string if an error does occur. + * @param {(message?: string) => void} callback + */ +function checkHttp(href, callback) { + if (href.includes("#")) { + process.exitCode = 1 + callback(`Expected href to be sanitized of hashes, but found ${href}`) + } + + if (urlCache.has(href)) { + const message = urlCache.get(href) + if (Array.isArray(message)) { + message.push(callback) + } else { + process.nextTick(callback, message) + } + } else { + const queue = [] + urlCache.set(href, queue) + checkHttpInner(href, (message) => { + urlCache.set(href, message) + process.nextTick(callback, message) + for (const callback of queue) { + process.nextTick(callback, message) + } + }) + } +} + module.exports = { checkHttp, } diff --git a/scripts/_lint-docs/task-queue.js b/scripts/_lint-docs/task-queue.js index 4f528aa86..8a26ebe4a 100644 --- a/scripts/_lint-docs/task-queue.js +++ b/scripts/_lint-docs/task-queue.js @@ -9,7 +9,7 @@ let running = 0 function runTask(task, callback) { process.nextTick(task, (...args) => { process.nextTick(callback, ...args) - if (running === maxConcurrency) { + if (running === maxConcurrency && queue.length !== 0) { const [nextTask, nextCallback] = queue.splice(0, 2) runTask(nextTask, nextCallback) } @@ -22,6 +22,14 @@ function runTask(task, callback) { * @param {(...args: A) => void} callback */ function submitTask(task, callback) { + if (typeof task !== "function") { + throw new TypeError("`task` must be a function") + } + + if (typeof callback !== "function") { + throw new TypeError("`callback` must be a function") + } + if (running < maxConcurrency) { running++ runTask(task, callback)