Skip to content

Conversation

@pull
Copy link

@pull pull bot commented Oct 28, 2025

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

rickhanlonii and others added 2 commits October 28, 2025 12:53
500 tests failed from not using async act. Will fix the tests and then
re-land this.
…35003)

IO tasks can execute more than once. E.g. a connection may fire each
time a new message or chunk comes in or a setInterval every time it
executes.

We used to treat these all as one I/O node and just updated the end time
as we go. Most of the time this was fine because typically you would
have a Promise instance whose end time is really the one that gets used
as the I/O anyway.

However, in a pattern like this it could be problematic:

```js
setTimeout(() => {
  function App() {
    return Promise.resolve(123);
  }
  renderToReadableStream(<App />);
});
```

Because the I/O's end time is before the render started so it should be
excluded from being considered I/O as part of the render. It happened
outside of render. But because the `Promise.resolve()` is inside render
its end time is after the render start so the promise is considered part
of the render. This is usually not a problem because the end time of the
I/O is still before the start of the render so even though the Promise
is valid it has no I/O source so it's properly excluded.

However, if the I/O's end time updates before we observe this then the
I/O can be considered part of the render. E.g. if this was a setInterval
it would be clearly wrong. But it turns out that even setTimeout can
sometimes execute more than once in the async_hooks because each run of
"process.nextTick" and microtasks respectively are ran in their own
before/after. When a micro task executes after this main body it'll
update the end time which can then turn the whole I/O as being inside
the render.

To solve this properly I create a new I/O node each time before() is
invoked so that each one gets to observe a different end time. This has
a potential CPU and memory allocation cost when there's a lot of them
like in a quick stream.
@pull pull bot locked and limited conversation to collaborators Oct 28, 2025
@pull pull bot added the ⤵️ pull label Oct 28, 2025
@pull pull bot merged commit 0fa3250 into code:main Oct 28, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants