summaryrefslogtreecommitdiffstats
path: root/g4f/Provider/npm/node_modules/undici/lib/fetch
diff options
context:
space:
mode:
Diffstat (limited to 'g4f/Provider/npm/node_modules/undici/lib/fetch')
-rw-r--r--g4f/Provider/npm/node_modules/undici/lib/fetch/LICENSE21
-rw-r--r--g4f/Provider/npm/node_modules/undici/lib/fetch/body.js605
-rw-r--r--g4f/Provider/npm/node_modules/undici/lib/fetch/constants.js151
-rw-r--r--g4f/Provider/npm/node_modules/undici/lib/fetch/dataURL.js630
-rw-r--r--g4f/Provider/npm/node_modules/undici/lib/fetch/file.js344
-rw-r--r--g4f/Provider/npm/node_modules/undici/lib/fetch/formdata.js265
-rw-r--r--g4f/Provider/npm/node_modules/undici/lib/fetch/global.js40
-rw-r--r--g4f/Provider/npm/node_modules/undici/lib/fetch/headers.js552
-rw-r--r--g4f/Provider/npm/node_modules/undici/lib/fetch/index.js2145
-rw-r--r--g4f/Provider/npm/node_modules/undici/lib/fetch/request.js944
-rw-r--r--g4f/Provider/npm/node_modules/undici/lib/fetch/response.js575
-rw-r--r--g4f/Provider/npm/node_modules/undici/lib/fetch/symbols.js10
-rw-r--r--g4f/Provider/npm/node_modules/undici/lib/fetch/util.js1046
-rw-r--r--g4f/Provider/npm/node_modules/undici/lib/fetch/webidl.js648
14 files changed, 0 insertions, 7976 deletions
diff --git a/g4f/Provider/npm/node_modules/undici/lib/fetch/LICENSE b/g4f/Provider/npm/node_modules/undici/lib/fetch/LICENSE
deleted file mode 100644
index 29435004..00000000
--- a/g4f/Provider/npm/node_modules/undici/lib/fetch/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2020 Ethan Arrowood
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/g4f/Provider/npm/node_modules/undici/lib/fetch/body.js b/g4f/Provider/npm/node_modules/undici/lib/fetch/body.js
deleted file mode 100644
index fd8481b7..00000000
--- a/g4f/Provider/npm/node_modules/undici/lib/fetch/body.js
+++ /dev/null
@@ -1,605 +0,0 @@
-'use strict'
-
-const Busboy = require('@fastify/busboy')
-const util = require('../core/util')
-const {
- ReadableStreamFrom,
- isBlobLike,
- isReadableStreamLike,
- readableStreamClose,
- createDeferredPromise,
- fullyReadBody
-} = require('./util')
-const { FormData } = require('./formdata')
-const { kState } = require('./symbols')
-const { webidl } = require('./webidl')
-const { DOMException, structuredClone } = require('./constants')
-const { Blob, File: NativeFile } = require('buffer')
-const { kBodyUsed } = require('../core/symbols')
-const assert = require('assert')
-const { isErrored } = require('../core/util')
-const { isUint8Array, isArrayBuffer } = require('util/types')
-const { File: UndiciFile } = require('./file')
-const { parseMIMEType, serializeAMimeType } = require('./dataURL')
-
-let ReadableStream = globalThis.ReadableStream
-
-/** @type {globalThis['File']} */
-const File = NativeFile ?? UndiciFile
-const textEncoder = new TextEncoder()
-const textDecoder = new TextDecoder()
-
-// https://fetch.spec.whatwg.org/#concept-bodyinit-extract
-function extractBody (object, keepalive = false) {
- if (!ReadableStream) {
- ReadableStream = require('stream/web').ReadableStream
- }
-
- // 1. Let stream be null.
- let stream = null
-
- // 2. If object is a ReadableStream object, then set stream to object.
- if (object instanceof ReadableStream) {
- stream = object
- } else if (isBlobLike(object)) {
- // 3. Otherwise, if object is a Blob object, set stream to the
- // result of running object’s get stream.
- stream = object.stream()
- } else {
- // 4. Otherwise, set stream to a new ReadableStream object, and set
- // up stream.
- stream = new ReadableStream({
- async pull (controller) {
- controller.enqueue(
- typeof source === 'string' ? textEncoder.encode(source) : source
- )
- queueMicrotask(() => readableStreamClose(controller))
- },
- start () {},
- type: undefined
- })
- }
-
- // 5. Assert: stream is a ReadableStream object.
- assert(isReadableStreamLike(stream))
-
- // 6. Let action be null.
- let action = null
-
- // 7. Let source be null.
- let source = null
-
- // 8. Let length be null.
- let length = null
-
- // 9. Let type be null.
- let type = null
-
- // 10. Switch on object:
- if (typeof object === 'string') {
- // Set source to the UTF-8 encoding of object.
- // Note: setting source to a Uint8Array here breaks some mocking assumptions.
- source = object
-
- // Set type to `text/plain;charset=UTF-8`.
- type = 'text/plain;charset=UTF-8'
- } else if (object instanceof URLSearchParams) {
- // URLSearchParams
-
- // spec says to run application/x-www-form-urlencoded on body.list
- // this is implemented in Node.js as apart of an URLSearchParams instance toString method
- // See: https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/lib/internal/url.js#L490
- // and https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/lib/internal/url.js#L1100
-
- // Set source to the result of running the application/x-www-form-urlencoded serializer with object’s list.
- source = object.toString()
-
- // Set type to `application/x-www-form-urlencoded;charset=UTF-8`.
- type = 'application/x-www-form-urlencoded;charset=UTF-8'
- } else if (isArrayBuffer(object)) {
- // BufferSource/ArrayBuffer
-
- // Set source to a copy of the bytes held by object.
- source = new Uint8Array(object.slice())
- } else if (ArrayBuffer.isView(object)) {
- // BufferSource/ArrayBufferView
-
- // Set source to a copy of the bytes held by object.
- source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength))
- } else if (util.isFormDataLike(object)) {
- const boundary = `----formdata-undici-0${`${Math.floor(Math.random() * 1e11)}`.padStart(11, '0')}`
- const prefix = `--${boundary}\r\nContent-Disposition: form-data`
-
- /*! formdata-polyfill. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> */
- const escape = (str) =>
- str.replace(/\n/g, '%0A').replace(/\r/g, '%0D').replace(/"/g, '%22')
- const normalizeLinefeeds = (value) => value.replace(/\r?\n|\r/g, '\r\n')
-
- // Set action to this step: run the multipart/form-data
- // encoding algorithm, with object’s entry list and UTF-8.
- // - This ensures that the body is immutable and can't be changed afterwords
- // - That the content-length is calculated in advance.
- // - And that all parts are pre-encoded and ready to be sent.
-
- const blobParts = []
- const rn = new Uint8Array([13, 10]) // '\r\n'
- length = 0
- let hasUnknownSizeValue = false
-
- for (const [name, value] of object) {
- if (typeof value === 'string') {
- const chunk = textEncoder.encode(prefix +
- `; name="${escape(normalizeLinefeeds(name))}"` +
- `\r\n\r\n${normalizeLinefeeds(value)}\r\n`)
- blobParts.push(chunk)
- length += chunk.byteLength
- } else {
- const chunk = textEncoder.encode(`${prefix}; name="${escape(normalizeLinefeeds(name))}"` +
- (value.name ? `; filename="${escape(value.name)}"` : '') + '\r\n' +
- `Content-Type: ${
- value.type || 'application/octet-stream'
- }\r\n\r\n`)
- blobParts.push(chunk, value, rn)
- if (typeof value.size === 'number') {
- length += chunk.byteLength + value.size + rn.byteLength
- } else {
- hasUnknownSizeValue = true
- }
- }
- }
-
- const chunk = textEncoder.encode(`--${boundary}--`)
- blobParts.push(chunk)
- length += chunk.byteLength
- if (hasUnknownSizeValue) {
- length = null
- }
-
- // Set source to object.
- source = object
-
- action = async function * () {
- for (const part of blobParts) {
- if (part.stream) {
- yield * part.stream()
- } else {
- yield part
- }
- }
- }
-
- // Set type to `multipart/form-data; boundary=`,
- // followed by the multipart/form-data boundary string generated
- // by the multipart/form-data encoding algorithm.
- type = 'multipart/form-data; boundary=' + boundary
- } else if (isBlobLike(object)) {
- // Blob
-
- // Set source to object.
- source = object
-
- // Set length to object’s size.
- length = object.size
-
- // If object’s type attribute is not the empty byte sequence, set
- // type to its value.
- if (object.type) {
- type = object.type
- }
- } else if (typeof object[Symbol.asyncIterator] === 'function') {
- // If keepalive is true, then throw a TypeError.
- if (keepalive) {
- throw new TypeError('keepalive')
- }
-
- // If object is disturbed or locked, then throw a TypeError.
- if (util.isDisturbed(object) || object.locked) {
- throw new TypeError(
- 'Response body object should not be disturbed or locked'
- )
- }
-
- stream =
- object instanceof ReadableStream ? object : ReadableStreamFrom(object)
- }
-
- // 11. If source is a byte sequence, then set action to a
- // step that returns source and length to source’s length.
- if (typeof source === 'string' || util.isBuffer(source)) {
- length = Buffer.byteLength(source)
- }
-
- // 12. If action is non-null, then run these steps in in parallel:
- if (action != null) {
- // Run action.
- let iterator
- stream = new ReadableStream({
- async start () {
- iterator = action(object)[Symbol.asyncIterator]()
- },
- async pull (controller) {
- const { value, done } = await iterator.next()
- if (done) {
- // When running action is done, close stream.
- queueMicrotask(() => {
- controller.close()
- })
- } else {
- // Whenever one or more bytes are available and stream is not errored,
- // enqueue a Uint8Array wrapping an ArrayBuffer containing the available
- // bytes into stream.
- if (!isErrored(stream)) {
- controller.enqueue(new Uint8Array(value))
- }
- }
- return controller.desiredSize > 0
- },
- async cancel (reason) {
- await iterator.return()
- },
- type: undefined
- })
- }
-
- // 13. Let body be a body whose stream is stream, source is source,
- // and length is length.
- const body = { stream, source, length }
-
- // 14. Return (body, type).
- return [body, type]
-}
-
-// https://fetch.spec.whatwg.org/#bodyinit-safely-extract
-function safelyExtractBody (object, keepalive = false) {
- if (!ReadableStream) {
- // istanbul ignore next
- ReadableStream = require('stream/web').ReadableStream
- }
-
- // To safely extract a body and a `Content-Type` value from
- // a byte sequence or BodyInit object object, run these steps:
-
- // 1. If object is a ReadableStream object, then:
- if (object instanceof ReadableStream) {
- // Assert: object is neither disturbed nor locked.
- // istanbul ignore next
- assert(!util.isDisturbed(object), 'The body has already been consumed.')
- // istanbul ignore next
- assert(!object.locked, 'The stream is locked.')
- }
-
- // 2. Return the results of extracting object.
- return extractBody(object, keepalive)
-}
-
-function cloneBody (body) {
- // To clone a body body, run these steps:
-
- // https://fetch.spec.whatwg.org/#concept-body-clone
-
- // 1. Let « out1, out2 » be the result of teeing body’s stream.
- const [out1, out2] = body.stream.tee()
- const out2Clone = structuredClone(out2, { transfer: [out2] })
- // This, for whatever reasons, unrefs out2Clone which allows
- // the process to exit by itself.
- const [, finalClone] = out2Clone.tee()
-
- // 2. Set body’s stream to out1.
- body.stream = out1
-
- // 3. Return a body whose stream is out2 and other members are copied from body.
- return {
- stream: finalClone,
- length: body.length,
- source: body.source
- }
-}
-
-async function * consumeBody (body) {
- if (body) {
- if (isUint8Array(body)) {
- yield body
- } else {
- const stream = body.stream
-
- if (util.isDisturbed(stream)) {
- throw new TypeError('The body has already been consumed.')
- }
-
- if (stream.locked) {
- throw new TypeError('The stream is locked.')
- }
-
- // Compat.
- stream[kBodyUsed] = true
-
- yield * stream
- }
- }
-}
-
-function throwIfAborted (state) {
- if (state.aborted) {
- throw new DOMException('The operation was aborted.', 'AbortError')
- }
-}
-
-function bodyMixinMethods (instance) {
- const methods = {
- blob () {
- // The blob() method steps are to return the result of
- // running consume body with this and the following step
- // given a byte sequence bytes: return a Blob whose
- // contents are bytes and whose type attribute is this’s
- // MIME type.
- return specConsumeBody(this, (bytes) => {
- let mimeType = bodyMimeType(this)
-
- if (mimeType === 'failure') {
- mimeType = ''
- } else if (mimeType) {
- mimeType = serializeAMimeType(mimeType)
- }
-
- // Return a Blob whose contents are bytes and type attribute
- // is mimeType.
- return new Blob([bytes], { type: mimeType })
- }, instance)
- },
-
- arrayBuffer () {
- // The arrayBuffer() method steps are to return the result
- // of running consume body with this and the following step
- // given a byte sequence bytes: return a new ArrayBuffer
- // whose contents are bytes.
- return specConsumeBody(this, (bytes) => {
- return new Uint8Array(bytes).buffer
- }, instance)
- },
-
- text () {
- // The text() method steps are to return the result of running
- // consume body with this and UTF-8 decode.
- return specConsumeBody(this, utf8DecodeBytes, instance)
- },
-
- json () {
- // The json() method steps are to return the result of running
- // consume body with this and parse JSON from bytes.
- return specConsumeBody(this, parseJSONFromBytes, instance)
- },
-
- async formData () {
- webidl.brandCheck(this, instance)
-
- throwIfAborted(this[kState])
-
- const contentType = this.headers.get('Content-Type')
-
- // If mimeType’s essence is "multipart/form-data", then:
- if (/multipart\/form-data/.test(contentType)) {
- const headers = {}
- for (const [key, value] of this.headers) headers[key.toLowerCase()] = value
-
- const responseFormData = new FormData()
-
- let busboy
-
- try {
- busboy = new Busboy({
- headers,
- preservePath: true
- })
- } catch (err) {
- throw new DOMException(`${err}`, 'AbortError')
- }
-
- busboy.on('field', (name, value) => {
- responseFormData.append(name, value)
- })
- busboy.on('file', (name, value, filename, encoding, mimeType) => {
- const chunks = []
-
- if (encoding === 'base64' || encoding.toLowerCase() === 'base64') {
- let base64chunk = ''
-
- value.on('data', (chunk) => {
- base64chunk += chunk.toString().replace(/[\r\n]/gm, '')
-
- const end = base64chunk.length - base64chunk.length % 4
- chunks.push(Buffer.from(base64chunk.slice(0, end), 'base64'))
-
- base64chunk = base64chunk.slice(end)
- })
- value.on('end', () => {
- chunks.push(Buffer.from(base64chunk, 'base64'))
- responseFormData.append(name, new File(chunks, filename, { type: mimeType }))
- })
- } else {
- value.on('data', (chunk) => {
- chunks.push(chunk)
- })
- value.on('end', () => {
- responseFormData.append(name, new File(chunks, filename, { type: mimeType }))
- })
- }
- })
-
- const busboyResolve = new Promise((resolve, reject) => {
- busboy.on('finish', resolve)
- busboy.on('error', (err) => reject(new TypeError(err)))
- })
-
- if (this.body !== null) for await (const chunk of consumeBody(this[kState].body)) busboy.write(chunk)
- busboy.end()
- await busboyResolve
-
- return responseFormData
- } else if (/application\/x-www-form-urlencoded/.test(contentType)) {
- // Otherwise, if mimeType’s essence is "application/x-www-form-urlencoded", then:
-
- // 1. Let entries be the result of parsing bytes.
- let entries
- try {
- let text = ''
- // application/x-www-form-urlencoded parser will keep the BOM.
- // https://url.spec.whatwg.org/#concept-urlencoded-parser
- // Note that streaming decoder is stateful and cannot be reused
- const streamingDecoder = new TextDecoder('utf-8', { ignoreBOM: true })
-
- for await (const chunk of consumeBody(this[kState].body)) {
- if (!isUint8Array(chunk)) {
- throw new TypeError('Expected Uint8Array chunk')
- }
- text += streamingDecoder.decode(chunk, { stream: true })
- }
- text += streamingDecoder.decode()
- entries = new URLSearchParams(text)
- } catch (err) {
- // istanbul ignore next: Unclear when new URLSearchParams can fail on a string.
- // 2. If entries is failure, then throw a TypeError.
- throw Object.assign(new TypeError(), { cause: err })
- }
-
- // 3. Return a new FormData object whose entries are entries.
- const formData = new FormData()
- for (const [name, value] of entries) {
- formData.append(name, value)
- }
- return formData
- } else {
- // Wait a tick before checking if the request has been aborted.
- // Otherwise, a TypeError can be thrown when an AbortError should.
- await Promise.resolve()
-
- throwIfAborted(this[kState])
-
- // Otherwise, throw a TypeError.
- throw webidl.errors.exception({
- header: `${instance.name}.formData`,
- message: 'Could not parse content as FormData.'
- })
- }
- }
- }
-
- return methods
-}
-
-function mixinBody (prototype) {
- Object.assign(prototype.prototype, bodyMixinMethods(prototype))
-}
-
-/**
- * @see https://fetch.spec.whatwg.org/#concept-body-consume-body
- * @param {Response|Request} object
- * @param {(value: unknown) => unknown} convertBytesToJSValue
- * @param {Response|Request} instance
- */
-async function specConsumeBody (object, convertBytesToJSValue, instance) {
- webidl.brandCheck(object, instance)
-
- throwIfAborted(object[kState])
-
- // 1. If object is unusable, then return a promise rejected
- // with a TypeError.
- if (bodyUnusable(object[kState].body)) {
- throw new TypeError('Body is unusable')
- }
-
- // 2. Let promise be a new promise.
- const promise = createDeferredPromise()
-
- // 3. Let errorSteps given error be to reject promise with error.
- const errorSteps = (error) => promise.reject(error)
-
- // 4. Let successSteps given a byte sequence data be to resolve
- // promise with the result of running convertBytesToJSValue
- // with data. If that threw an exception, then run errorSteps
- // with that exception.
- const successSteps = (data) => {
- try {
- promise.resolve(convertBytesToJSValue(data))
- } catch (e) {
- errorSteps(e)
- }
- }
-
- // 5. If object’s body is null, then run successSteps with an
- // empty byte sequence.
- if (object[kState].body == null) {
- successSteps(new Uint8Array())
- return promise.promise
- }
-
- // 6. Otherwise, fully read object’s body given successSteps,
- // errorSteps, and object’s relevant global object.
- await fullyReadBody(object[kState].body, successSteps, errorSteps)
-
- // 7. Return promise.
- return promise.promise
-}
-
-// https://fetch.spec.whatwg.org/#body-unusable
-function bodyUnusable (body) {
- // An object including the Body interface mixin is
- // said to be unusable if its body is non-null and
- // its body’s stream is disturbed or locked.
- return body != null && (body.stream.locked || util.isDisturbed(body.stream))
-}
-
-/**
- * @see https://encoding.spec.whatwg.org/#utf-8-decode
- * @param {Buffer} buffer
- */
-function utf8DecodeBytes (buffer) {
- if (buffer.length === 0) {
- return ''
- }
-
- // 1. Let buffer be the result of peeking three bytes from
- // ioQueue, converted to a byte sequence.
-
- // 2. If buffer is 0xEF 0xBB 0xBF, then read three
- // bytes from ioQueue. (Do nothing with those bytes.)
- if (buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) {
- buffer = buffer.subarray(3)
- }
-
- // 3. Process a queue with an instance of UTF-8’s
- // decoder, ioQueue, output, and "replacement".
- const output = textDecoder.decode(buffer)
-
- // 4. Return output.
- return output
-}
-
-/**
- * @see https://infra.spec.whatwg.org/#parse-json-bytes-to-a-javascript-value
- * @param {Uint8Array} bytes
- */
-function parseJSONFromBytes (bytes) {
- return JSON.parse(utf8DecodeBytes(bytes))
-}
-
-/**
- * @see https://fetch.spec.whatwg.org/#concept-body-mime-type
- * @param {import('./response').Response|import('./request').Request} object
- */
-function bodyMimeType (object) {
- const { headersList } = object[kState]
- const contentType = headersList.get('content-type')
-
- if (contentType === null) {
- return 'failure'
- }
-
- return parseMIMEType(contentType)
-}
-
-module.exports = {
- extractBody,
- safelyExtractBody,
- cloneBody,
- mixinBody
-}
diff --git a/g4f/Provider/npm/node_modules/undici/lib/fetch/constants.js b/g4f/Provider/npm/node_modules/undici/lib/fetch/constants.js
deleted file mode 100644
index 218fcbee..00000000
--- a/g4f/Provider/npm/node_modules/undici/lib/fetch/constants.js
+++ /dev/null
@@ -1,151 +0,0 @@
-'use strict'
-
-const { MessageChannel, receiveMessageOnPort } = require('worker_threads')
-
-const corsSafeListedMethods = ['GET', 'HEAD', 'POST']
-const corsSafeListedMethodsSet = new Set(corsSafeListedMethods)
-
-const nullBodyStatus = [101, 204, 205, 304]
-
-const redirectStatus = [301, 302, 303, 307, 308]
-const redirectStatusSet = new Set(redirectStatus)
-
-// https://fetch.spec.whatwg.org/#block-bad-port
-const badPorts = [
- '1', '7', '9', '11', '13', '15', '17', '19', '20', '21', '22', '23', '25', '37', '42', '43', '53', '69', '77', '79',
- '87', '95', '101', '102', '103', '104', '109', '110', '111', '113', '115', '117', '119', '123', '135', '137',
- '139', '143', '161', '179', '389', '427', '465', '512', '513', '514', '515', '526', '530', '531', '532',
- '540', '548', '554', '556', '563', '587', '601', '636', '989', '990', '993', '995', '1719', '1720', '1723',
- '2049', '3659', '4045', '5060', '5061', '6000', '6566', '6665', '6666', '6667', '6668', '6669', '6697',
- '10080'
-]
-
-const badPortsSet = new Set(badPorts)
-
-// https://w3c.github.io/webappsec-referrer-policy/#referrer-policies
-const referrerPolicy = [
- '',
- 'no-referrer',
- 'no-referrer-when-downgrade',
- 'same-origin',
- 'origin',
- 'strict-origin',
- 'origin-when-cross-origin',
- 'strict-origin-when-cross-origin',
- 'unsafe-url'
-]
-const referrerPolicySet = new Set(referrerPolicy)
-
-const requestRedirect = ['follow', 'manual', 'error']
-
-const safeMethods = ['GET', 'HEAD', 'OPTIONS', 'TRACE']
-const safeMethodsSet = new Set(safeMethods)
-
-const requestMode = ['navigate', 'same-origin', 'no-cors', 'cors']
-
-const requestCredentials = ['omit', 'same-origin', 'include']
-
-const requestCache = [
- 'default',
- 'no-store',
- 'reload',
- 'no-cache',
- 'force-cache',
- 'only-if-cached'
-]
-
-// https://fetch.spec.whatwg.org/#request-body-header-name
-const requestBodyHeader = [
- 'content-encoding',
- 'content-language',
- 'content-location',
- 'content-type',
- // See https://github.com/nodejs/undici/issues/2021
- // 'Content-Length' is a forbidden header name, which is typically
- // removed in the Headers implementation. However, undici doesn't
- // filter out headers, so we add it here.
- 'content-length'
-]
-
-// https://fetch.spec.whatwg.org/#enumdef-requestduplex
-const requestDuplex = [
- 'half'
-]
-
-// http://fetch.spec.whatwg.org/#forbidden-method
-const forbiddenMethods = ['CONNECT', 'TRACE', 'TRACK']
-const forbiddenMethodsSet = new Set(forbiddenMethods)
-
-const subresource = [
- 'audio',
- 'audioworklet',
- 'font',
- 'image',
- 'manifest',
- 'paintworklet',
- 'script',
- 'style',
- 'track',
- 'video',
- 'xslt',
- ''
-]
-const subresourceSet = new Set(subresource)
-
-/** @type {globalThis['DOMException']} */
-const DOMException = globalThis.DOMException ?? (() => {
- // DOMException was only made a global in Node v17.0.0,
- // but fetch supports >= v16.8.
- try {
- atob('~')
- } catch (err) {
- return Object.getPrototypeOf(err).constructor
- }
-})()
-
-let channel
-
-/** @type {globalThis['structuredClone']} */
-const structuredClone =
- globalThis.structuredClone ??
- // https://github.com/nodejs/node/blob/b27ae24dcc4251bad726d9d84baf678d1f707fed/lib/internal/structured_clone.js
- // structuredClone was added in v17.0.0, but fetch supports v16.8
- function structuredClone (value, options = undefined) {
- if (arguments.length === 0) {
- throw new TypeError('missing argument')
- }
-
- if (!channel) {
- channel = new MessageChannel()
- }
- channel.port1.unref()
- channel.port2.unref()
- channel.port1.postMessage(value, options?.transfer)
- return receiveMessageOnPort(channel.port2).message
- }
-
-module.exports = {
- DOMException,
- structuredClone,
- subresource,
- forbiddenMethods,
- requestBodyHeader,
- referrerPolicy,
- requestRedirect,
- requestMode,
- requestCredentials,
- requestCache,
- redirectStatus,
- corsSafeListedMethods,
- nullBodyStatus,
- safeMethods,
- badPorts,
- requestDuplex,
- subresourceSet,
- badPortsSet,
- redirectStatusSet,
- corsSafeListedMethodsSet,
- safeMethodsSet,
- forbiddenMethodsSet,
- referrerPolicySet
-}
diff --git a/g4f/Provider/npm/node_modules/undici/lib/fetch/dataURL.js b/g4f/Provider/npm/node_modules/undici/lib/fetch/dataURL.js
deleted file mode 100644
index 6df4fcc8..00000000
--- a/g4f/Provider/npm/node_modules/undici/lib/fetch/dataURL.js
+++ /dev/null
@@ -1,630 +0,0 @@
-const assert = require('assert')
-const { atob } = require('buffer')
-const { isomorphicDecode } = require('./util')
-
-const encoder = new TextEncoder()
-
-/**
- * @see https://mimesniff.spec.whatwg.org/#http-token-code-point
- */
-const HTTP_TOKEN_CODEPOINTS = /^[!#$%&'*+-.^_|~A-Za-z0-9]+$/
-const HTTP_WHITESPACE_REGEX = /(\u000A|\u000D|\u0009|\u0020)/ // eslint-disable-line
-/**
- * @see https://mimesniff.spec.whatwg.org/#http-quoted-string-token-code-point
- */
-const HTTP_QUOTED_STRING_TOKENS = /[\u0009|\u0020-\u007E|\u0080-\u00FF]/ // eslint-disable-line
-
-// https://fetch.spec.whatwg.org/#data-url-processor
-/** @param {URL} dataURL */
-function dataURLProcessor (dataURL) {
- // 1. Assert: dataURL’s scheme is "data".
- assert(dataURL.protocol === 'data:')
-
- // 2. Let input be the result of running the URL
- // serializer on dataURL with exclude fragment
- // set to true.
- let input = URLSerializer(dataURL, true)
-
- // 3. Remove the leading "data:" string from input.
- input = input.slice(5)
-
- // 4. Let position point at the start of input.
- const position = { position: 0 }
-
- // 5. Let mimeType be the result of collecting a
- // sequence of code points that are not equal
- // to U+002C (,), given position.
- let mimeType = collectASequenceOfCodePointsFast(
- ',',
- input,
- position
- )
-
- // 6. Strip leading and trailing ASCII whitespace
- // from mimeType.
- // Undici implementation note: we need to store the
- // length because if the mimetype has spaces removed,
- // the wrong amount will be sliced from the input in
- // step #9
- const mimeTypeLength = mimeType.length
- mimeType = removeASCIIWhitespace(mimeType, true, true)
-
- // 7. If position is past the end of input, then
- // return failure
- if (position.position >= input.length) {
- return 'failure'
- }
-
- // 8. Advance position by 1.
- position.position++
-
- // 9. Let encodedBody be the remainder of input.
- const encodedBody = input.slice(mimeTypeLength + 1)
-
- // 10. Let body be the percent-decoding of encodedBody.
- let body = stringPercentDecode(encodedBody)
-
- // 11. If mimeType ends with U+003B (;), followed by
- // zero or more U+0020 SPACE, followed by an ASCII
- // case-insensitive match for "base64", then:
- if (/;(\u0020){0,}base64$/i.test(mimeType)) {
- // 1. Let stringBody be the isomorphic decode of body.
- const stringBody = isomorphicDecode(body)
-
- // 2. Set body to the forgiving-base64 decode of
- // stringBody.
- body = forgivingBase64(stringBody)
-
- // 3. If body is failure, then return failure.
- if (body === 'failure') {
- return 'failure'
- }
-
- // 4. Remove the last 6 code points from mimeType.
- mimeType = mimeType.slice(0, -6)
-
- // 5. Remove trailing U+0020 SPACE code points from mimeType,
- // if any.
- mimeType = mimeType.replace(/(\u0020)+$/, '')
-
- // 6. Remove the last U+003B (;) code point from mimeType.
- mimeType = mimeType.slice(0, -1)
- }
-
- // 12. If mimeType starts with U+003B (;), then prepend
- // "text/plain" to mimeType.
- if (mimeType.startsWith(';')) {
- mimeType = 'text/plain' + mimeType
- }
-
- // 13. Let mimeTypeRecord be the result of parsing
- // mimeType.
- let mimeTypeRecord = parseMIMEType(mimeType)
-
- // 14. If mimeTypeRecord is failure, then set
- // mimeTypeRecord to text/plain;charset=US-ASCII.
- if (mimeTypeRecord === 'failure') {
- mimeTypeRecord = parseMIMEType('text/plain;charset=US-ASCII')
- }
-
- // 15. Return a new data: URL struct whose MIME
- // type is mimeTypeRecord and body is body.
- // https://fetch.spec.whatwg.org/#data-url-struct
- return { mimeType: mimeTypeRecord, body }
-}
-
-// https://url.spec.whatwg.org/#concept-url-serializer
-/**
- * @param {URL} url
- * @param {boolean} excludeFragment
- */
-function URLSerializer (url, excludeFragment = false) {
- const href = url.href
-
- if (!excludeFragment) {
- return href
- }
-
- const hash = href.lastIndexOf('#')
- if (hash === -1) {
- return href
- }
- return href.slice(0, hash)
-}
-
-// https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points
-/**
- * @param {(char: string) => boolean} condition
- * @param {string} input
- * @param {{ position: number }} position
- */
-function collectASequenceOfCodePoints (condition, input, position) {
- // 1. Let result be the empty string.
- let result = ''
-
- // 2. While position doesn’t point past the end of input and the
- // code point at position within input meets the condition condition:
- while (position.position < input.length && condition(input[position.position])) {
- // 1. Append that code point to the end of result.
- result += input[position.position]
-
- // 2. Advance position by 1.
- position.position++
- }
-
- // 3. Return result.
- return result
-}
-
-/**
- * A faster collectASequenceOfCodePoints that only works when comparing a single character.
- * @param {string} char
- * @param {string} input
- * @param {{ position: number }} position
- */
-function collectASequenceOfCodePointsFast (char, input, position) {
- const idx = input.indexOf(char, position.position)
- const start = position.position
-
- if (idx === -1) {
- position.position = input.length
- return input.slice(start)
- }
-
- position.position = idx
- return input.slice(start, position.position)
-}
-
-// https://url.spec.whatwg.org/#string-percent-decode
-/** @param {string} input */
-function stringPercentDecode (input) {
- // 1. Let bytes be the UTF-8 encoding of input.
- const bytes = encoder.encode(input)
-
- // 2. Return the percent-decoding of bytes.
- return percentDecode(bytes)
-}
-
-// https://url.spec.whatwg.org/#percent-decode
-/** @param {Uint8Array} input */
-function percentDecode (input) {
- // 1. Let output be an empty byte sequence.
- /** @type {number[]} */
- const output = []
-
- // 2. For each byte byte in input:
- for (let i = 0; i < input.length; i++) {
- const byte = input[i]
-
- // 1. If byte is not 0x25 (%), then append byte to output.
- if (byte !== 0x25) {
- output.push(byte)
-
- // 2. Otherwise, if byte is 0x25 (%) and the next two bytes
- // after byte in input are not in the ranges
- // 0x30 (0) to 0x39 (9), 0x41 (A) to 0x46 (F),
- // and 0x61 (a) to 0x66 (f), all inclusive, append byte
- // to output.
- } else if (
- byte === 0x25 &&
- !/^[0-9A-Fa-f]{2}$/i.test(String.fromCharCode(input[i + 1], input[i + 2]))
- ) {
- output.push(0x25)
-
- // 3. Otherwise:
- } else {
- // 1. Let bytePoint be the two bytes after byte in input,
- // decoded, and then interpreted as hexadecimal number.
- const nextTwoBytes = String.fromCharCode(input[i + 1], input[i + 2])
- const bytePoint = Number.parseInt(nextTwoBytes, 16)
-
- // 2. Append a byte whose value is bytePoint to output.
- output.push(bytePoint)
-
- // 3. Skip the next two bytes in input.
- i += 2
- }
- }
-
- // 3. Return output.
- return Uint8Array.from(output)
-}
-
-// https://mimesniff.spec.whatwg.org/#parse-a-mime-type
-/** @param {string} input */
-function parseMIMEType (input) {
- // 1. Remove any leading and trailing HTTP whitespace
- // from input.
- input = removeHTTPWhitespace(input, true, true)
-
- // 2. Let position be a position variable for input,
- // initially pointing at the start of input.
- const position = { position: 0 }
-
- // 3. Let type be the result of collecting a sequence
- // of code points that are not U+002F (/) from
- // input, given position.
- const type = collectASequenceOfCodePointsFast(
- '/',
- input,
- position
- )
-
- // 4. If type is the empty string or does not solely
- // contain HTTP token code points, then return failure.
- // https://mimesniff.spec.whatwg.org/#http-token-code-point
- if (type.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(type)) {
- return 'failure'
- }
-
- // 5. If position is past the end of input, then return
- // failure
- if (position.position > input.length) {
- return 'failure'
- }
-
- // 6. Advance position by 1. (This skips past U+002F (/).)
- position.position++
-
- // 7. Let subtype be the result of collecting a sequence of
- // code points that are not U+003B (;) from input, given
- // position.
- let subtype = collectASequenceOfCodePointsFast(
- ';',
- input,
- position
- )
-
- // 8. Remove any trailing HTTP whitespace from subtype.
- subtype = removeHTTPWhitespace(subtype, false, true)
-
- // 9. If subtype is the empty string or does not solely
- // contain HTTP token code points, then return failure.
- if (subtype.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(subtype)) {
- return 'failure'
- }
-
- const typeLowercase = type.toLowerCase()
- const subtypeLowercase = subtype.toLowerCase()
-
- // 10. Let mimeType be a new MIME type record whose type
- // is type, in ASCII lowercase, and subtype is subtype,
- // in ASCII lowercase.
- // https://mimesniff.spec.whatwg.org/#mime-type
- const mimeType = {
- type: typeLowercase,
- subtype: subtypeLowercase,
- /** @type {Map<string, string>} */
- parameters: new Map(),
- // https://mimesniff.spec.whatwg.org/#mime-type-essence
- essence: `${typeLowercase}/${subtypeLowercase}`
- }
-
- // 11. While position is not past the end of input:
- while (position.position < input.length) {
- // 1. Advance position by 1. (This skips past U+003B (;).)
- position.position++
-
- // 2. Collect a sequence of code points that are HTTP
- // whitespace from input given position.
- collectASequenceOfCodePoints(
- // https://fetch.spec.whatwg.org/#http-whitespace
- char => HTTP_WHITESPACE_REGEX.test(char),
- input,
- position
- )
-
- // 3. Let parameterName be the result of collecting a
- // sequence of code points that are not U+003B (;)
- // or U+003D (=) from input, given position.
- let parameterName = collectASequenceOfCodePoints(
- (char) => char !== ';' && char !== '=',
- input,
- position
- )
-
- // 4. Set parameterName to parameterName, in ASCII
- // lowercase.
- parameterName = parameterName.toLowerCase()
-
- // 5. If position is not past the end of input, then:
- if (position.position < input.length) {
- // 1. If the code point at position within input is
- // U+003B (;), then continue.
- if (input[position.position] === ';') {
- continue
- }
-
- // 2. Advance position by 1. (This skips past U+003D (=).)
- position.position++
- }
-
- // 6. If position is past the end of input, then break.
- if (position.position > input.length) {
- break
- }
-
- // 7. Let parameterValue be null.
- let parameterValue = null
-
- // 8. If the code point at position within input is
- // U+0022 ("), then:
- if (input[position.position] === '"') {
- // 1. Set parameterValue to the result of collecting
- // an HTTP quoted string from input, given position
- // and the extract-value flag.
- parameterValue = collectAnHTTPQuotedString(input, position, true)
-
- // 2. Collect a sequence of code points that are not
- // U+003B (;) from input, given position.
- collectASequenceOfCodePointsFast(
- ';',
- input,
- position
- )
-
- // 9. Otherwise:
- } else {
- // 1. Set parameterValue to the result of collecting
- // a sequence of code points that are not U+003B (;)
- // from input, given position.
- parameterValue = collectASequenceOfCodePointsFast(
- ';',
- input,
- position
- )
-
- // 2. Remove any trailing HTTP whitespace from parameterValue.
- parameterValue = removeHTTPWhitespace(parameterValue, false, true)
-
- // 3. If parameterValue is the empty string, then continue.
- if (parameterValue.length === 0) {
- continue
- }
- }
-
- // 10. If all of the following are true
- // - parameterName is not the empty string
- // - parameterName solely contains HTTP token code points
- // - parameterValue solely contains HTTP quoted-string token code points
- // - mimeType’s parameters[parameterName] does not exist
- // then set mimeType’s parameters[parameterName] to parameterValue.
- if (
- parameterName.length !== 0 &&
- HTTP_TOKEN_CODEPOINTS.test(parameterName) &&
- (parameterValue.length === 0 || HTTP_QUOTED_STRING_TOKENS.test(parameterValue)) &&
- !mimeType.parameters.has(parameterName)
- ) {
- mimeType.parameters.set(parameterName, parameterValue)
- }
- }
-
- // 12. Return mimeType.
- return mimeType
-}
-
-// https://infra.spec.whatwg.org/#forgiving-base64-decode
-/** @param {string} data */
-function forgivingBase64 (data) {
- // 1. Remove all ASCII whitespace from data.
- data = data.replace(/[\u0009\u000A\u000C\u000D\u0020]/g, '') // eslint-disable-line
-
- // 2. If data’s code point length divides by 4 leaving
- // no remainder, then:
- if (data.length % 4 === 0) {
- // 1. If data ends with one or two U+003D (=) code points,
- // then remove them from data.
- data = data.replace(/=?=$/, '')
- }
-
- // 3. If data’s code point length divides by 4 leaving
- // a remainder of 1, then return failure.
- if (data.length % 4 === 1) {
- return 'failure'
- }
-
- // 4. If data contains a code point that is not one of
- // U+002B (+)
- // U+002F (/)
- // ASCII alphanumeric
- // then return failure.
- if (/[^+/0-9A-Za-z]/.test(data)) {
- return 'failure'
- }
-
- const binary = atob(data)
- const bytes = new Uint8Array(binary.length)
-
- for (let byte = 0; byte < binary.length; byte++) {
- bytes[byte] = binary.charCodeAt(byte)
- }
-
- return bytes
-}
-
-// https://fetch.spec.whatwg.org/#collect-an-http-quoted-string
-// tests: https://fetch.spec.whatwg.org/#example-http-quoted-string
-/**
- * @param {string} input
- * @param {{ position: number }} position
- * @param {boolean?} extractValue
- */
-function collectAnHTTPQuotedString (input, position, extractValue) {
- // 1. Let positionStart be position.
- const positionStart = position.position
-
- // 2. Let value be the empty string.
- let value = ''
-
- // 3. Assert: the code point at position within input
- // is U+0022 (").
- assert(input[position.position] === '"')
-
- // 4. Advance position by 1.
- position.position++
-
- // 5. While true:
- while (true) {
- // 1. Append the result of collecting a sequence of code points
- // that are not U+0022 (") or U+005C (\) from input, given
- // position, to value.
- value += collectASequenceOfCodePoints(
- (char) => char !== '"' && char !== '\\',
- input,
- position
- )
-
- // 2. If position is past the end of input, then break.
- if (position.position >= input.length) {
- break
- }
-
- // 3. Let quoteOrBackslash be the code point at position within
- // input.
- const quoteOrBackslash = input[position.position]
-
- // 4. Advance position by 1.
- position.position++
-
- // 5. If quoteOrBackslash is U+005C (\), then:
- if (quoteOrBackslash === '\\') {
- // 1. If position is past the end of input, then append
- // U+005C (\) to value and break.
- if (position.position >= input.length) {
- value += '\\'
- break
- }
-
- // 2. Append the code point at position within input to value.
- value += input[position.position]
-
- // 3. Advance position by 1.
- position.position++
-
- // 6. Otherwise:
- } else {
- // 1. Assert: quoteOrBackslash is U+0022 (").
- assert(quoteOrBackslash === '"')
-
- // 2. Break.
- break
- }
- }
-
- // 6. If the extract-value flag is set, then return value.
- if (extractValue) {
- return value
- }
-
- // 7. Return the code points from positionStart to position,
- // inclusive, within input.
- return input.slice(positionStart, position.position)
-}
-
-/**
- * @see https://mimesniff.spec.whatwg.org/#serialize-a-mime-type
- */
-function serializeAMimeType (mimeType) {
- assert(mimeType !== 'failure')
- const { parameters, essence } = mimeType
-
- // 1. Let serialization be the concatenation of mimeType’s
- // type, U+002F (/), and mimeType’s subtype.
- let serialization = essence
-
- // 2. For each name → value of mimeType’s parameters:
- for (let [name, value] of parameters.entries()) {
- // 1. Append U+003B (;) to serialization.
- serialization += ';'
-
- // 2. Append name to serialization.
- serialization += name
-
- // 3. Append U+003D (=) to serialization.
- serialization += '='
-
- // 4. If value does not solely contain HTTP token code
- // points or value is the empty string, then:
- if (!HTTP_TOKEN_CODEPOINTS.test(value)) {
- // 1. Precede each occurence of U+0022 (") or
- // U+005C (\) in value with U+005C (\).
- value = value.replace(/(\\|")/g, '\\$1')
-
- // 2. Prepend U+0022 (") to value.
- value = '"' + value
-
- // 3. Append U+0022 (") to value.
- value += '"'
- }
-
- // 5. Append value to serialization.
- serialization += value
- }
-
- // 3. Return serialization.
- return serialization
-}
-
-/**
- * @see https://fetch.spec.whatwg.org/#http-whitespace
- * @param {string} char
- */
-function isHTTPWhiteSpace (char) {
- return char === '\r' || char === '\n' || char === '\t' || char === ' '
-}
-
-/**
- * @see https://fetch.spec.whatwg.org/#http-whitespace
- * @param {string} str
- */
-function removeHTTPWhitespace (str, leading = true, trailing = true) {
- let lead = 0
- let trail = str.length - 1
-
- if (leading) {
- for (; lead < str.length && isHTTPWhiteSpace(str[lead]); lead++);
- }
-
- if (trailing) {
- for (; trail > 0 && isHTTPWhiteSpace(str[trail]); trail--);
- }
-
- return str.slice(lead, trail + 1)
-}
-
-/**
- * @see https://infra.spec.whatwg.org/#ascii-whitespace
- * @param {string} char
- */
-function isASCIIWhitespace (char) {
- return char === '\r' || char === '\n' || char === '\t' || char === '\f' || char === ' '
-}
-
-/**
- * @see https://infra.spec.whatwg.org/#strip-leading-and-trailing-ascii-whitespace
- */
-function removeASCIIWhitespace (str, leading = true, trailing = true) {
- let lead = 0
- let trail = str.length - 1
-
- if (leading) {
- for (; lead < str.length && isASCIIWhitespace(str[lead]); lead++);
- }
-
- if (trailing) {
- for (; trail > 0 && isASCIIWhitespace(str[trail]); trail--);
- }
-
- return str.slice(lead, trail + 1)
-}
-
-module.exports = {
- dataURLProcessor,
- URLSerializer,
- collectASequenceOfCodePoints,
- collectASequenceOfCodePointsFast,
- stringPercentDecode,
- parseMIMEType,
- collectAnHTTPQuotedString,
- serializeAMimeType
-}
diff --git a/g4f/Provider/npm/node_modules/undici/lib/fetch/file.js b/g4f/Provider/npm/node_modules/undici/lib/fetch/file.js
deleted file mode 100644
index 3133d255..00000000
--- a/g4f/Provider/npm/node_modules/undici/lib/fetch/file.js
+++ /dev/null
@@ -1,344 +0,0 @@
-'use strict'
-
-const { Blob, File: NativeFile } = require('buffer')
-const { types } = require('util')
-const { kState } = require('./symbols')
-const { isBlobLike } = require('./util')
-const { webidl } = require('./webidl')
-const { parseMIMEType, serializeAMimeType } = require('./dataURL')
-const { kEnumerableProperty } = require('../core/util')
-const encoder = new TextEncoder()
-
-class File extends Blob {
- constructor (fileBits, fileName, options = {}) {
- // The File constructor is invoked with two or three parameters, depending
- // on whether the optional dictionary parameter is used. When the File()
- // constructor is invoked, user agents must run the following steps:
- webidl.argumentLengthCheck(arguments, 2, { header: 'File constructor' })
-
- fileBits = webidl.converters['sequence<BlobPart>'](fileBits)
- fileName = webidl.converters.USVString(fileName)
- options = webidl.converters.FilePropertyBag(options)
-
- // 1. Let bytes be the result of processing blob parts given fileBits and
- // options.
- // Note: Blob handles this for us
-
- // 2. Let n be the fileName argument to the constructor.
- const n = fileName
-
- // 3. Process FilePropertyBag dictionary argument by running the following
- // substeps:
-
- // 1. If the type member is provided and is not the empty string, let t
- // be set to the type dictionary member. If t contains any characters
- // outside the range U+0020 to U+007E, then set t to the empty string
- // and return from these substeps.
- // 2. Convert every character in t to ASCII lowercase.
- let t = options.type
- let d
-
- // eslint-disable-next-line no-labels
- substep: {
- if (t) {
- t = parseMIMEType(t)
-
- if (t === 'failure') {
- t = ''
- // eslint-disable-next-line no-labels
- break substep
- }
-
- t = serializeAMimeType(t).toLowerCase()
- }
-
- // 3. If the lastModified member is provided, let d be set to the
- // lastModified dictionary member. If it is not provided, set d to the
- // current date and time represented as the number of milliseconds since
- // the Unix Epoch (which is the equivalent of Date.now() [ECMA-262]).
- d = options.lastModified
- }
-
- // 4. Return a new File object F such that:
- // F refers to the bytes byte sequence.
- // F.size is set to the number of total bytes in bytes.
- // F.name is set to n.
- // F.type is set to t.
- // F.lastModified is set to d.
-
- super(processBlobParts(fileBits, options), { type: t })
- this[kState] = {
- name: n,
- lastModified: d,
- type: t
- }
- }
-
- get name () {
- webidl.brandCheck(this, File)
-
- return this[kState].name
- }
-
- get lastModified () {
- webidl.brandCheck(this, File)
-
- return this[kState].lastModified
- }
-
- get type () {
- webidl.brandCheck(this, File)
-
- return this[kState].type
- }
-}
-
-class FileLike {
- constructor (blobLike, fileName, options = {}) {
- // TODO: argument idl type check
-
- // The File constructor is invoked with two or three parameters, depending
- // on whether the optional dictionary parameter is used. When the File()
- // constructor is invoked, user agents must run the following steps:
-
- // 1. Let bytes be the result of processing blob parts given fileBits and
- // options.
-
- // 2. Let n be the fileName argument to the constructor.
- const n = fileName
-
- // 3. Process FilePropertyBag dictionary argument by running the following
- // substeps:
-
- // 1. If the type member is provided and is not the empty string, let t
- // be set to the type dictionary member. If t contains any characters
- // outside the range U+0020 to U+007E, then set t to the empty string
- // and return from these substeps.
- // TODO
- const t = options.type
-
- // 2. Convert every character in t to ASCII lowercase.
- // TODO
-
- // 3. If the lastModified member is provided, let d be set to the
- // lastModified dictionary member. If it is not provided, set d to the
- // current date and time represented as the number of milliseconds since
- // the Unix Epoch (which is the equivalent of Date.now() [ECMA-262]).
- const d = options.lastModified ?? Date.now()
-
- // 4. Return a new File object F such that:
- // F refers to the bytes byte sequence.
- // F.size is set to the number of total bytes in bytes.
- // F.name is set to n.
- // F.type is set to t.
- // F.lastModified is set to d.
-
- this[kState] = {
- blobLike,
- name: n,
- type: t,
- lastModified: d
- }
- }
-
- stream (...args) {
- webidl.brandCheck(this, FileLike)
-
- return this[kState].blobLike.stream(...args)
- }
-
- arrayBuffer (...args) {
- webidl.brandCheck(this, FileLike)
-
- return this[kState].blobLike.arrayBuffer(...args)
- }
-
- slice (...args) {
- webidl.brandCheck(this, FileLike)
-
- return this[kState].blobLike.slice(...args)
- }
-
- text (...args) {
- webidl.brandCheck(this, FileLike)
-
- return this[kState].blobLike.text(...args)
- }
-
- get size () {
- webidl.brandCheck(this, FileLike)
-
- return this[kState].blobLike.size
- }
-
- get type () {
- webidl.brandCheck(this, FileLike)
-
- return this[kState].blobLike.type
- }
-
- get name () {
- webidl.brandCheck(this, FileLike)
-
- return this[kState].name
- }
-
- get lastModified () {
- webidl.brandCheck(this, FileLike)
-
- return this[kState].lastModified
- }
-
- get [Symbol.toStringTag] () {
- return 'File'
- }
-}
-
-Object.defineProperties(File.prototype, {
- [Symbol.toStringTag]: {
- value: 'File',
- configurable: true
- },
- name: kEnumerableProperty,
- lastModified: kEnumerableProperty
-})
-
-webidl.converters.Blob = webidl.interfaceConverter(Blob)
-
-webidl.converters.BlobPart = function (V, opts) {
- if (webidl.util.Type(V) === 'Object') {
- if (isBlobLike(V)) {
- return webidl.converters.Blob(V, { strict: false })
- }
-
- if (
- ArrayBuffer.isView(V) ||
- types.isAnyArrayBuffer(V)
- ) {
- return webidl.converters.BufferSource(V, opts)
- }
- }
-
- return webidl.converters.USVString(V, opts)
-}
-
-webidl.converters['sequence<BlobPart>'] = webidl.sequenceConverter(
- webidl.converters.BlobPart
-)
-
-// https://www.w3.org/TR/FileAPI/#dfn-FilePropertyBag
-webidl.converters.FilePropertyBag = webidl.dictionaryConverter([
- {
- key: 'lastModified',
- converter: webidl.converters['long long'],
- get defaultValue () {
- return Date.now()
- }
- },
- {
- key: 'type',
- converter: webidl.converters.DOMString,
- defaultValue: ''
- },
- {
- key: 'endings',
- converter: (value) => {
- value = webidl.converters.DOMString(value)
- value = value.toLowerCase()
-
- if (value !== 'native') {
- value = 'transparent'
- }
-
- return value
- },
- defaultValue: 'transparent'
- }
-])
-
-/**
- * @see https://www.w3.org/TR/FileAPI/#process-blob-parts
- * @param {(NodeJS.TypedArray|Blob|string)[]} parts
- * @param {{ type: string, endings: string }} options
- */
-function processBlobParts (parts, options) {
- // 1. Let bytes be an empty sequence of bytes.
- /** @type {NodeJS.TypedArray[]} */
- const bytes = []
-
- // 2. For each element in parts:
- for (const element of parts) {
- // 1. If element is a USVString, run the following substeps:
- if (typeof element === 'string') {
- // 1. Let s be element.
- let s = element
-
- // 2. If the endings member of options is "native", set s
- // to the result of converting line endings to native
- // of element.
- if (options.endings === 'native') {
- s = convertLineEndingsNative(s)
- }
-
- // 3. Append the result of UTF-8 encoding s to bytes.
- bytes.push(encoder.encode(s))
- } else if (
- types.isAnyArrayBuffer(element) ||
- types.isTypedArray(element)
- ) {
- // 2. If element is a BufferSource, get a copy of the
- // bytes held by the buffer source, and append those
- // bytes to bytes.
- if (!element.buffer) { // ArrayBuffer
- bytes.push(new Uint8Array(element))
- } else {
- bytes.push(
- new Uint8Array(element.buffer, element.byteOffset, element.byteLength)
- )
- }
- } else if (isBlobLike(element)) {
- // 3. If element is a Blob, append the bytes it represents
- // to bytes.
- bytes.push(element)
- }
- }
-
- // 3. Return bytes.
- return bytes
-}
-
-/**
- * @see https://www.w3.org/TR/FileAPI/#convert-line-endings-to-native
- * @param {string} s
- */
-function convertLineEndingsNative (s) {
- // 1. Let native line ending be be the code point U+000A LF.
- let nativeLineEnding = '\n'
-
- // 2. If the underlying platform’s conventions are to
- // represent newlines as a carriage return and line feed
- // sequence, set native line ending to the code point
- // U+000D CR followed by the code point U+000A LF.
- if (process.platform === 'win32') {
- nativeLineEnding = '\r\n'
- }
-
- return s.replace(/\r?\n/g, nativeLineEnding)
-}
-
-// If this function is moved to ./util.js, some tools (such as
-// rollup) will warn about circular dependencies. See:
-// https://github.com/nodejs/undici/issues/1629
-function isFileLike (object) {
- return (
- (NativeFile && object instanceof NativeFile) ||
- object instanceof File || (
- object &&
- (typeof object.stream === 'function' ||
- typeof object.arrayBuffer === 'function') &&
- object[Symbol.toStringTag] === 'File'
- )
- )
-}
-
-module.exports = { File, FileLike, isFileLike }
diff --git a/g4f/Provider/npm/node_modules/undici/lib/fetch/formdata.js b/g4f/Provider/npm/node_modules/undici/lib/fetch/formdata.js
deleted file mode 100644
index 5975e26c..00000000
--- a/g4f/Provider/npm/node_modules/undici/lib/fetch/formdata.js
+++ /dev/null
@@ -1,265 +0,0 @@
-'use strict'
-
-const { isBlobLike, toUSVString, makeIterator } = require('./util')
-const { kState } = require('./symbols')
-const { File: UndiciFile, FileLike, isFileLike } = require('./file')
-const { webidl } = require('./webidl')
-const { Blob, File: NativeFile } = require('buffer')
-
-/** @type {globalThis['File']} */
-const File = NativeFile ?? UndiciFile
-
-// https://xhr.spec.whatwg.org/#formdata
-class FormData {
- constructor (form) {
- if (form !== undefined) {
- throw webidl.errors.conversionFailed({
- prefix: 'FormData constructor',
- argument: 'Argument 1',
- types: ['undefined']
- })
- }
-
- this[kState] = []
- }
-
- append (name, value, filename = undefined) {
- webidl.brandCheck(this, FormData)
-
- webidl.argumentLengthCheck(arguments, 2, { header: 'FormData.append' })
-
- if (arguments.length === 3 && !isBlobLike(value)) {
- throw new TypeError(
- "Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'"
- )
- }
-
- // 1. Let value be value if given; otherwise blobValue.
-
- name = webidl.converters.USVString(name)
- value = isBlobLike(value)
- ? webidl.converters.Blob(value, { strict: false })
- : webidl.converters.USVString(value)
- filename = arguments.length === 3
- ? webidl.converters.USVString(filename)
- : undefined
-
- // 2. Let entry be the result of creating an entry with
- // name, value, and filename if given.
- const entry = makeEntry(name, value, filename)
-
- // 3. Append entry to this’s entry list.
- this[kState].push(entry)
- }
-
- delete (name) {
- webidl.brandCheck(this, FormData)
-
- webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.delete' })
-
- name = webidl.converters.USVString(name)
-
- // The delete(name) method steps are to remove all entries whose name
- // is name from this’s entry list.
- this[kState] = this[kState].filter(entry => entry.name !== name)
- }
-
- get (name) {
- webidl.brandCheck(this, FormData)
-
- webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.get' })
-
- name = webidl.converters.USVString(name)
-
- // 1. If there is no entry whose name is name in this’s entry list,
- // then return null.
- const idx = this[kState].findIndex((entry) => entry.name === name)
- if (idx === -1) {
- return null
- }
-
- // 2. Return the value of the first entry whose name is name from
- // this’s entry list.
- return this[kState][idx].value
- }
-
- getAll (name) {
- webidl.brandCheck(this, FormData)
-
- webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.getAll' })
-
- name = webidl.converters.USVString(name)
-
- // 1. If there is no entry whose name is name in this’s entry list,
- // then return the empty list.
- // 2. Return the values of all entries whose name is name, in order,
- // from this’s entry list.
- return this[kState]
- .filter((entry) => entry.name === name)
- .map((entry) => entry.value)
- }
-
- has (name) {
- webidl.brandCheck(this, FormData)
-
- webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.has' })
-
- name = webidl.converters.USVString(name)
-
- // The has(name) method steps are to return true if there is an entry
- // whose name is name in this’s entry list; otherwise false.
- return this[kState].findIndex((entry) => entry.name === name) !== -1
- }
-
- set (name, value, filename = undefined) {
- webidl.brandCheck(this, FormData)
-
- webidl.argumentLengthCheck(arguments, 2, { header: 'FormData.set' })
-
- if (arguments.length === 3 && !isBlobLike(value)) {
- throw new TypeError(
- "Failed to execute 'set' on 'FormData': parameter 2 is not of type 'Blob'"
- )
- }
-
- // The set(name, value) and set(name, blobValue, filename) method steps
- // are:
-
- // 1. Let value be value if given; otherwise blobValue.
-
- name = webidl.converters.USVString(name)
- value = isBlobLike(value)
- ? webidl.converters.Blob(value, { strict: false })
- : webidl.converters.USVString(value)
- filename = arguments.length === 3
- ? toUSVString(filename)
- : undefined
-
- // 2. Let entry be the result of creating an entry with name, value, and
- // filename if given.
- const entry = makeEntry(name, value, filename)
-
- // 3. If there are entries in this’s entry list whose name is name, then
- // replace the first such entry with entry and remove the others.
- const idx = this[kState].findIndex((entry) => entry.name === name)
- if (idx !== -1) {
- this[kState] = [
- ...this[kState].slice(0, idx),
- entry,
- ...this[kState].slice(idx + 1).filter((entry) => entry.name !== name)
- ]
- } else {
- // 4. Otherwise, append entry to this’s entry list.
- this[kState].push(entry)
- }
- }
-
- entries () {
- webidl.brandCheck(this, FormData)
-
- return makeIterator(
- () => this[kState].map(pair => [pair.name, pair.value]),
- 'FormData',
- 'key+value'
- )
- }
-
- keys () {
- webidl.brandCheck(this, FormData)
-
- return makeIterator(
- () => this[kState].map(pair => [pair.name, pair.value]),
- 'FormData',
- 'key'
- )
- }
-
- values () {
- webidl.brandCheck(this, FormData)
-
- return makeIterator(
- () => this[kState].map(pair => [pair.name, pair.value]),
- 'FormData',
- 'value'
- )
- }
-
- /**
- * @param {(value: string, key: string, self: FormData) => void} callbackFn
- * @param {unknown} thisArg
- */
- forEach (callbackFn, thisArg = globalThis) {
- webidl.brandCheck(this, FormData)
-
- webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.forEach' })
-
- if (typeof callbackFn !== 'function') {
- throw new TypeError(
- "Failed to execute 'forEach' on 'FormData': parameter 1 is not of type 'Function'."
- )
- }
-
- for (const [key, value] of this) {
- callbackFn.apply(thisArg, [value, key, this])
- }
- }
-}
-
-FormData.prototype[Symbol.iterator] = FormData.prototype.entries
-
-Object.defineProperties(FormData.prototype, {
- [Symbol.toStringTag]: {
- value: 'FormData',
- configurable: true
- }
-})
-
-/**
- * @see https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#create-an-entry
- * @param {string} name
- * @param {string|Blob} value
- * @param {?string} filename
- * @returns
- */
-function makeEntry (name, value, filename) {
- // 1. Set name to the result of converting name into a scalar value string.
- // "To convert a string into a scalar value string, replace any surrogates
- // with U+FFFD."
- // see: https://nodejs.org/dist/latest-v18.x/docs/api/buffer.html#buftostringencoding-start-end
- name = Buffer.from(name).toString('utf8')
-
- // 2. If value is a string, then set value to the result of converting
- // value into a scalar value string.
- if (typeof value === 'string') {
- value = Buffer.from(value).toString('utf8')
- } else {
- // 3. Otherwise:
-
- // 1. If value is not a File object, then set value to a new File object,
- // representing the same bytes, whose name attribute value is "blob"
- if (!isFileLike(value)) {
- value = value instanceof Blob
- ? new File([value], 'blob', { type: value.type })
- : new FileLike(value, 'blob', { type: value.type })
- }
-
- // 2. If filename is given, then set value to a new File object,
- // representing the same bytes, whose name attribute is filename.
- if (filename !== undefined) {
- /** @type {FilePropertyBag} */
- const options = {
- type: value.type,
- lastModified: value.lastModified
- }
-
- value = (NativeFile && value instanceof NativeFile) || value instanceof UndiciFile
- ? new File([value], filename, options)
- : new FileLike(value, filename, options)
- }
- }
-
- // 4. Return an entry whose name is name and whose value is value.
- return { name, value }
-}
-
-module.exports = { FormData }
diff --git a/g4f/Provider/npm/node_modules/undici/lib/fetch/global.js b/g4f/Provider/npm/node_modules/undici/lib/fetch/global.js
deleted file mode 100644
index 1df6f122..00000000
--- a/g4f/Provider/npm/node_modules/undici/lib/fetch/global.js
+++ /dev/null
@@ -1,40 +0,0 @@
-'use strict'
-
-// In case of breaking changes, increase the version
-// number to avoid conflicts.
-const globalOrigin = Symbol.for('undici.globalOrigin.1')
-
-function getGlobalOrigin () {
- return globalThis[globalOrigin]
-}
-
-function setGlobalOrigin (newOrigin) {
- if (newOrigin === undefined) {
- Object.defineProperty(globalThis, globalOrigin, {
- value: undefined,
- writable: true,
- enumerable: false,
- configurable: false
- })
-
- return
- }
-
- const parsedURL = new URL(newOrigin)
-
- if (parsedURL.protocol !== 'http:' && parsedURL.protocol !== 'https:') {
- throw new TypeError(`Only http & https urls are allowed, received ${parsedURL.protocol}`)
- }
-
- Object.defineProperty(globalThis, globalOrigin, {
- value: parsedURL,
- writable: true,
- enumerable: false,
- configurable: false
- })
-}
-
-module.exports = {
- getGlobalOrigin,
- setGlobalOrigin
-}
diff --git a/g4f/Provider/npm/node_modules/undici/lib/fetch/headers.js b/g4f/Provider/npm/node_modules/undici/lib/fetch/headers.js
deleted file mode 100644
index aa5e73e5..00000000
--- a/g4f/Provider/npm/node_modules/undici/lib/fetch/headers.js
+++ /dev/null
@@ -1,552 +0,0 @@
-// https://github.com/Ethan-Arrowood/undici-fetch
-
-'use strict'
-
-const { kHeadersList } = require('../core/symbols')
-const { kGuard } = require('./symbols')
-const { kEnumerableProperty } = require('../core/util')
-const {
- makeIterator,
- isValidHeaderName,
- isValidHeaderValue
-} = require('./util')
-const { webidl } = require('./webidl')
-const assert = require('assert')
-
-const kHeadersMap = Symbol('headers map')
-const kHeadersSortedMap = Symbol('headers map sorted')
-
-/**
- * @see https://fetch.spec.whatwg.org/#concept-header-value-normalize
- * @param {string} potentialValue
- */
-function headerValueNormalize (potentialValue) {
- // To normalize a byte sequence potentialValue, remove
- // any leading and trailing HTTP whitespace bytes from
- // potentialValue.
-
- // Trimming the end with `.replace()` and a RegExp is typically subject to
- // ReDoS. This is safer and faster.
- let i = potentialValue.length
- while (/[\r\n\t ]/.test(potentialValue.charAt(--i)));
- return potentialValue.slice(0, i + 1).replace(/^[\r\n\t ]+/, '')
-}
-
-function fill (headers, object) {
- // To fill a Headers object headers with a given object object, run these steps:
-
- // 1. If object is a sequence, then for each header in object:
- // Note: webidl conversion to array has already been done.
- if (Array.isArray(object)) {
- for (const header of object) {
- // 1. If header does not contain exactly two items, then throw a TypeError.
- if (header.length !== 2) {
- throw webidl.errors.exception({
- header: 'Headers constructor',
- message: `expected name/value pair to be length 2, found ${header.length}.`
- })
- }
-
- // 2. Append (header’s first item, header’s second item) to headers.
- headers.append(header[0], header[1])
- }
- } else if (typeof object === 'object' && object !== null) {
- // Note: null should throw
-
- // 2. Otherwise, object is a record, then for each key → value in object,
- // append (key, value) to headers
- for (const [key, value] of Object.entries(object)) {
- headers.append(key, value)
- }
- } else {
- throw webidl.errors.conversionFailed({
- prefix: 'Headers constructor',
- argument: 'Argument 1',
- types: ['sequence<sequence<ByteString>>', 'record<ByteString, ByteString>']
- })
- }
-}
-
-class HeadersList {
- /** @type {[string, string][]|null} */
- cookies = null
-
- constructor (init) {
- if (init instanceof HeadersList) {
- this[kHeadersMap] = new Map(init[kHeadersMap])
- this[kHeadersSortedMap] = init[kHeadersSortedMap]
- this.cookies = init.cookies
- } else {
- this[kHeadersMap] = new Map(init)
- this[kHeadersSortedMap] = null
- }
- }
-
- // https://fetch.spec.whatwg.org/#header-list-contains
- contains (name) {
- // A header list list contains a header name name if list
- // contains a header whose name is a byte-case-insensitive
- // match for name.
- name = name.toLowerCase()
-
- return this[kHeadersMap].has(name)
- }
-
- clear () {
- this[kHeadersMap].clear()
- this[kHeadersSortedMap] = null
- this.cookies = null
- }
-
- // https://fetch.spec.whatwg.org/#concept-header-list-append
- append (name, value) {
- this[kHeadersSortedMap] = null
-
- // 1. If list contains name, then set name to the first such
- // header’s name.
- const lowercaseName = name.toLowerCase()
- const exists = this[kHeadersMap].get(lowercaseName)
-
- // 2. Append (name, value) to list.
- if (exists) {
- const delimiter = lowercaseName === 'cookie' ? '; ' : ', '
- this[kHeadersMap].set(lowercaseName, {
- name: exists.name,
- value: `${exists.value}${delimiter}${value}`
- })
- } else {
- this[kHeadersMap].set(lowercaseName, { name, value })
- }
-
- if (lowercaseName === 'set-cookie') {
- this.cookies ??= []
- this.cookies.push(value)
- }
- }
-
- // https://fetch.spec.whatwg.org/#concept-header-list-set
- set (name, value) {
- this[kHeadersSortedMap] = null
- const lowercaseName = name.toLowerCase()
-
- if (lowercaseName === 'set-cookie') {
- this.cookies = [value]
- }
-
- // 1. If list contains name, then set the value of
- // the first such header to value and remove the
- // others.
- // 2. Otherwise, append header (name, value) to list.
- return this[kHeadersMap].set(lowercaseName, { name, value })
- }
-
- // https://fetch.spec.whatwg.org/#concept-header-list-delete
- delete (name) {
- this[kHeadersSortedMap] = null
-
- name = name.toLowerCase()
-
- if (name === 'set-cookie') {
- this.cookies = null
- }
-
- return this[kHeadersMap].delete(name)
- }
-
- // https://fetch.spec.whatwg.org/#concept-header-list-get
- get (name) {
- // 1. If list does not contain name, then return null.
- if (!this.contains(name)) {
- return null
- }
-
- // 2. Return the values of all headers in list whose name
- // is a byte-case-insensitive match for name,
- // separated from each other by 0x2C 0x20, in order.
- return this[kHeadersMap].get(name.toLowerCase())?.value ?? null
- }
-
- * [Symbol.iterator] () {
- // use the lowercased name
- for (const [name, { value }] of this[kHeadersMap]) {
- yield [name, value]
- }
- }
-
- get entries () {
- const headers = {}
-
- if (this[kHeadersMap].size) {
- for (const { name, value } of this[kHeadersMap].values()) {
- headers[name] = value
- }
- }
-
- return headers
- }
-}
-
-// https://fetch.spec.whatwg.org/#headers-class
-class Headers {
- constructor (init = undefined) {
- this[kHeadersList] = new HeadersList()
-
- // The new Headers(init) constructor steps are:
-
- // 1. Set this’s guard to "none".
- this[kGuard] = 'none'
-
- // 2. If init is given, then fill this with init.
- if (init !== undefined) {
- init = webidl.converters.HeadersInit(init)
- fill(this, init)
- }
- }
-
- // https://fetch.spec.whatwg.org/#dom-headers-append
- append (name, value) {
- webidl.brandCheck(this, Headers)
-
- webidl.argumentLengthCheck(arguments, 2, { header: 'Headers.append' })
-
- name = webidl.converters.ByteString(name)
- value = webidl.converters.ByteString(value)
-
- // 1. Normalize value.
- value = headerValueNormalize(value)
-
- // 2. If name is not a header name or value is not a
- // header value, then throw a TypeError.
- if (!isValidHeaderName(name)) {
- throw webidl.errors.invalidArgument({
- prefix: 'Headers.append',
- value: name,
- type: 'header name'
- })
- } else if (!isValidHeaderValue(value)) {
- throw webidl.errors.invalidArgument({
- prefix: 'Headers.append',
- value,
- type: 'header value'
- })
- }
-
- // 3. If headers’s guard is "immutable", then throw a TypeError.
- // 4. Otherwise, if headers’s guard is "request" and name is a
- // forbidden header name, return.
- // Note: undici does not implement forbidden header names
- if (this[kGuard] === 'immutable') {
- throw new TypeError('immutable')
- } else if (this[kGuard] === 'request-no-cors') {
- // 5. Otherwise, if headers’s guard is "request-no-cors":
- // TODO
- }
-
- // 6. Otherwise, if headers’s guard is "response" and name is a
- // forbidden response-header name, return.
-
- // 7. Append (name, value) to headers’s header list.
- // 8. If headers’s guard is "request-no-cors", then remove
- // privileged no-CORS request headers from headers
- return this[kHeadersList].append(name, value)
- }
-
- // https://fetch.spec.whatwg.org/#dom-headers-delete
- delete (name) {
- webidl.brandCheck(this, Headers)
-
- webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.delete' })
-
- name = webidl.converters.ByteString(name)
-
- // 1. If name is not a header name, then throw a TypeError.
- if (!isValidHeaderName(name)) {
- throw webidl.errors.invalidArgument({
- prefix: 'Headers.delete',
- value: name,
- type: 'header name'
- })
- }
-
- // 2. If this’s guard is "immutable", then throw a TypeError.
- // 3. Otherwise, if this’s guard is "request" and name is a
- // forbidden header name, return.
- // 4. Otherwise, if this’s guard is "request-no-cors", name
- // is not a no-CORS-safelisted request-header name, and
- // name is not a privileged no-CORS request-header name,
- // return.
- // 5. Otherwise, if this’s guard is "response" and name is
- // a forbidden response-header name, return.
- // Note: undici does not implement forbidden header names
- if (this[kGuard] === 'immutable') {
- throw new TypeError('immutable')
- } else if (this[kGuard] === 'request-no-cors') {
- // TODO
- }
-
- // 6. If this’s header list does not contain name, then
- // return.
- if (!this[kHeadersList].contains(name)) {
- return
- }
-
- // 7. Delete name from this’s header list.
- // 8. If this’s guard is "request-no-cors", then remove
- // privileged no-CORS request headers from this.
- return this[kHeadersList].delete(name)
- }
-
- // https://fetch.spec.whatwg.org/#dom-headers-get
- get (name) {
- webidl.brandCheck(this, Headers)
-
- webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.get' })
-
- name = webidl.converters.ByteString(name)
-
- // 1. If name is not a header name, then throw a TypeError.
- if (!isValidHeaderName(name)) {
- throw webidl.errors.invalidArgument({
- prefix: 'Headers.get',
- value: name,
- type: 'header name'
- })
- }
-
- // 2. Return the result of getting name from this’s header
- // list.
- return this[kHeadersList].get(name)
- }
-
- // https://fetch.spec.whatwg.org/#dom-headers-has
- has (name) {
- webidl.brandCheck(this, Headers)
-
- webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.has' })
-
- name = webidl.converters.ByteString(name)
-
- // 1. If name is not a header name, then throw a TypeError.
- if (!isValidHeaderName(name)) {
- throw webidl.errors.invalidArgument({
- prefix: 'Headers.has',
- value: name,
- type: 'header name'
- })
- }
-
- // 2. Return true if this’s header list contains name;
- // otherwise false.
- return this[kHeadersList].contains(name)
- }
-
- // https://fetch.spec.whatwg.org/#dom-headers-set
- set (name, value) {
- webidl.brandCheck(this, Headers)
-
- webidl.argumentLengthCheck(arguments, 2, { header: 'Headers.set' })
-
- name = webidl.converters.ByteString(name)
- value = webidl.converters.ByteString(value)
-
- // 1. Normalize value.
- value = headerValueNormalize(value)
-
- // 2. If name is not a header name or value is not a
- // header value, then throw a TypeError.
- if (!isValidHeaderName(name)) {
- throw webidl.errors.invalidArgument({
- prefix: 'Headers.set',
- value: name,
- type: 'header name'
- })
- } else if (!isValidHeaderValue(value)) {
- throw webidl.errors.invalidArgument({
- prefix: 'Headers.set',
- value,
- type: 'header value'
- })
- }
-
- // 3. If this’s guard is "immutable", then throw a TypeError.
- // 4. Otherwise, if this’s guard is "request" and name is a
- // forbidden header name, return.
- // 5. Otherwise, if this’s guard is "request-no-cors" and
- // name/value is not a no-CORS-safelisted request-header,
- // return.
- // 6. Otherwise, if this’s guard is "response" and name is a
- // forbidden response-header name, return.
- // Note: undici does not implement forbidden header names
- if (this[kGuard] === 'immutable') {
- throw new TypeError('immutable')
- } else if (this[kGuard] === 'request-no-cors') {
- // TODO
- }
-
- // 7. Set (name, value) in this’s header list.
- // 8. If this’s guard is "request-no-cors", then remove
- // privileged no-CORS request headers from this
- return this[kHeadersList].set(name, value)
- }
-
- // https://fetch.spec.whatwg.org/#dom-headers-getsetcookie
- getSetCookie () {
- webidl.brandCheck(this, Headers)
-
- // 1. If this’s header list does not contain `Set-Cookie`, then return « ».
- // 2. Return the values of all headers in this’s header list whose name is
- // a byte-case-insensitive match for `Set-Cookie`, in order.
-
- const list = this[kHeadersList].cookies
-
- if (list) {
- return [...list]
- }
-
- return []
- }
-
- // https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine
- get [kHeadersSortedMap] () {
- if (this[kHeadersList][kHeadersSortedMap]) {
- return this[kHeadersList][kHeadersSortedMap]
- }
-
- // 1. Let headers be an empty list of headers with the key being the name
- // and value the value.
- const headers = []
-
- // 2. Let names be the result of convert header names to a sorted-lowercase
- // set with all the names of the headers in list.
- const names = [...this[kHeadersList]].sort((a, b) => a[0] < b[0] ? -1 : 1)
- const cookies = this[kHeadersList].cookies
-
- // 3. For each name of names:
- for (const [name, value] of names) {
- // 1. If name is `set-cookie`, then:
- if (name === 'set-cookie') {
- // 1. Let values be a list of all values of headers in list whose name
- // is a byte-case-insensitive match for name, in order.
-
- // 2. For each value of values:
- // 1. Append (name, value) to headers.
- for (const value of cookies) {
- headers.push([name, value])
- }
- } else {
- // 2. Otherwise:
-
- // 1. Let value be the result of getting name from list.
-
- // 2. Assert: value is non-null.
- assert(value !== null)
-
- // 3. Append (name, value) to headers.
- headers.push([name, value])
- }
- }
-
- this[kHeadersList][kHeadersSortedMap] = headers
-
- // 4. Return headers.
- return headers
- }
-
- keys () {
- webidl.brandCheck(this, Headers)
-
- return makeIterator(
- () => [...this[kHeadersSortedMap].values()],
- 'Headers',
- 'key'
- )
- }
-
- values () {
- webidl.brandCheck(this, Headers)
-
- return makeIterator(
- () => [...this[kHeadersSortedMap].values()],
- 'Headers',
- 'value'
- )
- }
-
- entries () {
- webidl.brandCheck(this, Headers)
-
- return makeIterator(
- () => [...this[kHeadersSortedMap].values()],
- 'Headers',
- 'key+value'
- )
- }
-
- /**
- * @param {(value: string, key: string, self: Headers) => void} callbackFn
- * @param {unknown} thisArg
- */
- forEach (callbackFn, thisArg = globalThis) {
- webidl.brandCheck(this, Headers)
-
- webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.forEach' })
-
- if (typeof callbackFn !== 'function') {
- throw new TypeError(
- "Failed to execute 'forEach' on 'Headers': parameter 1 is not of type 'Function'."
- )
- }
-
- for (const [key, value] of this) {
- callbackFn.apply(thisArg, [value, key, this])
- }
- }
-
- [Symbol.for('nodejs.util.inspect.custom')] () {
- webidl.brandCheck(this, Headers)
-
- return this[kHeadersList]
- }
-}
-
-Headers.prototype[Symbol.iterator] = Headers.prototype.entries
-
-Object.defineProperties(Headers.prototype, {
- append: kEnumerableProperty,
- delete: kEnumerableProperty,
- get: kEnumerableProperty,
- has: kEnumerableProperty,
- set: kEnumerableProperty,
- getSetCookie: kEnumerableProperty,
- keys: kEnumerableProperty,
- values: kEnumerableProperty,
- entries: kEnumerableProperty,
- forEach: kEnumerableProperty,
- [Symbol.iterator]: { enumerable: false },
- [Symbol.toStringTag]: {
- value: 'Headers',
- configurable: true
- }
-})
-
-webidl.converters.HeadersInit = function (V) {
- if (webidl.util.Type(V) === 'Object') {
- if (V[Symbol.iterator]) {
- return webidl.converters['sequence<sequence<ByteString>>'](V)
- }
-
- return webidl.converters['record<ByteString, ByteString>'](V)
- }
-
- throw webidl.errors.conversionFailed({
- prefix: 'Headers constructor',
- argument: 'Argument 1',
- types: ['sequence<sequence<ByteString>>', 'record<ByteString, ByteString>']
- })
-}
-
-module.exports = {
- fill,
- Headers,
- HeadersList
-}
diff --git a/g4f/Provider/npm/node_modules/undici/lib/fetch/index.js b/g4f/Provider/npm/node_modules/undici/lib/fetch/index.js
deleted file mode 100644
index 298b3ddb..00000000
--- a/g4f/Provider/npm/node_modules/undici/lib/fetch/index.js
+++ /dev/null
@@ -1,2145 +0,0 @@
-// https://github.com/Ethan-Arrowood/undici-fetch
-
-'use strict'
-
-const {
- Response,
- makeNetworkError,
- makeAppropriateNetworkError,
- filterResponse,
- makeResponse
-} = require('./response')
-const { Headers } = require('./headers')
-const { Request, makeRequest } = require('./request')
-const zlib = require('zlib')
-const {
- bytesMatch,
- makePolicyContainer,
- clonePolicyContainer,
- requestBadPort,
- TAOCheck,
- appendRequestOriginHeader,
- responseLocationURL,
- requestCurrentURL,
- setRequestReferrerPolicyOnRedirect,
- tryUpgradeRequestToAPotentiallyTrustworthyURL,
- createOpaqueTimingInfo,
- appendFetchMetadata,
- corsCheck,
- crossOriginResourcePolicyCheck,
- determineRequestsReferrer,
- coarsenedSharedCurrentTime,
- createDeferredPromise,
- isBlobLike,
- sameOrigin,
- isCancelled,
- isAborted,
- isErrorLike,
- fullyReadBody,
- readableStreamClose,
- isomorphicEncode,
- urlIsLocal,
- urlIsHttpHttpsScheme,
- urlHasHttpsScheme
-} = require('./util')
-const { kState, kHeaders, kGuard, kRealm } = require('./symbols')
-const assert = require('assert')
-const { safelyExtractBody } = require('./body')
-const {
- redirectStatusSet,
- nullBodyStatus,
- safeMethodsSet,
- requestBodyHeader,
- subresourceSet,
- DOMException
-} = require('./constants')
-const { kHeadersList } = require('../core/symbols')
-const EE = require('events')
-const { Readable, pipeline } = require('stream')
-const { addAbortListener, isErrored, isReadable, nodeMajor, nodeMinor } = require('../core/util')
-const { dataURLProcessor, serializeAMimeType } = require('./dataURL')
-const { TransformStream } = require('stream/web')
-const { getGlobalDispatcher } = require('../global')
-const { webidl } = require('./webidl')
-const { STATUS_CODES } = require('http')
-const GET_OR_HEAD = ['GET', 'HEAD']
-
-/** @type {import('buffer').resolveObjectURL} */
-let resolveObjectURL
-let ReadableStream = globalThis.ReadableStream
-
-class Fetch extends EE {
- constructor (dispatcher) {
- super()
-
- this.dispatcher = dispatcher
- this.connection = null
- this.dump = false
- this.state = 'ongoing'
- // 2 terminated listeners get added per request,
- // but only 1 gets removed. If there are 20 redirects,
- // 21 listeners will be added.
- // See https://github.com/nodejs/undici/issues/1711
- // TODO (fix): Find and fix root cause for leaked listener.
- this.setMaxListeners(21)
- }
-
- terminate (reason) {
- if (this.state !== 'ongoing') {
- return
- }
-
- this.state = 'terminated'
- this.connection?.destroy(reason)
- this.emit('terminated', reason)
- }
-
- // https://fetch.spec.whatwg.org/#fetch-controller-abort
- abort (error) {
- if (this.state !== 'ongoing') {
- return
- }
-
- // 1. Set controller’s state to "aborted".
- this.state = 'aborted'
-
- // 2. Let fallbackError be an "AbortError" DOMException.
- // 3. Set error to fallbackError if it is not given.
- if (!error) {
- error = new DOMException('The operation was aborted.', 'AbortError')
- }
-
- // 4. Let serializedError be StructuredSerialize(error).
- // If that threw an exception, catch it, and let
- // serializedError be StructuredSerialize(fallbackError).
-
- // 5. Set controller’s serialized abort reason to serializedError.
- this.serializedAbortReason = error
-
- this.connection?.destroy(error)
- this.emit('terminated', error)
- }
-}
-
-// https://fetch.spec.whatwg.org/#fetch-method
-function fetch (input, init = {}) {
- webidl.argumentLengthCheck(arguments, 1, { header: 'globalThis.fetch' })
-
- // 1. Let p be a new promise.
- const p = createDeferredPromise()
-
- // 2. Let requestObject be the result of invoking the initial value of
- // Request as constructor with input and init as arguments. If this throws
- // an exception, reject p with it and return p.
- let requestObject
-
- try {
- requestObject = new Request(input, init)
- } catch (e) {
- p.reject(e)
- return p.promise
- }
-
- // 3. Let request be requestObject’s request.
- const request = requestObject[kState]
-
- // 4. If requestObject’s signal’s aborted flag is set, then:
- if (requestObject.signal.aborted) {
- // 1. Abort the fetch() call with p, request, null, and
- // requestObject’s signal’s abort reason.
- abortFetch(p, request, null, requestObject.signal.reason)
-
- // 2. Return p.
- return p.promise
- }
-
- // 5. Let globalObject be request’s client’s global object.
- const globalObject = request.client.globalObject
-
- // 6. If globalObject is a ServiceWorkerGlobalScope object, then set
- // request’s service-workers mode to "none".
- if (globalObject?.constructor?.name === 'ServiceWorkerGlobalScope') {
- request.serviceWorkers = 'none'
- }
-
- // 7. Let responseObject be null.
- let responseObject = null
-
- // 8. Let relevantRealm be this’s relevant Realm.
- const relevantRealm = null
-
- // 9. Let locallyAborted be false.
- let locallyAborted = false
-
- // 10. Let controller be null.
- let controller = null
-
- // 11. Add the following abort steps to requestObject’s signal:
- addAbortListener(
- requestObject.signal,
- () => {
- // 1. Set locallyAborted to true.
- locallyAborted = true
-
- // 2. Assert: controller is non-null.
- assert(controller != null)
-
- // 3. Abort controller with requestObject’s signal’s abort reason.
- controller.abort(requestObject.signal.reason)
-
- // 4. Abort the fetch() call with p, request, responseObject,
- // and requestObject’s signal’s abort reason.
- abortFetch(p, request, responseObject, requestObject.signal.reason)
- }
- )
-
- // 12. Let handleFetchDone given response response be to finalize and
- // report timing with response, globalObject, and "fetch".
- const handleFetchDone = (response) =>
- finalizeAndReportTiming(response, 'fetch')
-
- // 13. Set controller to the result of calling fetch given request,
- // with processResponseEndOfBody set to handleFetchDone, and processResponse
- // given response being these substeps:
-
- const processResponse = (response) => {
- // 1. If locallyAborted is true, terminate these substeps.
- if (locallyAborted) {
- return Promise.resolve()
- }
-
- // 2. If response’s aborted flag is set, then:
- if (response.aborted) {
- // 1. Let deserializedError be the result of deserialize a serialized
- // abort reason given controller’s serialized abort reason and
- // relevantRealm.
-
- // 2. Abort the fetch() call with p, request, responseObject, and
- // deserializedError.
-
- abortFetch(p, request, responseObject, controller.serializedAbortReason)
- return Promise.resolve()
- }
-
- // 3. If response is a network error, then reject p with a TypeError
- // and terminate these substeps.
- if (response.type === 'error') {
- p.reject(
- Object.assign(new TypeError('fetch failed'), { cause: response.error })
- )
- return Promise.resolve()
- }
-
- // 4. Set responseObject to the result of creating a Response object,
- // given response, "immutable", and relevantRealm.
- responseObject = new Response()
- responseObject[kState] = response
- responseObject[kRealm] = relevantRealm
- responseObject[kHeaders][kHeadersList] = response.headersList
- responseObject[kHeaders][kGuard] = 'immutable'
- responseObject[kHeaders][kRealm] = relevantRealm
-
- // 5. Resolve p with responseObject.
- p.resolve(responseObject)
- }
-
- controller = fetching({
- request,
- processResponseEndOfBody: handleFetchDone,
- processResponse,
- dispatcher: init.dispatcher ?? getGlobalDispatcher() // undici
- })
-
- // 14. Return p.
- return p.promise
-}
-
-// https://fetch.spec.whatwg.org/#finalize-and-report-timing
-function finalizeAndReportTiming (response, initiatorType = 'other') {
- // 1. If response is an aborted network error, then return.
- if (response.type === 'error' && response.aborted) {
- return
- }
-
- // 2. If response’s URL list is null or empty, then return.
- if (!response.urlList?.length) {
- return
- }
-
- // 3. Let originalURL be response’s URL list[0].
- const originalURL = response.urlList[0]
-
- // 4. Let timingInfo be response’s timing info.
- let timingInfo = response.timingInfo
-
- // 5. Let cacheState be response’s cache state.
- let cacheState = response.cacheState
-
- // 6. If originalURL’s scheme is not an HTTP(S) scheme, then return.
- if (!urlIsHttpHttpsScheme(originalURL)) {
- return
- }
-
- // 7. If timingInfo is null, then return.
- if (timingInfo === null) {
- return
- }
-
- // 8. If response’s timing allow passed flag is not set, then:
- if (!timingInfo.timingAllowPassed) {
- // 1. Set timingInfo to a the result of creating an opaque timing info for timingInfo.
- timingInfo = createOpaqueTimingInfo({
- startTime: timingInfo.startTime
- })
-
- // 2. Set cacheState to the empty string.
- cacheState = ''
- }
-
- // 9. Set timingInfo’s end time to the coarsened shared current time
- // given global’s relevant settings object’s cross-origin isolated
- // capability.
- // TODO: given global’s relevant settings object’s cross-origin isolated
- // capability?
- timingInfo.endTime = coarsenedSharedCurrentTime()
-
- // 10. Set response’s timing info to timingInfo.
- response.timingInfo = timingInfo
-
- // 11. Mark resource timing for timingInfo, originalURL, initiatorType,
- // global, and cacheState.
- markResourceTiming(
- timingInfo,
- originalURL,
- initiatorType,
- globalThis,
- cacheState
- )
-}
-
-// https://w3c.github.io/resource-timing/#dfn-mark-resource-timing
-function markResourceTiming (timingInfo, originalURL, initiatorType, globalThis, cacheState) {
- if (nodeMajor > 18 || (nodeMajor === 18 && nodeMinor >= 2)) {
- performance.markResourceTiming(timingInfo, originalURL.href, initiatorType, globalThis, cacheState)
- }
-}
-
-// https://fetch.spec.whatwg.org/#abort-fetch
-function abortFetch (p, request, responseObject, error) {
- // Note: AbortSignal.reason was added in node v17.2.0
- // which would give us an undefined error to reject with.
- // Remove this once node v16 is no longer supported.
- if (!error) {
- error = new DOMException('The operation was aborted.', 'AbortError')
- }
-
- // 1. Reject promise with error.
- p.reject(error)
-
- // 2. If request’s body is not null and is readable, then cancel request’s
- // body with error.
- if (request.body != null && isReadable(request.body?.stream)) {
- request.body.stream.cancel(error).catch((err) => {
- if (err.code === 'ERR_INVALID_STATE') {
- // Node bug?
- return
- }
- throw err
- })
- }
-
- // 3. If responseObject is null, then return.
- if (responseObject == null) {
- return
- }
-
- // 4. Let response be responseObject’s response.
- const response = responseObject[kState]
-
- // 5. If response’s body is not null and is readable, then error response’s
- // body with error.
- if (response.body != null && isReadable(response.body?.stream)) {
- response.body.stream.cancel(error).catch((err) => {
- if (err.code === 'ERR_INVALID_STATE') {
- // Node bug?
- return
- }
- throw err
- })
- }
-}
-
-// https://fetch.spec.whatwg.org/#fetching
-function fetching ({
- request,
- processRequestBodyChunkLength,
- processRequestEndOfBody,
- processResponse,
- processResponseEndOfBody,
- processResponseConsumeBody,
- useParallelQueue = false,
- dispatcher // undici
-}) {
- // 1. Let taskDestination be null.
- let taskDestination = null
-
- // 2. Let crossOriginIsolatedCapability be false.
- let crossOriginIsolatedCapability = false
-
- // 3. If request’s client is non-null, then:
- if (request.client != null) {
- // 1. Set taskDestination to request’s client’s global object.
- taskDestination = request.client.globalObject
-
- // 2. Set crossOriginIsolatedCapability to request’s client’s cross-origin
- // isolated capability.
- crossOriginIsolatedCapability =
- request.client.crossOriginIsolatedCapability
- }
-
- // 4. If useParallelQueue is true, then set taskDestination to the result of
- // starting a new parallel queue.
- // TODO
-
- // 5. Let timingInfo be a new fetch timing info whose start time and
- // post-redirect start time are the coarsened shared current time given
- // crossOriginIsolatedCapability.
- const currenTime = coarsenedSharedCurrentTime(crossOriginIsolatedCapability)
- const timingInfo = createOpaqueTimingInfo({
- startTime: currenTime
- })
-
- // 6. Let fetchParams be a new fetch params whose
- // request is request,
- // timing info is timingInfo,
- // process request body chunk length is processRequestBodyChunkLength,
- // process request end-of-body is processRequestEndOfBody,
- // process response is processResponse,
- // process response consume body is processResponseConsumeBody,
- // process response end-of-body is processResponseEndOfBody,
- // task destination is taskDestination,
- // and cross-origin isolated capability is crossOriginIsolatedCapability.
- const fetchParams = {
- controller: new Fetch(dispatcher),
- request,
- timingInfo,
- processRequestBodyChunkLength,
- processRequestEndOfBody,
- processResponse,
- processResponseConsumeBody,
- processResponseEndOfBody,
- taskDestination,
- crossOriginIsolatedCapability
- }
-
- // 7. If request’s body is a byte sequence, then set request’s body to
- // request’s body as a body.
- // NOTE: Since fetching is only called from fetch, body should already be
- // extracted.
- assert(!request.body || request.body.stream)
-
- // 8. If request’s window is "client", then set request’s window to request’s
- // client, if request’s client’s global object is a Window object; otherwise
- // "no-window".
- if (request.window === 'client') {
- // TODO: What if request.client is null?
- request.window =
- request.client?.globalObject?.constructor?.name === 'Window'
- ? request.client
- : 'no-window'
- }
-
- // 9. If request’s origin is "client", then set request’s origin to request’s
- // client’s origin.
- if (request.origin === 'client') {
- // TODO: What if request.client is null?
- request.origin = request.client?.origin
- }
-
- // 10. If all of the following conditions are true:
- // TODO
-
- // 11. If request’s policy container is "client", then:
- if (request.policyContainer === 'client') {
- // 1. If request’s client is non-null, then set request’s policy
- // container to a clone of request’s client’s policy container. [HTML]
- if (request.client != null) {
- request.policyContainer = clonePolicyContainer(
- request.client.policyContainer
- )
- } else {
- // 2. Otherwise, set request’s policy container to a new policy
- // container.
- request.policyContainer = makePolicyContainer()
- }
- }
-
- // 12. If request’s header list does not contain `Accept`, then:
- if (!request.headersList.contains('accept')) {
- // 1. Let value be `*/*`.
- const value = '*/*'
-
- // 2. A user agent should set value to the first matching statement, if
- // any, switching on request’s destination:
- // "document"
- // "frame"
- // "iframe"
- // `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8`
- // "image"
- // `image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5`
- // "style"
- // `text/css,*/*;q=0.1`
- // TODO
-
- // 3. Append `Accept`/value to request’s header list.
- request.headersList.append('accept', value)
- }
-
- // 13. If request’s header list does not contain `Accept-Language`, then
- // user agents should append `Accept-Language`/an appropriate value to
- // request’s header list.
- if (!request.headersList.contains('accept-language')) {
- request.headersList.append('accept-language', '*')
- }
-
- // 14. If request’s priority is null, then use request’s initiator and
- // destination appropriately in setting request’s priority to a
- // user-agent-defined object.
- if (request.priority === null) {
- // TODO
- }
-
- // 15. If request is a subresource request, then:
- if (subresourceSet.has(request.destination)) {
- // TODO
- }
-
- // 16. Run main fetch given fetchParams.
- mainFetch(fetchParams)
- .catch(err => {
- fetchParams.controller.terminate(err)
- })
-
- // 17. Return fetchParam's controller
- return fetchParams.controller
-}
-
-// https://fetch.spec.whatwg.org/#concept-main-fetch
-async function mainFetch (fetchParams, recursive = false) {
- // 1. Let request be fetchParams’s request.
- const request = fetchParams.request
-
- // 2. Let response be null.
- let response = null
-
- // 3. If request’s local-URLs-only flag is set and request’s current URL is
- // not local, then set response to a network error.
- if (request.localURLsOnly && !urlIsLocal(requestCurrentURL(request))) {
- response = makeNetworkError('local URLs only')
- }
-
- // 4. Run report Content Security Policy violations for request.
- // TODO
-
- // 5. Upgrade request to a potentially trustworthy URL, if appropriate.
- tryUpgradeRequestToAPotentiallyTrustworthyURL(request)
-
- // 6. If should request be blocked due to a bad port, should fetching request
- // be blocked as mixed content, or should request be blocked by Content
- // Security Policy returns blocked, then set response to a network error.
- if (requestBadPort(request) === 'blocked') {
- response = makeNetworkError('bad port')
- }
- // TODO: should fetching request be blocked as mixed content?
- // TODO: should request be blocked by Content Security Policy?
-
- // 7. If request’s referrer policy is the empty string, then set request’s
- // referrer policy to request’s policy container’s referrer policy.
- if (request.referrerPolicy === '') {
- request.referrerPolicy = request.policyContainer.referrerPolicy
- }
-
- // 8. If request’s referrer is not "no-referrer", then set request’s
- // referrer to the result of invoking determine request’s referrer.
- if (request.referrer !== 'no-referrer') {
- request.referrer = determineRequestsReferrer(request)
- }
-
- // 9. Set request’s current URL’s scheme to "https" if all of the following
- // conditions are true:
- // - request’s current URL’s scheme is "http"
- // - request’s current URL’s host is a domain
- // - Matching request’s current URL’s host per Known HSTS Host Domain Name
- // Matching results in either a superdomain match with an asserted
- // includeSubDomains directive or a congruent match (with or without an
- // asserted includeSubDomains directive). [HSTS]
- // TODO
-
- // 10. If recursive is false, then run the remaining steps in parallel.
- // TODO
-
- // 11. If response is null, then set response to the result of running
- // the steps corresponding to the first matching statement:
- if (response === null) {
- response = await (async () => {
- const currentURL = requestCurrentURL(request)
-
- if (
- // - request’s current URL’s origin is same origin with request’s origin,
- // and request’s response tainting is "basic"
- (sameOrigin(currentURL, request.url) && request.responseTainting === 'basic') ||
- // request’s current URL’s scheme is "data"
- (currentURL.protocol === 'data:') ||
- // - request’s mode is "navigate" or "websocket"
- (request.mode === 'navigate' || request.mode === 'websocket')
- ) {
- // 1. Set request’s response tainting to "basic".
- request.responseTainting = 'basic'
-
- // 2. Return the result of running scheme fetch given fetchParams.
- return await schemeFetch(fetchParams)
- }
-
- // request’s mode is "same-origin"
- if (request.mode === 'same-origin') {
- // 1. Return a network error.
- return makeNetworkError('request mode cannot be "same-origin"')
- }
-
- // request’s mode is "no-cors"
- if (request.mode === 'no-cors') {
- // 1. If request’s redirect mode is not "follow", then return a network
- // error.
- if (request.redirect !== 'follow') {
- return makeNetworkError(
- 'redirect mode cannot be "follow" for "no-cors" request'
- )
- }
-
- // 2. Set request’s response tainting to "opaque".
- request.responseTainting = 'opaque'
-
- // 3. Return the result of running scheme fetch given fetchParams.
- return await schemeFetch(fetchParams)
- }
-
- // request’s current URL’s scheme is not an HTTP(S) scheme
- if (!urlIsHttpHttpsScheme(requestCurrentURL(request))) {
- // Return a network error.
- return makeNetworkError('URL scheme must be a HTTP(S) scheme')
- }
-
- // - request’s use-CORS-preflight flag is set
- // - request’s unsafe-request flag is set and either request’s method is
- // not a CORS-safelisted method or CORS-unsafe request-header names with
- // request’s header list is not empty
- // 1. Set request’s response tainting to "cors".
- // 2. Let corsWithPreflightResponse be the result of running HTTP fetch
- // given fetchParams and true.
- // 3. If corsWithPreflightResponse is a network error, then clear cache
- // entries using request.
- // 4. Return corsWithPreflightResponse.
- // TODO
-
- // Otherwise
- // 1. Set request’s response tainting to "cors".
- request.responseTainting = 'cors'
-
- // 2. Return the result of running HTTP fetch given fetchParams.
- return await httpFetch(fetchParams)
- })()
- }
-
- // 12. If recursive is true, then return response.
- if (recursive) {
- return response
- }
-
- // 13. If response is not a network error and response is not a filtered
- // response, then:
- if (response.status !== 0 && !response.internalResponse) {
- // If request’s response tainting is "cors", then:
- if (request.responseTainting === 'cors') {
- // 1. Let headerNames be the result of extracting header list values
- // given `Access-Control-Expose-Headers` and response’s header list.
- // TODO
- // 2. If request’s credentials mode is not "include" and headerNames
- // contains `*`, then set response’s CORS-exposed header-name list to
- // all unique header names in response’s header list.
- // TODO
- // 3. Otherwise, if headerNames is not null or failure, then set
- // response’s CORS-exposed header-name list to headerNames.
- // TODO
- }
-
- // Set response to the following filtered response with response as its
- // internal response, depending on request’s response tainting:
- if (request.responseTainting === 'basic') {
- response = filterResponse(response, 'basic')
- } else if (request.responseTainting === 'cors') {
- response = filterResponse(response, 'cors')
- } else if (request.responseTainting === 'opaque') {
- response = filterResponse(response, 'opaque')
- } else {
- assert(false)
- }
- }
-
- // 14. Let internalResponse be response, if response is a network error,
- // and response’s internal response otherwise.
- let internalResponse =
- response.status === 0 ? response : response.internalResponse
-
- // 15. If internalResponse’s URL list is empty, then set it to a clone of
- // request’s URL list.
- if (internalResponse.urlList.length === 0) {
- internalResponse.urlList.push(...request.urlList)
- }
-
- // 16. If request’s timing allow failed flag is unset, then set
- // internalResponse’s timing allow passed flag.
- if (!request.timingAllowFailed) {
- response.timingAllowPassed = true
- }
-
- // 17. If response is not a network error and any of the following returns
- // blocked
- // - should internalResponse to request be blocked as mixed content
- // - should internalResponse to request be blocked by Content Security Policy
- // - should internalResponse to request be blocked due to its MIME type
- // - should internalResponse to request be blocked due to nosniff
- // TODO
-
- // 18. If response’s type is "opaque", internalResponse’s status is 206,
- // internalResponse’s range-requested flag is set, and request’s header
- // list does not contain `Range`, then set response and internalResponse
- // to a network error.
- if (
- response.type === 'opaque' &&
- internalResponse.status === 206 &&
- internalResponse.rangeRequested &&
- !request.headers.contains('range')
- ) {
- response = internalResponse = makeNetworkError()
- }
-
- // 19. If response is not a network error and either request’s method is
- // `HEAD` or `CONNECT`, or internalResponse’s status is a null body status,
- // set internalResponse’s body to null and disregard any enqueuing toward
- // it (if any).
- if (
- response.status !== 0 &&
- (request.method === 'HEAD' ||
- request.method === 'CONNECT' ||
- nullBodyStatus.includes(internalResponse.status))
- ) {
- internalResponse.body = null
- fetchParams.controller.dump = true
- }
-
- // 20. If request’s integrity metadata is not the empty string, then:
- if (request.integrity) {
- // 1. Let processBodyError be this step: run fetch finale given fetchParams
- // and a network error.
- const processBodyError = (reason) =>
- fetchFinale(fetchParams, makeNetworkError(reason))
-
- // 2. If request’s response tainting is "opaque", or response’s body is null,
- // then run processBodyError and abort these steps.
- if (request.responseTainting === 'opaque' || response.body == null) {
- processBodyError(response.error)
- return
- }
-
- // 3. Let processBody given bytes be these steps:
- const processBody = (bytes) => {
- // 1. If bytes do not match request’s integrity metadata,
- // then run processBodyError and abort these steps. [SRI]
- if (!bytesMatch(bytes, request.integrity)) {
- processBodyError('integrity mismatch')
- return
- }
-
- // 2. Set response’s body to bytes as a body.
- response.body = safelyExtractBody(bytes)[0]
-
- // 3. Run fetch finale given fetchParams and response.
- fetchFinale(fetchParams, response)
- }
-
- // 4. Fully read response’s body given processBody and processBodyError.
- await fullyReadBody(response.body, processBody, processBodyError)
- } else {
- // 21. Otherwise, run fetch finale given fetchParams and response.
- fetchFinale(fetchParams, response)
- }
-}
-
-// https://fetch.spec.whatwg.org/#concept-scheme-fetch
-// given a fetch params fetchParams
-function schemeFetch (fetchParams) {
- // Note: since the connection is destroyed on redirect, which sets fetchParams to a
- // cancelled state, we do not want this condition to trigger *unless* there have been
- // no redirects. See https://github.com/nodejs/undici/issues/1776
- // 1. If fetchParams is canceled, then return the appropriate network error for fetchParams.
- if (isCancelled(fetchParams) && fetchParams.request.redirectCount === 0) {
- return Promise.resolve(makeAppropriateNetworkError(fetchParams))
- }
-
- // 2. Let request be fetchParams’s request.
- const { request } = fetchParams
-
- const { protocol: scheme } = requestCurrentURL(request)
-
- // 3. Switch on request’s current URL’s scheme and run the associated steps:
- switch (scheme) {
- case 'about:': {
- // If request’s current URL’s path is the string "blank", then return a new response
- // whose status message is `OK`, header list is « (`Content-Type`, `text/html;charset=utf-8`) »,
- // and body is the empty byte sequence as a body.
-
- // Otherwise, return a network error.
- return Promise.resolve(makeNetworkError('about scheme is not supported'))
- }
- case 'blob:': {
- if (!resolveObjectURL) {
- resolveObjectURL = require('buffer').resolveObjectURL
- }
-
- // 1. Let blobURLEntry be request’s current URL’s blob URL entry.
- const blobURLEntry = requestCurrentURL(request)
-
- // https://github.com/web-platform-tests/wpt/blob/7b0ebaccc62b566a1965396e5be7bb2bc06f841f/FileAPI/url/resources/fetch-tests.js#L52-L56
- // Buffer.resolveObjectURL does not ignore URL queries.
- if (blobURLEntry.search.length !== 0) {
- return Promise.resolve(makeNetworkError('NetworkError when attempting to fetch resource.'))
- }
-
- const blobURLEntryObject = resolveObjectURL(blobURLEntry.toString())
-
- // 2. If request’s method is not `GET`, blobURLEntry is null, or blobURLEntry’s
- // object is not a Blob object, then return a network error.
- if (request.method !== 'GET' || !isBlobLike(blobURLEntryObject)) {
- return Promise.resolve(makeNetworkError('invalid method'))
- }
-
- // 3. Let bodyWithType be the result of safely extracting blobURLEntry’s object.
- const bodyWithType = safelyExtractBody(blobURLEntryObject)
-
- // 4. Let body be bodyWithType’s body.
- const body = bodyWithType[0]
-
- // 5. Let length be body’s length, serialized and isomorphic encoded.
- const length = isomorphicEncode(`${body.length}`)
-
- // 6. Let type be bodyWithType’s type if it is non-null; otherwise the empty byte sequence.
- const type = bodyWithType[1] ?? ''
-
- // 7. Return a new response whose status message is `OK`, header list is
- // « (`Content-Length`, length), (`Content-Type`, type) », and body is body.
- const response = makeResponse({
- statusText: 'OK',
- headersList: [
- ['content-length', { name: 'Content-Length', value: length }],
- ['content-type', { name: 'Content-Type', value: type }]
- ]
- })
-
- response.body = body
-
- return Promise.resolve(response)
- }
- case 'data:': {
- // 1. Let dataURLStruct be the result of running the
- // data: URL processor on request’s current URL.
- const currentURL = requestCurrentURL(request)
- const dataURLStruct = dataURLProcessor(currentURL)
-
- // 2. If dataURLStruct is failure, then return a
- // network error.
- if (dataURLStruct === 'failure') {
- return Promise.resolve(makeNetworkError('failed to fetch the data URL'))
- }
-
- // 3. Let mimeType be dataURLStruct’s MIME type, serialized.
- const mimeType = serializeAMimeType(dataURLStruct.mimeType)
-
- // 4. Return a response whose status message is `OK`,
- // header list is « (`Content-Type`, mimeType) »,
- // and body is dataURLStruct’s body as a body.
- return Promise.resolve(makeResponse({
- statusText: 'OK',
- headersList: [
- ['content-type', { name: 'Content-Type', value: mimeType }]
- ],
- body: safelyExtractBody(dataURLStruct.body)[0]
- }))
- }
- case 'file:': {
- // For now, unfortunate as it is, file URLs are left as an exercise for the reader.
- // When in doubt, return a network error.
- return Promise.resolve(makeNetworkError('not implemented... yet...'))
- }
- case 'http:':
- case 'https:': {
- // Return the result of running HTTP fetch given fetchParams.
-
- return httpFetch(fetchParams)
- .catch((err) => makeNetworkError(err))
- }
- default: {
- return Promise.resolve(makeNetworkError('unknown scheme'))
- }
- }
-}
-
-// https://fetch.spec.whatwg.org/#finalize-response
-function finalizeResponse (fetchParams, response) {
- // 1. Set fetchParams’s request’s done flag.
- fetchParams.request.done = true
-
- // 2, If fetchParams’s process response done is not null, then queue a fetch
- // task to run fetchParams’s process response done given response, with
- // fetchParams’s task destination.
- if (fetchParams.processResponseDone != null) {
- queueMicrotask(() => fetchParams.processResponseDone(response))
- }
-}
-
-// https://fetch.spec.whatwg.org/#fetch-finale
-function fetchFinale (fetchParams, response) {
- // 1. If response is a network error, then:
- if (response.type === 'error') {
- // 1. Set response’s URL list to « fetchParams’s request’s URL list[0] ».
- response.urlList = [fetchParams.request.urlList[0]]
-
- // 2. Set response’s timing info to the result of creating an opaque timing
- // info for fetchParams’s timing info.
- response.timingInfo = createOpaqueTimingInfo({
- startTime: fetchParams.timingInfo.startTime
- })
- }
-
- // 2. Let processResponseEndOfBody be the following steps:
- const processResponseEndOfBody = () => {
- // 1. Set fetchParams’s request’s done flag.
- fetchParams.request.done = true
-
- // If fetchParams’s process response end-of-body is not null,
- // then queue a fetch task to run fetchParams’s process response
- // end-of-body given response with fetchParams’s task destination.
- if (fetchParams.processResponseEndOfBody != null) {
- queueMicrotask(() => fetchParams.processResponseEndOfBody(response))
- }
- }
-
- // 3. If fetchParams’s process response is non-null, then queue a fetch task
- // to run fetchParams’s process response given response, with fetchParams’s
- // task destination.
- if (fetchParams.processResponse != null) {
- queueMicrotask(() => fetchParams.processResponse(response))
- }
-
- // 4. If response’s body is null, then run processResponseEndOfBody.
- if (response.body == null) {
- processResponseEndOfBody()
- } else {
- // 5. Otherwise:
-
- // 1. Let transformStream be a new a TransformStream.
-
- // 2. Let identityTransformAlgorithm be an algorithm which, given chunk,
- // enqueues chunk in transformStream.
- const identityTransformAlgorithm = (chunk, controller) => {
- controller.enqueue(chunk)
- }
-
- // 3. Set up transformStream with transformAlgorithm set to identityTransformAlgorithm
- // and flushAlgorithm set to processResponseEndOfBody.
- const transformStream = new TransformStream({
- start () {},
- transform: identityTransformAlgorithm,
- flush: processResponseEndOfBody
- }, {
- size () {
- return 1
- }
- }, {
- size () {
- return 1
- }
- })
-
- // 4. Set response’s body to the result of piping response’s body through transformStream.
- response.body = { stream: response.body.stream.pipeThrough(transformStream) }
- }
-
- // 6. If fetchParams’s process response consume body is non-null, then:
- if (fetchParams.processResponseConsumeBody != null) {
- // 1. Let processBody given nullOrBytes be this step: run fetchParams’s
- // process response consume body given response and nullOrBytes.
- const processBody = (nullOrBytes) => fetchParams.processResponseConsumeBody(response, nullOrBytes)
-
- // 2. Let processBodyError be this step: run fetchParams’s process
- // response consume body given response and failure.
- const processBodyError = (failure) => fetchParams.processResponseConsumeBody(response, failure)
-
- // 3. If response’s body is null, then queue a fetch task to run processBody
- // given null, with fetchParams’s task destination.
- if (response.body == null) {
- queueMicrotask(() => processBody(null))
- } else {
- // 4. Otherwise, fully read response’s body given processBody, processBodyError,
- // and fetchParams’s task destination.
- return fullyReadBody(response.body, processBody, processBodyError)
- }
- return Promise.resolve()
- }
-}
-
-// https://fetch.spec.whatwg.org/#http-fetch
-async function httpFetch (fetchParams) {
- // 1. Let request be fetchParams’s request.
- const request = fetchParams.request
-
- // 2. Let response be null.
- let response = null
-
- // 3. Let actualResponse be null.
- let actualResponse = null
-
- // 4. Let timingInfo be fetchParams’s timing info.
- const timingInfo = fetchParams.timingInfo
-
- // 5. If request’s service-workers mode is "all", then:
- if (request.serviceWorkers === 'all') {
- // TODO
- }
-
- // 6. If response is null, then:
- if (response === null) {
- // 1. If makeCORSPreflight is true and one of these conditions is true:
- // TODO
-
- // 2. If request’s redirect mode is "follow", then set request’s
- // service-workers mode to "none".
- if (request.redirect === 'follow') {
- request.serviceWorkers = 'none'
- }
-
- // 3. Set response and actualResponse to the result of running
- // HTTP-network-or-cache fetch given fetchParams.
- actualResponse = response = await httpNetworkOrCacheFetch(fetchParams)
-
- // 4. If request’s response tainting is "cors" and a CORS check
- // for request and response returns failure, then return a network error.
- if (
- request.responseTainting === 'cors' &&
- corsCheck(request, response) === 'failure'
- ) {
- return makeNetworkError('cors failure')
- }
-
- // 5. If the TAO check for request and response returns failure, then set
- // request’s timing allow failed flag.
- if (TAOCheck(request, response) === 'failure') {
- request.timingAllowFailed = true
- }
- }
-
- // 7. If either request’s response tainting or response’s type
- // is "opaque", and the cross-origin resource policy check with
- // request’s origin, request’s client, request’s destination,
- // and actualResponse returns blocked, then return a network error.
- if (
- (request.responseTainting === 'opaque' || response.type === 'opaque') &&
- crossOriginResourcePolicyCheck(
- request.origin,
- request.client,
- request.destination,
- actualResponse
- ) === 'blocked'
- ) {
- return makeNetworkError('blocked')
- }
-
- // 8. If actualResponse’s status is a redirect status, then:
- if (redirectStatusSet.has(actualResponse.status)) {
- // 1. If actualResponse’s status is not 303, request’s body is not null,
- // and the connection uses HTTP/2, then user agents may, and are even
- // encouraged to, transmit an RST_STREAM frame.
- // See, https://github.com/whatwg/fetch/issues/1288
- if (request.redirect !== 'manual') {
- fetchParams.controller.connection.destroy()
- }
-
- // 2. Switch on request’s redirect mode:
- if (request.redirect === 'error') {
- // Set response to a network error.
- response = makeNetworkError('unexpected redirect')
- } else if (request.redirect === 'manual') {
- // Set response to an opaque-redirect filtered response whose internal
- // response is actualResponse.
- // NOTE(spec): On the web this would return an `opaqueredirect` response,
- // but that doesn't make sense server side.
- // See https://github.com/nodejs/undici/issues/1193.
- response = actualResponse
- } else if (request.redirect === 'follow') {
- // Set response to the result of running HTTP-redirect fetch given
- // fetchParams and response.
- response = await httpRedirectFetch(fetchParams, response)
- } else {
- assert(false)
- }
- }
-
- // 9. Set response’s timing info to timingInfo.
- response.timingInfo = timingInfo
-
- // 10. Return response.
- return response
-}
-
-// https://fetch.spec.whatwg.org/#http-redirect-fetch
-function httpRedirectFetch (fetchParams, response) {
- // 1. Let request be fetchParams’s request.
- const request = fetchParams.request
-
- // 2. Let actualResponse be response, if response is not a filtered response,
- // and response’s internal response otherwise.
- const actualResponse = response.internalResponse
- ? response.internalResponse
- : response
-
- // 3. Let locationURL be actualResponse’s location URL given request’s current
- // URL’s fragment.
- let locationURL
-
- try {
- locationURL = responseLocationURL(
- actualResponse,
- requestCurrentURL(request).hash
- )
-
- // 4. If locationURL is null, then return response.
- if (locationURL == null) {
- return response
- }
- } catch (err) {
- // 5. If locationURL is failure, then return a network error.
- return Promise.resolve(makeNetworkError(err))
- }
-
- // 6. If locationURL’s scheme is not an HTTP(S) scheme, then return a network
- // error.
- if (!urlIsHttpHttpsScheme(locationURL)) {
- return Promise.resolve(makeNetworkError('URL scheme must be a HTTP(S) scheme'))
- }
-
- // 7. If request’s redirect count is 20, then return a network error.
- if (request.redirectCount === 20) {
- return Promise.resolve(makeNetworkError('redirect count exceeded'))
- }
-
- // 8. Increase request’s redirect count by 1.
- request.redirectCount += 1
-
- // 9. If request’s mode is "cors", locationURL includes credentials, and
- // request’s origin is not same origin with locationURL’s origin, then return
- // a network error.
- if (
- request.mode === 'cors' &&
- (locationURL.username || locationURL.password) &&
- !sameOrigin(request, locationURL)
- ) {
- return Promise.resolve(makeNetworkError('cross origin not allowed for request mode "cors"'))
- }
-
- // 10. If request’s response tainting is "cors" and locationURL includes
- // credentials, then return a network error.
- if (
- request.responseTainting === 'cors' &&
- (locationURL.username || locationURL.password)
- ) {
- return Promise.resolve(makeNetworkError(
- 'URL cannot contain credentials for request mode "cors"'
- ))
- }
-
- // 11. If actualResponse’s status is not 303, request’s body is non-null,
- // and request’s body’s source is null, then return a network error.
- if (
- actualResponse.status !== 303 &&
- request.body != null &&
- request.body.source == null
- ) {
- return Promise.resolve(makeNetworkError())
- }
-
- // 12. If one of the following is true
- // - actualResponse’s status is 301 or 302 and request’s method is `POST`
- // - actualResponse’s status is 303 and request’s method is not `GET` or `HEAD`
- if (
- ([301, 302].includes(actualResponse.status) && request.method === 'POST') ||
- (actualResponse.status === 303 &&
- !GET_OR_HEAD.includes(request.method))
- ) {
- // then:
- // 1. Set request’s method to `GET` and request’s body to null.
- request.method = 'GET'
- request.body = null
-
- // 2. For each headerName of request-body-header name, delete headerName from
- // request’s header list.
- for (const headerName of requestBodyHeader) {
- request.headersList.delete(headerName)
- }
- }
-
- // 13. If request’s current URL’s origin is not same origin with locationURL’s
- // origin, then for each headerName of CORS non-wildcard request-header name,
- // delete headerName from request’s header list.
- if (!sameOrigin(requestCurrentURL(request), locationURL)) {
- // https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name
- request.headersList.delete('authorization')
-
- // "Cookie" and "Host" are forbidden request-headers, which undici doesn't implement.
- request.headersList.delete('cookie')
- request.headersList.delete('host')
- }
-
- // 14. If request’s body is non-null, then set request’s body to the first return
- // value of safely extracting request’s body’s source.
- if (request.body != null) {
- assert(request.body.source != null)
- request.body = safelyExtractBody(request.body.source)[0]
- }
-
- // 15. Let timingInfo be fetchParams’s timing info.
- const timingInfo = fetchParams.timingInfo
-
- // 16. Set timingInfo’s redirect end time and post-redirect start time to the
- // coarsened shared current time given fetchParams’s cross-origin isolated
- // capability.
- timingInfo.redirectEndTime = timingInfo.postRedirectStartTime =
- coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability)
-
- // 17. If timingInfo’s redirect start time is 0, then set timingInfo’s
- // redirect start time to timingInfo’s start time.
- if (timingInfo.redirectStartTime === 0) {
- timingInfo.redirectStartTime = timingInfo.startTime
- }
-
- // 18. Append locationURL to request’s URL list.
- request.urlList.push(locationURL)
-
- // 19. Invoke set request’s referrer policy on redirect on request and
- // actualResponse.
- setRequestReferrerPolicyOnRedirect(request, actualResponse)
-
- // 20. Return the result of running main fetch given fetchParams and true.
- return mainFetch(fetchParams, true)
-}
-
-// https://fetch.spec.whatwg.org/#http-network-or-cache-fetch
-async function httpNetworkOrCacheFetch (
- fetchParams,
- isAuthenticationFetch = false,
- isNewConnectionFetch = false
-) {
- // 1. Let request be fetchParams’s request.
- const request = fetchParams.request
-
- // 2. Let httpFetchParams be null.
- let httpFetchParams = null
-
- // 3. Let httpRequest be null.
- let httpRequest = null
-
- // 4. Let response be null.
- let response = null
-
- // 5. Let storedResponse be null.
- // TODO: cache
-
- // 6. Let httpCache be null.
- const httpCache = null
-
- // 7. Let the revalidatingFlag be unset.
- const revalidatingFlag = false
-
- // 8. Run these steps, but abort when the ongoing fetch is terminated:
-
- // 1. If request’s window is "no-window" and request’s redirect mode is
- // "error", then set httpFetchParams to fetchParams and httpRequest to
- // request.
- if (request.window === 'no-window' && request.redirect === 'error') {
- httpFetchParams = fetchParams
- httpRequest = request
- } else {
- // Otherwise:
-
- // 1. Set httpRequest to a clone of request.
- httpRequest = makeRequest(request)
-
- // 2. Set httpFetchParams to a copy of fetchParams.
- httpFetchParams = { ...fetchParams }
-
- // 3. Set httpFetchParams’s request to httpRequest.
- httpFetchParams.request = httpRequest
- }
-
- // 3. Let includeCredentials be true if one of
- const includeCredentials =
- request.credentials === 'include' ||
- (request.credentials === 'same-origin' &&
- request.responseTainting === 'basic')
-
- // 4. Let contentLength be httpRequest’s body’s length, if httpRequest’s
- // body is non-null; otherwise null.
- const contentLength = httpRequest.body ? httpRequest.body.length : null
-
- // 5. Let contentLengthHeaderValue be null.
- let contentLengthHeaderValue = null
-
- // 6. If httpRequest’s body is null and httpRequest’s method is `POST` or
- // `PUT`, then set contentLengthHeaderValue to `0`.
- if (
- httpRequest.body == null &&
- ['POST', 'PUT'].includes(httpRequest.method)
- ) {
- contentLengthHeaderValue = '0'
- }
-
- // 7. If contentLength is non-null, then set contentLengthHeaderValue to
- // contentLength, serialized and isomorphic encoded.
- if (contentLength != null) {
- contentLengthHeaderValue = isomorphicEncode(`${contentLength}`)
- }
-
- // 8. If contentLengthHeaderValue is non-null, then append
- // `Content-Length`/contentLengthHeaderValue to httpRequest’s header
- // list.
- if (contentLengthHeaderValue != null) {
- httpRequest.headersList.append('content-length', contentLengthHeaderValue)
- }
-
- // 9. If contentLengthHeaderValue is non-null, then append (`Content-Length`,
- // contentLengthHeaderValue) to httpRequest’s header list.
-
- // 10. If contentLength is non-null and httpRequest’s keepalive is true,
- // then:
- if (contentLength != null && httpRequest.keepalive) {
- // NOTE: keepalive is a noop outside of browser context.
- }
-
- // 11. If httpRequest’s referrer is a URL, then append
- // `Referer`/httpRequest’s referrer, serialized and isomorphic encoded,
- // to httpRequest’s header list.
- if (httpRequest.referrer instanceof URL) {
- httpRequest.headersList.append('referer', isomorphicEncode(httpRequest.referrer.href))
- }
-
- // 12. Append a request `Origin` header for httpRequest.
- appendRequestOriginHeader(httpRequest)
-
- // 13. Append the Fetch metadata headers for httpRequest. [FETCH-METADATA]
- appendFetchMetadata(httpRequest)
-
- // 14. If httpRequest’s header list does not contain `User-Agent`, then
- // user agents should append `User-Agent`/default `User-Agent` value to
- // httpRequest’s header list.
- if (!httpRequest.headersList.contains('user-agent')) {
- httpRequest.headersList.append('user-agent', typeof esbuildDetection === 'undefined' ? 'undici' : 'node')
- }
-
- // 15. If httpRequest’s cache mode is "default" and httpRequest’s header
- // list contains `If-Modified-Since`, `If-None-Match`,
- // `If-Unmodified-Since`, `If-Match`, or `If-Range`, then set
- // httpRequest’s cache mode to "no-store".
- if (
- httpRequest.cache === 'default' &&
- (httpRequest.headersList.contains('if-modified-since') ||
- httpRequest.headersList.contains('if-none-match') ||
- httpRequest.headersList.contains('if-unmodified-since') ||
- httpRequest.headersList.contains('if-match') ||
- httpRequest.headersList.contains('if-range'))
- ) {
- httpRequest.cache = 'no-store'
- }
-
- // 16. If httpRequest’s cache mode is "no-cache", httpRequest’s prevent
- // no-cache cache-control header modification flag is unset, and
- // httpRequest’s header list does not contain `Cache-Control`, then append
- // `Cache-Control`/`max-age=0` to httpRequest’s header list.
- if (
- httpRequest.cache === 'no-cache' &&
- !httpRequest.preventNoCacheCacheControlHeaderModification &&
- !httpRequest.headersList.contains('cache-control')
- ) {
- httpRequest.headersList.append('cache-control', 'max-age=0')
- }
-
- // 17. If httpRequest’s cache mode is "no-store" or "reload", then:
- if (httpRequest.cache === 'no-store' || httpRequest.cache === 'reload') {
- // 1. If httpRequest’s header list does not contain `Pragma`, then append
- // `Pragma`/`no-cache` to httpRequest’s header list.
- if (!httpRequest.headersList.contains('pragma')) {
- httpRequest.headersList.append('pragma', 'no-cache')
- }
-
- // 2. If httpRequest’s header list does not contain `Cache-Control`,
- // then append `Cache-Control`/`no-cache` to httpRequest’s header list.
- if (!httpRequest.headersList.contains('cache-control')) {
- httpRequest.headersList.append('cache-control', 'no-cache')
- }
- }
-
- // 18. If httpRequest’s header list contains `Range`, then append
- // `Accept-Encoding`/`identity` to httpRequest’s header list.
- if (httpRequest.headersList.contains('range')) {
- httpRequest.headersList.append('accept-encoding', 'identity')
- }
-
- // 19. Modify httpRequest’s header list per HTTP. Do not append a given
- // header if httpRequest’s header list contains that header’s name.
- // TODO: https://github.com/whatwg/fetch/issues/1285#issuecomment-896560129
- if (!httpRequest.headersList.contains('accept-encoding')) {
- if (urlHasHttpsScheme(requestCurrentURL(httpRequest))) {
- httpRequest.headersList.append('accept-encoding', 'br, gzip, deflate')
- } else {
- httpRequest.headersList.append('accept-encoding', 'gzip, deflate')
- }
- }
-
- httpRequest.headersList.delete('host')
-
- // 20. If includeCredentials is true, then:
- if (includeCredentials) {
- // 1. If the user agent is not configured to block cookies for httpRequest
- // (see section 7 of [COOKIES]), then:
- // TODO: credentials
- // 2. If httpRequest’s header list does not contain `Authorization`, then:
- // TODO: credentials
- }
-
- // 21. If there’s a proxy-authentication entry, use it as appropriate.
- // TODO: proxy-authentication
-
- // 22. Set httpCache to the result of determining the HTTP cache
- // partition, given httpRequest.
- // TODO: cache
-
- // 23. If httpCache is null, then set httpRequest’s cache mode to
- // "no-store".
- if (httpCache == null) {
- httpRequest.cache = 'no-store'
- }
-
- // 24. If httpRequest’s cache mode is neither "no-store" nor "reload",
- // then:
- if (httpRequest.mode !== 'no-store' && httpRequest.mode !== 'reload') {
- // TODO: cache
- }
-
- // 9. If aborted, then return the appropriate network error for fetchParams.
- // TODO
-
- // 10. If response is null, then:
- if (response == null) {
- // 1. If httpRequest’s cache mode is "only-if-cached", then return a
- // network error.
- if (httpRequest.mode === 'only-if-cached') {
- return makeNetworkError('only if cached')
- }
-
- // 2. Let forwardResponse be the result of running HTTP-network fetch
- // given httpFetchParams, includeCredentials, and isNewConnectionFetch.
- const forwardResponse = await httpNetworkFetch(
- httpFetchParams,
- includeCredentials,
- isNewConnectionFetch
- )
-
- // 3. If httpRequest’s method is unsafe and forwardResponse’s status is
- // in the range 200 to 399, inclusive, invalidate appropriate stored
- // responses in httpCache, as per the "Invalidation" chapter of HTTP
- // Caching, and set storedResponse to null. [HTTP-CACHING]
- if (
- !safeMethodsSet.has(httpRequest.method) &&
- forwardResponse.status >= 200 &&
- forwardResponse.status <= 399
- ) {
- // TODO: cache
- }
-
- // 4. If the revalidatingFlag is set and forwardResponse’s status is 304,
- // then:
- if (revalidatingFlag && forwardResponse.status === 304) {
- // TODO: cache
- }
-
- // 5. If response is null, then:
- if (response == null) {
- // 1. Set response to forwardResponse.
- response = forwardResponse
-
- // 2. Store httpRequest and forwardResponse in httpCache, as per the
- // "Storing Responses in Caches" chapter of HTTP Caching. [HTTP-CACHING]
- // TODO: cache
- }
- }
-
- // 11. Set response’s URL list to a clone of httpRequest’s URL list.
- response.urlList = [...httpRequest.urlList]
-
- // 12. If httpRequest’s header list contains `Range`, then set response’s
- // range-requested flag.
- if (httpRequest.headersList.contains('range')) {
- response.rangeRequested = true
- }
-
- // 13. Set response’s request-includes-credentials to includeCredentials.
- response.requestIncludesCredentials = includeCredentials
-
- // 14. If response’s status is 401, httpRequest’s response tainting is not
- // "cors", includeCredentials is true, and request’s window is an environment
- // settings object, then:
- // TODO
-
- // 15. If response’s status is 407, then:
- if (response.status === 407) {
- // 1. If request’s window is "no-window", then return a network error.
- if (request.window === 'no-window') {
- return makeNetworkError()
- }
-
- // 2. ???
-
- // 3. If fetchParams is canceled, then return the appropriate network error for fetchParams.
- if (isCancelled(fetchParams)) {
- return makeAppropriateNetworkError(fetchParams)
- }
-
- // 4. Prompt the end user as appropriate in request’s window and store
- // the result as a proxy-authentication entry. [HTTP-AUTH]
- // TODO: Invoke some kind of callback?
-
- // 5. Set response to the result of running HTTP-network-or-cache fetch given
- // fetchParams.
- // TODO
- return makeNetworkError('proxy authentication required')
- }
-
- // 16. If all of the following are true
- if (
- // response’s status is 421
- response.status === 421 &&
- // isNewConnectionFetch is false
- !isNewConnectionFetch &&
- // request’s body is null, or request’s body is non-null and request’s body’s source is non-null
- (request.body == null || request.body.source != null)
- ) {
- // then:
-
- // 1. If fetchParams is canceled, then return the appropriate network error for fetchParams.
- if (isCancelled(fetchParams)) {
- return makeAppropriateNetworkError(fetchParams)
- }
-
- // 2. Set response to the result of running HTTP-network-or-cache
- // fetch given fetchParams, isAuthenticationFetch, and true.
-
- // TODO (spec): The spec doesn't specify this but we need to cancel
- // the active response before we can start a new one.
- // https://github.com/whatwg/fetch/issues/1293
- fetchParams.controller.connection.destroy()
-
- response = await httpNetworkOrCacheFetch(
- fetchParams,
- isAuthenticationFetch,
- true
- )
- }
-
- // 17. If isAuthenticationFetch is true, then create an authentication entry
- if (isAuthenticationFetch) {
- // TODO
- }
-
- // 18. Return response.
- return response
-}
-
-// https://fetch.spec.whatwg.org/#http-network-fetch
-async function httpNetworkFetch (
- fetchParams,
- includeCredentials = false,
- forceNewConnection = false
-) {
- assert(!fetchParams.controller.connection || fetchParams.controller.connection.destroyed)
-
- fetchParams.controller.connection = {
- abort: null,
- destroyed: false,
- destroy (err) {
- if (!this.destroyed) {
- this.destroyed = true
- this.abort?.(err ?? new DOMException('The operation was aborted.', 'AbortError'))
- }
- }
- }
-
- // 1. Let request be fetchParams’s request.
- const request = fetchParams.request
-
- // 2. Let response be null.
- let response = null
-
- // 3. Let timingInfo be fetchParams’s timing info.
- const timingInfo = fetchParams.timingInfo
-
- // 4. Let httpCache be the result of determining the HTTP cache partition,
- // given request.
- // TODO: cache
- const httpCache = null
-
- // 5. If httpCache is null, then set request’s cache mode to "no-store".
- if (httpCache == null) {
- request.cache = 'no-store'
- }
-
- // 6. Let networkPartitionKey be the result of determining the network
- // partition key given request.
- // TODO
-
- // 7. Let newConnection be "yes" if forceNewConnection is true; otherwise
- // "no".
- const newConnection = forceNewConnection ? 'yes' : 'no' // eslint-disable-line no-unused-vars
-
- // 8. Switch on request’s mode:
- if (request.mode === 'websocket') {
- // Let connection be the result of obtaining a WebSocket connection,
- // given request’s current URL.
- // TODO
- } else {
- // Let connection be the result of obtaining a connection, given
- // networkPartitionKey, request’s current URL’s origin,
- // includeCredentials, and forceNewConnection.
- // TODO
- }
-
- // 9. Run these steps, but abort when the ongoing fetch is terminated:
-
- // 1. If connection is failure, then return a network error.
-
- // 2. Set timingInfo’s final connection timing info to the result of
- // calling clamp and coarsen connection timing info with connection’s
- // timing info, timingInfo’s post-redirect start time, and fetchParams’s
- // cross-origin isolated capability.
-
- // 3. If connection is not an HTTP/2 connection, request’s body is non-null,
- // and request’s body’s source is null, then append (`Transfer-Encoding`,
- // `chunked`) to request’s header list.
-
- // 4. Set timingInfo’s final network-request start time to the coarsened
- // shared current time given fetchParams’s cross-origin isolated
- // capability.
-
- // 5. Set response to the result of making an HTTP request over connection
- // using request with the following caveats:
-
- // - Follow the relevant requirements from HTTP. [HTTP] [HTTP-SEMANTICS]
- // [HTTP-COND] [HTTP-CACHING] [HTTP-AUTH]
-
- // - If request’s body is non-null, and request’s body’s source is null,
- // then the user agent may have a buffer of up to 64 kibibytes and store
- // a part of request’s body in that buffer. If the user agent reads from
- // request’s body beyond that buffer’s size and the user agent needs to
- // resend request, then instead return a network error.
-
- // - Set timingInfo’s final network-response start time to the coarsened
- // shared current time given fetchParams’s cross-origin isolated capability,
- // immediately after the user agent’s HTTP parser receives the first byte
- // of the response (e.g., frame header bytes for HTTP/2 or response status
- // line for HTTP/1.x).
-
- // - Wait until all the headers are transmitted.
-
- // - Any responses whose status is in the range 100 to 199, inclusive,
- // and is not 101, are to be ignored, except for the purposes of setting
- // timingInfo’s final network-response start time above.
-
- // - If request’s header list contains `Transfer-Encoding`/`chunked` and
- // response is transferred via HTTP/1.0 or older, then return a network
- // error.
-
- // - If the HTTP request results in a TLS client certificate dialog, then:
-
- // 1. If request’s window is an environment settings object, make the
- // dialog available in request’s window.
-
- // 2. Otherwise, return a network error.
-
- // To transmit request’s body body, run these steps:
- let requestBody = null
- // 1. If body is null and fetchParams’s process request end-of-body is
- // non-null, then queue a fetch task given fetchParams’s process request
- // end-of-body and fetchParams’s task destination.
- if (request.body == null && fetchParams.processRequestEndOfBody) {
- queueMicrotask(() => fetchParams.processRequestEndOfBody())
- } else if (request.body != null) {
- // 2. Otherwise, if body is non-null:
-
- // 1. Let processBodyChunk given bytes be these steps:
- const processBodyChunk = async function * (bytes) {
- // 1. If the ongoing fetch is terminated, then abort these steps.
- if (isCancelled(fetchParams)) {
- return
- }
-
- // 2. Run this step in parallel: transmit bytes.
- yield bytes
-
- // 3. If fetchParams’s process request body is non-null, then run
- // fetchParams’s process request body given bytes’s length.
- fetchParams.processRequestBodyChunkLength?.(bytes.byteLength)
- }
-
- // 2. Let processEndOfBody be these steps:
- const processEndOfBody = () => {
- // 1. If fetchParams is canceled, then abort these steps.
- if (isCancelled(fetchParams)) {
- return
- }
-
- // 2. If fetchParams’s process request end-of-body is non-null,
- // then run fetchParams’s process request end-of-body.
- if (fetchParams.processRequestEndOfBody) {
- fetchParams.processRequestEndOfBody()
- }
- }
-
- // 3. Let processBodyError given e be these steps:
- const processBodyError = (e) => {
- // 1. If fetchParams is canceled, then abort these steps.
- if (isCancelled(fetchParams)) {
- return
- }
-
- // 2. If e is an "AbortError" DOMException, then abort fetchParams’s controller.
- if (e.name === 'AbortError') {
- fetchParams.controller.abort()
- } else {
- fetchParams.controller.terminate(e)
- }
- }
-
- // 4. Incrementally read request’s body given processBodyChunk, processEndOfBody,
- // processBodyError, and fetchParams’s task destination.
- requestBody = (async function * () {
- try {
- for await (const bytes of request.body.stream) {
- yield * processBodyChunk(bytes)
- }
- processEndOfBody()
- } catch (err) {
- processBodyError(err)
- }
- })()
- }
-
- try {
- // socket is only provided for websockets
- const { body, status, statusText, headersList, socket } = await dispatch({ body: requestBody })
-
- if (socket) {
- response = makeResponse({ status, statusText, headersList, socket })
- } else {
- const iterator = body[Symbol.asyncIterator]()
- fetchParams.controller.next = () => iterator.next()
-
- response = makeResponse({ status, statusText, headersList })
- }
- } catch (err) {
- // 10. If aborted, then:
- if (err.name === 'AbortError') {
- // 1. If connection uses HTTP/2, then transmit an RST_STREAM frame.
- fetchParams.controller.connection.destroy()
-
- // 2. Return the appropriate network error for fetchParams.
- return makeAppropriateNetworkError(fetchParams, err)
- }
-
- return makeNetworkError(err)
- }
-
- // 11. Let pullAlgorithm be an action that resumes the ongoing fetch
- // if it is suspended.
- const pullAlgorithm = () => {
- fetchParams.controller.resume()
- }
-
- // 12. Let cancelAlgorithm be an algorithm that aborts fetchParams’s
- // controller with reason, given reason.
- const cancelAlgorithm = (reason) => {
- fetchParams.controller.abort(reason)
- }
-
- // 13. Let highWaterMark be a non-negative, non-NaN number, chosen by
- // the user agent.
- // TODO
-
- // 14. Let sizeAlgorithm be an algorithm that accepts a chunk object
- // and returns a non-negative, non-NaN, non-infinite number, chosen by the user agent.
- // TODO
-
- // 15. Let stream be a new ReadableStream.
- // 16. Set up stream with pullAlgorithm set to pullAlgorithm,
- // cancelAlgorithm set to cancelAlgorithm, highWaterMark set to
- // highWaterMark, and sizeAlgorithm set to sizeAlgorithm.
- if (!ReadableStream) {
- ReadableStream = require('stream/web').ReadableStream
- }
-
- const stream = new ReadableStream(
- {
- async start (controller) {
- fetchParams.controller.controller = controller
- },
- async pull (controller) {
- await pullAlgorithm(controller)
- },
- async cancel (reason) {
- await cancelAlgorithm(reason)
- }
- },
- {
- highWaterMark: 0,
- size () {
- return 1
- }
- }
- )
-
- // 17. Run these steps, but abort when the ongoing fetch is terminated:
-
- // 1. Set response’s body to a new body whose stream is stream.
- response.body = { stream }
-
- // 2. If response is not a network error and request’s cache mode is
- // not "no-store", then update response in httpCache for request.
- // TODO
-
- // 3. If includeCredentials is true and the user agent is not configured
- // to block cookies for request (see section 7 of [COOKIES]), then run the
- // "set-cookie-string" parsing algorithm (see section 5.2 of [COOKIES]) on
- // the value of each header whose name is a byte-case-insensitive match for
- // `Set-Cookie` in response’s header list, if any, and request’s current URL.
- // TODO
-
- // 18. If aborted, then:
- // TODO
-
- // 19. Run these steps in parallel:
-
- // 1. Run these steps, but abort when fetchParams is canceled:
- fetchParams.controller.on('terminated', onAborted)
- fetchParams.controller.resume = async () => {
- // 1. While true
- while (true) {
- // 1-3. See onData...
-
- // 4. Set bytes to the result of handling content codings given
- // codings and bytes.
- let bytes
- let isFailure
- try {
- const { done, value } = await fetchParams.controller.next()
-
- if (isAborted(fetchParams)) {
- break
- }
-
- bytes = done ? undefined : value
- } catch (err) {
- if (fetchParams.controller.ended && !timingInfo.encodedBodySize) {
- // zlib doesn't like empty streams.
- bytes = undefined
- } else {
- bytes = err
-
- // err may be propagated from the result of calling readablestream.cancel,
- // which might not be an error. https://github.com/nodejs/undici/issues/2009
- isFailure = true
- }
- }
-
- if (bytes === undefined) {
- // 2. Otherwise, if the bytes transmission for response’s message
- // body is done normally and stream is readable, then close
- // stream, finalize response for fetchParams and response, and
- // abort these in-parallel steps.
- readableStreamClose(fetchParams.controller.controller)
-
- finalizeResponse(fetchParams, response)
-
- return
- }
-
- // 5. Increase timingInfo’s decoded body size by bytes’s length.
- timingInfo.decodedBodySize += bytes?.byteLength ?? 0
-
- // 6. If bytes is failure, then terminate fetchParams’s controller.
- if (isFailure) {
- fetchParams.controller.terminate(bytes)
- return
- }
-
- // 7. Enqueue a Uint8Array wrapping an ArrayBuffer containing bytes
- // into stream.
- fetchParams.controller.controller.enqueue(new Uint8Array(bytes))
-
- // 8. If stream is errored, then terminate the ongoing fetch.
- if (isErrored(stream)) {
- fetchParams.controller.terminate()
- return
- }
-
- // 9. If stream doesn’t need more data ask the user agent to suspend
- // the ongoing fetch.
- if (!fetchParams.controller.controller.desiredSize) {
- return
- }
- }
- }
-
- // 2. If aborted, then:
- function onAborted (reason) {
- // 2. If fetchParams is aborted, then:
- if (isAborted(fetchParams)) {
- // 1. Set response’s aborted flag.
- response.aborted = true
-
- // 2. If stream is readable, then error stream with the result of
- // deserialize a serialized abort reason given fetchParams’s
- // controller’s serialized abort reason and an
- // implementation-defined realm.
- if (isReadable(stream)) {
- fetchParams.controller.controller.error(
- fetchParams.controller.serializedAbortReason
- )
- }
- } else {
- // 3. Otherwise, if stream is readable, error stream with a TypeError.
- if (isReadable(stream)) {
- fetchParams.controller.controller.error(new TypeError('terminated', {
- cause: isErrorLike(reason) ? reason : undefined
- }))
- }
- }
-
- // 4. If connection uses HTTP/2, then transmit an RST_STREAM frame.
- // 5. Otherwise, the user agent should close connection unless it would be bad for performance to do so.
- fetchParams.controller.connection.destroy()
- }
-
- // 20. Return response.
- return response
-
- async function dispatch ({ body }) {
- const url = requestCurrentURL(request)
- /** @type {import('../..').Agent} */
- const agent = fetchParams.controller.dispatcher
-
- return new Promise((resolve, reject) => agent.dispatch(
- {
- path: url.pathname + url.search,
- origin: url.origin,
- method: request.method,
- body: fetchParams.controller.dispatcher.isMockActive ? request.body && request.body.source : body,
- headers: request.headersList.entries,
- maxRedirections: 0,
- upgrade: request.mode === 'websocket' ? 'websocket' : undefined
- },
- {
- body: null,
- abort: null,
-
- onConnect (abort) {
- // TODO (fix): Do we need connection here?
- const { connection } = fetchParams.controller
-
- if (connection.destroyed) {
- abort(new DOMException('The operation was aborted.', 'AbortError'))
- } else {
- fetchParams.controller.on('terminated', abort)
- this.abort = connection.abort = abort
- }
- },
-
- onHeaders (status, headersList, resume, statusText) {
- if (status < 200) {
- return
- }
-
- let codings = []
- let location = ''
-
- const headers = new Headers()
-
- // For H2, the headers are a plain JS object
- // We distinguish between them and iterate accordingly
- if (Array.isArray(headersList)) {
- for (let n = 0; n < headersList.length; n += 2) {
- const key = headersList[n + 0].toString('latin1')
- const val = headersList[n + 1].toString('latin1')
- if (key.toLowerCase() === 'content-encoding') {
- // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.1
- // "All content-coding values are case-insensitive..."
- codings = val.toLowerCase().split(',').map((x) => x.trim())
- } else if (key.toLowerCase() === 'location') {
- location = val
- }
-
- headers.append(key, val)
- }
- } else {
- const keys = Object.keys(headersList)
- for (const key of keys) {
- const val = headersList[key]
- if (key.toLowerCase() === 'content-encoding') {
- // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.1
- // "All content-coding values are case-insensitive..."
- codings = val.toLowerCase().split(',').map((x) => x.trim()).reverse()
- } else if (key.toLowerCase() === 'location') {
- location = val
- }
-
- headers.append(key, val)
- }
- }
-
- this.body = new Readable({ read: resume })
-
- const decoders = []
-
- const willFollow = request.redirect === 'follow' &&
- location &&
- redirectStatusSet.has(status)
-
- // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding
- if (request.method !== 'HEAD' && request.method !== 'CONNECT' && !nullBodyStatus.includes(status) && !willFollow) {
- for (const coding of codings) {
- // https://www.rfc-editor.org/rfc/rfc9112.html#section-7.2
- if (coding === 'x-gzip' || coding === 'gzip') {
- decoders.push(zlib.createGunzip({
- // Be less strict when decoding compressed responses, since sometimes
- // servers send slightly invalid responses that are still accepted
- // by common browsers.
- // Always using Z_SYNC_FLUSH is what cURL does.
- flush: zlib.constants.Z_SYNC_FLUSH,
- finishFlush: zlib.constants.Z_SYNC_FLUSH
- }))
- } else if (coding === 'deflate') {
- decoders.push(zlib.createInflate())
- } else if (coding === 'br') {
- decoders.push(zlib.createBrotliDecompress())
- } else {
- decoders.length = 0
- break
- }
- }
- }
-
- resolve({
- status,
- statusText,
- headersList: headers[kHeadersList],
- body: decoders.length
- ? pipeline(this.body, ...decoders, () => { })
- : this.body.on('error', () => {})
- })
-
- return true
- },
-
- onData (chunk) {
- if (fetchParams.controller.dump) {
- return
- }
-
- // 1. If one or more bytes have been transmitted from response’s
- // message body, then:
-
- // 1. Let bytes be the transmitted bytes.
- const bytes = chunk
-
- // 2. Let codings be the result of extracting header list values
- // given `Content-Encoding` and response’s header list.
- // See pullAlgorithm.
-
- // 3. Increase timingInfo’s encoded body size by bytes’s length.
- timingInfo.encodedBodySize += bytes.byteLength
-
- // 4. See pullAlgorithm...
-
- return this.body.push(bytes)
- },
-
- onComplete () {
- if (this.abort) {
- fetchParams.controller.off('terminated', this.abort)
- }
-
- fetchParams.controller.ended = true
-
- this.body.push(null)
- },
-
- onError (error) {
- if (this.abort) {
- fetchParams.controller.off('terminated', this.abort)
- }
-
- this.body?.destroy(error)
-
- fetchParams.controller.terminate(error)
-
- reject(error)
- },
-
- onUpgrade (status, headersList, socket) {
- if (status !== 101) {
- return
- }
-
- const headers = new Headers()
-
- for (let n = 0; n < headersList.length; n += 2) {
- const key = headersList[n + 0].toString('latin1')
- const val = headersList[n + 1].toString('latin1')
-
- headers.append(key, val)
- }
-
- resolve({
- status,
- statusText: STATUS_CODES[status],
- headersList: headers[kHeadersList],
- socket
- })
-
- return true
- }
- }
- ))
- }
-}
-
-module.exports = {
- fetch,
- Fetch,
- fetching,
- finalizeAndReportTiming
-}
diff --git a/g4f/Provider/npm/node_modules/undici/lib/fetch/request.js b/g4f/Provider/npm/node_modules/undici/lib/fetch/request.js
deleted file mode 100644
index 60e654ec..00000000
--- a/g4f/Provider/npm/node_modules/undici/lib/fetch/request.js
+++ /dev/null
@@ -1,944 +0,0 @@
-/* globals AbortController */
-
-'use strict'
-
-const { extractBody, mixinBody, cloneBody } = require('./body')
-const { Headers, fill: fillHeaders, HeadersList } = require('./headers')
-const { FinalizationRegistry } = require('../compat/dispatcher-weakref')()
-const util = require('../core/util')
-const {
- isValidHTTPToken,
- sameOrigin,
- normalizeMethod,
- makePolicyContainer
-} = require('./util')
-const {
- forbiddenMethodsSet,
- corsSafeListedMethodsSet,
- referrerPolicy,
- requestRedirect,
- requestMode,
- requestCredentials,
- requestCache,
- requestDuplex
-} = require('./constants')
-const { kEnumerableProperty } = util
-const { kHeaders, kSignal, kState, kGuard, kRealm } = require('./symbols')
-const { webidl } = require('./webidl')
-const { getGlobalOrigin } = require('./global')
-const { URLSerializer } = require('./dataURL')
-const { kHeadersList } = require('../core/symbols')
-const assert = require('assert')
-const { getMaxListeners, setMaxListeners, getEventListeners, defaultMaxListeners } = require('events')
-
-let TransformStream = globalThis.TransformStream
-
-const kInit = Symbol('init')
-const kAbortController = Symbol('abortController')
-
-const requestFinalizer = new FinalizationRegistry(({ signal, abort }) => {
- signal.removeEventListener('abort', abort)
-})
-
-// https://fetch.spec.whatwg.org/#request-class
-class Request {
- // https://fetch.spec.whatwg.org/#dom-request
- constructor (input, init = {}) {
- if (input === kInit) {
- return
- }
-
- webidl.argumentLengthCheck(arguments, 1, { header: 'Request constructor' })
-
- input = webidl.converters.RequestInfo(input)
- init = webidl.converters.RequestInit(init)
-
- // https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object
- this[kRealm] = {
- settingsObject: {
- baseUrl: getGlobalOrigin(),
- get origin () {
- return this.baseUrl?.origin
- },
- policyContainer: makePolicyContainer()
- }
- }
-
- // 1. Let request be null.
- let request = null
-
- // 2. Let fallbackMode be null.
- let fallbackMode = null
-
- // 3. Let baseURL be this’s relevant settings object’s API base URL.
- const baseUrl = this[kRealm].settingsObject.baseUrl
-
- // 4. Let signal be null.
- let signal = null
-
- // 5. If input is a string, then:
- if (typeof input === 'string') {
- // 1. Let parsedURL be the result of parsing input with baseURL.
- // 2. If parsedURL is failure, then throw a TypeError.
- let parsedURL
- try {
- parsedURL = new URL(input, baseUrl)
- } catch (err) {
- throw new TypeError('Failed to parse URL from ' + input, { cause: err })
- }
-
- // 3. If parsedURL includes credentials, then throw a TypeError.
- if (parsedURL.username || parsedURL.password) {
- throw new TypeError(
- 'Request cannot be constructed from a URL that includes credentials: ' +
- input
- )
- }
-
- // 4. Set request to a new request whose URL is parsedURL.
- request = makeRequest({ urlList: [parsedURL] })
-
- // 5. Set fallbackMode to "cors".
- fallbackMode = 'cors'
- } else {
- // 6. Otherwise:
-
- // 7. Assert: input is a Request object.
- assert(input instanceof Request)
-
- // 8. Set request to input’s request.
- request = input[kState]
-
- // 9. Set signal to input’s signal.
- signal = input[kSignal]
- }
-
- // 7. Let origin be this’s relevant settings object’s origin.
- const origin = this[kRealm].settingsObject.origin
-
- // 8. Let window be "client".
- let window = 'client'
-
- // 9. If request’s window is an environment settings object and its origin
- // is same origin with origin, then set window to request’s window.
- if (
- request.window?.constructor?.name === 'EnvironmentSettingsObject' &&
- sameOrigin(request.window, origin)
- ) {
- window = request.window
- }
-
- // 10. If init["window"] exists and is non-null, then throw a TypeError.
- if (init.window != null) {
- throw new TypeError(`'window' option '${window}' must be null`)
- }
-
- // 11. If init["window"] exists, then set window to "no-window".
- if ('window' in init) {
- window = 'no-window'
- }
-
- // 12. Set request to a new request with the following properties:
- request = makeRequest({
- // URL request’s URL.
- // undici implementation note: this is set as the first item in request's urlList in makeRequest
- // method request’s method.
- method: request.method,
- // header list A copy of request’s header list.
- // undici implementation note: headersList is cloned in makeRequest
- headersList: request.headersList,
- // unsafe-request flag Set.
- unsafeRequest: request.unsafeRequest,
- // client This’s relevant settings object.
- client: this[kRealm].settingsObject,
- // window window.
- window,
- // priority request’s priority.
- priority: request.priority,
- // origin request’s origin. The propagation of the origin is only significant for navigation requests
- // being handled by a service worker. In this scenario a request can have an origin that is different
- // from the current client.
- origin: request.origin,
- // referrer request’s referrer.
- referrer: request.referrer,
- // referrer policy request’s referrer policy.
- referrerPolicy: request.referrerPolicy,
- // mode request’s mode.
- mode: request.mode,
- // credentials mode request’s credentials mode.
- credentials: request.credentials,
- // cache mode request’s cache mode.
- cache: request.cache,
- // redirect mode request’s redirect mode.
- redirect: request.redirect,
- // integrity metadata request’s integrity metadata.
- integrity: request.integrity,
- // keepalive request’s keepalive.
- keepalive: request.keepalive,
- // reload-navigation flag request’s reload-navigation flag.
- reloadNavigation: request.reloadNavigation,
- // history-navigation flag request’s history-navigation flag.
- historyNavigation: request.historyNavigation,
- // URL list A clone of request’s URL list.
- urlList: [...request.urlList]
- })
-
- // 13. If init is not empty, then:
- if (Object.keys(init).length > 0) {
- // 1. If request’s mode is "navigate", then set it to "same-origin".
- if (request.mode === 'navigate') {
- request.mode = 'same-origin'
- }
-
- // 2. Unset request’s reload-navigation flag.
- request.reloadNavigation = false
-
- // 3. Unset request’s history-navigation flag.
- request.historyNavigation = false
-
- // 4. Set request’s origin to "client".
- request.origin = 'client'
-
- // 5. Set request’s referrer to "client"
- request.referrer = 'client'
-
- // 6. Set request’s referrer policy to the empty string.
- request.referrerPolicy = ''
-
- // 7. Set request’s URL to request’s current URL.
- request.url = request.urlList[request.urlList.length - 1]
-
- // 8. Set request’s URL list to « request’s URL ».
- request.urlList = [request.url]
- }
-
- // 14. If init["referrer"] exists, then:
- if (init.referrer !== undefined) {
- // 1. Let referrer be init["referrer"].
- const referrer = init.referrer
-
- // 2. If referrer is the empty string, then set request’s referrer to "no-referrer".
- if (referrer === '') {
- request.referrer = 'no-referrer'
- } else {
- // 1. Let parsedReferrer be the result of parsing referrer with
- // baseURL.
- // 2. If parsedReferrer is failure, then throw a TypeError.
- let parsedReferrer
- try {
- parsedReferrer = new URL(referrer, baseUrl)
- } catch (err) {
- throw new TypeError(`Referrer "${referrer}" is not a valid URL.`, { cause: err })
- }
-
- // 3. If one of the following is true
- // - parsedReferrer’s scheme is "about" and path is the string "client"
- // - parsedReferrer’s origin is not same origin with origin
- // then set request’s referrer to "client".
- if (
- (parsedReferrer.protocol === 'about:' && parsedReferrer.hostname === 'client') ||
- (origin && !sameOrigin(parsedReferrer, this[kRealm].settingsObject.baseUrl))
- ) {
- request.referrer = 'client'
- } else {
- // 4. Otherwise, set request’s referrer to parsedReferrer.
- request.referrer = parsedReferrer
- }
- }
- }
-
- // 15. If init["referrerPolicy"] exists, then set request’s referrer policy
- // to it.
- if (init.referrerPolicy !== undefined) {
- request.referrerPolicy = init.referrerPolicy
- }
-
- // 16. Let mode be init["mode"] if it exists, and fallbackMode otherwise.
- let mode
- if (init.mode !== undefined) {
- mode = init.mode
- } else {
- mode = fallbackMode
- }
-
- // 17. If mode is "navigate", then throw a TypeError.
- if (mode === 'navigate') {
- throw webidl.errors.exception({
- header: 'Request constructor',
- message: 'invalid request mode navigate.'
- })
- }
-
- // 18. If mode is non-null, set request’s mode to mode.
- if (mode != null) {
- request.mode = mode
- }
-
- // 19. If init["credentials"] exists, then set request’s credentials mode
- // to it.
- if (init.credentials !== undefined) {
- request.credentials = init.credentials
- }
-
- // 18. If init["cache"] exists, then set request’s cache mode to it.
- if (init.cache !== undefined) {
- request.cache = init.cache
- }
-
- // 21. If request’s cache mode is "only-if-cached" and request’s mode is
- // not "same-origin", then throw a TypeError.
- if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') {
- throw new TypeError(
- "'only-if-cached' can be set only with 'same-origin' mode"
- )
- }
-
- // 22. If init["redirect"] exists, then set request’s redirect mode to it.
- if (init.redirect !== undefined) {
- request.redirect = init.redirect
- }
-
- // 23. If init["integrity"] exists, then set request’s integrity metadata to it.
- if (init.integrity !== undefined && init.integrity != null) {
- request.integrity = String(init.integrity)
- }
-
- // 24. If init["keepalive"] exists, then set request’s keepalive to it.
- if (init.keepalive !== undefined) {
- request.keepalive = Boolean(init.keepalive)
- }
-
- // 25. If init["method"] exists, then:
- if (init.method !== undefined) {
- // 1. Let method be init["method"].
- let method = init.method
-
- // 2. If method is not a method or method is a forbidden method, then
- // throw a TypeError.
- if (!isValidHTTPToken(init.method)) {
- throw TypeError(`'${init.method}' is not a valid HTTP method.`)
- }
-
- if (forbiddenMethodsSet.has(method.toUpperCase())) {
- throw TypeError(`'${init.method}' HTTP method is unsupported.`)
- }
-
- // 3. Normalize method.
- method = normalizeMethod(init.method)
-
- // 4. Set request’s method to method.
- request.method = method
- }
-
- // 26. If init["signal"] exists, then set signal to it.
- if (init.signal !== undefined) {
- signal = init.signal
- }
-
- // 27. Set this’s request to request.
- this[kState] = request
-
- // 28. Set this’s signal to a new AbortSignal object with this’s relevant
- // Realm.
- // TODO: could this be simplified with AbortSignal.any
- // (https://dom.spec.whatwg.org/#dom-abortsignal-any)
- const ac = new AbortController()
- this[kSignal] = ac.signal
- this[kSignal][kRealm] = this[kRealm]
-
- // 29. If signal is not null, then make this’s signal follow signal.
- if (signal != null) {
- if (
- !signal ||
- typeof signal.aborted !== 'boolean' ||
- typeof signal.addEventListener !== 'function'
- ) {
- throw new TypeError(
- "Failed to construct 'Request': member signal is not of type AbortSignal."
- )
- }
-
- if (signal.aborted) {
- ac.abort(signal.reason)
- } else {
- // Keep a strong ref to ac while request object
- // is alive. This is needed to prevent AbortController
- // from being prematurely garbage collected.
- // See, https://github.com/nodejs/undici/issues/1926.
- this[kAbortController] = ac
-
- const acRef = new WeakRef(ac)
- const abort = function () {
- const ac = acRef.deref()
- if (ac !== undefined) {
- ac.abort(this.reason)
- }
- }
-
- // Third-party AbortControllers may not work with these.
- // See, https://github.com/nodejs/undici/pull/1910#issuecomment-1464495619.
- try {
- // If the max amount of listeners is equal to the default, increase it
- // This is only available in node >= v19.9.0
- if (typeof getMaxListeners === 'function' && getMaxListeners(signal) === defaultMaxListeners) {
- setMaxListeners(100, signal)
- } else if (getEventListeners(signal, 'abort').length >= defaultMaxListeners) {
- setMaxListeners(100, signal)
- }
- } catch {}
-
- util.addAbortListener(signal, abort)
- requestFinalizer.register(ac, { signal, abort })
- }
- }
-
- // 30. Set this’s headers to a new Headers object with this’s relevant
- // Realm, whose header list is request’s header list and guard is
- // "request".
- this[kHeaders] = new Headers()
- this[kHeaders][kHeadersList] = request.headersList
- this[kHeaders][kGuard] = 'request'
- this[kHeaders][kRealm] = this[kRealm]
-
- // 31. If this’s request’s mode is "no-cors", then:
- if (mode === 'no-cors') {
- // 1. If this’s request’s method is not a CORS-safelisted method,
- // then throw a TypeError.
- if (!corsSafeListedMethodsSet.has(request.method)) {
- throw new TypeError(
- `'${request.method} is unsupported in no-cors mode.`
- )
- }
-
- // 2. Set this’s headers’s guard to "request-no-cors".
- this[kHeaders][kGuard] = 'request-no-cors'
- }
-
- // 32. If init is not empty, then:
- if (Object.keys(init).length !== 0) {
- // 1. Let headers be a copy of this’s headers and its associated header
- // list.
- let headers = new Headers(this[kHeaders])
-
- // 2. If init["headers"] exists, then set headers to init["headers"].
- if (init.headers !== undefined) {
- headers = init.headers
- }
-
- // 3. Empty this’s headers’s header list.
- this[kHeaders][kHeadersList].clear()
-
- // 4. If headers is a Headers object, then for each header in its header
- // list, append header’s name/header’s value to this’s headers.
- if (headers.constructor.name === 'Headers') {
- for (const [key, val] of headers) {
- this[kHeaders].append(key, val)
- }
- } else {
- // 5. Otherwise, fill this’s headers with headers.
- fillHeaders(this[kHeaders], headers)
- }
- }
-
- // 33. Let inputBody be input’s request’s body if input is a Request
- // object; otherwise null.
- const inputBody = input instanceof Request ? input[kState].body : null
-
- // 34. If either init["body"] exists and is non-null or inputBody is
- // non-null, and request’s method is `GET` or `HEAD`, then throw a
- // TypeError.
- if (
- (init.body != null || inputBody != null) &&
- (request.method === 'GET' || request.method === 'HEAD')
- ) {
- throw new TypeError('Request with GET/HEAD method cannot have body.')
- }
-
- // 35. Let initBody be null.
- let initBody = null
-
- // 36. If init["body"] exists and is non-null, then:
- if (init.body != null) {
- // 1. Let Content-Type be null.
- // 2. Set initBody and Content-Type to the result of extracting
- // init["body"], with keepalive set to request’s keepalive.
- const [extractedBody, contentType] = extractBody(
- init.body,
- request.keepalive
- )
- initBody = extractedBody
-
- // 3, If Content-Type is non-null and this’s headers’s header list does
- // not contain `Content-Type`, then append `Content-Type`/Content-Type to
- // this’s headers.
- if (contentType && !this[kHeaders][kHeadersList].contains('content-type')) {
- this[kHeaders].append('content-type', contentType)
- }
- }
-
- // 37. Let inputOrInitBody be initBody if it is non-null; otherwise
- // inputBody.
- const inputOrInitBody = initBody ?? inputBody
-
- // 38. If inputOrInitBody is non-null and inputOrInitBody’s source is
- // null, then:
- if (inputOrInitBody != null && inputOrInitBody.source == null) {
- // 1. If initBody is non-null and init["duplex"] does not exist,
- // then throw a TypeError.
- if (initBody != null && init.duplex == null) {
- throw new TypeError('RequestInit: duplex option is required when sending a body.')
- }
-
- // 2. If this’s request’s mode is neither "same-origin" nor "cors",
- // then throw a TypeError.
- if (request.mode !== 'same-origin' && request.mode !== 'cors') {
- throw new TypeError(
- 'If request is made from ReadableStream, mode should be "same-origin" or "cors"'
- )
- }
-
- // 3. Set this’s request’s use-CORS-preflight flag.
- request.useCORSPreflightFlag = true
- }
-
- // 39. Let finalBody be inputOrInitBody.
- let finalBody = inputOrInitBody
-
- // 40. If initBody is null and inputBody is non-null, then:
- if (initBody == null && inputBody != null) {
- // 1. If input is unusable, then throw a TypeError.
- if (util.isDisturbed(inputBody.stream) || inputBody.stream.locked) {
- throw new TypeError(
- 'Cannot construct a Request with a Request object that has already been used.'
- )
- }
-
- // 2. Set finalBody to the result of creating a proxy for inputBody.
- if (!TransformStream) {
- TransformStream = require('stream/web').TransformStream
- }
-
- // https://streams.spec.whatwg.org/#readablestream-create-a-proxy
- const identityTransform = new TransformStream()
- inputBody.stream.pipeThrough(identityTransform)
- finalBody = {
- source: inputBody.source,
- length: inputBody.length,
- stream: identityTransform.readable
- }
- }
-
- // 41. Set this’s request’s body to finalBody.
- this[kState].body = finalBody
- }
-
- // Returns request’s HTTP method, which is "GET" by default.
- get method () {
- webidl.brandCheck(this, Request)
-
- // The method getter steps are to return this’s request’s method.
- return this[kState].method
- }
-
- // Returns the URL of request as a string.
- get url () {
- webidl.brandCheck(this, Request)
-
- // The url getter steps are to return this’s request’s URL, serialized.
- return URLSerializer(this[kState].url)
- }
-
- // Returns a Headers object consisting of the headers associated with request.
- // Note that headers added in the network layer by the user agent will not
- // be accounted for in this object, e.g., the "Host" header.
- get headers () {
- webidl.brandCheck(this, Request)
-
- // The headers getter steps are to return this’s headers.
- return this[kHeaders]
- }
-
- // Returns the kind of resource requested by request, e.g., "document"
- // or "script".
- get destination () {
- webidl.brandCheck(this, Request)
-
- // The destination getter are to return this’s request’s destination.
- return this[kState].destination
- }
-
- // Returns the referrer of request. Its value can be a same-origin URL if
- // explicitly set in init, the empty string to indicate no referrer, and
- // "about:client" when defaulting to the global’s default. This is used
- // during fetching to determine the value of the `Referer` header of the
- // request being made.
- get referrer () {
- webidl.brandCheck(this, Request)
-
- // 1. If this’s request’s referrer is "no-referrer", then return the
- // empty string.
- if (this[kState].referrer === 'no-referrer') {
- return ''
- }
-
- // 2. If this’s request’s referrer is "client", then return
- // "about:client".
- if (this[kState].referrer === 'client') {
- return 'about:client'
- }
-
- // Return this’s request’s referrer, serialized.
- return this[kState].referrer.toString()
- }
-
- // Returns the referrer policy associated with request.
- // This is used during fetching to compute the value of the request’s
- // referrer.
- get referrerPolicy () {
- webidl.brandCheck(this, Request)
-
- // The referrerPolicy getter steps are to return this’s request’s referrer policy.
- return this[kState].referrerPolicy
- }
-
- // Returns the mode associated with request, which is a string indicating
- // whether the request will use CORS, or will be restricted to same-origin
- // URLs.
- get mode () {
- webidl.brandCheck(this, Request)
-
- // The mode getter steps are to return this’s request’s mode.
- return this[kState].mode
- }
-
- // Returns the credentials mode associated with request,
- // which is a string indicating whether credentials will be sent with the
- // request always, never, or only when sent to a same-origin URL.
- get credentials () {
- // The credentials getter steps are to return this’s request’s credentials mode.
- return this[kState].credentials
- }
-
- // Returns the cache mode associated with request,
- // which is a string indicating how the request will
- // interact with the browser’s cache when fetching.
- get cache () {
- webidl.brandCheck(this, Request)
-
- // The cache getter steps are to return this’s request’s cache mode.
- return this[kState].cache
- }
-
- // Returns the redirect mode associated with request,
- // which is a string indicating how redirects for the
- // request will be handled during fetching. A request
- // will follow redirects by default.
- get redirect () {
- webidl.brandCheck(this, Request)
-
- // The redirect getter steps are to return this’s request’s redirect mode.
- return this[kState].redirect
- }
-
- // Returns request’s subresource integrity metadata, which is a
- // cryptographic hash of the resource being fetched. Its value
- // consists of multiple hashes separated by whitespace. [SRI]
- get integrity () {
- webidl.brandCheck(this, Request)
-
- // The integrity getter steps are to return this’s request’s integrity
- // metadata.
- return this[kState].integrity
- }
-
- // Returns a boolean indicating whether or not request can outlive the
- // global in which it was created.
- get keepalive () {
- webidl.brandCheck(this, Request)
-
- // The keepalive getter steps are to return this’s request’s keepalive.
- return this[kState].keepalive
- }
-
- // Returns a boolean indicating whether or not request is for a reload
- // navigation.
- get isReloadNavigation () {
- webidl.brandCheck(this, Request)
-
- // The isReloadNavigation getter steps are to return true if this’s
- // request’s reload-navigation flag is set; otherwise false.
- return this[kState].reloadNavigation
- }
-
- // Returns a boolean indicating whether or not request is for a history
- // navigation (a.k.a. back-foward navigation).
- get isHistoryNavigation () {
- webidl.brandCheck(this, Request)
-
- // The isHistoryNavigation getter steps are to return true if this’s request’s
- // history-navigation flag is set; otherwise false.
- return this[kState].historyNavigation
- }
-
- // Returns the signal associated with request, which is an AbortSignal
- // object indicating whether or not request has been aborted, and its
- // abort event handler.
- get signal () {
- webidl.brandCheck(this, Request)
-
- // The signal getter steps are to return this’s signal.
- return this[kSignal]
- }
-
- get body () {
- webidl.brandCheck(this, Request)
-
- return this[kState].body ? this[kState].body.stream : null
- }
-
- get bodyUsed () {
- webidl.brandCheck(this, Request)
-
- return !!this[kState].body && util.isDisturbed(this[kState].body.stream)
- }
-
- get duplex () {
- webidl.brandCheck(this, Request)
-
- return 'half'
- }
-
- // Returns a clone of request.
- clone () {
- webidl.brandCheck(this, Request)
-
- // 1. If this is unusable, then throw a TypeError.
- if (this.bodyUsed || this.body?.locked) {
- throw new TypeError('unusable')
- }
-
- // 2. Let clonedRequest be the result of cloning this’s request.
- const clonedRequest = cloneRequest(this[kState])
-
- // 3. Let clonedRequestObject be the result of creating a Request object,
- // given clonedRequest, this’s headers’s guard, and this’s relevant Realm.
- const clonedRequestObject = new Request(kInit)
- clonedRequestObject[kState] = clonedRequest
- clonedRequestObject[kRealm] = this[kRealm]
- clonedRequestObject[kHeaders] = new Headers()
- clonedRequestObject[kHeaders][kHeadersList] = clonedRequest.headersList
- clonedRequestObject[kHeaders][kGuard] = this[kHeaders][kGuard]
- clonedRequestObject[kHeaders][kRealm] = this[kHeaders][kRealm]
-
- // 4. Make clonedRequestObject’s signal follow this’s signal.
- const ac = new AbortController()
- if (this.signal.aborted) {
- ac.abort(this.signal.reason)
- } else {
- util.addAbortListener(
- this.signal,
- () => {
- ac.abort(this.signal.reason)
- }
- )
- }
- clonedRequestObject[kSignal] = ac.signal
-
- // 4. Return clonedRequestObject.
- return clonedRequestObject
- }
-}
-
-mixinBody(Request)
-
-function makeRequest (init) {
- // https://fetch.spec.whatwg.org/#requests
- const request = {
- method: 'GET',
- localURLsOnly: false,
- unsafeRequest: false,
- body: null,
- client: null,
- reservedClient: null,
- replacesClientId: '',
- window: 'client',
- keepalive: false,
- serviceWorkers: 'all',
- initiator: '',
- destination: '',
- priority: null,
- origin: 'client',
- policyContainer: 'client',
- referrer: 'client',
- referrerPolicy: '',
- mode: 'no-cors',
- useCORSPreflightFlag: false,
- credentials: 'same-origin',
- useCredentials: false,
- cache: 'default',
- redirect: 'follow',
- integrity: '',
- cryptoGraphicsNonceMetadata: '',
- parserMetadata: '',
- reloadNavigation: false,
- historyNavigation: false,
- userActivation: false,
- taintedOrigin: false,
- redirectCount: 0,
- responseTainting: 'basic',
- preventNoCacheCacheControlHeaderModification: false,
- done: false,
- timingAllowFailed: false,
- ...init,
- headersList: init.headersList
- ? new HeadersList(init.headersList)
- : new HeadersList()
- }
- request.url = request.urlList[0]
- return request
-}
-
-// https://fetch.spec.whatwg.org/#concept-request-clone
-function cloneRequest (request) {
- // To clone a request request, run these steps:
-
- // 1. Let newRequest be a copy of request, except for its body.
- const newRequest = makeRequest({ ...request, body: null })
-
- // 2. If request’s body is non-null, set newRequest’s body to the
- // result of cloning request’s body.
- if (request.body != null) {
- newRequest.body = cloneBody(request.body)
- }
-
- // 3. Return newRequest.
- return newRequest
-}
-
-Object.defineProperties(Request.prototype, {
- method: kEnumerableProperty,
- url: kEnumerableProperty,
- headers: kEnumerableProperty,
- redirect: kEnumerableProperty,
- clone: kEnumerableProperty,
- signal: kEnumerableProperty,
- duplex: kEnumerableProperty,
- destination: kEnumerableProperty,
- body: kEnumerableProperty,
- bodyUsed: kEnumerableProperty,
- isHistoryNavigation: kEnumerableProperty,
- isReloadNavigation: kEnumerableProperty,
- keepalive: kEnumerableProperty,
- integrity: kEnumerableProperty,
- cache: kEnumerableProperty,
- credentials: kEnumerableProperty,
- attribute: kEnumerableProperty,
- referrerPolicy: kEnumerableProperty,
- referrer: kEnumerableProperty,
- mode: kEnumerableProperty,
- [Symbol.toStringTag]: {
- value: 'Request',
- configurable: true
- }
-})
-
-webidl.converters.Request = webidl.interfaceConverter(
- Request
-)
-
-// https://fetch.spec.whatwg.org/#requestinfo
-webidl.converters.RequestInfo = function (V) {
- if (typeof V === 'string') {
- return webidl.converters.USVString(V)
- }
-
- if (V instanceof Request) {
- return webidl.converters.Request(V)
- }
-
- return webidl.converters.USVString(V)
-}
-
-webidl.converters.AbortSignal = webidl.interfaceConverter(
- AbortSignal
-)
-
-// https://fetch.spec.whatwg.org/#requestinit
-webidl.converters.RequestInit = webidl.dictionaryConverter([
- {
- key: 'method',
- converter: webidl.converters.ByteString
- },
- {
- key: 'headers',
- converter: webidl.converters.HeadersInit
- },
- {
- key: 'body',
- converter: webidl.nullableConverter(
- webidl.converters.BodyInit
- )
- },
- {
- key: 'referrer',
- converter: webidl.converters.USVString
- },
- {
- key: 'referrerPolicy',
- converter: webidl.converters.DOMString,
- // https://w3c.github.io/webappsec-referrer-policy/#referrer-policy
- allowedValues: referrerPolicy
- },
- {
- key: 'mode',
- converter: webidl.converters.DOMString,
- // https://fetch.spec.whatwg.org/#concept-request-mode
- allowedValues: requestMode
- },
- {
- key: 'credentials',
- converter: webidl.converters.DOMString,
- // https://fetch.spec.whatwg.org/#requestcredentials
- allowedValues: requestCredentials
- },
- {
- key: 'cache',
- converter: webidl.converters.DOMString,
- // https://fetch.spec.whatwg.org/#requestcache
- allowedValues: requestCache
- },
- {
- key: 'redirect',
- converter: webidl.converters.DOMString,
- // https://fetch.spec.whatwg.org/#requestredirect
- allowedValues: requestRedirect
- },
- {
- key: 'integrity',
- converter: webidl.converters.DOMString
- },
- {
- key: 'keepalive',
- converter: webidl.converters.boolean
- },
- {
- key: 'signal',
- converter: webidl.nullableConverter(
- (signal) => webidl.converters.AbortSignal(
- signal,
- { strict: false }
- )
- )
- },
- {
- key: 'window',
- converter: webidl.converters.any
- },
- {
- key: 'duplex',
- converter: webidl.converters.DOMString,
- allowedValues: requestDuplex
- }
-])
-
-module.exports = { Request, makeRequest }
diff --git a/g4f/Provider/npm/node_modules/undici/lib/fetch/response.js b/g4f/Provider/npm/node_modules/undici/lib/fetch/response.js
deleted file mode 100644
index 23cf55c5..00000000
--- a/g4f/Provider/npm/node_modules/undici/lib/fetch/response.js
+++ /dev/null
@@ -1,575 +0,0 @@
-'use strict'
-
-const { Headers, HeadersList, fill } = require('./headers')
-const { extractBody, cloneBody, mixinBody } = require('./body')
-const util = require('../core/util')
-const { kEnumerableProperty } = util
-const {
- isValidReasonPhrase,
- isCancelled,
- isAborted,
- isBlobLike,
- serializeJavascriptValueToJSONString,
- isErrorLike,
- isomorphicEncode
-} = require('./util')
-const {
- redirectStatusSet,
- nullBodyStatus,
- DOMException
-} = require('./constants')
-const { kState, kHeaders, kGuard, kRealm } = require('./symbols')
-const { webidl } = require('./webidl')
-const { FormData } = require('./formdata')
-const { getGlobalOrigin } = require('./global')
-const { URLSerializer } = require('./dataURL')
-const { kHeadersList } = require('../core/symbols')
-const assert = require('assert')
-const { types } = require('util')
-
-const ReadableStream = globalThis.ReadableStream || require('stream/web').ReadableStream
-const textEncoder = new TextEncoder('utf-8')
-
-// https://fetch.spec.whatwg.org/#response-class
-class Response {
- // Creates network error Response.
- static error () {
- // TODO
- const relevantRealm = { settingsObject: {} }
-
- // The static error() method steps are to return the result of creating a
- // Response object, given a new network error, "immutable", and this’s
- // relevant Realm.
- const responseObject = new Response()
- responseObject[kState] = makeNetworkError()
- responseObject[kRealm] = relevantRealm
- responseObject[kHeaders][kHeadersList] = responseObject[kState].headersList
- responseObject[kHeaders][kGuard] = 'immutable'
- responseObject[kHeaders][kRealm] = relevantRealm
- return responseObject
- }
-
- // https://fetch.spec.whatwg.org/#dom-response-json
- static json (data, init = {}) {
- webidl.argumentLengthCheck(arguments, 1, { header: 'Response.json' })
-
- if (init !== null) {
- init = webidl.converters.ResponseInit(init)
- }
-
- // 1. Let bytes the result of running serialize a JavaScript value to JSON bytes on data.
- const bytes = textEncoder.encode(
- serializeJavascriptValueToJSONString(data)
- )
-
- // 2. Let body be the result of extracting bytes.
- const body = extractBody(bytes)
-
- // 3. Let responseObject be the result of creating a Response object, given a new response,
- // "response", and this’s relevant Realm.
- const relevantRealm = { settingsObject: {} }
- const responseObject = new Response()
- responseObject[kRealm] = relevantRealm
- responseObject[kHeaders][kGuard] = 'response'
- responseObject[kHeaders][kRealm] = relevantRealm
-
- // 4. Perform initialize a response given responseObject, init, and (body, "application/json").
- initializeResponse(responseObject, init, { body: body[0], type: 'application/json' })
-
- // 5. Return responseObject.
- return responseObject
- }
-
- // Creates a redirect Response that redirects to url with status status.
- static redirect (url, status = 302) {
- const relevantRealm = { settingsObject: {} }
-
- webidl.argumentLengthCheck(arguments, 1, { header: 'Response.redirect' })
-
- url = webidl.converters.USVString(url)
- status = webidl.converters['unsigned short'](status)
-
- // 1. Let parsedURL be the result of parsing url with current settings
- // object’s API base URL.
- // 2. If parsedURL is failure, then throw a TypeError.
- // TODO: base-URL?
- let parsedURL
- try {
- parsedURL = new URL(url, getGlobalOrigin())
- } catch (err) {
- throw Object.assign(new TypeError('Failed to parse URL from ' + url), {
- cause: err
- })
- }
-
- // 3. If status is not a redirect status, then throw a RangeError.
- if (!redirectStatusSet.has(status)) {
- throw new RangeError('Invalid status code ' + status)
- }
-
- // 4. Let responseObject be the result of creating a Response object,
- // given a new response, "immutable", and this’s relevant Realm.
- const responseObject = new Response()
- responseObject[kRealm] = relevantRealm
- responseObject[kHeaders][kGuard] = 'immutable'
- responseObject[kHeaders][kRealm] = relevantRealm
-
- // 5. Set responseObject’s response’s status to status.
- responseObject[kState].status = status
-
- // 6. Let value be parsedURL, serialized and isomorphic encoded.
- const value = isomorphicEncode(URLSerializer(parsedURL))
-
- // 7. Append `Location`/value to responseObject’s response’s header list.
- responseObject[kState].headersList.append('location', value)
-
- // 8. Return responseObject.
- return responseObject
- }
-
- // https://fetch.spec.whatwg.org/#dom-response
- constructor (body = null, init = {}) {
- if (body !== null) {
- body = webidl.converters.BodyInit(body)
- }
-
- init = webidl.converters.ResponseInit(init)
-
- // TODO
- this[kRealm] = { settingsObject: {} }
-
- // 1. Set this’s response to a new response.
- this[kState] = makeResponse({})
-
- // 2. Set this’s headers to a new Headers object with this’s relevant
- // Realm, whose header list is this’s response’s header list and guard
- // is "response".
- this[kHeaders] = new Headers()
- this[kHeaders][kGuard] = 'response'
- this[kHeaders][kHeadersList] = this[kState].headersList
- this[kHeaders][kRealm] = this[kRealm]
-
- // 3. Let bodyWithType be null.
- let bodyWithType = null
-
- // 4. If body is non-null, then set bodyWithType to the result of extracting body.
- if (body != null) {
- const [extractedBody, type] = extractBody(body)
- bodyWithType = { body: extractedBody, type }
- }
-
- // 5. Perform initialize a response given this, init, and bodyWithType.
- initializeResponse(this, init, bodyWithType)
- }
-
- // Returns response’s type, e.g., "cors".
- get type () {
- webidl.brandCheck(this, Response)
-
- // The type getter steps are to return this’s response’s type.
- return this[kState].type
- }
-
- // Returns response’s URL, if it has one; otherwise the empty string.
- get url () {
- webidl.brandCheck(this, Response)
-
- const urlList = this[kState].urlList
-
- // The url getter steps are to return the empty string if this’s
- // response’s URL is null; otherwise this’s response’s URL,
- // serialized with exclude fragment set to true.
- const url = urlList[urlList.length - 1] ?? null
-
- if (url === null) {
- return ''
- }
-
- return URLSerializer(url, true)
- }
-
- // Returns whether response was obtained through a redirect.
- get redirected () {
- webidl.brandCheck(this, Response)
-
- // The redirected getter steps are to return true if this’s response’s URL
- // list has more than one item; otherwise false.
- return this[kState].urlList.length > 1
- }
-
- // Returns response’s status.
- get status () {
- webidl.brandCheck(this, Response)
-
- // The status getter steps are to return this’s response’s status.
- return this[kState].status
- }
-
- // Returns whether response’s status is an ok status.
- get ok () {
- webidl.brandCheck(this, Response)
-
- // The ok getter steps are to return true if this’s response’s status is an
- // ok status; otherwise false.
- return this[kState].status >= 200 && this[kState].status <= 299
- }
-
- // Returns response’s status message.
- get statusText () {
- webidl.brandCheck(this, Response)
-
- // The statusText getter steps are to return this’s response’s status
- // message.
- return this[kState].statusText
- }
-
- // Returns response’s headers as Headers.
- get headers () {
- webidl.brandCheck(this, Response)
-
- // The headers getter steps are to return this’s headers.
- return this[kHeaders]
- }
-
- get body () {
- webidl.brandCheck(this, Response)
-
- return this[kState].body ? this[kState].body.stream : null
- }
-
- get bodyUsed () {
- webidl.brandCheck(this, Response)
-
- return !!this[kState].body && util.isDisturbed(this[kState].body.stream)
- }
-
- // Returns a clone of response.
- clone () {
- webidl.brandCheck(this, Response)
-
- // 1. If this is unusable, then throw a TypeError.
- if (this.bodyUsed || (this.body && this.body.locked)) {
- throw webidl.errors.exception({
- header: 'Response.clone',
- message: 'Body has already been consumed.'
- })
- }
-
- // 2. Let clonedResponse be the result of cloning this’s response.
- const clonedResponse = cloneResponse(this[kState])
-
- // 3. Return the result of creating a Response object, given
- // clonedResponse, this’s headers’s guard, and this’s relevant Realm.
- const clonedResponseObject = new Response()
- clonedResponseObject[kState] = clonedResponse
- clonedResponseObject[kRealm] = this[kRealm]
- clonedResponseObject[kHeaders][kHeadersList] = clonedResponse.headersList
- clonedResponseObject[kHeaders][kGuard] = this[kHeaders][kGuard]
- clonedResponseObject[kHeaders][kRealm] = this[kHeaders][kRealm]
-
- return clonedResponseObject
- }
-}
-
-mixinBody(Response)
-
-Object.defineProperties(Response.prototype, {
- type: kEnumerableProperty,
- url: kEnumerableProperty,
- status: kEnumerableProperty,
- ok: kEnumerableProperty,
- redirected: kEnumerableProperty,
- statusText: kEnumerableProperty,
- headers: kEnumerableProperty,
- clone: kEnumerableProperty,
- body: kEnumerableProperty,
- bodyUsed: kEnumerableProperty,
- [Symbol.toStringTag]: {
- value: 'Response',
- configurable: true
- }
-})
-
-Object.defineProperties(Response, {
- json: kEnumerableProperty,
- redirect: kEnumerableProperty,
- error: kEnumerableProperty
-})
-
-// https://fetch.spec.whatwg.org/#concept-response-clone
-function cloneResponse (response) {
- // To clone a response response, run these steps:
-
- // 1. If response is a filtered response, then return a new identical
- // filtered response whose internal response is a clone of response’s
- // internal response.
- if (response.internalResponse) {
- return filterResponse(
- cloneResponse(response.internalResponse),
- response.type
- )
- }
-
- // 2. Let newResponse be a copy of response, except for its body.
- const newResponse = makeResponse({ ...response, body: null })
-
- // 3. If response’s body is non-null, then set newResponse’s body to the
- // result of cloning response’s body.
- if (response.body != null) {
- newResponse.body = cloneBody(response.body)
- }
-
- // 4. Return newResponse.
- return newResponse
-}
-
-function makeResponse (init) {
- return {
- aborted: false,
- rangeRequested: false,
- timingAllowPassed: false,
- requestIncludesCredentials: false,
- type: 'default',
- status: 200,
- timingInfo: null,
- cacheState: '',
- statusText: '',
- ...init,
- headersList: init.headersList
- ? new HeadersList(init.headersList)
- : new HeadersList(),
- urlList: init.urlList ? [...init.urlList] : []
- }
-}
-
-function makeNetworkError (reason) {
- const isError = isErrorLike(reason)
- return makeResponse({
- type: 'error',
- status: 0,
- error: isError
- ? reason
- : new Error(reason ? String(reason) : reason),
- aborted: reason && reason.name === 'AbortError'
- })
-}
-
-function makeFilteredResponse (response, state) {
- state = {
- internalResponse: response,
- ...state
- }
-
- return new Proxy(response, {
- get (target, p) {
- return p in state ? state[p] : target[p]
- },
- set (target, p, value) {
- assert(!(p in state))
- target[p] = value
- return true
- }
- })
-}
-
-// https://fetch.spec.whatwg.org/#concept-filtered-response
-function filterResponse (response, type) {
- // Set response to the following filtered response with response as its
- // internal response, depending on request’s response tainting:
- if (type === 'basic') {
- // A basic filtered response is a filtered response whose type is "basic"
- // and header list excludes any headers in internal response’s header list
- // whose name is a forbidden response-header name.
-
- // Note: undici does not implement forbidden response-header names
- return makeFilteredResponse(response, {
- type: 'basic',
- headersList: response.headersList
- })
- } else if (type === 'cors') {
- // A CORS filtered response is a filtered response whose type is "cors"
- // and header list excludes any headers in internal response’s header
- // list whose name is not a CORS-safelisted response-header name, given
- // internal response’s CORS-exposed header-name list.
-
- // Note: undici does not implement CORS-safelisted response-header names
- return makeFilteredResponse(response, {
- type: 'cors',
- headersList: response.headersList
- })
- } else if (type === 'opaque') {
- // An opaque filtered response is a filtered response whose type is
- // "opaque", URL list is the empty list, status is 0, status message
- // is the empty byte sequence, header list is empty, and body is null.
-
- return makeFilteredResponse(response, {
- type: 'opaque',
- urlList: Object.freeze([]),
- status: 0,
- statusText: '',
- body: null
- })
- } else if (type === 'opaqueredirect') {
- // An opaque-redirect filtered response is a filtered response whose type
- // is "opaqueredirect", status is 0, status message is the empty byte
- // sequence, header list is empty, and body is null.
-
- return makeFilteredResponse(response, {
- type: 'opaqueredirect',
- status: 0,
- statusText: '',
- headersList: [],
- body: null
- })
- } else {
- assert(false)
- }
-}
-
-// https://fetch.spec.whatwg.org/#appropriate-network-error
-function makeAppropriateNetworkError (fetchParams, err = null) {
- // 1. Assert: fetchParams is canceled.
- assert(isCancelled(fetchParams))
-
- // 2. Return an aborted network error if fetchParams is aborted;
- // otherwise return a network error.
- return isAborted(fetchParams)
- ? makeNetworkError(Object.assign(new DOMException('The operation was aborted.', 'AbortError'), { cause: err }))
- : makeNetworkError(Object.assign(new DOMException('Request was cancelled.'), { cause: err }))
-}
-
-// https://whatpr.org/fetch/1392.html#initialize-a-response
-function initializeResponse (response, init, body) {
- // 1. If init["status"] is not in the range 200 to 599, inclusive, then
- // throw a RangeError.
- if (init.status !== null && (init.status < 200 || init.status > 599)) {
- throw new RangeError('init["status"] must be in the range of 200 to 599, inclusive.')
- }
-
- // 2. If init["statusText"] does not match the reason-phrase token production,
- // then throw a TypeError.
- if ('statusText' in init && init.statusText != null) {
- // See, https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2:
- // reason-phrase = *( HTAB / SP / VCHAR / obs-text )
- if (!isValidReasonPhrase(String(init.statusText))) {
- throw new TypeError('Invalid statusText')
- }
- }
-
- // 3. Set response’s response’s status to init["status"].
- if ('status' in init && init.status != null) {
- response[kState].status = init.status
- }
-
- // 4. Set response’s response’s status message to init["statusText"].
- if ('statusText' in init && init.statusText != null) {
- response[kState].statusText = init.statusText
- }
-
- // 5. If init["headers"] exists, then fill response’s headers with init["headers"].
- if ('headers' in init && init.headers != null) {
- fill(response[kHeaders], init.headers)
- }
-
- // 6. If body was given, then:
- if (body) {
- // 1. If response's status is a null body status, then throw a TypeError.
- if (nullBodyStatus.includes(response.status)) {
- throw webidl.errors.exception({
- header: 'Response constructor',
- message: 'Invalid response status code ' + response.status
- })
- }
-
- // 2. Set response's body to body's body.
- response[kState].body = body.body
-
- // 3. If body's type is non-null and response's header list does not contain
- // `Content-Type`, then append (`Content-Type`, body's type) to response's header list.
- if (body.type != null && !response[kState].headersList.contains('Content-Type')) {
- response[kState].headersList.append('content-type', body.type)
- }
- }
-}
-
-webidl.converters.ReadableStream = webidl.interfaceConverter(
- ReadableStream
-)
-
-webidl.converters.FormData = webidl.interfaceConverter(
- FormData
-)
-
-webidl.converters.URLSearchParams = webidl.interfaceConverter(
- URLSearchParams
-)
-
-// https://fetch.spec.whatwg.org/#typedefdef-xmlhttprequestbodyinit
-webidl.converters.XMLHttpRequestBodyInit = function (V) {
- if (typeof V === 'string') {
- return webidl.converters.USVString(V)
- }
-
- if (isBlobLike(V)) {
- return webidl.converters.Blob(V, { strict: false })
- }
-
- if (
- types.isAnyArrayBuffer(V) ||
- types.isTypedArray(V) ||
- types.isDataView(V)
- ) {
- return webidl.converters.BufferSource(V)
- }
-
- if (util.isFormDataLike(V)) {
- return webidl.converters.FormData(V, { strict: false })
- }
-
- if (V instanceof URLSearchParams) {
- return webidl.converters.URLSearchParams(V)
- }
-
- return webidl.converters.DOMString(V)
-}
-
-// https://fetch.spec.whatwg.org/#bodyinit
-webidl.converters.BodyInit = function (V) {
- if (V instanceof ReadableStream) {
- return webidl.converters.ReadableStream(V)
- }
-
- // Note: the spec doesn't include async iterables,
- // this is an undici extension.
- if (V?.[Symbol.asyncIterator]) {
- return V
- }
-
- return webidl.converters.XMLHttpRequestBodyInit(V)
-}
-
-webidl.converters.ResponseInit = webidl.dictionaryConverter([
- {
- key: 'status',
- converter: webidl.converters['unsigned short'],
- defaultValue: 200
- },
- {
- key: 'statusText',
- converter: webidl.converters.ByteString,
- defaultValue: ''
- },
- {
- key: 'headers',
- converter: webidl.converters.HeadersInit
- }
-])
-
-module.exports = {
- makeNetworkError,
- makeResponse,
- makeAppropriateNetworkError,
- filterResponse,
- Response,
- cloneResponse
-}
diff --git a/g4f/Provider/npm/node_modules/undici/lib/fetch/symbols.js b/g4f/Provider/npm/node_modules/undici/lib/fetch/symbols.js
deleted file mode 100644
index 0b947d55..00000000
--- a/g4f/Provider/npm/node_modules/undici/lib/fetch/symbols.js
+++ /dev/null
@@ -1,10 +0,0 @@
-'use strict'
-
-module.exports = {
- kUrl: Symbol('url'),
- kHeaders: Symbol('headers'),
- kSignal: Symbol('signal'),
- kState: Symbol('state'),
- kGuard: Symbol('guard'),
- kRealm: Symbol('realm')
-}
diff --git a/g4f/Provider/npm/node_modules/undici/lib/fetch/util.js b/g4f/Provider/npm/node_modules/undici/lib/fetch/util.js
deleted file mode 100644
index 033fa206..00000000
--- a/g4f/Provider/npm/node_modules/undici/lib/fetch/util.js
+++ /dev/null
@@ -1,1046 +0,0 @@
-'use strict'
-
-const { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet } = require('./constants')
-const { getGlobalOrigin } = require('./global')
-const { performance } = require('perf_hooks')
-const { isBlobLike, toUSVString, ReadableStreamFrom } = require('../core/util')
-const assert = require('assert')
-const { isUint8Array } = require('util/types')
-
-// https://nodejs.org/api/crypto.html#determining-if-crypto-support-is-unavailable
-/** @type {import('crypto')|undefined} */
-let crypto
-
-try {
- crypto = require('crypto')
-} catch {
-
-}
-
-function responseURL (response) {
- // https://fetch.spec.whatwg.org/#responses
- // A response has an associated URL. It is a pointer to the last URL
- // in response’s URL list and null if response’s URL list is empty.
- const urlList = response.urlList
- const length = urlList.length
- return length === 0 ? null : urlList[length - 1].toString()
-}
-
-// https://fetch.spec.whatwg.org/#concept-response-location-url
-function responseLocationURL (response, requestFragment) {
- // 1. If response’s status is not a redirect status, then return null.
- if (!redirectStatusSet.has(response.status)) {
- return null
- }
-
- // 2. Let location be the result of extracting header list values given
- // `Location` and response’s header list.
- let location = response.headersList.get('location')
-
- // 3. If location is a header value, then set location to the result of
- // parsing location with response’s URL.
- if (location !== null && isValidHeaderValue(location)) {
- location = new URL(location, responseURL(response))
- }
-
- // 4. If location is a URL whose fragment is null, then set location’s
- // fragment to requestFragment.
- if (location && !location.hash) {
- location.hash = requestFragment
- }
-
- // 5. Return location.
- return location
-}
-
-/** @returns {URL} */
-function requestCurrentURL (request) {
- return request.urlList[request.urlList.length - 1]
-}
-
-function requestBadPort (request) {
- // 1. Let url be request’s current URL.
- const url = requestCurrentURL(request)
-
- // 2. If url’s scheme is an HTTP(S) scheme and url’s port is a bad port,
- // then return blocked.
- if (urlIsHttpHttpsScheme(url) && badPortsSet.has(url.port)) {
- return 'blocked'
- }
-
- // 3. Return allowed.
- return 'allowed'
-}
-
-function isErrorLike (object) {
- return object instanceof Error || (
- object?.constructor?.name === 'Error' ||
- object?.constructor?.name === 'DOMException'
- )
-}
-
-// Check whether |statusText| is a ByteString and
-// matches the Reason-Phrase token production.
-// RFC 2616: https://tools.ietf.org/html/rfc2616
-// RFC 7230: https://tools.ietf.org/html/rfc7230
-// "reason-phrase = *( HTAB / SP / VCHAR / obs-text )"
-// https://github.com/chromium/chromium/blob/94.0.4604.1/third_party/blink/renderer/core/fetch/response.cc#L116
-function isValidReasonPhrase (statusText) {
- for (let i = 0; i < statusText.length; ++i) {
- const c = statusText.charCodeAt(i)
- if (
- !(
- (
- c === 0x09 || // HTAB
- (c >= 0x20 && c <= 0x7e) || // SP / VCHAR
- (c >= 0x80 && c <= 0xff)
- ) // obs-text
- )
- ) {
- return false
- }
- }
- return true
-}
-
-function isTokenChar (c) {
- return !(
- c >= 0x7f ||
- c <= 0x20 ||
- c === '(' ||
- c === ')' ||
- c === '<' ||
- c === '>' ||
- c === '@' ||
- c === ',' ||
- c === ';' ||
- c === ':' ||
- c === '\\' ||
- c === '"' ||
- c === '/' ||
- c === '[' ||
- c === ']' ||
- c === '?' ||
- c === '=' ||
- c === '{' ||
- c === '}'
- )
-}
-
-// See RFC 7230, Section 3.2.6.
-// https://github.com/chromium/chromium/blob/d7da0240cae77824d1eda25745c4022757499131/third_party/blink/renderer/platform/network/http_parsers.cc#L321
-function isValidHTTPToken (characters) {
- if (!characters || typeof characters !== 'string') {
- return false
- }
- for (let i = 0; i < characters.length; ++i) {
- const c = characters.charCodeAt(i)
- if (c > 0x7f || !isTokenChar(c)) {
- return false
- }
- }
- return true
-}
-
-// https://fetch.spec.whatwg.org/#header-name
-// https://github.com/chromium/chromium/blob/b3d37e6f94f87d59e44662d6078f6a12de845d17/net/http/http_util.cc#L342
-function isValidHeaderName (potentialValue) {
- if (potentialValue.length === 0) {
- return false
- }
-
- return isValidHTTPToken(potentialValue)
-}
-
-/**
- * @see https://fetch.spec.whatwg.org/#header-value
- * @param {string} potentialValue
- */
-function isValidHeaderValue (potentialValue) {
- // - Has no leading or trailing HTTP tab or space bytes.
- // - Contains no 0x00 (NUL) or HTTP newline bytes.
- if (
- potentialValue.startsWith('\t') ||
- potentialValue.startsWith(' ') ||
- potentialValue.endsWith('\t') ||
- potentialValue.endsWith(' ')
- ) {
- return false
- }
-
- if (
- potentialValue.includes('\0') ||
- potentialValue.includes('\r') ||
- potentialValue.includes('\n')
- ) {
- return false
- }
-
- return true
-}
-
-// https://w3c.github.io/webappsec-referrer-policy/#set-requests-referrer-policy-on-redirect
-function setRequestReferrerPolicyOnRedirect (request, actualResponse) {
- // Given a request request and a response actualResponse, this algorithm
- // updates request’s referrer policy according to the Referrer-Policy
- // header (if any) in actualResponse.
-
- // 1. Let policy be the result of executing § 8.1 Parse a referrer policy
- // from a Referrer-Policy header on actualResponse.
-
- // 8.1 Parse a referrer policy from a Referrer-Policy header
- // 1. Let policy-tokens be the result of extracting header list values given `Referrer-Policy` and response’s header list.
- const { headersList } = actualResponse
- // 2. Let policy be the empty string.
- // 3. For each token in policy-tokens, if token is a referrer policy and token is not the empty string, then set policy to token.
- // 4. Return policy.
- const policyHeader = (headersList.get('referrer-policy') ?? '').split(',')
-
- // Note: As the referrer-policy can contain multiple policies
- // separated by comma, we need to loop through all of them
- // and pick the first valid one.
- // Ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy#specify_a_fallback_policy
- let policy = ''
- if (policyHeader.length > 0) {
- // The right-most policy takes precedence.
- // The left-most policy is the fallback.
- for (let i = policyHeader.length; i !== 0; i--) {
- const token = policyHeader[i - 1].trim()
- if (referrerPolicyTokens.has(token)) {
- policy = token
- break
- }
- }
- }
-
- // 2. If policy is not the empty string, then set request’s referrer policy to policy.
- if (policy !== '') {
- request.referrerPolicy = policy
- }
-}
-
-// https://fetch.spec.whatwg.org/#cross-origin-resource-policy-check
-function crossOriginResourcePolicyCheck () {
- // TODO
- return 'allowed'
-}
-
-// https://fetch.spec.whatwg.org/#concept-cors-check
-function corsCheck () {
- // TODO
- return 'success'
-}
-
-// https://fetch.spec.whatwg.org/#concept-tao-check
-function TAOCheck () {
- // TODO
- return 'success'
-}
-
-function appendFetchMetadata (httpRequest) {
- // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-dest-header
- // TODO
-
- // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-mode-header
-
- // 1. Assert: r’s url is a potentially trustworthy URL.
- // TODO
-
- // 2. Let header be a Structured Header whose value is a token.
- let header = null
-
- // 3. Set header’s value to r’s mode.
- header = httpRequest.mode
-
- // 4. Set a structured field value `Sec-Fetch-Mode`/header in r’s header list.
- httpRequest.headersList.set('sec-fetch-mode', header)
-
- // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-site-header
- // TODO
-
- // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-user-header
- // TODO
-}
-
-// https://fetch.spec.whatwg.org/#append-a-request-origin-header
-function appendRequestOriginHeader (request) {
- // 1. Let serializedOrigin be the result of byte-serializing a request origin with request.
- let serializedOrigin = request.origin
-
- // 2. If request’s response tainting is "cors" or request’s mode is "websocket", then append (`Origin`, serializedOrigin) to request’s header list.
- if (request.responseTainting === 'cors' || request.mode === 'websocket') {
- if (serializedOrigin) {
- request.headersList.append('origin', serializedOrigin)
- }
-
- // 3. Otherwise, if request’s method is neither `GET` nor `HEAD`, then:
- } else if (request.method !== 'GET' && request.method !== 'HEAD') {
- // 1. Switch on request’s referrer policy:
- switch (request.referrerPolicy) {
- case 'no-referrer':
- // Set serializedOrigin to `null`.
- serializedOrigin = null
- break
- case 'no-referrer-when-downgrade':
- case 'strict-origin':
- case 'strict-origin-when-cross-origin':
- // If request’s origin is a tuple origin, its scheme is "https", and request’s current URL’s scheme is not "https", then set serializedOrigin to `null`.
- if (request.origin && urlHasHttpsScheme(request.origin) && !urlHasHttpsScheme(requestCurrentURL(request))) {
- serializedOrigin = null
- }
- break
- case 'same-origin':
- // If request’s origin is not same origin with request’s current URL’s origin, then set serializedOrigin to `null`.
- if (!sameOrigin(request, requestCurrentURL(request))) {
- serializedOrigin = null
- }
- break
- default:
- // Do nothing.
- }
-
- if (serializedOrigin) {
- // 2. Append (`Origin`, serializedOrigin) to request’s header list.
- request.headersList.append('origin', serializedOrigin)
- }
- }
-}
-
-function coarsenedSharedCurrentTime (crossOriginIsolatedCapability) {
- // TODO
- return performance.now()
-}
-
-// https://fetch.spec.whatwg.org/#create-an-opaque-timing-info
-function createOpaqueTimingInfo (timingInfo) {
- return {
- startTime: timingInfo.startTime ?? 0,
- redirectStartTime: 0,
- redirectEndTime: 0,
- postRedirectStartTime: timingInfo.startTime ?? 0,
- finalServiceWorkerStartTime: 0,
- finalNetworkResponseStartTime: 0,
- finalNetworkRequestStartTime: 0,
- endTime: 0,
- encodedBodySize: 0,
- decodedBodySize: 0,
- finalConnectionTimingInfo: null
- }
-}
-
-// https://html.spec.whatwg.org/multipage/origin.html#policy-container
-function makePolicyContainer () {
- // Note: the fetch spec doesn't make use of embedder policy or CSP list
- return {
- referrerPolicy: 'strict-origin-when-cross-origin'
- }
-}
-
-// https://html.spec.whatwg.org/multipage/origin.html#clone-a-policy-container
-function clonePolicyContainer (policyContainer) {
- return {
- referrerPolicy: policyContainer.referrerPolicy
- }
-}
-
-// https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer
-function determineRequestsReferrer (request) {
- // 1. Let policy be request's referrer policy.
- const policy = request.referrerPolicy
-
- // Note: policy cannot (shouldn't) be null or an empty string.
- assert(policy)
-
- // 2. Let environment be request’s client.
-
- let referrerSource = null
-
- // 3. Switch on request’s referrer:
- if (request.referrer === 'client') {
- // Note: node isn't a browser and doesn't implement document/iframes,
- // so we bypass this step and replace it with our own.
-
- const globalOrigin = getGlobalOrigin()
-
- if (!globalOrigin || globalOrigin.origin === 'null') {
- return 'no-referrer'
- }
-
- // note: we need to clone it as it's mutated
- referrerSource = new URL(globalOrigin)
- } else if (request.referrer instanceof URL) {
- // Let referrerSource be request’s referrer.
- referrerSource = request.referrer
- }
-
- // 4. Let request’s referrerURL be the result of stripping referrerSource for
- // use as a referrer.
- let referrerURL = stripURLForReferrer(referrerSource)
-
- // 5. Let referrerOrigin be the result of stripping referrerSource for use as
- // a referrer, with the origin-only flag set to true.
- const referrerOrigin = stripURLForReferrer(referrerSource, true)
-
- // 6. If the result of serializing referrerURL is a string whose length is
- // greater than 4096, set referrerURL to referrerOrigin.
- if (referrerURL.toString().length > 4096) {
- referrerURL = referrerOrigin
- }
-
- const areSameOrigin = sameOrigin(request, referrerURL)
- const isNonPotentiallyTrustWorthy = isURLPotentiallyTrustworthy(referrerURL) &&
- !isURLPotentiallyTrustworthy(request.url)
-
- // 8. Execute the switch statements corresponding to the value of policy:
- switch (policy) {
- case 'origin': return referrerOrigin != null ? referrerOrigin : stripURLForReferrer(referrerSource, true)
- case 'unsafe-url': return referrerURL
- case 'same-origin':
- return areSameOrigin ? referrerOrigin : 'no-referrer'
- case 'origin-when-cross-origin':
- return areSameOrigin ? referrerURL : referrerOrigin
- case 'strict-origin-when-cross-origin': {
- const currentURL = requestCurrentURL(request)
-
- // 1. If the origin of referrerURL and the origin of request’s current
- // URL are the same, then return referrerURL.
- if (sameOrigin(referrerURL, currentURL)) {
- return referrerURL
- }
-
- // 2. If referrerURL is a potentially trustworthy URL and request’s
- // current URL is not a potentially trustworthy URL, then return no
- // referrer.
- if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) {
- return 'no-referrer'
- }
-
- // 3. Return referrerOrigin.
- return referrerOrigin
- }
- case 'strict-origin': // eslint-disable-line
- /**
- * 1. If referrerURL is a potentially trustworthy URL and
- * request’s current URL is not a potentially trustworthy URL,
- * then return no referrer.
- * 2. Return referrerOrigin
- */
- case 'no-referrer-when-downgrade': // eslint-disable-line
- /**
- * 1. If referrerURL is a potentially trustworthy URL and
- * request’s current URL is not a potentially trustworthy URL,
- * then return no referrer.
- * 2. Return referrerOrigin
- */
-
- default: // eslint-disable-line
- return isNonPotentiallyTrustWorthy ? 'no-referrer' : referrerOrigin
- }
-}
-
-/**
- * @see https://w3c.github.io/webappsec-referrer-policy/#strip-url
- * @param {URL} url
- * @param {boolean|undefined} originOnly
- */
-function stripURLForReferrer (url, originOnly) {
- // 1. Assert: url is a URL.
- assert(url instanceof URL)
-
- // 2. If url’s scheme is a local scheme, then return no referrer.
- if (url.protocol === 'file:' || url.protocol === 'about:' || url.protocol === 'blank:') {
- return 'no-referrer'
- }
-
- // 3. Set url’s username to the empty string.
- url.username = ''
-
- // 4. Set url’s password to the empty string.
- url.password = ''
-
- // 5. Set url’s fragment to null.
- url.hash = ''
-
- // 6. If the origin-only flag is true, then:
- if (originOnly) {
- // 1. Set url’s path to « the empty string ».
- url.pathname = ''
-
- // 2. Set url’s query to null.
- url.search = ''
- }
-
- // 7. Return url.
- return url
-}
-
-function isURLPotentiallyTrustworthy (url) {
- if (!(url instanceof URL)) {
- return false
- }
-
- // If child of about, return true
- if (url.href === 'about:blank' || url.href === 'about:srcdoc') {
- return true
- }
-
- // If scheme is data, return true
- if (url.protocol === 'data:') return true
-
- // If file, return true
- if (url.protocol === 'file:') return true
-
- return isOriginPotentiallyTrustworthy(url.origin)
-
- function isOriginPotentiallyTrustworthy (origin) {
- // If origin is explicitly null, return false
- if (origin == null || origin === 'null') return false
-
- const originAsURL = new URL(origin)
-
- // If secure, return true
- if (originAsURL.protocol === 'https:' || originAsURL.protocol === 'wss:') {
- return true
- }
-
- // If localhost or variants, return true
- if (/^127(?:\.[0-9]+){0,2}\.[0-9]+$|^\[(?:0*:)*?:?0*1\]$/.test(originAsURL.hostname) ||
- (originAsURL.hostname === 'localhost' || originAsURL.hostname.includes('localhost.')) ||
- (originAsURL.hostname.endsWith('.localhost'))) {
- return true
- }
-
- // If any other, return false
- return false
- }
-}
-
-/**
- * @see https://w3c.github.io/webappsec-subresource-integrity/#does-response-match-metadatalist
- * @param {Uint8Array} bytes
- * @param {string} metadataList
- */
-function bytesMatch (bytes, metadataList) {
- // If node is not built with OpenSSL support, we cannot check
- // a request's integrity, so allow it by default (the spec will
- // allow requests if an invalid hash is given, as precedence).
- /* istanbul ignore if: only if node is built with --without-ssl */
- if (crypto === undefined) {
- return true
- }
-
- // 1. Let parsedMetadata be the result of parsing metadataList.
- const parsedMetadata = parseMetadata(metadataList)
-
- // 2. If parsedMetadata is no metadata, return true.
- if (parsedMetadata === 'no metadata') {
- return true
- }
-
- // 3. If parsedMetadata is the empty set, return true.
- if (parsedMetadata.length === 0) {
- return true
- }
-
- // 4. Let metadata be the result of getting the strongest
- // metadata from parsedMetadata.
- const list = parsedMetadata.sort((c, d) => d.algo.localeCompare(c.algo))
- // get the strongest algorithm
- const strongest = list[0].algo
- // get all entries that use the strongest algorithm; ignore weaker
- const metadata = list.filter((item) => item.algo === strongest)
-
- // 5. For each item in metadata:
- for (const item of metadata) {
- // 1. Let algorithm be the alg component of item.
- const algorithm = item.algo
-
- // 2. Let expectedValue be the val component of item.
- let expectedValue = item.hash
-
- // See https://github.com/web-platform-tests/wpt/commit/e4c5cc7a5e48093220528dfdd1c4012dc3837a0e
- // "be liberal with padding". This is annoying, and it's not even in the spec.
-
- if (expectedValue.endsWith('==')) {
- expectedValue = expectedValue.slice(0, -2)
- }
-
- // 3. Let actualValue be the result of applying algorithm to bytes.
- let actualValue = crypto.createHash(algorithm).update(bytes).digest('base64')
-
- if (actualValue.endsWith('==')) {
- actualValue = actualValue.slice(0, -2)
- }
-
- // 4. If actualValue is a case-sensitive match for expectedValue,
- // return true.
- if (actualValue === expectedValue) {
- return true
- }
-
- let actualBase64URL = crypto.createHash(algorithm).update(bytes).digest('base64url')
-
- if (actualBase64URL.endsWith('==')) {
- actualBase64URL = actualBase64URL.slice(0, -2)
- }
-
- if (actualBase64URL === expectedValue) {
- return true
- }
- }
-
- // 6. Return false.
- return false
-}
-
-// https://w3c.github.io/webappsec-subresource-integrity/#grammardef-hash-with-options
-// https://www.w3.org/TR/CSP2/#source-list-syntax
-// https://www.rfc-editor.org/rfc/rfc5234#appendix-B.1
-const parseHashWithOptions = /((?<algo>sha256|sha384|sha512)-(?<hash>[A-z0-9+/]{1}.*={0,2}))( +[\x21-\x7e]?)?/i
-
-/**
- * @see https://w3c.github.io/webappsec-subresource-integrity/#parse-metadata
- * @param {string} metadata
- */
-function parseMetadata (metadata) {
- // 1. Let result be the empty set.
- /** @type {{ algo: string, hash: string }[]} */
- const result = []
-
- // 2. Let empty be equal to true.
- let empty = true
-
- const supportedHashes = crypto.getHashes()
-
- // 3. For each token returned by splitting metadata on spaces:
- for (const token of metadata.split(' ')) {
- // 1. Set empty to false.
- empty = false
-
- // 2. Parse token as a hash-with-options.
- const parsedToken = parseHashWithOptions.exec(token)
-
- // 3. If token does not parse, continue to the next token.
- if (parsedToken === null || parsedToken.groups === undefined) {
- // Note: Chromium blocks the request at this point, but Firefox
- // gives a warning that an invalid integrity was given. The
- // correct behavior is to ignore these, and subsequently not
- // check the integrity of the resource.
- continue
- }
-
- // 4. Let algorithm be the hash-algo component of token.
- const algorithm = parsedToken.groups.algo
-
- // 5. If algorithm is a hash function recognized by the user
- // agent, add the parsed token to result.
- if (supportedHashes.includes(algorithm.toLowerCase())) {
- result.push(parsedToken.groups)
- }
- }
-
- // 4. Return no metadata if empty is true, otherwise return result.
- if (empty === true) {
- return 'no metadata'
- }
-
- return result
-}
-
-// https://w3c.github.io/webappsec-upgrade-insecure-requests/#upgrade-request
-function tryUpgradeRequestToAPotentiallyTrustworthyURL (request) {
- // TODO
-}
-
-/**
- * @link {https://html.spec.whatwg.org/multipage/origin.html#same-origin}
- * @param {URL} A
- * @param {URL} B
- */
-function sameOrigin (A, B) {
- // 1. If A and B are the same opaque origin, then return true.
- if (A.origin === B.origin && A.origin === 'null') {
- return true
- }
-
- // 2. If A and B are both tuple origins and their schemes,
- // hosts, and port are identical, then return true.
- if (A.protocol === B.protocol && A.hostname === B.hostname && A.port === B.port) {
- return true
- }
-
- // 3. Return false.
- return false
-}
-
-function createDeferredPromise () {
- let res
- let rej
- const promise = new Promise((resolve, reject) => {
- res = resolve
- rej = reject
- })
-
- return { promise, resolve: res, reject: rej }
-}
-
-function isAborted (fetchParams) {
- return fetchParams.controller.state === 'aborted'
-}
-
-function isCancelled (fetchParams) {
- return fetchParams.controller.state === 'aborted' ||
- fetchParams.controller.state === 'terminated'
-}
-
-// https://fetch.spec.whatwg.org/#concept-method-normalize
-function normalizeMethod (method) {
- return /^(DELETE|GET|HEAD|OPTIONS|POST|PUT)$/i.test(method)
- ? method.toUpperCase()
- : method
-}
-
-// https://infra.spec.whatwg.org/#serialize-a-javascript-value-to-a-json-string
-function serializeJavascriptValueToJSONString (value) {
- // 1. Let result be ? Call(%JSON.stringify%, undefined, « value »).
- const result = JSON.stringify(value)
-
- // 2. If result is undefined, then throw a TypeError.
- if (result === undefined) {
- throw new TypeError('Value is not JSON serializable')
- }
-
- // 3. Assert: result is a string.
- assert(typeof result === 'string')
-
- // 4. Return result.
- return result
-}
-
-// https://tc39.es/ecma262/#sec-%25iteratorprototype%25-object
-const esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))
-
-/**
- * @see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object
- * @param {() => unknown[]} iterator
- * @param {string} name name of the instance
- * @param {'key'|'value'|'key+value'} kind
- */
-function makeIterator (iterator, name, kind) {
- const object = {
- index: 0,
- kind,
- target: iterator
- }
-
- const i = {
- next () {
- // 1. Let interface be the interface for which the iterator prototype object exists.
-
- // 2. Let thisValue be the this value.
-
- // 3. Let object be ? ToObject(thisValue).
-
- // 4. If object is a platform object, then perform a security
- // check, passing:
-
- // 5. If object is not a default iterator object for interface,
- // then throw a TypeError.
- if (Object.getPrototypeOf(this) !== i) {
- throw new TypeError(
- `'next' called on an object that does not implement interface ${name} Iterator.`
- )
- }
-
- // 6. Let index be object’s index.
- // 7. Let kind be object’s kind.
- // 8. Let values be object’s target's value pairs to iterate over.
- const { index, kind, target } = object
- const values = target()
-
- // 9. Let len be the length of values.
- const len = values.length
-
- // 10. If index is greater than or equal to len, then return
- // CreateIterResultObject(undefined, true).
- if (index >= len) {
- return { value: undefined, done: true }
- }
-
- // 11. Let pair be the entry in values at index index.
- const pair = values[index]
-
- // 12. Set object’s index to index + 1.
- object.index = index + 1
-
- // 13. Return the iterator result for pair and kind.
- return iteratorResult(pair, kind)
- },
- // The class string of an iterator prototype object for a given interface is the
- // result of concatenating the identifier of the interface and the string " Iterator".
- [Symbol.toStringTag]: `${name} Iterator`
- }
-
- // The [[Prototype]] internal slot of an iterator prototype object must be %IteratorPrototype%.
- Object.setPrototypeOf(i, esIteratorPrototype)
- // esIteratorPrototype needs to be the prototype of i
- // which is the prototype of an empty object. Yes, it's confusing.
- return Object.setPrototypeOf({}, i)
-}
-
-// https://webidl.spec.whatwg.org/#iterator-result
-function iteratorResult (pair, kind) {
- let result
-
- // 1. Let result be a value determined by the value of kind:
- switch (kind) {
- case 'key': {
- // 1. Let idlKey be pair’s key.
- // 2. Let key be the result of converting idlKey to an
- // ECMAScript value.
- // 3. result is key.
- result = pair[0]
- break
- }
- case 'value': {
- // 1. Let idlValue be pair’s value.
- // 2. Let value be the result of converting idlValue to
- // an ECMAScript value.
- // 3. result is value.
- result = pair[1]
- break
- }
- case 'key+value': {
- // 1. Let idlKey be pair’s key.
- // 2. Let idlValue be pair’s value.
- // 3. Let key be the result of converting idlKey to an
- // ECMAScript value.
- // 4. Let value be the result of converting idlValue to
- // an ECMAScript value.
- // 5. Let array be ! ArrayCreate(2).
- // 6. Call ! CreateDataProperty(array, "0", key).
- // 7. Call ! CreateDataProperty(array, "1", value).
- // 8. result is array.
- result = pair
- break
- }
- }
-
- // 2. Return CreateIterResultObject(result, false).
- return { value: result, done: false }
-}
-
-/**
- * @see https://fetch.spec.whatwg.org/#body-fully-read
- */
-async function fullyReadBody (body, processBody, processBodyError) {
- // 1. If taskDestination is null, then set taskDestination to
- // the result of starting a new parallel queue.
-
- // 2. Let successSteps given a byte sequence bytes be to queue a
- // fetch task to run processBody given bytes, with taskDestination.
- const successSteps = processBody
-
- // 3. Let errorSteps be to queue a fetch task to run processBodyError,
- // with taskDestination.
- const errorSteps = processBodyError
-
- // 4. Let reader be the result of getting a reader for body’s stream.
- // If that threw an exception, then run errorSteps with that
- // exception and return.
- let reader
-
- try {
- reader = body.stream.getReader()
- } catch (e) {
- errorSteps(e)
- return
- }
-
- // 5. Read all bytes from reader, given successSteps and errorSteps.
- try {
- const result = await readAllBytes(reader)
- successSteps(result)
- } catch (e) {
- errorSteps(e)
- }
-}
-
-/** @type {ReadableStream} */
-let ReadableStream = globalThis.ReadableStream
-
-function isReadableStreamLike (stream) {
- if (!ReadableStream) {
- ReadableStream = require('stream/web').ReadableStream
- }
-
- return stream instanceof ReadableStream || (
- stream[Symbol.toStringTag] === 'ReadableStream' &&
- typeof stream.tee === 'function'
- )
-}
-
-const MAXIMUM_ARGUMENT_LENGTH = 65535
-
-/**
- * @see https://infra.spec.whatwg.org/#isomorphic-decode
- * @param {number[]|Uint8Array} input
- */
-function isomorphicDecode (input) {
- // 1. To isomorphic decode a byte sequence input, return a string whose code point
- // length is equal to input’s length and whose code points have the same values
- // as the values of input’s bytes, in the same order.
-
- if (input.length < MAXIMUM_ARGUMENT_LENGTH) {
- return String.fromCharCode(...input)
- }
-
- return input.reduce((previous, current) => previous + String.fromCharCode(current), '')
-}
-
-/**
- * @param {ReadableStreamController<Uint8Array>} controller
- */
-function readableStreamClose (controller) {
- try {
- controller.close()
- } catch (err) {
- // TODO: add comment explaining why this error occurs.
- if (!err.message.includes('Controller is already closed')) {
- throw err
- }
- }
-}
-
-/**
- * @see https://infra.spec.whatwg.org/#isomorphic-encode
- * @param {string} input
- */
-function isomorphicEncode (input) {
- // 1. Assert: input contains no code points greater than U+00FF.
- for (let i = 0; i < input.length; i++) {
- assert(input.charCodeAt(i) <= 0xFF)
- }
-
- // 2. Return a byte sequence whose length is equal to input’s code
- // point length and whose bytes have the same values as the
- // values of input’s code points, in the same order
- return input
-}
-
-/**
- * @see https://streams.spec.whatwg.org/#readablestreamdefaultreader-read-all-bytes
- * @see https://streams.spec.whatwg.org/#read-loop
- * @param {ReadableStreamDefaultReader} reader
- */
-async function readAllBytes (reader) {
- const bytes = []
- let byteLength = 0
-
- while (true) {
- const { done, value: chunk } = await reader.read()
-
- if (done) {
- // 1. Call successSteps with bytes.
- return Buffer.concat(bytes, byteLength)
- }
-
- // 1. If chunk is not a Uint8Array object, call failureSteps
- // with a TypeError and abort these steps.
- if (!isUint8Array(chunk)) {
- throw new TypeError('Received non-Uint8Array chunk')
- }
-
- // 2. Append the bytes represented by chunk to bytes.
- bytes.push(chunk)
- byteLength += chunk.length
-
- // 3. Read-loop given reader, bytes, successSteps, and failureSteps.
- }
-}
-
-/**
- * @see https://fetch.spec.whatwg.org/#is-local
- * @param {URL} url
- */
-function urlIsLocal (url) {
- assert('protocol' in url) // ensure it's a url object
-
- const protocol = url.protocol
-
- return protocol === 'about:' || protocol === 'blob:' || protocol === 'data:'
-}
-
-/**
- * @param {string|URL} url
- */
-function urlHasHttpsScheme (url) {
- if (typeof url === 'string') {
- return url.startsWith('https:')
- }
-
- return url.protocol === 'https:'
-}
-
-/**
- * @see https://fetch.spec.whatwg.org/#http-scheme
- * @param {URL} url
- */
-function urlIsHttpHttpsScheme (url) {
- assert('protocol' in url) // ensure it's a url object
-
- const protocol = url.protocol
-
- return protocol === 'http:' || protocol === 'https:'
-}
-
-/**
- * Fetch supports node >= 16.8.0, but Object.hasOwn was added in v16.9.0.
- */
-const hasOwn = Object.hasOwn || ((dict, key) => Object.prototype.hasOwnProperty.call(dict, key))
-
-module.exports = {
- isAborted,
- isCancelled,
- createDeferredPromise,
- ReadableStreamFrom,
- toUSVString,
- tryUpgradeRequestToAPotentiallyTrustworthyURL,
- coarsenedSharedCurrentTime,
- determineRequestsReferrer,
- makePolicyContainer,
- clonePolicyContainer,
- appendFetchMetadata,
- appendRequestOriginHeader,
- TAOCheck,
- corsCheck,
- crossOriginResourcePolicyCheck,
- createOpaqueTimingInfo,
- setRequestReferrerPolicyOnRedirect,
- isValidHTTPToken,
- requestBadPort,
- requestCurrentURL,
- responseURL,
- responseLocationURL,
- isBlobLike,
- isURLPotentiallyTrustworthy,
- isValidReasonPhrase,
- sameOrigin,
- normalizeMethod,
- serializeJavascriptValueToJSONString,
- makeIterator,
- isValidHeaderName,
- isValidHeaderValue,
- hasOwn,
- isErrorLike,
- fullyReadBody,
- bytesMatch,
- isReadableStreamLike,
- readableStreamClose,
- isomorphicEncode,
- isomorphicDecode,
- urlIsLocal,
- urlHasHttpsScheme,
- urlIsHttpHttpsScheme,
- readAllBytes
-}
diff --git a/g4f/Provider/npm/node_modules/undici/lib/fetch/webidl.js b/g4f/Provider/npm/node_modules/undici/lib/fetch/webidl.js
deleted file mode 100644
index 38a05e65..00000000
--- a/g4f/Provider/npm/node_modules/undici/lib/fetch/webidl.js
+++ /dev/null
@@ -1,648 +0,0 @@
-'use strict'
-
-const { types } = require('util')
-const { hasOwn, toUSVString } = require('./util')
-
-/** @type {import('../../types/webidl').Webidl} */
-const webidl = {}
-webidl.converters = {}
-webidl.util = {}
-webidl.errors = {}
-
-webidl.errors.exception = function (message) {
- return new TypeError(`${message.header}: ${message.message}`)
-}
-
-webidl.errors.conversionFailed = function (context) {
- const plural = context.types.length === 1 ? '' : ' one of'
- const message =
- `${context.argument} could not be converted to` +
- `${plural}: ${context.types.join(', ')}.`
-
- return webidl.errors.exception({
- header: context.prefix,
- message
- })
-}
-
-webidl.errors.invalidArgument = function (context) {
- return webidl.errors.exception({
- header: context.prefix,
- message: `"${context.value}" is an invalid ${context.type}.`
- })
-}
-
-// https://webidl.spec.whatwg.org/#implements
-webidl.brandCheck = function (V, I, opts = undefined) {
- if (opts?.strict !== false && !(V instanceof I)) {
- throw new TypeError('Illegal invocation')
- } else {
- return V?.[Symbol.toStringTag] === I.prototype[Symbol.toStringTag]
- }
-}
-
-webidl.argumentLengthCheck = function ({ length }, min, ctx) {
- if (length < min) {
- throw webidl.errors.exception({
- message: `${min} argument${min !== 1 ? 's' : ''} required, ` +
- `but${length ? ' only' : ''} ${length} found.`,
- ...ctx
- })
- }
-}
-
-webidl.illegalConstructor = function () {
- throw webidl.errors.exception({
- header: 'TypeError',
- message: 'Illegal constructor'
- })
-}
-
-// https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values
-webidl.util.Type = function (V) {
- switch (typeof V) {
- case 'undefined': return 'Undefined'
- case 'boolean': return 'Boolean'
- case 'string': return 'String'
- case 'symbol': return 'Symbol'
- case 'number': return 'Number'
- case 'bigint': return 'BigInt'
- case 'function':
- case 'object': {
- if (V === null) {
- return 'Null'
- }
-
- return 'Object'
- }
- }
-}
-
-// https://webidl.spec.whatwg.org/#abstract-opdef-converttoint
-webidl.util.ConvertToInt = function (V, bitLength, signedness, opts = {}) {
- let upperBound
- let lowerBound
-
- // 1. If bitLength is 64, then:
- if (bitLength === 64) {
- // 1. Let upperBound be 2^53 − 1.
- upperBound = Math.pow(2, 53) - 1
-
- // 2. If signedness is "unsigned", then let lowerBound be 0.
- if (signedness === 'unsigned') {
- lowerBound = 0
- } else {
- // 3. Otherwise let lowerBound be −2^53 + 1.
- lowerBound = Math.pow(-2, 53) + 1
- }
- } else if (signedness === 'unsigned') {
- // 2. Otherwise, if signedness is "unsigned", then:
-
- // 1. Let lowerBound be 0.
- lowerBound = 0
-
- // 2. Let upperBound be 2^bitLength − 1.
- upperBound = Math.pow(2, bitLength) - 1
- } else {
- // 3. Otherwise:
-
- // 1. Let lowerBound be -2^bitLength − 1.
- lowerBound = Math.pow(-2, bitLength) - 1
-
- // 2. Let upperBound be 2^bitLength − 1 − 1.
- upperBound = Math.pow(2, bitLength - 1) - 1
- }
-
- // 4. Let x be ? ToNumber(V).
- let x = Number(V)
-
- // 5. If x is −0, then set x to +0.
- if (x === 0) {
- x = 0
- }
-
- // 6. If the conversion is to an IDL type associated
- // with the [EnforceRange] extended attribute, then:
- if (opts.enforceRange === true) {
- // 1. If x is NaN, +∞, or −∞, then throw a TypeError.
- if (
- Number.isNaN(x) ||
- x === Number.POSITIVE_INFINITY ||
- x === Number.NEGATIVE_INFINITY
- ) {
- throw webidl.errors.exception({
- header: 'Integer conversion',
- message: `Could not convert ${V} to an integer.`
- })
- }
-
- // 2. Set x to IntegerPart(x).
- x = webidl.util.IntegerPart(x)
-
- // 3. If x < lowerBound or x > upperBound, then
- // throw a TypeError.
- if (x < lowerBound || x > upperBound) {
- throw webidl.errors.exception({
- header: 'Integer conversion',
- message: `Value must be between ${lowerBound}-${upperBound}, got ${x}.`
- })
- }
-
- // 4. Return x.
- return x
- }
-
- // 7. If x is not NaN and the conversion is to an IDL
- // type associated with the [Clamp] extended
- // attribute, then:
- if (!Number.isNaN(x) && opts.clamp === true) {
- // 1. Set x to min(max(x, lowerBound), upperBound).
- x = Math.min(Math.max(x, lowerBound), upperBound)
-
- // 2. Round x to the nearest integer, choosing the
- // even integer if it lies halfway between two,
- // and choosing +0 rather than −0.
- if (Math.floor(x) % 2 === 0) {
- x = Math.floor(x)
- } else {
- x = Math.ceil(x)
- }
-
- // 3. Return x.
- return x
- }
-
- // 8. If x is NaN, +0, +∞, or −∞, then return +0.
- if (
- Number.isNaN(x) ||
- (x === 0 && Object.is(0, x)) ||
- x === Number.POSITIVE_INFINITY ||
- x === Number.NEGATIVE_INFINITY
- ) {
- return 0
- }
-
- // 9. Set x to IntegerPart(x).
- x = webidl.util.IntegerPart(x)
-
- // 10. Set x to x modulo 2^bitLength.
- x = x % Math.pow(2, bitLength)
-
- // 11. If signedness is "signed" and x ≥ 2^bitLength − 1,
- // then return x − 2^bitLength.
- if (signedness === 'signed' && x >= Math.pow(2, bitLength) - 1) {
- return x - Math.pow(2, bitLength)
- }
-
- // 12. Otherwise, return x.
- return x
-}
-
-// https://webidl.spec.whatwg.org/#abstract-opdef-integerpart
-webidl.util.IntegerPart = function (n) {
- // 1. Let r be floor(abs(n)).
- const r = Math.floor(Math.abs(n))
-
- // 2. If n < 0, then return -1 × r.
- if (n < 0) {
- return -1 * r
- }
-
- // 3. Otherwise, return r.
- return r
-}
-
-// https://webidl.spec.whatwg.org/#es-sequence
-webidl.sequenceConverter = function (converter) {
- return (V) => {
- // 1. If Type(V) is not Object, throw a TypeError.
- if (webidl.util.Type(V) !== 'Object') {
- throw webidl.errors.exception({
- header: 'Sequence',
- message: `Value of type ${webidl.util.Type(V)} is not an Object.`
- })
- }
-
- // 2. Let method be ? GetMethod(V, @@iterator).
- /** @type {Generator} */
- const method = V?.[Symbol.iterator]?.()
- const seq = []
-
- // 3. If method is undefined, throw a TypeError.
- if (
- method === undefined ||
- typeof method.next !== 'function'
- ) {
- throw webidl.errors.exception({
- header: 'Sequence',
- message: 'Object is not an iterator.'
- })
- }
-
- // https://webidl.spec.whatwg.org/#create-sequence-from-iterable
- while (true) {
- const { done, value } = method.next()
-
- if (done) {
- break
- }
-
- seq.push(converter(value))
- }
-
- return seq
- }
-}
-
-// https://webidl.spec.whatwg.org/#es-to-record
-webidl.recordConverter = function (keyConverter, valueConverter) {
- return (O) => {
- // 1. If Type(O) is not Object, throw a TypeError.
- if (webidl.util.Type(O) !== 'Object') {
- throw webidl.errors.exception({
- header: 'Record',
- message: `Value of type ${webidl.util.Type(O)} is not an Object.`
- })
- }
-
- // 2. Let result be a new empty instance of record<K, V>.
- const result = {}
-
- if (!types.isProxy(O)) {
- // Object.keys only returns enumerable properties
- const keys = Object.keys(O)
-
- for (const key of keys) {
- // 1. Let typedKey be key converted to an IDL value of type K.
- const typedKey = keyConverter(key)
-
- // 2. Let value be ? Get(O, key).
- // 3. Let typedValue be value converted to an IDL value of type V.
- const typedValue = valueConverter(O[key])
-
- // 4. Set result[typedKey] to typedValue.
- result[typedKey] = typedValue
- }
-
- // 5. Return result.
- return result
- }
-
- // 3. Let keys be ? O.[[OwnPropertyKeys]]().
- const keys = Reflect.ownKeys(O)
-
- // 4. For each key of keys.
- for (const key of keys) {
- // 1. Let desc be ? O.[[GetOwnProperty]](key).
- const desc = Reflect.getOwnPropertyDescriptor(O, key)
-
- // 2. If desc is not undefined and desc.[[Enumerable]] is true:
- if (desc?.enumerable) {
- // 1. Let typedKey be key converted to an IDL value of type K.
- const typedKey = keyConverter(key)
-
- // 2. Let value be ? Get(O, key).
- // 3. Let typedValue be value converted to an IDL value of type V.
- const typedValue = valueConverter(O[key])
-
- // 4. Set result[typedKey] to typedValue.
- result[typedKey] = typedValue
- }
- }
-
- // 5. Return result.
- return result
- }
-}
-
-webidl.interfaceConverter = function (i) {
- return (V, opts = {}) => {
- if (opts.strict !== false && !(V instanceof i)) {
- throw webidl.errors.exception({
- header: i.name,
- message: `Expected ${V} to be an instance of ${i.name}.`
- })
- }
-
- return V
- }
-}
-
-webidl.dictionaryConverter = function (converters) {
- return (dictionary) => {
- const type = webidl.util.Type(dictionary)
- const dict = {}
-
- if (type === 'Null' || type === 'Undefined') {
- return dict
- } else if (type !== 'Object') {
- throw webidl.errors.exception({
- header: 'Dictionary',
- message: `Expected ${dictionary} to be one of: Null, Undefined, Object.`
- })
- }
-
- for (const options of converters) {
- const { key, defaultValue, required, converter } = options
-
- if (required === true) {
- if (!hasOwn(dictionary, key)) {
- throw webidl.errors.exception({
- header: 'Dictionary',
- message: `Missing required key "${key}".`
- })
- }
- }
-
- let value = dictionary[key]
- const hasDefault = hasOwn(options, 'defaultValue')
-
- // Only use defaultValue if value is undefined and
- // a defaultValue options was provided.
- if (hasDefault && value !== null) {
- value = value ?? defaultValue
- }
-
- // A key can be optional and have no default value.
- // When this happens, do not perform a conversion,
- // and do not assign the key a value.
- if (required || hasDefault || value !== undefined) {
- value = converter(value)
-
- if (
- options.allowedValues &&
- !options.allowedValues.includes(value)
- ) {
- throw webidl.errors.exception({
- header: 'Dictionary',
- message: `${value} is not an accepted type. Expected one of ${options.allowedValues.join(', ')}.`
- })
- }
-
- dict[key] = value
- }
- }
-
- return dict
- }
-}
-
-webidl.nullableConverter = function (converter) {
- return (V) => {
- if (V === null) {
- return V
- }
-
- return converter(V)
- }
-}
-
-// https://webidl.spec.whatwg.org/#es-DOMString
-webidl.converters.DOMString = function (V, opts = {}) {
- // 1. If V is null and the conversion is to an IDL type
- // associated with the [LegacyNullToEmptyString]
- // extended attribute, then return the DOMString value
- // that represents the empty string.
- if (V === null && opts.legacyNullToEmptyString) {
- return ''
- }
-
- // 2. Let x be ? ToString(V).
- if (typeof V === 'symbol') {
- throw new TypeError('Could not convert argument of type symbol to string.')
- }
-
- // 3. Return the IDL DOMString value that represents the
- // same sequence of code units as the one the
- // ECMAScript String value x represents.
- return String(V)
-}
-
-// https://webidl.spec.whatwg.org/#es-ByteString
-webidl.converters.ByteString = function (V) {
- // 1. Let x be ? ToString(V).
- // Note: DOMString converter perform ? ToString(V)
- const x = webidl.converters.DOMString(V)
-
- // 2. If the value of any element of x is greater than
- // 255, then throw a TypeError.
- for (let index = 0; index < x.length; index++) {
- const charCode = x.charCodeAt(index)
-
- if (charCode > 255) {
- throw new TypeError(
- 'Cannot convert argument to a ByteString because the character at ' +
- `index ${index} has a value of ${charCode} which is greater than 255.`
- )
- }
- }
-
- // 3. Return an IDL ByteString value whose length is the
- // length of x, and where the value of each element is
- // the value of the corresponding element of x.
- return x
-}
-
-// https://webidl.spec.whatwg.org/#es-USVString
-webidl.converters.USVString = toUSVString
-
-// https://webidl.spec.whatwg.org/#es-boolean
-webidl.converters.boolean = function (V) {
- // 1. Let x be the result of computing ToBoolean(V).
- const x = Boolean(V)
-
- // 2. Return the IDL boolean value that is the one that represents
- // the same truth value as the ECMAScript Boolean value x.
- return x
-}
-
-// https://webidl.spec.whatwg.org/#es-any
-webidl.converters.any = function (V) {
- return V
-}
-
-// https://webidl.spec.whatwg.org/#es-long-long
-webidl.converters['long long'] = function (V) {
- // 1. Let x be ? ConvertToInt(V, 64, "signed").
- const x = webidl.util.ConvertToInt(V, 64, 'signed')
-
- // 2. Return the IDL long long value that represents
- // the same numeric value as x.
- return x
-}
-
-// https://webidl.spec.whatwg.org/#es-unsigned-long-long
-webidl.converters['unsigned long long'] = function (V) {
- // 1. Let x be ? ConvertToInt(V, 64, "unsigned").
- const x = webidl.util.ConvertToInt(V, 64, 'unsigned')
-
- // 2. Return the IDL unsigned long long value that
- // represents the same numeric value as x.
- return x
-}
-
-// https://webidl.spec.whatwg.org/#es-unsigned-long
-webidl.converters['unsigned long'] = function (V) {
- // 1. Let x be ? ConvertToInt(V, 32, "unsigned").
- const x = webidl.util.ConvertToInt(V, 32, 'unsigned')
-
- // 2. Return the IDL unsigned long value that
- // represents the same numeric value as x.
- return x
-}
-
-// https://webidl.spec.whatwg.org/#es-unsigned-short
-webidl.converters['unsigned short'] = function (V, opts) {
- // 1. Let x be ? ConvertToInt(V, 16, "unsigned").
- const x = webidl.util.ConvertToInt(V, 16, 'unsigned', opts)
-
- // 2. Return the IDL unsigned short value that represents
- // the same numeric value as x.
- return x
-}
-
-// https://webidl.spec.whatwg.org/#idl-ArrayBuffer
-webidl.converters.ArrayBuffer = function (V, opts = {}) {
- // 1. If Type(V) is not Object, or V does not have an
- // [[ArrayBufferData]] internal slot, then throw a
- // TypeError.
- // see: https://tc39.es/ecma262/#sec-properties-of-the-arraybuffer-instances
- // see: https://tc39.es/ecma262/#sec-properties-of-the-sharedarraybuffer-instances
- if (
- webidl.util.Type(V) !== 'Object' ||
- !types.isAnyArrayBuffer(V)
- ) {
- throw webidl.errors.conversionFailed({
- prefix: `${V}`,
- argument: `${V}`,
- types: ['ArrayBuffer']
- })
- }
-
- // 2. If the conversion is not to an IDL type associated
- // with the [AllowShared] extended attribute, and
- // IsSharedArrayBuffer(V) is true, then throw a
- // TypeError.
- if (opts.allowShared === false && types.isSharedArrayBuffer(V)) {
- throw webidl.errors.exception({
- header: 'ArrayBuffer',
- message: 'SharedArrayBuffer is not allowed.'
- })
- }
-
- // 3. If the conversion is not to an IDL type associated
- // with the [AllowResizable] extended attribute, and
- // IsResizableArrayBuffer(V) is true, then throw a
- // TypeError.
- // Note: resizable ArrayBuffers are currently a proposal.
-
- // 4. Return the IDL ArrayBuffer value that is a
- // reference to the same object as V.
- return V
-}
-
-webidl.converters.TypedArray = function (V, T, opts = {}) {
- // 1. Let T be the IDL type V is being converted to.
-
- // 2. If Type(V) is not Object, or V does not have a
- // [[TypedArrayName]] internal slot with a value
- // equal to T’s name, then throw a TypeError.
- if (
- webidl.util.Type(V) !== 'Object' ||
- !types.isTypedArray(V) ||
- V.constructor.name !== T.name
- ) {
- throw webidl.errors.conversionFailed({
- prefix: `${T.name}`,
- argument: `${V}`,
- types: [T.name]
- })
- }
-
- // 3. If the conversion is not to an IDL type associated
- // with the [AllowShared] extended attribute, and
- // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is
- // true, then throw a TypeError.
- if (opts.allowShared === false && types.isSharedArrayBuffer(V.buffer)) {
- throw webidl.errors.exception({
- header: 'ArrayBuffer',
- message: 'SharedArrayBuffer is not allowed.'
- })
- }
-
- // 4. If the conversion is not to an IDL type associated
- // with the [AllowResizable] extended attribute, and
- // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is
- // true, then throw a TypeError.
- // Note: resizable array buffers are currently a proposal
-
- // 5. Return the IDL value of type T that is a reference
- // to the same object as V.
- return V
-}
-
-webidl.converters.DataView = function (V, opts = {}) {
- // 1. If Type(V) is not Object, or V does not have a
- // [[DataView]] internal slot, then throw a TypeError.
- if (webidl.util.Type(V) !== 'Object' || !types.isDataView(V)) {
- throw webidl.errors.exception({
- header: 'DataView',
- message: 'Object is not a DataView.'
- })
- }
-
- // 2. If the conversion is not to an IDL type associated
- // with the [AllowShared] extended attribute, and
- // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is true,
- // then throw a TypeError.
- if (opts.allowShared === false && types.isSharedArrayBuffer(V.buffer)) {
- throw webidl.errors.exception({
- header: 'ArrayBuffer',
- message: 'SharedArrayBuffer is not allowed.'
- })
- }
-
- // 3. If the conversion is not to an IDL type associated
- // with the [AllowResizable] extended attribute, and
- // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is
- // true, then throw a TypeError.
- // Note: resizable ArrayBuffers are currently a proposal
-
- // 4. Return the IDL DataView value that is a reference
- // to the same object as V.
- return V
-}
-
-// https://webidl.spec.whatwg.org/#BufferSource
-webidl.converters.BufferSource = function (V, opts = {}) {
- if (types.isAnyArrayBuffer(V)) {
- return webidl.converters.ArrayBuffer(V, opts)
- }
-
- if (types.isTypedArray(V)) {
- return webidl.converters.TypedArray(V, V.constructor)
- }
-
- if (types.isDataView(V)) {
- return webidl.converters.DataView(V, opts)
- }
-
- throw new TypeError(`Could not convert ${V} to a BufferSource.`)
-}
-
-webidl.converters['sequence<ByteString>'] = webidl.sequenceConverter(
- webidl.converters.ByteString
-)
-
-webidl.converters['sequence<sequence<ByteString>>'] = webidl.sequenceConverter(
- webidl.converters['sequence<ByteString>']
-)
-
-webidl.converters['record<ByteString, ByteString>'] = webidl.recordConverter(
- webidl.converters.ByteString,
- webidl.converters.ByteString
-)
-
-module.exports = {
- webidl
-}