Skip to content

Commit f375e1d

Browse files
ronagKhafraDev
authored andcommitted
fix(fetch): toUSVString (nodejs#986)
* fix(fetch): toUSVString * fixup * fixup * fixup
1 parent ad8f6e9 commit f375e1d

File tree

6 files changed

+38
-31
lines changed

6 files changed

+38
-31
lines changed

lib/api/readable.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const assert = require('assert')
66
const { Readable } = require('stream')
77
const { RequestAbortedError, NotSupportedError } = require('../core/errors')
88
const util = require('../core/util')
9-
const { ReadableStreamFrom } = require('../fetch/util')
9+
const { ReadableStreamFrom, toUSVString } = require('../fetch/util')
1010

1111
let Blob
1212

@@ -98,27 +98,27 @@ module.exports = class BodyReadable extends Readable {
9898
}
9999

100100
// https://fetch.spec.whatwg.org/#dom-body-text
101-
text () {
102-
return consume(this, 'text')
101+
async text () {
102+
return toUSVString(await consume(this, 'text'))
103103
}
104104

105105
// https://fetch.spec.whatwg.org/#dom-body-json
106-
json () {
106+
async json () {
107107
return consume(this, 'json')
108108
}
109109

110110
// https://fetch.spec.whatwg.org/#dom-body-blob
111-
blob () {
111+
async blob () {
112112
return consume(this, 'blob')
113113
}
114114

115115
// https://fetch.spec.whatwg.org/#dom-body-arraybuffer
116-
arrayBuffer () {
116+
async arrayBuffer () {
117117
return consume(this, 'arrayBuffer')
118118
}
119119

120120
// https://fetch.spec.whatwg.org/#dom-body-formdata
121-
formData () {
121+
async formData () {
122122
// TODO: Implement.
123123
throw new NotSupportedError()
124124
}

lib/fetch/body.js

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict'
22

33
const util = require('../core/util')
4-
const { ReadableStreamFrom } = require('./util')
4+
const { ReadableStreamFrom, toUSVString } = require('./util')
55
const { FormData } = require('./formdata')
66
const { kState } = require('./symbols')
77
const { Blob } = require('buffer')
@@ -75,8 +75,9 @@ function extractBody (object, keepalive = false) {
7575
const prefix = `--${boundary}\r\nContent-Disposition: form-data`
7676

7777
/*! formdata-polyfill. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> */
78-
const escape = str => str.replace(/\n/g, '%0A').replace(/\r/g, '%0D').replace(/"/g, '%22')
79-
const normalizeLinefeeds = value => value.replace(/\r?\n|\r/g, '\r\n')
78+
const escape = (str) =>
79+
str.replace(/\n/g, '%0A').replace(/\r/g, '%0D').replace(/"/g, '%22')
80+
const normalizeLinefeeds = (value) => value.replace(/\r?\n|\r/g, '\r\n')
8081

8182
// Set action to this step: run the multipart/form-data
8283
// encoding algorithm, with object’s entry list and UTF-8.
@@ -94,7 +95,8 @@ function extractBody (object, keepalive = false) {
9495
yield enc.encode(
9596
prefix +
9697
`; name="${escape(normalizeLinefeeds(name))}"` +
97-
(value.filename ? `; filename="${escape(value.filename)}"` : '') + '\r\n' +
98+
(value.filename ? `; filename="${escape(value.filename)}"` : '') +
99+
'\r\n' +
98100
`Content-Type: ${
99101
value.type || 'application/octet-stream'
100102
}\r\n\r\n`
@@ -149,14 +151,13 @@ function extractBody (object, keepalive = false) {
149151
)
150152
}
151153

152-
stream = object instanceof ReadableStream
153-
? object
154-
: ReadableStreamFrom(object)
154+
stream =
155+
object instanceof ReadableStream ? object : ReadableStreamFrom(object)
155156
} else {
156157
// TODO: byte sequence?
157158
// TODO: scalar value string?
158159
// TODO: else?
159-
source = String(object)
160+
source = toUSVString(object)
160161
contentType = 'text/plain;charset=UTF-8'
161162
}
162163

@@ -293,7 +294,7 @@ const methods = {
293294

294295
async text () {
295296
const blob = await this.blob()
296-
return await blob.text()
297+
return toUSVString(await blob.text())
297298
},
298299

299300
async json () {

lib/fetch/formdata.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
const { Blob } = require('buffer')
44
const { kState } = require('./symbols')
55
const { File } = require('./file')
6-
const { HTMLFormElement } = require('./util')
6+
const { HTMLFormElement, toUSVString } = require('./util')
77

88
class FormData {
99
constructor (...args) {
@@ -30,11 +30,11 @@ class FormData {
3030
"Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'"
3131
)
3232
}
33-
const name = String(args[0])
34-
const filename = args.length === 3 ? String(args[2]) : undefined
33+
const name = toUSVString(args[0])
34+
const filename = args.length === 3 ? toUSVString(args[2]) : undefined
3535

3636
// 1. Let value be value if given; otherwise blobValue.
37-
const value = args[1] instanceof Blob ? args[1] : String(args[1])
37+
const value = args[1] instanceof Blob ? args[1] : toUSVString(args[1])
3838

3939
// 2. Let entry be the result of creating an entry with
4040
// name, value, and filename if given.
@@ -53,7 +53,7 @@ class FormData {
5353
`Failed to execute 'delete' on 'FormData': 1 arguments required, but only ${args.length} present.`
5454
)
5555
}
56-
const name = String(args[0])
56+
const name = toUSVString(args[0])
5757

5858
// The delete(name) method steps are to remove all entries whose name
5959
// is name from this’s entry list.
@@ -76,7 +76,7 @@ class FormData {
7676
`Failed to execute 'get' on 'FormData': 1 arguments required, but only ${args.length} present.`
7777
)
7878
}
79-
const name = String(args[0])
79+
const name = toUSVString(args[0])
8080

8181
// 1. If there is no entry whose name is name in this’s entry list,
8282
// then return null.
@@ -99,7 +99,7 @@ class FormData {
9999
`Failed to execute 'getAll' on 'FormData': 1 arguments required, but only ${args.length} present.`
100100
)
101101
}
102-
const name = String(args[0])
102+
const name = toUSVString(args[0])
103103

104104
// 1. If there is no entry whose name is name in this’s entry list,
105105
// then return the empty list.
@@ -119,7 +119,7 @@ class FormData {
119119
`Failed to execute 'has' on 'FormData': 1 arguments required, but only ${args.length} present.`
120120
)
121121
}
122-
const name = String(args[0])
122+
const name = toUSVString(args[0])
123123

124124
// The has(name) method steps are to return true if there is an entry
125125
// whose name is name in this’s entry list; otherwise false.
@@ -140,14 +140,14 @@ class FormData {
140140
"Failed to execute 'set' on 'FormData': parameter 2 is not of type 'Blob'"
141141
)
142142
}
143-
const name = String(args[0])
144-
const filename = args.length === 3 ? String(args[2]) : undefined
143+
const name = toUSVString(args[0])
144+
const filename = args.length === 3 ? toUSVString(args[2]) : undefined
145145

146146
// The set(name, value) and set(name, blobValue, filename) method steps
147147
// are:
148148

149149
// 1. Let value be value if given; otherwise blobValue.
150-
const value = args[1] instanceof Blob ? args[1] : String(args[1])
150+
const value = args[1] instanceof Blob ? args[1] : toUSVString(args[1])
151151

152152
// 2. Let entry be the result of creating an entry with name, value, and
153153
// filename if given.

lib/fetch/request.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55
const { extractBody, mixinBody, cloneBody } = require('./body')
66
const { Headers, fill: fillHeaders, HeadersList } = require('./headers')
77
const util = require('../core/util')
8-
const { isValidHTTPToken, EnvironmentSettingsObject } = require('./util')
8+
const {
9+
isValidHTTPToken,
10+
EnvironmentSettingsObject,
11+
toUSVString
12+
} = require('./util')
913
const {
1014
forbiddenMethods,
1115
corsSafeListedMethods,
@@ -46,7 +50,7 @@ class Request {
4650
"Failed to construct 'Request': cannot convert to dictionary."
4751
)
4852
}
49-
const input = args[0] instanceof Request ? args[0] : String(args[0])
53+
const input = args[0] instanceof Request ? args[0] : toUSVString(args[0])
5054
const init = args.length >= 1 ? args[1] ?? {} : {}
5155

5256
// TODO

lib/fetch/response.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const { Headers, HeadersList, fill } = require('./headers')
44
const { extractBody, cloneBody, mixinBody } = require('./body')
55
const util = require('../core/util')
66
const { kEnumerableProperty } = util
7-
const { responseURL, isValidReasonPhrase } = require('./util')
7+
const { responseURL, isValidReasonPhrase, toUSVString } = require('./util')
88
const {
99
redirectStatus,
1010
nullBodyStatus,
@@ -44,7 +44,7 @@ class Response {
4444
}
4545

4646
const status = args.length >= 2 ? args[1] : 302
47-
const url = String(args[0])
47+
const url = toUSVString(args[0])
4848

4949
// 1. Let parsedURL be the result of parsing url with current settings
5050
// object’s API base URL.

lib/fetch/util.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
const { redirectStatus } = require('./constants')
44
const { performance } = require('perf_hooks')
5+
const nodeUtil = require('util')
56

67
let ReadableStream
78

@@ -290,6 +291,7 @@ module.exports = {
290291
ServiceWorkerGlobalScope,
291292
Window,
292293
EnvironmentSettingsObject,
294+
toUSVString: nodeUtil.toUSVString || ((val) => `${val}`),
293295
tryUpgradeRequestToAPotentiallyTrustworthyURL,
294296
coarsenedSharedCurrentTime,
295297
matchRequestIntegrity,

0 commit comments

Comments
 (0)