@@ -1580,23 +1580,47 @@ bool RequestOrResponse::body_source_pull_algorithm(JSContext *cx, JS::CallArgs a
15801580 // piped to the same destination this is guaranteed to happen in the right
15811581 // order: ReadableStream#pipeTo locks the destination WritableStream until the
15821582 // source ReadableStream is closed/canceled, so only one stream can ever be
1583- // piped in at the same time.
1583+ // piped in at the same time. There may be a chain of TransformStreams in
1584+ // between the source and destination, so we walk the piping chain to find the
1585+ // final destination.
15841586 JS::RootedObject pipe_dest (cx, NativeStreamSource::piped_to_transform_stream (source));
15851587 if (pipe_dest) {
1588+ // Walk the chain of TransformStreams to find the final destination
1589+ JS::RootedObject current_dest (cx, pipe_dest);
1590+ JS::RootedObject next_dest (cx);
1591+
1592+ while (current_dest) {
1593+ // Try to find the next TransformStream in the chain
1594+ JS::RootedObject readable (cx, TransformStream::readable (current_dest));
1595+ JS::RootedObject next_source (cx, NativeStreamSource::get_stream_source (cx, readable));
1596+ if (next_source) {
1597+ next_dest.set (NativeStreamSource::piped_to_transform_stream (next_source));
1598+ } else {
1599+ next_dest.set (nullptr );
1600+ }
15861601
1587- if (TransformStream::readable_used_as_body (pipe_dest)) {
1602+ // If there's no next destination, we've found the last one in the chain
1603+ if (!next_dest) {
1604+ // If this is used as a body, we can append directly and close
1605+ if (TransformStream::readable_used_as_body (current_dest)) {
1606+ JS::RootedObject dest_owner (cx, TransformStream::owner (current_dest));
1607+ if (!RequestOrResponse::append_body (cx, dest_owner, body_owner)) {
1608+ return false ;
1609+ }
15881610
1589- JS::RootedObject dest_owner (cx, TransformStream::owner (pipe_dest));
1590- if (!RequestOrResponse::append_body (cx, dest_owner, body_owner)) {
1591- return false ;
1592- }
1611+ JS::RootedObject stream (cx, NativeStreamSource::stream (source));
1612+ bool success = JS::ReadableStreamClose (cx, stream);
1613+ MOZ_RELEASE_ASSERT (success);
15931614
1594- JS::RootedObject stream (cx, NativeStreamSource::stream (source));
1595- bool success = JS::ReadableStreamClose (cx, stream);
1596- MOZ_RELEASE_ASSERT (success);
1615+ args.rval ().setUndefined ();
1616+ return true ;
1617+ }
1618+ // If the last one isn't used as a body it must be doing something else with
1619+ // the data, so we fall back to reading and writing chunks as normal
1620+ break ;
1621+ }
15971622
1598- args.rval ().setUndefined ();
1599- return true ;
1623+ current_dest.set (next_dest);
16001624 }
16011625 }
16021626
0 commit comments