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

Prevent stale legacy root from clearing a container (DRAFT) #18792

Merged
merged 2 commits into from
Apr 30, 2020

Conversation

bvaughn
Copy link
Contributor

@bvaughn bvaughn commented Apr 30, 2020

Fixes the legacy root bug we observed after the recent sync (caused by #18730).

Alternate fix to #18781.

@facebook-github-bot facebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Apr 30, 2020
@codesandbox-ci
Copy link

codesandbox-ci bot commented Apr 30, 2020

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit b6312ff:

Sandbox Source
adoring-bose-lwx7f Configuration

@sizebot
Copy link

sizebot commented Apr 30, 2020

Details of bundled changes.

Comparing: 53d68b3...b6312ff

react-test-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-test-renderer.development.js +0.1% +0.1% 572.75 KB 573.35 KB 119.56 KB 119.7 KB UMD_DEV
react-test-renderer.production.min.js 🔺+0.1% 🔺+0.1% 74.61 KB 74.72 KB 22.77 KB 22.79 KB UMD_PROD
react-test-renderer-shallow.development.js 0.0% -0.0% 39.07 KB 39.07 KB 9.55 KB 9.55 KB UMD_DEV
react-test-renderer-shallow.production.min.js 0.0% -0.1% 12.74 KB 12.74 KB 3.97 KB 3.97 KB UMD_PROD
react-test-renderer.development.js +0.1% +0.1% 546.09 KB 546.67 KB 118.18 KB 118.31 KB NODE_DEV
react-test-renderer.production.min.js 🔺+0.1% 🔺+0.1% 74.41 KB 74.52 KB 22.44 KB 22.47 KB NODE_PROD
ReactTestRenderer-dev.js +0.1% +0.1% 573.08 KB 573.7 KB 121.46 KB 121.63 KB FB_WWW_DEV

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom.profiling.min.js +0.1% +0.1% 128.91 KB 129.02 KB 40.31 KB 40.33 KB NODE_PROFILING
ReactDOM-dev.js +0.1% +0.1% 1013.64 KB 1014.27 KB 225.98 KB 226.14 KB FB_WWW_DEV
ReactDOM-prod.js 🔺+0.1% 🔺+0.1% 421.21 KB 421.61 KB 73.87 KB 73.92 KB FB_WWW_PROD
ReactDOMServer-prod.js 0.0% -0.0% 52.03 KB 52.03 KB 12.54 KB 12.53 KB FB_WWW_PROD
ReactDOM-profiling.js +0.1% +0.1% 432.11 KB 432.51 KB 75.7 KB 75.76 KB FB_WWW_PROFILING
react-dom-unstable-fizz.node.development.js 0.0% -0.1% 5.51 KB 5.51 KB 1.83 KB 1.83 KB NODE_DEV
ReactDOMTesting-dev.js +0.1% +0.1% 909.54 KB 910.17 KB 203.08 KB 203.24 KB FB_WWW_DEV
ReactDOMTesting-prod.js 🔺+0.1% 🔺+0.1% 378.56 KB 378.96 KB 69.13 KB 69.19 KB FB_WWW_PROD
ReactDOMTesting-profiling.js +0.1% +0.1% 378.56 KB 378.96 KB 69.13 KB 69.19 KB FB_WWW_PROFILING
react-dom-server.node.development.js 0.0% -0.0% 153.88 KB 153.88 KB 40.75 KB 40.75 KB NODE_DEV
react-dom.development.js +0.1% +0.1% 941.62 KB 942.22 KB 206.09 KB 206.23 KB UMD_DEV
react-dom-server.browser.development.js 0.0% -0.0% 162.17 KB 162.17 KB 41.27 KB 41.26 KB UMD_DEV
react-dom.production.min.js 🔺+0.1% 🔺+0.1% 124.7 KB 124.81 KB 39.92 KB 39.96 KB UMD_PROD
ReactDOMForked-dev.js +0.1% +0.1% 1008.93 KB 1009.55 KB 224.65 KB 224.79 KB FB_WWW_DEV
react-dom-server.browser.production.min.js 0.0% -0.0% 23.4 KB 23.4 KB 8.61 KB 8.61 KB UMD_PROD
react-dom.profiling.min.js +0.1% +0.1% 128.58 KB 128.68 KB 41.07 KB 41.1 KB UMD_PROFILING
ReactDOMForked-prod.js 🔺+0.1% 🔺+0.1% 422.55 KB 422.95 KB 74.03 KB 74.08 KB FB_WWW_PROD
react-dom.development.js +0.1% +0.1% 896.48 KB 897.06 KB 203.55 KB 203.7 KB NODE_DEV
ReactDOMForked-profiling.js +0.1% +0.1% 432.89 KB 433.29 KB 75.76 KB 75.81 KB FB_WWW_PROFILING
react-dom.production.min.js 🔺+0.1% 🔺+0.1% 124.89 KB 125 KB 39.03 KB 39.06 KB NODE_PROD

react-art

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactART-dev.js +0.1% +0.2% 598.59 KB 599.22 KB 126.2 KB 126.39 KB FB_WWW_DEV
ReactART-prod.js 🔺+0.1% 🔺+0.1% 242.09 KB 242.33 KB 41.34 KB 41.39 KB FB_WWW_PROD
react-art.development.js +0.1% +0.1% 660.17 KB 660.76 KB 139.25 KB 139.41 KB UMD_DEV
react-art.production.min.js 🔺+0.1% 🔺+0.2% 110.87 KB 110.98 KB 33.6 KB 33.66 KB UMD_PROD
react-art.development.js +0.1% +0.1% 563.38 KB 563.97 KB 121.74 KB 121.89 KB NODE_DEV
react-art.production.min.js 🔺+0.1% 🔺+0.1% 75.82 KB 75.92 KB 22.8 KB 22.83 KB NODE_PROD

react-native-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactNativeRenderer-dev.js +0.1% +0.1% 662.07 KB 662.69 KB 142.35 KB 142.49 KB RN_FB_DEV
ReactNativeRenderer-prod.js 🔺+0.1% 🔺+0.2% 272.14 KB 272.38 KB 47 KB 47.07 KB RN_FB_PROD
ReactNativeRenderer-profiling.js +0.1% +0.1% 283.58 KB 283.82 KB 49.22 KB 49.26 KB RN_FB_PROFILING
ReactFabric-dev.js +0.1% +0.1% 638.3 KB 638.93 KB 137 KB 137.14 KB RN_OSS_DEV
ReactFabric-prod.js 🔺+0.1% 🔺+0.1% 263.91 KB 264.15 KB 45.45 KB 45.5 KB RN_OSS_PROD
ReactFabric-profiling.js +0.1% +0.1% 275.33 KB 275.58 KB 47.65 KB 47.7 KB RN_OSS_PROFILING
ReactFabric-dev.js +0.1% +0.1% 643.12 KB 643.74 KB 137.77 KB 137.91 KB RN_FB_DEV
ReactFabric-prod.js 🔺+0.1% 🔺+0.1% 264.06 KB 264.31 KB 45.48 KB 45.53 KB RN_FB_PROD
ReactNativeRenderer-dev.js +0.1% +0.1% 657.26 KB 657.89 KB 141.56 KB 141.71 KB RN_OSS_DEV
ReactFabric-profiling.js +0.1% +0.1% 275.48 KB 275.72 KB 47.68 KB 47.72 KB RN_FB_PROFILING
ReactNativeRenderer-prod.js 🔺+0.1% 🔺+0.2% 271.99 KB 272.23 KB 46.97 KB 47.04 KB RN_OSS_PROD
ReactNativeRenderer-profiling.js +0.1% +0.1% 283.44 KB 283.68 KB 49.19 KB 49.23 KB RN_OSS_PROFILING

react-reconciler

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-reconciler.development.js +0.1% +0.1% 606.73 KB 607.31 KB 128.71 KB 128.86 KB NODE_DEV
react-reconciler.production.min.js 🔺+0.1% 🔺+0.2% 81.5 KB 81.61 KB 24.14 KB 24.19 KB NODE_PROD

Size changes (experimental)

Generated by 🚫 dangerJS against b6312ff

@sizebot
Copy link

sizebot commented Apr 30, 2020

Details of bundled changes.

Comparing: 53d68b3...b6312ff

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom.production.min.js 🔺+0.1% 🔺+0.1% 119.98 KB 120.09 KB 37.63 KB 37.66 KB NODE_PROD
react-dom-test-utils.development.js 0.0% -0.0% 75.22 KB 75.22 KB 20.15 KB 20.15 KB UMD_DEV
ReactDOMTesting-profiling.js +0.1% +0.1% 390.42 KB 390.82 KB 71.13 KB 71.17 KB FB_WWW_PROFILING
react-dom.profiling.min.js +0.1% +0.1% 123.88 KB 123.98 KB 38.79 KB 38.82 KB NODE_PROFILING
ReactDOMServer-prod.js 0.0% -0.0% 52.92 KB 52.92 KB 12.72 KB 12.72 KB FB_WWW_PROD
ReactDOMForked-dev.js +0.1% +0.1% 1.01 MB 1.01 MB 230.19 KB 230.33 KB FB_WWW_DEV
ReactDOMForked-prod.js 🔺+0.1% 🔺+0.1% 434.01 KB 434.41 KB 76.02 KB 76.07 KB FB_WWW_PROD
react-dom.development.js +0.1% +0.1% 907.74 KB 908.34 KB 199.63 KB 199.77 KB UMD_DEV
ReactDOMForked-profiling.js +0.1% +0.1% 444.42 KB 444.81 KB 77.77 KB 77.82 KB FB_WWW_PROFILING
react-dom.production.min.js 🔺+0.1% 🔺+0.1% 119.86 KB 119.97 KB 38.42 KB 38.45 KB UMD_PROD
react-dom.profiling.min.js +0.1% +0.1% 123.63 KB 123.74 KB 39.62 KB 39.66 KB UMD_PROFILING
ReactDOMTesting-dev.js +0.1% +0.1% 935.34 KB 935.96 KB 208.61 KB 208.76 KB FB_WWW_DEV
react-dom.development.js +0.1% +0.1% 864.05 KB 864.63 KB 197.1 KB 197.24 KB NODE_DEV
ReactDOMTesting-prod.js 🔺+0.1% 🔺+0.1% 390.42 KB 390.82 KB 71.13 KB 71.17 KB FB_WWW_PROD
ReactDOM-dev.js +0.1% +0.1% 1.01 MB 1.02 MB 231.53 KB 231.67 KB FB_WWW_DEV
ReactDOM-prod.js 🔺+0.1% 🔺+0.1% 432.68 KB 433.08 KB 75.87 KB 75.93 KB FB_WWW_PROD
react-dom-unstable-fizz.node.development.js 0.0% -0.1% 5.5 KB 5.5 KB 1.83 KB 1.82 KB NODE_DEV
ReactDOM-profiling.js +0.1% +0.1% 443.64 KB 444.03 KB 77.72 KB 77.77 KB FB_WWW_PROFILING
react-dom-server.browser.development.js 0.0% -0.0% 154.86 KB 154.86 KB 39.47 KB 39.47 KB UMD_DEV
react-dom-server.browser.development.js 0.0% -0.0% 145.71 KB 145.71 KB 38.7 KB 38.7 KB NODE_DEV
react-dom-unstable-fizz.browser.production.min.js 0.0% -0.1% 1.19 KB 1.19 KB 698 B 697 B UMD_PROD

react-native-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactNativeRenderer-dev.js +0.1% +0.1% 657.25 KB 657.88 KB 141.55 KB 141.7 KB RN_OSS_DEV
ReactNativeRenderer-prod.js 🔺+0.1% 🔺+0.2% 271.98 KB 272.22 KB 46.96 KB 47.04 KB RN_OSS_PROD
ReactNativeRenderer-profiling.js +0.1% +0.1% 283.42 KB 283.67 KB 49.18 KB 49.22 KB RN_OSS_PROFILING
ReactFabric-dev.js +0.1% +0.1% 638.29 KB 638.92 KB 136.99 KB 137.13 KB RN_OSS_DEV
ReactFabric-prod.js 🔺+0.1% 🔺+0.1% 263.9 KB 264.14 KB 45.44 KB 45.49 KB RN_OSS_PROD
ReactFabric-profiling.js +0.1% +0.1% 275.32 KB 275.56 KB 47.64 KB 47.69 KB RN_OSS_PROFILING

react-art

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-art.development.js +0.1% +0.1% 540.06 KB 540.64 KB 116.81 KB 116.95 KB NODE_DEV
react-art.production.min.js 🔺+0.1% 🔺+0.2% 72.5 KB 72.61 KB 21.79 KB 21.83 KB NODE_PROD
ReactART-dev.js +0.1% +0.1% 608.61 KB 609.23 KB 128.23 KB 128.42 KB FB_WWW_DEV
ReactART-prod.js 🔺+0.1% 🔺+0.1% 249.12 KB 249.37 KB 42.59 KB 42.63 KB FB_WWW_PROD
react-art.development.js +0.1% +0.1% 635.84 KB 636.43 KB 134.38 KB 134.53 KB UMD_DEV
react-art.production.min.js 🔺+0.1% 🔺+0.2% 107.5 KB 107.61 KB 32.63 KB 32.68 KB UMD_PROD

react-test-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-test-renderer-shallow.development.js 0.0% -0.0% 39.05 KB 39.05 KB 9.54 KB 9.54 KB UMD_DEV
react-test-renderer-shallow.production.min.js 0.0% -0.1% 12.73 KB 12.73 KB 3.97 KB 3.96 KB UMD_PROD
react-test-renderer.development.js +0.1% +0.1% 546.06 KB 546.65 KB 118.17 KB 118.3 KB NODE_DEV
react-test-renderer.production.min.js 🔺+0.1% 🔺+0.1% 74.39 KB 74.5 KB 22.42 KB 22.46 KB NODE_PROD
ReactTestRenderer-dev.js +0.1% +0.1% 573.07 KB 573.69 KB 121.46 KB 121.63 KB FB_WWW_DEV
react-test-renderer.development.js +0.1% +0.1% 572.72 KB 573.32 KB 119.54 KB 119.69 KB UMD_DEV
react-test-renderer.production.min.js 🔺+0.1% 🔺+0.1% 74.59 KB 74.7 KB 22.75 KB 22.77 KB UMD_PROD

react-reconciler

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-reconciler.development.js +0.1% +0.1% 581.05 KB 581.63 KB 123.31 KB 123.45 KB NODE_DEV
react-reconciler.production.min.js 🔺+0.1% 🔺+0.1% 77.77 KB 77.88 KB 23.1 KB 23.12 KB NODE_PROD

Size changes (stable)

Generated by 🚫 dangerJS against b6312ff

@bvaughn
Copy link
Contributor Author

bvaughn commented Apr 30, 2020

The thing I'm not able to repro in a test yet (but that we're seeing within Facebook) is completeWork() running for the initial root after the new root has been committed. The sequence in both cases is:

unmountComponentAtNode() root 1
unmountComponentAtNode() -> unbatched update root 1
legacyRenderSubtreeIntoContainer() update root 1

legacyRenderSubtreeIntoContainer() mount root 2
completeWork() Marking root to be cleared root 2
clearContainer() root 2

completeWork() root 1 // I can't reproduce this in a test though

@trueadm
Copy link
Contributor

trueadm commented Apr 30, 2020

@bvaughn Nice findings. It might have something to do with the fact that when we call unmountComponentAtNode, we schedule a discrete event on root 1. If you call focus later (after we mount root 2), it flushes the pending scheduled work in root 1, causing it to render again, thus causing it to hit the completion phase on root 1.

@bvaughn
Copy link
Contributor Author

bvaughn commented Apr 30, 2020

I think I got it!

@bvaughn
Copy link
Contributor Author

bvaughn commented Apr 30, 2020

Thanks @trueadm, that comment was very helpful in helping me realize the thing I was missing in my test.

@bvaughn bvaughn marked this pull request as ready for review April 30, 2020 21:34
@bvaughn bvaughn force-pushed the fix-clearContainer-legacy-bug branch from e486c16 to 6366862 Compare April 30, 2020 21:37
@bvaughn bvaughn force-pushed the fix-clearContainer-legacy-bug branch from 6366862 to b6312ff Compare April 30, 2020 21:37
@trueadm
Copy link
Contributor

