| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 7625dc4 commit 4a3ecbf
15 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -488,7 +488,7 @@ added: v16.5.0 | |||
| 488 | 488 | --> | |
| 489 | 489 | ||
| 490 | 490 | * Returns: A promise fulfilled with an object: | |
| 491 | - * `value` {ArrayBuffer} | ||
| 491 | + * `value` {any} | ||
| 492 | 492 | * `done` {boolean} | |
| 493 | 493 | ||
| 494 | 494 | Requests the next chunk of data from the underlying {ReadableStream} | |
@@ -613,15 +613,24 @@ added: v16.5.0 | |||
| 613 | 613 | {ReadableStream} is closed or rejected if the stream errors or the reader's | |
| 614 | 614 | lock is released before the stream finishes closing. | |
| 615 | 615 | ||
| 616 | - #### `readableStreamBYOBReader.read(view)` | ||
| 616 | + #### `readableStreamBYOBReader.read(view[, options])` | ||
| 617 | 617 | ||
| 618 | 618 | <!-- YAML | |
| 619 | 619 | added: v16.5.0 | |
| 620 | + changes: | ||
| 621 | + - version: REPLACEME | ||
| 622 | + pr-url: https://github.com/nodejs/node/pull/54044 | ||
| 623 | + description: Added `min` option. | ||
| 620 | 624 | --> | |
| 621 | 625 | ||
| 622 | 626 | * `view` {Buffer|TypedArray|DataView} | |
| 627 | + * `options` {Object} | ||
| 628 | + * `min` {number} When set, the returned promise will only be | ||
| 629 | + fulfilled as soon as `min` number of elements are available. | ||
| 630 | + When not set, the promise fulfills when at least one element | ||
| 631 | + is available. | ||
| 623 | 632 | * Returns: A promise fulfilled with an object: | |
| 624 | - * `value` {ArrayBuffer} | ||
| 633 | + * `value` {TypedArray|DataView} | ||
| 625 | 634 | * `done` {boolean} | |
| 626 | 635 | ||
| 627 | 636 | Requests the next chunk of data from the underlying {ReadableStream} | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -47,9 +47,7 @@ const { | |||
| 47 | 47 | const { | |
| 48 | 48 | validateString, | |
| 49 | 49 | validateObject, | |
| 50 | - kValidateObjectAllowNullable, | ||
| 51 | - kValidateObjectAllowArray, | ||
| 52 | - kValidateObjectAllowFunction, | ||
| 50 | + kValidateObjectAllowObjectsAndNull, | ||
| 53 | 51 | } = require('internal/validators'); | |
| 54 | 52 | const binding = internalBinding('encoding_binding'); | |
| 55 | 53 | const { | |
@@ -393,10 +391,6 @@ const TextDecoder = | |||
| 393 | 391 | makeTextDecoderICU() : | |
| 394 | 392 | makeTextDecoderJS(); | |
| 395 | 393 | ||
| 396 | - const kValidateObjectAllowObjectsAndNull = kValidateObjectAllowNullable | | ||
| 397 | - kValidateObjectAllowArray | | ||
| 398 | - kValidateObjectAllowFunction; | ||
| 399 | - | ||
| 400 | 394 | function makeTextDecoderICU() { | |
| 401 | 395 | const { | |
| 402 | 396 | decode: _decode, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -222,6 +222,11 @@ const kValidateObjectNone = 0; | |||
| 222 | 222 | const kValidateObjectAllowNullable = 1 << 0; | |
| 223 | 223 | const kValidateObjectAllowArray = 1 << 1; | |
| 224 | 224 | const kValidateObjectAllowFunction = 1 << 2; | |
| 225 | + const kValidateObjectAllowObjects = kValidateObjectAllowArray | | ||
| 226 | + kValidateObjectAllowFunction; | ||
| 227 | + const kValidateObjectAllowObjectsAndNull = kValidateObjectAllowNullable | | ||
| 228 | + kValidateObjectAllowArray | | ||
| 229 | + kValidateObjectAllowFunction; | ||
| 225 | 230 | ||
| 226 | 231 | /** | |
| 227 | 232 | * @callback validateObject | |
@@ -583,6 +588,8 @@ module.exports = { | |||
| 583 | 588 | kValidateObjectAllowNullable, | |
| 584 | 589 | kValidateObjectAllowArray, | |
| 585 | 590 | kValidateObjectAllowFunction, | |
| 591 | + kValidateObjectAllowObjects, | ||
| 592 | + kValidateObjectAllowObjectsAndNull, | ||
| 586 | 593 | validateOneOf, | |
| 587 | 594 | validatePlainFunction, | |
| 588 | 595 | validatePort, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -23,6 +23,7 @@ const { | |||
| 23 | 23 | SymbolAsyncIterator, | |
| 24 | 24 | SymbolDispose, | |
| 25 | 25 | SymbolToStringTag, | |
| 26 | + TypedArrayPrototypeGetLength, | ||
| 26 | 27 | Uint8Array, | |
| 27 | 28 | } = primordials; | |
| 28 | 29 | ||
@@ -34,6 +35,7 @@ const { | |||
| 34 | 35 | ERR_INVALID_ARG_TYPE, | |
| 35 | 36 | ERR_INVALID_STATE, | |
| 36 | 37 | ERR_INVALID_THIS, | |
| 38 | + ERR_OUT_OF_RANGE, | ||
| 37 | 39 | }, | |
| 38 | 40 | } = require('internal/errors'); | |
| 39 | 41 | ||
@@ -59,8 +61,8 @@ const { | |||
| 59 | 61 | validateAbortSignal, | |
| 60 | 62 | validateBuffer, | |
| 61 | 63 | validateObject, | |
| 62 | - kValidateObjectAllowNullable, | ||
| 63 | - kValidateObjectAllowFunction, | ||
| 64 | + kValidateObjectAllowObjects, | ||
| 65 | + kValidateObjectAllowObjectsAndNull, | ||
| 64 | 66 | } = require('internal/validators'); | |
| 65 | 67 | ||
| 66 | 68 | const { | |
@@ -247,9 +249,9 @@ class ReadableStream { | |||
| 247 | 249 | * @param {UnderlyingSource} [source] | |
| 248 | 250 | * @param {QueuingStrategy} [strategy] | |
| 249 | 251 | */ | |
| 250 | - constructor(source = {}, strategy = kEmptyObject) { | ||
| 251 | - if (source === null) | ||
| 252 | - throw new ERR_INVALID_ARG_VALUE('source', 'Object', source); | ||
| 252 | + constructor(source = kEmptyObject, strategy = kEmptyObject) { | ||
| 253 | + validateObject(source, 'source', kValidateObjectAllowObjects); | ||
| 254 | + validateObject(strategy, 'strategy', kValidateObjectAllowObjectsAndNull); | ||
| 253 | 255 | this[kState] = createReadableStreamState(); | |
| 254 | 256 | ||
| 255 | 257 | this[kIsClosedPromise] = createDeferredPromise(); | |
@@ -335,7 +337,7 @@ class ReadableStream { | |||
| 335 | 337 | getReader(options = kEmptyObject) { | |
| 336 | 338 | if (!isReadableStream(this)) | |
| 337 | 339 | throw new ERR_INVALID_THIS('ReadableStream'); | |
| 338 | - validateObject(options, 'options', kValidateObjectAllowNullable | kValidateObjectAllowFunction); | ||
| 340 | + validateObject(options, 'options', kValidateObjectAllowObjectsAndNull); | ||
| 339 | 341 | const mode = options?.mode; | |
| 340 | 342 | ||
| 341 | 343 | if (mode === undefined) | |
@@ -373,6 +375,7 @@ class ReadableStream { | |||
| 373 | 375 | ||
| 374 | 376 | // The web platform tests require that these be handled one at a | |
| 375 | 377 | // time and in a specific order. options can be null or undefined. | |
| 378 | + validateObject(options, 'options', kValidateObjectAllowObjectsAndNull); | ||
| 376 | 379 | const preventAbort = options?.preventAbort; | |
| 377 | 380 | const preventCancel = options?.preventCancel; | |
| 378 | 381 | const preventClose = options?.preventClose; | |
@@ -415,6 +418,7 @@ class ReadableStream { | |||
| 415 | 418 | destination); | |
| 416 | 419 | } | |
| 417 | 420 | ||
| 421 | + validateObject(options, 'options', kValidateObjectAllowObjectsAndNull); | ||
| 418 | 422 | const preventAbort = options?.preventAbort; | |
| 419 | 423 | const preventCancel = options?.preventCancel; | |
| 420 | 424 | const preventClose = options?.preventClose; | |
@@ -459,10 +463,8 @@ class ReadableStream { | |||
| 459 | 463 | values(options = kEmptyObject) { | |
| 460 | 464 | if (!isReadableStream(this)) | |
| 461 | 465 | throw new ERR_INVALID_THIS('ReadableStream'); | |
| 462 | - validateObject(options, 'options'); | ||
| 463 | - const { | ||
| 464 | - preventCancel = false, | ||
| 465 | - } = options; | ||
| 466 | + validateObject(options, 'options', kValidateObjectAllowObjectsAndNull); | ||
| 467 | + const preventCancel = !!(options?.preventCancel); | ||
| 466 | 468 | ||
| 467 | 469 | // eslint-disable-next-line no-use-before-define | |
| 468 | 470 | const reader = new ReadableStreamDefaultReader(this); | |
@@ -926,47 +928,62 @@ class ReadableStreamBYOBReader { | |||
| 926 | 928 | ||
| 927 | 929 | /** | |
| 928 | 930 | * @param {ArrayBufferView} view | |
| 931 | + * @param {{ | ||
| 932 | + * min? : number | ||
| 933 | + * }} [options] | ||
| 929 | 934 | * @returns {Promise<{ | |
| 930 | - * view : ArrayBufferView, | ||
| 935 | + * value : ArrayBufferView, | ||
| 931 | 936 | * done : boolean, | |
| 932 | 937 | * }>} | |
| 933 | 938 | */ | |
| 934 | - read(view) { | ||
| 939 | + async read(view, options = kEmptyObject) { | ||
| 935 | 940 | if (!isReadableStreamBYOBReader(this)) | |
| 936 | - return PromiseReject(new ERR_INVALID_THIS('ReadableStreamBYOBReader')); | ||
| 941 | + throw new ERR_INVALID_THIS('ReadableStreamBYOBReader'); | ||
| 937 | 942 | if (!isArrayBufferView(view)) { | |
| 938 | - return PromiseReject( | ||
| 939 | - new ERR_INVALID_ARG_TYPE( | ||
| 940 | - 'view', | ||
| 941 | - [ | ||
| 942 | - 'Buffer', | ||
| 943 | - 'TypedArray', | ||
| 944 | - 'DataView', | ||
| 945 | - ], | ||
| 946 | - view)); | ||
| 943 | + throw new ERR_INVALID_ARG_TYPE( | ||
| 944 | + 'view', | ||
| 945 | + [ | ||
| 946 | + 'Buffer', | ||
| 947 | + 'TypedArray', | ||
| 948 | + 'DataView', | ||
| 949 | + ], | ||
| 950 | + view, | ||
| 951 | + ); | ||
| 947 | 952 | } | |
| 953 | + validateObject(options, 'options', kValidateObjectAllowObjectsAndNull); | ||
| 948 | 954 | ||
| 949 | 955 | const viewByteLength = ArrayBufferViewGetByteLength(view); | |
| 950 | 956 | const viewBuffer = ArrayBufferViewGetBuffer(view); | |
| 951 | 957 | const viewBufferByteLength = ArrayBufferPrototypeGetByteLength(viewBuffer); | |
| 952 | 958 | ||
| 953 | 959 | if (viewByteLength === 0 || viewBufferByteLength === 0) { | |
| 954 | - return PromiseReject( | ||
| 955 | - new ERR_INVALID_STATE.TypeError( | ||
| 956 | - 'View or Viewed ArrayBuffer is zero-length or detached', | ||
| 957 | - ), | ||
| 958 | - ); | ||
| 960 | + throw new ERR_INVALID_STATE.TypeError( | ||
| 961 | + 'View or Viewed ArrayBuffer is zero-length or detached'); | ||
| 959 | 962 | } | |
| 960 | 963 | ||
| 961 | 964 | // Supposed to assert here that the view's buffer is not | |
| 962 | 965 | // detached, but there's no API available to use to check that. | |
| 966 | + | ||
| 967 | + const min = options?.min ?? 1; | ||
| 968 | + if (typeof min !== 'number') | ||
| 969 | + throw new ERR_INVALID_ARG_TYPE('options.min', 'number', min); | ||
| 970 | + if (!NumberIsInteger(min)) | ||
| 971 | + throw new ERR_INVALID_ARG_VALUE('options.min', min, 'must be an integer'); | ||
| 972 | + if (min <= 0) | ||
| 973 | + throw new ERR_INVALID_ARG_VALUE('options.min', min, 'must be greater than 0'); | ||
| 974 | + if (!isDataView(view)) { | ||
| 975 | + if (min > TypedArrayPrototypeGetLength(view)) { | ||
| 976 | + throw new ERR_OUT_OF_RANGE('options.min', '<= view.length', min); | ||
| 977 | + } | ||
| 978 | + } else if (min > viewByteLength) { | ||
| 979 | + throw new ERR_OUT_OF_RANGE('options.min', '<= view.byteLength', min); | ||
| 980 | + } | ||
| 981 | + | ||
| 963 | 982 | if (this[kState].stream === undefined) { | |
| 964 | - return PromiseReject( | ||
| 965 | - new ERR_INVALID_STATE.TypeError( | ||
| 966 | - 'The reader is not attached to a stream')); | ||
| 983 | + throw new ERR_INVALID_STATE.TypeError('The reader is not attached to a stream'); | ||
| 967 | 984 | } | |
| 968 | 985 | const readIntoRequest = new ReadIntoRequest(); | |
| 969 | - readableStreamBYOBReaderRead(this, view, readIntoRequest); | ||
| 986 | + readableStreamBYOBReaderRead(this, view, min, readIntoRequest); | ||
| 970 | 987 | return readIntoRequest.promise; | |
| 971 | 988 | } | |
| 972 | 989 | ||
@@ -1880,7 +1897,7 @@ function readableByteStreamTee(stream) { | |||
| 1880 | 1897 | reading = false; | |
| 1881 | 1898 | }, | |
| 1882 | 1899 | }; | |
| 1883 | - readableStreamBYOBReaderRead(reader, view, readIntoRequest); | ||
| 1900 | + readableStreamBYOBReaderRead(reader, view, 1, readIntoRequest); | ||
| 1884 | 1901 | } | |
| 1885 | 1902 | ||
| 1886 | 1903 | function pull1Algorithm() { | |
@@ -2207,7 +2224,7 @@ function readableStreamReaderGenericRelease(reader) { | |||
| 2207 | 2224 | reader[kState].stream = undefined; | |
| 2208 | 2225 | } | |
| 2209 | 2226 | ||
| 2210 | - function readableStreamBYOBReaderRead(reader, view, readIntoRequest) { | ||
| 2227 | + function readableStreamBYOBReaderRead(reader, view, min, readIntoRequest) { | ||
| 2211 | 2228 | const { | |
| 2212 | 2229 | stream, | |
| 2213 | 2230 | } = reader[kState]; | |
@@ -2220,6 +2237,7 @@ function readableStreamBYOBReaderRead(reader, view, readIntoRequest) { | |||
| 2220 | 2237 | readableByteStreamControllerPullInto( | |
| 2221 | 2238 | stream[kState].controller, | |
| 2222 | 2239 | view, | |
| 2240 | + min, | ||
| 2223 | 2241 | readIntoRequest); | |
| 2224 | 2242 | } | |
| 2225 | 2243 | ||
@@ -2492,7 +2510,7 @@ function readableByteStreamControllerClose(controller) { | |||
| 2492 | 2510 | ||
| 2493 | 2511 | if (pendingPullIntos.length) { | |
| 2494 | 2512 | const firstPendingPullInto = pendingPullIntos[0]; | |
| 2495 | - if (firstPendingPullInto.bytesFilled > 0) { | ||
| 2513 | + if (firstPendingPullInto.bytesFilled % firstPendingPullInto.elementSize !== 0) { | ||
| 2496 | 2514 | const error = new ERR_INVALID_STATE.TypeError('Partial read'); | |
| 2497 | 2515 | readableByteStreamControllerError(controller, error); | |
| 2498 | 2516 | throw error; | |
@@ -2509,7 +2527,7 @@ function readableByteStreamControllerCommitPullIntoDescriptor(stream, desc) { | |||
| 2509 | 2527 | ||
| 2510 | 2528 | let done = false; | |
| 2511 | 2529 | if (stream[kState].state === 'closed') { | |
| 2512 | - desc.bytesFilled = 0; | ||
| 2530 | + assert(desc.bytesFilled % desc.elementSize === 0); | ||
| 2513 | 2531 | done = true; | |
| 2514 | 2532 | } | |
| 2515 | 2533 | ||
@@ -2598,6 +2616,7 @@ function readableByteStreamControllerHandleQueueDrain(controller) { | |||
| 2598 | 2616 | function readableByteStreamControllerPullInto( | |
| 2599 | 2617 | controller, | |
| 2600 | 2618 | view, | |
| 2619 | + min, | ||
| 2601 | 2620 | readIntoRequest) { | |
| 2602 | 2621 | const { | |
| 2603 | 2622 | closeRequested, | |
@@ -2610,6 +2629,11 @@ function readableByteStreamControllerPullInto( | |||
| 2610 | 2629 | elementSize = view.constructor.BYTES_PER_ELEMENT; | |
| 2611 | 2630 | ctor = view.constructor; | |
| 2612 | 2631 | } | |
| 2632 | + | ||
| 2633 | + const minimumFill = min * elementSize; | ||
| 2634 | + assert(minimumFill >= elementSize && minimumFill <= view.byteLength); | ||
| 2635 | + assert(minimumFill % elementSize === 0); | ||
| 2636 | + | ||
| 2613 | 2637 | const buffer = ArrayBufferViewGetBuffer(view); | |
| 2614 | 2638 | const byteOffset = ArrayBufferViewGetByteOffset(view); | |
| 2615 | 2639 | const byteLength = ArrayBufferViewGetByteLength(view); | |
@@ -2628,6 +2652,7 @@ function readableByteStreamControllerPullInto( | |||
| 2628 | 2652 | byteOffset, | |
| 2629 | 2653 | byteLength, | |
| 2630 | 2654 | bytesFilled: 0, | |
| 2655 | + minimumFill, | ||
| 2631 | 2656 | elementSize, | |
| 2632 | 2657 | ctor, | |
| 2633 | 2658 | type: 'byob', | |
@@ -2715,7 +2740,7 @@ function readableByteStreamControllerRespond(controller, bytesWritten) { | |||
| 2715 | 2740 | } | |
| 2716 | 2741 | ||
| 2717 | 2742 | function readableByteStreamControllerRespondInClosedState(controller, desc) { | |
| 2718 | - assert(!desc.bytesFilled); | ||
| 2743 | + assert(desc.bytesFilled % desc.elementSize === 0); | ||
| 2719 | 2744 | if (desc.type === 'none') { | |
| 2720 | 2745 | readableByteStreamControllerShiftPendingPullInto(controller); | |
| 2721 | 2746 | } | |
@@ -2892,17 +2917,18 @@ function readableByteStreamControllerFillPullIntoDescriptorFromQueue( | |||
| 2892 | 2917 | byteLength, | |
| 2893 | 2918 | byteOffset, | |
| 2894 | 2919 | bytesFilled, | |
| 2920 | + minimumFill, | ||
| 2895 | 2921 | elementSize, | |
| 2896 | 2922 | } = desc; | |
| 2897 | - const currentAlignedBytes = bytesFilled - (bytesFilled % elementSize); | ||
| 2898 | 2923 | const maxBytesToCopy = MathMin( | |
| 2899 | 2924 | controller[kState].queueTotalSize, | |
| 2900 | 2925 | byteLength - bytesFilled); | |
| 2901 | 2926 | const maxBytesFilled = bytesFilled + maxBytesToCopy; | |
| 2902 | 2927 | const maxAlignedBytes = maxBytesFilled - (maxBytesFilled % elementSize); | |
| 2903 | 2928 | let totalBytesToCopyRemaining = maxBytesToCopy; | |
| 2904 | 2929 | let ready = false; | |
| 2905 | - if (maxAlignedBytes > currentAlignedBytes) { | ||
| 2930 | + assert(bytesFilled < minimumFill); | ||
| 2931 | + if (maxAlignedBytes >= minimumFill) { | ||
| 2906 | 2932 | totalBytesToCopyRemaining = maxAlignedBytes - bytesFilled; | |
| 2907 | 2933 | ready = true; | |
| 2908 | 2934 | } | |
@@ -2945,7 +2971,7 @@ function readableByteStreamControllerFillPullIntoDescriptorFromQueue( | |||
| 2945 | 2971 | if (!ready) { | |
| 2946 | 2972 | assert(!controller[kState].queueTotalSize); | |
| 2947 | 2973 | assert(desc.bytesFilled > 0); | |
| 2948 | - assert(desc.bytesFilled < elementSize); | ||
| 2974 | + assert(desc.bytesFilled < minimumFill); | ||
| 2949 | 2975 | } | |
| 2950 | 2976 | return ready; | |
| 2951 | 2977 | } | |
@@ -3001,7 +3027,7 @@ function readableByteStreamControllerRespondInReadableState( | |||
| 3001 | 3027 | return; | |
| 3002 | 3028 | } | |
| 3003 | 3029 | ||
| 3004 | - if (desc.bytesFilled < desc.elementSize) | ||
| 3030 | + if (desc.bytesFilled < desc.minimumFill) | ||
| 3005 | 3031 | return; | |
| 3006 | 3032 | ||
| 3007 | 3033 | readableByteStreamControllerShiftPendingPullInto(controller); | |
@@ -3186,6 +3212,7 @@ function readableByteStreamControllerPullSteps(controller, readRequest) { | |||
| 3186 | 3212 | byteOffset: 0, | |
| 3187 | 3213 | byteLength: autoAllocateChunkSize, | |
| 3188 | 3214 | bytesFilled: 0, | |
| 3215 | + minimumFill: 1, | ||
| 3189 | 3216 | elementSize: 1, | |
| 3190 | 3217 | ctor: Uint8Array, | |
| 3191 | 3218 | type: 'default', | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -29,6 +29,12 @@ const { | |||
| 29 | 29 | kEnumerableProperty, | |
| 30 | 30 | } = require('internal/util'); | |
| 31 | 31 | ||
| 32 | + const { | ||
| 33 | + validateObject, | ||
| 34 | + kValidateObjectAllowObjects, | ||
| 35 | + kValidateObjectAllowObjectsAndNull, | ||
| 36 | + } = require('internal/validators'); | ||
| 37 | + | ||
| 32 | 38 | const { | |
| 33 | 39 | kDeserialize, | |
| 34 | 40 | kTransfer, | |
@@ -119,9 +125,12 @@ class TransformStream { | |||
| 119 | 125 | * @param {QueuingStrategy} [readableStrategy] | |
| 120 | 126 | */ | |
| 121 | 127 | constructor( | |
| 122 | - transformer = null, | ||
| 128 | + transformer = kEmptyObject, | ||
| 123 | 129 | writableStrategy = kEmptyObject, | |
| 124 | 130 | readableStrategy = kEmptyObject) { | |
| 131 | + validateObject(transformer, 'transformer', kValidateObjectAllowObjects); | ||
| 132 | + validateObject(writableStrategy, 'writableStrategy', kValidateObjectAllowObjectsAndNull); | ||
| 133 | + validateObject(readableStrategy, 'readableStrategy', kValidateObjectAllowObjectsAndNull); | ||
| 125 | 134 | const readableType = transformer?.readableType; | |
| 126 | 135 | const writableType = transformer?.writableType; | |
| 127 | 136 | const start = transformer?.start; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments