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

[Flight] Normalize Stack Using Fake Evals #30401

Merged
merged 3 commits into from
Jul 22, 2024

Conversation

sebmarkbage
Copy link
Collaborator

@sebmarkbage sebmarkbage commented Jul 19, 2024

Stacked on #30400 and #30369

Previously we were using fake evals to recreate a stack for console replaying and thrown errors. However, for owner stacks we just used the raw string that came from the server.

This means that the format of the owner stack could include different formats. Like Spidermonkey format for the client components and V8 for the server components. This means that this stack can't be parsed natively by the browser like when printing them as error like in #30289. Additionally, since there's no source file registered with that name and no source mapping url, it can't be source mapped.

Before:

before-firefox

Instead, we need to create a fake stack like we do for the other things. That way when it's printed as an Error it gets source mapped. It also means that the format is consistently in the native format of the current browser.

After:

after-firefox

So this is nice because you can just take the result from captureOwnerStack() and append it to an Error stack and print it natively. E.g. this is what React DevTools will do.

If you want to parse and present it yourself though it's a bit awkward though. The captureOwnerStack() API now includes a bunch of rsc://React/ URLs. These don't really have any direct connection to the source map. Only the browser knows this connection from the eval. You basically have to strip the prefix and then manually pass the remainder to your own findSourceMapURL.

Another awkward part is that since Safari doesn't support eval sourceURL exposed into error.stack - it means that captureOwnerStack() get an empty location for server components since the fake eval doesn't work there. That's not a big deal since these stacks are already broken even for client modules for many because the eval-source-map strategy in Webpack doesn't work in Safari for this same reason.

A lot of this refactoring is just clarifying that there's three kind of ReactComponentInfo fields:

  • stack - The raw stack as described on the original server.
  • debugStack - The Error object containing the stack as represented in the current client as fake evals.
  • debugTask - The same thing as debugStack but described in terms of a native console.createTask.

Copy link

vercel bot commented Jul 19, 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 Jul 22, 2024 2:59pm

@react-sizebot
Copy link

react-sizebot commented Jul 19, 2024