trueadm commented Apr 30, 2020

This is awesome! I wonder if we use createRoot do we have a similar issue?

@bvaughn
Copy link
Contributor Author

bvaughn commented Apr 30, 2020

I wonder if we use createRoot do we have a similar issue?

No, I don't think so. This only applies to legacy roots.

Also if you tried to create a new root (createRoot(container)) before the old one finished flushing the unmount, we warn about it.

// can sometimes cause the container to be cleared after the new render.
const containerInfo = fiberRoot.containerInfo;
const legacyRootContainer =
containerInfo == null ? null : containerInfo._reactRootContainer;
Copy link
Contributor

Choose a reason for hiding this comment

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

The only reason I opted to do this in the renderer in my PR was because this seemed host-specific. I see you reasoning for doing it earlier though, it avoids doing unecessary work before it's too late. Another approach could be to expose a host config function that does this check (as this is only related to the legacy roots, which doesn't necessarily affect other renderers) that can do this check for us.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I guess it is DOM renderer specific (then again, so is clearContainer itself really). I just thought it would be better to do this check earlier rather than in the perf-sensitive commit phase. Will be great to remove this check entirely eventually.

Copy link
Contributor

@trueadm trueadm left a comment

Choose a reason for hiding this comment

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

I'm more than happy with this change - awesome stuff! My comment can be worked on in the future as a TODO, as I don't see it blocking this.

