Skip to content

Commit 0d6ecc5

Browse files
KhafraDevtsctx
andauthored
add bodymixin.textStream() (#5416)
* add bodymixin.textStream() * types * Update types/fetch.d.ts Co-authored-by: tsctx <[email protected]> * Update test/types/fetch.test-d.ts Co-authored-by: tsctx <[email protected]> --------- Co-authored-by: tsctx <[email protected]>
1 parent 42d4955 commit 0d6ecc5

5 files changed

Lines changed: 107 additions & 1 deletion

File tree

lib/web/fetch/body.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,49 @@ function bodyMixinMethods (instance, getInternalState) {
392392
return consumeBody(this, (bytes) => {
393393
return new Uint8Array(bytes)
394394
}, instance, getInternalState)
395+
},
396+
397+
textStream () {
398+
const this_ = getInternalState(this)
399+
400+
// 1. If this is unusable, then throw a TypeError.
401+
if (bodyUnusable(this_)) {
402+
throw new TypeError('Body is unusable: Body has already been read')
403+
}
404+
405+
// 2. If this’s body is null:
406+
if (this_.body == null) {
407+
// 2.1. Let emptyStream be a new ReadableStream in this’s relevant realm.
408+
// 2.2. Set up emptyStream.
409+
/** @type {ReadableStreamDefaultController<any>} */
410+
let controller
411+
const emptyStream = new ReadableStream({
412+
start: (c) => {
413+
controller = c
414+
},
415+
pull: () => Promise.resolve(),
416+
cancel: () => Promise.resolve()
417+
}, {
418+
size: () => 1
419+
})
420+
421+
// 2.3. Close emptyStream.
422+
controller.close()
423+
424+
// 2.4. Return emptyStream.
425+
return emptyStream
426+
}
427+
428+
// 3. Let stream be this’s body’s stream.
429+
/** @type {ReadableStream} */
430+
const stream = this_.body.stream
431+
432+
// 4. Let decoder be a new TextDecoderStream object in this’s relevant realm.
433+
// 5. Set up decoder with UTF-8.
434+
const decoder = new TextDecoderStream('UTF-8')
435+
436+
// 6. Return the result of stream, piped through decoder.
437+
return stream.pipeThrough(decoder)
395438
}
396439
}
397440

test/types/fetch.test-d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ expectType<Promise<FormData>>(response.formData())
177177
expectType<Promise<Uint8Array>>(response.bytes())
178178
expectType<Promise<unknown>>(response.json())
179179
expectType<Promise<string>>(response.text())
180+
expectType<ReadableStream<string>>(response.textStream())
180181
expectType<Response>(response.clone())
181182

182183
expectType<Request>(new Request('https://example.com', { body: 'Hello, world', duplex: 'half' }))

test/web-platform-tests/expectation.json

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6762,6 +6762,67 @@
67626762
"success": true
67636763
}
67646764
]
6765+
},
6766+
"textstream.any.html": {
6767+
"success": true,
6768+
"cases": [
6769+
{
6770+
"name": "textStream method existence",
6771+
"success": true
6772+
},
6773+
{
6774+
"name": "Response.textStream() on consumed body throws TypeError",
6775+
"success": true
6776+
},
6777+
{
6778+
"name": "Request.textStream() on consumed body throws TypeError",
6779+
"success": true
6780+
},
6781+
{
6782+
"name": "Response.textStream() on locked body throws TypeError",
6783+
"success": true
6784+
},
6785+
{
6786+
"name": "Request.textStream() on locked body throws TypeError",
6787+
"success": true
6788+
},
6789+
{
6790+
"name": "Response.textStream() basic functionality",
6791+
"success": true
6792+
},
6793+
{
6794+
"name": "Request.textStream() basic functionality",
6795+
"success": true
6796+
},
6797+
{
6798+
"name": "textStream() handles chunked byte stream input",
6799+
"success": true
6800+
},
6801+
{
6802+
"name": "Response.textStream() with null body",
6803+
"success": true
6804+
},
6805+
{
6806+
"name": "Request.textStream() with null body",
6807+
"success": true
6808+
},
6809+
{
6810+
"name": "Response.textStream() with empty body",
6811+
"success": true
6812+
},
6813+
{
6814+
"name": "Response.textStream() ignores Content-Type charset (UTF-16LE)",
6815+
"success": true
6816+
},
6817+
{
6818+
"name": "Request.textStream() ignores Content-Type charset (UTF-16LE)",
6819+
"success": true
6820+
},
6821+
{
6822+
"name": "Response.textStream() ignores invalid Content-Type charset (invalid-charset)",
6823+
"success": true
6824+
}
6825+
]
67656826
}
67666827
},
67676828
"cors": {

test/web-platform-tests/wpt

Submodule wpt updated 70053 files

types/fetch.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export class BodyMixin {
5757
readonly formData: () => Promise<FormData>
5858
readonly json: () => Promise<unknown>
5959
readonly text: () => Promise<string>
60+
readonly textStream: () => ReadableStream<string>
6061
}
6162

6263
export interface SpecIterator<T, TReturn = any, TNext = undefined> {

0 commit comments

Comments
 (0)