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

[Fiber] Create virtual Fiber when an error occurs during reconcilation #29804

Merged
merged 1 commit into from
Jun 11, 2024

Conversation

sebmarkbage
Copy link
Collaborator

This lets us rethrow it in the conceptual place of the child.

There's currently a problem when we suspend or throw in the child fiber reconciliation phase. This work is done by the parent component, so if it suspends or errors it is as if that component errored or suspended. However, conceptually it's like a child suspended or errored.

In theory any thing can throw but it is really mainly due to either React.lazy (both in the element.type position and node position), Thenables or the Thenables that make up AsyncIterables.

Mainly this happens because a Server Component that errors turns into a React.lazy. In practice this means that if you have a Server Component as the direct child of an Error Boundary. Errors inside of it won't be caught.

We used to have the same problem with Thenables and Suspense but because it's now always nested inside an inner Offscreen boundary that shields it by being one level nested. However, when we have raw Offscreen (Activity) boundaries they should also be able to catch the suspense if it's in a hidden state so the problem returns. This fixes it for thrown promises but it doesn't fix it for SuspenseException. I'm not sure this is even the right strategy for Suspense though. It kind of relies on the node never actually mounting/committing.

It's conceptually a little tricky because the current component can inspect the children and make decisions based on them. Such as SuspenseList.

The other thing that this PR tries to address is that it sets the foundation for dealing with error reporting for Server Components that errored. If something client side errors it'll be a stack like Server (DebugInfo) -> Fiber -> Fiber -> Server -> (DebugInfo) -> Fiber. However, all error reporting relies on it eventually terminating into a Fiber that is responsible for the error. To avoid having to fork too much it would be nice if I could create a Fiber to associate with the error so that even a Server component error in this case ultimately terminates in a Fiber.

@sebmarkbage sebmarkbage requested review from acdlite and hoxyq June 7, 2024 17:39
Copy link

vercel bot commented Jun 7, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
react-compiler-playground ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 7, 2024 6:00pm

@facebook-github-bot facebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Jun 7, 2024
@react-sizebot
Copy link

react-sizebot commented Jun 7, 2024

Comparing: a0a435d...52ca1a9

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.js = 6.66 kB 6.66 kB = 1.82 kB 1.82 kB
oss-stable/react-dom/cjs/react-dom-client.production.js +0.07% 497.25 kB 497.61 kB +0.09% 89.11 kB 89.19 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.67 kB 6.67 kB = 1.83 kB 1.83 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js +0.07% 502.07 kB 502.43 kB +0.10% 89.79 kB 89.89 kB
facebook-www/ReactDOM-prod.classic.js +0.11% 596.75 kB 597.38 kB +0.12% 105.19 kB 105.32 kB
facebook-www/ReactDOM-prod.modern.js +0.07% 570.93 kB 571.30 kB +0.08% 101.13 kB 101.21 kB
test_utils/ReactAllWarnings.js Deleted 63.89 kB 0.00 kB Deleted 15.97 kB 0.00 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
test_utils/ReactAllWarnings.js Deleted 63.89 kB 0.00 kB Deleted 15.97 kB 0.00 kB

Generated by 🚫 dangerJS against 52ca1a9

This lets us rethrow it in the conceptual place of the child.
@sebmarkbage sebmarkbage merged commit 270229f into facebook:main Jun 11, 2024
44 checks passed
github-actions bot pushed a commit that referenced this pull request Jun 11, 2024
#29804)

This lets us rethrow it in the conceptual place of the child.

There's currently a problem when we suspend or throw in the child fiber
reconciliation phase. This work is done by the parent component, so if
it suspends or errors it is as if that component errored or suspended.
However, conceptually it's like a child suspended or errored.

In theory any thing can throw but it is really mainly due to either
`React.lazy` (both in the element.type position and node position),
`Thenable`s or the `Thenable`s that make up `AsyncIterable`s.

Mainly this happens because a Server Component that errors turns into a
`React.lazy`. In practice this means that if you have a Server Component
as the direct child of an Error Boundary. Errors inside of it won't be
caught.

We used to have the same problem with Thenables and Suspense but because
it's now always nested inside an inner Offscreen boundary that shields
it by being one level nested. However, when we have raw Offscreen
(Activity) boundaries they should also be able to catch the suspense if
it's in a hidden state so the problem returns. This fixes it for thrown
promises but it doesn't fix it for SuspenseException. I'm not sure this
is even the right strategy for Suspense though. It kind of relies on the
node never actually mounting/committing.

It's conceptually a little tricky because the current component can
inspect the children and make decisions based on them. Such as
SuspenseList.

The other thing that this PR tries to address is that it sets the
foundation for dealing with error reporting for Server Components that
errored. If something client side errors it'll be a stack like Server
(DebugInfo) -> Fiber -> Fiber -> Server -> (DebugInfo) -> Fiber.
However, all error reporting relies on it eventually terminating into a
Fiber that is responsible for the error. To avoid having to fork too
much it would be nice if I could create a Fiber to associate with the
error so that even a Server component error in this case ultimately
terminates in a Fiber.

DiffTrain build for commit 270229f.
github-actions bot pushed a commit that referenced this pull request Jun 11, 2024
#29804)

This lets us rethrow it in the conceptual place of the child.

There's currently a problem when we suspend or throw in the child fiber
reconciliation phase. This work is done by the parent component, so if
it suspends or errors it is as if that component errored or suspended.
However, conceptually it's like a child suspended or errored.