@bvaughn
Copy link
Contributor Author

bvaughn commented Apr 30, 2020

Thanks for the review, Dominic. I'm going to merge this to hopefully unblock you on the sync. (Let me know if you need someone to take over the sync btw.)

I can follow up later if there are concerns or suggested changes from others.

@bvaughn bvaughn merged commit ac533fd into facebook:master Apr 30, 2020
@bvaughn bvaughn deleted the fix-clearContainer-legacy-bug branch April 30, 2020 22:56

ReactDOM.render(<NewApp />, container);

// Calling focus again will flush previously scheduled discerete work for the old root-
Copy link
Collaborator

@sebmarkbage sebmarkbage Apr 30, 2020

Choose a reason for hiding this comment

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

Something is off here because there's no concept of "discrete work" for legacy mode (and I'm removing it for CM too). At least there shouldn't be. Maybe for passive effects but that doesn't kick in here.

There's only Sync work in legacy mode.

What do you mean by discrete work here? It might that something is misnamed in a method or something.

It could also indicate a bigger bug in legacy mode.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@sebmarkbage This comment was based on Dominic's comment above.

Copy link
Contributor

Choose a reason for hiding this comment

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

@sebmarkbage Upon calling scheduleUpdateOnFiber, you add an entry to rootsWithPendingDiscreteUpdates which is the problem in this issue. I'd assume your work of removing the concept of discrete work didn't include this particulat code-path?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I haven't landed that part yet. Still blocked on some stuff.

