cloudflare / cloudflare/workerd
Response.clone() + HTMLRewriter.transform() deadlocks when clone is read first
- Dominant language
- C++
- Stars
- 8.7k
- Forks
- 739
- Avg merge
- 2d 20h
- Merged PRs (30d)
- 174
Description
`Response.clone()` followed by `HTMLRewriter.transform(response)` deadlocks when the clone's body is consumed before the HTMLRewriter output. workerd kills the request with "your Worker's code had hung and would never generate a response".
Without HTMLRewriter, reading the clone first works fine — the tee branches are independent. HTMLRewriter appears to couple them, so the clone's branch can't be read unless the HTMLRewriter branch is also being consumed.
```js
export default {
async fetch() {
const response = new Response("
Hello
");const clone = response.clone();
new HTMLRewriter()
.on("h1", { element(el) { el.setInnerContent("Rewritten"); } })
.transform(response);
// Hangs — tee branch for `clone` is blocked because HTMLRewriter
// holds the other branch and nothing is reading its output.
return new Response(await clone.text());
},
};
```
I think this is the root cause of [cloudflare/workers-sdk#7313](https://github.com/cloudflare/workers-sdk/issues/7313). The common pattern of `ctx.waitUntil(cache.put(req, response.clone()))` combined with `return new HTMLRewriter().transform(response)` deadlocks in `@cloudflare/vitest-pool-workers` tests, because `waitOnExecutionContext()` waits for `cache.put` (which needs to read the clone) before the test consumes the HTMLRewriter output.
Contributor guide
Assessment
This issue has not been assessed yet.