format: prettify entire project

This commit is contained in:
Rim
2025-04-02 06:50:39 -04:00
parent 86f0782a98
commit 7ccc0be712
1711 changed files with 755867 additions and 235931 deletions

View File

@ -1,59 +1,59 @@
'use strict'
'use strict';
const { addAbortListener } = require('../core/util')
const { RequestAbortedError } = require('../core/errors')
const { addAbortListener } = require('../core/util');
const { RequestAbortedError } = require('../core/errors');
const kListener = Symbol('kListener')
const kSignal = Symbol('kSignal')
const kListener = Symbol('kListener');
const kSignal = Symbol('kSignal');
function abort (self) {
function abort(self) {
if (self.abort) {
self.abort(self[kSignal]?.reason)
self.abort(self[kSignal]?.reason);
} else {
self.reason = self[kSignal]?.reason ?? new RequestAbortedError()
self.reason = self[kSignal]?.reason ?? new RequestAbortedError();
}
removeSignal(self)
removeSignal(self);
}
function addSignal (self, signal) {
self.reason = null
function addSignal(self, signal) {
self.reason = null;
self[kSignal] = null
self[kListener] = null
self[kSignal] = null;
self[kListener] = null;
if (!signal) {
return
return;
}
if (signal.aborted) {
abort(self)
return
abort(self);
return;
}
self[kSignal] = signal
self[kSignal] = signal;
self[kListener] = () => {
abort(self)
}
abort(self);
};
addAbortListener(self[kSignal], self[kListener])
addAbortListener(self[kSignal], self[kListener]);
}
function removeSignal (self) {
function removeSignal(self) {
if (!self[kSignal]) {
return
return;
}
if ('removeEventListener' in self[kSignal]) {
self[kSignal].removeEventListener('abort', self[kListener])
self[kSignal].removeEventListener('abort', self[kListener]);
} else {
self[kSignal].removeListener('abort', self[kListener])
self[kSignal].removeListener('abort', self[kListener]);
}
self[kSignal] = null
self[kListener] = null
self[kSignal] = null;
self[kListener] = null;
}
module.exports = {
addSignal,
removeSignal
}
removeSignal,
};

View File

@ -1,64 +1,73 @@
'use strict'
'use strict';
const assert = require('node:assert')
const { AsyncResource } = require('node:async_hooks')
const { InvalidArgumentError, SocketError } = require('../core/errors')
const util = require('../core/util')
const { addSignal, removeSignal } = require('./abort-signal')
const assert = require('node:assert');
const { AsyncResource } = require('node:async_hooks');
const { InvalidArgumentError, SocketError } = require('../core/errors');
const util = require('../core/util');
const { addSignal, removeSignal } = require('./abort-signal');
class ConnectHandler extends AsyncResource {
constructor (opts, callback) {
constructor(opts, callback) {
if (!opts || typeof opts !== 'object') {
throw new InvalidArgumentError('invalid opts')
throw new InvalidArgumentError('invalid opts');
}
if (typeof callback !== 'function') {
throw new InvalidArgumentError('invalid callback')
throw new InvalidArgumentError('invalid callback');
}
const { signal, opaque, responseHeaders } = opts
const { signal, opaque, responseHeaders } = opts;
if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') {
throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget')
if (
signal &&
typeof signal.on !== 'function' &&
typeof signal.addEventListener !== 'function'
) {
throw new InvalidArgumentError(
'signal must be an EventEmitter or EventTarget'
);
}
super('UNDICI_CONNECT')
super('UNDICI_CONNECT');
this.opaque = opaque || null
this.responseHeaders = responseHeaders || null
this.callback = callback
this.abort = null
this.opaque = opaque || null;
this.responseHeaders = responseHeaders || null;
this.callback = callback;
this.abort = null;
addSignal(this, signal)
addSignal(this, signal);
}
onConnect (abort, context) {
onConnect(abort, context) {
if (this.reason) {
abort(this.reason)
return
abort(this.reason);
return;
}
assert(this.callback)
assert(this.callback);
this.abort = abort
this.context = context
this.abort = abort;
this.context = context;
}
onHeaders () {
throw new SocketError('bad connect', null)
onHeaders() {
throw new SocketError('bad connect', null);
}
onUpgrade (statusCode, rawHeaders, socket) {
const { callback, opaque, context } = this
onUpgrade(statusCode, rawHeaders, socket) {
const { callback, opaque, context } = this;
removeSignal(this)
removeSignal(this);
this.callback = null
this.callback = null;
let headers = rawHeaders
let headers = rawHeaders;
// Indicates is an HTTP2Session
if (headers != null) {
headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders)
headers =
this.responseHeaders === 'raw' ?
util.parseRawHeaders(rawHeaders)
: util.parseHeaders(rawHeaders);
}
this.runInAsyncScope(callback, null, null, {
@ -66,45 +75,45 @@ class ConnectHandler extends AsyncResource {
headers,
socket,
opaque,
context
})
context,
});
}
onError (err) {
const { callback, opaque } = this
onError(err) {
const { callback, opaque } = this;
removeSignal(this)
removeSignal(this);
if (callback) {
this.callback = null
this.callback = null;
queueMicrotask(() => {
this.runInAsyncScope(callback, null, err, { opaque })
})
this.runInAsyncScope(callback, null, err, { opaque });
});
}
}
}
function connect (opts, callback) {
function connect(opts, callback) {
if (callback === undefined) {
return new Promise((resolve, reject) => {
connect.call(this, opts, (err, data) => {
return err ? reject(err) : resolve(data)
})
})
return err ? reject(err) : resolve(data);
});
});
}
try {
const connectHandler = new ConnectHandler(opts, callback)
const connectOptions = { ...opts, method: 'CONNECT' }
const connectHandler = new ConnectHandler(opts, callback);
const connectOptions = { ...opts, method: 'CONNECT' };
this.dispatch(connectOptions, connectHandler)
this.dispatch(connectOptions, connectHandler);
} catch (err) {
if (typeof callback !== 'function') {
throw err
throw err;
}
const opaque = opts?.opaque
queueMicrotask(() => callback(err, { opaque }))
const opaque = opts?.opaque;
queueMicrotask(() => callback(err, { opaque }));
}
}
module.exports = connect
module.exports = connect;

View File

