aboutsummaryrefslogtreecommitdiffstats
path: root/vanilla/node_modules/undici/lib/util
diff options
context:
space:
mode:
Diffstat (limited to 'vanilla/node_modules/undici/lib/util')
-rw-r--r--vanilla/node_modules/undici/lib/util/cache.js405
-rw-r--r--vanilla/node_modules/undici/lib/util/date.js653
-rw-r--r--vanilla/node_modules/undici/lib/util/promise.js28
-rw-r--r--vanilla/node_modules/undici/lib/util/runtime-features.js124
-rw-r--r--vanilla/node_modules/undici/lib/util/stats.js32
-rw-r--r--vanilla/node_modules/undici/lib/util/timers.js425
6 files changed, 0 insertions, 1667 deletions
diff --git a/vanilla/node_modules/undici/lib/util/cache.js b/vanilla/node_modules/undici/lib/util/cache.js
deleted file mode 100644
index b7627d0..0000000
--- a/vanilla/node_modules/undici/lib/util/cache.js
+++ /dev/null
@@ -1,405 +0,0 @@
-'use strict'
-
-const {
- safeHTTPMethods,
- pathHasQueryOrFragment
-} = require('../core/util')
-
-const { serializePathWithQuery } = require('../core/util')
-
-/**
- * @param {import('../../types/dispatcher.d.ts').default.DispatchOptions} opts
- */
-function makeCacheKey (opts) {
- if (!opts.origin) {
- throw new Error('opts.origin is undefined')
- }
-
- let fullPath = opts.path || '/'
-
- if (opts.query && !pathHasQueryOrFragment(opts.path)) {
- fullPath = serializePathWithQuery(fullPath, opts.query)
- }
-
- return {
- origin: opts.origin.toString(),
- method: opts.method,
- path: fullPath,
- headers: opts.headers
- }
-}
-
-/**
- * @param {Record<string, string[] | string>}
- * @returns {Record<string, string[] | string>}
- */
-function normalizeHeaders (opts) {
- let headers
- if (opts.headers == null) {
- headers = {}
- } else if (typeof opts.headers[Symbol.iterator] === 'function') {
- headers = {}
- for (const x of opts.headers) {
- if (!Array.isArray(x)) {
- throw new Error('opts.headers is not a valid header map')
- }
- const [key, val] = x
- if (typeof key !== 'string' || typeof val !== 'string') {
- throw new Error('opts.headers is not a valid header map')
- }
- headers[key.toLowerCase()] = val
- }
- } else if (typeof opts.headers === 'object') {
- headers = {}
-
- for (const key of Object.keys(opts.headers)) {
- headers[key.toLowerCase()] = opts.headers[key]
- }
- } else {
- throw new Error('opts.headers is not an object')
- }
-
- return headers
-}
-
-/**
- * @param {any} key
- */
-function assertCacheKey (key) {
- if (typeof key !== 'object') {
- throw new TypeError(`expected key to be object, got ${typeof key}`)
- }
-
- for (const property of ['origin', 'method', 'path']) {
- if (typeof key[property] !== 'string') {
- throw new TypeError(`expected key.${property} to be string, got ${typeof key[property]}`)
- }
- }
-
- if (key.headers !== undefined && typeof key.headers !== 'object') {
- throw new TypeError(`expected headers to be object, got ${typeof key}`)
- }
-}
-
-/**
- * @param {any} value
- */
-function assertCacheValue (value) {
- if (typeof value !== 'object') {
- throw new TypeError(`expected value to be object, got ${typeof value}`)
- }
-
- for (const property of ['statusCode', 'cachedAt', 'staleAt', 'deleteAt']) {
- if (typeof value[property] !== 'number') {
- throw new TypeError(`expected value.${property} to be number, got ${typeof value[property]}`)
- }
- }
-
- if (typeof value.statusMessage !== 'string') {
- throw new TypeError(`expected value.statusMessage to be string, got ${typeof value.statusMessage}`)
- }
-
- if (value.headers != null && typeof value.headers !== 'object') {
- throw new TypeError(`expected value.rawHeaders to be object, got ${typeof value.headers}`)
- }
-
- if (value.vary !== undefined && typeof value.vary !== 'object') {
- throw new TypeError(`expected value.vary to be object, got ${typeof value.vary}`)
- }
-
- if (value.etag !== undefined && typeof value.etag !== 'string') {
- throw new TypeError(`expected value.etag to be string, got ${typeof value.etag}`)
- }
-}
-
-/**
- * @see https://www.rfc-editor.org/rfc/rfc9111.html#name-cache-control
- * @see https://www.iana.org/assignments/http-cache-directives/http-cache-directives.xhtml
-
- * @param {string | string[]} header
- * @returns {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives}
- */
-function parseCacheControlHeader (header) {
- /**
- * @type {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives}
- */
- const output = {}
-
- let directives
- if (Array.isArray(header)) {
- directives = []
-
- for (const directive of header) {
- directives.push(...directive.split(','))
- }
- } else {
- directives = header.split(',')
- }
-
- for (let i = 0; i < directives.length; i++) {
- const directive = directives[i].toLowerCase()
- const keyValueDelimiter = directive.indexOf('=')
-
- let key
- let value
- if (keyValueDelimiter !== -1) {
- key = directive.substring(0, keyValueDelimiter).trimStart()
- value = directive.substring(keyValueDelimiter + 1)
- } else {
- key = directive.trim()
- }
-
- switch (key) {
- case 'min-fresh':
- case 'max-stale':
- case 'max-age':
- case 's-maxage':
- case 'stale-while-revalidate':
- case 'stale-if-error': {
- if (value === undefined || value[0] === ' ') {
- continue
- }
-
- if (
- value.length >= 2 &&
- value[0] === '"' &&
- value[value.length - 1] === '"'
- ) {
- value = value.substring(1, value.length - 1)
- }
-
- const parsedValue = parseInt(value, 10)
- // eslint-disable-next-line no-self-compare
- if (parsedValue !== parsedValue) {
- continue
- }
-
- if (key === 'max-age' && key in output && output[key] >= parsedValue) {
- continue
- }
-
- output[key] = parsedValue
-
- break
- }
- case 'private':
- case 'no-cache': {
- if (value) {
- // The private and no-cache directives can be unqualified (aka just
- // `private` or `no-cache`) or qualified (w/ a value). When they're
- // qualified, it's a list of headers like `no-cache=header1`,
- // `no-cache="header1"`, or `no-cache="header1, header2"`
- // If we're given multiple headers, the comma messes us up since
- // we split the full header by commas. So, let's loop through the
- // remaining parts in front of us until we find one that ends in a
- // quote. We can then just splice all of the parts in between the
- // starting quote and the ending quote out of the directives array
- // and continue parsing like normal.
- // https://www.rfc-editor.org/rfc/rfc9111.html#name-no-cache-2
- if (value[0] === '"') {
- // Something like `no-cache="some-header"` OR `no-cache="some-header, another-header"`.
-
- // Add the first header on and cut off the leading quote
- const headers = [value.substring(1)]
-
- let foundEndingQuote = value[value.length - 1] === '"'
- if (!foundEndingQuote) {
- // Something like `no-cache="some-header, another-header"`
- // This can still be something invalid, e.g. `no-cache="some-header, ...`
- for (let j = i + 1; j < directives.length; j++) {
- const nextPart = directives[j]
- const nextPartLength = nextPart.length
-
- headers.push(nextPart.trim())
-
- if (nextPartLength !== 0 && nextPart[nextPartLength - 1] === '"') {
- foundEndingQuote = true
- break
- }
- }
- }
-
- if (foundEndingQuote) {
- let lastHeader = headers[headers.length - 1]
- if (lastHeader[lastHeader.length - 1] === '"') {
- lastHeader = lastHeader.substring(0, lastHeader.length - 1)
- headers[headers.length - 1] = lastHeader
- }
-
- if (key in output) {
- output[key] = output[key].concat(headers)
- } else {
- output[key] = headers
- }
- }
- } else {
- // Something like `no-cache="some-header"`
- if (key in output) {
- output[key] = output[key].concat(value)
- } else {
- output[key] = [value]
- }
- }
-
- break
- }
- }
- // eslint-disable-next-line no-fallthrough
- case 'public':
- case 'no-store':
- case 'must-revalidate':
- case 'proxy-revalidate':
- case 'immutable':
- case 'no-transform':
- case 'must-understand':
- case 'only-if-cached':
- if (value) {
- // These are qualified (something like `public=...`) when they aren't
- // allowed to be, skip
- continue
- }
-
- output[key] = true
- break
- default:
- // Ignore unknown directives as per https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.3-1
- continue
- }
- }
-
- return output
-}
-
-/**
- * @param {string | string[]} varyHeader Vary header from the server
- * @param {Record<string, string | string[]>} headers Request headers
- * @returns {Record<string, string | string[]>}
- */
-function parseVaryHeader (varyHeader, headers) {
- if (typeof varyHeader === 'string' && varyHeader.includes('*')) {
- return headers
- }
-
- const output = /** @type {Record<string, string | string[] | null>} */ ({})
-
- const varyingHeaders = typeof varyHeader === 'string'
- ? varyHeader.split(',')
- : varyHeader
-
- for (const header of varyingHeaders) {
- const trimmedHeader = header.trim().toLowerCase()
-
- output[trimmedHeader] = headers[trimmedHeader] ?? null
- }
-
- return output
-}
-
-/**
- * Note: this deviates from the spec a little. Empty etags ("", W/"") are valid,
- * however, including them in cached resposnes serves little to no purpose.
- *
- * @see https://www.rfc-editor.org/rfc/rfc9110.html#name-etag
- *
- * @param {string} etag
- * @returns {boolean}
- */
-function isEtagUsable (etag) {
- if (etag.length <= 2) {
- // Shortest an etag can be is two chars (just ""). This is where we deviate
- // from the spec requiring a min of 3 chars however
- return false
- }
-
- if (etag[0] === '"' && etag[etag.length - 1] === '"') {
- // ETag: ""asd123"" or ETag: "W/"asd123"", kinda undefined behavior in the
- // spec. Some servers will accept these while others don't.
- // ETag: "asd123"
- return !(etag[1] === '"' || etag.startsWith('"W/'))
- }
-
- if (etag.startsWith('W/"') && etag[etag.length - 1] === '"') {
- // ETag: W/"", also where we deviate from the spec & require a min of 3
- // chars
- // ETag: for W/"", W/"asd123"
- return etag.length !== 4
- }
-
- // Anything else
- return false
-}
-
-/**
- * @param {unknown} store
- * @returns {asserts store is import('../../types/cache-interceptor.d.ts').default.CacheStore}
- */
-function assertCacheStore (store, name = 'CacheStore') {
- if (typeof store !== 'object' || store === null) {
- throw new TypeError(`expected type of ${name} to be a CacheStore, got ${store === null ? 'null' : typeof store}`)
- }
-
- for (const fn of ['get', 'createWriteStream', 'delete']) {
- if (typeof store[fn] !== 'function') {
- throw new TypeError(`${name} needs to have a \`${fn}()\` function`)
- }
- }
-}
-/**
- * @param {unknown} methods
- * @returns {asserts methods is import('../../types/cache-interceptor.d.ts').default.CacheMethods[]}
- */
-function assertCacheMethods (methods, name = 'CacheMethods') {
- if (!Array.isArray(methods)) {
- throw new TypeError(`expected type of ${name} needs to be an array, got ${methods === null ? 'null' : typeof methods}`)
- }
-
- if (methods.length === 0) {
- throw new TypeError(`${name} needs to have at least one method`)
- }
-
- for (const method of methods) {
- if (!safeHTTPMethods.includes(method)) {
- throw new TypeError(`element of ${name}-array needs to be one of following values: ${safeHTTPMethods.join(', ')}, got ${method}`)
- }
- }
-}
-
-/**
- * Creates a string key for request deduplication purposes.
- * This key is used to identify in-flight requests that can be shared.
- * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey
- * @param {Set<string>} [excludeHeaders] Set of lowercase header names to exclude from the key
- * @returns {string}
- */
-function makeDeduplicationKey (cacheKey, excludeHeaders) {
- // Create a deterministic string key from the cache key
- // Include origin, method, path, and sorted headers
- let key = `${cacheKey.origin}:${cacheKey.method}:${cacheKey.path}`
-
- if (cacheKey.headers) {
- const sortedHeaders = Object.keys(cacheKey.headers).sort()
- for (const header of sortedHeaders) {
- // Skip excluded headers
- if (excludeHeaders?.has(header.toLowerCase())) {
- continue
- }
- const value = cacheKey.headers[header]
- key += `:${header}=${Array.isArray(value) ? value.join(',') : value}`
- }
- }
-
- return key
-}
-
-module.exports = {
- makeCacheKey,
- normalizeHeaders,
- assertCacheKey,
- assertCacheValue,
- parseCacheControlHeader,
- parseVaryHeader,
- isEtagUsable,
- assertCacheMethods,
- assertCacheStore,
- makeDeduplicationKey
-}
diff --git a/vanilla/node_modules/undici/lib/util/date.js b/vanilla/node_modules/undici/lib/util/date.js
deleted file mode 100644
index 99dd150..0000000
--- a/vanilla/node_modules/undici/lib/util/date.js
+++ /dev/null
@@ -1,653 +0,0 @@
-'use strict'
-
-/**
- * @see https://www.rfc-editor.org/rfc/rfc9110.html#name-date-time-formats
- *
- * @param {string} date
- * @returns {Date | undefined}
- */
-function parseHttpDate (date) {
- // Sun, 06 Nov 1994 08:49:37 GMT ; IMF-fixdate
- // Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
- // Sunday, 06-Nov-94 08:49:37 GMT ; obsolete RFC 850 format
-
- switch (date[3]) {
- case ',': return parseImfDate(date)
- case ' ': return parseAscTimeDate(date)
- default: return parseRfc850Date(date)
- }
-}
-
-/**
- * @see https://httpwg.org/specs/rfc9110.html#preferred.date.format
- *
- * @param {string} date
- * @returns {Date | undefined}
- */
-function parseImfDate (date) {
- if (
- date.length !== 29 ||
- date[4] !== ' ' ||
- date[7] !== ' ' ||
- date[11] !== ' ' ||
- date[16] !== ' ' ||
- date[19] !== ':' ||
- date[22] !== ':' ||
- date[25] !== ' ' ||
- date[26] !== 'G' ||
- date[27] !== 'M' ||
- date[28] !== 'T'
- ) {
- return undefined
- }
-
- let weekday = -1
- if (date[0] === 'S' && date[1] === 'u' && date[2] === 'n') { // Sunday
- weekday = 0
- } else if (date[0] === 'M' && date[1] === 'o' && date[2] === 'n') { // Monday
- weekday = 1
- } else if (date[0] === 'T' && date[1] === 'u' && date[2] === 'e') { // Tuesday
- weekday = 2
- } else if (date[0] === 'W' && date[1] === 'e' && date[2] === 'd') { // Wednesday
- weekday = 3
- } else if (date[0] === 'T' && date[1] === 'h' && date[2] === 'u') { // Thursday
- weekday = 4
- } else if (date[0] === 'F' && date[1] === 'r' && date[2] === 'i') { // Friday
- weekday = 5
- } else if (date[0] === 'S' && date[1] === 'a' && date[2] === 't') { // Saturday
- weekday = 6
- } else {
- return undefined // Not a valid day of the week
- }
-
- let day = 0
- if (date[5] === '0') {
- // Single digit day, e.g. "Sun Nov 6 08:49:37 1994"
- const code = date.charCodeAt(6)
- if (code < 49 || code > 57) {
- return undefined // Not a digit
- }
- day = code - 48 // Convert ASCII code to number
- } else {
- const code1 = date.charCodeAt(5)
- if (code1 < 49 || code1 > 51) {
- return undefined // Not a digit between 1 and 3
- }
- const code2 = date.charCodeAt(6)
- if (code2 < 48 || code2 > 57) {
- return undefined // Not a digit
- }
- day = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number
- }
-
- let monthIdx = -1
- if (
- (date[8] === 'J' && date[9] === 'a' && date[10] === 'n')
- ) {
- monthIdx = 0 // Jan
- } else if (
- (date[8] === 'F' && date[9] === 'e' && date[10] === 'b')
- ) {
- monthIdx = 1 // Feb
- } else if (
- (date[8] === 'M' && date[9] === 'a')
- ) {
- if (date[10] === 'r') {
- monthIdx = 2 // Mar
- } else if (date[10] === 'y') {
- monthIdx = 4 // May
- } else {
- return undefined // Invalid month
- }
- } else if (
- (date[8] === 'J')
- ) {
- if (date[9] === 'a' && date[10] === 'n') {
- monthIdx = 0 // Jan
- } else if (date[9] === 'u') {
- if (date[10] === 'n') {
- monthIdx = 5 // Jun
- } else if (date[10] === 'l') {
- monthIdx = 6 // Jul
- } else {
- return undefined // Invalid month
- }
- } else {
- return undefined // Invalid month
- }
- } else if (
- (date[8] === 'A')
- ) {
- if (date[9] === 'p' && date[10] === 'r') {
- monthIdx = 3 // Apr
- } else if (date[9] === 'u' && date[10] === 'g') {
- monthIdx = 7 // Aug
- } else {
- return undefined // Invalid month
- }
- } else if (
- (date[8] === 'S' && date[9] === 'e' && date[10] === 'p')
- ) {
- monthIdx = 8 // Sep
- } else if (
- (date[8] === 'O' && date[9] === 'c' && date[10] === 't')
- ) {
- monthIdx = 9 // Oct
- } else if (
- (date[8] === 'N' && date[9] === 'o' && date[10] === 'v')
- ) {
- monthIdx = 10 // Nov
- } else if (
- (date[8] === 'D' && date[9] === 'e' && date[10] === 'c')
- ) {
- monthIdx = 11 // Dec
- } else {
- // Not a valid month
- return undefined
- }
-
- const yearDigit1 = date.charCodeAt(12)
- if (yearDigit1 < 48 || yearDigit1 > 57) {
- return undefined // Not a digit
- }
- const yearDigit2 = date.charCodeAt(13)
- if (yearDigit2 < 48 || yearDigit2 > 57) {
- return undefined // Not a digit
- }
- const yearDigit3 = date.charCodeAt(14)
- if (yearDigit3 < 48 || yearDigit3 > 57) {
- return undefined // Not a digit
- }
- const yearDigit4 = date.charCodeAt(15)
- if (yearDigit4 < 48 || yearDigit4 > 57) {
- return undefined // Not a digit
- }
- const year = (yearDigit1 - 48) * 1000 + (yearDigit2 - 48) * 100 + (yearDigit3 - 48) * 10 + (yearDigit4 - 48)
-
- let hour = 0
- if (date[17] === '0') {
- const code = date.charCodeAt(18)
- if (code < 48 || code > 57) {
- return undefined // Not a digit
- }
- hour = code - 48 // Convert ASCII code to number
- } else {
- const code1 = date.charCodeAt(17)
- if (code1 < 48 || code1 > 50) {
- return undefined // Not a digit between 0 and 2
- }
- const code2 = date.charCodeAt(18)
- if (code2 < 48 || code2 > 57) {
- return undefined // Not a digit
- }
- if (code1 === 50 && code2 > 51) {
- return undefined // Hour cannot be greater than 23
- }
- hour = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number
- }
-
- let minute = 0
- if (date[20] === '0') {
- const code = date.charCodeAt(21)
- if (code < 48 || code > 57) {
- return undefined // Not a digit
- }
- minute = code - 48 // Convert ASCII code to number
- } else {
- const code1 = date.charCodeAt(20)
- if (code1 < 48 || code1 > 53) {
- return undefined // Not a digit between 0 and 5
- }
- const code2 = date.charCodeAt(21)
- if (code2 < 48 || code2 > 57) {
- return undefined // Not a digit
- }
- minute = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number
- }
-
- let second = 0
- if (date[23] === '0') {
- const code = date.charCodeAt(24)
- if (code < 48 || code > 57) {
- return undefined // Not a digit
- }
- second = code - 48 // Convert ASCII code to number
- } else {
- const code1 = date.charCodeAt(23)
- if (code1 < 48 || code1 > 53) {
- return undefined // Not a digit between 0 and 5
- }
- const code2 = date.charCodeAt(24)
- if (code2 < 48 || code2 > 57) {
- return undefined // Not a digit
- }
- second = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number
- }
-
- const result = new Date(Date.UTC(year, monthIdx, day, hour, minute, second))
- return result.getUTCDay() === weekday ? result : undefined
-}
-
-/**
- * @see https://httpwg.org/specs/rfc9110.html#obsolete.date.formats
- *
- * @param {string} date
- * @returns {Date | undefined}
- */
-function parseAscTimeDate (date) {
- // This is assumed to be in UTC
-
- if (
- date.length !== 24 ||
- date[7] !== ' ' ||
- date[10] !== ' ' ||
- date[19] !== ' '
- ) {
- return undefined
- }
-
- let weekday = -1
- if (date[0] === 'S' && date[1] === 'u' && date[2] === 'n') { // Sunday
- weekday = 0
- } else if (date[0] === 'M' && date[1] === 'o' && date[2] === 'n') { // Monday
- weekday = 1
- } else if (date[0] === 'T' && date[1] === 'u' && date[2] === 'e') { // Tuesday
- weekday = 2
- } else if (date[0] === 'W' && date[1] === 'e' && date[2] === 'd') { // Wednesday
- weekday = 3
- } else if (date[0] === 'T' && date[1] === 'h' && date[2] === 'u') { // Thursday
- weekday = 4
- } else if (date[0] === 'F' && date[1] === 'r' && date[2] === 'i') { // Friday
- weekday = 5
- } else if (date[0] === 'S' && date[1] === 'a' && date[2] === 't') { // Saturday
- weekday = 6
- } else {
- return undefined // Not a valid day of the week
- }
-
- let monthIdx = -1
- if (
- (date[4] === 'J' && date[5] === 'a' && date[6] === 'n')
- ) {
- monthIdx = 0 // Jan
- } else if (
- (date[4] === 'F' && date[5] === 'e' && date[6] === 'b')
- ) {
- monthIdx = 1 // Feb
- } else if (
- (date[4] === 'M' && date[5] === 'a')
- ) {
- if (date[6] === 'r') {
- monthIdx = 2 // Mar
- } else if (date[6] === 'y') {
- monthIdx = 4 // May
- } else {
- return undefined // Invalid month
- }
- } else if (
- (date[4] === 'J')
- ) {
- if (date[5] === 'a' && date[6] === 'n') {
- monthIdx = 0 // Jan
- } else if (date[5] === 'u') {
- if (date[6] === 'n') {
- monthIdx = 5 // Jun
- } else if (date[6] === 'l') {
- monthIdx = 6 // Jul
- } else {
- return undefined // Invalid month
- }
- } else {
- return undefined // Invalid month
- }
- } else if (
- (date[4] === 'A')
- ) {
- if (date[5] === 'p' && date[6] === 'r') {
- monthIdx = 3 // Apr
- } else if (date[5] === 'u' && date[6] === 'g') {
- monthIdx = 7 // Aug
- } else {
- return undefined // Invalid month
- }
- } else if (
- (date[4] === 'S' && date[5] === 'e' && date[6] === 'p')
- ) {
- monthIdx = 8 // Sep
- } else if (
- (date[4] === 'O' && date[5] === 'c' && date[6] === 't')
- ) {
- monthIdx = 9 // Oct
- } else if (
- (date[4] === 'N' && date[5] === 'o' && date[6] === 'v')
- ) {
- monthIdx = 10 // Nov
- } else if (
- (date[4] === 'D' && date[5] === 'e' && date[6] === 'c')
- ) {
- monthIdx = 11 // Dec
- } else {
- // Not a valid month
- return undefined
- }
-
- let day = 0
- if (date[8] === ' ') {
- // Single digit day, e.g. "Sun Nov 6 08:49:37 1994"
- const code = date.charCodeAt(9)
- if (code < 49 || code > 57) {
- return undefined // Not a digit
- }
- day = code - 48 // Convert ASCII code to number
- } else {
- const code1 = date.charCodeAt(8)
- if (code1 < 49 || code1 > 51) {
- return undefined // Not a digit between 1 and 3
- }
- const code2 = date.charCodeAt(9)
- if (code2 < 48 || code2 > 57) {
- return undefined // Not a digit
- }
- day = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number
- }
-
- let hour = 0
- if (date[11] === '0') {
- const code = date.charCodeAt(12)
- if (code < 48 || code > 57) {
- return undefined // Not a digit
- }
- hour = code - 48 // Convert ASCII code to number
- } else {
- const code1 = date.charCodeAt(11)
- if (code1 < 48 || code1 > 50) {
- return undefined // Not a digit between 0 and 2
- }
- const code2 = date.charCodeAt(12)
- if (code2 < 48 || code2 > 57) {
- return undefined // Not a digit
- }
- if (code1 === 50 && code2 > 51) {
- return undefined // Hour cannot be greater than 23
- }
- hour = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number
- }
-
- let minute = 0
- if (date[14] === '0') {
- const code = date.charCodeAt(15)
- if (code < 48 || code > 57) {
- return undefined // Not a digit
- }
- minute = code - 48 // Convert ASCII code to number
- } else {
- const code1 = date.charCodeAt(14)
- if (code1 < 48 || code1 > 53) {
- return undefined // Not a digit between 0 and 5
- }
- const code2 = date.charCodeAt(15)
- if (code2 < 48 || code2 > 57) {
- return undefined // Not a digit
- }
- minute = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number
- }
-
- let second = 0
- if (date[17] === '0') {
- const code = date.charCodeAt(18)
- if (code < 48 || code > 57) {
- return undefined // Not a digit
- }
- second = code - 48 // Convert ASCII code to number
- } else {
- const code1 = date.charCodeAt(17)
- if (code1 < 48 || code1 > 53) {
- return undefined // Not a digit between 0 and 5
- }
- const code2 = date.charCodeAt(18)
- if (code2 < 48 || code2 > 57) {
- return undefined // Not a digit
- }
- second = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number
- }
-
- const yearDigit1 = date.charCodeAt(20)
- if (yearDigit1 < 48 || yearDigit1 > 57) {
- return undefined // Not a digit
- }
- const yearDigit2 = date.charCodeAt(21)
- if (yearDigit2 < 48 || yearDigit2 > 57) {
- return undefined // Not a digit
- }
- const yearDigit3 = date.charCodeAt(22)
- if (yearDigit3 < 48 || yearDigit3 > 57) {
- return undefined // Not a digit
- }
- const yearDigit4 = date.charCodeAt(23)
- if (yearDigit4 < 48 || yearDigit4 > 57) {
- return undefined // Not a digit
- }
- const year = (yearDigit1 - 48) * 1000 + (yearDigit2 - 48) * 100 + (yearDigit3 - 48) * 10 + (yearDigit4 - 48)
-
- const result = new Date(Date.UTC(year, monthIdx, day, hour, minute, second))
- return result.getUTCDay() === weekday ? result : undefined
-}
-
-/**
- * @see https://httpwg.org/specs/rfc9110.html#obsolete.date.formats
- *
- * @param {string} date
- * @returns {Date | undefined}
- */
-function parseRfc850Date (date) {
- let commaIndex = -1
-
- let weekday = -1
- if (date[0] === 'S') {
- if (date[1] === 'u' && date[2] === 'n' && date[3] === 'd' && date[4] === 'a' && date[5] === 'y') {
- weekday = 0 // Sunday
- commaIndex = 6
- } else if (date[1] === 'a' && date[2] === 't' && date[3] === 'u' && date[4] === 'r' && date[5] === 'd' && date[6] === 'a' && date[7] === 'y') {
- weekday = 6 // Saturday
- commaIndex = 8
- }
- } else if (date[0] === 'M' && date[1] === 'o' && date[2] === 'n' && date[3] === 'd' && date[4] === 'a' && date[5] === 'y') {
- weekday = 1 // Monday
- commaIndex = 6
- } else if (date[0] === 'T') {
- if (date[1] === 'u' && date[2] === 'e' && date[3] === 's' && date[4] === 'd' && date[5] === 'a' && date[6] === 'y') {
- weekday = 2 // Tuesday
- commaIndex = 7
- } else if (date[1] === 'h' && date[2] === 'u' && date[3] === 'r' && date[4] === 's' && date[5] === 'd' && date[6] === 'a' && date[7] === 'y') {
- weekday = 4 // Thursday
- commaIndex = 8
- }
- } else if (date[0] === 'W' && date[1] === 'e' && date[2] === 'd' && date[3] === 'n' && date[4] === 'e' && date[5] === 's' && date[6] === 'd' && date[7] === 'a' && date[8] === 'y') {
- weekday = 3 // Wednesday
- commaIndex = 9
- } else if (date[0] === 'F' && date[1] === 'r' && date[2] === 'i' && date[3] === 'd' && date[4] === 'a' && date[5] === 'y') {
- weekday = 5 // Friday
- commaIndex = 6
- } else {
- // Not a valid day name
- return undefined
- }
-
- if (
- date[commaIndex] !== ',' ||
- (date.length - commaIndex - 1) !== 23 ||
- date[commaIndex + 1] !== ' ' ||
- date[commaIndex + 4] !== '-' ||
- date[commaIndex + 8] !== '-' ||
- date[commaIndex + 11] !== ' ' ||
- date[commaIndex + 14] !== ':' ||
- date[commaIndex + 17] !== ':' ||
- date[commaIndex + 20] !== ' ' ||
- date[commaIndex + 21] !== 'G' ||
- date[commaIndex + 22] !== 'M' ||
- date[commaIndex + 23] !== 'T'
- ) {
- return undefined
- }
-
- let day = 0
- if (date[commaIndex + 2] === '0') {
- // Single digit day, e.g. "Sun Nov 6 08:49:37 1994"
- const code = date.charCodeAt(commaIndex + 3)
- if (code < 49 || code > 57) {
- return undefined // Not a digit
- }
- day = code - 48 // Convert ASCII code to number
- } else {
- const code1 = date.charCodeAt(commaIndex + 2)
- if (code1 < 49 || code1 > 51) {
- return undefined // Not a digit between 1 and 3
- }
- const code2 = date.charCodeAt(commaIndex + 3)
- if (code2 < 48 || code2 > 57) {
- return undefined // Not a digit
- }
- day = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number
- }
-
- let monthIdx = -1
- if (
- (date[commaIndex + 5] === 'J' && date[commaIndex + 6] === 'a' && date[commaIndex + 7] === 'n')
- ) {
- monthIdx = 0 // Jan
- } else if (
- (date[commaIndex + 5] === 'F' && date[commaIndex + 6] === 'e' && date[commaIndex + 7] === 'b')
- ) {
- monthIdx = 1 // Feb
- } else if (
- (date[commaIndex + 5] === 'M' && date[commaIndex + 6] === 'a' && date[commaIndex + 7] === 'r')
- ) {
- monthIdx = 2 // Mar
- } else if (
- (date[commaIndex + 5] === 'A' && date[commaIndex + 6] === 'p' && date[commaIndex + 7] === 'r')
- ) {
- monthIdx = 3 // Apr
- } else if (
- (date[commaIndex + 5] === 'M' && date[commaIndex + 6] === 'a' && date[commaIndex + 7] === 'y')
- ) {
- monthIdx = 4 // May
- } else if (
- (date[commaIndex + 5] === 'J' && date[commaIndex + 6] === 'u' && date[commaIndex + 7] === 'n')
- ) {
- monthIdx = 5 // Jun
- } else if (
- (date[commaIndex + 5] === 'J' && date[commaIndex + 6] === 'u' && date[commaIndex + 7] === 'l')
- ) {
- monthIdx = 6 // Jul
- } else if (
- (date[commaIndex + 5] === 'A' && date[commaIndex + 6] === 'u' && date[commaIndex + 7] === 'g')
- ) {
- monthIdx = 7 // Aug
- } else if (
- (date[commaIndex + 5] === 'S' && date[commaIndex + 6] === 'e' && date[commaIndex + 7] === 'p')
- ) {
- monthIdx = 8 // Sep
- } else if (
- (date[commaIndex + 5] === 'O' && date[commaIndex + 6] === 'c' && date[commaIndex + 7] === 't')
- ) {
- monthIdx = 9 // Oct
- } else if (
- (date[commaIndex + 5] === 'N' && date[commaIndex + 6] === 'o' && date[commaIndex + 7] === 'v')
- ) {
- monthIdx = 10 // Nov
- } else if (
- (date[commaIndex + 5] === 'D' && date[commaIndex + 6] === 'e' && date[commaIndex + 7] === 'c')
- ) {
- monthIdx = 11 // Dec
- } else {
- // Not a valid month
- return undefined
- }
-
- const yearDigit1 = date.charCodeAt(commaIndex + 9)
- if (yearDigit1 < 48 || yearDigit1 > 57) {
- return undefined // Not a digit
- }
- const yearDigit2 = date.charCodeAt(commaIndex + 10)
- if (yearDigit2 < 48 || yearDigit2 > 57) {
- return undefined // Not a digit
- }
-
- let year = (yearDigit1 - 48) * 10 + (yearDigit2 - 48) // Convert ASCII codes to number
-
- // RFC 6265 states that the year is in the range 1970-2069.
- // @see https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.1
- //
- // 3. If the year-value is greater than or equal to 70 and less than or
- // equal to 99, increment the year-value by 1900.
- // 4. If the year-value is greater than or equal to 0 and less than or
- // equal to 69, increment the year-value by 2000.
- year += year < 70 ? 2000 : 1900
-
- let hour = 0
- if (date[commaIndex + 12] === '0') {
- const code = date.charCodeAt(commaIndex + 13)
- if (code < 48 || code > 57) {
- return undefined // Not a digit
- }
- hour = code - 48 // Convert ASCII code to number
- } else {
- const code1 = date.charCodeAt(commaIndex + 12)
- if (code1 < 48 || code1 > 50) {
- return undefined // Not a digit between 0 and 2
- }
- const code2 = date.charCodeAt(commaIndex + 13)
- if (code2 < 48 || code2 > 57) {
- return undefined // Not a digit
- }
- if (code1 === 50 && code2 > 51) {
- return undefined // Hour cannot be greater than 23
- }
- hour = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number
- }
-
- let minute = 0
- if (date[commaIndex + 15] === '0') {
- const code = date.charCodeAt(commaIndex + 16)
- if (code < 48 || code > 57) {
- return undefined // Not a digit
- }
- minute = code - 48 // Convert ASCII code to number
- } else {
- const code1 = date.charCodeAt(commaIndex + 15)
- if (code1 < 48 || code1 > 53) {
- return undefined // Not a digit between 0 and 5
- }
- const code2 = date.charCodeAt(commaIndex + 16)
- if (code2 < 48 || code2 > 57) {
- return undefined // Not a digit
- }
- minute = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number
- }
-
- let second = 0
- if (date[commaIndex + 18] === '0') {
- const code = date.charCodeAt(commaIndex + 19)
- if (code < 48 || code > 57) {
- return undefined // Not a digit
- }
- second = code - 48 // Convert ASCII code to number
- } else {
- const code1 = date.charCodeAt(commaIndex + 18)
- if (code1 < 48 || code1 > 53) {
- return undefined // Not a digit between 0 and 5
- }
- const code2 = date.charCodeAt(commaIndex + 19)
- if (code2 < 48 || code2 > 57) {
- return undefined // Not a digit
- }
- second = (code1 - 48) * 10 + (code2 - 48) // Convert ASCII codes to number
- }
-
- const result = new Date(Date.UTC(year, monthIdx, day, hour, minute, second))
- return result.getUTCDay() === weekday ? result : undefined
-}
-
-module.exports = {
- parseHttpDate
-}
diff --git a/vanilla/node_modules/undici/lib/util/promise.js b/vanilla/node_modules/undici/lib/util/promise.js
deleted file mode 100644
index 048f86e..0000000
--- a/vanilla/node_modules/undici/lib/util/promise.js
+++ /dev/null
@@ -1,28 +0,0 @@
-'use strict'
-
-/**
- * @template {*} T
- * @typedef {Object} DeferredPromise
- * @property {Promise<T>} promise
- * @property {(value?: T) => void} resolve
- * @property {(reason?: any) => void} reject
- */
-
-/**
- * @template {*} T
- * @returns {DeferredPromise<T>} An object containing a promise and its resolve/reject methods.
- */
-function createDeferredPromise () {
- let res
- let rej
- const promise = new Promise((resolve, reject) => {
- res = resolve
- rej = reject
- })
-
- return { promise, resolve: res, reject: rej }
-}
-
-module.exports = {
- createDeferredPromise
-}
diff --git a/vanilla/node_modules/undici/lib/util/runtime-features.js b/vanilla/node_modules/undici/lib/util/runtime-features.js
deleted file mode 100644
index 3e62dc0..0000000
--- a/vanilla/node_modules/undici/lib/util/runtime-features.js
+++ /dev/null
@@ -1,124 +0,0 @@
-'use strict'
-
-/** @typedef {`node:${string}`} NodeModuleName */
-
-/** @type {Record<NodeModuleName, () => any>} */
-const lazyLoaders = {
- __proto__: null,
- 'node:crypto': () => require('node:crypto'),
- 'node:sqlite': () => require('node:sqlite'),
- 'node:worker_threads': () => require('node:worker_threads'),
- 'node:zlib': () => require('node:zlib')
-}
-
-/**
- * @param {NodeModuleName} moduleName
- * @returns {boolean}
- */
-function detectRuntimeFeatureByNodeModule (moduleName) {
- try {
- lazyLoaders[moduleName]()
- return true
- } catch (err) {
- if (err.code !== 'ERR_UNKNOWN_BUILTIN_MODULE' && err.code !== 'ERR_NO_CRYPTO') {
- throw err
- }
- return false
- }
-}
-
-/**
- * @param {NodeModuleName} moduleName
- * @param {string} property
- * @returns {boolean}
- */
-function detectRuntimeFeatureByExportedProperty (moduleName, property) {
- const module = lazyLoaders[moduleName]()
- return typeof module[property] !== 'undefined'
-}
-
-const runtimeFeaturesByExportedProperty = /** @type {const} */ (['markAsUncloneable', 'zstd'])
-
-/** @type {Record<RuntimeFeatureByExportedProperty, [NodeModuleName, string]>} */
-const exportedPropertyLookup = {
- markAsUncloneable: ['node:worker_threads', 'markAsUncloneable'],
- zstd: ['node:zlib', 'createZstdDecompress']
-}
-
-/** @typedef {typeof runtimeFeaturesByExportedProperty[number]} RuntimeFeatureByExportedProperty */
-
-const runtimeFeaturesAsNodeModule = /** @type {const} */ (['crypto', 'sqlite'])
-/** @typedef {typeof runtimeFeaturesAsNodeModule[number]} RuntimeFeatureByNodeModule */
-
-const features = /** @type {const} */ ([
- ...runtimeFeaturesAsNodeModule,
- ...runtimeFeaturesByExportedProperty
-])
-
-/** @typedef {typeof features[number]} Feature */
-
-/**
- * @param {Feature} feature
- * @returns {boolean}
- */
-function detectRuntimeFeature (feature) {
- if (runtimeFeaturesAsNodeModule.includes(/** @type {RuntimeFeatureByNodeModule} */ (feature))) {
- return detectRuntimeFeatureByNodeModule(`node:${feature}`)
- } else if (runtimeFeaturesByExportedProperty.includes(/** @type {RuntimeFeatureByExportedProperty} */ (feature))) {
- const [moduleName, property] = exportedPropertyLookup[feature]
- return detectRuntimeFeatureByExportedProperty(moduleName, property)
- }
- throw new TypeError(`unknown feature: ${feature}`)
-}
-
-/**
- * @class
- * @name RuntimeFeatures
- */
-class RuntimeFeatures {
- /** @type {Map<Feature, boolean>} */
- #map = new Map()
-
- /**
- * Clears all cached feature detections.
- */
- clear () {
- this.#map.clear()
- }
-
- /**
- * @param {Feature} feature
- * @returns {boolean}
- */
- has (feature) {
- return (
- this.#map.get(feature) ?? this.#detectRuntimeFeature(feature)
- )
- }
-
- /**
- * @param {Feature} feature
- * @param {boolean} value
- */
- set (feature, value) {
- if (features.includes(feature) === false) {
- throw new TypeError(`unknown feature: ${feature}`)
- }
- this.#map.set(feature, value)
- }
-
- /**
- * @param {Feature} feature
- * @returns {boolean}
- */
- #detectRuntimeFeature (feature) {
- const result = detectRuntimeFeature(feature)
- this.#map.set(feature, result)
- return result
- }
-}
-
-const instance = new RuntimeFeatures()
-
-module.exports.runtimeFeatures = instance
-module.exports.default = instance
diff --git a/vanilla/node_modules/undici/lib/util/stats.js b/vanilla/node_modules/undici/lib/util/stats.js
deleted file mode 100644
index a13132e..0000000
--- a/vanilla/node_modules/undici/lib/util/stats.js
+++ /dev/null
@@ -1,32 +0,0 @@
-'use strict'
-
-const {
- kConnected,
- kPending,
- kRunning,
- kSize,
- kFree,
- kQueued
-} = require('../core/symbols')
-
-class ClientStats {
- constructor (client) {
- this.connected = client[kConnected]
- this.pending = client[kPending]
- this.running = client[kRunning]
- this.size = client[kSize]
- }
-}
-
-class PoolStats {
- constructor (pool) {
- this.connected = pool[kConnected]
- this.free = pool[kFree]
- this.pending = pool[kPending]
- this.queued = pool[kQueued]
- this.running = pool[kRunning]
- this.size = pool[kSize]
- }
-}
-
-module.exports = { ClientStats, PoolStats }
diff --git a/vanilla/node_modules/undici/lib/util/timers.js b/vanilla/node_modules/undici/lib/util/timers.js
deleted file mode 100644
index 14984d4..0000000
--- a/vanilla/node_modules/undici/lib/util/timers.js
+++ /dev/null
@@ -1,425 +0,0 @@
-'use strict'
-
-/**
- * This module offers an optimized timer implementation designed for scenarios
- * where high precision is not critical.
- *
- * The timer achieves faster performance by using a low-resolution approach,
- * with an accuracy target of within 500ms. This makes it particularly useful
- * for timers with delays of 1 second or more, where exact timing is less
- * crucial.
- *
- * It's important to note that Node.js timers are inherently imprecise, as
- * delays can occur due to the event loop being blocked by other operations.
- * Consequently, timers may trigger later than their scheduled time.
- */
-
-/**
- * The fastNow variable contains the internal fast timer clock value.
- *
- * @type {number}
- */
-let fastNow = 0
-
-/**
- * RESOLUTION_MS represents the target resolution time in milliseconds.
- *
- * @type {number}
- * @default 1000
- */
-const RESOLUTION_MS = 1e3
-
-/**
- * TICK_MS defines the desired interval in milliseconds between each tick.
- * The target value is set to half the resolution time, minus 1 ms, to account
- * for potential event loop overhead.
- *
- * @type {number}
- * @default 499
- */
-const TICK_MS = (RESOLUTION_MS >> 1) - 1
-
-/**
- * fastNowTimeout is a Node.js timer used to manage and process
- * the FastTimers stored in the `fastTimers` array.
- *
- * @type {NodeJS.Timeout}
- */
-let fastNowTimeout
-
-/**
- * The kFastTimer symbol is used to identify FastTimer instances.
- *
- * @type {Symbol}
- */
-const kFastTimer = Symbol('kFastTimer')
-
-/**
- * The fastTimers array contains all active FastTimers.
- *
- * @type {FastTimer[]}
- */
-const fastTimers = []
-
-/**
- * These constants represent the various states of a FastTimer.
- */
-
-/**
- * The `NOT_IN_LIST` constant indicates that the FastTimer is not included
- * in the `fastTimers` array. Timers with this status will not be processed
- * during the next tick by the `onTick` function.
- *
- * A FastTimer can be re-added to the `fastTimers` array by invoking the
- * `refresh` method on the FastTimer instance.
- *
- * @type {-2}
- */
-const NOT_IN_LIST = -2
-
-/**
- * The `TO_BE_CLEARED` constant indicates that the FastTimer is scheduled
- * for removal from the `fastTimers` array. A FastTimer in this state will
- * be removed in the next tick by the `onTick` function and will no longer
- * be processed.
- *
- * This status is also set when the `clear` method is called on the FastTimer instance.
- *
- * @type {-1}
- */
-const TO_BE_CLEARED = -1
-
-/**
- * The `PENDING` constant signifies that the FastTimer is awaiting processing
- * in the next tick by the `onTick` function. Timers with this status will have
- * their `_idleStart` value set and their status updated to `ACTIVE` in the next tick.
- *
- * @type {0}
- */
-const PENDING = 0
-
-/**
- * The `ACTIVE` constant indicates that the FastTimer is active and waiting
- * for its timer to expire. During the next tick, the `onTick` function will
- * check if the timer has expired, and if so, it will execute the associated callback.
- *
- * @type {1}
- */
-const ACTIVE = 1
-
-/**
- * The onTick function processes the fastTimers array.
- *
- * @returns {void}
- */
-function onTick () {
- /**
- * Increment the fastNow value by the TICK_MS value, despite the actual time
- * that has passed since the last tick. This approach ensures independence
- * from the system clock and delays caused by a blocked event loop.
- *
- * @type {number}
- */
- fastNow += TICK_MS
-
- /**
- * The `idx` variable is used to iterate over the `fastTimers` array.
- * Expired timers are removed by replacing them with the last element in the array.
- * Consequently, `idx` is only incremented when the current element is not removed.
- *
- * @type {number}
- */
- let idx = 0
-
- /**
- * The len variable will contain the length of the fastTimers array
- * and will be decremented when a FastTimer should be removed from the
- * fastTimers array.
- *
- * @type {number}
- */
- let len = fastTimers.length
-
- while (idx < len) {
- /**
- * @type {FastTimer}
- */
- const timer = fastTimers[idx]
-
- // If the timer is in the ACTIVE state and the timer has expired, it will
- // be processed in the next tick.
- if (timer._state === PENDING) {
- // Set the _idleStart value to the fastNow value minus the TICK_MS value
- // to account for the time the timer was in the PENDING state.
- timer._idleStart = fastNow - TICK_MS
- timer._state = ACTIVE
- } else if (
- timer._state === ACTIVE &&
- fastNow >= timer._idleStart + timer._idleTimeout
- ) {
- timer._state = TO_BE_CLEARED
- timer._idleStart = -1
- timer._onTimeout(timer._timerArg)
- }
-
- if (timer._state === TO_BE_CLEARED) {
- timer._state = NOT_IN_LIST
-
- // Move the last element to the current index and decrement len if it is
- // not the only element in the array.
- if (--len !== 0) {
- fastTimers[idx] = fastTimers[len]
- }
- } else {
- ++idx
- }
- }
-
- // Set the length of the fastTimers array to the new length and thus
- // removing the excess FastTimers elements from the array.
- fastTimers.length = len
-
- // If there are still active FastTimers in the array, refresh the Timer.
- // If there are no active FastTimers, the timer will be refreshed again
- // when a new FastTimer is instantiated.
- if (fastTimers.length !== 0) {
- refreshTimeout()
- }
-}
-
-function refreshTimeout () {
- // If the fastNowTimeout is already set and the Timer has the refresh()-
- // method available, call it to refresh the timer.
- // Some timer objects returned by setTimeout may not have a .refresh()
- // method (e.g. mocked timers in tests).
- if (fastNowTimeout?.refresh) {
- fastNowTimeout.refresh()
- // fastNowTimeout is not instantiated yet or refresh is not availabe,
- // create a new Timer.
- } else {
- clearTimeout(fastNowTimeout)
- fastNowTimeout = setTimeout(onTick, TICK_MS)
- // If the Timer has an unref method, call it to allow the process to exit,
- // if there are no other active handles. When using fake timers or mocked
- // environments (like Jest), .unref() may not be defined,
- fastNowTimeout?.unref()
- }
-}
-
-/**
- * The `FastTimer` class is a data structure designed to store and manage
- * timer information.
- */
-class FastTimer {
- [kFastTimer] = true
-
- /**
- * The state of the timer, which can be one of the following:
- * - NOT_IN_LIST (-2)
- * - TO_BE_CLEARED (-1)
- * - PENDING (0)
- * - ACTIVE (1)
- *
- * @type {-2|-1|0|1}
- * @private
- */
- _state = NOT_IN_LIST
-
- /**
- * The number of milliseconds to wait before calling the callback.
- *
- * @type {number}
- * @private
- */
- _idleTimeout = -1
-
- /**
- * The time in milliseconds when the timer was started. This value is used to
- * calculate when the timer should expire.
- *
- * @type {number}
- * @default -1
- * @private
- */
- _idleStart = -1
-
- /**
- * The function to be executed when the timer expires.
- * @type {Function}
- * @private
- */
- _onTimeout
-
- /**
- * The argument to be passed to the callback when the timer expires.
- *
- * @type {*}
- * @private
- */
- _timerArg
-
- /**
- * @constructor
- * @param {Function} callback A function to be executed after the timer
- * expires.
- * @param {number} delay The time, in milliseconds that the timer should wait
- * before the specified function or code is executed.
- * @param {*} arg
- */
- constructor (callback, delay, arg) {
- this._onTimeout = callback
- this._idleTimeout = delay
- this._timerArg = arg
-
- this.refresh()
- }
-
- /**
- * Sets the timer's start time to the current time, and reschedules the timer
- * to call its callback at the previously specified duration adjusted to the
- * current time.
- * Using this on a timer that has already called its callback will reactivate
- * the timer.
- *
- * @returns {void}
- */
- refresh () {
- // In the special case that the timer is not in the list of active timers,
- // add it back to the array to be processed in the next tick by the onTick
- // function.
- if (this._state === NOT_IN_LIST) {
- fastTimers.push(this)
- }
-
- // If the timer is the only active timer, refresh the fastNowTimeout for
- // better resolution.
- if (!fastNowTimeout || fastTimers.length === 1) {
- refreshTimeout()
- }
-
- // Setting the state to PENDING will cause the timer to be reset in the
- // next tick by the onTick function.
- this._state = PENDING
- }
-
- /**
- * The `clear` method cancels the timer, preventing it from executing.
- *
- * @returns {void}
- * @private
- */
- clear () {
- // Set the state to TO_BE_CLEARED to mark the timer for removal in the next
- // tick by the onTick function.
- this._state = TO_BE_CLEARED
-
- // Reset the _idleStart value to -1 to indicate that the timer is no longer
- // active.
- this._idleStart = -1
- }
-}
-
-/**
- * This module exports a setTimeout and clearTimeout function that can be
- * used as a drop-in replacement for the native functions.
- */
-module.exports = {
- /**
- * The setTimeout() method sets a timer which executes a function once the
- * timer expires.
- * @param {Function} callback A function to be executed after the timer
- * expires.
- * @param {number} delay The time, in milliseconds that the timer should
- * wait before the specified function or code is executed.
- * @param {*} [arg] An optional argument to be passed to the callback function
- * when the timer expires.
- * @returns {NodeJS.Timeout|FastTimer}
- */
- setTimeout (callback, delay, arg) {
- // If the delay is less than or equal to the RESOLUTION_MS value return a
- // native Node.js Timer instance.
- return delay <= RESOLUTION_MS
- ? setTimeout(callback, delay, arg)
- : new FastTimer(callback, delay, arg)
- },
- /**
- * The clearTimeout method cancels an instantiated Timer previously created
- * by calling setTimeout.
- *
- * @param {NodeJS.Timeout|FastTimer} timeout
- */
- clearTimeout (timeout) {
- // If the timeout is a FastTimer, call its own clear method.
- if (timeout[kFastTimer]) {
- /**
- * @type {FastTimer}
- */
- timeout.clear()
- // Otherwise it is an instance of a native NodeJS.Timeout, so call the
- // Node.js native clearTimeout function.
- } else {
- clearTimeout(timeout)
- }
- },
- /**
- * The setFastTimeout() method sets a fastTimer which executes a function once
- * the timer expires.
- * @param {Function} callback A function to be executed after the timer
- * expires.
- * @param {number} delay The time, in milliseconds that the timer should
- * wait before the specified function or code is executed.
- * @param {*} [arg] An optional argument to be passed to the callback function
- * when the timer expires.
- * @returns {FastTimer}
- */
- setFastTimeout (callback, delay, arg) {
- return new FastTimer(callback, delay, arg)
- },
- /**
- * The clearTimeout method cancels an instantiated FastTimer previously
- * created by calling setFastTimeout.
- *
- * @param {FastTimer} timeout
- */
- clearFastTimeout (timeout) {
- timeout.clear()
- },
- /**
- * The now method returns the value of the internal fast timer clock.
- *
- * @returns {number}
- */
- now () {
- return fastNow
- },
- /**
- * Trigger the onTick function to process the fastTimers array.
- * Exported for testing purposes only.
- * Marking as deprecated to discourage any use outside of testing.
- * @deprecated
- * @param {number} [delay=0] The delay in milliseconds to add to the now value.
- */
- tick (delay = 0) {
- fastNow += delay - RESOLUTION_MS + 1
- onTick()
- onTick()
- },
- /**
- * Reset FastTimers.
- * Exported for testing purposes only.
- * Marking as deprecated to discourage any use outside of testing.
- * @deprecated
- */
- reset () {
- fastNow = 0
- fastTimers.length = 0
- clearTimeout(fastNowTimeout)
- fastNowTimeout = null
- },
- /**
- * Exporting for testing purposes only.
- * Marking as deprecated to discourage any use outside of testing.
- * @deprecated
- */
- kFastTimer
-}