mirror of
https://github.com/denoland/deno.git
synced 2025-09-26 12:19:12 +00:00
feat(streams): ReadableStream.read min option (#20849)
This commit is contained in:
parent
998d9061ef
commit
6f02fa1abf
4 changed files with 72 additions and 15 deletions
|
@ -79,6 +79,7 @@ const {
|
||||||
TypedArrayPrototypeGetBuffer,
|
TypedArrayPrototypeGetBuffer,
|
||||||
TypedArrayPrototypeGetByteLength,
|
TypedArrayPrototypeGetByteLength,
|
||||||
TypedArrayPrototypeGetByteOffset,
|
TypedArrayPrototypeGetByteOffset,
|
||||||
|
TypedArrayPrototypeGetLength,
|
||||||
TypedArrayPrototypeGetSymbolToStringTag,
|
TypedArrayPrototypeGetSymbolToStringTag,
|
||||||
TypedArrayPrototypeSet,
|
TypedArrayPrototypeSet,
|
||||||
TypedArrayPrototypeSlice,
|
TypedArrayPrototypeSlice,
|
||||||
|
@ -1303,7 +1304,9 @@ function readableByteStreamControllerClose(controller) {
|
||||||
}
|
}
|
||||||
if (controller[_pendingPullIntos].length !== 0) {
|
if (controller[_pendingPullIntos].length !== 0) {
|
||||||
const firstPendingPullInto = controller[_pendingPullIntos][0];
|
const firstPendingPullInto = controller[_pendingPullIntos][0];
|
||||||
if (firstPendingPullInto.bytesFilled > 0) {
|
if (
|
||||||
|
firstPendingPullInto.bytesFilled % firstPendingPullInto.elementSize !== 0
|
||||||
|
) {
|
||||||
const e = new TypeError(
|
const e = new TypeError(
|
||||||
"Insufficient bytes to fill elements in the given buffer",
|
"Insufficient bytes to fill elements in the given buffer",
|
||||||
);
|
);
|
||||||
|
@ -1847,10 +1850,11 @@ function readableStreamDefaultcontrollerShouldCallPull(controller) {
|
||||||
/**
|
/**
|
||||||
* @param {ReadableStreamBYOBReader} reader
|
* @param {ReadableStreamBYOBReader} reader
|
||||||
* @param {ArrayBufferView} view
|
* @param {ArrayBufferView} view
|
||||||
|
* @param {number} min
|
||||||
* @param {ReadIntoRequest} readIntoRequest
|
* @param {ReadIntoRequest} readIntoRequest
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
function readableStreamBYOBReaderRead(reader, view, readIntoRequest) {
|
function readableStreamBYOBReaderRead(reader, view, min, readIntoRequest) {
|
||||||
const stream = reader[_stream];
|
const stream = reader[_stream];
|
||||||
assert(stream);
|
assert(stream);
|
||||||
stream[_disturbed] = true;
|
stream[_disturbed] = true;
|
||||||
|
@ -1860,6 +1864,7 @@ function readableStreamBYOBReaderRead(reader, view, readIntoRequest) {
|
||||||
readableByteStreamControllerPullInto(
|
readableByteStreamControllerPullInto(
|
||||||
stream[_controller],
|
stream[_controller],
|
||||||
view,
|
view,
|
||||||
|
min,
|
||||||
readIntoRequest,
|
readIntoRequest,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1935,12 +1940,14 @@ function readableByteStreamControllerProcessReadRequestsUsingQueue(
|
||||||
/**
|
/**
|
||||||
* @param {ReadableByteStreamController} controller
|
* @param {ReadableByteStreamController} controller
|
||||||
* @param {ArrayBufferView} view
|
* @param {ArrayBufferView} view
|
||||||
|
* @param {number} min
|
||||||
* @param {ReadIntoRequest} readIntoRequest
|
* @param {ReadIntoRequest} readIntoRequest
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
function readableByteStreamControllerPullInto(
|
function readableByteStreamControllerPullInto(
|
||||||
controller,
|
controller,
|
||||||
view,
|
view,
|
||||||
|
min,
|
||||||
readIntoRequest,
|
readIntoRequest,
|
||||||
) {
|
) {
|
||||||
const stream = controller[_stream];
|
const stream = controller[_stream];
|
||||||
|
@ -2010,6 +2017,10 @@ function readableByteStreamControllerPullInto(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const minimumFill = min * elementSize;
|
||||||
|
assert(minimumFill >= 0 && minimumFill <= byteLength);
|
||||||
|
assert(minimumFill % elementSize === 0);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
buffer = transferArrayBuffer(buffer);
|
buffer = transferArrayBuffer(buffer);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -2024,6 +2035,7 @@ function readableByteStreamControllerPullInto(
|
||||||
byteOffset,
|
byteOffset,
|
||||||
byteLength,
|
byteLength,
|
||||||
bytesFilled: 0,
|
bytesFilled: 0,
|
||||||
|
minimumFill,
|
||||||
elementSize,
|
elementSize,
|
||||||
viewConstructor: ctor,
|
viewConstructor: ctor,
|
||||||
readerType: "byob",
|
readerType: "byob",
|
||||||
|
@ -2139,7 +2151,7 @@ function readableByteStreamControllerRespondInReadableState(
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize) {
|
if (pullIntoDescriptor.bytesFilled < pullIntoDescriptor.minimumFill) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
readableByteStreamControllerShiftPendingPullInto(controller);
|
readableByteStreamControllerShiftPendingPullInto(controller);
|
||||||
|
@ -2219,7 +2231,7 @@ function readableByteStreamControllerRespondInClosedState(
|
||||||
controller,
|
controller,
|
||||||
firstDescriptor,
|
firstDescriptor,
|
||||||
) {
|
) {
|
||||||
assert(firstDescriptor.bytesFilled === 0);
|
assert(firstDescriptor.bytesFilled % firstDescriptor.elementSize === 0);
|
||||||
if (firstDescriptor.readerType === "none") {
|
if (firstDescriptor.readerType === "none") {
|
||||||
readableByteStreamControllerShiftPendingPullInto(controller);
|
readableByteStreamControllerShiftPendingPullInto(controller);
|
||||||
}
|
}
|
||||||
|
@ -2249,7 +2261,9 @@ function readableByteStreamControllerCommitPullIntoDescriptor(
|
||||||
assert(pullIntoDescriptor.readerType !== "none");
|
assert(pullIntoDescriptor.readerType !== "none");
|
||||||
let done = false;
|
let done = false;
|
||||||
if (stream[_state] === "closed") {
|
if (stream[_state] === "closed") {
|
||||||
assert(pullIntoDescriptor.bytesFilled === 0);
|
assert(
|
||||||
|
pullIntoDescriptor.bytesFilled % pullIntoDescriptor.elementSize === 0,
|
||||||
|
);
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
const filledView = readableByteStreamControllerConvertPullIntoDescriptor(
|
const filledView = readableByteStreamControllerConvertPullIntoDescriptor(
|
||||||
|
@ -2340,19 +2354,18 @@ function readableByteStreamControllerFillPullIntoDescriptorFromQueue(
|
||||||
controller,
|
controller,
|
||||||
pullIntoDescriptor,
|
pullIntoDescriptor,
|
||||||
) {
|
) {
|
||||||
const elementSize = pullIntoDescriptor.elementSize;
|
|
||||||
const currentAlignedBytes = pullIntoDescriptor.bytesFilled -
|
|
||||||
(pullIntoDescriptor.bytesFilled % elementSize);
|
|
||||||
const maxBytesToCopy = MathMin(
|
const maxBytesToCopy = MathMin(
|
||||||
controller[_queueTotalSize],
|
controller[_queueTotalSize],
|
||||||
// deno-lint-ignore prefer-primordials
|
// deno-lint-ignore prefer-primordials
|
||||||
pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled,
|
pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled,
|
||||||
);
|
);
|
||||||
const maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy;
|
const maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy;
|
||||||
const maxAlignedBytes = maxBytesFilled - (maxBytesFilled % elementSize);
|
|
||||||
let totalBytesToCopyRemaining = maxBytesToCopy;
|
let totalBytesToCopyRemaining = maxBytesToCopy;
|
||||||
let ready = false;
|
let ready = false;
|
||||||
if (maxAlignedBytes > currentAlignedBytes) {
|
assert(pullIntoDescriptor.bytesFilled < pullIntoDescriptor.minimumFill);
|
||||||
|
const maxAlignedBytes = maxBytesFilled -
|
||||||
|
(maxBytesFilled % pullIntoDescriptor.elementSize);
|
||||||
|
if (maxAlignedBytes >= pullIntoDescriptor.minimumFill) {
|
||||||
totalBytesToCopyRemaining = maxAlignedBytes -
|
totalBytesToCopyRemaining = maxAlignedBytes -
|
||||||
pullIntoDescriptor.bytesFilled;
|
pullIntoDescriptor.bytesFilled;
|
||||||
ready = true;
|
ready = true;
|
||||||
|
@ -2402,7 +2415,7 @@ function readableByteStreamControllerFillPullIntoDescriptorFromQueue(
|
||||||
if (!ready) {
|
if (!ready) {
|
||||||
assert(controller[_queueTotalSize] === 0);
|
assert(controller[_queueTotalSize] === 0);
|
||||||
assert(pullIntoDescriptor.bytesFilled > 0);
|
assert(pullIntoDescriptor.bytesFilled > 0);
|
||||||
assert(pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize);
|
assert(pullIntoDescriptor.bytesFilled < pullIntoDescriptor.minimumFill);
|
||||||
}
|
}
|
||||||
return ready;
|
return ready;
|
||||||
}
|
}
|
||||||
|
@ -3375,7 +3388,7 @@ function readableByteStreamTee(stream) {
|
||||||
reading = false;
|
reading = false;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
readableStreamBYOBReaderRead(reader, view, readIntoRequest);
|
readableStreamBYOBReaderRead(reader, view, 1, readIntoRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
function pull1Algorithm() {
|
function pull1Algorithm() {
|
||||||
|
@ -5543,13 +5556,19 @@ class ReadableStreamBYOBReader {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ArrayBufferView} view
|
* @param {ArrayBufferView} view
|
||||||
|
* @param {ReadableStreamBYOBReaderReadOptions} options
|
||||||
* @returns {Promise<ReadableStreamBYOBReadResult>}
|
* @returns {Promise<ReadableStreamBYOBReadResult>}
|
||||||
*/
|
*/
|
||||||
read(view) {
|
read(view, options = {}) {
|
||||||
try {
|
try {
|
||||||
webidl.assertBranded(this, ReadableStreamBYOBReaderPrototype);
|
webidl.assertBranded(this, ReadableStreamBYOBReaderPrototype);
|
||||||
const prefix = "Failed to execute 'read' on 'ReadableStreamBYOBReader'";
|
const prefix = "Failed to execute 'read' on 'ReadableStreamBYOBReader'";
|
||||||
view = webidl.converters.ArrayBufferView(view, prefix, "Argument 1");
|
view = webidl.converters.ArrayBufferView(view, prefix, "Argument 1");
|
||||||
|
options = webidl.converters.ReadableStreamBYOBReaderReadOptions(
|
||||||
|
options,
|
||||||
|
prefix,
|
||||||
|
"Argument 2",
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return PromiseReject(err);
|
return PromiseReject(err);
|
||||||
}
|
}
|
||||||
|
@ -5584,6 +5603,23 @@ class ReadableStreamBYOBReader {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.min === 0) {
|
||||||
|
return PromiseReject(new TypeError("options.min must be non-zero"));
|
||||||
|
}
|
||||||
|
if (TypedArrayPrototypeGetSymbolToStringTag(view) !== undefined) {
|
||||||
|
if (options.min > TypedArrayPrototypeGetLength(view)) {
|
||||||
|
return PromiseReject(
|
||||||
|
new RangeError("options.min must be smaller or equal to view's size"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (options.min > DataViewPrototypeGetByteLength(view)) {
|
||||||
|
return PromiseReject(
|
||||||
|
new RangeError("options.min must be smaller or equal to view's size"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this[_stream] === undefined) {
|
if (this[_stream] === undefined) {
|
||||||
return PromiseReject(
|
return PromiseReject(
|
||||||
new TypeError("Reader has no associated stream."),
|
new TypeError("Reader has no associated stream."),
|
||||||
|
@ -5603,7 +5639,7 @@ class ReadableStreamBYOBReader {
|
||||||
promise.reject(e);
|
promise.reject(e);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
readableStreamBYOBReaderRead(this, view, readIntoRequest);
|
readableStreamBYOBReaderRead(this, view, options.min, readIntoRequest);
|
||||||
return promise.promise;
|
return promise.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5929,6 +5965,7 @@ class ReadableByteStreamController {
|
||||||
byteLength: autoAllocateChunkSize,
|
byteLength: autoAllocateChunkSize,
|
||||||
bytesFilled: 0,
|
bytesFilled: 0,
|
||||||
elementSize: 1,
|
elementSize: 1,
|
||||||
|
minimumFill: 1,
|
||||||
viewConstructor: Uint8Array,
|
viewConstructor: Uint8Array,
|
||||||
readerType: "default",
|
readerType: "default",
|
||||||
};
|
};
|
||||||
|
@ -6799,6 +6836,17 @@ webidl.converters.ReadableStreamGetReaderOptions = webidl
|
||||||
converter: webidl.converters.ReadableStreamReaderMode,
|
converter: webidl.converters.ReadableStreamReaderMode,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
|
webidl.converters.ReadableStreamBYOBReaderReadOptions = webidl
|
||||||
|
.createDictionaryConverter("ReadableStreamBYOBReaderReadOptions", [{
|
||||||
|
key: "min",
|
||||||
|
converter: (V, prefix, context, opts) =>
|
||||||
|
webidl.converters["unsigned long long"](V, prefix, context, {
|
||||||
|
...opts,
|
||||||
|
enforceRange: true,
|
||||||
|
}),
|
||||||
|
defaultValue: 1,
|
||||||
|
}]);
|
||||||
|
|
||||||
webidl.converters.ReadableWritablePair = webidl
|
webidl.converters.ReadableWritablePair = webidl
|
||||||
.createDictionaryConverter("ReadableWritablePair", [
|
.createDictionaryConverter("ReadableWritablePair", [
|
||||||
{
|
{
|
||||||
|
|
1
ext/web/06_streams_types.d.ts
vendored
1
ext/web/06_streams_types.d.ts
vendored
|
@ -30,6 +30,7 @@ interface PullIntoDescriptor {
|
||||||
byteOffset: number;
|
byteOffset: number;
|
||||||
byteLength: number;
|
byteLength: number;
|
||||||
bytesFilled: number;
|
bytesFilled: number;
|
||||||
|
minimumFill: number;
|
||||||
elementSize: number;
|
elementSize: number;
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
viewConstructor: any;
|
viewConstructor: any;
|
||||||
|
|
6
ext/web/lib.deno_web.d.ts
vendored
6
ext/web/lib.deno_web.d.ts
vendored
|
@ -623,12 +623,18 @@ declare type ReadableStreamBYOBReadResult<V extends ArrayBufferView> =
|
||||||
| ReadableStreamBYOBReadDoneResult<V>
|
| ReadableStreamBYOBReadDoneResult<V>
|
||||||
| ReadableStreamBYOBReadValueResult<V>;
|
| ReadableStreamBYOBReadValueResult<V>;
|
||||||
|
|
||||||
|
/** @category Streams API */
|
||||||
|
declare interface ReadableStreamBYOBReaderReadOptions {
|
||||||
|
min?: number;
|
||||||
|
}
|
||||||
|
|
||||||
/** @category Streams API */
|
/** @category Streams API */
|
||||||
declare interface ReadableStreamBYOBReader {
|
declare interface ReadableStreamBYOBReader {
|
||||||
readonly closed: Promise<void>;
|
readonly closed: Promise<void>;
|
||||||
cancel(reason?: any): Promise<void>;
|
cancel(reason?: any): Promise<void>;
|
||||||
read<V extends ArrayBufferView>(
|
read<V extends ArrayBufferView>(
|
||||||
view: V,
|
view: V,
|
||||||
|
options?: ReadableStreamBYOBReaderReadOptions,
|
||||||
): Promise<ReadableStreamBYOBReadResult<V>>;
|
): Promise<ReadableStreamBYOBReadResult<V>>;
|
||||||
releaseLock(): void;
|
releaseLock(): void;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3204,7 +3204,9 @@
|
||||||
"respond-after-enqueue.any.html": true,
|
"respond-after-enqueue.any.html": true,
|
||||||
"respond-after-enqueue.any.worker.html": true,
|
"respond-after-enqueue.any.worker.html": true,
|
||||||
"enqueue-with-detached-buffer.any.html": true,
|
"enqueue-with-detached-buffer.any.html": true,
|
||||||
"enqueue-with-detached-buffer.any.worker.html": true
|
"enqueue-with-detached-buffer.any.worker.html": true,
|
||||||
|
"read-min.any.html": true,
|
||||||
|
"read-min.any.worker.html": true
|
||||||
},
|
},
|
||||||
"readable-streams": {
|
"readable-streams": {
|
||||||
"async-iterator.any.html": true,
|
"async-iterator.any.html": true,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue