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

[Fizz] Add Component Stacks to onError and onPostpone when in dev mode or during prerenders in prod mode #27761

Merged
merged 1 commit into from
Dec 16, 2023

Conversation

gnoff
Copy link
Collaborator

@gnoff gnoff commented Nov 29, 2023

Historically React would produce component stacks for dev builds only. There is a cost to tracking component stacks and given the prod builds try to optimize runtime performance these stacks were left out. More recently React added production component stacks to Fiber in because it can be immensely helpful in tracking down hard to debug production issues. Fizz was not updated to have a similar behavior.

With the advent of prerendering however stacks for production in Fizz are more relevant because prerendering is not really a dev-time task. If you want the ability to reason about errors or postpones that happen during a prerender having component stacks to interrogate is helpful and these component stacks need to be available in production otherwise you are really never going to see them. (it is possible that you could do dev-mode prerenders but we don't expect this to be a common dev mode workflow)

To better support the prerender use case and to make error logging in Fizz more useful the following changes have been made

  1. onPostpone now accepts a second postponeInfo argument which will contain a componentStack. Postpones always originate from a component render so the stack should be consistently available. The type however will indicate the stack is optional so we can remove them in the future if we decide the overhead is the wrong tradeoff in certain cases
  2. onError now accepts a second errorInfo argument which may contain a componentStack. If an error originated from a component a stack will be included in the following cases.

This change entails tracking the component hierarchy in prod builds now. While this isn't cost free it is implemented in a relatively lean manner. Deferring the most expensive work (reifying the stack) until we are actually in an error pathway.

In the course of implementing this change a number of simplifications were made to the code which should make the stack tracking more resilient. We no longer use a module global to curry the stack up to some handler. This was delicate because you needed to always reset it properly. We now curry the stack on the task itself.

Another change made was to track the component stack on SuspenseBoundary instances so that we can provide the stack when aborting suspense boundaries to help you determine which ones were affected by an abort.

@facebook-github-bot facebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Nov 29, 2023
@react-sizebot
Copy link

react-sizebot commented Nov 29, 2023

Comparing: 493610f...9325617

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 = 175.90 kB 175.90 kB = 54.76 kB 54.76 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js = 177.97 kB 177.97 kB = 55.39 kB 55.40 kB
facebook-www/ReactDOM-prod.classic.js = 570.21 kB 570.21 kB = 100.35 kB 100.35 kB
facebook-www/ReactDOM-prod.modern.js = 554.06 kB 554.06 kB = 97.43 kB 97.43 kB
oss-stable-semver/react-server/cjs/react-server.production.js +10.74% 140.07 kB 155.11 kB +11.42% 32.62 kB 36.34 kB
oss-stable/react-server/cjs/react-server.production.js +10.74% 140.07 kB 155.11 kB +11.42% 32.62 kB 36.34 kB
oss-experimental/react-server/cjs/react-server.production.js +10.22% 150.31 kB 165.66 kB +10.87% 34.45 kB 38.19 kB
oss-stable-semver/react-server/cjs/react-server.production.min.js +8.57% 34.98 kB 37.98 kB +7.91% 11.21 kB 12.10 kB
oss-stable/react-server/cjs/react-server.production.min.js +8.57% 34.98 kB 37.98 kB +7.91% 11.21 kB 12.10 kB
oss-experimental/react-server/cjs/react-server.production.min.js +8.11% 37.86 kB 40.94 kB +7.49% 11.94 kB 12.84 kB
oss-stable-semver/react-dom/cjs/react-dom-server.bun.production.js +5.00% 300.58 kB 315.61 kB +5.74% 64.85 kB 68.57 kB
oss-stable/react-dom/cjs/react-dom-server.bun.production.js +5.00% 300.61 kB 315.64 kB +5.74% 64.87 kB 68.60 kB
oss-stable-semver/react-dom/cjs/react-dom-server.browser.production.js +4.97% 302.09 kB 317.12 kB +5.58% 65.63 kB 69.29 kB
oss-stable/react-dom/cjs/react-dom-server.browser.production.js +4.97% 302.12 kB 317.15 kB +5.58% 65.65 kB 69.32 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.browser.production.js +4.96% 302.69 kB 317.72 kB +5.59% 65.49 kB 69.15 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.browser.production.js +4.96% 302.71 kB 317.74 kB +5.59% 65.52 kB 69.18 kB
oss-stable-semver/react-dom/cjs/react-dom-server.node.production.js +4.93% 304.74 kB 319.77 kB +5.67% 65.62 kB 69.33 kB
oss-stable/react-dom/cjs/react-dom-server.node.production.js +4.93% 304.77 kB 319.80 kB +5.66% 65.65 kB 69.36 kB
oss-experimental/react-dom/cjs/react-dom-server.bun.production.js +4.93% 311.41 kB 326.76 kB +5.61% 66.83 kB 70.57 kB
oss-stable-semver/react-dom/cjs/react-dom-server.edge.production.js +4.91% 306.37 kB 321.40 kB +5.57% 66.89 kB 70.62 kB
oss-stable/react-dom/cjs/react-dom-server.edge.production.js +4.90% 306.40 kB 321.42 kB +5.57% 66.92 kB 70.65 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.browser.production.js +4.90% 313.21 kB 328.56 kB +5.53% 67.29 kB 71.01 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.node.production.js +4.87% 308.63 kB 323.66 kB +5.52% 67.21 kB 70.92 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.node.production.js +4.87% 308.66 kB 323.68 kB +5.52% 67.24 kB 70.95 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.node.production.js +4.80% 319.46 kB 334.80 kB +5.42% 69.17 kB 72.92 kB
oss-experimental/react-dom/cjs/react-dom-server.browser.production.js +4.77% 321.87 kB 337.22 kB +5.51% 68.37 kB 72.14 kB
oss-experimental/react-dom/cjs/react-dom-server.node.production.js +4.73% 324.29 kB 339.64 kB +5.51% 68.80 kB 72.59 kB
oss-experimental/react-dom/cjs/react-dom-server.edge.production.js +4.70% 326.45 kB 341.80 kB +5.45% 69.78 kB 73.59 kB
facebook-www/ReactDOMServer-prod.classic.js +4.48% 191.91 kB 200.51 kB +4.50% 34.72 kB 36.28 kB
facebook-www/ReactDOMServer-prod.modern.js +4.27% 190.03 kB 198.15 kB +4.49% 34.40 kB 35.94 kB
facebook-www/ReactDOMServerStreaming-prod.modern.js +4.19% 193.88 kB 202.00 kB +4.56% 35.52 kB 37.15 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.browser.production.min.js +3.91% 76.93 kB 79.93 kB +3.75% 23.39 kB 24.26 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.browser.production.min.js +3.90% 76.95 kB 79.96 kB +3.75% 23.41 kB 24.29 kB
oss-stable-semver/react-dom/umd/react-dom-server-legacy.browser.production.min.js +3.89% 77.02 kB 80.02 kB +3.79% 23.76 kB 24.66 kB
oss-stable/react-dom/umd/react-dom-server-legacy.browser.production.min.js +3.89% 77.05 kB 80.05 kB +3.79% 23.78 kB 24.68 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.browser.production.min.js +3.89% 79.59 kB 82.69 kB +3.76% 24.15 kB 25.06 kB
oss-experimental/react-dom/umd/react-dom-server-legacy.browser.production.min.js +3.87% 79.68 kB 82.77 kB +3.73% 24.53 kB 25.44 kB
oss-stable-semver/react-dom/cjs/react-dom-server.browser.production.min.js +3.84% 77.89 kB 80.88 kB +3.72% 24.22 kB 25.12 kB
oss-stable/react-dom/cjs/react-dom-server.browser.production.min.js +3.84% 77.91 kB 80.90 kB +3.71% 24.24 kB 25.14 kB
oss-stable-semver/react-dom/umd/react-dom-server.browser.production.min.js +3.82% 77.97 kB 80.95 kB +3.55% 24.60 kB 25.47 kB
oss-stable/react-dom/umd/react-dom-server.browser.production.min.js +3.82% 78.00 kB 80.98 kB +3.57% 24.62 kB 25.50 kB
oss-stable-semver/react-dom/cjs/react-dom-server.bun.production.min.js +3.76% 79.50 kB 82.49 kB +3.66% 24.07 kB 24.95 kB
oss-stable/react-dom/cjs/react-dom-server.bun.production.min.js +3.76% 79.53 kB 82.52 kB +3.66% 24.09 kB 24.98 kB
oss-experimental/react-dom/cjs/react-dom-server.bun.production.min.js +3.72% 82.53 kB 85.60 kB +3.86% 24.89 kB 25.85 kB
oss-stable-semver/react-dom/cjs/react-dom-server.node.production.min.js +3.69% 81.09 kB 84.08 kB +3.99% 24.95 kB 25.94 kB
oss-stable/react-dom/cjs/react-dom-server.node.production.min.js +3.68% 81.11 kB 84.10 kB +3.96% 24.98 kB 25.97 kB
oss-experimental/react-dom/cjs/react-dom-server.browser.production.min.js +3.67% 84.05 kB 87.14 kB +3.36% 25.73 kB 26.59 kB
oss-experimental/react-dom/umd/react-dom-server.browser.production.min.js +3.65% 84.13 kB 87.20 kB +3.27% 26.07 kB 26.92 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.node.production.min.js +3.62% 82.54 kB 85.53 kB +3.64% 25.25 kB 26.17 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.node.production.min.js +3.62% 82.57 kB 85.55 kB +3.66% 25.27 kB 26.20 kB
oss-stable-semver/react-dom/cjs/react-dom-server.edge.production.min.js +3.60% 82.96 kB 85.95 kB +3.74% 25.83 kB 26.79 kB
oss-stable/react-dom/cjs/react-dom-server.edge.production.min.js +3.60% 82.99 kB 85.98 kB +3.74% 25.85 kB 26.82 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.node.production.min.js +3.60% 85.56 kB 88.64 kB +3.39% 26.10 kB 26.98 kB
oss-experimental/react-dom/cjs/react-dom-server.node.production.min.js +3.52% 87.69 kB 90.78 kB +3.65% 26.55 kB 27.52 kB
oss-experimental/react-dom/cjs/react-dom-server.edge.production.min.js +3.45% 89.47 kB 92.55 kB +3.32% 27.42 kB 28.33 kB
test_utils/ReactAllWarnings.js Deleted 67.41 kB 0.00 kB Deleted 16.49 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
oss-stable-semver/react-server/cjs/react-server.production.js +10.74% 140.07 kB 155.11 kB +11.42% 32.62 kB 36.34 kB
oss-stable/react-server/cjs/react-server.production.js +10.74% 140.07 kB 155.11 kB +11.42% 32.62 kB 36.34 kB
oss-experimental/react-server/cjs/react-server.production.js +10.22% 150.31 kB 165.66 kB +10.87% 34.45 kB 38.19 kB
oss-stable-semver/react-server/cjs/react-server.production.min.js +8.57% 34.98 kB 37.98 kB +7.91% 11.21 kB 12.10 kB
oss-stable/react-server/cjs/react-server.production.min.js +8.57% 34.98 kB 37.98 kB +7.91% 11.21 kB 12.10 kB
oss-experimental/react-server/cjs/react-server.production.min.js +8.11% 37.86 kB 40.94 kB +7.49% 11.94 kB 12.84 kB
oss-stable-semver/react-dom/cjs/react-dom-server.bun.production.js +5.00% 300.58 kB 315.61 kB +5.74% 64.85 kB 68.57 kB
oss-stable/react-dom/cjs/react-dom-server.bun.production.js +5.00% 300.61 kB 315.64 kB +5.74% 64.87 kB 68.60 kB
oss-stable-semver/react-dom/cjs/react-dom-server.browser.production.js +4.97% 302.09 kB 317.12 kB +5.58% 65.63 kB 69.29 kB
oss-stable/react-dom/cjs/react-dom-server.browser.production.js +4.97% 302.12 kB 317.15 kB +5.58% 65.65 kB 69.32 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.browser.production.js +4.96% 302.69 kB 317.72 kB +5.59% 65.49 kB 69.15 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.browser.production.js +4.96% 302.71 kB 317.74 kB +5.59% 65.52 kB 69.18 kB
oss-stable-semver/react-dom/cjs/react-dom-server.node.production.js +4.93% 304.74 kB 319.77 kB +5.67% 65.62 kB 69.33 kB
oss-stable/react-dom/cjs/react-dom-server.node.production.js +4.93% 304.77 kB 319.80 kB +5.66% 65.65 kB 69.36 kB
oss-experimental/react-dom/cjs/react-dom-server.bun.production.js +4.93% 311.41 kB 326.76 kB +5.61% 66.83 kB 70.57 kB
oss-stable-semver/react-dom/cjs/react-dom-server.edge.production.js +4.91% 306.37 kB 321.40 kB +5.57% 66.89 kB 70.62 kB
oss-stable/react-dom/cjs/react-dom-server.edge.production.js +4.90% 306.40 kB 321.42 kB +5.57% 66.92 kB 70.65 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.browser.production.js +4.90% 313.21 kB 328.56 kB +5.53% 67.29 kB 71.01 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.node.production.js +4.87% 308.63 kB 323.66 kB +5.52% 67.21 kB 70.92 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.node.production.js +4.87% 308.66 kB 323.68 kB +5.52% 67.24 kB 70.95 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.node.production.js +4.80% 319.46 kB 334.80 kB +5.42% 69.17 kB 72.92 kB
oss-experimental/react-dom/cjs/react-dom-server.browser.production.js +4.77% 321.87 kB 337.22 kB +5.51% 68.37 kB 72.14 kB
oss-experimental/react-dom/cjs/react-dom-server.node.production.js +4.73% 324.29 kB 339.64 kB +5.51% 68.80 kB 72.59 kB
oss-experimental/react-dom/cjs/react-dom-server.edge.production.js +4.70% 326.45 kB 341.80 kB +5.45% 69.78 kB 73.59 kB
facebook-www/ReactDOMServer-prod.classic.js +4.48% 191.91 kB 200.51 kB +4.50% 34.72 kB 36.28 kB
facebook-www/ReactDOMServer-prod.modern.js +4.27% 190.03 kB 198.15 kB +4.49% 34.40 kB 35.94 kB
facebook-www/ReactDOMServerStreaming-prod.modern.js +4.19% 193.88 kB 202.00 kB +4.56% 35.52 kB 37.15 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.browser.production.min.js +3.91% 76.93 kB 79.93 kB +3.75% 23.39 kB 24.26 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.browser.production.min.js +3.90% 76.95 kB 79.96 kB +3.75% 23.41 kB 24.29 kB
oss-stable-semver/react-dom/umd/react-dom-server-legacy.browser.production.min.js +3.89% 77.02 kB 80.02 kB +3.79% 23.76 kB 24.66 kB
oss-stable/react-dom/umd/react-dom-server-legacy.browser.production.min.js +3.89% 77.05 kB 80.05 kB +3.79% 23.78 kB 24.68 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.browser.production.min.js +3.89% 79.59 kB 82.69 kB +3.76% 24.15 kB 25.06 kB
oss-experimental/react-dom/umd/react-dom-server-legacy.browser.production.min.js +3.87% 79.68 kB 82.77 kB +3.73% 24.53 kB 25.44 kB
oss-stable-semver/react-dom/cjs/react-dom-server.browser.production.min.js +3.84% 77.89 kB 80.88 kB +3.72% 24.22 kB 25.12 kB
oss-stable/react-dom/cjs/react-dom-server.browser.production.min.js +3.84% 77.91 kB 80.90 kB +3.71% 24.24 kB 25.14 kB
oss-stable-semver/react-dom/umd/react-dom-server.browser.production.min.js +3.82% 77.97 kB 80.95 kB +3.55% 24.60 kB 25.47 kB
oss-stable/react-dom/umd/react-dom-server.browser.production.min.js +3.82% 78.00 kB 80.98 kB +3.57% 24.62 kB 25.50 kB
oss-stable-semver/react-dom/cjs/react-dom-server.bun.production.min.js +3.76% 79.50 kB 82.49 kB +3.66% 24.07 kB 24.95 kB
oss-stable/react-dom/cjs/react-dom-server.bun.production.min.js +3.76% 79.53 kB 82.52 kB +3.66% 24.09 kB 24.98 kB
oss-experimental/react-dom/cjs/react-dom-server.bun.production.min.js +3.72% 82.53 kB 85.60 kB +3.86% 24.89 kB 25.85 kB
oss-stable-semver/react-dom/cjs/react-dom-server.node.production.min.js +3.69% 81.09 kB 84.08 kB +3.99% 24.95 kB 25.94 kB
oss-stable/react-dom/cjs/react-dom-server.node.production.min.js +3.68% 81.11 kB 84.10 kB +3.96% 24.98 kB 25.97 kB
oss-experimental/react-dom/cjs/react-dom-server.browser.production.min.js +3.67% 84.05 kB 87.14 kB +3.36% 25.73 kB 26.59 kB
oss-experimental/react-dom/umd/react-dom-server.browser.production.min.js +3.65% 84.13 kB 87.20 kB +3.27% 26.07 kB 26.92 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.node.production.min.js +3.62% 82.54 kB 85.53 kB +3.64% 25.25 kB 26.17 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.node.production.min.js +3.62% 82.57 kB 85.55 kB +3.66% 25.27 kB 26.20 kB
oss-stable-semver/react-dom/cjs/react-dom-server.edge.production.min.js +3.60% 82.96 kB 85.95 kB +3.74% 25.83 kB 26.79 kB
oss-stable/react-dom/cjs/react-dom-server.edge.production.min.js +3.60% 82.99 kB 85.98 kB +3.74% 25.85 kB 26.82 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.node.production.min.js +3.60% 85.56 kB 88.64 kB +3.39% 26.10 kB 26.98 kB
oss-experimental/react-dom/cjs/react-dom-server.node.production.min.js +3.52% 87.69 kB 90.78 kB +3.65% 26.55 kB 27.52 kB
oss-experimental/react-dom/cjs/react-dom-server.edge.production.min.js +3.45% 89.47 kB 92.55 kB +3.32% 27.42 kB 28.33 kB
oss-experimental/react-server/cjs/react-server.development.js +0.48% 208.21 kB 209.22 kB +0.33% 48.52 kB 48.69 kB
oss-stable-semver/react-server/cjs/react-server.development.js +0.45% 197.81 kB 198.70 kB +0.35% 46.64 kB 46.80 kB
oss-stable/react-server/cjs/react-server.development.js +0.45% 197.81 kB 198.70 kB +0.35% 46.64 kB 46.80 kB
oss-experimental/react-dom/cjs/react-dom-server.bun.development.js +0.23% 424.04 kB 425.04 kB +0.22% 94.40 kB 94.61 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.browser.development.js +0.23% 430.45 kB 431.45 kB +0.21% 96.37 kB 96.58 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.node.development.js +0.23% 432.31 kB 433.30 kB +0.21% 96.84 kB 97.04 kB
oss-experimental/react-dom/cjs/react-dom-server.node.development.js +0.23% 437.61 kB 438.62 kB +0.17% 96.73 kB 96.90 kB
oss-experimental/react-dom/cjs/react-dom-server.browser.development.js +0.23% 439.18 kB 440.19 kB +0.17% 97.51 kB 97.67 kB
oss-experimental/react-dom/cjs/react-dom-server.edge.development.js +0.23% 439.77 kB 440.77 kB +0.17% 97.64 kB 97.81 kB
oss-stable-semver/react-dom/cjs/react-dom-server.bun.development.js +0.21% 412.35 kB 413.23 kB +0.21% 92.23 kB 92.43 kB
oss-stable/react-dom/cjs/react-dom-server.bun.development.js +0.21% 412.38 kB 413.26 kB +0.22% 92.26 kB 92.46 kB
oss-stable-semver/react-dom/cjs/react-dom-server.node.development.js +0.21% 417.16 kB 418.04 kB +0.21% 93.30 kB 93.50 kB
oss-stable/react-dom/cjs/react-dom-server.node.development.js +0.21% 417.18 kB 418.07 kB +0.22% 93.33 kB 93.53 kB
oss-stable-semver/react-dom/cjs/react-dom-server.browser.development.js +0.21% 418.20 kB 419.08 kB +0.21% 94.36 kB 94.56 kB
oss-stable/react-dom/cjs/react-dom-server.browser.development.js +0.21% 418.22 kB 419.10 kB +0.21% 94.38 kB 94.59 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.browser.development.js +0.21% 418.76 kB 419.64 kB +0.21% 94.21 kB 94.40 kB
oss-stable-semver/react-dom/cjs/react-dom-server.edge.development.js +0.21% 418.78 kB 419.66 kB +0.22% 94.50 kB 94.70 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.browser.development.js +0.21% 418.79 kB 419.67 kB +0.21% 94.23 kB 94.43 kB
oss-stable/react-dom/cjs/react-dom-server.edge.development.js +0.21% 418.81 kB 419.69 kB +0.22% 94.52 kB 94.72 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.node.development.js +0.21% 420.62 kB 421.50 kB +0.21% 94.67 kB 94.87 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.node.development.js +0.21% 420.64 kB 421.52 kB +0.21% 94.70 kB 94.90 kB
test_utils/ReactAllWarnings.js Deleted 67.41 kB 0.00 kB Deleted 16.49 kB 0.00 kB

Generated by 🚫 dangerJS against 9325617

Comment on lines -2242 to -2254
} catch (x) {
if (
typeof x === 'object' &&
x !== null &&
typeof x.then === 'function'
) {
// this Lazy initializer is suspending. push a temporary frame onto the stack so it can be
// popped off in spawnNewSuspendedTask. This aligns stack behavior between Lazy in element position
// vs Component position. We do not want the frame for Errors so we exclusively do this in
// the wakeable branch
pushBuiltInComponentStackInDEV(task, 'Lazy');
}
throw x;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I was originally motivated to remove this special case because I didn't want to have the extra try in prod. However I'm also not sure this was correct to begin with. The comment (which I wrote) indicates we are trying to have parity between stack behavior with element and Component position lazy's. However When I test the client behavior there is a seemingly buggy thing today where as an element if the lazy itself rejects you are told there is an error in component. However by removing this special case now elements and components both get a Lazy frame if the promise rejects and if the promise resolves this frame is removed from any future errors that arise deeper in the render. I think this makes sense but I wrote this comment for a reason and I no longer remember why. For now I'm going with this until we can clarify what the proper client behavior is since it should match

Comment on lines -735 to -742
function pushFunctionComponentStackInDEV(task: Task, type: Function): void {
if (__DEV__) {
task.componentStack = {
tag: 1,
parent: task.componentStack,
type,
};
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I refactored the way we track our stacks to be more efficient since we are running this in prod now. instead of pushing and popping we always stash and restore. To make this pattern clearer I renamed to get...() instead of push...() and moved the task mutation into the functions where these are used. This should inline better and eliminates a null check.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Arguably this is more of a create prefix because you're not getting it from somewhere else.

Copy link
Collaborator

@sebmarkbage sebmarkbage left a comment

Choose a reason for hiding this comment

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

Since we're doing all the work when there's no error in prod, arguably we could always expose it since it only has to do the expensive computation if there's actually an error.

@gnoff gnoff merged commit 63310df into facebook:main Dec 16, 2023
36 checks passed
@gnoff gnoff deleted the prerender-stacks branch December 16, 2023 02:06
github-actions bot pushed a commit that referenced this pull request Dec 16, 2023
… mode or during prerenders in prod mode (#27761)

Historically React would produce component stacks for dev builds only.
There is a cost to tracking component stacks and given the prod builds
try to optimize runtime performance these stacks were left out. More
recently React added production component stacks to Fiber in because it
can be immensely helpful in tracking down hard to debug production
issues. Fizz was not updated to have a similar behavior.

With the advent of prerendering however stacks for production in Fizz
are more relevant because prerendering is not really a dev-time task. If
you want the ability to reason about errors or postpones that happen
during a prerender having component stacks to interrogate is helpful and
these component stacks need to be available in production otherwise you
are really never going to see them. (it is possible that you could do
dev-mode prerenders but we don't expect this to be a common dev mode
workflow)

To better support the prerender use case and to make error logging in
Fizz more useful the following changes have been made

1. `onPostpone` now accepts a second `postponeInfo` argument which will
contain a componentStack. Postpones always originate from a component
render so the stack should be consistently available. The type however
will indicate the stack is optional so we can remove them in the future
if we decide the overhead is the wrong tradeoff in certain cases
2. `onError` now accepts a second `errorInfo` argument which may contain
a componentStack. If an error originated from a component a stack will
be included in the following cases.

This change entails tracking the component hierarchy in prod builds now.
While this isn't cost free it is implemented in a relatively lean
manner. Deferring the most expensive work (reifying the stack) until we
are actually in an error pathway.

In the course of implementing this change a number of simplifications
were made to the code which should make the stack tracking more
resilient. We no longer use a module global to curry the stack up to
some handler. This was delicate because you needed to always reset it
properly. We now curry the stack on the task itself.

Another change made was to track the component stack on SuspenseBoundary
instances so that we can provide the stack when aborting suspense
boundaries to help you determine which ones were affected by an abort.

DiffTrain build for [63310df](63310df)
@josephsavona
Copy link
Contributor

Just a heads up that this is causing a performance regression and we may need to back out or fix forward.

neildhar added a commit to neildhar/react that referenced this pull request Dec 19, 2023
…`onError` and `onPostpone` when in dev mode or during prerenders in prod mode (facebook#27761)"

Summary:
Backing out this change since it is the most likely culprit for a significant observed performance regression.

Original commit changeset: bf4ae59939dc

Original Phabricator Diffs: D52225293, D52290859

Reviewed By: josephsavona, fullstackhacker

Differential Revision: D52307383
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
… mode or during prerenders in prod mode (facebook#27761)

Historically React would produce component stacks for dev builds only.
There is a cost to tracking component stacks and given the prod builds
try to optimize runtime performance these stacks were left out. More
recently React added production component stacks to Fiber in because it
can be immensely helpful in tracking down hard to debug production
issues. Fizz was not updated to have a similar behavior.

With the advent of prerendering however stacks for production in Fizz
are more relevant because prerendering is not really a dev-time task. If
you want the ability to reason about errors or postpones that happen
during a prerender having component stacks to interrogate is helpful and
these component stacks need to be available in production otherwise you
are really never going to see them. (it is possible that you could do
dev-mode prerenders but we don't expect this to be a common dev mode
workflow)

To better support the prerender use case and to make error logging in
Fizz more useful the following changes have been made

1. `onPostpone` now accepts a second `postponeInfo` argument which will
contain a componentStack. Postpones always originate from a component
render so the stack should be consistently available. The type however
will indicate the stack is optional so we can remove them in the future
if we decide the overhead is the wrong tradeoff in certain cases
2. `onError` now accepts a second `errorInfo` argument which may contain
a componentStack. If an error originated from a component a stack will
be included in the following cases.

This change entails tracking the component hierarchy in prod builds now.
While this isn't cost free it is implemented in a relatively lean
manner. Deferring the most expensive work (reifying the stack) until we
are actually in an error pathway.

In the course of implementing this change a number of simplifications
were made to the code which should make the stack tracking more
resilient. We no longer use a module global to curry the stack up to
some handler. This was delicate because you needed to always reset it
properly. We now curry the stack on the task itself.

Another change made was to track the component stack on SuspenseBoundary
instances so that we can provide the stack when aborting suspense
boundaries to help you determine which ones were affected by an abort.
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
… mode or during prerenders in prod mode (#27761)

Historically React would produce component stacks for dev builds only.
There is a cost to tracking component stacks and given the prod builds
try to optimize runtime performance these stacks were left out. More
recently React added production component stacks to Fiber in because it
can be immensely helpful in tracking down hard to debug production
issues. Fizz was not updated to have a similar behavior.

With the advent of prerendering however stacks for production in Fizz
are more relevant because prerendering is not really a dev-time task. If
you want the ability to reason about errors or postpones that happen
during a prerender having component stacks to interrogate is helpful and
these component stacks need to be available in production otherwise you
are really never going to see them. (it is possible that you could do
dev-mode prerenders but we don't expect this to be a common dev mode
workflow)

To better support the prerender use case and to make error logging in
Fizz more useful the following changes have been made

1. `onPostpone` now accepts a second `postponeInfo` argument which will
contain a componentStack. Postpones always originate from a component
render so the stack should be consistently available. The type however
will indicate the stack is optional so we can remove them in the future
if we decide the overhead is the wrong tradeoff in certain cases
2. `onError` now accepts a second `errorInfo` argument which may contain
a componentStack. If an error originated from a component a stack will
be included in the following cases.

This change entails tracking the component hierarchy in prod builds now.
While this isn't cost free it is implemented in a relatively lean
manner. Deferring the most expensive work (reifying the stack) until we
are actually in an error pathway.

In the course of implementing this change a number of simplifications
were made to the code which should make the stack tracking more
resilient. We no longer use a module global to curry the stack up to
some handler. This was delicate because you needed to always reset it
properly. We now curry the stack on the task itself.

Another change made was to track the component stack on SuspenseBoundary
instances so that we can provide the stack when aborting suspense
boundaries to help you determine which ones were affected by an abort.

DiffTrain build for commit 63310df.
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