Concretely I'm worried that we've accidentally landed "discrete" semantics in legacy mode at some point. I.e. some subtle breaking change.

// can sometimes cause the container to be cleared after the new render.
const containerInfo = fiberRoot.containerInfo;
const legacyRootContainer =
containerInfo == null ? null : containerInfo._reactRootContainer;
Copy link
Collaborator

Choose a reason for hiding this comment

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

This field is DOM specific. Not sure what happens to this code in RN. I guess it would just schedule a Snapshot which is currently a noop?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. RN doesn't have a way to clear its container anyway (since there's no native API).

Copy link
Contributor

Choose a reason for hiding this comment

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

I mentioned this too in my previous comment. It's something we can address in a follow up.

Copy link
Contributor Author

@bvaughn bvaughn Apr 30, 2020

Choose a reason for hiding this comment

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

Even though it is kind of renderer-specific, I don't know if I agree that moving it into the host config (and commit phase) is a good follow up change. Happy to talk more about it though. I agree that having a renderer-specific legacy check here isn't great either. Just felt less bad than incorrectly scheduling commit phase work.

Copy link
Contributor

@trueadm trueadm Apr 30, 2020

Choose a reason for hiding this comment

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

Yeah, it sucks either way. I guess a complete phase legacy check is less bad as it has less overhead than my commit phase fix and we know we'll likely be removing it in the near future.

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.

5 participants