In theory any thing can throw but it is really mainly due to either
`React.lazy` (both in the element.type position and node position),
`Thenable`s or the `Thenable`s that make up `AsyncIterable`s.

Mainly this happens because a Server Component that errors turns into a
`React.lazy`. In practice this means that if you have a Server Component
as the direct child of an Error Boundary. Errors inside of it won't be
caught.

We used to have the same problem with Thenables and Suspense but because
it's now always nested inside an inner Offscreen boundary that shields
it by being one level nested. However, when we have raw Offscreen
(Activity) boundaries they should also be able to catch the suspense if
it's in a hidden state so the problem returns. This fixes it for thrown
promises but it doesn't fix it for SuspenseException. I'm not sure this
is even the right strategy for Suspense though. It kind of relies on the
node never actually mounting/committing.

It's conceptually a little tricky because the current component can
inspect the children and make decisions based on them. Such as
SuspenseList.

The other thing that this PR tries to address is that it sets the
foundation for dealing with error reporting for Server Components that
errored. If something client side errors it'll be a stack like Server
(DebugInfo) -> Fiber -> Fiber -> Server -> (DebugInfo) -> Fiber.
However, all error reporting relies on it eventually terminating into a
Fiber that is responsible for the error. To avoid having to fork too
much it would be nice if I could create a Fiber to associate with the
error so that even a Server component error in this case ultimately
terminates in a Fiber.

DiffTrain build for [270229f](270229f)
sebmarkbage added a commit that referenced this pull request Jun 11, 2024
Stacked on #29804.

Transferring of debugInfo was added in #28286. It represents the parent
stack between the current Fiber and into the next Fiber we're about to
create. I.e. Server Components in between. ~I don't love passing
DEV-only fields as arguments anyway since I don't trust closure to
remove unused arguments that way.~ EDIT: Actually it seems like closure
handled that just fine before which is why this is no change in prod.

Instead, I track it on the module scope. Notably with DON'T use
try/finally because if something throws we want to observe what it was
at the time we threw. Like the pattern we use many other places.

Now we can use this when we create the Throw Fiber to associate the
Server Components that were part of the parent stack before this error
threw. There by giving us the correct parent stacks at the location that
threw.
hoxyq added a commit that referenced this pull request Jun 18, 2024
Full list of changes:

* chore[react-devtools]: improve console arguments formatting before
passing it to original console ([hoxyq](https://github.com/hoxyq) in
[#29873](#29873))
* chore[react-devtools]: unify console patching and default to ansi
escape symbols ([hoxyq](https://github.com/hoxyq) in
[#29869](#29869))
* chore[react-devtools/backend]: remove
consoleManagedByDevToolsDuringStrictMode
([hoxyq](https://github.com/hoxyq) in
[#29856](#29856))
* chore[react-devtools/extensions]: make source maps url relative
([hoxyq](https://github.com/hoxyq) in
[#29886](#29886))
* fix[react-devtools] divided inspecting elements between inspecting do…
([vzaidman](https://github.com/vzaidman) in
[#29885](#29885))
* [Fiber] Create virtual Fiber when an error occurs during reconcilation
([sebmarkbage](https://github.com/sebmarkbage) in
[#29804](#29804))
* fix[react-devtools] component badge in light mode is now not invisible
([vzaidman](https://github.com/vzaidman) in
[#29852](#29852))
* Remove Warning: prefix and toString on console Arguments
([sebmarkbage](https://github.com/sebmarkbage) in
[#29839](#29839))
* Add jest lint rules ([rickhanlonii](https://github.com/rickhanlonii)
in [#29760](#29760))
* [Fiber] Track the Real Fiber for Key Warnings
([sebmarkbage](https://github.com/sebmarkbage) in
[#29791](#29791))
* fix[react-devtools/store-test]: fork the test to represent current be…
([hoxyq](https://github.com/hoxyq) in
[#29777](#29777))
* Default native inspections config false
([vzaidman](https://github.com/vzaidman) in
[#29784](#29784))
* fix[react-devtools] remove native inspection button when it can't be
used ([vzaidman](https://github.com/vzaidman) in
[#29779](#29779))
* chore[react-devtools]: ip => internal-ip
([hoxyq](https://github.com/hoxyq) in
[#29772](#29772))
* Fix #29724: `ip` dependency update for CVE-2024-29415
([Rekl0w](https://github.com/Rekl0w) in
[#29725](#29725))
* cleanup[react-devtools]: remove unused supportsProfiling flag from
store config ([hoxyq](https://github.com/hoxyq) in
[#29193](#29193))
* [Fiber] Enable Native console.createTask Stacks When Available
([sebmarkbage](https://github.com/sebmarkbage) in
[#29223](#29223))
* Move createElement/JSX Warnings into the Renderer
([sebmarkbage](https://github.com/sebmarkbage) in
[#29088](#29088))
* Set the current fiber to the source of the error during error
reporting ([sebmarkbage](https://github.com/sebmarkbage) in
[#29044](#29044))
* Unify ReactFiberCurrentOwner and ReactCurrentFiber
([sebmarkbage](https://github.com/sebmarkbage) in
[#29038](#29038))
* Dim `console` calls on additional Effect invocations due to
`StrictMode` ([eps1lon](https://github.com/eps1lon) in
[#29007](#29007))
* refactor[react-devtools]: rewrite context menus
([hoxyq](https://github.com/hoxyq) in
[#29049](#29049))
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