undici 5.12.0 → 5.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -5
- package/docs/assets/lifecycle-diagram.png +0 -0
- package/index.d.ts +23 -23
- package/lib/fetch/body.js +18 -20
- package/lib/fetch/constants.js +19 -1
- package/lib/fetch/dataURL.js +5 -70
- package/lib/fetch/file.js +16 -40
- package/lib/fetch/formdata.js +25 -72
- package/lib/fetch/headers.js +32 -83
- package/lib/fetch/index.js +22 -26
- package/lib/fetch/request.js +34 -112
- package/lib/fetch/response.js +25 -53
- package/lib/fetch/util.js +63 -21
- package/lib/fetch/webidl.js +38 -54
- package/lib/fileapi/filereader.js +23 -77
- package/lib/fileapi/progressevent.js +3 -9
- package/lib/mock/mock-utils.js +22 -4
- package/package.json +4 -4
- package/types/agent.d.ts +4 -5
- package/types/api.d.ts +1 -1
- package/types/balanced-pool.d.ts +3 -4
- package/types/client.d.ts +5 -5
- package/types/connector.d.ts +3 -3
- package/types/diagnostics-channel.d.ts +4 -4
- package/types/dispatcher.d.ts +23 -23
- package/types/errors.d.ts +3 -3
- package/types/fetch.d.ts +1 -1
- package/types/filereader.d.ts +8 -3
- package/types/global-dispatcher.d.ts +1 -1
- package/types/interceptors.d.ts +2 -2
- package/types/mock-agent.d.ts +3 -3
- package/types/mock-client.d.ts +4 -4
- package/types/mock-errors.d.ts +3 -3
- package/types/mock-interceptor.d.ts +1 -1
- package/types/mock-pool.d.ts +4 -4
- package/types/patch.d.ts +51 -0
- package/types/pool-stats.d.ts +2 -2
- package/types/pool.d.ts +5 -6
- package/types/proxy-agent.d.ts +3 -3
- package/types/readable.d.ts +1 -1
- package/types/webidl.d.ts +213 -0
package/README.md
CHANGED
|
@@ -178,10 +178,6 @@ Implements [fetch](https://fetch.spec.whatwg.org/#fetch-method).
|
|
|
178
178
|
|
|
179
179
|
Only supported on Node 16.8+.
|
|
180
180
|
|
|
181
|
-
This is [experimental](https://nodejs.org/api/documentation.html#documentation_stability_index) and is not yet fully compliant with the Fetch Standard.
|
|
182
|
-
We plan to ship breaking changes to this feature until it is out of experimental.
|
|
183
|
-
Help us improve the test coverage by following instructions at [nodejs/undici/#951](https://github.com/nodejs/undici/issues/951).
|
|
184
|
-
|
|
185
181
|
Basic usage example:
|
|
186
182
|
|
|
187
183
|
```js
|
|
@@ -234,9 +230,15 @@ const data = {
|
|
|
234
230
|
},
|
|
235
231
|
}
|
|
236
232
|
|
|
237
|
-
await fetch('https://example.com', { body: data, method: 'POST' })
|
|
233
|
+
await fetch('https://example.com', { body: data, method: 'POST', duplex: 'half' })
|
|
238
234
|
```
|
|
239
235
|
|
|
236
|
+
#### `request.duplex`
|
|
237
|
+
|
|
238
|
+
- half
|
|
239
|
+
|
|
240
|
+
In this implementation of fetch, `request.duplex` must be set if `request.body` is `ReadableStream` or `Async Iterables`. And fetch requests are currently always be full duplex. More detail refer to [Fetch Standard.](https://fetch.spec.whatwg.org/#dom-requestinit-duplex)
|
|
241
|
+
|
|
240
242
|
#### `response.body`
|
|
241
243
|
|
|
242
244
|
Nodejs has two kinds of streams: [web streams](https://nodejs.org/dist/latest-v16.x/docs/api/webstreams.html), which follow the API of the WHATWG web standard found in browsers, and an older Node-specific [streams API](https://nodejs.org/api/stream.html). `response.body` returns a readable web stream. If you would prefer to work with a Node stream you can convert a web stream using `.fromWeb()`.
|
|
Binary file
|
package/index.d.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import Dispatcher
|
|
1
|
+
import Dispatcher from'./types/dispatcher'
|
|
2
2
|
import { setGlobalDispatcher, getGlobalDispatcher } from './types/global-dispatcher'
|
|
3
3
|
import { setGlobalOrigin, getGlobalOrigin } from './types/global-origin'
|
|
4
|
-
import Pool
|
|
4
|
+
import Pool from'./types/pool'
|
|
5
5
|
import { RedirectHandler, DecoratorHandler } from './types/handlers'
|
|
6
6
|
|
|
7
|
-
import BalancedPool
|
|
8
|
-
import Client
|
|
9
|
-
import buildConnector
|
|
10
|
-
import errors
|
|
11
|
-
import Agent
|
|
12
|
-
import MockClient
|
|
13
|
-
import MockPool
|
|
14
|
-
import MockAgent
|
|
15
|
-
import mockErrors
|
|
16
|
-
import ProxyAgent
|
|
7
|
+
import BalancedPool from './types/balanced-pool'
|
|
8
|
+
import Client from'./types/client'
|
|
9
|
+
import buildConnector from'./types/connector'
|
|
10
|
+
import errors from'./types/errors'
|
|
11
|
+
import Agent from'./types/agent'
|
|
12
|
+
import MockClient from'./types/mock-client'
|
|
13
|
+
import MockPool from'./types/mock-pool'
|
|
14
|
+
import MockAgent from'./types/mock-agent'
|
|
15
|
+
import mockErrors from'./types/mock-errors'
|
|
16
|
+
import ProxyAgent from'./types/proxy-agent'
|
|
17
17
|
import { request, pipeline, stream, connect, upgrade } from './types/api'
|
|
18
18
|
|
|
19
19
|
export * from './types/fetch'
|
|
@@ -27,16 +27,16 @@ export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent,
|
|
|
27
27
|
export default Undici
|
|
28
28
|
|
|
29
29
|
declare namespace Undici {
|
|
30
|
-
var Dispatcher: typeof import('./types/dispatcher')
|
|
31
|
-
var Pool: typeof import('./types/pool');
|
|
30
|
+
var Dispatcher: typeof import('./types/dispatcher').default
|
|
31
|
+
var Pool: typeof import('./types/pool').default;
|
|
32
32
|
var RedirectHandler: typeof import ('./types/handlers').RedirectHandler
|
|
33
33
|
var DecoratorHandler: typeof import ('./types/handlers').DecoratorHandler
|
|
34
34
|
var createRedirectInterceptor: typeof import ('./types/interceptors').createRedirectInterceptor
|
|
35
|
-
var BalancedPool: typeof import('./types/balanced-pool');
|
|
36
|
-
var Client: typeof import('./types/client');
|
|
37
|
-
var buildConnector: typeof import('./types/connector');
|
|
38
|
-
var errors: typeof import('./types/errors');
|
|
39
|
-
var Agent: typeof import('./types/agent');
|
|
35
|
+
var BalancedPool: typeof import('./types/balanced-pool').default;
|
|
36
|
+
var Client: typeof import('./types/client').default;
|
|
37
|
+
var buildConnector: typeof import('./types/connector').default;
|
|
38
|
+
var errors: typeof import('./types/errors').default;
|
|
39
|
+
var Agent: typeof import('./types/agent').default;
|
|
40
40
|
var setGlobalDispatcher: typeof import('./types/global-dispatcher').setGlobalDispatcher;
|
|
41
41
|
var getGlobalDispatcher: typeof import('./types/global-dispatcher').getGlobalDispatcher;
|
|
42
42
|
var request: typeof import('./types/api').request;
|
|
@@ -44,9 +44,9 @@ declare namespace Undici {
|
|
|
44
44
|
var pipeline: typeof import('./types/api').pipeline;
|
|
45
45
|
var connect: typeof import('./types/api').connect;
|
|
46
46
|
var upgrade: typeof import('./types/api').upgrade;
|
|
47
|
-
var MockClient: typeof import('./types/mock-client');
|
|
48
|
-
var MockPool: typeof import('./types/mock-pool');
|
|
49
|
-
var MockAgent: typeof import('./types/mock-agent');
|
|
50
|
-
var mockErrors: typeof import('./types/mock-errors');
|
|
47
|
+
var MockClient: typeof import('./types/mock-client').default;
|
|
48
|
+
var MockPool: typeof import('./types/mock-pool').default;
|
|
49
|
+
var MockAgent: typeof import('./types/mock-agent').default;
|
|
50
|
+
var mockErrors: typeof import('./types/mock-errors').default;
|
|
51
51
|
var fetch: typeof import('./types/fetch').fetch;
|
|
52
52
|
}
|
package/lib/fetch/body.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const Busboy = require('busboy')
|
|
4
4
|
const util = require('../core/util')
|
|
5
|
-
const { ReadableStreamFrom,
|
|
5
|
+
const { ReadableStreamFrom, isBlobLike, isReadableStreamLike, readableStreamClose } = require('./util')
|
|
6
6
|
const { FormData } = require('./formdata')
|
|
7
7
|
const { kState } = require('./symbols')
|
|
8
8
|
const { webidl } = require('./webidl')
|
|
@@ -66,9 +66,13 @@ function extractBody (object, keepalive = false) {
|
|
|
66
66
|
let type = null
|
|
67
67
|
|
|
68
68
|
// 10. Switch on object:
|
|
69
|
-
if (object
|
|
70
|
-
//
|
|
71
|
-
//
|
|
69
|
+
if (typeof object === 'string') {
|
|
70
|
+
// Set source to the UTF-8 encoding of object.
|
|
71
|
+
// Note: setting source to a Uint8Array here breaks some mocking assumptions.
|
|
72
|
+
source = object
|
|
73
|
+
|
|
74
|
+
// Set type to `text/plain;charset=UTF-8`.
|
|
75
|
+
type = 'text/plain;charset=UTF-8'
|
|
72
76
|
} else if (object instanceof URLSearchParams) {
|
|
73
77
|
// URLSearchParams
|
|
74
78
|
|
|
@@ -126,7 +130,8 @@ function extractBody (object, keepalive = false) {
|
|
|
126
130
|
|
|
127
131
|
yield * value.stream()
|
|
128
132
|
|
|
129
|
-
|
|
133
|
+
// '\r\n' encoded
|
|
134
|
+
yield new Uint8Array([13, 10])
|
|
130
135
|
}
|
|
131
136
|
}
|
|
132
137
|
|
|
@@ -157,6 +162,11 @@ function extractBody (object, keepalive = false) {
|
|
|
157
162
|
if (object.type) {
|
|
158
163
|
type = object.type
|
|
159
164
|
}
|
|
165
|
+
} else if (object instanceof Uint8Array) {
|
|
166
|
+
// byte sequence
|
|
167
|
+
|
|
168
|
+
// Set source to object.
|
|
169
|
+
source = object
|
|
160
170
|
} else if (typeof object[Symbol.asyncIterator] === 'function') {
|
|
161
171
|
// If keepalive is true, then throw a TypeError.
|
|
162
172
|
if (keepalive) {
|
|
@@ -172,17 +182,10 @@ function extractBody (object, keepalive = false) {
|
|
|
172
182
|
|
|
173
183
|
stream =
|
|
174
184
|
object instanceof ReadableStream ? object : ReadableStreamFrom(object)
|
|
175
|
-
} else {
|
|
176
|
-
// TODO: byte sequence?
|
|
177
|
-
// TODO: scalar value string?
|
|
178
|
-
// TODO: else?
|
|
179
|
-
source = toUSVString(object)
|
|
180
|
-
type = 'text/plain;charset=UTF-8'
|
|
181
185
|
}
|
|
182
186
|
|
|
183
187
|
// 11. If source is a byte sequence, then set action to a
|
|
184
188
|
// step that returns source and length to source’s length.
|
|
185
|
-
// TODO: What is a "byte sequence?"
|
|
186
189
|
if (typeof source === 'string' || util.isBuffer(source)) {
|
|
187
190
|
length = Buffer.byteLength(source)
|
|
188
191
|
}
|
|
@@ -329,9 +332,7 @@ function bodyMixinMethods (instance) {
|
|
|
329
332
|
},
|
|
330
333
|
|
|
331
334
|
async formData () {
|
|
332
|
-
|
|
333
|
-
throw new TypeError('Illegal invocation')
|
|
334
|
-
}
|
|
335
|
+
webidl.brandCheck(this, instance)
|
|
335
336
|
|
|
336
337
|
throwIfAborted(this[kState])
|
|
337
338
|
|
|
@@ -433,7 +434,7 @@ function bodyMixinMethods (instance) {
|
|
|
433
434
|
throwIfAborted(this[kState])
|
|
434
435
|
|
|
435
436
|
// Otherwise, throw a TypeError.
|
|
436
|
-
webidl.errors.exception({
|
|
437
|
+
throw webidl.errors.exception({
|
|
437
438
|
header: `${instance.name}.formData`,
|
|
438
439
|
message: 'Could not parse content as FormData.'
|
|
439
440
|
})
|
|
@@ -450,11 +451,8 @@ function mixinBody (prototype) {
|
|
|
450
451
|
|
|
451
452
|
// https://fetch.spec.whatwg.org/#concept-body-consume-body
|
|
452
453
|
async function specConsumeBody (object, type, instance) {
|
|
453
|
-
|
|
454
|
-
throw new TypeError('Illegal invocation')
|
|
455
|
-
}
|
|
454
|
+
webidl.brandCheck(object, instance)
|
|
456
455
|
|
|
457
|
-
// TODO: why is this needed?
|
|
458
456
|
throwIfAborted(object[kState])
|
|
459
457
|
|
|
460
458
|
// 1. If object is unusable, then return a promise rejected
|
package/lib/fetch/constants.js
CHANGED
|
@@ -8,6 +8,17 @@ const nullBodyStatus = [101, 204, 205, 304]
|
|
|
8
8
|
|
|
9
9
|
const redirectStatus = [301, 302, 303, 307, 308]
|
|
10
10
|
|
|
11
|
+
// https://fetch.spec.whatwg.org/#block-bad-port
|
|
12
|
+
const badPorts = [
|
|
13
|
+
'1', '7', '9', '11', '13', '15', '17', '19', '20', '21', '22', '23', '25', '37', '42', '43', '53', '69', '77', '79',
|
|
14
|
+
'87', '95', '101', '102', '103', '104', '109', '110', '111', '113', '115', '117', '119', '123', '135', '137',
|
|
15
|
+
'139', '143', '161', '179', '389', '427', '465', '512', '513', '514', '515', '526', '530', '531', '532',
|
|
16
|
+
'540', '548', '554', '556', '563', '587', '601', '636', '989', '990', '993', '995', '1719', '1720', '1723',
|
|
17
|
+
'2049', '3659', '4045', '5060', '5061', '6000', '6566', '6665', '6666', '6667', '6668', '6669', '6697',
|
|
18
|
+
'10080'
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
// https://w3c.github.io/webappsec-referrer-policy/#referrer-policies
|
|
11
22
|
const referrerPolicy = [
|
|
12
23
|
'',
|
|
13
24
|
'no-referrer',
|
|
@@ -44,6 +55,11 @@ const requestBodyHeader = [
|
|
|
44
55
|
'content-type'
|
|
45
56
|
]
|
|
46
57
|
|
|
58
|
+
// https://fetch.spec.whatwg.org/#enumdef-requestduplex
|
|
59
|
+
const requestDuplex = [
|
|
60
|
+
'half'
|
|
61
|
+
]
|
|
62
|
+
|
|
47
63
|
// http://fetch.spec.whatwg.org/#forbidden-method
|
|
48
64
|
const forbiddenMethods = ['CONNECT', 'TRACE', 'TRACK']
|
|
49
65
|
|
|
@@ -108,5 +124,7 @@ module.exports = {
|
|
|
108
124
|
redirectStatus,
|
|
109
125
|
corsSafeListedMethods,
|
|
110
126
|
nullBodyStatus,
|
|
111
|
-
safeMethods
|
|
127
|
+
safeMethods,
|
|
128
|
+
badPorts,
|
|
129
|
+
requestDuplex
|
|
112
130
|
}
|
package/lib/fetch/dataURL.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const assert = require('assert')
|
|
2
2
|
const { atob } = require('buffer')
|
|
3
|
-
const {
|
|
3
|
+
const { format } = require('url')
|
|
4
|
+
const { isValidHTTPToken, isomorphicDecode } = require('./util')
|
|
4
5
|
|
|
5
6
|
const encoder = new TextEncoder()
|
|
6
7
|
|
|
@@ -54,7 +55,6 @@ function dataURLProcessor (dataURL) {
|
|
|
54
55
|
const encodedBody = input.slice(mimeTypeLength + 1)
|
|
55
56
|
|
|
56
57
|
// 10. Let body be the percent-decoding of encodedBody.
|
|
57
|
-
/** @type {Uint8Array|string} */
|
|
58
58
|
let body = stringPercentDecode(encodedBody)
|
|
59
59
|
|
|
60
60
|
// 11. If mimeType ends with U+003B (;), followed by
|
|
@@ -62,7 +62,8 @@ function dataURLProcessor (dataURL) {
|
|
|
62
62
|
// case-insensitive match for "base64", then:
|
|
63
63
|
if (/;(\u0020){0,}base64$/i.test(mimeType)) {
|
|
64
64
|
// 1. Let stringBody be the isomorphic decode of body.
|
|
65
|
-
const stringBody =
|
|
65
|
+
const stringBody = isomorphicDecode(body)
|
|
66
|
+
|
|
66
67
|
// 2. Set body to the forgiving-base64 decode of
|
|
67
68
|
// stringBody.
|
|
68
69
|
body = forgivingBase64(stringBody)
|
|
@@ -111,73 +112,7 @@ function dataURLProcessor (dataURL) {
|
|
|
111
112
|
* @param {boolean} excludeFragment
|
|
112
113
|
*/
|
|
113
114
|
function URLSerializer (url, excludeFragment = false) {
|
|
114
|
-
|
|
115
|
-
let output = url.protocol
|
|
116
|
-
|
|
117
|
-
// 2. If url’s host is non-null:
|
|
118
|
-
if (url.host.length > 0) {
|
|
119
|
-
// 1. Append "//" to output.
|
|
120
|
-
output += '//'
|
|
121
|
-
|
|
122
|
-
// 2. If url includes credentials, then:
|
|
123
|
-
if (url.username.length > 0 || url.password.length > 0) {
|
|
124
|
-
// 1. Append url’s username to output.
|
|
125
|
-
output += url.username
|
|
126
|
-
|
|
127
|
-
// 2. If url’s password is not the empty string, then append U+003A (:),
|
|
128
|
-
// followed by url’s password, to output.
|
|
129
|
-
if (url.password.length > 0) {
|
|
130
|
-
output += ':' + url.password
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// 3. Append U+0040 (@) to output.
|
|
134
|
-
output += '@'
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// 3. Append url’s host, serialized, to output.
|
|
138
|
-
output += decodeURIComponent(url.hostname)
|
|
139
|
-
|
|
140
|
-
// 4. If url’s port is non-null, append U+003A (:) followed by url’s port,
|
|
141
|
-
// serialized, to output.
|
|
142
|
-
if (url.port.length > 0) {
|
|
143
|
-
output += ':' + url.port
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// 3. If url’s host is null, url does not have an opaque path,
|
|
148
|
-
// url’s path’s size is greater than 1, and url’s path[0]
|
|
149
|
-
// is the empty string, then append U+002F (/) followed by
|
|
150
|
-
// U+002E (.) to output.
|
|
151
|
-
// Note: This prevents web+demo:/.//not-a-host/ or web+demo:/path/..//not-a-host/,
|
|
152
|
-
// when parsed and then serialized, from ending up as web+demo://not-a-host/
|
|
153
|
-
// (they end up as web+demo:/.//not-a-host/).
|
|
154
|
-
// Undici implementation note: url's path[0] can never be an
|
|
155
|
-
// empty string, so we have to slightly alter what the spec says.
|
|
156
|
-
if (
|
|
157
|
-
url.host.length === 0 &&
|
|
158
|
-
url.pathname.length > 1 &&
|
|
159
|
-
url.href.slice(url.protocol.length + 1)[0] === '.'
|
|
160
|
-
) {
|
|
161
|
-
output += '/.'
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// 4. Append the result of URL path serializing url to output.
|
|
165
|
-
output += url.pathname
|
|
166
|
-
|
|
167
|
-
// 5. If url’s query is non-null, append U+003F (?),
|
|
168
|
-
// followed by url’s query, to output.
|
|
169
|
-
if (url.search.length > 0) {
|
|
170
|
-
output += url.search
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// 6. If exclude fragment is false and url’s fragment is non-null,
|
|
174
|
-
// then append U+0023 (#), followed by url’s fragment, to output.
|
|
175
|
-
if (excludeFragment === false && url.hash.length > 0) {
|
|
176
|
-
output += url.hash
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// 7. Return output.
|
|
180
|
-
return output
|
|
115
|
+
return format(url, { fragment: !excludeFragment })
|
|
181
116
|
}
|
|
182
117
|
|
|
183
118
|
// https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points
|
package/lib/fetch/file.js
CHANGED
|
@@ -13,9 +13,7 @@ class File extends Blob {
|
|
|
13
13
|
// The File constructor is invoked with two or three parameters, depending
|
|
14
14
|
// on whether the optional dictionary parameter is used. When the File()
|
|
15
15
|
// constructor is invoked, user agents must run the following steps:
|
|
16
|
-
|
|
17
|
-
throw new TypeError('2 arguments required')
|
|
18
|
-
}
|
|
16
|
+
webidl.argumentLengthCheck(arguments, 2, { header: 'File constructor' })
|
|
19
17
|
|
|
20
18
|
fileBits = webidl.converters['sequence<BlobPart>'](fileBits)
|
|
21
19
|
fileName = webidl.converters.USVString(fileName)
|
|
@@ -76,32 +74,22 @@ class File extends Blob {
|
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
get name () {
|
|
79
|
-
|
|
80
|
-
throw new TypeError('Illegal invocation')
|
|
81
|
-
}
|
|
77
|
+
webidl.brandCheck(this, File)
|
|
82
78
|
|
|
83
79
|
return this[kState].name
|
|
84
80
|
}
|
|
85
81
|
|
|
86
82
|
get lastModified () {
|
|
87
|
-
|
|
88
|
-
throw new TypeError('Illegal invocation')
|
|
89
|
-
}
|
|
83
|
+
webidl.brandCheck(this, File)
|
|
90
84
|
|
|
91
85
|
return this[kState].lastModified
|
|
92
86
|
}
|
|
93
87
|
|
|
94
88
|
get type () {
|
|
95
|
-
|
|
96
|
-
throw new TypeError('Illegal invocation')
|
|
97
|
-
}
|
|
89
|
+
webidl.brandCheck(this, File)
|
|
98
90
|
|
|
99
91
|
return this[kState].type
|
|
100
92
|
}
|
|
101
|
-
|
|
102
|
-
get [Symbol.toStringTag] () {
|
|
103
|
-
return this.constructor.name
|
|
104
|
-
}
|
|
105
93
|
}
|
|
106
94
|
|
|
107
95
|
class FileLike {
|
|
@@ -153,65 +141,49 @@ class FileLike {
|
|
|
153
141
|
}
|
|
154
142
|
|
|
155
143
|
stream (...args) {
|
|
156
|
-
|
|
157
|
-
throw new TypeError('Illegal invocation')
|
|
158
|
-
}
|
|
144
|
+
webidl.brandCheck(this, FileLike)
|
|
159
145
|
|
|
160
146
|
return this[kState].blobLike.stream(...args)
|
|
161
147
|
}
|
|
162
148
|
|
|
163
149
|
arrayBuffer (...args) {
|
|
164
|
-
|
|
165
|
-
throw new TypeError('Illegal invocation')
|
|
166
|
-
}
|
|
150
|
+
webidl.brandCheck(this, FileLike)
|
|
167
151
|
|
|
168
152
|
return this[kState].blobLike.arrayBuffer(...args)
|
|
169
153
|
}
|
|
170
154
|
|
|
171
155
|
slice (...args) {
|
|
172
|
-
|
|
173
|
-
throw new TypeError('Illegal invocation')
|
|
174
|
-
}
|
|
156
|
+
webidl.brandCheck(this, FileLike)
|
|
175
157
|
|
|
176
158
|
return this[kState].blobLike.slice(...args)
|
|
177
159
|
}
|
|
178
160
|
|
|
179
161
|
text (...args) {
|
|
180
|
-
|
|
181
|
-
throw new TypeError('Illegal invocation')
|
|
182
|
-
}
|
|
162
|
+
webidl.brandCheck(this, FileLike)
|
|
183
163
|
|
|
184
164
|
return this[kState].blobLike.text(...args)
|
|
185
165
|
}
|
|
186
166
|
|
|
187
167
|
get size () {
|
|
188
|
-
|
|
189
|
-
throw new TypeError('Illegal invocation')
|
|
190
|
-
}
|
|
168
|
+
webidl.brandCheck(this, FileLike)
|
|
191
169
|
|
|
192
170
|
return this[kState].blobLike.size
|
|
193
171
|
}
|
|
194
172
|
|
|
195
173
|
get type () {
|
|
196
|
-
|
|
197
|
-
throw new TypeError('Illegal invocation')
|
|
198
|
-
}
|
|
174
|
+
webidl.brandCheck(this, FileLike)
|
|
199
175
|
|
|
200
176
|
return this[kState].blobLike.type
|
|
201
177
|
}
|
|
202
178
|
|
|
203
179
|
get name () {
|
|
204
|
-
|
|
205
|
-
throw new TypeError('Illegal invocation')
|
|
206
|
-
}
|
|
180
|
+
webidl.brandCheck(this, FileLike)
|
|
207
181
|
|
|
208
182
|
return this[kState].name
|
|
209
183
|
}
|
|
210
184
|
|
|
211
185
|
get lastModified () {
|
|
212
|
-
|
|
213
|
-
throw new TypeError('Illegal invocation')
|
|
214
|
-
}
|
|
186
|
+
webidl.brandCheck(this, FileLike)
|
|
215
187
|
|
|
216
188
|
return this[kState].lastModified
|
|
217
189
|
}
|
|
@@ -222,6 +194,10 @@ class FileLike {
|
|
|
222
194
|
}
|
|
223
195
|
|
|
224
196
|
Object.defineProperties(File.prototype, {
|
|
197
|
+
[Symbol.toStringTag]: {
|
|
198
|
+
value: 'File',
|
|
199
|
+
configurable: true
|
|
200
|
+
},
|
|
225
201
|
name: kEnumerableProperty,
|
|
226
202
|
lastModified: kEnumerableProperty
|
|
227
203
|
})
|
package/lib/fetch/formdata.js
CHANGED
|
@@ -8,11 +8,9 @@ const { Blob } = require('buffer')
|
|
|
8
8
|
|
|
9
9
|
// https://xhr.spec.whatwg.org/#formdata
|
|
10
10
|
class FormData {
|
|
11
|
-
static name = 'FormData'
|
|
12
|
-
|
|
13
11
|
constructor (form) {
|
|
14
12
|
if (form !== undefined) {
|
|
15
|
-
webidl.errors.conversionFailed({
|
|
13
|
+
throw webidl.errors.conversionFailed({
|
|
16
14
|
prefix: 'FormData constructor',
|
|
17
15
|
argument: 'Argument 1',
|
|
18
16
|
types: ['undefined']
|
|
@@ -23,15 +21,9 @@ class FormData {
|
|
|
23
21
|
}
|
|
24
22
|
|
|
25
23
|
append (name, value, filename = undefined) {
|
|
26
|
-
|
|
27
|
-
throw new TypeError('Illegal invocation')
|
|
28
|
-
}
|
|
24
|
+
webidl.brandCheck(this, FormData)
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
throw new TypeError(
|
|
32
|
-
`Failed to execute 'append' on 'FormData': 2 arguments required, but only ${arguments.length} present.`
|
|
33
|
-
)
|
|
34
|
-
}
|
|
26
|
+
webidl.argumentLengthCheck(arguments, 2, { header: 'FormData.append' })
|
|
35
27
|
|
|
36
28
|
if (arguments.length === 3 && !isBlobLike(value)) {
|
|
37
29
|
throw new TypeError(
|
|
@@ -58,15 +50,9 @@ class FormData {
|
|
|
58
50
|
}
|
|
59
51
|
|
|
60
52
|
delete (name) {
|
|
61
|
-
|
|
62
|
-
throw new TypeError('Illegal invocation')
|
|
63
|
-
}
|
|
53
|
+
webidl.brandCheck(this, FormData)
|
|
64
54
|
|
|
65
|
-
|
|
66
|
-
throw new TypeError(
|
|
67
|
-
`Failed to execute 'delete' on 'FormData': 1 arguments required, but only ${arguments.length} present.`
|
|
68
|
-
)
|
|
69
|
-
}
|
|
55
|
+
webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.delete' })
|
|
70
56
|
|
|
71
57
|
name = webidl.converters.USVString(name)
|
|
72
58
|
|
|
@@ -83,15 +69,9 @@ class FormData {
|
|
|
83
69
|
}
|
|
84
70
|
|
|
85
71
|
get (name) {
|
|
86
|
-
|
|
87
|
-
throw new TypeError('Illegal invocation')
|
|
88
|
-
}
|
|
72
|
+
webidl.brandCheck(this, FormData)
|
|
89
73
|
|
|
90
|
-
|
|
91
|
-
throw new TypeError(
|
|
92
|
-
`Failed to execute 'get' on 'FormData': 1 arguments required, but only ${arguments.length} present.`
|
|
93
|
-
)
|
|
94
|
-
}
|
|
74
|
+
webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.get' })
|
|
95
75
|
|
|
96
76
|
name = webidl.converters.USVString(name)
|
|
97
77
|
|
|
@@ -108,15 +88,9 @@ class FormData {
|
|
|
108
88
|
}
|
|
109
89
|
|
|
110
90
|
getAll (name) {
|
|
111
|
-
|
|
112
|
-
throw new TypeError('Illegal invocation')
|
|
113
|
-
}
|
|
91
|
+
webidl.brandCheck(this, FormData)
|
|
114
92
|
|
|
115
|
-
|
|
116
|
-
throw new TypeError(
|
|
117
|
-
`Failed to execute 'getAll' on 'FormData': 1 arguments required, but only ${arguments.length} present.`
|
|
118
|
-
)
|
|
119
|
-
}
|
|
93
|
+
webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.getAll' })
|
|
120
94
|
|
|
121
95
|
name = webidl.converters.USVString(name)
|
|
122
96
|
|
|
@@ -130,15 +104,9 @@ class FormData {
|
|
|
130
104
|
}
|
|
131
105
|
|
|
132
106
|
has (name) {
|
|
133
|
-
|
|
134
|
-
throw new TypeError('Illegal invocation')
|
|
135
|
-
}
|
|
107
|
+
webidl.brandCheck(this, FormData)
|
|
136
108
|
|
|
137
|
-
|
|
138
|
-
throw new TypeError(
|
|
139
|
-
`Failed to execute 'has' on 'FormData': 1 arguments required, but only ${arguments.length} present.`
|
|
140
|
-
)
|
|
141
|
-
}
|
|
109
|
+
webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.has' })
|
|
142
110
|
|
|
143
111
|
name = webidl.converters.USVString(name)
|
|
144
112
|
|
|
@@ -148,15 +116,9 @@ class FormData {
|
|
|
148
116
|
}
|
|
149
117
|
|
|
150
118
|
set (name, value, filename = undefined) {
|
|
151
|
-
|
|
152
|
-
throw new TypeError('Illegal invocation')
|
|
153
|
-
}
|
|
119
|
+
webidl.brandCheck(this, FormData)
|
|
154
120
|
|
|
155
|
-
|
|
156
|
-
throw new TypeError(
|
|
157
|
-
`Failed to execute 'set' on 'FormData': 2 arguments required, but only ${arguments.length} present.`
|
|
158
|
-
)
|
|
159
|
-
}
|
|
121
|
+
webidl.argumentLengthCheck(arguments, 2, { header: 'FormData.set' })
|
|
160
122
|
|
|
161
123
|
if (arguments.length === 3 && !isBlobLike(value)) {
|
|
162
124
|
throw new TypeError(
|
|
@@ -196,14 +158,8 @@ class FormData {
|
|
|
196
158
|
}
|
|
197
159
|
}
|
|
198
160
|
|
|
199
|
-
get [Symbol.toStringTag] () {
|
|
200
|
-
return this.constructor.name
|
|
201
|
-
}
|
|
202
|
-
|
|
203
161
|
entries () {
|
|
204
|
-
|
|
205
|
-
throw new TypeError('Illegal invocation')
|
|
206
|
-
}
|
|
162
|
+
webidl.brandCheck(this, FormData)
|
|
207
163
|
|
|
208
164
|
return makeIterator(
|
|
209
165
|
() => this[kState].map(pair => [pair.name, pair.value]),
|
|
@@ -213,9 +169,7 @@ class FormData {
|
|
|
213
169
|
}
|
|
214
170
|
|
|
215
171
|
keys () {
|
|
216
|
-
|
|
217
|
-
throw new TypeError('Illegal invocation')
|
|
218
|
-
}
|
|
172
|
+
webidl.brandCheck(this, FormData)
|
|
219
173
|
|
|
220
174
|
return makeIterator(
|
|
221
175
|
() => this[kState].map(pair => [pair.name, pair.value]),
|
|
@@ -225,9 +179,7 @@ class FormData {
|
|
|
225
179
|
}
|
|
226
180
|
|
|
227
181
|
values () {
|
|
228
|
-
|
|
229
|
-
throw new TypeError('Illegal invocation')
|
|
230
|
-
}
|
|
182
|
+
webidl.brandCheck(this, FormData)
|
|
231
183
|
|
|
232
184
|
return makeIterator(
|
|
233
185
|
() => this[kState].map(pair => [pair.name, pair.value]),
|
|
@@ -241,15 +193,9 @@ class FormData {
|
|
|
241
193
|
* @param {unknown} thisArg
|
|
242
194
|
*/
|
|
243
195
|
forEach (callbackFn, thisArg = globalThis) {
|
|
244
|
-
|
|
245
|
-
throw new TypeError('Illegal invocation')
|
|
246
|
-
}
|
|
196
|
+
webidl.brandCheck(this, FormData)
|
|
247
197
|
|
|
248
|
-
|
|
249
|
-
throw new TypeError(
|
|
250
|
-
`Failed to execute 'forEach' on 'FormData': 1 argument required, but only ${arguments.length} present.`
|
|
251
|
-
)
|
|
252
|
-
}
|
|
198
|
+
webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.forEach' })
|
|
253
199
|
|
|
254
200
|
if (typeof callbackFn !== 'function') {
|
|
255
201
|
throw new TypeError(
|
|
@@ -265,6 +211,13 @@ class FormData {
|
|
|
265
211
|
|
|
266
212
|
FormData.prototype[Symbol.iterator] = FormData.prototype.entries
|
|
267
213
|
|
|
214
|
+
Object.defineProperties(FormData.prototype, {
|
|
215
|
+
[Symbol.toStringTag]: {
|
|
216
|
+
value: 'FormData',
|
|
217
|
+
configurable: true
|
|
218
|
+
}
|
|
219
|
+
})
|
|
220
|
+
|
|
268
221
|
/**
|
|
269
222
|
* @see https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#create-an-entry
|
|
270
223
|
* @param {string} name
|