@ -1,252 +1,260 @@
'use strict'
'use strict';
const {
Readable,
Duplex,
PassThrough
} = require('node:stream')
const assert = require('node:assert')
const { AsyncResource } = require('node:async_hooks')
const { Readable, Duplex, PassThrough } = require('node:stream');
const assert = require('node:assert');
const { AsyncResource } = require('node:async_hooks');
const {
InvalidArgumentError,
InvalidReturnValueError,
RequestAbortedError
} = require('../core/errors')
const util = require('../core/util')
const { addSignal, removeSignal } = require('./abort-signal')
RequestAbortedError,
} = require('../core/errors');
const util = require('../core/util');
const { addSignal, removeSignal } = require('./abort-signal');
function noop () {}
function noop() {}
const kResume = Symbol('resume')
const kResume = Symbol('resume');
class PipelineRequest extends Readable {
constructor () {
super({ autoDestroy: true })
constructor() {
super({ autoDestroy: true });
this[kResume] = null
this[kResume] = null;
}
_read () {
const { [kResume]: resume } = this
_read() {
const { [kResume]: resume } = this;
if (resume) {
this[kResume] = null
resume()
this[kResume] = null;
resume();
}
}
_destroy (err, callback) {
this._read()
_destroy(err, callback) {
this._read();
callback(err)
callback(err);
}
}
class PipelineResponse extends Readable {
constructor (resume) {
super({ autoDestroy: true })
this[kResume] = resume
constructor(resume) {
super({ autoDestroy: true });
this[kResume] = resume;
}
_read () {
this[kResume]()
_read() {
this[kResume]();
}
_destroy (err, callback) {
_destroy(err, callback) {
if (!err && !this._readableState.endEmitted) {
err = new RequestAbortedError()
err = new RequestAbortedError();
}
callback(err)
callback(err);
}
}
class PipelineHandler extends AsyncResource {
constructor (opts, handler) {
constructor(opts, handler) {
if (!opts || typeof opts !== 'object') {
throw new InvalidArgumentError('invalid opts')
throw new InvalidArgumentError('invalid opts');
}
if (typeof handler !== 'function') {
throw new InvalidArgumentError('invalid handler')
throw new InvalidArgumentError('invalid handler');
}
const { signal, method, opaque, onInfo, responseHeaders } = opts
const { signal, method, opaque, onInfo, responseHeaders } = opts;
if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') {
throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget')
if (
signal &&
typeof signal.on !== 'function' &&
typeof signal.addEventListener !== 'function'
) {
throw new InvalidArgumentError(
'signal must be an EventEmitter or EventTarget'
);
}
if (method === 'CONNECT') {
throw new InvalidArgumentError('invalid method')
throw new InvalidArgumentError('invalid method');
}
if (onInfo && typeof onInfo !== 'function') {
throw new InvalidArgumentError('invalid onInfo callback')
throw new InvalidArgumentError('invalid onInfo callback');
}
super('UNDICI_PIPELINE')
super('UNDICI_PIPELINE');
this.opaque = opaque || null
this.responseHeaders = responseHeaders || null
this.handler = handler
this.abort = null
this.context = null
this.onInfo = onInfo || null
this.opaque = opaque || null;
this.responseHeaders = responseHeaders || null;
this.handler = handler;
this.abort = null;
this.context = null;
this.onInfo = onInfo || null;
this.req = new PipelineRequest().on('error', noop)
this.req = new PipelineRequest().on('error', noop);
this.ret = new Duplex({
readableObjectMode: opts.objectMode,
autoDestroy: true,
read: () => {
const { body } = this
const { body } = this;
if (body?.resume) {
body.resume()
body.resume();
}
},
write: (chunk, encoding, callback) => {
const { req } = this
const { req } = this;
if (req.push(chunk, encoding) || req._readableState.destroyed) {
callback()
callback();
} else {
req[kResume] = callback
req[kResume] = callback;
}
},
destroy: (err, callback) => {
const { body, req, res, ret, abort } = this
const { body, req, res, ret, abort } = this;
if (!err && !ret._readableState.endEmitted) {
err = new RequestAbortedError()
err = new RequestAbortedError();
}
if (abort && err) {
abort()
abort();
}
util.destroy(body, err)
util.destroy(req, err)
util.destroy(res, err)
util.destroy(body, err);
util.destroy(req, err);
util.destroy(res, err);
removeSignal(this)
removeSignal(this);
callback(err)
}
callback(err);
},
}).on('prefinish', () => {
const { req } = this
const { req } = this;
// Node < 15 does not call _final in same tick.
req.push(null)
})
req.push(null);
});
this.res = null
this.res = null;
addSignal(this, signal)
addSignal(this, signal);
}
onConnect (abort, context) {
const { res } = this
onConnect(abort, context) {
const { res } = this;
if (this.reason) {
abort(this.reason)
return
abort(this.reason);
return;
}
assert(!res, 'pipeline cannot be retried')
assert(!res, 'pipeline cannot be retried');
this.abort = abort
this.context = context
this.abort = abort;
this.context = context;
}
onHeaders (statusCode, rawHeaders, resume) {
const { opaque, handler, context } = this
onHeaders(statusCode, rawHeaders, resume) {
const { opaque, handler, context } = this;
if (statusCode < 200) {
if (this.onInfo) {
const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders)
this.onInfo({ statusCode, headers })
const headers =
this.responseHeaders === 'raw' ?
util.parseRawHeaders(rawHeaders)
: util.parseHeaders(rawHeaders);
this.onInfo({ statusCode, headers });
}
return
return;
}
this.res = new PipelineResponse(resume)
this.res = new PipelineResponse(resume);
let body
let body;
try {
this.handler = null
const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders)
this.handler = null;
const headers =
this.responseHeaders === 'raw' ?
util.parseRawHeaders(rawHeaders)
: util.parseHeaders(rawHeaders);
body = this.runInAsyncScope(handler, null, {
statusCode,
headers,
opaque,
body: this.res,
context
})
context,
});
} catch (err) {
this.res.on('error', noop)
throw err
this.res.on('error', noop);
throw err;
}
if (!body || typeof body.on !== 'function') {
throw new InvalidReturnValueError('expected Readable')
throw new InvalidReturnValueError('expected Readable');
}
body
.on('data', (chunk) => {
const { ret, body } = this
const { ret, body } = this;
if (!ret.push(chunk) && body.pause) {
body.pause()
body.pause();
}
})
.on('error', (err) => {
const { ret } = this
const { ret } = this;
util.destroy(ret, err)
util.destroy(ret, err);
})
.on('end', () => {
const { ret } = this
const { ret } = this;
ret.push(null)
ret.push(null);
})
.on('close', () => {
const { ret } = this
const { ret } = this;
if (!ret._readableState.ended) {
util.destroy(ret, new RequestAbortedError())
util.destroy(ret, new RequestAbortedError());
}
})
});
this.body = body
this.body = body;
}
onData (chunk) {
const { res } = this
return res.push(chunk)
onData(chunk) {
const { res } = this;
return res.push(chunk);
}
onComplete (trailers) {
const { res } = this
res.push(null)
onComplete(trailers) {
const { res } = this;
res.push(null);
}
onError (err) {
const { ret } = this
this.handler = null
util.destroy(ret, err)
onError(err) {
const { ret } = this;
this.handler = null;
util.destroy(ret, err);
}
}
function pipeline (opts, handler) {
function pipeline(opts, handler) {
try {
const pipelineHandler = new PipelineHandler(opts, handler)
this.dispatch({ ...opts, body: pipelineHandler.req }, pipelineHandler)
return pipelineHandler.ret
const pipelineHandler = new PipelineHandler(opts, handler);
this.dispatch({ ...opts, body: pipelineHandler.req }, pipelineHandler);
return pipelineHandler.ret;
} catch (err) {
return new PassThrough().destroy(err)
return new PassThrough().destroy(err);
}
}
module.exports = pipeline
module.exports = pipeline;

View File

@ -1,122 +1,143 @@
'use strict'
'use strict';
const assert = require('node:assert')
const { AsyncResource } = require('node:async_hooks')
const { Readable } = require('./readable')
const { InvalidArgumentError, RequestAbortedError } = require('../core/errors')
const util = require('../core/util')
const assert = require('node:assert');
const { AsyncResource } = require('node:async_hooks');
const { Readable } = require('./readable');
const { InvalidArgumentError, RequestAbortedError } = require('../core/errors');
const util = require('../core/util');
function noop () {}
function noop() {}
class RequestHandler extends AsyncResource {
constructor (opts, callback) {
constructor(opts, callback) {
if (!opts || typeof opts !== 'object') {
throw new InvalidArgumentError('invalid opts')
throw new InvalidArgumentError('invalid opts');
}
const { signal, method, opaque, body, onInfo, responseHeaders, highWaterMark } = opts
const {
signal,
method,
opaque,
body,
onInfo,
responseHeaders,
highWaterMark,
} = opts;
try {
if (typeof callback !== 'function') {
throw new InvalidArgumentError('invalid callback')
throw new InvalidArgumentError('invalid callback');
}
if (highWaterMark && (typeof highWaterMark !== 'number' || highWaterMark < 0)) {
throw new InvalidArgumentError('invalid highWaterMark')
if (
highWaterMark &&
(typeof highWaterMark !== 'number' || highWaterMark < 0)
) {
throw new InvalidArgumentError('invalid highWaterMark');
}
if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') {
throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget')
if (
signal &&
typeof signal.on !== 'function' &&
typeof signal.addEventListener !== 'function'
) {
throw new InvalidArgumentError(
'signal must be an EventEmitter or EventTarget'
);
}
if (method === 'CONNECT') {
throw new InvalidArgumentError('invalid method')
throw new InvalidArgumentError('invalid method');
}
if (onInfo && typeof onInfo !== 'function') {
throw new InvalidArgumentError('invalid onInfo callback')
throw new InvalidArgumentError('invalid onInfo callback');
}
super('UNDICI_REQUEST')
super('UNDICI_REQUEST');
} catch (err) {
if (util.isStream(body)) {
util.destroy(body.on('error', noop), err)
util.destroy(body.on('error', noop), err);
}
throw err
throw err;
}
this.method = method
this.responseHeaders = responseHeaders || null
this.opaque = opaque || null
this.callback = callback
this.res = null
this.abort = null
this.body = body
this.trailers = {}
this.context = null
this.onInfo = onInfo || null
this.highWaterMark = highWaterMark
this.reason = null
this.removeAbortListener = null
this.method = method;
this.responseHeaders = responseHeaders || null;
this.opaque = opaque || null;
this.callback = callback;
this.res = null;
this.abort = null;
this.body = body;
this.trailers = {};
this.context = null;
this.onInfo = onInfo || null;
this.highWaterMark = highWaterMark;
this.reason = null;
this.removeAbortListener = null;
if (signal?.aborted) {
this.reason = signal.reason ?? new RequestAbortedError()
this.reason = signal.reason ?? new RequestAbortedError();
} else if (signal) {
this.removeAbortListener = util.addAbortListener(signal, () => {
this.reason = signal.reason ?? new RequestAbortedError()
this.reason = signal.reason ?? new RequestAbortedError();
if (this.res) {
util.destroy(this.res.on('error', noop), this.reason)
util.destroy(this.res.on('error', noop), this.reason);
} else if (this.abort) {
this.abort(this.reason)
this.abort(this.reason);
}
})
});
}
}
onConnect (abort, context) {
onConnect(abort, context) {
if (this.reason) {
abort(this.reason)
return
abort(this.reason);
return;
}
assert(this.callback)
assert(this.callback);
this.abort = abort
this.context = context
this.abort = abort;
this.context = context;
}
onHeaders (statusCode, rawHeaders, resume, statusMessage) {
const { callback, opaque, abort, context, responseHeaders, highWaterMark } = this
onHeaders(statusCode, rawHeaders, resume, statusMessage) {
const { callback, opaque, abort, context, responseHeaders, highWaterMark } =
this;
const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders)
const headers =
responseHeaders === 'raw' ?
util.parseRawHeaders(rawHeaders)
: util.parseHeaders(rawHeaders);
if (statusCode < 200) {
if (this.onInfo) {
this.onInfo({ statusCode, headers })
this.onInfo({ statusCode, headers });
}
return
return;
}
const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers
const contentType = parsedHeaders['content-type']
const contentLength = parsedHeaders['content-length']
const parsedHeaders =
responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers;
const contentType = parsedHeaders['content-type'];
const contentLength = parsedHeaders['content-length'];
const res = new Readable({
resume,
abort,
contentType,
contentLength: this.method !== 'HEAD' && contentLength
? Number(contentLength)
: null,
highWaterMark
})
contentLength:
this.method !== 'HEAD' && contentLength ? Number(contentLength) : null,
highWaterMark,
});
if (this.removeAbortListener) {
res.on('close', this.removeAbortListener)
this.removeAbortListener = null
res.on('close', this.removeAbortListener);
this.removeAbortListener = null;
}
this.callback = null
this.res = res
this.callback = null;
this.res = res;
if (callback !== null) {
this.runInAsyncScope(callback, null, null, {
statusCode,
@ -124,76 +145,76 @@ class RequestHandler extends AsyncResource {
trailers: this.trailers,
opaque,
body: res,
context
})
context,
});
}
}
onData (chunk) {
return this.res.push(chunk)
onData(chunk) {
return this.res.push(chunk);
}
onComplete (trailers) {
util.parseHeaders(trailers, this.trailers)
this.res.push(null)
onComplete(trailers) {
util.parseHeaders(trailers, this.trailers);
this.res.push(null);
}
onError (err) {
const { res, callback, body, opaque } = this
onError(err) {
const { res, callback, body, opaque } = this;
if (callback) {
// TODO: Does this need queueMicrotask?
this.callback = null
this.callback = null;
queueMicrotask(() => {
this.runInAsyncScope(callback, null, err, { opaque })
})
this.runInAsyncScope(callback, null, err, { opaque });
});
}
if (res) {
this.res = null
this.res = null;
// Ensure all queued handlers are invoked before destroying res.
queueMicrotask(() => {
util.destroy(res.on('error', noop), err)
})
util.destroy(res.on('error', noop), err);
});
}
if (body) {
this.body = null
this.body = null;
if (util.isStream(body)) {
body.on('error', noop)
util.destroy(body, err)
body.on('error', noop);
util.destroy(body, err);
}
}
if (this.removeAbortListener) {
this.removeAbortListener()
this.removeAbortListener = null
this.removeAbortListener();
this.removeAbortListener = null;
}
}
}
function request (opts, callback) {
function request(opts, callback) {
if (callback === undefined) {
return new Promise((resolve, reject) => {
request.call(this, opts, (err, data) => {
return err ? reject(err) : resolve(data)
})
})
return err ? reject(err) : resolve(data);
});
});
}
try {
const handler = new RequestHandler(opts, callback)
const handler = new RequestHandler(opts, callback);
this.dispatch(opts, handler)
this.dispatch(opts, handler);
} catch (err) {
if (typeof callback !== 'function') {
throw err
throw err;
}
const opaque = opts?.opaque
queueMicrotask(() => callback(err, { opaque }))
const opaque = opts?.opaque;
queueMicrotask(() => callback(err, { opaque }));
}
}
module.exports = request
module.exports.RequestHandler = RequestHandler
module.exports = request;
module.exports.RequestHandler = RequestHandler;

