-
Notifications
You must be signed in to change notification settings - Fork 47k
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
Resolve references to deduped owner objects #30549
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Comparing: 5d19e1c...9dd6563 Critical size changesIncludes critical production bundles, as well as any change greater than 2%:
Significant size changesIncludes any change greater than 0.2%: (No significant changes) |
d13d994
to
5807d57
Compare
) { | ||
handler.value.props = parentObject[key]; | ||
const element: any = handler.value; | ||
switch (key) { |
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.
What about "key" and "type"? E.g. when they're blocked client references. That should be testable even without deduping.
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 my testing, those were just normal client references, using your example but adapted for clientExports
:
"use client";
export const key = "hi";
export const type = "div";
import { key, type as Component } from …
<Component key={key} />
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.
But what if they're not yet resolved? What happens then?
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.
That's a lazy ID that's being resolved, not a reference ID. In other words, the default
case of parseModelString
is not used, and therefore getOutlinedModel
is not called which would call waitForReference
. So this code is not used at all. But maybe you're saying we also need to do this dance elsewhere? 🤔
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.
actually, we get this error: Error: Element type is invalid. Received a promise that resolves to: div. Lazy element type must resolve to a class or function.
and the key
is the stringified client reference proxy function, it seems: "function() {throw new Error(\"Attempted to call key() from the server but key is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.\");}"
This is a follow-up from facebook#30528 to not only handle props (the critical change), but also the owner and stack of a referenced element. Handling stacks here is rather academic because the Flight Server currently does not deduplicate owner stacks. And if they are really identical, we should probably just dedupe the whole element.
5807d57
to
fcb0bf2
Compare
// Assigning the path elements to variables in module scope (here simulated | ||
// with the test's function scope), and rendering a second time, prevents | ||
// the owner of the path elements (i.e. Svg1/Svg2) to be deduped. The owner | ||
// of the path in Svg1 is fully inlined. The owner of the owner of the path | ||
// in Svg2 is Server, which is deduped and replaced with a reference to the | ||
// owner of the owner of the path in Svg1. This nested owner is actually | ||
// Server from the previous render pass, which is kinda broken and libaries | ||
// probably shouldn't generate code like this. This reference can only be | ||
// resolved properly if owners are specifically handled when resolving | ||
// outlined models. |
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.
The first render pass yields:
1:{"name":"Server","env":"Server","key":null,"owner":null}
0:D"$1"
3:{"name":"Svg1","env":"Server","key":null,"owner":"$1"}
2:D"$3"
2:["$","svg",null,{"id":"1","children":[["$","path",null,{},"$3"],["$","path",null,{},"$3"]]},"$3"]
5:{"name":"Svg2","env":"Server","key":null,"owner":"$1"}
4:D"$5"
4:["$","svg",null,{"id":"2","children":["$","path",null,{},"$5"]},"$5"]
0:["$2","$4"]
Notice how the owners are fully deduped to their own chunks.
The second render pass yields:
1:{"name":"Server","env":"Server","key":null,"owner":null}
0:D"$1"
3:{"name":"Svg1","env":"Server","key":null,"owner":"$1"}
2:D"$3"
2:["$","svg",null,{"id":"1","children":[["$","path",null,{},{"name":"Svg1","env":"Server","key":null,"owner":{"name":"Server","env":"Server","key":null,"owner":null}}],["$","path",null,{},"$2:props:children:0:_owner"]]},"$3"]
5:{"name":"Svg2","env":"Server","key":null,"owner":"$1"}
4:D"$5"
4:["$","svg",null,{"id":"2","children":["$","path",null,{},{"name":"Svg2","env":"Server","key":null,"owner":"$2:props:children:0:_owner:owner"}]},"$5"]
0:["$2","$4"]
Notice the $2:props:children:0:_owner:owner
reference that can now be revolved with the provided fix. Before, the reference was $2:props:children:0:4:owner
and could not be resolved, leading to the error: TypeError: Cannot read properties of undefined (reading '$$typeof')
in getOutlinedModel
.
fcb0bf2
to
3f9a7c3
Compare
Previously, the test only covered the change in the react flight server.
This is a follow-up from #30528 to not only handle props (the critical change), but also the owner
and stackof a referenced element.Handling stacks here is rather academic because the Flight Server currently does not deduplicate owner stacks. And if they are really identical, we should probably just dedupe the whole element.EDIT: Removed from the PR.Handling owner objects on the other hand is an actual requirement as reported in vercel/next.js#69545. This problem only affects the stable release channel, as the absence of owner stacks allows for the specific kind of shared owner deduping as demonstrated in the unit test.