Skip to content
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

Don't modify keyPath until right before recursive renderNode call #27366

Merged
merged 1 commit into from
Sep 13, 2023

Conversation

acdlite
Copy link
Collaborator

@acdlite acdlite commented Sep 13, 2023

Currently, if a component suspends, the keyPath has already been modified to include the identity of the component itself; the path is set before the component body is called (akin to the begin phase in Fiber). An accidental consequence is that when the promise resolves and component is retried, the identity gets appended to the keyPath again, leading to a duplicate node in the path.

To address this, we should only modify contexts after any code that may suspend. For maximum safety, this should occur as late as possible: right before the recursive renderNode call, before the children are rendered.

I did not add a test yet because there's no feature that currently observes it, but I do have tests in my other WIP PR for useFormState: #27321

@facebook-github-bot facebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Sep 13, 2023
// TODO: Should we pass keyPath as an argument and set that here, instead of
// setting it in the caller? It would reduce repetition, but it would be also
// be a redundant assignment in some cases, because not all node types
// contribute to the key path.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sebmarkbage Any thoughts?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we shouldn't pass it as an argument. Not all paths set the formatContext or legacyContext etc neither. Only the ones that do set it (and reset it, unless there's an error).

Maybe childIndex also is not quite necessary because not all paths change the childIndex.

@react-sizebot
Copy link

react-sizebot commented Sep 13, 2023

Comparing: 7a3cb8f...e03c96d

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.min.js = 166.38 kB 166.38 kB = 52.08 kB 52.08 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js = 175.64 kB 175.64 kB = 54.88 kB 54.88 kB
facebook-www/ReactDOM-prod.classic.js = 571.59 kB 571.59 kB = 100.62 kB 100.62 kB
facebook-www/ReactDOM-prod.modern.js = 555.37 kB 555.37 kB = 97.74 kB 97.74 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable-semver/react-server/cjs/react-server.production.min.js +0.92% 27.02 kB 27.27 kB +0.66% 9.06 kB 9.12 kB
oss-stable/react-server/cjs/react-server.production.min.js +0.92% 27.02 kB 27.27 kB +0.66% 9.06 kB 9.12 kB
oss-experimental/react-server/cjs/react-server.production.min.js +0.86% 29.13 kB 29.38 kB +0.59% 9.65 kB 9.70 kB
facebook-www/ReactDOMServer-prod.classic.js +0.73% 155.59 kB 156.73 kB +0.56% 28.46 kB 28.61 kB
facebook-www/ReactDOMServer-prod.modern.js +0.67% 154.69 kB 155.73 kB +0.52% 28.22 kB 28.37 kB
facebook-www/ReactDOMServerStreaming-prod.modern.js +0.66% 156.83 kB 157.88 kB +0.49% 29.18 kB 29.33 kB
oss-stable-semver/react-server/cjs/react-server.development.js +0.66% 154.32 kB 155.33 kB +0.41% 38.00 kB 38.15 kB
oss-stable/react-server/cjs/react-server.development.js +0.66% 154.32 kB 155.33 kB +0.41% 38.00 kB 38.15 kB
oss-experimental/react-server/cjs/react-server.development.js +0.61% 165.82 kB 166.84 kB +0.31% 40.84 kB 40.97 kB
facebook-www/ReactDOMServerStreaming-dev.modern.js +0.41% 346.95 kB 348.36 kB +0.34% 77.32 kB 77.58 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.browser.production.min.js +0.41% 62.17 kB 62.42 kB +0.26% 18.82 kB 18.87 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.browser.production.min.js +0.41% 62.20 kB 62.45 kB +0.26% 18.84 kB 18.89 kB
oss-stable-semver/react-dom/umd/react-dom-server-legacy.browser.production.min.js +0.40% 62.33 kB 62.58 kB +0.27% 19.10 kB 19.16 kB
oss-stable/react-dom/umd/react-dom-server-legacy.browser.production.min.js +0.40% 62.36 kB 62.61 kB +0.27% 19.13 kB 19.18 kB
facebook-www/ReactDOMServer-dev.modern.js +0.40% 351.75 kB 353.17 kB +0.34% 78.47 kB 78.73 kB
oss-stable-semver/react-dom/cjs/react-dom-server.browser.production.min.js +0.40% 63.15 kB 63.40 kB +0.38% 19.74 kB 19.81 kB
oss-stable/react-dom/cjs/react-dom-server.browser.production.min.js +0.40% 63.17 kB 63.42 kB +0.37% 19.76 kB 19.83 kB
oss-stable-semver/react-dom/umd/react-dom-server.browser.production.min.js +0.40% 63.29 kB 63.54 kB +0.42% 19.96 kB 20.04 kB
oss-stable/react-dom/umd/react-dom-server.browser.production.min.js +0.39% 63.31 kB 63.56 kB +0.42% 19.98 kB 20.06 kB
facebook-www/ReactDOMServer-dev.classic.js +0.39% 359.18 kB 360.59 kB +0.33% 80.12 kB 80.38 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.browser.production.min.js +0.38% 65.59 kB 65.85 kB +0.27% 19.96 kB 20.01 kB
oss-experimental/react-dom/umd/react-dom-server-legacy.browser.production.min.js +0.38% 65.75 kB 66.00 kB +0.33% 20.32 kB 20.39 kB
oss-stable-semver/react-dom/cjs/react-dom-server.bun.production.min.js +0.38% 65.47 kB 65.72 kB +0.33% 20.13 kB 20.20 kB
oss-stable/react-dom/cjs/react-dom-server.bun.production.min.js +0.38% 65.50 kB 65.75 kB +0.33% 20.16 kB 20.22 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.node.production.min.js +0.37% 67.05 kB 67.30 kB +0.26% 20.43 kB 20.48 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.node.production.min.js +0.37% 67.08 kB 67.33 kB +0.26% 20.45 kB 20.51 kB
oss-stable-semver/react-dom/cjs/react-dom-server.edge.production.min.js +0.37% 67.37 kB 67.62 kB +0.39% 21.17 kB 21.25 kB
oss-stable/react-dom/cjs/react-dom-server.edge.production.min.js +0.37% 67.40 kB 67.65 kB +0.39% 21.19 kB 21.28 kB
oss-stable-semver/react-dom/cjs/react-dom-server.node.production.min.js +0.37% 67.43 kB 67.68 kB +0.34% 21.19 kB 21.26 kB
oss-stable/react-dom/cjs/react-dom-server.node.production.min.js +0.37% 67.46 kB 67.71 kB +0.34% 21.21 kB 21.29 kB
oss-experimental/react-dom/cjs/react-dom-server.browser.production.min.js +0.37% 68.46 kB 68.71 kB +0.22% 21.06 kB 21.10 kB
oss-experimental/react-dom/umd/react-dom-server.browser.production.min.js +0.37% 68.59 kB 68.84 kB +0.27% 21.30 kB 21.35 kB
oss-experimental/react-dom/cjs/react-dom-server.bun.production.min.js +0.36% 69.14 kB 69.39 kB +0.31% 21.34 kB 21.41 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.node.production.min.js +0.35% 70.73 kB 70.98 kB +0.25% 21.63 kB 21.68 kB
oss-experimental/react-dom/cjs/react-dom-server.edge.production.min.js +0.34% 72.91 kB 73.16 kB +0.26% 22.55 kB 22.60 kB
oss-experimental/react-dom/cjs/react-dom-server.node.production.min.js +0.34% 73.19 kB 73.44 kB +0.30% 22.71 kB 22.77 kB
oss-stable-semver/react-dom/cjs/react-dom-server.bun.development.js +0.30% 339.86 kB 340.87 kB +0.20% 76.92 kB 77.07 kB
oss-stable/react-dom/cjs/react-dom-server.bun.development.js +0.30% 339.88 kB 340.90 kB +0.20% 76.94 kB 77.10 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.browser.development.js +0.30% 342.42 kB 343.43 kB +0.20% 77.35 kB 77.50 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.browser.development.js +0.30% 342.44 kB 343.46 kB +0.20% 77.38 kB 77.53 kB
oss-stable-semver/react-dom/cjs/react-dom-server.browser.development.js +0.30% 342.63 kB 343.65 kB +0.20% 77.82 kB 77.97 kB
oss-stable/react-dom/cjs/react-dom-server.browser.development.js +0.30% 342.66 kB 343.67 kB +0.20% 77.84 kB 78.00 kB
oss-stable-semver/react-dom/cjs/react-dom-server.edge.development.js +0.30% 343.04 kB 344.06 kB +0.19% 77.94 kB 78.09 kB
oss-stable/react-dom/cjs/react-dom-server.edge.development.js +0.30% 343.07 kB 344.08 kB +0.19% 77.97 kB 78.12 kB
oss-stable-semver/react-dom/umd/react-dom-server-legacy.browser.development.js +0.30% 359.00 kB 360.06 kB +0.16% 78.22 kB 78.35 kB
oss-stable/react-dom/umd/react-dom-server-legacy.browser.development.js +0.30% 359.03 kB 360.09 kB +0.16% 78.25 kB 78.37 kB
oss-stable-semver/react-dom/umd/react-dom-server.browser.development.js +0.30% 359.22 kB 360.28 kB +0.16% 78.70 kB 78.82 kB
oss-stable/react-dom/umd/react-dom-server.browser.development.js +0.30% 359.25 kB 360.31 kB +0.16% 78.73 kB 78.85 kB
oss-stable-semver/react-dom/cjs/react-dom-server.node.development.js +0.29% 344.11 kB 345.13 kB +0.20% 77.85 kB 78.00 kB
oss-stable/react-dom/cjs/react-dom-server.node.development.js +0.29% 344.14 kB 345.15 kB +0.19% 77.88 kB 78.03 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.node.development.js +0.29% 344.32 kB 345.34 kB +0.20% 77.81 kB 77.96 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.node.development.js +0.29% 344.35 kB 345.36 kB +0.20% 77.83 kB 77.99 kB
oss-experimental/react-dom/cjs/react-dom-server.bun.development.js +0.28% 357.04 kB 358.05 kB +0.16% 80.61 kB 80.75 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.browser.development.js +0.28% 359.59 kB 360.61 kB +0.16% 81.06 kB 81.20 kB
oss-experimental/react-dom/umd/react-dom-server-legacy.browser.development.js +0.28% 376.87 kB 377.93 kB +0.15% 81.94 kB 82.07 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.node.development.js +0.28% 361.50 kB 362.52 kB +0.16% 81.52 kB 81.65 kB
oss-experimental/react-dom/cjs/react-dom-server.browser.development.js +0.28% 365.64 kB 366.66 kB +0.15% 81.79 kB 81.91 kB
oss-experimental/react-dom/cjs/react-dom-server.edge.development.js +0.28% 366.05 kB 367.07 kB +0.16% 81.91 kB 82.04 kB
oss-experimental/react-dom/umd/react-dom-server.browser.development.js +0.28% 383.21 kB 384.27 kB +0.15% 82.67 kB 82.80 kB
oss-experimental/react-dom/cjs/react-dom-server.node.development.js +0.28% 366.94 kB 367.95 kB +0.15% 82.11 kB 82.23 kB

