From 483e191ab5c42b04a3c345c7c33187dfa0111031 Mon Sep 17 00:00:00 2001 From: KATT Date: Sat, 7 Oct 2023 16:33:02 +0200 Subject: [PATCH 1/6] chore: close consistently --- src/async/handlers/tsonAsyncIterable.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/async/handlers/tsonAsyncIterable.ts b/src/async/handlers/tsonAsyncIterable.ts index ce58840e..43e15e4b 100644 --- a/src/async/handlers/tsonAsyncIterable.ts +++ b/src/async/handlers/tsonAsyncIterable.ts @@ -36,12 +36,10 @@ export const tsonAsyncIterator: TsonAsyncType< switch (value[0]) { case ITERATOR_DONE: { - opts.controller.close(); return; } case ITERATOR_ERROR: { - opts.controller.close(); throw TsonPromiseRejectionError.from(value[1]); } @@ -51,6 +49,8 @@ export const tsonAsyncIterator: TsonAsyncType< } } } + + opts.controller.close(); })(); }, key: "AsyncIterable", From 90f0f86126720eeae822d980d41606573f9096ee Mon Sep 17 00:00:00 2001 From: KATT Date: Sat, 7 Oct 2023 16:34:07 +0200 Subject: [PATCH 2/6] cool --- src/async/deserializeAsync.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/async/deserializeAsync.ts b/src/async/deserializeAsync.ts index b3c56329..d71e8a8d 100644 --- a/src/async/deserializeAsync.ts +++ b/src/async/deserializeAsync.ts @@ -198,11 +198,7 @@ export function createTsonParseAsyncInner(opts: TsonAsyncOptions) { // enqueue the error to all the streams for (const controller of cache.values()) { - try { - controller.enqueue(err); - } catch { - // ignore if the controller is closed - } + controller.enqueue(err); } opts.onStreamError?.(err); From e3d86012716ccd1a00ec8136fd0d8e73da467d75 Mon Sep 17 00:00:00 2001 From: KATT Date: Sat, 7 Oct 2023 16:36:09 +0200 Subject: [PATCH 3/6] wip --- src/async/asyncTypes.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/async/asyncTypes.ts b/src/async/asyncTypes.ts index a14f7d62..c93ee013 100644 --- a/src/async/asyncTypes.ts +++ b/src/async/asyncTypes.ts @@ -27,13 +27,9 @@ export interface TsonTransformerSerializeDeserializeAsync< */ deserialize: (opts: { /** - * Abort signal from of the full stream - */ - // abortSignal: Promise; - /** - * The controller for the ReadableStream, to close when we're done + * Close the controller for the ReadableStream of values */ - controller: ReadableStreamDefaultController; + close: () => void; /** * Reader for the ReadableStream of values */ From 060fb39211857f01267c5e3c9f5006d6f9a4cea2 Mon Sep 17 00:00:00 2001 From: KATT Date: Sat, 7 Oct 2023 16:37:13 +0200 Subject: [PATCH 4/6] fix --- src/async/deserializeAsync.ts | 6 ++++-- src/async/handlers/tsonAsyncIterable.ts | 2 +- src/async/handlers/tsonPromise.ts | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/async/deserializeAsync.ts b/src/async/deserializeAsync.ts index d71e8a8d..f84e3d2e 100644 --- a/src/async/deserializeAsync.ts +++ b/src/async/deserializeAsync.ts @@ -74,12 +74,14 @@ export function createTsonParseAsyncInner(opts: TsonAsyncOptions) { return transformer.deserialize({ // abortSignal - get controller() { + close() { // the `start` method is called "immediately when the object is constructed" // [MDN](http://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/ReadableStream) // so we're guaranteed that the controller is set in the cache // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return cache.get(idx)!; + const controller = cache.get(idx)!; + controller.close(); + cache.delete(idx); }, reader: readable.getReader(), }); diff --git a/src/async/handlers/tsonAsyncIterable.ts b/src/async/handlers/tsonAsyncIterable.ts index 43e15e4b..46a74d2e 100644 --- a/src/async/handlers/tsonAsyncIterable.ts +++ b/src/async/handlers/tsonAsyncIterable.ts @@ -50,7 +50,7 @@ export const tsonAsyncIterator: TsonAsyncType< } } - opts.controller.close(); + opts.close(); })(); }, key: "AsyncIterable", diff --git a/src/async/handlers/tsonPromise.ts b/src/async/handlers/tsonPromise.ts index ad650d0b..e6f60e6a 100644 --- a/src/async/handlers/tsonPromise.ts +++ b/src/async/handlers/tsonPromise.ts @@ -28,7 +28,7 @@ export const tsonPromise: TsonAsyncType = { const promise = new Promise((resolve, reject) => { async function _handle() { const next = await opts.reader.read(); - opts.controller.close(); + opts.close(); if (next.done) { throw new TsonPromiseRejectionError( From 7da28bdbda710a622c4ee8a69be65064d6c43a1e Mon Sep 17 00:00:00 2001 From: KATT Date: Sat, 7 Oct 2023 16:37:34 +0200 Subject: [PATCH 5/6] cool --- src/async/asyncTypes.ts | 4 ---- src/async/deserializeAsync.ts | 1 - src/async/serializeAsync.ts | 1 - 3 files changed, 6 deletions(-) diff --git a/src/async/asyncTypes.ts b/src/async/asyncTypes.ts index c93ee013..4f28b5f2 100644 --- a/src/async/asyncTypes.ts +++ b/src/async/asyncTypes.ts @@ -46,10 +46,6 @@ export interface TsonTransformerSerializeDeserializeAsync< * JSON-serializable value */ serializeIterator: (opts: { - /** - * Abort signal from of the full stream - */ - // abortSignal?: AbortSignal; /** * The value we're serializing */ diff --git a/src/async/deserializeAsync.ts b/src/async/deserializeAsync.ts index f84e3d2e..8bebdd44 100644 --- a/src/async/deserializeAsync.ts +++ b/src/async/deserializeAsync.ts @@ -73,7 +73,6 @@ export function createTsonParseAsyncInner(opts: TsonAsyncOptions) { }); return transformer.deserialize({ - // abortSignal close() { // the `start` method is called "immediately when the object is constructed" // [MDN](http://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/ReadableStream) diff --git a/src/async/serializeAsync.ts b/src/async/serializeAsync.ts index 13d20e9a..78eb8772 100644 --- a/src/async/serializeAsync.ts +++ b/src/async/serializeAsync.ts @@ -96,7 +96,6 @@ function walkerFactory(nonce: TsonNonce, types: TsonAsyncOptions["types"]) { const idx = asyncIndex++ as TsonAsyncIndex; const iterator = handler.serializeIterator({ - // abortSignal: new AbortSignal(), value, }); iterators.set(idx, iterator[Symbol.asyncIterator]()); From d87ed9b3173497016d0d3c38b32f2eb7634b3d88 Mon Sep 17 00:00:00 2001 From: KATT Date: Sat, 7 Oct 2023 16:41:04 +0200 Subject: [PATCH 6/6] cool --- src/async/deserializeAsync.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/async/deserializeAsync.ts b/src/async/deserializeAsync.ts index 8bebdd44..0f298b4e 100644 --- a/src/async/deserializeAsync.ts +++ b/src/async/deserializeAsync.ts @@ -66,19 +66,22 @@ export function createTsonParseAsyncInner(opts: TsonAsyncOptions) { const idx = serializedValue as TsonAsyncIndex; + let controller: ReadableStreamDefaultController = + null as unknown as ReadableStreamDefaultController; const readable = new ReadableStream({ start(c) { - cache.set(idx, c); + controller = c; }, }); + // the `start` method is called "immediately when the object is constructed" + // [MDN](http://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/ReadableStream) + // so we're guaranteed that the controller is set in the cache + assert(controller, "Controller not set - this is a bug"); + + cache.set(idx, controller); return transformer.deserialize({ close() { - // the `start` method is called "immediately when the object is constructed" - // [MDN](http://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/ReadableStream) - // so we're guaranteed that the controller is set in the cache - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const controller = cache.get(idx)!; controller.close(); cache.delete(idx); },