-
Notifications
You must be signed in to change notification settings - Fork 50k
[Flight] Make debug info and console log resolve in predictable order #33665
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
Conversation
| type ConsoleEntry = [ | ||
| string, | ||
| ReactStackTrace, | ||
| null | ReactComponentInfo, | ||
| string, | ||
| mixed, | ||
| ]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| type ConsoleEntry = [ | |
| string, | |
| ReactStackTrace, | |
| null | ReactComponentInfo, | |
| string, | |
| mixed, | |
| ]; | |
| type ConsoleEntry = [ | |
| /* eslint-disable no-undef -- eslint does not understand Flow tuple syntax. */ | |
| methodName: string, | |
| stackTrace: ReactStackTrace, | |
| owner: null | ReactComponentInfo, | |
| env: string, | |
| args: mixed, | |
| /* eslint-enable no-undef */ | |
| ]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where does this error? I'm not seeing any lint errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In your version it does not error. I wanted to suggest adding the tuple labels. And then it would error unless we disable eslint. Devon did the same here:
react/packages/react-server-dom-parcel/src/shared/ReactFlightImportMetadata.js
Lines 12 to 20 in 3cfcdfb
| export type ImportMetadata = [ | |
| // eslint does not understand Flow tuple syntax. | |
| /* eslint-disable */ | |
| id: string, | |
| name: string, | |
| bundles: Array<string>, | |
| importMap?: {[string]: string}, | |
| /* eslint-enable */ | |
| ]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given how much trouble we've had with parsers I'm not sure I trust that this won't break linting elsewhere.
0236f23 to
636f359
Compare
| stream, | ||
| controller, | ||
| ); | ||
| blockedDebugInfo.then(unblock, unblock); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is safe because the chunk needs to enter a non-pending state before the next chunk is resolved. Otherwise the next chunk doesn't know it's a stream entry.
|
Do we block forever or do we give up after a timeout and log a dumbed down value after some time? We could log a placeholder object if it takes to long to resolve the value and set a dedicated property later. We'd end up logging something slightly different but when you have a debugger attached, you could inspect the resolved value later for debuggers where logged values are live (e.g. Chrome DevTools) |
|
Currently the only thing that can block it is a client reference and it's kind of unusual that you would be able to render anything at all without it. Everything else comes before in the stream anyway. However, the main reason to do this is to allow the separate debug stream. I think for that one, it's up to the framework to ensure that it's live connected and if it closes then we'd fall back to skipping debug info. |
This lets us pass a writable on the server side and readable on the client side to send debug info through a separate channel so that it doesn't interfere with the main payload as much. The main payload refers to chunks defined in the debug info which means it's still blocked on it though. This ensures that the debug data has loaded by the time the value is rendered so that the next step can forward the data. This will be a bit fragile to race conditions until #33665 lands. Another follow up needed is the ability to skip the debug channel on the receiving side. Right now it'll block forever if you don't provide one since we're blocking on the debug data.
React Elements reference debug data (their stack and owner) in the debug channel. If the debug channel isn't wired up this can block the client from resolving. We can infer that if there's no debug channel wired up and the reference wasn't emitted before the element, then it's probably because it's in the debug channel. So we can skip it. This should also apply to debug chunks but they're not yet blocking until #33665 lands.
|
There's two issues with this approach that I don't like.
Neither of these are an issue for the console part of this since it's an eager side-effect regardless to preserve order and there's nothing else in the stream that depends on a console entry, where as you can depend on a chunk which is blocked by debug info. |
These types cause an infinite loop in flow.
Instead we wait to add a debug info entry until it resolves. This will always be in order since they depend on each other.
|
I pushed a version that is able to lazily initialize and resolve cycles. However, I ended up eagerly initializing anyway because we rely on that downstream in Fiber and Fizz. I also ensured that we can avoid blocking if the debug info is a reference that isn't available and there's no debug channel. |
…facebook#33665) This resolves an outstanding issue where it was possible for debug info and console logs to become out of order if they up blocked. E.g. by a future reference or a client reference that hasn't loaded yet. Such as if you console.log a client reference followed by one that doesn't. This encodes the order similar to how the stream chunks work. This also blocks the main chunk from resolving until the last debug info has fully loaded, including future references and client references. This also ensures that we could send some of that data in a different stream, since then it can come out of order. DiffTrain build for [28d4bc4](facebook@28d4bc4)
…facebook#33665) This resolves an outstanding issue where it was possible for debug info and console logs to become out of order if they up blocked. E.g. by a future reference or a client reference that hasn't loaded yet. Such as if you console.log a client reference followed by one that doesn't. This encodes the order similar to how the stream chunks work. This also blocks the main chunk from resolving until the last debug info has fully loaded, including future references and client references. This also ensures that we could send some of that data in a different stream, since then it can come out of order. DiffTrain build for [28d4bc4](facebook@28d4bc4)
This PR contains the following updates: | Package | Change | Age | Confidence | |---|---|---|---| | [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react) ([source](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react)) | [`19.1.10` -> `19.2.6`](https://renovatebot.com/diffs/npm/@types%2freact/19.1.10/19.2.6) | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | | [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react-dom) ([source](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom)) | [`19.1.7` -> `19.2.3`](https://renovatebot.com/diffs/npm/@types%2freact-dom/19.1.7/19.2.3) | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | | [react](https://react.dev/) ([source](https://github.com/facebook/react/tree/HEAD/packages/react)) | [`19.1.1` -> `19.2.0`](https://renovatebot.com/diffs/npm/react/19.1.1/19.2.0) | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | | [react-dom](https://react.dev/) ([source](https://github.com/facebook/react/tree/HEAD/packages/react-dom)) | [`19.1.1` -> `19.2.0`](https://renovatebot.com/diffs/npm/react-dom/19.1.1/19.2.0) | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes <details> <summary>facebook/react (react)</summary> ### [`v19.2.0`](https://github.com/facebook/react/blob/HEAD/CHANGELOG.md#1920-October-1st-2025) [Compare Source](facebook/react@v19.1.1...v19.2.0) Below is a list of all new features, APIs, and bug fixes. Read the [React 19.2 release post](https://react.dev/blog/2025/10/01/react-19-2) for more information. ##### New React Features - [`<Activity>`](https://react.dev/reference/react/Activity): A new API to hide and restore the UI and internal state of its children. - [`useEffectEvent`](https://react.dev/reference/react/useEffectEvent) is a React Hook that lets you extract non-reactive logic into an [Effect Event](https://react.dev/learn/separating-events-from-effects#declaring-an-effect-event). - [`cacheSignal`](https://react.dev/reference/react/cacheSignal) (for RSCs) lets your know when the `cache()` lifetime is over. - [React Performance tracks](https://react.dev/reference/dev-tools/react-performance-tracks) appear on the Performance panel’s timeline in your browser developer tools ##### New React DOM Features - Added resume APIs for partial pre-rendering with Web Streams: - [`resume`](https://react.dev/reference/react-dom/server/resume): to resume a prerender to a stream. - [`resumeAndPrerender`](https://react.dev/reference/react-dom/static/resumeAndPrerender): to resume a prerender to HTML. - Added resume APIs for partial pre-rendering with Node Streams: - [`resumeToPipeableStream`](https://react.dev/reference/react-dom/server/resumeToPipeableStream): to resume a prerender to a stream. - [`resumeAndPrerenderToNodeStream`](https://react.dev/reference/react-dom/static/resumeAndPrerenderToNodeStream): to resume a prerender to HTML. - Updated [`prerender`](https://react.dev/reference/react-dom/static/prerender) APIs to return a `postponed` state that can be passed to the `resume` APIs. ##### Notable changes - React DOM now batches suspense boundary reveals, matching the behavior of client side rendering. This change is especially noticeable when animating the reveal of Suspense boundaries e.g. with the upcoming `<ViewTransition>` Component. React will batch as much reveals as possible before the first paint while trying to hit popular first-contentful paint metrics. - Add Node Web Streams (`prerender`, `renderToReadableStream`) to server-side-rendering APIs for Node.js - Use underscore instead of `:` IDs generated by useId ##### All Changes ##### React - `<Activity />` was developed over many years, starting before `ClassComponent.setState` ([@​acdlite](https://github.com/acdlite) [@​sebmarkbage](https://github.com/sebmarkbage) and many others) - Stringify context as "SomeContext" instead of "SomeContext.Provider" ([@​kassens](https://github.com/kassens) [#​33507](facebook/react#33507)) - Include stack of cause of React instrumentation errors with `%o` placeholder ([@​eps1lon](https://github.com/eps1lon) [#​34198](facebook/react#34198)) - Fix infinite `useDeferredValue` loop in popstate event ([@​acdlite](https://github.com/acdlite) [#​32821](facebook/react#32821)) - Fix a bug when an initial value was passed to `useDeferredValue` ([@​acdlite](https://github.com/acdlite) [#​34376](facebook/react#34376)) - Fix a crash when submitting forms with Client Actions ([@​sebmarkbage](https://github.com/sebmarkbage) [#​33055](facebook/react#33055)) - Hide/unhide the content of dehydrated suspense boundaries if they resuspend ([@​sebmarkbage](https://github.com/sebmarkbage) [#​32900](facebook/react#32900)) - Avoid stack overflow on wide trees during Hot Reload ([@​sophiebits](https://github.com/sophiebits) [#​34145](facebook/react#34145)) - Improve Owner and Component stacks in various places ([@​sebmarkbage](https://github.com/sebmarkbage), [@​eps1lon](https://github.com/eps1lon): [#​33629](facebook/react#33629), [#​33724](facebook/react#33724), [#​32735](facebook/react#32735), [#​33723](facebook/react#33723)) - Add `cacheSignal` ([@​sebmarkbage](https://github.com/sebmarkbage) [#​33557](facebook/react#33557)) ##### React DOM - Block on Suspensey Fonts during reveal of server-side-rendered content ([@​sebmarkbage](https://github.com/sebmarkbage) [#​33342](facebook/react#33342)) - Use underscore instead of `:` for IDs generated by `useId` ([@​sebmarkbage](https://github.com/sebmarkbage), [@​eps1lon](https://github.com/eps1lon): [#​32001](facebook/react#32001), [#​33342](https://github.com/facebook/react/pull/33342)[#​33099](https://github.com/facebook/react/pull/33099), [#​33422](facebook/react#33422)) - Stop warning when ARIA 1.3 attributes are used ([@​Abdul-Omira](https://github.com/Abdul-Omira) [#​34264](facebook/react#34264)) - Allow `nonce` to be used on hoistable styles ([@​Andarist](https://github.com/Andarist) [#​32461](facebook/react#32461)) - Warn for using a React owned node as a Container if it also has text content ([@​sebmarkbage](https://github.com/sebmarkbage) [#​32774](facebook/react#32774)) - s/HTML/text for for error messages if text hydration mismatches ([@​rickhanlonii](https://github.com/rickhanlonii) [#​32763](facebook/react#32763)) - Fix a bug with `React.use` inside `React.lazy`-ed Component ([@​hi-ogawa](https://github.com/hi-ogawa) [#​33941](facebook/react#33941)) - Enable the `progressiveChunkSize` option for server-side-rendering APIs ([@​sebmarkbage](https://github.com/sebmarkbage) [#​33027](facebook/react#33027)) - Fix a bug with deeply nested Suspense inside Suspense fallback when server-side-rendering ([@​gnoff](https://github.com/gnoff) [#​33467](facebook/react#33467)) - Avoid hanging when suspending after aborting while rendering ([@​gnoff](https://github.com/gnoff) [#​34192](facebook/react#34192)) - Add Node Web Streams to server-side-rendering APIs for Node.js ([@​sebmarkbage](https://github.com/sebmarkbage) [#​33475](facebook/react#33475)) ##### React Server Components - Preload `<img>` and `<link>` using hints before they're rendered ([@​sebmarkbage](https://github.com/sebmarkbage) [#​34604](facebook/react#34604)) - Log error if production elements are rendered during development ([@​eps1lon](https://github.com/eps1lon) [#​34189](facebook/react#34189)) - Fix a bug when returning a Temporary reference (e.g. a Client Reference) from Server Functions ([@​sebmarkbage](https://github.com/sebmarkbage) [#​34084](facebook/react#34084), [@​denk0403](https://github.com/denk0403) [#​33761](facebook/react#33761)) - Pass line/column to `filterStackFrame` ([@​eps1lon](https://github.com/eps1lon) [#​33707](facebook/react#33707)) - Support Async Modules in Turbopack Server References ([@​lubieowoce](https://github.com/lubieowoce) [#​34531](facebook/react#34531)) - Add support for .mjs file extension in Webpack ([@​jennyscript](https://github.com/jennyscript) [#​33028](facebook/react#33028)) - Fix a wrong missing key warning ([@​unstubbable](https://github.com/unstubbable) [#​34350](facebook/react#34350)) - Make console log resolve in predictable order ([@​sebmarkbage](https://github.com/sebmarkbage) [#​33665](facebook/react#33665)) ##### React Reconciler - [createContainer](https://github.com/facebook/react/blob/v19.2.0/packages/react-reconciler/src/ReactFiberReconciler.js#L255-L261) and [createHydrationContainer](https://github.com/facebook/react/blob/v19.2.0/packages/react-reconciler/src/ReactFiberReconciler.js#L305-L312) had their parameter order adjusted after `on*` handlers to account for upcoming experimental APIs </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNDguNCIsInVwZGF0ZWRJblZlciI6IjQyLjEwLjUiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbXX0=--> Reviewed-on: https://git.in.csmpro.ru/csmpro/csm-mapban/pulls/36 Co-authored-by: Renovate Bot <[email protected]> Co-committed-by: Renovate Bot <[email protected]>
Stacked on #33664.
This resolves an outstanding issue where it was possible for debug info and console logs to become out of order if they up blocked. E.g. by a future reference or a client reference that hasn't loaded yet. Such as if you console.log a client reference followed by one that doesn't. This encodes the order similar to how the stream chunks work.
This also blocks the main chunk from resolving until the last debug info has fully loaded, including future references and client references. This also ensures that we could send some of that data in a different stream, since then it can come out of order.