question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ReadableStream object could not be cloned when trying to use stream as a mocked response body

See original GitHub issue

This issue originated from the earlier issue: https://github.com/mswjs/msw/issues/156

If we need msw to support SSE, then we need to make the code work:

export const worker = setupWorker(
  rest.get('/sse', (req, res, ctx) => {
    return res(
      ctx.status(200)
    , ctx.set('Content-Type', 'text/event-stream')
    , ctx.body(sse(function* () {
        yield 'message1'
        yield 'message2'
      }))
    )
  })
)

function sse(gfn) {
  let iter
  return new ReadableStream({
    start() {
      iter = gfn()
    }
  , pull(controller) {
      controller.enqueue(`data: ${iter.next().value}\n\n`)
    }
  })
}

Browser:

[MSW] Request handler function for "GET http://localhost:8080/sse" has thrown the following exception:

DOMException: Failed to execute 'postMessage' on 'MessagePort': ReadableStream object could not be cloned.
(see more detailed error stack trace in the mocked response body)

Node.js:

TypeError: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received an instance of ReadableStreamTypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received an instance of ReadableStream

      at ClientRequestOverride.<anonymous> (node_modules/node-request-interceptor/src/interceptors/ClientRequest/ClientRequestOverride.ts:216:34)
      at step (node_modules/node-request-interceptor/lib/interceptors/ClientRequest/ClientRequestOverride.js:33:23)
      at Object.next (node_modules/node-request-interceptor/lib/interceptors/ClientRequest/ClientRequestOverride.js:14:53)
      at fulfilled (node_modules/node-request-interceptor/lib/interceptors/ClientRequest/ClientRequestOverride.js:5:58)

_Originally posted by @BlackGlory in https://github.com/mswjs/msw/issues/156#issuecomment-739362584_

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:4
  • Comments:7 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
kettanaitocommented, Jul 16, 2022

One thing to mention: there is no ReadableStream API in Node. There’s Readable, which is a different thing. There are also some transformation utils like Readable.toWeb() in the latest versions of Node but I have no confirmation of whether they construct an actual window.ReadableStream-compatible API.

Generally, we’ve adopted ReadableStream internally but MSW doesn’t have support for ReadableStream as a mocked response body yet. Even this internal change seems to have broken a thing or two for some browsers, as the request is pending indefinitely in some cases (see #1325, #1324).

The way we’ve implemented readable streams internally is:

  1. Construct new Response(mockedResponse.body) and then read it as response.body.getReader().
  2. Send all read chunks to the worker via messageChannel.postMessage().
  3. On the worker’s side, construct another readable stream and manually pipe the incoming messages to that stream’s queue: https://github.com/mswjs/msw/blob/6c6e1193327ba6c7d55826fd7997ddc9f1fb4fd5/src/mockServiceWorker.js#L351-L355

This effectively means that we’re constructing two streams and stitching them together.

I’ve just tried sending a stream via transport of postMessage but while that works fine in Chrome, browsers like Firefox and Safari refuse to clone a ReadableStream. This is despite the spec describing Transferable as various data types, including ReadableStream.

I suspect that the pending request issue is caused by the operation channel (BroadcastChannel) that we create internally to bind the chunks transfer to a specific request:

https://github.com/mswjs/msw/blob/6c6e1193327ba6c7d55826fd7997ddc9f1fb4fd5/src/mockServiceWorker.js#L234-L239

If this channel gets corrupted/destroyed, the internal stream in the worker will pend forever.

0reactions
kettanaitocommented, Jul 4, 2022

Released: v0.43.0 🎉

This has been released in v0.43.0!

Make sure to always update to the latest version (npm i msw@latest) to get the newest features and bug fixes.


Predictable release automation by @ossjs/release.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to clone a readable stream - node.js - Stack Overflow
I thought about cloning the stream but simply creating a new variable and assigning the stream to that variable does not work. node.js...
Read more >
1659025 - Implement transferable streams - Bugzilla@Mozilla
A "The object could not be cloned." DOMException is thrown because transferable streams are not implemented. Expected results:.
Read more >
Safari Technology Preview Release Notes - Apple Developer
If you already have Safari Technology Preview installed, you can update in the Software Update pane of System Preferences on macOS Monterey, or...
Read more >
observe fetch request javascript - You.com | The AI Search ...
log( pointer.responseText ); //Here is where you can add any code to process the response. //If you want to pass the Ajax request...
Read more >
Changelog - Miniflare
Previously, flushing all alarms would attempt to execute the alarm handler of every constructed Durable Object instance, even if that instance hadn't ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found