- From: Mattias Buelens <notifications@github.com>
- Date: Sun, 13 Jun 2021 15:32:33 -0700
- To: whatwg/streams <streams@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/streams/pull/1114/review/682449601@github.com>
@MattiasBuelens commented on this pull request. I've added handling for errors from cloning chunks. Still gotta find some time to write tests for all these edge cases. 😛 > + 1. Perform ! [$ReadableStreamDefaultControllerError$](|branch1|.[=ReadableStream/[[controller]]=], |cloneResult|.\[[Value]]). + 1. Perform ! [$ReadableStreamDefaultControllerError$](|branch2|.[=ReadableStream/[[controller]]=], |cloneResult|.\[[Value]]). + 1. [=Resolve=] |cancelPromise| with ! [$ReadableStreamCancel$](|stream|, |cloneResult|.\[[Value]]). There's another re-entrancy risk here. `ReadableStreamDefaultControllerError` will call `readRequest.errorSteps(e)`, which *could* call both `branch1.cancel()` and `branch2.cancel()`. Thus, our `cancel1Algorithm` (or `cancel2Algorithm` depending on which branch is cancelled last) will call `ReadableStreamCancel(stream, e)` twice. This is "okay" since it'll immediately return an already-resolved promise, but we'll also try to *resolve* our `cancelPromise` twice, which we want to avoid. Possible solutions: * Swap the order: cancel first, error branches second. However, this doesn't really solve the problem, since the stream's cancel steps might *also* cancel the branches and make us cancel the stream *again*. I guess we could add a separate `canceled` flag to remember if we already called `ReadableStreamCancel` before, but that seems messy... 😕 * Add an extra _"if `canceled1` is false or `canceled2` is false"_ check before cancelling. I think I'll go with the second option, with a note about why this check is necessary. Not sure if we can trigger this edge case from WPT, because we always have at least one micro-task delay from the user-facing `reader.read()` promises. > :: 1. [=Queue a microtask=] to perform the following steps: 1. Set |reading| to false. - 1. Let |value1| and |value2| be |value|. - 1. If |canceled2| is false and |cloneForBranch2| is true, set |value2| to ? - [$StructuredDeserialize$](? [$StructuredSerialize$](|value2|), [=the current Realm=]). - 1. If |canceled1| is false, perform ? + 1. Let |chunk1| and |chunk2| be |chunk|. + 1. If |canceled2| is false and |cloneForBranch2| is true, + 1. Let |cloneResult| be [$StructuredClone$](|chunk2|). + 1. If |cloneResult| is an abrupt completion, + 1. Perform ! [$ReadableStreamDefaultControllerError$](|branch1|.[=ReadableStream/[[controller]]=], |cloneResult|.\[[Value]]). Should we use the original error as-is (i.e. a `"DataCloneError"` `DOMException`), or should we do "let `cloneError` be a new `TypeError`" instead? 🤔 -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/whatwg/streams/pull/1114#pullrequestreview-682449601
Received on Sunday, 13 June 2021 22:32:54 UTC