Skip to content

Commit 55f4844

Browse files
KhafraDevrichardlau
authored andcommitted
buffer: implement blob.textStream()
Signed-off-by: Matthew Aitken <maitken033380023@gmail.com> PR-URL: #64036 Refs: w3c/FileAPI@cd1d1da Refs: nodejs/undici@0d6ecc5 Reviewed-By: René <contact.9a5d6388@renegade334.me.uk> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Mattias Buelens <mattias@buelens.com>
1 parent eda91b6 commit 55f4844

3 files changed

Lines changed: 54 additions & 1 deletion

File tree

‎doc/api/buffer.md‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,18 @@ added:
593593
Returns a promise that fulfills with the contents of the `Blob` decoded as a
594594
UTF-8 string.
595595

596+
### `blob.textStream()`
597+
598+
<!-- YAML
599+
added: REPLACEME
600+
-->
601+
602+
* Returns: {ReadableStream}
603+
604+
Returns a new `ReadableStream` that allows the content of the `Blob` to be read
605+
as a stream of UTF-8 decoded strings. It is equivalent to piping
606+
[`blob.stream()`][] through a [`TextDecoderStream`][] set up with UTF-8.
607+
596608
### `blob.type`
597609

598610
<!-- YAML
@@ -5610,10 +5622,12 @@ introducing security vulnerabilities into an application.
56105622
[`String.prototype.indexOf()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf
56115623
[`String.prototype.lastIndexOf()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/lastIndexOf
56125624
[`String.prototype.length`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length
5625+
[`TextDecoderStream`]: webstreams.md#class-textdecoderstream
56135626
[`TypedArray.from()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/from
56145627
[`TypedArray.prototype.set()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set
56155628
[`TypedArray.prototype.slice()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
56165629
[`TypedArray.prototype.subarray()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/subarray
5630+
[`blob.stream()`]: #blobstream
56175631
[`buf.buffer`]: #bufbuffer
56185632
[`buf.compare()`]: #bufcomparetarget-targetstart-targetend-sourcestart-sourceend
56195633
[`buf.entries()`]: #bufentries

‎lib/internal/blob.js‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ const kNotCloneable = Symbol('kNotCloneable');
8585
constdisallowedTypeCharacters=/[^\u{0020}-\u{007E}]/u;
8686

8787
letReadableStream;
88+
letTextDecoderStream;
8889

8990
constenc=newTextEncoder();
9091
letdec;
@@ -100,6 +101,13 @@ function lazyReadableStream(options) {
100101
returnnewReadableStream(options);
101102
}
102103

104+
functionlazyTextDecoderStream(){
105+
// eslint-disable-next-line no-global-assign
106+
TextDecoderStream??=
107+
require('internal/webstreams/encoding').TextDecoderStream;
108+
returnnewTextDecoderStream();
109+
}
110+
103111
const{EOL}=require('internal/constants');
104112

105113
functionisBlob(object){
@@ -325,6 +333,17 @@ class Blob {
325333
thrownewERR_INVALID_THIS('Blob');
326334
returncreateBlobReaderStream(this[kHandle].getReader());
327335
}
336+
337+
/**
338+
* @returns {ReadableStream}
339+
*/
340+
textStream(){
341+
if(!isBlob(this))
342+
thrownewERR_INVALID_THIS('Blob');
343+
conststream=createBlobReaderStream(this[kHandle].getReader());
344+
constdecoder=lazyTextDecoderStream();
345+
returnstream.pipeThrough(decoder);
346+
}
328347
}
329348

330349
functionTransferableBlob(handle,length,type=''){
@@ -358,6 +377,7 @@ ObjectDefineProperties(Blob.prototype, {
358377
type: kEnumerableProperty,
359378
slice: kEnumerableProperty,
360379
stream: kEnumerableProperty,
380+
textStream: kEnumerableProperty,
361381
text: kEnumerableProperty,
362382
arrayBuffer: kEnumerableProperty,
363383
bytes: kEnumerableProperty,

‎test/parallel/test-blob.js‎

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
constcommon=require('../common');
55
constassert=require('assert');
6-
const{ Blob }=require('buffer');
6+
const{ Blob, File}=require('buffer');
77
const{ inspect }=require('util');
88
const{EOL}=require('os');
99
const{ kState }=require('internal/webstreams/util');
@@ -524,3 +524,22 @@ assert.throws(() => new Blob({}), {
524524
Blob.prototype.arrayBuffer=arrayBuffer;
525525
}
526526
})().then(common.mustCall());
527+
528+
{
529+
assert.strictEqual(typeofBlob.prototype.textStream,'function');
530+
assert.strictEqual(typeofFile.prototype.textStream,'function');
531+
assert.strictEqual(File.prototype.textStream,Blob.prototype.textStream);
532+
}
533+
534+
(async()=>{
535+
constsmiley=Buffer.from('😀','utf8');
536+
constblob=newBlob(['hello ',smiley.subarray(0,2),smiley.subarray(2)]);
537+
conststream=blob.textStream();
538+
assert.ok(streaminstanceofReadableStream);
539+
letresult='';
540+
forawait(constchunkofstream){
541+
assert.strictEqual(typeofchunk,'string');
542+
result+=chunk;
543+
}
544+
assert.strictEqual(result,'hello 😀');
545+
})().then(common.mustCall());

0 commit comments

Comments
 (0)