View File

@ -1,107 +1,119 @@
'use strict'
'use strict';
const assert = require('node:assert')
const { finished } = require('node:stream')
const { AsyncResource } = require('node:async_hooks')
const { InvalidArgumentError, InvalidReturnValueError } = require('../core/errors')
const util = require('../core/util')
const { addSignal, removeSignal } = require('./abort-signal')
const assert = require('node:assert');
const { finished } = require('node:stream');
const { AsyncResource } = require('node:async_hooks');
const {
InvalidArgumentError,
InvalidReturnValueError,
} = require('../core/errors');
const util = require('../core/util');
const { addSignal, removeSignal } = require('./abort-signal');
function noop () {}
function noop() {}
class StreamHandler extends AsyncResource {
constructor (opts, factory, callback) {
constructor(opts, factory, callback) {
if (!opts || typeof opts !== 'object') {
throw new InvalidArgumentError('invalid opts')
throw new InvalidArgumentError('invalid opts');
}
const { signal, method, opaque, body, onInfo, responseHeaders } = opts
const { signal, method, opaque, body, onInfo, responseHeaders } = opts;
try {
if (typeof callback !== 'function') {
throw new InvalidArgumentError('invalid callback')
throw new InvalidArgumentError('invalid callback');
}
if (typeof factory !== 'function') {
throw new InvalidArgumentError('invalid factory')
throw new InvalidArgumentError('invalid factory');
}
if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') {
throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget')
if (
signal &&
typeof signal.on !== 'function' &&
typeof signal.addEventListener !== 'function'
) {
throw new InvalidArgumentError(
'signal must be an EventEmitter or EventTarget'
);
}
if (method === 'CONNECT') {
throw new InvalidArgumentError('invalid method')
throw new InvalidArgumentError('invalid method');
}
if (onInfo && typeof onInfo !== 'function') {
throw new InvalidArgumentError('invalid onInfo callback')
throw new InvalidArgumentError('invalid onInfo callback');
}
super('UNDICI_STREAM')
super('UNDICI_STREAM');
} catch (err) {
if (util.isStream(body)) {
util.destroy(body.on('error', noop), err)
util.destroy(body.on('error', noop), err);
}
throw err
throw err;
}
this.responseHeaders = responseHeaders || null
this.opaque = opaque || null
this.factory = factory
this.callback = callback
this.res = null
this.abort = null
this.context = null
this.trailers = null
this.body = body
this.onInfo = onInfo || null
this.responseHeaders = responseHeaders || null;
this.opaque = opaque || null;
this.factory = factory;
this.callback = callback;
this.res = null;
this.abort = null;
this.context = null;
this.trailers = null;
this.body = body;
this.onInfo = onInfo || null;
if (util.isStream(body)) {
body.on('error', (err) => {
this.onError(err)
})
this.onError(err);
});
}
addSignal(this, signal)
addSignal(this, signal);
}
onConnect (abort, context) {
onConnect(abort, context) {
if (this.reason) {
abort(this.reason)
return
abort(this.reason);
return;
}
assert(this.callback)
assert(this.callback);
this.abort = abort
this.context = context
this.abort = abort;
this.context = context;
}
onHeaders (statusCode, rawHeaders, resume, statusMessage) {
const { factory, opaque, context, responseHeaders } = this
onHeaders(statusCode, rawHeaders, resume, statusMessage) {
const { factory, opaque, context, responseHeaders } = this;
const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders)
const headers =
responseHeaders === 'raw' ?
util.parseRawHeaders(rawHeaders)
: util.parseHeaders(rawHeaders);
if (statusCode < 200) {
if (this.onInfo) {
this.onInfo({ statusCode, headers })
this.onInfo({ statusCode, headers });
}
return
return;
}
this.factory = null
this.factory = null;
if (factory === null) {
return
return;
}
const res = this.runInAsyncScope(factory, null, {
statusCode,
headers,
opaque,
context
})
context,
});
if (
!res ||
@ -109,101 +121,102 @@ class StreamHandler extends AsyncResource {
typeof res.end !== 'function' ||
typeof res.on !== 'function'
) {
throw new InvalidReturnValueError('expected Writable')
throw new InvalidReturnValueError('expected Writable');
}
// TODO: Avoid finished. It registers an unnecessary amount of listeners.
finished(res, { readable: false }, (err) => {
const { callback, res, opaque, trailers, abort } = this
const { callback, res, opaque, trailers, abort } = this;
this.res = null
this.res = null;
if (err || !res.readable) {
util.destroy(res, err)
util.destroy(res, err);
}
this.callback = null
this.runInAsyncScope(callback, null, err || null, { opaque, trailers })
this.callback = null;
this.runInAsyncScope(callback, null, err || null, { opaque, trailers });
if (err) {
abort()
abort();
}
})
});
res.on('drain', resume)
res.on('drain', resume);
this.res = res
this.res = res;
const needDrain = res.writableNeedDrain !== undefined
? res.writableNeedDrain
: res._writableState?.needDrain
const needDrain =
res.writableNeedDrain !== undefined ?
res.writableNeedDrain
: res._writableState?.needDrain;
return needDrain !== true
return needDrain !== true;
}
onData (chunk) {
const { res } = this
onData(chunk) {
const { res } = this;
return res ? res.write(chunk) : true
return res ? res.write(chunk) : true;
}
onComplete (trailers) {
const { res } = this
onComplete(trailers) {
const { res } = this;
removeSignal(this)
removeSignal(this);
if (!res) {
return
return;
}
this.trailers = util.parseHeaders(trailers)
this.trailers = util.parseHeaders(trailers);
res.end()
res.end();
}
onError (err) {
const { res, callback, opaque, body } = this
onError(err) {
const { res, callback, opaque, body } = this;
removeSignal(this)
removeSignal(this);
this.factory = null
this.factory = null;
if (res) {
this.res = null
util.destroy(res, err)
this.res = null;
util.destroy(res, err);
} else if (callback) {
this.callback = null
this.callback = null;
queueMicrotask(() => {
this.runInAsyncScope(callback, null, err, { opaque })
})
this.runInAsyncScope(callback, null, err, { opaque });
});
}
if (body) {
this.body = null
util.destroy(body, err)
this.body = null;
util.destroy(body, err);
}
}
}
function stream (opts, factory, callback) {
function stream(opts, factory, callback) {
if (callback === undefined) {
return new Promise((resolve, reject) => {
stream.call(this, opts, factory, (err, data) => {
return err ? reject(err) : resolve(data)
})
})
return err ? reject(err) : resolve(data);
});
});
}
try {
const handler = new StreamHandler(opts, factory, callback)
const handler = new StreamHandler(opts, factory, callback);
this.dispatch(opts, handler)
this.dispatch(opts, handler);
} catch (err) {
if (typeof callback !== 'function') {
throw err
throw err;
}
const opaque = opts?.opaque
queueMicrotask(() => callback(err, { opaque }))
const opaque = opts?.opaque;
queueMicrotask(() => callback(err, { opaque }));
}
}
module.exports = stream
module.exports = stream;