Comparing: 792f192...25af710

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.68 kB 6.68 kB = 1.82 kB 1.82 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 499.44 kB 499.44 kB = 89.59 kB 89.59 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.69 kB 6.69 kB = 1.83 kB 1.83 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js = 504.26 kB 504.26 kB = 90.30 kB 90.30 kB
facebook-www/ReactDOM-prod.classic.js = 599.20 kB 599.20 kB = 105.79 kB 105.79 kB
facebook-www/ReactDOM-prod.modern.js = 573.37 kB 573.37 kB = 101.68 kB 101.68 kB
oss-stable-rc/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js +5.14% 98.52 kB 103.59 kB +7.91% 21.63 kB 23.34 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js +5.14% 98.52 kB 103.59 kB +7.91% 21.63 kB 23.34 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js +5.14% 98.52 kB 103.59 kB +7.91% 21.63 kB 23.34 kB
oss-stable-rc/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js +4.32% 69.69 kB 72.70 kB +6.45% 12.89 kB 13.72 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js +4.32% 69.69 kB 72.70 kB +6.45% 12.89 kB 13.72 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js +4.32% 69.69 kB 72.70 kB +6.45% 12.89 kB 13.72 kB
oss-stable-rc/react-client/cjs/react-client-flight.development.js +4.24% 73.27 kB 76.38 kB +6.21% 13.25 kB 14.07 kB
oss-stable-semver/react-client/cjs/react-client-flight.development.js +4.24% 73.27 kB 76.38 kB +6.21% 13.25 kB 14.07 kB
oss-stable/react-client/cjs/react-client-flight.development.js +4.24% 73.27 kB 76.38 kB +6.21% 13.25 kB 14.07 kB
oss-stable-rc/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js +4.21% 71.54 kB 74.55 kB +6.42% 13.26 kB 14.11 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js +4.21% 71.54 kB 74.55 kB +6.42% 13.26 kB 14.11 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js +4.21% 71.54 kB 74.55 kB +6.42% 13.26 kB 14.11 kB
oss-stable-rc/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js +4.18% 71.99 kB 75.00 kB +6.24% 13.41 kB 14.24 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js +4.18% 71.99 kB 75.00 kB +6.24% 13.41 kB 14.24 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js +4.18% 71.99 kB 75.00 kB +6.24% 13.41 kB 14.24 kB
oss-stable-rc/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js +4.17% 74.63 kB 77.74 kB +5.78% 13.97 kB 14.78 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js +4.17% 74.63 kB 77.74 kB +5.78% 13.97 kB 14.78 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js +4.17% 74.63 kB 77.74 kB +5.78% 13.97 kB 14.78 kB
oss-stable-rc/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.unbundled.development.js +4.09% 76.04 kB 79.15 kB +5.66% 14.28 kB 15.08 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.unbundled.development.js +4.09% 76.04 kB 79.15 kB +5.66% 14.28 kB 15.08 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.unbundled.development.js +4.09% 76.04 kB 79.15 kB +5.66% 14.28 kB 15.08 kB
oss-stable-rc/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js +4.05% 76.84 kB 79.95 kB +5.60% 14.45 kB 15.26 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js +4.05% 76.84 kB 79.95 kB +5.60% 14.45 kB 15.26 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js +4.05% 76.84 kB 79.95 kB +5.60% 14.45 kB 15.26 kB
oss-stable-rc/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js +3.98% 78.20 kB 81.31 kB +5.71% 14.69 kB 15.53 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js +3.98% 78.20 kB 81.31 kB +5.71% 14.69 kB 15.53 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js +3.98% 78.20 kB 81.31 kB +5.71% 14.69 kB 15.53 kB
oss-stable-rc/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js +3.97% 78.22 kB 81.33 kB +5.71% 14.67 kB 15.51 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js +3.97% 78.22 kB 81.33 kB +5.71% 14.67 kB 15.51 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js +3.97% 78.22 kB 81.33 kB +5.71% 14.67 kB 15.51 kB
oss-stable-rc/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js +3.89% 79.92 kB 83.03 kB +5.45% 14.79 kB 15.60 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js +3.89% 79.92 kB 83.03 kB +5.45% 14.79 kB 15.60 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js +3.89% 79.92 kB 83.03 kB +5.45% 14.79 kB 15.60 kB
oss-stable-rc/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js +3.85% 80.71 kB 83.81 kB +5.41% 14.97 kB 15.78 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js +3.85% 80.71 kB 83.81 kB +5.41% 14.97 kB 15.78 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js +3.85% 80.71 kB 83.81 kB +5.41% 14.97 kB 15.78 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js +2.01% 107.95 kB 110.12 kB +2.30% 24.25 kB 24.81 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable-rc/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js +5.14% 98.52 kB 103.59 kB +7.91% 21.63 kB 23.34 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js +5.14% 98.52 kB 103.59 kB +7.91% 21.63 kB 23.34 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js +5.14% 98.52 kB 103.59 kB +7.91% 21.63 kB 23.34 kB
oss-stable-rc/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js +4.32% 69.69 kB 72.70 kB +6.45% 12.89 kB 13.72 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js +4.32% 69.69 kB 72.70 kB +6.45% 12.89 kB 13.72 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js +4.32% 69.69 kB 72.70 kB +6.45% 12.89 kB 13.72 kB
oss-stable-rc/react-client/cjs/react-client-flight.development.js +4.24% 73.27 kB 76.38 kB +6.21% 13.25 kB 14.07 kB
oss-stable-semver/react-client/cjs/react-client-flight.development.js +4.24% 73.27 kB 76.38 kB +6.21% 13.25 kB 14.07 kB
oss-stable/react-client/cjs/react-client-flight.development.js +4.24% 73.27 kB 76.38 kB +6.21% 13.25 kB 14.07 kB
oss-stable-rc/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js +4.21% 71.54 kB 74.55 kB +6.42% 13.26 kB 14.11 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js +4.21% 71.54 kB 74.55 kB +6.42% 13.26 kB 14.11 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js +4.21% 71.54 kB 74.55 kB +6.42% 13.26 kB 14.11 kB
oss-stable-rc/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js +4.18% 71.99 kB 75.00 kB +6.24% 13.41 kB 14.24 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js +4.18% 71.99 kB 75.00 kB +6.24% 13.41 kB 14.24 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js +4.18% 71.99 kB 75.00 kB +6.24% 13.41 kB 14.24 kB
oss-stable-rc/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js +4.17% 74.63 kB 77.74 kB +5.78% 13.97 kB 14.78 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js +4.17% 74.63 kB 77.74 kB +5.78% 13.97 kB 14.78 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js +4.17% 74.63 kB 77.74 kB +5.78% 13.97 kB 14.78 kB
oss-stable-rc/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.unbundled.development.js +4.09% 76.04 kB 79.15 kB +5.66% 14.28 kB 15.08 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.unbundled.development.js +4.09% 76.04 kB 79.15 kB +5.66% 14.28 kB 15.08 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.unbundled.development.js +4.09% 76.04 kB 79.15 kB +5.66% 14.28 kB 15.08 kB
oss-stable-rc/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js +4.05% 76.84 kB 79.95 kB +5.60% 14.45 kB 15.26 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js +4.05% 76.84 kB 79.95 kB +5.60% 14.45 kB 15.26 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js +4.05% 76.84 kB 79.95 kB +5.60% 14.45 kB 15.26 kB
oss-stable-rc/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js +3.98% 78.20 kB 81.31 kB +5.71% 14.69 kB 15.53 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js +3.98% 78.20 kB 81.31 kB +5.71% 14.69 kB 15.53 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js +3.98% 78.20 kB 81.31 kB +5.71% 14.69 kB 15.53 kB
oss-stable-rc/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js +3.97% 78.22 kB 81.33 kB +5.71% 14.67 kB 15.51 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js +3.97% 78.22 kB 81.33 kB +5.71% 14.67 kB 15.51 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js +3.97% 78.22 kB 81.33 kB +5.71% 14.67 kB 15.51 kB
oss-stable-rc/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js +3.89% 79.92 kB 83.03 kB +5.45% 14.79 kB 15.60 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js +3.89% 79.92 kB 83.03 kB +5.45% 14.79 kB 15.60 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js +3.89% 79.92 kB 83.03 kB +5.45% 14.79 kB 15.60 kB
oss-stable-rc/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js +3.85% 80.71 kB 83.81 kB +5.41% 14.97 kB 15.78 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js +3.85% 80.71 kB 83.81 kB +5.41% 14.97 kB 15.78 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js +3.85% 80.71 kB 83.81 kB +5.41% 14.97 kB 15.78 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js +2.01% 107.95 kB 110.12 kB +2.30% 24.25 kB 24.81 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js +1.47% 78.11 kB 79.26 kB +1.21% 14.91 kB 15.09 kB
oss-experimental/react-client/cjs/react-client-flight.development.js +1.44% 79.55 kB 80.70 kB +1.25% 14.68 kB 14.86 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js +1.43% 75.82 kB 76.90 kB +1.26% 14.38 kB 14.56 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js +1.42% 80.75 kB 81.90 kB +1.20% 15.40 kB 15.58 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js +1.40% 77.66 kB 78.75 kB +1.21% 14.79 kB 14.97 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.unbundled.development.js +1.40% 82.16 kB 83.31 kB +1.18% 15.72 kB 15.91 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js +1.38% 82.96 kB 84.11 kB +1.17% 15.89 kB 16.08 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js +1.36% 84.33 kB 85.47 kB +1.16% 16.18 kB 16.37 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js +1.36% 84.34 kB 85.49 kB +1.14% 16.16 kB 16.35 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js +1.33% 86.08 kB 87.22 kB +1.14% 16.25 kB 16.43 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js +1.32% 86.86 kB 88.01 kB +1.13% 16.43 kB 16.62 kB
oss-experimental/react-server/cjs/react-server-flight.development.js +1.25% 94.09 kB 95.27 kB +0.89% 17.47 kB 17.62 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-server.node.development.js +0.87% 134.57 kB 135.75 kB +0.65% 25.09 kB 25.25 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.browser.development.js +0.85% 137.79 kB 138.96 kB +0.60% 25.64 kB 25.80 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.development.js +0.85% 138.41 kB 139.58 kB +0.59% 25.82 kB 25.97 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.edge.development.js +0.84% 139.85 kB 141.03 kB +0.62% 25.96 kB 26.12 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js +0.84% 140.00 kB 141.18 kB +0.61% 26.02 kB 26.18 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.unbundled.development.js +0.83% 140.94 kB 142.11 kB +0.59% 26.07 kB 26.23 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.unbundled.development.js +0.83% 141.10 kB 142.28 kB +0.59% 26.14 kB 26.29 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.development.js +0.83% 142.05 kB 143.22 kB +0.58% 26.34 kB 26.49 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js +0.83% 142.19 kB 143.37 kB +0.57% 26.40 kB 26.55 kB
oss-experimental/react-html/cjs/react-html.react-server.development.js +0.52% 482.39 kB 484.89 kB +0.48% 87.32 kB 87.74 kB