Generated by 🚫 dangerJS against e03c96d

Currently, if a component suspends, the keyPath has already been modified to
include the identity of the component itself; the path is set before the
component body is called (akin to the begin phase in Fiber). An accidental
consequence is that when the promise resolves and component is retried, the
identity gets appended to the keyPath again, leading to a duplicate node in
the path.

To address this, we should only modify contexts after any code that may suspend.
For maximum safety, this should occur as late as possible: right before the
recursive renderNode call, before the children are rendered.
@acdlite acdlite force-pushed the keypath-after-suspend branch from 05435b7 to e03c96d Compare September 13, 2023 01:27
@acdlite acdlite merged commit d07921e into facebook:main Sep 13, 2023
2 checks passed
github-actions bot pushed a commit that referenced this pull request Sep 13, 2023
…7366)

Currently, if a component suspends, the keyPath has already been
modified to include the identity of the component itself; the path is
set before the component body is called (akin to the begin phase in
Fiber). An accidental consequence is that when the promise resolves and
component is retried, the identity gets appended to the keyPath again,
leading to a duplicate node in the path.

To address this, we should only modify contexts after any code that may
suspend. For maximum safety, this should occur as late as possible:
right before the recursive renderNode call, before the children are
rendered.

I did not add a test yet because there's no feature that currently
observes it, but I do have tests in my other WIP PR for useFormState:
#27321

DiffTrain build for [d07921e](d07921e)
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
…cebook#27366)

Currently, if a component suspends, the keyPath has already been
modified to include the identity of the component itself; the path is
set before the component body is called (akin to the begin phase in
Fiber). An accidental consequence is that when the promise resolves and
component is retried, the identity gets appended to the keyPath again,
leading to a duplicate node in the path.

To address this, we should only modify contexts after any code that may
suspend. For maximum safety, this should occur as late as possible:
right before the recursive renderNode call, before the children are
rendered.

I did not add a test yet because there's no feature that currently
observes it, but I do have tests in my other WIP PR for useFormState:
facebook#27321
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
…7366)

Currently, if a component suspends, the keyPath has already been
modified to include the identity of the component itself; the path is
set before the component body is called (akin to the begin phase in
Fiber). An accidental consequence is that when the promise resolves and
component is retried, the identity gets appended to the keyPath again,
leading to a duplicate node in the path.

To address this, we should only modify contexts after any code that may
suspend. For maximum safety, this should occur as late as possible:
right before the recursive renderNode call, before the children are
rendered.

I did not add a test yet because there's no feature that currently
observes it, but I do have tests in my other WIP PR for useFormState:
#27321

DiffTrain build for commit d07921e.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed React Core Team Opened by a member of the React Core Team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants