undici 6.13.0 → 6.14.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/docs/docs/api/EnvHttpProxyAgent.md +162 -0
- package/docs/docs/api/EventSource.md +27 -3
- package/docs/docs/api/Fetch.md +0 -6
- package/index.js +3 -1
- package/lib/api/util.js +14 -7
- package/lib/core/request.js +3 -5
- package/lib/core/symbols.js +4 -1
- package/lib/core/util.js +45 -20
- package/lib/dispatcher/client-h2.js +2 -4
- package/lib/dispatcher/client.js +2 -1
- package/lib/dispatcher/dispatcher-base.js +1 -3
- package/lib/dispatcher/env-http-proxy-agent.js +160 -0
- package/lib/dispatcher/pool.js +1 -1
- package/lib/llhttp/.gitkeep +0 -0
- package/lib/llhttp/llhttp-wasm.js +3 -1
- package/lib/llhttp/llhttp_simd-wasm.js +3 -1
- package/lib/web/cache/cache.js +2 -3
- package/lib/web/eventsource/eventsource.js +35 -38
- package/lib/web/fetch/body.js +12 -10
- package/lib/web/fetch/file.js +5 -216
- package/lib/web/fetch/formdata-parser.js +2 -2
- package/lib/web/fetch/formdata.js +3 -3
- package/lib/web/fetch/index.js +3 -6
- package/lib/web/fetch/request.js +8 -26
- package/lib/web/fetch/response.js +9 -22
- package/lib/web/fetch/symbols.js +0 -1
- package/lib/web/fetch/util.js +34 -8
- package/lib/web/websocket/util.js +6 -13
- package/package.json +4 -3
- package/types/dispatcher.d.ts +1 -1
- package/types/env-http-proxy-agent.d.ts +21 -0
- package/types/eventsource.d.ts +4 -2
- package/types/index.d.ts +2 -1
- package/lib/llhttp/constants.d.ts +0 -199
- package/lib/llhttp/constants.js.map +0 -1
- package/lib/llhttp/utils.d.ts +0 -4
- package/lib/llhttp/utils.js.map +0 -1
- package/lib/llhttp/wasm_build_env.txt +0 -32
package/lib/web/fetch/file.js
CHANGED
|
@@ -1,100 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const {
|
|
4
|
-
const { Blob, File: NativeFile } = require('node:buffer')
|
|
5
|
-
const { types } = require('node:util')
|
|
3
|
+
const { Blob, File } = require('node:buffer')
|
|
6
4
|
const { kState } = require('./symbols')
|
|
7
|
-
const { isBlobLike } = require('./util')
|
|
8
5
|
const { webidl } = require('./webidl')
|
|
9
|
-
const { parseMIMEType, serializeAMimeType } = require('./data-url')
|
|
10
|
-
const { kEnumerableProperty } = require('../../core/util')
|
|
11
|
-
|
|
12
|
-
const encoder = new TextEncoder()
|
|
13
|
-
|
|
14
|
-
class File extends Blob {
|
|
15
|
-
constructor (fileBits, fileName, options = {}) {
|
|
16
|
-
// The File constructor is invoked with two or three parameters, depending
|
|
17
|
-
// on whether the optional dictionary parameter is used. When the File()
|
|
18
|
-
// constructor is invoked, user agents must run the following steps:
|
|
19
|
-
webidl.argumentLengthCheck(arguments, 2, { header: 'File constructor' })
|
|
20
|
-
|
|
21
|
-
fileBits = webidl.converters['sequence<BlobPart>'](fileBits)
|
|
22
|
-
fileName = webidl.converters.USVString(fileName)
|
|
23
|
-
options = webidl.converters.FilePropertyBag(options)
|
|
24
|
-
|
|
25
|
-
// 1. Let bytes be the result of processing blob parts given fileBits and
|
|
26
|
-
// options.
|
|
27
|
-
// Note: Blob handles this for us
|
|
28
|
-
|
|
29
|
-
// 2. Let n be the fileName argument to the constructor.
|
|
30
|
-
const n = fileName
|
|
31
|
-
|
|
32
|
-
// 3. Process FilePropertyBag dictionary argument by running the following
|
|
33
|
-
// substeps:
|
|
34
|
-
|
|
35
|
-
// 1. If the type member is provided and is not the empty string, let t
|
|
36
|
-
// be set to the type dictionary member. If t contains any characters
|
|
37
|
-
// outside the range U+0020 to U+007E, then set t to the empty string
|
|
38
|
-
// and return from these substeps.
|
|
39
|
-
// 2. Convert every character in t to ASCII lowercase.
|
|
40
|
-
let t = options.type
|
|
41
|
-
let d
|
|
42
|
-
|
|
43
|
-
// eslint-disable-next-line no-labels
|
|
44
|
-
substep: {
|
|
45
|
-
if (t) {
|
|
46
|
-
t = parseMIMEType(t)
|
|
47
|
-
|
|
48
|
-
if (t === 'failure') {
|
|
49
|
-
t = ''
|
|
50
|
-
// eslint-disable-next-line no-labels
|
|
51
|
-
break substep
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
t = serializeAMimeType(t).toLowerCase()
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// 3. If the lastModified member is provided, let d be set to the
|
|
58
|
-
// lastModified dictionary member. If it is not provided, set d to the
|
|
59
|
-
// current date and time represented as the number of milliseconds since
|
|
60
|
-
// the Unix Epoch (which is the equivalent of Date.now() [ECMA-262]).
|
|
61
|
-
d = options.lastModified
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// 4. Return a new File object F such that:
|
|
65
|
-
// F refers to the bytes byte sequence.
|
|
66
|
-
// F.size is set to the number of total bytes in bytes.
|
|
67
|
-
// F.name is set to n.
|
|
68
|
-
// F.type is set to t.
|
|
69
|
-
// F.lastModified is set to d.
|
|
70
|
-
|
|
71
|
-
super(processBlobParts(fileBits, options), { type: t })
|
|
72
|
-
this[kState] = {
|
|
73
|
-
name: n,
|
|
74
|
-
lastModified: d,
|
|
75
|
-
type: t
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
get name () {
|
|
80
|
-
webidl.brandCheck(this, File)
|
|
81
|
-
|
|
82
|
-
return this[kState].name
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
get lastModified () {
|
|
86
|
-
webidl.brandCheck(this, File)
|
|
87
|
-
|
|
88
|
-
return this[kState].lastModified
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
get type () {
|
|
92
|
-
webidl.brandCheck(this, File)
|
|
93
|
-
|
|
94
|
-
return this[kState].type
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
6
|
|
|
7
|
+
// TODO(@KhafraDev): remove
|
|
98
8
|
class FileLike {
|
|
99
9
|
constructor (blobLike, fileName, options = {}) {
|
|
100
10
|
// TODO: argument idl type check
|
|
@@ -196,136 +106,15 @@ class FileLike {
|
|
|
196
106
|
}
|
|
197
107
|
}
|
|
198
108
|
|
|
199
|
-
Object.defineProperties(File.prototype, {
|
|
200
|
-
[Symbol.toStringTag]: {
|
|
201
|
-
value: 'File',
|
|
202
|
-
configurable: true
|
|
203
|
-
},
|
|
204
|
-
name: kEnumerableProperty,
|
|
205
|
-
lastModified: kEnumerableProperty
|
|
206
|
-
})
|
|
207
|
-
|
|
208
109
|
webidl.converters.Blob = webidl.interfaceConverter(Blob)
|
|
209
110
|
|
|
210
|
-
webidl.converters.BlobPart = function (V, opts) {
|
|
211
|
-
if (webidl.util.Type(V) === 'Object') {
|
|
212
|
-
if (isBlobLike(V)) {
|
|
213
|
-
return webidl.converters.Blob(V, { strict: false })
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (ArrayBuffer.isView(V) || types.isAnyArrayBuffer(V)) {
|
|
217
|
-
return webidl.converters.BufferSource(V, opts)
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return webidl.converters.USVString(V, opts)
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
webidl.converters['sequence<BlobPart>'] = webidl.sequenceConverter(
|
|
225
|
-
webidl.converters.BlobPart
|
|
226
|
-
)
|
|
227
|
-
|
|
228
|
-
// https://www.w3.org/TR/FileAPI/#dfn-FilePropertyBag
|
|
229
|
-
webidl.converters.FilePropertyBag = webidl.dictionaryConverter([
|
|
230
|
-
{
|
|
231
|
-
key: 'lastModified',
|
|
232
|
-
converter: webidl.converters['long long'],
|
|
233
|
-
get defaultValue () {
|
|
234
|
-
return Date.now()
|
|
235
|
-
}
|
|
236
|
-
},
|
|
237
|
-
{
|
|
238
|
-
key: 'type',
|
|
239
|
-
converter: webidl.converters.DOMString,
|
|
240
|
-
defaultValue: ''
|
|
241
|
-
},
|
|
242
|
-
{
|
|
243
|
-
key: 'endings',
|
|
244
|
-
converter: (value) => {
|
|
245
|
-
value = webidl.converters.DOMString(value)
|
|
246
|
-
value = value.toLowerCase()
|
|
247
|
-
|
|
248
|
-
if (value !== 'native') {
|
|
249
|
-
value = 'transparent'
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
return value
|
|
253
|
-
},
|
|
254
|
-
defaultValue: 'transparent'
|
|
255
|
-
}
|
|
256
|
-
])
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* @see https://www.w3.org/TR/FileAPI/#process-blob-parts
|
|
260
|
-
* @param {(NodeJS.TypedArray|Blob|string)[]} parts
|
|
261
|
-
* @param {{ type: string, endings: string }} options
|
|
262
|
-
*/
|
|
263
|
-
function processBlobParts (parts, options) {
|
|
264
|
-
// 1. Let bytes be an empty sequence of bytes.
|
|
265
|
-
/** @type {NodeJS.TypedArray[]} */
|
|
266
|
-
const bytes = []
|
|
267
|
-
|
|
268
|
-
// 2. For each element in parts:
|
|
269
|
-
for (const element of parts) {
|
|
270
|
-
// 1. If element is a USVString, run the following substeps:
|
|
271
|
-
if (typeof element === 'string') {
|
|
272
|
-
// 1. Let s be element.
|
|
273
|
-
let s = element
|
|
274
|
-
|
|
275
|
-
// 2. If the endings member of options is "native", set s
|
|
276
|
-
// to the result of converting line endings to native
|
|
277
|
-
// of element.
|
|
278
|
-
if (options.endings === 'native') {
|
|
279
|
-
s = convertLineEndingsNative(s)
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// 3. Append the result of UTF-8 encoding s to bytes.
|
|
283
|
-
bytes.push(encoder.encode(s))
|
|
284
|
-
} else if (ArrayBuffer.isView(element) || types.isArrayBuffer(element)) {
|
|
285
|
-
// 2. If element is a BufferSource, get a copy of the
|
|
286
|
-
// bytes held by the buffer source, and append those
|
|
287
|
-
// bytes to bytes.
|
|
288
|
-
if (element.buffer) {
|
|
289
|
-
bytes.push(
|
|
290
|
-
new Uint8Array(element.buffer, element.byteOffset, element.byteLength)
|
|
291
|
-
)
|
|
292
|
-
} else { // ArrayBuffer
|
|
293
|
-
bytes.push(new Uint8Array(element))
|
|
294
|
-
}
|
|
295
|
-
} else if (isBlobLike(element)) {
|
|
296
|
-
// 3. If element is a Blob, append the bytes it represents
|
|
297
|
-
// to bytes.
|
|
298
|
-
bytes.push(element)
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// 3. Return bytes.
|
|
303
|
-
return bytes
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* @see https://www.w3.org/TR/FileAPI/#convert-line-endings-to-native
|
|
308
|
-
* @param {string} s
|
|
309
|
-
*/
|
|
310
|
-
function convertLineEndingsNative (s) {
|
|
311
|
-
// 1. Let native line ending be be the code point U+000A LF.
|
|
312
|
-
// 2. If the underlying platform’s conventions are to
|
|
313
|
-
// represent newlines as a carriage return and line feed
|
|
314
|
-
// sequence, set native line ending to the code point
|
|
315
|
-
// U+000D CR followed by the code point U+000A LF.
|
|
316
|
-
// NOTE: We are using the native line ending for the current
|
|
317
|
-
// platform, provided by node's os module.
|
|
318
|
-
|
|
319
|
-
return s.replace(/\r?\n/g, EOL)
|
|
320
|
-
}
|
|
321
|
-
|
|
322
111
|
// If this function is moved to ./util.js, some tools (such as
|
|
323
112
|
// rollup) will warn about circular dependencies. See:
|
|
324
113
|
// https://github.com/nodejs/undici/issues/1629
|
|
325
114
|
function isFileLike (object) {
|
|
326
115
|
return (
|
|
327
|
-
(
|
|
328
|
-
|
|
116
|
+
(object instanceof File) ||
|
|
117
|
+
(
|
|
329
118
|
object &&
|
|
330
119
|
(typeof object.stream === 'function' ||
|
|
331
120
|
typeof object.arrayBuffer === 'function') &&
|
|
@@ -334,4 +123,4 @@ function isFileLike (object) {
|
|
|
334
123
|
)
|
|
335
124
|
}
|
|
336
125
|
|
|
337
|
-
module.exports = {
|
|
126
|
+
module.exports = { FileLike, isFileLike }
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
const { isUSVString, bufferToLowerCasedHeaderName } = require('../../core/util')
|
|
4
4
|
const { utf8DecodeBytes } = require('./util')
|
|
5
5
|
const { HTTP_TOKEN_CODEPOINTS, isomorphicDecode } = require('./data-url')
|
|
6
|
-
const { isFileLike
|
|
6
|
+
const { isFileLike } = require('./file')
|
|
7
7
|
const { makeEntry } = require('./formdata')
|
|
8
8
|
const assert = require('node:assert')
|
|
9
9
|
const { File: NodeFile } = require('node:buffer')
|
|
10
10
|
|
|
11
|
-
const File = globalThis.File ?? NodeFile
|
|
11
|
+
const File = globalThis.File ?? NodeFile
|
|
12
12
|
|
|
13
13
|
const formDataNameBuffer = Buffer.from('form-data; name="')
|
|
14
14
|
const filenameBuffer = Buffer.from('; filename')
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
const { isBlobLike, iteratorMixin } = require('./util')
|
|
4
4
|
const { kState } = require('./symbols')
|
|
5
5
|
const { kEnumerableProperty } = require('../../core/util')
|
|
6
|
-
const {
|
|
6
|
+
const { FileLike, isFileLike } = require('./file')
|
|
7
7
|
const { webidl } = require('./webidl')
|
|
8
8
|
const { File: NativeFile } = require('node:buffer')
|
|
9
9
|
const nodeUtil = require('node:util')
|
|
10
10
|
|
|
11
11
|
/** @type {globalThis['File']} */
|
|
12
|
-
const File =
|
|
12
|
+
const File = globalThis.File ?? NativeFile
|
|
13
13
|
|
|
14
14
|
// https://xhr.spec.whatwg.org/#formdata
|
|
15
15
|
class FormData {
|
|
@@ -231,7 +231,7 @@ function makeEntry (name, value, filename) {
|
|
|
231
231
|
lastModified: value.lastModified
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
-
value =
|
|
234
|
+
value = value instanceof NativeFile
|
|
235
235
|
? new File([value], filename, options)
|
|
236
236
|
: new FileLike(value, filename, options)
|
|
237
237
|
}
|
package/lib/web/fetch/index.js
CHANGED
|
@@ -59,7 +59,7 @@ const {
|
|
|
59
59
|
} = require('./constants')
|
|
60
60
|
const EE = require('node:events')
|
|
61
61
|
const { Readable, pipeline, finished } = require('node:stream')
|
|
62
|
-
const { addAbortListener, isErrored, isReadable,
|
|
62
|
+
const { addAbortListener, isErrored, isReadable, bufferToLowerCasedHeaderName } = require('../../core/util')
|
|
63
63
|
const { dataURLProcessor, serializeAMimeType, minimizeSupportedMimeType } = require('./data-url')
|
|
64
64
|
const { getGlobalDispatcher } = require('../../global')
|
|
65
65
|
const { webidl } = require('./webidl')
|
|
@@ -165,7 +165,6 @@ function fetch (input, init = undefined) {
|
|
|
165
165
|
let responseObject = null
|
|
166
166
|
|
|
167
167
|
// 8. Let relevantRealm be this’s relevant Realm.
|
|
168
|
-
const relevantRealm = null
|
|
169
168
|
|
|
170
169
|
// 9. Let locallyAborted be false.
|
|
171
170
|
let locallyAborted = false
|
|
@@ -229,7 +228,7 @@ function fetch (input, init = undefined) {
|
|
|
229
228
|
|
|
230
229
|
// 4. Set responseObject to the result of creating a Response object,
|
|
231
230
|
// given response, "immutable", and relevantRealm.
|
|
232
|
-
responseObject = fromInnerResponse(response, 'immutable'
|
|
231
|
+
responseObject = fromInnerResponse(response, 'immutable')
|
|
233
232
|
|
|
234
233
|
// 5. Resolve p with responseObject.
|
|
235
234
|
p.resolve(responseObject)
|
|
@@ -310,9 +309,7 @@ function finalizeAndReportTiming (response, initiatorType = 'other') {
|
|
|
310
309
|
}
|
|
311
310
|
|
|
312
311
|
// https://w3c.github.io/resource-timing/#dfn-mark-resource-timing
|
|
313
|
-
const markResourceTiming =
|
|
314
|
-
? performance.markResourceTiming
|
|
315
|
-
: () => {}
|
|
312
|
+
const markResourceTiming = performance.markResourceTiming
|
|
316
313
|
|
|
317
314
|
// https://fetch.spec.whatwg.org/#abort-fetch
|
|
318
315
|
function abortFetch (p, request, responseObject, error) {
|
package/lib/web/fetch/request.js
CHANGED
|
@@ -11,7 +11,7 @@ const {
|
|
|
11
11
|
isValidHTTPToken,
|
|
12
12
|
sameOrigin,
|
|
13
13
|
normalizeMethod,
|
|
14
|
-
|
|
14
|
+
environmentSettingsObject,
|
|
15
15
|
normalizeMethodRecord
|
|
16
16
|
} = require('./util')
|
|
17
17
|
const {
|
|
@@ -25,9 +25,8 @@ const {
|
|
|
25
25
|
requestDuplex
|
|
26
26
|
} = require('./constants')
|
|
27
27
|
const { kEnumerableProperty } = util
|
|
28
|
-
const { kHeaders, kSignal, kState, kGuard,
|
|
28
|
+
const { kHeaders, kSignal, kState, kGuard, kDispatcher } = require('./symbols')
|
|
29
29
|
const { webidl } = require('./webidl')
|
|
30
|
-
const { getGlobalOrigin } = require('./global')
|
|
31
30
|
const { URLSerializer } = require('./data-url')
|
|
32
31
|
const { kHeadersList, kConstruct } = require('../../core/symbols')
|
|
33
32
|
const assert = require('node:assert')
|
|
@@ -54,17 +53,6 @@ class Request {
|
|
|
54
53
|
input = webidl.converters.RequestInfo(input)
|
|
55
54
|
init = webidl.converters.RequestInit(init)
|
|
56
55
|
|
|
57
|
-
// https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object
|
|
58
|
-
this[kRealm] = {
|
|
59
|
-
settingsObject: {
|
|
60
|
-
baseUrl: getGlobalOrigin(),
|
|
61
|
-
get origin () {
|
|
62
|
-
return this.baseUrl?.origin
|
|
63
|
-
},
|
|
64
|
-
policyContainer: makePolicyContainer()
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
56
|
// 1. Let request be null.
|
|
69
57
|
let request = null
|
|
70
58
|
|
|
@@ -72,7 +60,7 @@ class Request {
|
|
|
72
60
|
let fallbackMode = null
|
|
73
61
|
|
|
74
62
|
// 3. Let baseURL be this’s relevant settings object’s API base URL.
|
|
75
|
-
const baseUrl =
|
|
63
|
+
const baseUrl = environmentSettingsObject.settingsObject.baseUrl
|
|
76
64
|
|
|
77
65
|
// 4. Let signal be null.
|
|
78
66
|
let signal = null
|
|
@@ -119,7 +107,7 @@ class Request {
|
|
|
119
107
|
}
|
|
120
108
|
|
|
121
109
|
// 7. Let origin be this’s relevant settings object’s origin.
|
|
122
|
-
const origin =
|
|
110
|
+
const origin = environmentSettingsObject.settingsObject.origin
|
|
123
111
|
|
|
124
112
|
// 8. Let window be "client".
|
|
125
113
|
let window = 'client'
|
|
@@ -155,7 +143,7 @@ class Request {
|
|
|
155
143
|
// unsafe-request flag Set.
|
|
156
144
|
unsafeRequest: request.unsafeRequest,
|
|
157
145
|
// client This’s relevant settings object.
|
|
158
|
-
client:
|
|
146
|
+
client: environmentSettingsObject.settingsObject,
|
|
159
147
|
// window window.
|
|
160
148
|
window,
|
|
161
149
|
// priority request’s priority.
|
|
@@ -244,7 +232,7 @@ class Request {
|
|
|
244
232
|
// then set request’s referrer to "client".
|
|
245
233
|
if (
|
|
246
234
|
(parsedReferrer.protocol === 'about:' && parsedReferrer.hostname === 'client') ||
|
|
247
|
-
(origin && !sameOrigin(parsedReferrer,
|
|
235
|
+
(origin && !sameOrigin(parsedReferrer, environmentSettingsObject.settingsObject.baseUrl))
|
|
248
236
|
) {
|
|
249
237
|
request.referrer = 'client'
|
|
250
238
|
} else {
|
|
@@ -366,7 +354,6 @@ class Request {
|
|
|
366
354
|
// (https://dom.spec.whatwg.org/#dom-abortsignal-any)
|
|
367
355
|
const ac = new AbortController()
|
|
368
356
|
this[kSignal] = ac.signal
|
|
369
|
-
this[kSignal][kRealm] = this[kRealm]
|
|
370
357
|
|
|
371
358
|
// 29. If signal is not null, then make this’s signal follow signal.
|
|
372
359
|
if (signal != null) {
|
|
@@ -436,7 +423,6 @@ class Request {
|
|
|
436
423
|
this[kHeaders] = new Headers(kConstruct)
|
|
437
424
|
this[kHeaders][kHeadersList] = request.headersList
|
|
438
425
|
this[kHeaders][kGuard] = 'request'
|
|
439
|
-
this[kHeaders][kRealm] = this[kRealm]
|
|
440
426
|
|
|
441
427
|
// 31. If this’s request’s mode is "no-cors", then:
|
|
442
428
|
if (mode === 'no-cors') {
|
|
@@ -770,7 +756,7 @@ class Request {
|
|
|
770
756
|
}
|
|
771
757
|
|
|
772
758
|
// 4. Return clonedRequestObject.
|
|
773
|
-
return fromInnerRequest(clonedRequest, ac.signal, this[kHeaders][kGuard]
|
|
759
|
+
return fromInnerRequest(clonedRequest, ac.signal, this[kHeaders][kGuard])
|
|
774
760
|
}
|
|
775
761
|
|
|
776
762
|
[nodeUtil.inspect.custom] (depth, options) {
|
|
@@ -873,19 +859,15 @@ function cloneRequest (request) {
|
|
|
873
859
|
* @param {any} innerRequest
|
|
874
860
|
* @param {AbortSignal} signal
|
|
875
861
|
* @param {'request' | 'immutable' | 'request-no-cors' | 'response' | 'none'} guard
|
|
876
|
-
* @param {any} [realm]
|
|
877
862
|
* @returns {Request}
|
|
878
863
|
*/
|
|
879
|
-
function fromInnerRequest (innerRequest, signal, guard
|
|
864
|
+
function fromInnerRequest (innerRequest, signal, guard) {
|
|
880
865
|
const request = new Request(kConstruct)
|
|
881
866
|
request[kState] = innerRequest
|
|
882
|
-
request[kRealm] = realm
|
|
883
867
|
request[kSignal] = signal
|
|
884
|
-
request[kSignal][kRealm] = realm
|
|
885
868
|
request[kHeaders] = new Headers(kConstruct)
|
|
886
869
|
request[kHeaders][kHeadersList] = innerRequest.headersList
|
|
887
870
|
request[kHeaders][kGuard] = guard
|
|
888
|
-
request[kHeaders][kRealm] = realm
|
|
889
871
|
return request
|
|
890
872
|
}
|
|
891
873
|
|
|
@@ -12,16 +12,16 @@ const {
|
|
|
12
12
|
isBlobLike,
|
|
13
13
|
serializeJavascriptValueToJSONString,
|
|
14
14
|
isErrorLike,
|
|
15
|
-
isomorphicEncode
|
|
15
|
+
isomorphicEncode,
|
|
16
|
+
environmentSettingsObject: relevantRealm
|
|
16
17
|
} = require('./util')
|
|
17
18
|
const {
|
|
18
19
|
redirectStatusSet,
|
|
19
20
|
nullBodyStatus
|
|
20
21
|
} = require('./constants')
|
|
21
|
-
const { kState, kHeaders, kGuard
|
|
22
|
+
const { kState, kHeaders, kGuard } = require('./symbols')
|
|
22
23
|
const { webidl } = require('./webidl')
|
|
23
24
|
const { FormData } = require('./formdata')
|
|
24
|
-
const { getGlobalOrigin } = require('./global')
|
|
25
25
|
const { URLSerializer } = require('./data-url')
|
|
26
26
|
const { kHeadersList, kConstruct } = require('../../core/symbols')
|
|
27
27
|
const assert = require('node:assert')
|
|
@@ -33,13 +33,10 @@ const textEncoder = new TextEncoder('utf-8')
|
|
|
33
33
|
class Response {
|
|
34
34
|
// Creates network error Response.
|
|
35
35
|
static error () {
|
|
36
|
-
// TODO
|
|
37
|
-
const relevantRealm = { settingsObject: {} }
|
|
38
|
-
|
|
39
36
|
// The static error() method steps are to return the result of creating a
|
|
40
37
|
// Response object, given a new network error, "immutable", and this’s
|
|
41
38
|
// relevant Realm.
|
|
42
|
-
const responseObject = fromInnerResponse(makeNetworkError(), 'immutable'
|
|
39
|
+
const responseObject = fromInnerResponse(makeNetworkError(), 'immutable')
|
|
43
40
|
|
|
44
41
|
return responseObject
|
|
45
42
|
}
|
|
@@ -62,8 +59,7 @@ class Response {
|
|
|
62
59
|
|
|
63
60
|
// 3. Let responseObject be the result of creating a Response object, given a new response,
|
|
64
61
|
// "response", and this’s relevant Realm.
|
|
65
|
-
const
|
|
66
|
-
const responseObject = fromInnerResponse(makeResponse({}), 'response', relevantRealm)
|
|
62
|
+
const responseObject = fromInnerResponse(makeResponse({}), 'response')
|
|
67
63
|
|
|
68
64
|
// 4. Perform initialize a response given responseObject, init, and (body, "application/json").
|
|
69
65
|
initializeResponse(responseObject, init, { body: body[0], type: 'application/json' })
|
|
@@ -74,8 +70,6 @@ class Response {
|
|
|
74
70
|
|
|
75
71
|
// Creates a redirect Response that redirects to url with status status.
|
|
76
72
|
static redirect (url, status = 302) {
|
|
77
|
-
const relevantRealm = { settingsObject: {} }
|
|
78
|
-
|
|
79
73
|
webidl.argumentLengthCheck(arguments, 1, { header: 'Response.redirect' })
|
|
80
74
|
|
|
81
75
|
url = webidl.converters.USVString(url)
|
|
@@ -87,7 +81,7 @@ class Response {
|
|
|
87
81
|
// TODO: base-URL?
|
|
88
82
|
let parsedURL
|
|
89
83
|
try {
|
|
90
|
-
parsedURL = new URL(url,
|
|
84
|
+
parsedURL = new URL(url, relevantRealm.settingsObject.baseUrl)
|
|
91
85
|
} catch (err) {
|
|
92
86
|
throw new TypeError(`Failed to parse URL from ${url}`, { cause: err })
|
|
93
87
|
}
|
|
@@ -99,7 +93,7 @@ class Response {
|
|
|
99
93
|
|
|
100
94
|
// 4. Let responseObject be the result of creating a Response object,
|
|
101
95
|
// given a new response, "immutable", and this’s relevant Realm.
|
|
102
|
-
const responseObject = fromInnerResponse(makeResponse({}), 'immutable'
|
|
96
|
+
const responseObject = fromInnerResponse(makeResponse({}), 'immutable')
|
|
103
97
|
|
|
104
98
|
// 5. Set responseObject’s response’s status to status.
|
|
105
99
|
responseObject[kState].status = status
|
|
@@ -126,9 +120,6 @@ class Response {
|
|
|
126
120
|
|
|
127
121
|
init = webidl.converters.ResponseInit(init)
|
|
128
122
|
|
|
129
|
-
// TODO
|
|
130
|
-
this[kRealm] = { settingsObject: {} }
|
|
131
|
-
|
|
132
123
|
// 1. Set this’s response to a new response.
|
|
133
124
|
this[kState] = makeResponse({})
|
|
134
125
|
|
|
@@ -138,7 +129,6 @@ class Response {
|
|
|
138
129
|
this[kHeaders] = new Headers(kConstruct)
|
|
139
130
|
this[kHeaders][kGuard] = 'response'
|
|
140
131
|
this[kHeaders][kHeadersList] = this[kState].headersList
|
|
141
|
-
this[kHeaders][kRealm] = this[kRealm]
|
|
142
132
|
|
|
143
133
|
// 3. Let bodyWithType be null.
|
|
144
134
|
let bodyWithType = null
|
|
@@ -251,7 +241,7 @@ class Response {
|
|
|
251
241
|
|
|
252
242
|
// 3. Return the result of creating a Response object, given
|
|
253
243
|
// clonedResponse, this’s headers’s guard, and this’s relevant Realm.
|
|
254
|
-
return fromInnerResponse(clonedResponse, this[kHeaders][kGuard]
|
|
244
|
+
return fromInnerResponse(clonedResponse, this[kHeaders][kGuard])
|
|
255
245
|
}
|
|
256
246
|
|
|
257
247
|
[nodeUtil.inspect.custom] (depth, options) {
|
|
@@ -512,17 +502,14 @@ function initializeResponse (response, init, body) {
|
|
|
512
502
|
* @see https://fetch.spec.whatwg.org/#response-create
|
|
513
503
|
* @param {any} innerResponse
|
|
514
504
|
* @param {'request' | 'immutable' | 'request-no-cors' | 'response' | 'none'} guard
|
|
515
|
-
* @param {any} [realm]
|
|
516
505
|
* @returns {Response}
|
|
517
506
|
*/
|
|
518
|
-
function fromInnerResponse (innerResponse, guard
|
|
507
|
+
function fromInnerResponse (innerResponse, guard) {
|
|
519
508
|
const response = new Response(kConstruct)
|
|
520
509
|
response[kState] = innerResponse
|
|
521
|
-
response[kRealm] = realm
|
|
522
510
|
response[kHeaders] = new Headers(kConstruct)
|
|
523
511
|
response[kHeaders][kHeadersList] = innerResponse.headersList
|
|
524
512
|
response[kHeaders][kGuard] = guard
|
|
525
|
-
response[kHeaders][kRealm] = realm
|
|
526
513
|
return response
|
|
527
514
|
}
|
|
528
515
|
|
package/lib/web/fetch/symbols.js
CHANGED
package/lib/web/fetch/util.js
CHANGED
|
@@ -1043,7 +1043,7 @@ function iteratorMixin (name, object, kInternalIterator, keyIndex = 0, valueInde
|
|
|
1043
1043
|
/**
|
|
1044
1044
|
* @see https://fetch.spec.whatwg.org/#body-fully-read
|
|
1045
1045
|
*/
|
|
1046
|
-
async function fullyReadBody (body, processBody, processBodyError) {
|
|
1046
|
+
async function fullyReadBody (body, processBody, processBodyError, shouldClone) {
|
|
1047
1047
|
// 1. If taskDestination is null, then set taskDestination to
|
|
1048
1048
|
// the result of starting a new parallel queue.
|
|
1049
1049
|
|
|
@@ -1069,8 +1069,7 @@ async function fullyReadBody (body, processBody, processBodyError) {
|
|
|
1069
1069
|
|
|
1070
1070
|
// 5. Read all bytes from reader, given successSteps and errorSteps.
|
|
1071
1071
|
try {
|
|
1072
|
-
|
|
1073
|
-
successSteps(result)
|
|
1072
|
+
successSteps(await readAllBytes(reader, shouldClone))
|
|
1074
1073
|
} catch (e) {
|
|
1075
1074
|
errorSteps(e)
|
|
1076
1075
|
}
|
|
@@ -1098,15 +1097,15 @@ function readableStreamClose (controller) {
|
|
|
1098
1097
|
}
|
|
1099
1098
|
}
|
|
1100
1099
|
|
|
1100
|
+
const invalidIsomorphicEncodeValueRegex = /[^\x00-\xFF]/ // eslint-disable-line
|
|
1101
|
+
|
|
1101
1102
|
/**
|
|
1102
1103
|
* @see https://infra.spec.whatwg.org/#isomorphic-encode
|
|
1103
1104
|
* @param {string} input
|
|
1104
1105
|
*/
|
|
1105
1106
|
function isomorphicEncode (input) {
|
|
1106
1107
|
// 1. Assert: input contains no code points greater than U+00FF.
|
|
1107
|
-
|
|
1108
|
-
assert(input.charCodeAt(i) <= 0xFF)
|
|
1109
|
-
}
|
|
1108
|
+
assert(!invalidIsomorphicEncodeValueRegex.test(input))
|
|
1110
1109
|
|
|
1111
1110
|
// 2. Return a byte sequence whose length is equal to input’s code
|
|
1112
1111
|
// point length and whose bytes have the same values as the
|
|
@@ -1118,8 +1117,9 @@ function isomorphicEncode (input) {
|
|
|
1118
1117
|
* @see https://streams.spec.whatwg.org/#readablestreamdefaultreader-read-all-bytes
|
|
1119
1118
|
* @see https://streams.spec.whatwg.org/#read-loop
|
|
1120
1119
|
* @param {ReadableStreamDefaultReader} reader
|
|
1120
|
+
* @param {boolean} [shouldClone]
|
|
1121
1121
|
*/
|
|
1122
|
-
async function readAllBytes (reader) {
|
|
1122
|
+
async function readAllBytes (reader, shouldClone) {
|
|
1123
1123
|
const bytes = []
|
|
1124
1124
|
let byteLength = 0
|
|
1125
1125
|
|
|
@@ -1128,6 +1128,13 @@ async function readAllBytes (reader) {
|
|
|
1128
1128
|
|
|
1129
1129
|
if (done) {
|
|
1130
1130
|
// 1. Call successSteps with bytes.
|
|
1131
|
+
if (bytes.length === 1) {
|
|
1132
|
+
const { buffer, byteOffset, byteLength } = bytes[0]
|
|
1133
|
+
if (shouldClone === false) {
|
|
1134
|
+
return Buffer.from(buffer, byteOffset, byteLength)
|
|
1135
|
+
}
|
|
1136
|
+
return Buffer.from(buffer.slice(byteOffset, byteOffset + byteLength), 0, byteLength)
|
|
1137
|
+
}
|
|
1131
1138
|
return Buffer.concat(bytes, byteLength)
|
|
1132
1139
|
}
|
|
1133
1140
|
|
|
@@ -1562,6 +1569,24 @@ function utf8DecodeBytes (buffer) {
|
|
|
1562
1569
|
return output
|
|
1563
1570
|
}
|
|
1564
1571
|
|
|
1572
|
+
class EnvironmentSettingsObjectBase {
|
|
1573
|
+
get baseUrl () {
|
|
1574
|
+
return getGlobalOrigin()
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
get origin () {
|
|
1578
|
+
return this.baseUrl?.origin
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
policyContainer = makePolicyContainer()
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
class EnvironmentSettingsObject {
|
|
1585
|
+
settingsObject = new EnvironmentSettingsObjectBase()
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
const environmentSettingsObject = new EnvironmentSettingsObject()
|
|
1589
|
+
|
|
1565
1590
|
module.exports = {
|
|
1566
1591
|
isAborted,
|
|
1567
1592
|
isCancelled,
|
|
@@ -1613,5 +1638,6 @@ module.exports = {
|
|
|
1613
1638
|
createInflate,
|
|
1614
1639
|
extractMimeType,
|
|
1615
1640
|
getDecodeSplit,
|
|
1616
|
-
utf8DecodeBytes
|
|
1641
|
+
utf8DecodeBytes,
|
|
1642
|
+
environmentSettingsObject
|
|
1617
1643
|
}
|
|
@@ -211,19 +211,12 @@ const fatalDecoder = hasIntl ? new TextDecoder('utf-8', { fatal: true }) : undef
|
|
|
211
211
|
*/
|
|
212
212
|
const utf8Decode = hasIntl
|
|
213
213
|
? fatalDecoder.decode.bind(fatalDecoder)
|
|
214
|
-
:
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
}
|
|
221
|
-
: function (buffer) {
|
|
222
|
-
if (isUtf8(buffer)) {
|
|
223
|
-
return buffer.toString('utf-8')
|
|
224
|
-
}
|
|
225
|
-
throw new TypeError('Invalid utf-8 received.')
|
|
226
|
-
}
|
|
214
|
+
: function (buffer) {
|
|
215
|
+
if (isUtf8(buffer)) {
|
|
216
|
+
return buffer.toString('utf-8')
|
|
217
|
+
}
|
|
218
|
+
throw new TypeError('Invalid utf-8 received.')
|
|
219
|
+
}
|
|
227
220
|
|
|
228
221
|
module.exports = {
|
|
229
222
|
isConnecting,
|