View File

@ -1,110 +1,119 @@
'use strict'
'use strict';
const { InvalidArgumentError, SocketError } = require('../core/errors')
const { AsyncResource } = require('node:async_hooks')
const assert = require('node:assert')
const util = require('../core/util')
const { addSignal, removeSignal } = require('./abort-signal')
const { InvalidArgumentError, SocketError } = require('../core/errors');
const { AsyncResource } = require('node:async_hooks');
const assert = require('node:assert');
const util = require('../core/util');
const { addSignal, removeSignal } = require('./abort-signal');
class UpgradeHandler extends AsyncResource {
constructor (opts, callback) {
constructor(opts, callback) {
if (!opts || typeof opts !== 'object') {
throw new InvalidArgumentError('invalid opts')
throw new InvalidArgumentError('invalid opts');
}
if (typeof callback !== 'function') {
throw new InvalidArgumentError('invalid callback')
throw new InvalidArgumentError('invalid callback');
}
const { signal, opaque, responseHeaders } = opts
const { signal, opaque, responseHeaders } = opts;
if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') {
throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget')
if (
signal &&
typeof signal.on !== 'function' &&
typeof signal.addEventListener !== 'function'
) {
throw new InvalidArgumentError(
'signal must be an EventEmitter or EventTarget'
);
}
super('UNDICI_UPGRADE')
super('UNDICI_UPGRADE');
this.responseHeaders = responseHeaders || null
this.opaque = opaque || null
this.callback = callback
this.abort = null
this.context = null
this.responseHeaders = responseHeaders || null;
this.opaque = opaque || null;
this.callback = callback;
this.abort = null;
this.context = null;
addSignal(this, signal)
addSignal(this, signal);
}
onConnect (abort, context) {
onConnect(abort, context) {
if (this.reason) {
abort(this.reason)
return
abort(this.reason);
return;
}
assert(this.callback)
assert(this.callback);
this.abort = abort
this.context = null
this.abort = abort;
this.context = null;
}
onHeaders () {
throw new SocketError('bad upgrade', null)
onHeaders() {
throw new SocketError('bad upgrade', null);
}
onUpgrade (statusCode, rawHeaders, socket) {
assert(statusCode === 101)
onUpgrade(statusCode, rawHeaders, socket) {
assert(statusCode === 101);
const { callback, opaque, context } = this
const { callback, opaque, context } = this;
removeSignal(this)
removeSignal(this);
this.callback = null
const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders)
this.callback = null;
const headers =
this.responseHeaders === 'raw' ?
util.parseRawHeaders(rawHeaders)
: util.parseHeaders(rawHeaders);
this.runInAsyncScope(callback, null, null, {
headers,
socket,
opaque,
context
})
context,
});
}
onError (err) {
const { callback, opaque } = this
onError(err) {
const { callback, opaque } = this;
removeSignal(this)
removeSignal(this);
if (callback) {
this.callback = null
this.callback = null;
queueMicrotask(() => {
this.runInAsyncScope(callback, null, err, { opaque })
})
this.runInAsyncScope(callback, null, err, { opaque });
});
}
}
}
function upgrade (opts, callback) {
function upgrade(opts, callback) {
if (callback === undefined) {
return new Promise((resolve, reject) => {
upgrade.call(this, opts, (err, data) => {
return err ? reject(err) : resolve(data)
})
})
return err ? reject(err) : resolve(data);
});
});
}
try {
const upgradeHandler = new UpgradeHandler(opts, callback)
const upgradeHandler = new UpgradeHandler(opts, callback);
const upgradeOpts = {
...opts,
method: opts.method || 'GET',
upgrade: opts.protocol || 'Websocket'
}
upgrade: opts.protocol || 'Websocket',
};
this.dispatch(upgradeOpts, upgradeHandler)
this.dispatch(upgradeOpts, upgradeHandler);
} catch (err) {
if (typeof callback !== 'function') {
throw err
throw err;
}
const opaque = opts?.opaque
queueMicrotask(() => callback(err, { opaque }))
const opaque = opts?.opaque;
queueMicrotask(() => callback(err, { opaque }));
}
}
module.exports = upgrade
module.exports = upgrade;

