-
Notifications
You must be signed in to change notification settings - Fork 46.9k
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
[Flight] Emit debug info for a Server Component #28272
Conversation
@@ -1306,7 +1350,7 @@ function renderModelDestructive( | |||
} | |||
if (value instanceof Float64Array) { | |||
// double | |||
return serializeTypedArray(request, 'D', value); | |||
return serializeTypedArray(request, 'd', value); |
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 switched this to use the lower case since the capital version fits better with the other common cases and this is very rare.
(The d is for double.)
@@ -605,6 +622,33 @@ function renderClientElement( | |||
return element; | |||
} | |||
|
|||
// The chunk ID we're currently rendering that we can assign debug data to. | |||
let debugID: null | number = null; |
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.
This is mainly to know if we're at the shallow end of the task or deep within the task. We really have the ID on the task already, but we can use this for other things too like console.logs.
// If you use() to Suspend this should always exist but if you throw a Promise instead, | ||
// which is not really supported anymore, it will be empty. We use the empty set as a | ||
// marker to know if this was a replay of the same component or first attempt. | ||
const state = thenableState || createThenableState(); |
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.
@acdlite I used a new mutable state if it wasn't already created.
I really only need this for DEV mode but seems generally useful. We could align Fizz/Fiber too but not necessary.
62da24a
to
3cfd12b
Compare
3cfd12b
to
2a299a6
Compare
@@ -76,53 +76,63 @@ const RESOLVED_MODULE = 'resolved_module'; | |||
const INITIALIZED = 'fulfilled'; | |||
const ERRORED = 'rejected'; | |||
|
|||
// Dev-only | |||
type ReactDebugInfo = Array<{+name?: string}>; |
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.
Why Array
? Could there be a collection with a size > 1 for a chunk?
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.
Yea. For one chunk you can have multiple Server Components. Like a Server Component rendering another Server Component and so on. There will also be possible to have other steps inside like promises resolving. There will also be logs which has to be associated with the right component so order matters.
Basically all kinds of things that happened will be expressed in the order they happened.
This adds a new DEV-only row type `D` for DebugInfo. If we see this in prod, that's an error. It can contain extra debug information about the Server Components (or Promises) that were compiled away during the server render. It's DEV-only since this can contain sensitive information (similar to errors) and since it'll be a lot of data, but it's worth using the same stream for simplicity rather than a side-channel. In this first pass it's just the Server Component's name but I'll keep adding more debug info to the stream, and it won't always just be a Server Component's stack frame. Each row can get more debug rows data streaming in as it resolves and renders multiple server components in a row. The data structure is just a side-channel and it would be perfectly fine to ignore the D rows and it would behave the same as prod. With this data structure though the data is associated with the row ID / chunk, so you can't have inline meta data. This means that an inline Server Component that doesn't get an ID otherwise will need to be outlined. The way I outline Server Components is using a direct reference where it's synchronous though so on the client side it behaves the same (i.e. there's no lazy wrapper in this case). In most cases the `_debugInfo` is on the Promises that we yield and we also expose this on the `React.Lazy` wrappers. In the case where it's a synchronous render it might attach this data to Elements or Arrays (fragments) too. In a future PR I'll wire this information up with Fiber to stash it in the Fiber data structures so that DevTools can pick it up. This property and the information in it is not limited to Server Components. The name of the property that we look for probably shouldn't be `_debugInfo` since it's semi-public. Should consider the name we use for that. If it's a synchronous render that returns a string or number (text node) then we don't have anywhere to attach them to. We could add a `React.Lazy` wrapper for those but I chose to prioritize keeping the data structure untouched. Can be useful if you use Server Components to render data instead of React Nodes. DiffTrain build for [b229f54](b229f54)
Updates React from 2bc7d336a to ba5e6a832. ### React upstream changes - facebook/react#28283 - facebook/react#28280 - facebook/react#28079 - facebook/react#28233 - facebook/react#28276 - facebook/react#28272 - facebook/react#28265 - facebook/react#28259 - facebook/react#28153 - facebook/react#28246 - facebook/react#28218 - facebook/react#28263 - facebook/react#28257 - facebook/react#28261 - facebook/react#28262 - facebook/react#28260 - facebook/react#28258 - facebook/react#27864 - facebook/react#28254 - facebook/react#28219 - facebook/react#28248 - facebook/react#28216 - facebook/react#28249 - facebook/react#28241 - facebook/react#28243 - facebook/react#28253 - facebook/react#28256 - facebook/react#28236 - facebook/react#28237 - facebook/react#28242 - facebook/react#28251 - facebook/react#28252 Closes NEXT-2411
One thing I realized about this approach is that it’s sufficient for parent stacks but it doesn’t include owner information about elements inside a row. They may have a different owner and each one may have a different owner. We may need to encode owner information on each element itself. Eg four argument. This needs to point to a server component though which means the meta data for knowing which one needs to be outlined. |
This adds a new DEV-only row type `D` for DebugInfo. If we see this in prod, that's an error. It can contain extra debug information about the Server Components (or Promises) that were compiled away during the server render. It's DEV-only since this can contain sensitive information (similar to errors) and since it'll be a lot of data, but it's worth using the same stream for simplicity rather than a side-channel. In this first pass it's just the Server Component's name but I'll keep adding more debug info to the stream, and it won't always just be a Server Component's stack frame. Each row can get more debug rows data streaming in as it resolves and renders multiple server components in a row. The data structure is just a side-channel and it would be perfectly fine to ignore the D rows and it would behave the same as prod. With this data structure though the data is associated with the row ID / chunk, so you can't have inline meta data. This means that an inline Server Component that doesn't get an ID otherwise will need to be outlined. The way I outline Server Components is using a direct reference where it's synchronous though so on the client side it behaves the same (i.e. there's no lazy wrapper in this case). In most cases the `_debugInfo` is on the Promises that we yield and we also expose this on the `React.Lazy` wrappers. In the case where it's a synchronous render it might attach this data to Elements or Arrays (fragments) too. In a future PR I'll wire this information up with Fiber to stash it in the Fiber data structures so that DevTools can pick it up. This property and the information in it is not limited to Server Components. The name of the property that we look for probably shouldn't be `_debugInfo` since it's semi-public. Should consider the name we use for that. If it's a synchronous render that returns a string or number (text node) then we don't have anywhere to attach them to. We could add a `React.Lazy` wrapper for those but I chose to prioritize keeping the data structure untouched. Can be useful if you use Server Components to render data instead of React Nodes.
This adds a new DEV-only row type `D` for DebugInfo. If we see this in prod, that's an error. It can contain extra debug information about the Server Components (or Promises) that were compiled away during the server render. It's DEV-only since this can contain sensitive information (similar to errors) and since it'll be a lot of data, but it's worth using the same stream for simplicity rather than a side-channel. In this first pass it's just the Server Component's name but I'll keep adding more debug info to the stream, and it won't always just be a Server Component's stack frame. Each row can get more debug rows data streaming in as it resolves and renders multiple server components in a row. The data structure is just a side-channel and it would be perfectly fine to ignore the D rows and it would behave the same as prod. With this data structure though the data is associated with the row ID / chunk, so you can't have inline meta data. This means that an inline Server Component that doesn't get an ID otherwise will need to be outlined. The way I outline Server Components is using a direct reference where it's synchronous though so on the client side it behaves the same (i.e. there's no lazy wrapper in this case). In most cases the `_debugInfo` is on the Promises that we yield and we also expose this on the `React.Lazy` wrappers. In the case where it's a synchronous render it might attach this data to Elements or Arrays (fragments) too. In a future PR I'll wire this information up with Fiber to stash it in the Fiber data structures so that DevTools can pick it up. This property and the information in it is not limited to Server Components. The name of the property that we look for probably shouldn't be `_debugInfo` since it's semi-public. Should consider the name we use for that. If it's a synchronous render that returns a string or number (text node) then we don't have anywhere to attach them to. We could add a `React.Lazy` wrapper for those but I chose to prioritize keeping the data structure untouched. Can be useful if you use Server Components to render data instead of React Nodes. DiffTrain build for commit b229f54.
This adds a new DEV-only row type
D
for DebugInfo. If we see this in prod, that's an error. It can contain extra debug information about the Server Components (or Promises) that were compiled away during the server render. It's DEV-only since this can contain sensitive information (similar to errors) and since it'll be a lot of data, but it's worth using the same stream for simplicity rather than a side-channel.In this first pass it's just the Server Component's name but I'll keep adding more debug info to the stream, and it won't always just be a Server Component's stack frame.
Each row can get more debug rows data streaming in as it resolves and renders multiple server components in a row.
The data structure is just a side-channel and it would be perfectly fine to ignore the D rows and it would behave the same as prod. With this data structure though the data is associated with the row ID / chunk, so you can't have inline meta data. This means that an inline Server Component that doesn't get an ID otherwise will need to be outlined. The way I outline Server Components is using a direct reference where it's synchronous though so on the client side it behaves the same (i.e. there's no lazy wrapper in this case).
In most cases the
_debugInfo
is on the Promises that we yield and we also expose this on theReact.Lazy
wrappers. In the case where it's a synchronous render it might attach this data to Elements or Arrays (fragments) too.In a future PR I'll wire this information up with Fiber to stash it in the Fiber data structures so that DevTools can pick it up. This property and the information in it is not limited to Server Components. The name of the property that we look for probably shouldn't be
_debugInfo
since it's semi-public. Should consider the name we use for that.If it's a synchronous render that returns a string or number (text node) then we don't have anywhere to attach them to. We could add a
React.Lazy
wrapper for those but I chose to prioritize keeping the data structure untouched. Can be useful if you use Server Components to render data instead of React Nodes.