Open ricea opened 2 years ago
Looking at the call sites for WritableStreamDefaultControllerClearAlgorithms and I can't really see any rhyme or reason behind them. I'd expect them to happen whenever we set [[state]] to "errored" (maybe "erroring"?) and "closed".
Patching the immediate problem by moving that particular case later might be reasonable, but I wonder if we should do a more comprehensive reform of when they are cleared.
The issue is not urgent (at least for Blink), so we can take the time to do it properly.
Consider the following code:
The call to
writer.close()
results in a call toWritableStreamDefaultControllerProcessClose
, which runs[[closeAlgorithm]]
which calls into the underlying sink close() method in step 5. This immediately returns, executing step 6.Perform ! WritableStreamDefaultControllerClearAlgorithms(controller).
On the next microtask,
writer.write()
is called. This results in a call toWritableStreamDefaultWriterWrite
which on step 4 callsWritableStreamDefaultControllerGetChunkSize
. This runscontroller.[[strategySizeAlgorithm]]
which was set to undefined inWritableStreamDefaultControllerClearAlgorithms
.The reference implementation doesn't crash. Instead, it catches the 'undefined is not a function' error:
This seems like cheating.
Blink's implementation explicitly checks if
[[strategySize]]
is undefined. It only crashes when compiled with debugging checks. I don't recall why I included a check for undefined there. It also seems like cheating, since it's nowhere in the standard.I think the correct fix is not to call
WritableStreamDefaultControllerClearAlgorithms
until after the promise returned by[[closeAlgorithm]]
resolves or rejects. I don't recall why I didn't do that originally.The same also applies to
[[abortAlgorithm]]
.What do you think?