Generated by 🚫 dangerJS against 523ef76

@sebmarkbage sebmarkbage requested a review from hoxyq July 19, 2024 03:41
@@ -0,0 +1,42 @@
/**
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 think it's likely that Fiber/Fizz/Flight OwnerStack.js merge into a shared helper for extracting a presentable string.

}
return stack.slice(startIdx, endIdx);
}

function filterDebugStack(error: Error): string {
Copy link
Collaborator Author

@sebmarkbage sebmarkbage Jul 19, 2024

Choose a reason for hiding this comment

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

This is different from the one in FlightOwnerStack which is for formatting the string for captureOwnerStack() for presentation.

This one is for formatting the string into the serializable stack field for serialization. This is turning into a structured form instead of a string in the follow up #30410.

This could be coming from the current server, however, this Error could also be one that includes fake stack frames it originated on another server. In this case we'd need to do something to reverse engineer it to get it back into its serialized form. E.g. stripping the rsc://React/ prefixes.

@sebmarkbage
Copy link
Collaborator Author

sebmarkbage commented Jul 20, 2024

There's three "urls/files" essentially:

  • The original source file. We get this from the source map.
  • The file that was loaded by the server. This could be the compiled output of Babel or even bundled which might represent a "chunk". In our fixture this has the same url as the original source file since it's not bundled but it doesn't have the same line/column numbers since it is transpiled.
  • The fake eval file that was generated by the Flight Client. This is file/chunk loaded by the server prefixed by rsc://React/.

While it would be enough for us to emit the original source file URL + original line number + column number in the stack to get it pointing to the right place, we don't actually have this information in React.

It is also not enough to point to the url loaded by the server, because the browser doesn't have access to this. E.g. if it's a bundled chunk that is never loaded by the browser. The browser only sees the fake eval and the source map pointing to the original source file. Even if it's not bundled and just transpiled we'd have the file but we'd not have the original line number.

We also need to generate more than one fake eval per file so we give it the + "?" + id suffix. We could just use this suffix to differentiate and then that might make it easier to parse the owner stack. You'd get an extra suffix but the right file path. The problem with that is that the way they're presented in the file view in browsers is next to each other which makes that view kind of useless. So the tradeoff is to make parsing owner stacks manually a bit more difficult by needing to remove the RSC specific prefix.

We already do this for recreating serialized errors.

This does it for stacks both in the stacks of parent components,
JSX callsites and owners.
This represents the stack trace as a native console.createTask object in
the current execution environment. Not as part of the serialized protocol.
This represents the stack in the current execution environment. As opposed
to the .stack property which represents the stack in the transport protocol.
@sebmarkbage sebmarkbage merged commit b15c198 into facebook:main Jul 22, 2024
187 checks passed
github-actions bot pushed a commit that referenced this pull request Jul 22, 2024
Stacked on #30400 and
#30369

Previously we were using fake evals to recreate a stack for console
replaying and thrown errors. However, for owner stacks we just used the
raw string that came from the server.

This means that the format of the owner stack could include different
formats. Like Spidermonkey format for the client components and V8 for
the server components. This means that this stack can't be parsed
natively by the browser like when printing them as error like in
#30289. Additionally, since
there's no source file registered with that name and no source mapping
url, it can't be source mapped.

Before:

<img width="1329" alt="before-firefox"
src="https://github.com/user-attachments/assets/cbe03f9c-96ac-48fb-b58f-f3a224a774f4">

Instead, we need to create a fake stack like we do for the other things.
That way when it's printed as an Error it gets source mapped. It also
means that the format is consistently in the native format of the
current browser.

After:

<img width="753" alt="after-firefox"
src="https://github.com/user-attachments/assets/b436f1f5-ca37-4203-b29f-df9828c9fad3">

So this is nice because you can just take the result from
`captureOwnerStack()` and append it to an `Error` stack and print it
natively. E.g. this is what React DevTools will do.

If you want to parse and present it yourself though it's a bit awkward
though. The `captureOwnerStack()` API now includes a bunch of
`rsc://React/` URLs. These don't really have any direct connection to
the source map. Only the browser knows this connection from the eval.
You basically have to strip the prefix and then manually pass the
remainder to your own `findSourceMapURL`.

Another awkward part is that since Safari doesn't support eval sourceURL
exposed into `error.stack` - it means that `captureOwnerStack()` get an
empty location for server components since the fake eval doesn't work
there. That's not a big deal since these stacks are already broken even
for client modules for many because the `eval-source-map` strategy in
Webpack doesn't work in Safari for this same reason.

A lot of this refactoring is just clarifying that there's three kind of
ReactComponentInfo fields:

- `stack` - The raw stack as described on the original server.
- `debugStack` - The Error object containing the stack as represented in
the current client as fake evals.
- `debugTask` - The same thing as `debugStack` but described in terms of
a native `console.createTask`.

DiffTrain build for [b15c198](b15c198)
sebmarkbage added a commit that referenced this pull request Jul 22, 2024
)

Stacked on #30401.

Previously we were transferring the original V8 stack trace string to
the client and then parsing it there. However, really the server is the
one that knows what format it is and it should be able to vary by server
environment.

We also don't use the raw string anymore (at least not in
enableOwnerStacks). We always create the native Error stacks.

The string also made it unclear which environment it is and it was
tempting to just use it as is.

Instead I parse it on the server and make it a structured stack in the
transfer format. It also makes it clear that it needs to be formatted in
the current environment before presented.
felixshiftellecon added a commit to felixshiftellecon/react that referenced this pull request Jul 24, 2024
…ebook#30410)

Stacked on facebook#30401.

Previously we were transferring the original V8 stack trace string to
the client and then parsing it there. However, really the server is the
one that knows what format it is and it should be able to vary by server
environment.

We also don't use the raw string anymore (at least not in
enableOwnerStacks). We always create the native Error stacks.

The string also made it unclear which environment it is and it was
tempting to just use it as is.

Instead I parse it on the server and make it a structured stack in the
transfer format. It also makes it clear that it needs to be formatted in
the current environment before presented.
felixshiftellecon added a commit to felixshiftellecon/react that referenced this pull request Jul 24, 2024
Stacked on facebook#30400 and
facebook#30369

Previously we were using fake evals to recreate a stack for console
replaying and thrown errors. However, for owner stacks we just used the
raw string that came from the server.

This means that the format of the owner stack could include different
formats. Like Spidermonkey format for the client components and V8 for
the server components. This means that this stack can't be parsed
natively by the browser like when printing them as error like in
facebook#30289. Additionally, since
there's no source file registered with that name and no source mapping
url, it can't be source mapped.

Before:

<img width="1329" alt="before-firefox"
src="https://github.com/user-attachments/assets/cbe03f9c-96ac-48fb-b58f-f3a224a774f4">

Instead, we need to create a fake stack like we do for the other things.
That way when it's printed as an Error it gets source mapped. It also
means that the format is consistently in the native format of the
current browser.

After:

<img width="753" alt="after-firefox"
src="https://github.com/user-attachments/assets/b436f1f5-ca37-4203-b29f-df9828c9fad3">

So this is nice because you can just take the result from
`captureOwnerStack()` and append it to an `Error` stack and print it
natively. E.g. this is what React DevTools will do.

If you want to parse and present it yourself though it's a bit awkward
though. The `captureOwnerStack()` API now includes a bunch of
`rsc://React/` URLs. These don't really have any direct connection to
the source map. Only the browser knows this connection from the eval.
You basically have to strip the prefix and then manually pass the
remainder to your own `findSourceMapURL`.

Another awkward part is that since Safari doesn't support eval sourceURL
exposed into `error.stack` - it means that `captureOwnerStack()` get an
empty location for server components since the fake eval doesn't work
there. That's not a big deal since these stacks are already broken even
for client modules for many because the `eval-source-map` strategy in
Webpack doesn't work in Safari for this same reason.

A lot of this refactoring is just clarifying that there's three kind of
ReactComponentInfo fields:

- `stack` - The raw stack as described on the original server.
- `debugStack` - The Error object containing the stack as represented in
the current client as fake evals.
- `debugTask` - The same thing as `debugStack` but described in terms of
a native `console.createTask`.
felixshiftellecon added a commit to felixshiftellecon/react that referenced this pull request Jul 24, 2024
…ebook#30410)

Stacked on facebook#30401.

Previously we were transferring the original V8 stack trace string to
the client and then parsing it there. However, really the server is the
one that knows what format it is and it should be able to vary by server
environment.

We also don't use the raw string anymore (at least not in
enableOwnerStacks). We always create the native Error stacks.

The string also made it unclear which environment it is and it was
tempting to just use it as is.

Instead I parse it on the server and make it a structured stack in the
transfer format. It also makes it clear that it needs to be formatted in
the current environment before presented.
felixshiftellecon added a commit to felixshiftellecon/react that referenced this pull request Jul 24, 2024
Stacked on facebook#30400 and
facebook#30369

Previously we were using fake evals to recreate a stack for console
replaying and thrown errors. However, for owner stacks we just used the
raw string that came from the server.

This means that the format of the owner stack could include different
formats. Like Spidermonkey format for the client components and V8 for
the server components. This means that this stack can't be parsed
natively by the browser like when printing them as error like in
facebook#30289. Additionally, since
there's no source file registered with that name and no source mapping
url, it can't be source mapped.

Before:

<img width="1329" alt="before-firefox"
src="https://github.com/user-attachments/assets/cbe03f9c-96ac-48fb-b58f-f3a224a774f4">

Instead, we need to create a fake stack like we do for the other things.
That way when it's printed as an Error it gets source mapped. It also
means that the format is consistently in the native format of the
current browser.

After:

<img width="753" alt="after-firefox"
src="https://github.com/user-attachments/assets/b436f1f5-ca37-4203-b29f-df9828c9fad3">

So this is nice because you can just take the result from
`captureOwnerStack()` and append it to an `Error` stack and print it
natively. E.g. this is what React DevTools will do.

If you want to parse and present it yourself though it's a bit awkward
though. The `captureOwnerStack()` API now includes a bunch of
`rsc://React/` URLs. These don't really have any direct connection to
the source map. Only the browser knows this connection from the eval.
You basically have to strip the prefix and then manually pass the
remainder to your own `findSourceMapURL`.

Another awkward part is that since Safari doesn't support eval sourceURL
exposed into `error.stack` - it means that `captureOwnerStack()` get an
empty location for server components since the fake eval doesn't work
there. That's not a big deal since these stacks are already broken even
for client modules for many because the `eval-source-map` strategy in
Webpack doesn't work in Safari for this same reason.

A lot of this refactoring is just clarifying that there's three kind of
ReactComponentInfo fields:

- `stack` - The raw stack as described on the original server.
- `debugStack` - The Error object containing the stack as represented in
the current client as fake evals.
- `debugTask` - The same thing as `debugStack` but described in terms of
a native `console.createTask`.
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.

4 participants