@@ -29,10 +29,17 @@ const {
2929const {
3030 codes : {
3131 ERR_INVALID_ARG_TYPE ,
32+ ERR_INVALID_ARG_VALUE ,
3233 ERR_OUT_OF_RANGE ,
3334 } ,
3435} = require ( 'internal/errors' ) ;
3536const { TextDecoder } = require ( 'internal/encoding' ) ;
37+ const {
38+ validateAbortSignal,
39+ validateFunction,
40+ validateInteger,
41+ validateObject,
42+ } = require ( 'internal/validators' ) ;
3643
3744const {
3845 isAsyncIterable,
@@ -189,6 +196,49 @@ function toArrayBuffer(data) {
189196 byteOffset + byteLength ) ;
190197}
191198
199+ // =============================================================================
200+ // Shared option validation
201+ // =============================================================================
202+
203+ function validateConsumerOptions ( options ) {
204+ validateObject ( options , 'options' ) ;
205+ if ( options . signal !== undefined ) {
206+ validateAbortSignal ( options . signal , 'options.signal' ) ;
207+ }
208+ if ( options . limit !== undefined ) {
209+ validateInteger ( options . limit , 'options.limit' , 0 ) ;
210+ }
211+ if ( options . encoding !== undefined ) {
212+ if ( typeof options . encoding !== 'string' ) {
213+ throw new ERR_INVALID_ARG_TYPE ( 'options.encoding' , 'string' ,
214+ options . encoding ) ;
215+ }
216+ try {
217+ new TextDecoder ( options . encoding ) ;
218+ } catch {
219+ throw new ERR_INVALID_ARG_VALUE ( 'options.encoding' , options . encoding ) ;
220+ }
221+ }
222+ }
223+
224+ function validateSyncConsumerOptions ( options ) {
225+ validateObject ( options , 'options' ) ;
226+ if ( options . limit !== undefined ) {
227+ validateInteger ( options . limit , 'options.limit' , 0 ) ;
228+ }
229+ if ( options . encoding !== undefined ) {
230+ if ( typeof options . encoding !== 'string' ) {
231+ throw new ERR_INVALID_ARG_TYPE ( 'options.encoding' , 'string' ,
232+ options . encoding ) ;
233+ }
234+ try {
235+ new TextDecoder ( options . encoding ) ;
236+ } catch {
237+ throw new ERR_INVALID_ARG_VALUE ( 'options.encoding' , options . encoding ) ;
238+ }
239+ }
240+ }
241+
192242// =============================================================================
193243// Sync Consumers
194244// =============================================================================
@@ -199,7 +249,8 @@ function toArrayBuffer(data) {
199249 * @param {{ limit?: number } } [options]
200250 * @returns {Uint8Array }
201251 */
202- function bytesSync ( source , options ) {
252+ function bytesSync ( source , options = { __proto__ : null } ) {
253+ validateSyncConsumerOptions ( options ) ;
203254 return concatBytes ( collectSync ( source , options ?. limit ) ) ;
204255}
205256
@@ -209,9 +260,10 @@ function bytesSync(source, options) {
209260 * @param {{ encoding?: string, limit?: number } } [options]
210261 * @returns {string }
211262 */
212- function textSync ( source , options ) {
213- const data = bytesSync ( source , options ) ;
214- const decoder = new TextDecoder ( options ?. encoding ?? 'utf-8' , {
263+ function textSync ( source , options = { __proto__ : null } ) {
264+ validateSyncConsumerOptions ( options ) ;
265+ const data = concatBytes ( collectSync ( source , options . limit ) ) ;
266+ const decoder = new TextDecoder ( options . encoding ?? 'utf-8' , {
215267 __proto__ : null ,
216268 fatal : true ,
217269 ignoreBOM : true ,
@@ -225,8 +277,9 @@ function textSync(source, options) {
225277 * @param {{ limit?: number } } [options]
226278 * @returns {ArrayBuffer }
227279 */
228- function arrayBufferSync ( source , options ) {
229- return toArrayBuffer ( bytesSync ( source , options ) ) ;
280+ function arrayBufferSync ( source , options = { __proto__ : null } ) {
281+ validateSyncConsumerOptions ( options ) ;
282+ return toArrayBuffer ( concatBytes ( collectSync ( source , options . limit ) ) ) ;
230283}
231284
232285/**
@@ -235,8 +288,9 @@ function arrayBufferSync(source, options) {
235288 * @param {{ limit?: number } } [options]
236289 * @returns {Uint8Array[] }
237290 */
238- function arraySync ( source , options ) {
239- return collectSync ( source , options ?. limit ) ;
291+ function arraySync ( source , options = { __proto__ : null } ) {
292+ validateSyncConsumerOptions ( options ) ;
293+ return collectSync ( source , options . limit ) ;
240294}
241295
242296// =============================================================================
@@ -249,8 +303,9 @@ function arraySync(source, options) {
249303 * @param {{ signal?: AbortSignal, limit?: number } } [options]
250304 * @returns {Promise<Uint8Array> }
251305 */
252- async function bytes ( source , options ) {
253- const chunks = await collectAsync ( source , options ?. signal , options ?. limit ) ;
306+ async function bytes ( source , options = { __proto__ : null } ) {
307+ validateConsumerOptions ( options ) ;
308+ const chunks = await collectAsync ( source , options . signal , options . limit ) ;
254309 return concatBytes ( chunks ) ;
255310}
256311
@@ -260,9 +315,11 @@ async function bytes(source, options) {
260315 * @param {{ encoding?: string, signal?: AbortSignal, limit?: number } } [options]
261316 * @returns {Promise<string> }
262317 */
263- async function text ( source , options ) {
264- const data = await bytes ( source , options ) ;
265- const decoder = new TextDecoder ( options ?. encoding ?? 'utf-8' , {
318+ async function text ( source , options = { __proto__ : null } ) {
319+ validateConsumerOptions ( options ) ;
320+ const chunks = await collectAsync ( source , options . signal , options . limit ) ;
321+ const data = concatBytes ( chunks ) ;
322+ const decoder = new TextDecoder ( options . encoding ?? 'utf-8' , {
266323 __proto__ : null ,
267324 fatal : true ,
268325 ignoreBOM : true ,
@@ -276,8 +333,10 @@ async function text(source, options) {
276333 * @param {{ signal?: AbortSignal, limit?: number } } [options]
277334 * @returns {Promise<ArrayBuffer> }
278335 */
279- async function arrayBuffer ( source , options ) {
280- return toArrayBuffer ( await bytes ( source , options ) ) ;
336+ async function arrayBuffer ( source , options = { __proto__ : null } ) {
337+ validateConsumerOptions ( options ) ;
338+ const chunks = await collectAsync ( source , options . signal , options . limit ) ;
339+ return toArrayBuffer ( concatBytes ( chunks ) ) ;
281340}
282341
283342/**
@@ -286,8 +345,9 @@ async function arrayBuffer(source, options) {
286345 * @param {{ signal?: AbortSignal, limit?: number } } [options]
287346 * @returns {Promise<Uint8Array[]> }
288347 */
289- async function array ( source , options ) {
290- return collectAsync ( source , options ?. signal , options ?. limit ) ;
348+ async function array ( source , options = { __proto__ : null } ) {
349+ validateConsumerOptions ( options ) ;
350+ return collectAsync ( source , options . signal , options . limit ) ;
291351}
292352
293353// =============================================================================
@@ -300,6 +360,7 @@ async function array(source, options) {
300360 * @returns {Function }
301361 */
302362function tap ( callback ) {
363+ validateFunction ( callback , 'callback' ) ;
303364 return async ( chunks , options ) => {
304365 await callback ( chunks , options ) ;
305366 return chunks ;
@@ -312,6 +373,7 @@ function tap(callback) {
312373 * @returns {Function }
313374 */
314375function tapSync ( callback ) {
376+ validateFunction ( callback , 'callback' ) ;
315377 return ( chunks ) => {
316378 callback ( chunks ) ;
317379 return chunks ;
@@ -370,6 +432,10 @@ function merge(...args) {
370432 sources = args ;
371433 }
372434
435+ if ( options ?. signal !== undefined ) {
436+ validateAbortSignal ( options . signal , 'options.signal' ) ;
437+ }
438+
373439 return {
374440 __proto__ : null ,
375441 async * [ SymbolAsyncIterator ] ( ) {
0 commit comments