Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/web/fetch/formdata.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class FormData {

name = webidl.converters.USVString(name)
value = isBlobLike(value)
? webidl.converters.Blob(value, prefix, 'value', { strict: false })
? webidl.converters.Blob(value, prefix, 'value')
: webidl.converters.USVString(value)
filename = arguments.length === 3
? webidl.converters.USVString(filename)
Expand Down Expand Up @@ -137,7 +137,7 @@ class FormData {

name = webidl.converters.USVString(name)
value = isBlobLike(value)
? webidl.converters.Blob(value, prefix, 'name', { strict: false })
? webidl.converters.Blob(value, prefix, 'name')
: webidl.converters.USVString(value)
filename = arguments.length === 3
? webidl.converters.USVString(filename)
Expand Down
3 changes: 1 addition & 2 deletions lib/web/fetch/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -1011,8 +1011,7 @@ webidl.converters.RequestInit = webidl.dictionaryConverter([
(signal) => webidl.converters.AbortSignal(
signal,
'RequestInit',
'signal',
{ strict: false }
'signal'
)
)
},
Expand Down
4 changes: 2 additions & 2 deletions lib/web/fetch/response.js
Original file line number Diff line number Diff line change
Expand Up @@ -542,15 +542,15 @@ webidl.converters.XMLHttpRequestBodyInit = function (V, prefix, name) {
}

if (isBlobLike(V)) {
return webidl.converters.Blob(V, prefix, name, { strict: false })
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 })
return webidl.converters.FormData(V, prefix, name)
}

if (V instanceof URLSearchParams) {
Expand Down
14 changes: 4 additions & 10 deletions lib/web/fetch/webidl.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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}.`
Expand Down
2 changes: 1 addition & 1 deletion lib/web/websocket/websocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,7 @@ webidl.converters['DOMString or sequence<DOMString> or WebSocketInit'] = functio
webidl.converters.WebSocketSendData = function (V) {
if (webidl.util.Type(V) === 'Object') {
if (isBlobLike(V)) {
return webidl.converters.Blob(V, { strict: false })
return webidl.converters.Blob(V)
}

if (ArrayBuffer.isView(V) || types.isArrayBuffer(V)) {
Expand Down
3 changes: 0 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": "^24.0.0",
"neostandard": "^0.11.2",
"node-forge": "^1.3.1",
"pre-commit": "^1.2.2",
Expand Down
31 changes: 0 additions & 31 deletions test/fetch/abort.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
18 changes: 0 additions & 18 deletions test/fetch/formdata.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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')
Expand Down Expand Up @@ -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)
Expand Down
27 changes: 0 additions & 27 deletions test/fetch/jsdom-abortcontroller-1910-1464495619.js

This file was deleted.

24 changes: 0 additions & 24 deletions test/fetch/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')

Expand Down Expand Up @@ -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', {
Expand Down
18 changes: 0 additions & 18 deletions test/fetch/response.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')

Expand Down Expand Up @@ -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 })
Expand Down
43 changes: 0 additions & 43 deletions test/issue-2065.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')

Expand All @@ -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
})
})
6 changes: 3 additions & 3 deletions test/node-fetch/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.'))
])
})

Expand Down
5 changes: 3 additions & 2 deletions types/webidl.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ export interface Webidl {
* @description Performs a brand-check on {@param V} to ensure it is a
* {@param cls} object.
*/
brandCheck <Interface extends new () => unknown>(V: unknown, cls: Interface, opts?: { strict?: boolean }): asserts V is Interface
brandCheck <Interface extends new () => unknown>(V: unknown, cls: Interface): asserts V is Interface

brandCheckMultiple <Interfaces extends (new () => unknown)[]> (V: unknown, list: Interfaces): asserts V is Interfaces[number]

Expand All @@ -194,7 +194,8 @@ export interface Webidl {
*/
interfaceConverter <Interface>(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
Expand Down