1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-11 16:42:21 -05:00

fix(ext/web/streams): fix ReadableStream asyncIterator (#16276)

This commit is contained in:
Marcos Casagrande 2023-01-09 21:17:36 +01:00 committed by David Sherret
parent fab10ea3e0
commit 49b5ac947f
2 changed files with 84 additions and 38 deletions

View file

@ -32,6 +32,7 @@
ObjectDefineProperties, ObjectDefineProperties,
ObjectDefineProperty, ObjectDefineProperty,
ObjectGetPrototypeOf, ObjectGetPrototypeOf,
ObjectPrototype,
ObjectPrototypeIsPrototypeOf, ObjectPrototypeIsPrototypeOf,
ObjectSetPrototypeOf, ObjectSetPrototypeOf,
Promise, Promise,
@ -4424,7 +4425,7 @@
* @returns {IteratorResult<T>} * @returns {IteratorResult<T>}
*/ */
function createIteratorResult(value, done) { function createIteratorResult(value, done) {
const result = ObjectCreate(null); const result = ObjectCreate(ObjectPrototype);
ObjectDefineProperties(result, { ObjectDefineProperties(result, {
value: { value, writable: true, enumerable: true, configurable: true }, value: { value, writable: true, enumerable: true, configurable: true },
done: { done: {
@ -4442,12 +4443,20 @@
ObjectGetPrototypeOf(async function* () {}).prototype, ObjectGetPrototypeOf(async function* () {}).prototype,
); );
const _iteratorNext = Symbol("[[iteratorNext]]");
const _iteratorFinished = Symbol("[[iteratorFinished]]");
/** @type {AsyncIterator<unknown>} */ /** @type {AsyncIterator<unknown>} */
const readableStreamAsyncIteratorPrototype = ObjectSetPrototypeOf({ const readableStreamAsyncIteratorPrototype = ObjectSetPrototypeOf({
/** @returns {Promise<IteratorResult<unknown>>} */ /** @returns {Promise<IteratorResult<unknown>>} */
next() { next() {
/** @type {ReadableStreamDefaultReader} */ /** @type {ReadableStreamDefaultReader} */
const reader = this[_reader]; const reader = this[_reader];
function nextSteps() {
if (reader[_iteratorFinished]) {
return PromiseResolve(createIteratorResult(undefined, true));
}
if (reader[_stream] === undefined) { if (reader[_stream] === undefined) {
return PromiseReject( return PromiseReject(
new TypeError( new TypeError(
@ -4455,6 +4464,7 @@
), ),
); );
} }
/** @type {Deferred<IteratorResult<any>>} */ /** @type {Deferred<IteratorResult<any>>} */
const promise = new Deferred(); const promise = new Deferred();
/** @type {ReadRequest} */ /** @type {ReadRequest} */
@ -4471,28 +4481,61 @@
promise.reject(e); promise.reject(e);
}, },
}; };
readableStreamDefaultReaderRead(reader, readRequest); readableStreamDefaultReaderRead(reader, readRequest);
return promise.promise; return PromisePrototypeThen(promise.promise, (result) => {
reader[_iteratorNext] = null;
if (result.done === true) {
reader[_iteratorFinished] = true;
return createIteratorResult(undefined, true);
}
return result;
}, (reason) => {
reader[_iteratorNext] = null;
reader[_iteratorFinished] = true;
throw reason;
});
}
reader[_iteratorNext] = reader[_iteratorNext]
? PromisePrototypeThen(reader[_iteratorNext], nextSteps, nextSteps)
: nextSteps();
return reader[_iteratorNext];
}, },
/** /**
* @param {unknown} arg * @param {unknown} arg
* @returns {Promise<IteratorResult<unknown>>} * @returns {Promise<IteratorResult<unknown>>}
*/ */
async return(arg) { return(arg) {
/** @type {ReadableStreamDefaultReader} */ /** @type {ReadableStreamDefaultReader} */
const reader = this[_reader]; const reader = this[_reader];
const returnSteps = () => {
if (reader[_iteratorFinished]) {
return PromiseResolve(createIteratorResult(arg, true));
}
reader[_iteratorFinished] = true;
if (reader[_stream] === undefined) { if (reader[_stream] === undefined) {
return createIteratorResult(undefined, true); return PromiseResolve(createIteratorResult(undefined, true));
} }
assert(reader[_readRequests].length === 0); assert(reader[_readRequests].length === 0);
if (this[_preventCancel] === false) { if (this[_preventCancel] === false) {
const result = readableStreamReaderGenericCancel(reader, arg); const result = readableStreamReaderGenericCancel(reader, arg);
readableStreamDefaultReaderRelease(reader); readableStreamDefaultReaderRelease(reader);
await result; return result;
return createIteratorResult(arg, true);
} }
readableStreamDefaultReaderRelease(reader); readableStreamDefaultReaderRelease(reader);
return createIteratorResult(undefined, true); return PromiseResolve(createIteratorResult(undefined, true));
};
const returnPromise = reader[_iteratorNext]
? PromisePrototypeThen(reader[_iteratorNext], returnSteps, returnSteps)
: returnSteps();
return PromisePrototypeThen(
returnPromise,
() => createIteratorResult(arg, true),
);
}, },
}, asyncIteratorPrototype); }, asyncIteratorPrototype);

View file

@ -1311,7 +1311,10 @@
"respond-after-enqueue.any.worker.html": true "respond-after-enqueue.any.worker.html": true
}, },
"readable-streams": { "readable-streams": {
"async-iterator.any.html": false, "async-iterator.any.html": [
"next() that succeeds; return()",
"next() that succeeds; return() [no awaiting]"
],
"bad-strategies.any.html": true, "bad-strategies.any.html": true,
"bad-strategies.any.worker.html": true, "bad-strategies.any.worker.html": true,
"bad-underlying-sources.any.html": true, "bad-underlying-sources.any.html": true,