-
Notifications
You must be signed in to change notification settings - Fork 46.4k
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] Update stale blocked values in createModelResolver
#28669
Merged
Merged
Changes from 4 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
6e92c9f
Add a test for issue #28595
unstubbable 4099282
Wrap `Posts` in `Suspense` to differentiate test expectations
unstubbable 5d1bdea
Enhance test to show that b835af277 is not a solution
unstubbable c578cff
Update stale blocked values in `createModelResolver`
unstubbable 7d5ad2e
Never outline element props in Flight Server
unstubbable 32c5b0b
Cast `value` to `any`
unstubbable File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -584,6 +584,25 @@ function createModelResolver<T>( | |
} | ||
return value => { | ||
parentObject[key] = value; | ||
|
||
// If this is a tuple that's representing a react element, and the props | ||
// were resolved (4th item, key '3'), the props of `blocked.value` must be | ||
// updated. | ||
if ( | ||
Array.isArray(parentObject) && | ||
key === '3' && | ||
blocked.value && | ||
blocked.value.$$typeof === REACT_ELEMENT_TYPE | ||
) { | ||
blocked.value.props = value; | ||
} | ||
|
||
// If this is the root object for a model reference, where `blocked.value` | ||
// is a stale `null`, the resolved value can be used directly. | ||
if (key === '' && blocked.value === null) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is clever. I think this hold true because if the root is blocked, there can't be any other objects that are also blocked. At least for now. Might not hold in the future but should be ok for now at least. |
||
blocked.value = value; | ||
} | ||
|
||
blocked.deps--; | ||
if (blocked.deps === 0) { | ||
if (chunk.status !== BLOCKED) { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 an interesting observation. For any parentObject where we later might replace it with another object, this problem occurs. I guess that can really just be React Elements for now.
https://github.com/facebook/react/blob/main/packages/react-client/src/ReactFlightClient.js#L1440-L1442
It seems like in principle it could happen to any of the keys inside of it though. Not just the props.
Also, it seems like in theory it should be able to happen even even if the element is not at the root. I think it's problematic to assume that if the parent object is representing the object that's blocked at the root. If the blocked object is an element that itself has further objects below which itself happens to have an array as the parent object then this would incorrectly match that case. So this doesn't seem safe.
At first, I was confused how this could happen but it's really an artifact of the other problem that the props get outlined separately from the element because when we start outlining an object we've seen everything inside of it before which causes us to outline everything inside of it too which is inefficient because we might not ever see them again outside of this particular object. Which happens to props and elements.
This should ideally have some more clever strategy.
However, one thing we could do is mark props objects inside elements in the outlining as never outlined. E.g. give it id
-2
or something. That way they're never outline independently from the element that they're apart of. That way this particular scenario doesn't happen. (Although ideally the parser would be resilient to it.)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 like the idea of not outlining the props. The condition for updating them in the blocked element felt brittle to me. I've implemented the suggested change in 7d5ad2e.
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 this doesn't do (yet), is prevent the objects inside of the props from being outlined. Is this something you would want to see being done too? To fix the issue, this wouldn't be needed. It might maybe be useful to keep outlining them when the same object is passed to different elements as part of the props. Although it would of course be even better to detect exactly this case, and only then outline them. Not sure if we want to add more complexity for this though.