Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getStreamAsArrayBuffer from a ReadableStream fails on Chrome, but works on FF. #116

Closed
emctague opened this issue Feb 28, 2024 · 3 comments · Fixed by #122
Closed

getStreamAsArrayBuffer from a ReadableStream fails on Chrome, but works on FF. #116

emctague opened this issue Feb 28, 2024 · 3 comments · Fixed by #122

Comments

@emctague
Copy link

Given the following snippet:

const inputString = "any text here"
const output = await getStreamAsArrayBuffer(
      new Blob([inputString]).stream().pipeThrough(new CompressionStream('gzip')))

This will succeed on Firefox, but fail on Chrome, apparently because isAsyncIterable returns false when given the resultant ReadableStream in that browser. It appears that Chrome's ReadableStream is not yet async iterable.

The README for the repository seems to indicate that a ReadableStream is valid input for getStreamAsArrayBuffer, and that it should work on all modern browsers which support ReadableStream.

@ehmicky
Copy link
Collaborator

ehmicky commented Feb 28, 2024

Thanks @emctague, that's a great (yet unfortunate) finding.

The logic in this module completely relies on async iterations. Actually, while it is called get-stream, it does not do anything stream-specific, instead it behaves as get-async-iterable. This module started as a Node.js-specific package targeting only Node.js streams, and generalized it to any async iterables in order to bring web support, since both web streams and Node.js streams are async iterables.

Polyfilling async iteration for web streams is quite complicated. With Node.js streams, it's solvable in ~20 lines of code but support for web streams would be quite tedious.

It seems like Chrome has started working on this since last week. Unfortunately, support might still be lagging for some time on Safari and Opera. Node.js, Deno and Firefox do currently support it.

This does not impact users who only target Node.js/Deno, or users who target web browsers but only use async iterables (instead of web streams).

A polyfill and a ponyfill are available. I would suggest the following: we should add a browser-specific entrypoint that uses that ponyfill. The ponyfill is pretty big (67KB minified) but web browser support would otherwise be basically broken if this works only on Firefox. A big browser entrypoint would be an improvement over a small entrypoint that does not work. Node.js users would not use that ponyfill and use a different entrypoint.

An alternative would be to ask users to install that polyfill/ponyfill themselves. However, if almost every web browser user needs to do it, I guess we might as well do it on their behalf?

What are your thoughts on this @sindresorhus?

@ehmicky
Copy link
Collaborator

ehmicky commented Mar 14, 2024

It appears that ReadableStream[Symbol.asyncIterator] has been implemented and will be released with Chrome 124. However, it's still missing with Edge, Safari and Opera.

Implementing it ourselves is possible, but is definitely quite complicated, especially if we want to thoroughly test every edge case.

Adding the ponyfill mentioned above is also a problem, even if we used a different entrypoint because it is 431KB which would be noticeable during npm install.

The only other ponyfill I found is the following one, which I am looking into to make sure it covers all edge cases. It seems spec-compliant and has good test coverage. Also it is quite small. I am going to try to use it as a ponyfill.

@ehmicky
Copy link
Collaborator

ehmicky commented Mar 14, 2024

PR at #122.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants