diff --git a/lib/web/fetch/body.js b/lib/web/fetch/body.js index 464e7b50e5c..683a67400c8 100644 --- a/lib/web/fetch/body.js +++ b/lib/web/fetch/body.js @@ -3,8 +3,6 @@ const util = require('../../core/util') const { ReadableStreamFrom, - isBlobLike, - isReadableStreamLike, readableStreamClose, createDeferredPromise, fullyReadBody, @@ -44,7 +42,7 @@ function extractBody (object, keepalive = false) { // 2. If object is a ReadableStream object, then set stream to object. if (object instanceof ReadableStream) { stream = object - } else if (isBlobLike(object)) { + } else if (object instanceof Blob) { // 3. Otherwise, if object is a Blob object, set stream to the // result of running object’s get stream. stream = object.stream() @@ -67,7 +65,7 @@ function extractBody (object, keepalive = false) { } // 5. Assert: stream is a ReadableStream object. - assert(isReadableStreamLike(stream)) + assert(stream instanceof ReadableStream) // 6. Let action be null. let action = null @@ -112,7 +110,7 @@ function extractBody (object, keepalive = false) { // 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)) { + } else if (object instanceof FormData) { const boundary = `----formdata-undici-0${`${Math.floor(Math.random() * 1e11)}`.padStart(11, '0')}` const prefix = `--${boundary}\r\nContent-Disposition: form-data` @@ -178,7 +176,7 @@ function extractBody (object, keepalive = false) { // 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)) { + } else if (object instanceof Blob) { // Blob // Set source to object. diff --git a/lib/web/fetch/file.js b/lib/web/fetch/file.js deleted file mode 100644 index 31ba40718ec..00000000000 --- a/lib/web/fetch/file.js +++ /dev/null @@ -1,126 +0,0 @@ -'use strict' - -const { Blob, File } = require('node:buffer') -const { kState } = require('./symbols') -const { webidl } = require('./webidl') - -// TODO(@KhafraDev): remove -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' - } -} - -webidl.converters.Blob = webidl.interfaceConverter(Blob) - -// 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 ( - (object instanceof File) || - ( - object && - (typeof object.stream === 'function' || - typeof object.arrayBuffer === 'function') && - object[Symbol.toStringTag] === 'File' - ) - ) -} - -module.exports = { FileLike, isFileLike } diff --git a/lib/web/fetch/formdata-parser.js b/lib/web/fetch/formdata-parser.js index 7e567e9ec65..90d4d2c7817 100644 --- a/lib/web/fetch/formdata-parser.js +++ b/lib/web/fetch/formdata-parser.js @@ -3,7 +3,6 @@ const { isUSVString, bufferToLowerCasedHeaderName } = require('../../core/util') const { utf8DecodeBytes } = require('./util') const { HTTP_TOKEN_CODEPOINTS, isomorphicDecode } = require('./data-url') -const { isFileLike } = require('./file') const { makeEntry } = require('./formdata') const assert = require('node:assert') const { File: NodeFile } = require('node:buffer') @@ -195,7 +194,7 @@ function multipartFormDataParser (input, mimeType) { // 5.12. Assert: name is a scalar value string and value is either a scalar value string or a File object. assert(isUSVString(name)) - assert((typeof value === 'string' && isUSVString(value)) || isFileLike(value)) + assert((typeof value === 'string' && isUSVString(value)) || value instanceof File) // 5.13. Create an entry with name and value, and append it to entry list. entryList.push(makeEntry(name, value, filename)) diff --git a/lib/web/fetch/formdata.js b/lib/web/fetch/formdata.js index 43e39068d5e..9feea1a0573 100644 --- a/lib/web/fetch/formdata.js +++ b/lib/web/fetch/formdata.js @@ -1,9 +1,8 @@ 'use strict' -const { isBlobLike, iteratorMixin } = require('./util') +const { iteratorMixin } = require('./util') const { kState } = require('./symbols') const { kEnumerableProperty } = require('../../core/util') -const { FileLike, isFileLike } = require('./file') const { webidl } = require('./webidl') const { File: NativeFile } = require('node:buffer') const nodeUtil = require('node:util') @@ -31,7 +30,7 @@ class FormData { const prefix = 'FormData.append' webidl.argumentLengthCheck(arguments, 2, prefix) - if (arguments.length === 3 && !isBlobLike(value)) { + if (arguments.length === 3 && !(value instanceof Blob)) { throw new TypeError( "Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'" ) @@ -40,8 +39,8 @@ class FormData { // 1. Let value be value if given; otherwise blobValue. name = webidl.converters.USVString(name) - value = isBlobLike(value) - ? webidl.converters.Blob(value, prefix, 'value', { strict: false }) + value = value instanceof Blob + ? webidl.converters.Blob(value, prefix, 'value') : webidl.converters.USVString(value) filename = arguments.length === 3 ? webidl.converters.USVString(filename) @@ -124,7 +123,7 @@ class FormData { const prefix = 'FormData.set' webidl.argumentLengthCheck(arguments, 2, prefix) - if (arguments.length === 3 && !isBlobLike(value)) { + if (arguments.length === 3 && !(value instanceof Blob)) { throw new TypeError( "Failed to execute 'set' on 'FormData': parameter 2 is not of type 'Blob'" ) @@ -136,8 +135,8 @@ class FormData { // 1. Let value be value if given; otherwise blobValue. name = webidl.converters.USVString(name) - value = isBlobLike(value) - ? webidl.converters.Blob(value, prefix, 'name', { strict: false }) + value = value instanceof Blob + ? webidl.converters.Blob(value, prefix, 'name') : webidl.converters.USVString(value) filename = arguments.length === 3 ? webidl.converters.USVString(filename) @@ -222,10 +221,8 @@ function makeEntry (name, value, filename) { // 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 }) + if (!(value instanceof File)) { + value = new File([value], 'blob', { type: value.type }) } // 2. If filename is given, then set value to a new File object, @@ -237,9 +234,7 @@ function makeEntry (name, value, filename) { lastModified: value.lastModified } - value = value instanceof NativeFile - ? new File([value], filename, options) - : new FileLike(value, filename, options) + value = new File([value], filename, options) } } diff --git a/lib/web/fetch/index.js b/lib/web/fetch/index.js index f9b3629c07b..025248d9742 100644 --- a/lib/web/fetch/index.js +++ b/lib/web/fetch/index.js @@ -30,7 +30,6 @@ const { determineRequestsReferrer, coarsenedSharedCurrentTime, createDeferredPromise, - isBlobLike, sameOrigin, isCancelled, isAborted, @@ -810,7 +809,7 @@ function schemeFetch (fetchParams) { // 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(blob)) { + if (request.method !== 'GET' || !(blob instanceof Blob)) { return Promise.resolve(makeNetworkError('invalid method')) } diff --git a/lib/web/fetch/request.js b/lib/web/fetch/request.js index ca0153922af..b82127f0c6b 100644 --- a/lib/web/fetch/request.js +++ b/lib/web/fetch/request.js @@ -400,16 +400,6 @@ class Request { // 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 { @@ -1011,8 +1001,7 @@ webidl.converters.RequestInit = webidl.dictionaryConverter([ (signal) => webidl.converters.AbortSignal( signal, 'RequestInit', - 'signal', - { strict: false } + 'signal' ) ) }, diff --git a/lib/web/fetch/response.js b/lib/web/fetch/response.js index 155dbadd1ad..252addc2286 100644 --- a/lib/web/fetch/response.js +++ b/lib/web/fetch/response.js @@ -9,7 +9,6 @@ const { isValidReasonPhrase, isCancelled, isAborted, - isBlobLike, serializeJavascriptValueToJSONString, isErrorLike, isomorphicEncode, @@ -541,16 +540,16 @@ webidl.converters.XMLHttpRequestBodyInit = function (V, prefix, name) { return webidl.converters.USVString(V, prefix, name) } - if (isBlobLike(V)) { - return webidl.converters.Blob(V, prefix, name, { strict: false }) + if (V instanceof Blob) { + return webidl.converters.Blob(V, prefix, name) } if (ArrayBuffer.isView(V) || types.isArrayBuffer(V)) { return webidl.converters.BufferSource(V, prefix, name) } - if (util.isFormDataLike(V)) { - return webidl.converters.FormData(V, prefix, name, { strict: false }) + if (V instanceof FormData) { + return webidl.converters.FormData(V, prefix, name) } if (V instanceof URLSearchParams) { diff --git a/lib/web/fetch/util.js b/lib/web/fetch/util.js index 623b475854f..28d54fe946c 100644 --- a/lib/web/fetch/util.js +++ b/lib/web/fetch/util.js @@ -6,7 +6,7 @@ const { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet const { getGlobalOrigin } = require('./global') const { collectASequenceOfCodePoints, collectAnHTTPQuotedString, removeChars, parseMIMEType } = require('./data-url') const { performance } = require('node:perf_hooks') -const { isBlobLike, ReadableStreamFrom, isValidHTTPToken, normalizedMethodRecordsBase } = require('../../core/util') +const { ReadableStreamFrom, isValidHTTPToken, normalizedMethodRecordsBase } = require('../../core/util') const assert = require('node:assert') const { isUint8Array } = require('node:util/types') const { webidl } = require('./webidl') @@ -1061,13 +1061,6 @@ async function fullyReadBody (body, processBody, processBodyError) { } } -function isReadableStreamLike (stream) { - return stream instanceof ReadableStream || ( - stream[Symbol.toStringTag] === 'ReadableStream' && - typeof stream.tee === 'function' - ) -} - /** * @param {ReadableStreamController} controller */ @@ -1589,7 +1582,6 @@ module.exports = { requestCurrentURL, responseURL, responseLocationURL, - isBlobLike, isURLPotentiallyTrustworthy, isValidReasonPhrase, sameOrigin, @@ -1602,7 +1594,6 @@ module.exports = { isErrorLike, fullyReadBody, bytesMatch, - isReadableStreamLike, readableStreamClose, isomorphicEncode, urlIsLocal, diff --git a/lib/web/fetch/webidl.js b/lib/web/fetch/webidl.js index de185fdea3a..ef0e6dc27f1 100644 --- a/lib/web/fetch/webidl.js +++ b/lib/web/fetch/webidl.js @@ -33,14 +33,8 @@ webidl.errors.invalidArgument = function (context) { } // https://webidl.spec.whatwg.org/#implements -webidl.brandCheck = function (V, I, opts) { - if (opts?.strict !== false && !(V instanceof I)) { - const err = new TypeError('Illegal invocation') - err.code = 'ERR_INVALID_THIS' // node compat. - throw err - } else if (V?.[Symbol.toStringTag] !== I.prototype[Symbol.toStringTag]) { - // TODO(@KhafraDev): this check does not work properly on extended classes - +webidl.brandCheck = function (V, I) { + if (!(V instanceof I)) { const err = new TypeError('Illegal invocation') err.code = 'ERR_INVALID_THIS' // node compat. throw err @@ -346,8 +340,8 @@ webidl.recordConverter = function (keyConverter, valueConverter) { } webidl.interfaceConverter = function (i) { - return (V, prefix, argument, opts) => { - if (opts?.strict !== false && !(V instanceof i)) { + return (V, prefix, argument) => { + if (!(V instanceof i)) { throw webidl.errors.exception({ header: prefix, message: `Expected ${argument} ("${webidl.util.Stringify(V)}") to be an instance of ${i.name}.` @@ -694,6 +688,8 @@ webidl.converters['record'] = webidl.recordConverter( webidl.converters.ByteString ) +webidl.converters.Blob = webidl.interfaceConverter(Blob) + module.exports = { webidl } diff --git a/lib/web/websocket/websocket.js b/lib/web/websocket/websocket.js index 345f2888cc4..96d6c4e453d 100644 --- a/lib/web/websocket/websocket.js +++ b/lib/web/websocket/websocket.js @@ -17,7 +17,7 @@ const { } = require('./util') const { establishWebSocketConnection, closeWebSocketConnection } = require('./connection') const { ByteParser } = require('./receiver') -const { kEnumerableProperty, isBlobLike } = require('../../core/util') +const { kEnumerableProperty } = require('../../core/util') const { getGlobalDispatcher } = require('../../global') const { types } = require('node:util') const { ErrorEvent, CloseEvent, createFastMessageEvent } = require('./events') @@ -324,7 +324,7 @@ class WebSocket extends EventTarget { this.#sendQueue.add(data, () => { this.#bufferedAmount -= data.byteLength }, sendHints.typedArray) - } else if (isBlobLike(data)) { + } else if (data instanceof Blob) { // If the WebSocket connection is established, and the WebSocket // closing handshake has not yet started, then the user agent must // send a WebSocket Message comprised of data using a binary frame @@ -793,8 +793,8 @@ webidl.converters['DOMString or sequence or WebSocketInit'] = functio webidl.converters.WebSocketSendData = function (V) { if (webidl.util.Type(V) === 'Object') { - if (isBlobLike(V)) { - return webidl.converters.Blob(V, { strict: false }) + if (V instanceof Blob) { + return webidl.converters.Blob(V) } if (ArrayBuffer.isView(V) || types.isArrayBuffer(V)) { diff --git a/package.json b/package.json index 7319b3e9eec..5737e0c74eb 100644 --- a/package.json +++ b/package.json @@ -113,12 +113,9 @@ "dns-packet": "^5.4.0", "eslint": "^9.9.0", "fast-check": "^3.17.1", - "form-data": "^4.0.0", - "formdata-node": "^6.0.3", "https-pem": "^3.0.0", "husky": "^9.0.7", "jest": "^29.0.2", - "jsdom": "^25.0.0", "neostandard": "^0.11.2", "node-forge": "^1.3.1", "pre-commit": "^1.2.2", diff --git a/test/fetch/abort.js b/test/fetch/abort.js index 018c9a10b68..73b4764fe81 100644 --- a/test/fetch/abort.js +++ b/test/fetch/abort.js @@ -6,39 +6,8 @@ const { tspl } = require('@matteo.collina/tspl') const { fetch } = require('../..') const { createServer } = require('node:http') const { once } = require('node:events') - const { closeServerAsPromise } = require('../utils/node-http') -const { AbortController: NPMAbortController } = require('abort-controller') - -test('Allow the usage of custom implementation of AbortController', async (t) => { - const body = { - fixes: 1605 - } - - const server = createServer((req, res) => { - res.statusCode = 200 - res.end(JSON.stringify(body)) - }) - - t.after(closeServerAsPromise(server)) - - server.listen(0) - await once(server, 'listening') - - const controller = new NPMAbortController() - const signal = controller.signal - controller.abort() - - try { - await fetch(`http://localhost:${server.address().port}`, { - signal - }) - } catch (e) { - assert.strictEqual(e.code, DOMException.ABORT_ERR) - } -}) - test('allows aborting with custom errors', async (t) => { const server = createServer().listen(0) diff --git a/test/fetch/formdata.js b/test/fetch/formdata.js index 31b563b0763..997e77ebabf 100644 --- a/test/fetch/formdata.js +++ b/test/fetch/formdata.js @@ -4,10 +4,8 @@ const { test } = require('node:test') const assert = require('node:assert') const { tspl } = require('@matteo.collina/tspl') const { FormData, Response, Request } = require('../../') -const { Blob: ThirdPartyBlob } = require('formdata-node') const { Blob, File } = require('node:buffer') const { isFormDataLike } = require('../../lib/core/util') -const ThirdPartyFormDataInvalid = require('form-data') test('arg validation', () => { const form = new FormData() @@ -110,17 +108,6 @@ test('append blob', async () => { assert.strictEqual(form.get('asd'), null) }) -test('append third-party blob', async () => { - const form = new FormData() - form.set('asd', new ThirdPartyBlob(['asd1'], { type: 'text/plain' })) - - assert.strictEqual(form.has('asd'), true) - assert.strictEqual(form.get('asd').type, 'text/plain') - assert.strictEqual(await form.get('asd').text(), 'asd1') - form.delete('asd') - assert.strictEqual(form.get('asd'), null) -}) - test('append string', () => { const form = new FormData() form.set('k1', 'v1') @@ -304,11 +291,6 @@ test('formData should be an instance of FormData', async (t) => { assert.strictEqual(isFormDataLike(form), false) }) - await t.test('Invalid third-party FormData', () => { - const form = new ThirdPartyFormDataInvalid() - assert.strictEqual(isFormDataLike(form), false) - }) - await t.test('Valid FormData', () => { const form = new FormData() assert.strictEqual(isFormDataLike(form), true) diff --git a/test/fetch/jsdom-abortcontroller-1910-1464495619.js b/test/fetch/jsdom-abortcontroller-1910-1464495619.js deleted file mode 100644 index b59ef9f95ca..00000000000 --- a/test/fetch/jsdom-abortcontroller-1910-1464495619.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict' - -const { test } = require('node:test') -const assert = require('node:assert') -const { createServer } = require('node:http') -const { once } = require('node:events') -const { fetch } = require('../..') -const { JSDOM } = require('jsdom') - -// https://github.com/nodejs/undici/pull/1910#issuecomment-1464495619 -test('third party AbortControllers', async (t) => { - const server = createServer((_, res) => res.end()).listen(0) - - const { AbortController } = new JSDOM().window - let controller = new AbortController() - - t.after(() => { - controller.abort() - controller = null - return server.close() - }) - await once(server, 'listening') - - await assert.doesNotReject(fetch(`http://localhost:${server.address().port}`, { - signal: controller.signal - })) -}) diff --git a/test/fetch/request.js b/test/fetch/request.js index 2cc1f6437de..64ead02f0ff 100644 --- a/test/fetch/request.js +++ b/test/fetch/request.js @@ -11,10 +11,6 @@ const { fetch } = require('../../') const { fromInnerRequest, makeRequest } = require('../../lib/web/fetch/request') -const { - Blob: ThirdPartyBlob, - FormData: ThirdPartyFormData -} = require('formdata-node') const { kState, kSignal, kHeaders } = require('../../lib/web/fetch/symbols') const { getHeadersGuard, getHeadersList } = require('../../lib/web/fetch/headers') @@ -419,26 +415,6 @@ test('RequestInit.signal option', async () => { }), TypeError) }) -test('constructing Request with third party Blob body', async () => { - const blob = new ThirdPartyBlob(['text']) - const req = new Request('http://asd', { - method: 'POST', - body: blob - }) - assert.strictEqual(await req.text(), 'text') -}) -test('constructing Request with third party FormData body', async () => { - const form = new ThirdPartyFormData() - form.set('key', 'value') - const req = new Request('http://asd', { - method: 'POST', - body: form - }) - const contentType = req.headers.get('content-type').split('=') - assert.strictEqual(contentType[0], 'multipart/form-data; boundary') - assert.ok((await req.text()).startsWith(`--${contentType[1]}`)) -}) - // https://github.com/nodejs/undici/issues/2050 test('set-cookie headers get cleared when passing a Request as first param', () => { const req1 = new Request('http://localhost', { diff --git a/test/fetch/response.js b/test/fetch/response.js index 8e7c865c78e..58c04a27422 100644 --- a/test/fetch/response.js +++ b/test/fetch/response.js @@ -10,10 +10,6 @@ const { FormData } = require('../../') const { fromInnerResponse, makeResponse } = require('../../lib/web/fetch/response') -const { - Blob: ThirdPartyBlob, - FormData: ThirdPartyFormData -} = require('formdata-node') const { kState, kHeaders } = require('../../lib/web/fetch/symbols') const { getHeadersGuard, getHeadersList } = require('../../lib/web/fetch/headers') @@ -239,20 +235,6 @@ test('constructing a Response with a ReadableStream body', async (t) => { }) }) -test('constructing Response with third party Blob body', async () => { - const blob = new ThirdPartyBlob(['text']) - const res = new Response(blob) - assert.strictEqual(await res.text(), 'text') -}) -test('constructing Response with third party FormData body', async () => { - const form = new ThirdPartyFormData() - form.set('key', 'value') - const res = new Response(form) - const contentType = res.headers.get('content-type').split('=') - assert.strictEqual(contentType[0], 'multipart/form-data; boundary') - assert.ok((await res.text()).startsWith(`--${contentType[1]}`)) -}) - // https://github.com/nodejs/undici/issues/2465 test('Issue#2465', async (t) => { const { strictEqual } = tspl(t, { plan: 1 }) diff --git a/test/issue-2065.js b/test/issue-2065.js index b84fe04085b..9037fb557c3 100644 --- a/test/issue-2065.js +++ b/test/issue-2065.js @@ -4,7 +4,6 @@ const { tspl } = require('@matteo.collina/tspl') const { test, after } = require('node:test') const { createServer } = require('node:http') const { once } = require('node:events') -const { createReadStream } = require('node:fs') const { FormData, request } = require('..') const { File } = require('node:buffer') @@ -27,45 +26,3 @@ test('undici.request with a FormData body should set content-length header', asy body }) }) - -test('undici.request with a FormData stream value should set transfer-encoding header', async (t) => { - t = tspl(t, { plan: 1 }) - - const server = createServer((req, res) => { - t.strictEqual(req.headers['transfer-encoding'], 'chunked') - res.end() - }).listen(0) - - after(() => server.close()) - await once(server, 'listening') - - class BlobFromStream { - #stream - #type - constructor (stream, type) { - this.#stream = stream - this.#type = type - } - - stream () { - return this.#stream - } - - get type () { - return this.#type - } - - get [Symbol.toStringTag] () { - return 'Blob' - } - } - - const body = new FormData() - const fileReadable = createReadStream(__filename) - body.set('file', new BlobFromStream(fileReadable, '.js'), 'streamfile') - - await request(`http://localhost:${server.address().port}`, { - method: 'POST', - body - }) -}) diff --git a/test/node-fetch/main.js b/test/node-fetch/main.js index 2360620740c..6d2e73b455d 100644 --- a/test/node-fetch/main.js +++ b/test/node-fetch/main.js @@ -919,9 +919,9 @@ describe('node-fetch', () => { it('should throw a TypeError if a signal is not of type AbortSignal or EventTarget', () => { return Promise.all([ - assert.rejects(fetch(`${base}inspect`, { signal: {} }), new TypeError("Failed to construct 'Request': member signal is not of type AbortSignal.")), - assert.rejects(fetch(`${base}inspect`, { signal: '' }), new TypeError("Failed to construct 'Request': member signal is not of type AbortSignal.")), - assert.rejects(fetch(`${base}inspect`, { signal: Object.create(null) }), new TypeError("Failed to construct 'Request': member signal is not of type AbortSignal.")) + assert.rejects(fetch(`${base}inspect`, { signal: {} }), new TypeError('RequestInit: Expected signal ("{}") to be an instance of AbortSignal.')), + assert.rejects(fetch(`${base}inspect`, { signal: '' }), new TypeError('RequestInit: Expected signal ("""") to be an instance of AbortSignal.')), + assert.rejects(fetch(`${base}inspect`, { signal: Object.create(null) }), new TypeError('RequestInit: Expected signal ("[Object: null prototype] {}") to be an instance of AbortSignal.')) ]) }) diff --git a/types/webidl.d.ts b/types/webidl.d.ts index 7ea596cafd0..eebe99c801c 100644 --- a/types/webidl.d.ts +++ b/types/webidl.d.ts @@ -167,7 +167,7 @@ export interface Webidl { * @description Performs a brand-check on {@param V} to ensure it is a * {@param cls} object. */ - brandCheck unknown>(V: unknown, cls: Interface, opts?: { strict?: boolean }): asserts V is Interface + brandCheck unknown>(V: unknown, cls: Interface): asserts V is Interface brandCheckMultiple unknown)[]> (V: unknown, list: Interfaces): asserts V is Interfaces[number] @@ -194,7 +194,8 @@ export interface Webidl { */ interfaceConverter (cls: Interface): ( V: unknown, - opts?: { strict: boolean } + prefix: string, + argument: string ) => asserts V is typeof cls // TODO(@KhafraDev): a type could likely be implemented that can infer the return type