12
node_modules/undici/lib/api/index.js generated vendored
View File

@ -1,7 +1,7 @@
'use strict'
'use strict';
module.exports.request = require('./api-request')
module.exports.stream = require('./api-stream')
module.exports.pipeline = require('./api-pipeline')
module.exports.upgrade = require('./api-upgrade')
module.exports.connect = require('./api-connect')
module.exports.request = require('./api-request');
module.exports.stream = require('./api-stream');
module.exports.pipeline = require('./api-pipeline');
module.exports.upgrade = require('./api-upgrade');
module.exports.connect = require('./api-connect');

View File

@ -1,23 +1,28 @@
// Ported from https://github.com/nodejs/undici/pull/907
'use strict'
'use strict';
const assert = require('node:assert')
const { Readable } = require('node:stream')
const { RequestAbortedError, NotSupportedError, InvalidArgumentError, AbortError } = require('../core/errors')
const util = require('../core/util')
const { ReadableStreamFrom } = require('../core/util')
const assert = require('node:assert');
const { Readable } = require('node:stream');
const {
RequestAbortedError,
NotSupportedError,
InvalidArgumentError,
AbortError,
} = require('../core/errors');
const util = require('../core/util');
const { ReadableStreamFrom } = require('../core/util');
const kConsume = Symbol('kConsume')
const kReading = Symbol('kReading')
const kBody = Symbol('kBody')
const kAbort = Symbol('kAbort')
const kContentType = Symbol('kContentType')
const kContentLength = Symbol('kContentLength')
const kUsed = Symbol('kUsed')
const kBytesRead = Symbol('kBytesRead')
const kConsume = Symbol('kConsume');
const kReading = Symbol('kReading');
const kBody = Symbol('kBody');
const kAbort = Symbol('kAbort');
const kContentType = Symbol('kContentType');
const kContentLength = Symbol('kContentLength');
const kUsed = Symbol('kUsed');
const kBytesRead = Symbol('kBytesRead');
const noop = () => {}
const noop = () => {};
/**
* @class
@ -33,41 +38,42 @@ class BodyReadable extends Readable {
* @param {number} [opts.contentLength]
* @param {number} [opts.highWaterMark = 64 * 1024]
*/
constructor ({
constructor({
resume,
abort,
contentType = '',
contentLength,
highWaterMark = 64 * 1024 // Same as nodejs fs streams.
highWaterMark = 64 * 1024, // Same as nodejs fs streams.
}) {
super({
autoDestroy: true,
read: resume,
highWaterMark
})
highWaterMark,
});
this._readableState.dataEmitted = false
this._readableState.dataEmitted = false;
this[kAbort] = abort
this[kAbort] = abort;
/**
* @type {Consume | null}
*/
this[kConsume] = null
this[kBytesRead] = 0
this[kConsume] = null;
this[kBytesRead] = 0;
/**
* @type {ReadableStream|null}
*/
this[kBody] = null
this[kUsed] = false
this[kContentType] = contentType
this[kContentLength] = Number.isFinite(contentLength) ? contentLength : null
this[kBody] = null;
this[kUsed] = false;
this[kContentType] = contentType;
this[kContentLength] =
Number.isFinite(contentLength) ? contentLength : null;
// Is stream being consumed through Readable API?
// This is an optimization so that we avoid checking
// for 'data' and 'readable' listeners in the hot path
// inside push().
this[kReading] = false
this[kReading] = false;
}
/**
@ -75,13 +81,13 @@ class BodyReadable extends Readable {
* @param {(error:(Error|null)) => void} callback
* @returns {void}
*/
_destroy (err, callback) {
_destroy(err, callback) {
if (!err && !this._readableState.endEmitted) {
err = new RequestAbortedError()
err = new RequestAbortedError();
}
if (err) {
this[kAbort]()
this[kAbort]();
}
// Workaround for Node "bug". If the stream is destroyed in same
@ -90,10 +96,10 @@ class BodyReadable extends Readable {
// never get a chance and will always encounter an unhandled exception.
if (!this[kUsed]) {
setImmediate(() => {
callback(err)
})
callback(err);
});
} else {
callback(err)
callback(err);
}
}
@ -102,12 +108,12 @@ class BodyReadable extends Readable {
* @param {(...args: any[]) => void} listener
* @returns {this}
*/
on (event, listener) {
on(event, listener) {
if (event === 'data' || event === 'readable') {
this[kReading] = true
this[kUsed] = true
this[kReading] = true;
this[kUsed] = true;
}
return super.on(event, listener)
return super.on(event, listener);
}
/**
@ -115,8 +121,8 @@ class BodyReadable extends Readable {
* @param {(...args: any[]) => void} listener
* @returns {this}
*/
addListener (event, listener) {
return this.on(event, listener)
addListener(event, listener) {
return this.on(event, listener);
}
/**
@ -124,15 +130,13 @@ class BodyReadable extends Readable {
* @param {(...args: any[]) => void} listener
* @returns {this}
*/
off (event, listener) {
const ret = super.off(event, listener)
off(event, listener) {
const ret = super.off(event, listener);
if (event === 'data' || event === 'readable') {
this[kReading] = (
this.listenerCount('data') > 0 ||
this.listenerCount('readable') > 0
)
this[kReading] =
this.listenerCount('data') > 0 || this.listenerCount('readable') > 0;
}
return ret
return ret;
}
/**
@ -140,22 +144,22 @@ class BodyReadable extends Readable {
* @param {(...args: any[]) => void} listener
* @returns {this}
*/
removeListener (event, listener) {
return this.off(event, listener)
removeListener(event, listener) {
return this.off(event, listener);
}
/**
* @param {Buffer|null} chunk
* @returns {boolean}
*/
push (chunk) {
this[kBytesRead] += chunk ? chunk.length : 0
push(chunk) {
this[kBytesRead] += chunk ? chunk.length : 0;
if (this[kConsume] && chunk !== null) {
consumePush(this[kConsume], chunk)
return this[kReading] ? super.push(chunk) : true
consumePush(this[kConsume], chunk);
return this[kReading] ? super.push(chunk) : true;
}
return super.push(chunk)
return super.push(chunk);
}
/**
@ -164,8 +168,8 @@ class BodyReadable extends Readable {
* @see https://fetch.spec.whatwg.org/#dom-body-text
* @returns {Promise<string>}
*/
text () {
return consume(this, 'text')
text() {
return consume(this, 'text');
}
/**
@ -174,8 +178,8 @@ class BodyReadable extends Readable {
* @see https://fetch.spec.whatwg.org/#dom-body-json
* @returns {Promise<unknown>}
*/
json () {
return consume(this, 'json')
json() {
return consume(this, 'json');
}
/**
@ -184,8 +188,8 @@ class BodyReadable extends Readable {
* @see https://fetch.spec.whatwg.org/#dom-body-blob
* @returns {Promise<Blob>}
*/
blob () {
return consume(this, 'blob')
blob() {
return consume(this, 'blob');
}
/**
@ -194,8 +198,8 @@ class BodyReadable extends Readable {
* @see https://fetch.spec.whatwg.org/#dom-body-bytes
* @returns {Promise<Uint8Array>}
*/
bytes () {
return consume(this, 'bytes')
bytes() {
return consume(this, 'bytes');
}
/**
@ -204,8 +208,8 @@ class BodyReadable extends Readable {
* @see https://fetch.spec.whatwg.org/#dom-body-arraybuffer
* @returns {Promise<ArrayBuffer>}
*/
arrayBuffer () {
return consume(this, 'arrayBuffer')
arrayBuffer() {
return consume(this, 'arrayBuffer');
}
/**
@ -214,9 +218,9 @@ class BodyReadable extends Readable {
* @see https://fetch.spec.whatwg.org/#dom-body-formdata
* @throws {NotSupportedError}
*/
async formData () {
async formData() {
// TODO: Implement.
throw new NotSupportedError()
throw new NotSupportedError();
}
/**
@ -227,8 +231,8 @@ class BodyReadable extends Readable {
* @readonly
* @returns {boolean}
*/
get bodyUsed () {
return util.isDisturbed(this)
get bodyUsed() {
return util.isDisturbed(this);
}
/**
@ -236,16 +240,16 @@ class BodyReadable extends Readable {
* @readonly
* @returns {ReadableStream}
*/
get body () {
get body() {
if (!this[kBody]) {
this[kBody] = ReadableStreamFrom(this)
this[kBody] = ReadableStreamFrom(this);
if (this[kConsume]) {
// TODO: Is this the best way to force a lock?
this[kBody].getReader() // Ensure stream is locked.
assert(this[kBody].locked)
this[kBody].getReader(); // Ensure stream is locked.
assert(this[kBody].locked);
}
}
return this[kBody]
return this[kBody];
}
/**
@ -255,69 +259,69 @@ class BodyReadable extends Readable {
* @param {AbortSignal} [opts.signal] An AbortSignal to cancel the dump.
* @returns {Promise<null>}
*/
async dump (opts) {
const signal = opts?.signal
async dump(opts) {
const signal = opts?.signal;
if (signal != null && (typeof signal !== 'object' || !('aborted' in signal))) {
throw new InvalidArgumentError('signal must be an AbortSignal')
if (
signal != null &&
(typeof signal !== 'object' || !('aborted' in signal))
) {
throw new InvalidArgumentError('signal must be an AbortSignal');
}
const limit = opts?.limit && Number.isFinite(opts.limit)
? opts.limit
: 128 * 1024
const limit =
opts?.limit && Number.isFinite(opts.limit) ? opts.limit : 128 * 1024;
signal?.throwIfAborted()
signal?.throwIfAborted();
if (this._readableState.closeEmitted) {
return null
return null;
}
return await new Promise((resolve, reject) => {
if (
(this[kContentLength] && (this[kContentLength] > limit)) ||
(this[kContentLength] && this[kContentLength] > limit) ||
this[kBytesRead] > limit
) {
this.destroy(new AbortError())
this.destroy(new AbortError());
}
if (signal) {
const onAbort = () => {
this.destroy(signal.reason ?? new AbortError())
}
signal.addEventListener('abort', onAbort)
this
.on('close', function () {
signal.removeEventListener('abort', onAbort)
if (signal.aborted) {
reject(signal.reason ?? new AbortError())
} else {
resolve(null)
}
})
this.destroy(signal.reason ?? new AbortError());
};
signal.addEventListener('abort', onAbort);
this.on('close', function () {
signal.removeEventListener('abort', onAbort);
if (signal.aborted) {
reject(signal.reason ?? new AbortError());
} else {
resolve(null);
}
});
} else {
this.on('close', resolve)
this.on('close', resolve);
}
this
.on('error', noop)
this.on('error', noop)
.on('data', () => {
if (this[kBytesRead] > limit) {
this.destroy()
this.destroy();
}
})
.resume()
})
.resume();
});
}
/**
* @param {BufferEncoding} encoding
* @returns {this}
*/
setEncoding (encoding) {
setEncoding(encoding) {
if (Buffer.isEncoding(encoding)) {
this._readableState.encoding = encoding
this._readableState.encoding = encoding;
}
return this
return this;
}
}
@ -326,9 +330,11 @@ class BodyReadable extends Readable {
* @param {BodyReadable} bodyReadable
* @returns {boolean}
*/
function isLocked (bodyReadable) {
function isLocked(bodyReadable) {
// Consume is an implicit lock.
return bodyReadable[kBody]?.locked === true || bodyReadable[kConsume] !== null
return (
bodyReadable[kBody]?.locked === true || bodyReadable[kConsume] !== null
);
}
/**
@ -336,8 +342,8 @@ function isLocked (bodyReadable) {
* @param {BodyReadable} bodyReadable
* @returns {boolean}
*/
function isUnusable (bodyReadable) {
return util.isDisturbed(bodyReadable) || isLocked(bodyReadable)
function isUnusable(bodyReadable) {
return util.isDisturbed(bodyReadable) || isLocked(bodyReadable);
}
/**
@ -355,22 +361,22 @@ function isUnusable (bodyReadable) {
* @param {string} type
* @returns {Promise<any>}
*/
function consume (stream, type) {
assert(!stream[kConsume])
function consume(stream, type) {
assert(!stream[kConsume]);
return new Promise((resolve, reject) => {
if (isUnusable(stream)) {
const rState = stream._readableState
const rState = stream._readableState;
if (rState.destroyed && rState.closeEmitted === false) {
stream
.on('error', err => {
reject(err)
.on('error', (err) => {
reject(err);
})
.on('close', () => {
reject(new TypeError('unusable'))
})
reject(new TypeError('unusable'));
});
} else {
reject(rState.errored ?? new TypeError('unusable'))
reject(rState.errored ?? new TypeError('unusable'));
}
} else {
queueMicrotask(() => {
@ -380,57 +386,57 @@ function consume (stream, type) {
resolve,
reject,
length: 0,
body: []
}
body: [],
};
stream
.on('error', function (err) {
consumeFinish(this[kConsume], err)
consumeFinish(this[kConsume], err);
})
.on('close', function () {
if (this[kConsume].body !== null) {
consumeFinish(this[kConsume], new RequestAbortedError())
consumeFinish(this[kConsume], new RequestAbortedError());
}
})
});
consumeStart(stream[kConsume])
})
consumeStart(stream[kConsume]);
});
}
})
});
}
/**
* @param {Consume} consume
* @returns {void}
*/
function consumeStart (consume) {
function consumeStart(consume) {
if (consume.body === null) {
return
return;
}
const { _readableState: state } = consume.stream
const { _readableState: state } = consume.stream;
if (state.bufferIndex) {
const start = state.bufferIndex
const end = state.buffer.length
const start = state.bufferIndex;
const end = state.buffer.length;
for (let n = start; n < end; n++) {
consumePush(consume, state.buffer[n])
consumePush(consume, state.buffer[n]);
}
} else {
for (const chunk of state.buffer) {
consumePush(consume, chunk)
consumePush(consume, chunk);
}
}
if (state.endEmitted) {
consumeEnd(this[kConsume], this._readableState.encoding)
consumeEnd(this[kConsume], this._readableState.encoding);
} else {
consume.stream.on('end', function () {
consumeEnd(this[kConsume], this._readableState.encoding)
})
consumeEnd(this[kConsume], this._readableState.encoding);
});
}
consume.stream.resume()
consume.stream.resume();
while (consume.stream.read() != null) {
// Loop
@ -443,25 +449,28 @@ function consumeStart (consume) {
* @param {BufferEncoding} encoding
* @returns {string}
*/
function chunksDecode (chunks, length, encoding) {
function chunksDecode(chunks, length, encoding) {
if (chunks.length === 0 || length === 0) {
return ''
return '';
}
const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks, length)
const bufferLength = buffer.length
const buffer =
chunks.length === 1 ? chunks[0] : Buffer.concat(chunks, length);
const bufferLength = buffer.length;
// Skip BOM.
const start =
bufferLength > 2 &&
buffer[0] === 0xef &&
buffer[1] === 0xbb &&
buffer[2] === 0xbf
? 3
: 0
(
bufferLength > 2 &&
buffer[0] === 0xef &&
buffer[1] === 0xbb &&
buffer[2] === 0xbf
) ?
3
: 0;
if (!encoding || encoding === 'utf8' || encoding === 'utf-8') {
return buffer.utf8Slice(start, bufferLength)
return buffer.utf8Slice(start, bufferLength);
} else {
return buffer.subarray(start, bufferLength).toString(encoding)
return buffer.subarray(start, bufferLength).toString(encoding);
}
}
@ -470,24 +479,24 @@ function chunksDecode (chunks, length, encoding) {
* @param {number} length
* @returns {Uint8Array}
*/
function chunksConcat (chunks, length) {
function chunksConcat(chunks, length) {
if (chunks.length === 0 || length === 0) {
return new Uint8Array(0)
return new Uint8Array(0);
}
if (chunks.length === 1) {
// fast-path
return new Uint8Array(chunks[0])
return new Uint8Array(chunks[0]);
}
const buffer = new Uint8Array(Buffer.allocUnsafeSlow(length).buffer)
const buffer = new Uint8Array(Buffer.allocUnsafeSlow(length).buffer);
let offset = 0
let offset = 0;
for (let i = 0; i < chunks.length; ++i) {
const chunk = chunks[i]
buffer.set(chunk, offset)
offset += chunk.length
const chunk = chunks[i];
buffer.set(chunk, offset);
offset += chunk.length;
}
return buffer
return buffer;
}
/**
@ -495,25 +504,25 @@ function chunksConcat (chunks, length) {
* @param {BufferEncoding} encoding
* @returns {void}
*/
function consumeEnd (consume, encoding) {
const { type, body, resolve, stream, length } = consume
function consumeEnd(consume, encoding) {
const { type, body, resolve, stream, length } = consume;
try {
if (type === 'text') {
resolve(chunksDecode(body, length, encoding))
resolve(chunksDecode(body, length, encoding));
} else if (type === 'json') {
resolve(JSON.parse(chunksDecode(body, length, encoding)))
resolve(JSON.parse(chunksDecode(body, length, encoding)));
} else if (type === 'arrayBuffer') {
resolve(chunksConcat(body, length).buffer)
resolve(chunksConcat(body, length).buffer);
} else if (type === 'blob') {
resolve(new Blob(body, { type: stream[kContentType] }))
resolve(new Blob(body, { type: stream[kContentType] }));
} else if (type === 'bytes') {
resolve(chunksConcat(body, length))
resolve(chunksConcat(body, length));
}
consumeFinish(consume)
consumeFinish(consume);
} catch (err) {
stream.destroy(err)
stream.destroy(err);
}
}
@ -522,9 +531,9 @@ function consumeEnd (consume, encoding) {
* @param {Buffer} chunk
* @returns {void}
*/
function consumePush (consume, chunk) {
consume.length += chunk.length
consume.body.push(chunk)
function consumePush(consume, chunk) {
consume.length += chunk.length;
consume.body.push(chunk);
}
/**
@ -532,27 +541,27 @@ function consumePush (consume, chunk) {
* @param {Error} [err]
* @returns {void}
*/
function consumeFinish (consume, err) {
function consumeFinish(consume, err) {
if (consume.body === null) {
return
return;
}
if (err) {
consume.reject(err)
consume.reject(err);
} else {
consume.resolve()
consume.resolve();
}
// Reset the consume object to allow for garbage collection.
consume.type = null
consume.stream = null
consume.resolve = null
consume.reject = null
consume.length = 0
consume.body = null
consume.type = null;
consume.stream = null;
consume.resolve = null;
consume.reject = null;
consume.length = 0;
consume.body = null;
}
module.exports = {
Readable: BodyReadable,
chunksDecode
}
chunksDecode,
};

77
node_modules/undici/lib/api/util.js generated vendored
View File

@ -1,58 +1,67 @@
'use strict'
'use strict';
const assert = require('node:assert')
const {
ResponseStatusCodeError
} = require('../core/errors')
const assert = require('node:assert');
const { ResponseStatusCodeError } = require('../core/errors');
const { chunksDecode } = require('./readable')
const CHUNK_LIMIT = 128 * 1024
const { chunksDecode } = require('./readable');
const CHUNK_LIMIT = 128 * 1024;
async function getResolveErrorBodyCallback ({ callback, body, contentType, statusCode, statusMessage, headers }) {
assert(body)
async function getResolveErrorBodyCallback({
callback,
body,
contentType,
statusCode,
statusMessage,
headers,
}) {
assert(body);
let chunks = []
let length = 0
let chunks = [];
let length = 0;
try {
for await (const chunk of body) {
chunks.push(chunk)
length += chunk.length
chunks.push(chunk);
length += chunk.length;
if (length > CHUNK_LIMIT) {
chunks = []
length = 0
break
chunks = [];
length = 0;
break;
}
}
} catch {
chunks = []
length = 0
chunks = [];
length = 0;
// Do nothing....
}
const message = `Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`
const message = `Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`;
if (statusCode === 204 || !contentType || !length) {
queueMicrotask(() => callback(new ResponseStatusCodeError(message, statusCode, headers)))
return
queueMicrotask(() =>
callback(new ResponseStatusCodeError(message, statusCode, headers))
);
return;
}
const stackTraceLimit = Error.stackTraceLimit
Error.stackTraceLimit = 0
let payload
const stackTraceLimit = Error.stackTraceLimit;
Error.stackTraceLimit = 0;
let payload;
try {
if (isContentTypeApplicationJson(contentType)) {
payload = JSON.parse(chunksDecode(chunks, length))
payload = JSON.parse(chunksDecode(chunks, length));
} else if (isContentTypeText(contentType)) {
payload = chunksDecode(chunks, length)
payload = chunksDecode(chunks, length);
}
} catch {
// process in a callback to avoid throwing in the microtask queue
} finally {
Error.stackTraceLimit = stackTraceLimit
Error.stackTraceLimit = stackTraceLimit;
}
queueMicrotask(() => callback(new ResponseStatusCodeError(message, statusCode, headers, payload)))
queueMicrotask(() =>
callback(new ResponseStatusCodeError(message, statusCode, headers, payload))
);
}
const isContentTypeApplicationJson = (contentType) => {
@ -74,8 +83,8 @@ const isContentTypeApplicationJson = (contentType) => {
contentType[13] === 's' &&
contentType[14] === 'o' &&
contentType[15] === 'n'
)
}
);
};
const isContentTypeText = (contentType) => {
return (
@ -85,11 +94,11 @@ const isContentTypeText = (contentType) => {
contentType[1] === 'e' &&
contentType[2] === 'x' &&
contentType[3] === 't'
)
}
);
};
module.exports = {
getResolveErrorBodyCallback,
isContentTypeApplicationJson,
isContentTypeText
}
isContentTypeText,
};