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

Fix for failed Suspense layout semantics #21694

Merged
merged 3 commits into from
Jun 16, 2021
Merged

Conversation

bvaughn
Copy link
Contributor

@bvaughn bvaughn commented Jun 16, 2021

Resolves #21676. Fixes failing test added in #21677

When adding the new Suspense/Offscreen effects semantics, we intentionally left out the subtreeFlags checks since these values aren't 100% reliable and the check is just an optimization. (Refer to the // TODO (Offscreen) comments in the source code.)

It looks like #21386 (re)added one though, which was causing a failure case originally reported here:
reactwg/react-18#31

For now, this PR just removes that check and adds a follow up TODO comment. This is just a bandaid fix to allow us to resume rolling out the new Suspense layout semantics. A proper long-term fix would be to identify why the subtreeFlags are incorrect in this case.

gaearon and others added 2 commits June 16, 2021 09:47
This was preventing layout effects from being recreated within Offscreen subtrees in some conditions.
@bvaughn bvaughn requested review from gaearon and acdlite June 16, 2021 17:41
@facebook-github-bot facebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Jun 16, 2021
@bvaughn bvaughn changed the title Add failing test for Suspense layout semantics Fix for failed Suspense layout semantics Jun 16, 2021
Copy link
Collaborator

@gaearon gaearon left a comment

Choose a reason for hiding this comment

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

Beautiful. Thank you.

@sizebot
Copy link

sizebot commented Jun 16, 2021

Comparing: a0d2d1e...742d0b0

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 = 127.40 kB 127.34 kB = 40.83 kB 40.82 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js = 130.21 kB 130.16 kB = 41.73 kB 41.73 kB
facebook-www/ReactDOM-prod.classic.js = 405.89 kB 405.75 kB = 75.02 kB 75.02 kB
facebook-www/ReactDOM-prod.modern.js = 394.32 kB 394.18 kB = 73.24 kB 73.24 kB
facebook-www/ReactDOMForked-prod.classic.js = 405.89 kB 405.75 kB = 75.03 kB 75.03 kB

Significant size changes

Includes any change greater than 0.2%:

(No significant changes)

Generated by 🚫 dangerJS against 742d0b0

@bvaughn
Copy link
Contributor Author

bvaughn commented Jun 16, 2021

That's interesting. We have a slight timing difference for when we destroy the layout effect in production tests too.

ReactTestRenderer.act(() => {
  _setShow(true);
});
expect(Scheduler).toHaveYielded([
  "Child 1",
  "Suspend! [Child 2]",
  "Loading...",
  // In development we destroy it here
  "destroy layout",
]);
jest.advanceTimersByTime(1000);
expect(Scheduler).toHaveYielded([
  // In production we destroy it here
  "destroy layout",
  "Promise resolved [Child 2]",
]);

I'm not sure why there's a difference in these two behaviors. I would not expect there to be. Looking at the stack, I see the following frames in DEV mode:

  at commitRoot (packages/react-reconciler/src/ReactFiberWorkLoop.new.js:1696:5)
  at finishConcurrentRender (packages/react-reconciler/src/ReactFiberWorkLoop.new.js:930:9)
  at performConcurrentWorkOnRoot (packages/react-reconciler/src/ReactFiberWorkLoop.new.js:820:5)
  at workLoop (packages/scheduler/src/forks/SchedulerMock.js:188:34)
  at flushWork (packages/scheduler/src/forks/SchedulerMock.js:141:16)
  at unstable_flushAllWithoutAsserting (packages/scheduler/src/forks/SchedulerMock.js:531:23)
  at flushActWork (packages/react-reconciler/src/ReactFiberWorkLoop.new.js:2948:14)

But in production mode I see:

  at commitRoot (packages/react-reconciler/src/ReactFiberWorkLoop.new.js:1696:5)
  at callback (node_modules/@jest/fake-timers/build/legacyFakeTimers.js:565:32)
  at FakeTimers._runTimerHandle (node_modules/@jest/fake-timers/build/legacyFakeTimers.js:601:9)
  at FakeTimers.advanceTimersByTime (node_modules/@jest/fake-timers/build/legacyFakeTimers.js:292:14)

So for some reason, it looks like commitRoot is being deferred behind a setTimeout in the prod tests.

In Dev, higher up in the call stack is finishConcurrentRender, which checks shouldForceFlushFallbacksInDEV(). So this is probably the difference. Kind of unfortunate that it manifests itself in an observably different way like this huh.

@bvaughn bvaughn merged commit d0f348d into facebook:master Jun 16, 2021
@bvaughn bvaughn deleted the issues/21676 branch June 16, 2021 23:44
@gaearon gaearon mentioned this pull request Jun 17, 2021
facebook-github-bot pushed a commit to facebook/react-native that referenced this pull request Jun 22, 2021
Summary:
This sync includes the following changes:
- **[43f4cc160](facebook/react@43f4cc160 )**: Fix failing test ([#21697](facebook/react#21697)) //<Dan Abramov>//
- **[d0f348dc1](facebook/react@d0f348dc1 )**: Fix for failed Suspense layout semantics ([#21694](facebook/react#21694)) //<Brian Vaughn>//
- **[bd0a96344](facebook/react@bd0a96344 )**: Throw when `act` is used in production ([#21686](facebook/react#21686)) //<Andrew Clark>//
- **[9343f8720](facebook/react@9343f8720 )**: Use the server src files as entry points for the builds/tests ([#21683](facebook/react#21683)) //<Sebastian Markbåge>//
- **[502f8a2a0](facebook/react@502f8a2a0 )**: [Fizz/Flight] Don't use default args ([#21681](facebook/react#21681)) //<Sebastian Markbåge>//
- **[a8f5e77b9](facebook/react@a8f5e77b9 )**: Remove invokeGuardedCallback from commit phase ([#21666](facebook/react#21666)) //<Dan Abramov>//
- **[dbe3363cc](facebook/react@dbe3363cc )**: [Fizz] Implement Legacy renderToString and renderToNodeStream on top of Fizz ([#21276](facebook/react#21276)) //<Sebastian Markbåge>//
- **[101ea9f55](facebook/react@101ea9f55 )**: Set deletedTreeCleanUpLevel to 3 ([#21679](facebook/react#21679)) //<Dan Abramov>//
- **[1a106bdc2](facebook/react@1a106bdc2 )**: Wrap eventhandle-specific logic in a flag ([#21657](facebook/react#21657)) //<Dan Abramov>//
- **[cb30388d1](facebook/react@cb30388d1 )**: Export React Native `AttributeType` Types ([#21661](facebook/react#21661)) //<Timothy Yung>//
- **[c1536795c](facebook/react@c1536795c )**: Revert "Make enableSuspenseLayoutEffectSemantics static for www ([#21617](facebook/react#21617))" ([#21656](facebook/react#21656)) //<Sebastian Markbåge>//

Changelog:
[General][Changed] - React Native sync for revisions c96b78e...568dc35

jest_e2e[run_all_tests]

Reviewed By: rickhanlonii

Differential Revision: D29303157

fbshipit-source-id: 90952885eb2264f4effa04070357b80700bb9be3
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.

Bug: Layout effects don't re-fire in 18 on Suspense re-showing
4 participants