node_modules: update (#344)

Co-authored-by: dawidd6 <9713907+dawidd6@users.noreply.github.com>
This commit is contained in:
Dawid Dziurlaanddawidd6 authored and GitHub committed 2026-10-10 17:27:57 +02:00
1 parent b099186883
commit 6e88c72525
63 files changed
+2863 -1227

No files matched your search

+209 -117
View File
@@ -8,6 +8,7 @@ import { isProtoKey, copyOwnKeys } from './objects.js';
import dns from 'node:dns';
import net from 'node:net';
import os from 'node:os';
import { finished } from 'node:stream';
// re-exported for the callers that already depend on this module, see ./objects
export { isProtoKey, copyOwnKeys };
const DNS_TTL = 5 * 60 * 1000;
@@ -21,14 +22,24 @@ export const _resetCacheCleanup = () => {
lastCacheCleanup = 0;
};
export let networkInterfaces;
try {
networkInterfaces = os.networkInterfaces();
}
catch (_err) {
// fails on some systems
}
let networkInterfacesRead = false;
// Read on first use rather than at load, so that importing the module does not ask for
// the interface table (Deno prompts for --allow-sys on it)
/** @internal */
export const _readNetworkInterfaces = () => {
if (!networkInterfacesRead) {
networkInterfacesRead = true;
try {
networkInterfaces = os.networkInterfaces();
}
catch (_err) {
// fails on some systems
}
}
return networkInterfaces;
};
const isFamilySupported = (family, allowInternal) => {
const addresses = Object.values(networkInterfaces || {}).flat();
const addresses = Object.values(_readNetworkInterfaces() || {}).flat();
if (!addresses.length) {
// hope for the best. Runtimes without an interface table (Cloudflare
// Workers) report an empty object rather than throwing
@@ -39,7 +50,8 @@ const isFamilySupported = (family, allowInternal) => {
const resolve = (family, hostname, options, callback) => {
options = options || {};
if (!isFamilySupported(family, options.allowInternalNetworkInterfaces)) {
return callback(null, []);
callback(null, []);
return null;
}
const dnsResolver = dns.Resolver ? new dns.Resolver(options) : dns;
dnsResolver['resolve' + family](hostname, (err, addresses) => {
@@ -58,6 +70,7 @@ const resolve = (family, hostname, options, callback) => {
}
return callback(null, Array.isArray(addresses) ? addresses : [].concat(addresses || []));
});
return dns.Resolver ? dnsResolver : null;
};
export const dnsCache = new Map();
const formatDNSValue = (value, extra) => {
@@ -121,115 +134,139 @@ export const resolveHostname = (options, callback) => {
}));
}
}
// Resolve both IPv4 and IPv6 addresses for fallback support
// The timeout limits the lookup as a whole. It is also handed to the resolver, but there
// it applies to every query attempt on its own, and the resolver retries a few times
let responded = false;
let deadline;
const respond = (err, result) => {
if (responded) {
return;
}
responded = true;
clearTimeout(deadline);
callback(err, result);
};
// a stale cached value is still better than no value at all
const respondCached = (error) => {
if (!cached) {
return false;
}
dnsCache.set(host, {
value: cached.value,
expires: Date.now() + (options.dnsTtl || DNS_TTL)
});
respond(null, formatDNSValue(cached.value, {
servername,
cached: true,
error
}));
return true;
};
const resolvers = [];
const timeout = Number(options.timeout) || 0;
if (timeout > 0) {
deadline = setTimeout(() => {
for (const resolver of resolvers) {
if (typeof resolver.cancel === 'function') {
resolver.cancel();
}
}
const err = new Error('DNS lookup for ' + host + ' timed out');
err.code = dns.TIMEOUT;
if (!respondCached(err)) {
respond(err);
}
}, timeout);
}
// Resolve both IPv4 and IPv6 addresses for fallback support, at the same time
let ipv4Addresses = [];
let ipv6Addresses = [];
let ipv4Error = null;
let ipv6Error = null;
resolve(4, options.host, options, (err, addresses) => {
if (err) {
ipv4Error = err;
let pending = 2;
const onResolved = () => {
if (--pending || responded) {
return;
}
else {
ipv4Addresses = addresses || [];
// Combine addresses: IPv4 first, then IPv6
const allAddresses = ipv4Addresses.concat(ipv6Addresses);
if (allAddresses.length) {
const value = {
addresses: allAddresses
};
dnsCache.set(host, {
value,
expires: Date.now() + (options.dnsTtl || DNS_TTL)
});
return respond(null, formatDNSValue(value, {
servername,
cached: false
}));
}
resolve(6, host, options, (err, addresses) => {
if (err) {
ipv6Error = err;
}
else {
ipv6Addresses = addresses || [];
}
// Combine addresses: IPv4 first, then IPv6
const allAddresses = ipv4Addresses.concat(ipv6Addresses);
if (allAddresses.length) {
// No addresses from resolve4/resolve6, try dns.lookup as fallback
if (ipv4Error && ipv6Error && respondCached(ipv4Error)) {
// Both resolvers had errors
return;
}
try {
dns.lookup(host, { all: true }, (err, addresses) => {
if (err) {
if (respondCached(err)) {
return;
}
return respond(err);
}
// Get all supported addresses from dns.lookup
const supportedAddresses = addresses
? addresses.filter(addr => isFamilySupported(addr.family)).map(addr => addr.address)
: [];
if (addresses && addresses.length && !supportedAddresses.length) {
// there are addresses but none can be used
console.warn(`Failed to resolve IPv${addresses[0].family} addresses with current network`);
}
if (!supportedAddresses.length && cached) {
// nothing was found, fallback to cached value
return respond(null, formatDNSValue(cached.value, {
servername,
cached: true
}));
}
const value = {
addresses: allAddresses
addresses: supportedAddresses.length ? supportedAddresses : [host]
};
dnsCache.set(host, {
value,
expires: Date.now() + (options.dnsTtl || DNS_TTL)
});
return callback(null, formatDNSValue(value, {
return respond(null, formatDNSValue(value, {
servername,
cached: false
}));
});
}
catch (lookupErr) {
if (respondCached(lookupErr)) {
return;
}
// No addresses from resolve4/resolve6, try dns.lookup as fallback
if (ipv4Error && ipv6Error) {
// Both resolvers had errors
if (cached) {
dnsCache.set(host, {
value: cached.value,
expires: Date.now() + (options.dnsTtl || DNS_TTL)
});
return callback(null, formatDNSValue(cached.value, {
servername,
cached: true,
error: ipv4Error
}));
}
return respond(ipv4Error || ipv6Error || lookupErr);
}
};
for (const family of [4, 6]) {
const resolver = resolve(family, host, options, (err, addresses) => {
if (family === 4) {
ipv4Error = err;
ipv4Addresses = addresses || [];
}
try {
dns.lookup(host, { all: true }, (err, addresses) => {
if (err) {
if (cached) {
dnsCache.set(host, {
value: cached.value,
expires: Date.now() + (options.dnsTtl || DNS_TTL)
});
return callback(null, formatDNSValue(cached.value, {
servername,
cached: true,
error: err
}));
}
return callback(err);
}
// Get all supported addresses from dns.lookup
const supportedAddresses = addresses
? addresses.filter(addr => isFamilySupported(addr.family)).map(addr => addr.address)
: [];
if (addresses && addresses.length && !supportedAddresses.length) {
// there are addresses but none can be used
console.warn(`Failed to resolve IPv${addresses[0].family} addresses with current network`);
}
if (!supportedAddresses.length && cached) {
// nothing was found, fallback to cached value
return callback(null, formatDNSValue(cached.value, {
servername,
cached: true
}));
}
const value = {
addresses: supportedAddresses.length ? supportedAddresses : [host]
};
dnsCache.set(host, {
value,
expires: Date.now() + (options.dnsTtl || DNS_TTL)
});
return callback(null, formatDNSValue(value, {
servername,
cached: false
}));
});
}
catch (lookupErr) {
if (cached) {
dnsCache.set(host, {
value: cached.value,
expires: Date.now() + (options.dnsTtl || DNS_TTL)
});
return callback(null, formatDNSValue(cached.value, {
servername,
cached: true,
error: lookupErr
}));
}
return callback(ipv4Error || ipv6Error || lookupErr);
else {
ipv6Error = err;
ipv6Addresses = addresses || [];
}
onResolved();
});
});
if (resolver) {
resolvers.push(resolver);
}
}
};
/**
* Parses connection url to a structured configuration object
@@ -548,43 +585,98 @@ export const encodeXText = (str) => {
}
return result;
};
// The first error a stream emitted, see recordStreamErrors
const streamErrors = new WeakMap();
/**
* Keeps the first error a content stream emits before it is read, so the error is reported
* when the stream is read instead of being thrown as unhandled. The listener stays attached
* for good, a stream that emits 'error' more than once never throws the later ones either
*
* @param stream Readable stream
*/
export function recordStreamErrors(stream) {
stream.on('error', err => {
if (!streamErrors.has(stream)) {
streamErrors.set(stream, err);
}
});
}
/**
* Destroys a value if it is a readable stream that was not destroyed yet
*
* @param value Any content value
*/
export function destroyStream(value) {
const stream = value;
if (stream && typeof stream.pipe === 'function' && typeof stream.destroy === 'function' && !stream.destroyed) {
stream.destroy();
}
}
/**
* Tells why a stream can not be read from start to end anymore. A stream that ended or was
* destroyed before anyone read it would never emit 'end' to a new reader, or, when piped, would
* end the destination right away and turn into an empty value without any error
*
* @param stream Readable stream
* @returns The error the stream failed with, an ESTREAM error, or null when it can be read
*/
export function unreadableStreamError(stream) {
const err = streamErrors.get(stream) || stream.errored;
if (err) {
return err;
}
if (stream.readableEnded || stream.destroyed) {
const unreadable = new Error('Content stream was already read or destroyed');
unreadable.code = errors.ESTREAM;
return unreadable;
}
return null;
}
/**
* Streams a stream value into a Buffer
*
* @param stream Readable stream
* @param callback Callback function with (err, value)
*/
function resolveStream(stream, callback) {
export function resolveStream(stream, callback) {
let responded = false;
const respond = (err, value) => {
if (responded) {
return;
}
responded = true;
callback(err, value);
};
const unreadable = unreadableStreamError(stream);
if (unreadable) {
// absorbs a later 'error' from the stream, there is nobody left to report it to
stream.on('error', () => false);
setImmediate(() => respond(unreadable));
return;
}
const chunks = [];
let chunklen = 0;
stream.on('error', err => {
if (responded) {
return;
stream.on('data', (chunk) => {
if (typeof chunk === 'string') {
chunk = Buffer.from(chunk);
}
responded = true;
callback(err);
chunks.push(chunk);
chunklen += chunk.length;
});
stream.on('readable', () => {
let chunk;
while ((chunk = stream.read()) !== null) {
chunks.push(chunk);
chunklen += chunk.length;
// finished() also reports a stream that is destroyed before 'end', which would otherwise
// leave the callback waiting forever
finished(stream, { writable: false }, err => {
if (err) {
return respond(err);
}
});
stream.on('end', () => {
if (responded) {
return;
}
responded = true;
let value;
try {
value = Buffer.concat(chunks, chunklen);
}
catch (E) {
return callback(E);
return respond(E);
}
callback(null, value);
respond(null, value);
});
}
/**