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

"TypeError: Failed to execute 'pipeThrough' on 'ReadableStream'" #93

Closed
akira-kurogane opened this issue Sep 22, 2021 · 4 comments
Closed
Labels

Comments

@akira-kurogane
Copy link

Hello.

I've not been able to use the polyfill due to encountering this error as soon as pipeThrough() is executed on the response body of a fetch().

TypeError: Failed to execute 'pipeThrough' on 'ReadableStream': Failed to read the 'readable' property from 'ReadableWritablePair': Failed to convert value to 'ReadableStream'

I reduced my script down to this reproduction case. As far as I can see it really is the point where .pipeThrough() is called that the exception is thrown.

<body>
  <div id="root"></div>
  <!-- Remove this include of polyfill.min.js to see native behaviour. N.b. of Sep 2021 TransformStream is supported in Chrome, but not in Firefox. -->
  <script src="https://unpkg.com/web-streams-polyfill/dist/polyfill.min.js"></script>
  <script>
    function DummyTransformStream() {
      return new TransformStream({
        transform(chunk, controller) {
          controller.enqueue(chunk); //just re-enqueue the chunk as it is
        },
      });
    }

    const url = 'https://jsonplaceholder.typicode.com/photos';

    fetch(url)
      .then(async res => {
        if (res.status !== 200) {
          console.log(`http request to ${url} failed, returned HTTP status ${res.status}. Please try a different URL.`);
        }

        const testReader = res.body
          .pipeThrough(DummyTransformStream())
          .getReader();

        while (true) {
          let { value: val, done: rdrDone } = await testReader.read();
          if (rdrDone) {
            break;
          }
          //console.log("Chunk of " + val.length + " bytes read");
          let msgDiv = document.createElement('div');
          msgDiv.append("Chunk of " + val.length + " bytes read");
          document.getElementById('root').append(msgDiv);
        }
      });
  </script>
</body>

Is there a something about syntax I've made a mistake with, etc.?

@MattiasBuelens
Copy link
Owner

No, your code is fine. Unfortunately, you ran into a limitation of the current version of the polyfill. 😞

When you load the polyfill onto the page, it replaces the existing ReadableStream/WritableStream/TransformStream global variables that may already be defined by the browser. That's fine if every stream in your code uses those overwritten global variables.

The problem is that web APIs like fetch() will return a native ReadableStream, as originally defined by the browser. Such a stream is not created by the polyfill, and thus either it won't have a .pipeThrough() method (e.g. in the current version of Firefox), or its .pipeThrough() method requires its first parameter to contain a native WritableStream (e.g. in the current version of Chrome). In both cases, it won't work with a polyfilled WritableStream.

I'm planning to rework the polyfill so it plays nicer together with the native ReadableStream of the browser, see #20. For now, you can work around this by first "adapting" the native ReadableStream from fetch() into a polyfilled ReadableStream. You can use web-streams-adapter for this. It'd look something like this:

<script src="https://unpkg.com/web-streams-polyfill/dist/polyfill.min.js"></script>
<script src="https://unpkg.com/@mattiasbuelens/[email protected]/dist/web-streams-adapter.js"></script>
<script>
const toPolyfillReadable = WebStreamsAdapter.createReadableStreamWrapper(ReadableStream);

fetch(url)
  .then(async res => {
    const testReader = toPolyfillReadable(res.body)
        .pipeThrough(DummyTransformStream())
        .getReader();
    // ...
  });
</script>

@akira-kurogane
Copy link
Author

Hello Mattias.

Thank you, I confirm that solves the issue I'd hit. That I just needed to use a related adapter for the browser's native ReadableStream makes sense.

Wow, it's been a real marathon getting to the right browser-side, WHATWG web streams implementation via google search. To be honest I began this after seeing that Node recently got a WHATWG standard implementation of ReadableStream, WritableStream and TransformStream in its inbuilt API recently in v16.5 (https://nodejs.org/api/webstreams.html#webstreams_web_streams_api). I appreciate Node is a server but by googling on the same terms I kept on finding pages that suggested it could be used client side. All my misinterpretation - it's ReadableStream, not ReadableStream or ReadableStream :p

Thanks for the polyfill! It suits the goals of my project well.

Akira

@MattiasBuelens
Copy link
Owner

Glad to hear that solves your problem. And thanks for the kind words! 😄

@akira-kurogane
Copy link
Author

👍

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

No branches or pull requests

2 participants