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

[Bugfix] Incorrect return pointer on deleted fiber #20942

Closed
wants to merge 2 commits into from

Conversation

acdlite
Copy link
Collaborator

@acdlite acdlite commented Mar 5, 2021

Regression test ported from #20932.

I think now that I know the bug I can write a more focused test, but I'll keep this one too.

Based on facebook#20932

Co-Authored-By: Dan Abramov <[email protected]>
@facebook-github-bot facebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Mar 5, 2021
When deleting a host node, we follow the return path to find the
nearest mounted host parent. Which means the return pointer of the
deleted tree must be correct in the mutation phase.
@@ -1964,6 +1964,10 @@ function commitMutationEffects_begin(
if (deletions !== null) {
for (let i = 0; i < deletions.length; i++) {
const childToDelete = deletions[i];
// When deleting a host node, we follow the return path to find the
// neartest mounted host parent. Which means the return pointer of
// the deleted tree must be correct.
Copy link
Collaborator

@sebmarkbage sebmarkbage Mar 5, 2021

Choose a reason for hiding this comment

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

Instead of doing that on-demand, we could do that eagerly here and then pass in the parent.

It's likely to be at least one DOM node deleted. If it's more than one, then it's unnecessary to backtrack more than once. We meant to do that optimization for that reason at some point anyway.

Or better yet, keep track of it on the stack since we're traversing through the parent anyway.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We don't use recursion for this function yet (was reverted because of slow down in open source build) so it'd have to be a virtual stack.

So I'll go with option 1 (eagerly find the current parent) for now and leave a TODO for when this recursive traversal is converted to use the JS stack.

@sizebot
Copy link

sizebot commented Mar 5, 2021

Comparing: ee43263...01ece92

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 = 122.55 kB 122.56 kB = 39.48 kB 39.48 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js = 129.13 kB 129.14 kB = 41.53 kB 41.53 kB
facebook-www/ReactDOM-prod.classic.js +0.01% 406.12 kB 406.18 kB = 75.38 kB 75.39 kB
facebook-www/ReactDOM-prod.modern.js +0.01% 394.47 kB 394.52 kB = 73.49 kB 73.49 kB
facebook-www/ReactDOMForked-prod.classic.js +0.01% 406.13 kB 406.19 kB = 75.38 kB 75.39 kB

Significant size changes

Includes any change greater than 0.2%:

(No significant changes)

Generated by 🚫 dangerJS against 01ece92

// When deleting a host node, we follow the return path to find the
// neartest mounted host parent. Which means the return pointer of
// the deleted tree must be correct.
childToDelete.return = fiber;
Copy link
Contributor

Choose a reason for hiding this comment

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

In my testing, the return pointer was not null the first time something was deleted. It ended up being null later b'c we tried to delete the same thing twice.

I'm wondering if the repro I had (the larger one that involved Feed and was more touch and go) is a different problem.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It’s always non-null at this particular location, but before the fix it would sometimes point to the wrong alternate. Does that describe what you were seeing?

Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, pretty sure I was seeing a double deletion, and the pointer was cleared in detach mutation.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

You're right, I checked again and it was a double deletion.

Fix here: #20942

acdlite added a commit to acdlite/react that referenced this pull request Mar 7, 2021
Alternate fix to facebook#20942

There was already a TODO to make this change, but at the time I left it,
I couldn't think of a way that it would actually cause a bug, and I was
hesistant to change something without fully understanding the
ramifications. This was during a time when we were hunting down a
different bug, so we were especially risk averse.

What I should have done in retrospect is put the change behind a flag
and tried rolling it out once the other bug had been flushed out.

OTOH, now we have a regression test, which wouldn't have otherwise, and
the bug it caused rarely fired in production.
@acdlite acdlite marked this pull request as draft March 7, 2021 06:58
@acdlite
Copy link
Collaborator Author

acdlite commented Mar 7, 2021

Switched back to draft status because I found the "real" fix in #20948

I still want to land the change suggested here, though: #20942 (comment)

acdlite added a commit that referenced this pull request Mar 7, 2021
* Add failing regression test

Based on #20932

Co-Authored-By: Dan Abramov <[email protected]>

* Reset `subtreeFlags` in `resetWorkInProgress`

Alternate fix to #20942

There was already a TODO to make this change, but at the time I left it,
I couldn't think of a way that it would actually cause a bug, and I was
hesistant to change something without fully understanding the
ramifications. This was during a time when we were hunting down a
different bug, so we were especially risk averse.

What I should have done in retrospect is put the change behind a flag
and tried rolling it out once the other bug had been flushed out.

OTOH, now we have a regression test, which wouldn't have otherwise, and
the bug it caused rarely fired in production.

Co-authored-by: Dan Abramov <[email protected]>
koto pushed a commit to koto/react that referenced this pull request Jun 15, 2021
* Add failing regression test

Based on facebook#20932

Co-Authored-By: Dan Abramov <[email protected]>

* Reset `subtreeFlags` in `resetWorkInProgress`

Alternate fix to facebook#20942

There was already a TODO to make this change, but at the time I left it,
I couldn't think of a way that it would actually cause a bug, and I was
hesistant to change something without fully understanding the
ramifications. This was during a time when we were hunting down a
different bug, so we were especially risk averse.

What I should have done in retrospect is put the change behind a flag
and tried rolling it out once the other bug had been flushed out.

OTOH, now we have a regression test, which wouldn't have otherwise, and
the bug it caused rarely fired in production.

Co-authored-by: Dan Abramov <[email protected]>
@sebmarkbage sebmarkbage deleted the branch facebook:master October 20, 2022 20:42
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.

6 participants