Skip to content

Conversation

sebmarkbage
Copy link
Collaborator

@sebmarkbage sebmarkbage commented May 7, 2025

Stacked on #33135.

This encodes the line/column of the enclosing function as part of the stack traces. When that information is available.

I adjusted the fake function code generation so that the beginning of the arrow function aligns with these as much as possible.

This ensures that when the browser tries to look up the line/column of the enclosing function, such as for getting the function name, it gets the right one. If we can't get the enclosing line/column, then we encode it at the beginning of the file. This is likely to get a miss in the source map identifiers, which means that the function name gets extracted from the runtime name instead which is better.

Another thing where this is used is the in the Performance Track. Ideally that would be fixed by https://issues.chromium.org/u/1/issues/415968771 but the enclosing information is useful for other things like the function name resolution anyway.

We can also use this for the "View source for this element" in React DevTools.

@sebmarkbage sebmarkbage requested a review from eps1lon May 7, 2025 04:23
@github-actions github-actions bot added the React Core Team Opened by a member of the React Core Team label May 7, 2025
@react-sizebot
Copy link

react-sizebot commented May 7, 2025

Comparing: 0ff1d13...bcb36b8

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 +0.11% 1.83 kB 1.83 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 528.26 kB 528.26 kB = 93.16 kB 93.16 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.69 kB 6.69 kB +0.05% 1.83 kB 1.83 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js = 645.02 kB 645.02 kB = 113.47 kB 113.47 kB
facebook-www/ReactDOM-prod.classic.js = 673.72 kB 673.72 kB = 118.32 kB 118.32 kB
facebook-www/ReactDOM-prod.modern.js = 664.00 kB 664.00 kB = 116.73 kB 116.73 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-dom-esm/cjs/react-server-dom-esm-client.browser.development.js +1.89% 96.57 kB 98.39 kB +1.52% 18.37 kB 18.65 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js +1.89% 96.62 kB 98.44 kB +1.52% 18.39 kB 18.67 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js +1.88% 96.93 kB 98.75 kB +1.54% 18.32 kB 18.61 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js +1.88% 96.98 kB 98.80 kB +1.54% 18.35 kB 18.63 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js +1.85% 98.76 kB 100.58 kB +1.50% 18.76 kB 19.04 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js +1.85% 98.81 kB 100.63 kB +1.51% 18.78 kB 19.06 kB
oss-stable-semver/react-client/cjs/react-client-flight.development.js +1.84% 98.25 kB 100.06 kB +1.62% 18.10 kB 18.39 kB
oss-stable/react-client/cjs/react-client-flight.development.js +1.84% 98.28 kB 100.08 kB +1.61% 18.12 kB 18.41 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js +1.84% 99.31 kB 101.14 kB +1.47% 18.90 kB 19.18 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js +1.83% 99.36 kB 101.19 kB +1.47% 18.92 kB 19.20 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js +1.81% 100.72 kB 102.54 kB +1.47% 19.13 kB 19.41 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js +1.81% 100.72 kB 102.54 kB +1.47% 19.13 kB 19.41 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js +1.80% 101.23 kB 103.05 kB +1.45% 19.15 kB 19.43 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js +1.80% 101.23 kB 103.05 kB +1.45% 19.15 kB 19.43 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js +1.78% 102.52 kB 104.34 kB +1.43% 19.46 kB 19.74 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js +1.78% 102.52 kB 104.34 kB +1.43% 19.46 kB 19.74 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js +1.76% 103.87 kB 105.69 kB +1.41% 19.64 kB 19.91 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js +1.76% 103.87 kB 105.69 kB +1.41% 19.64 kB 19.91 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js +1.73% 105.62 kB 107.44 kB +1.42% 19.95 kB 20.23 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js +1.73% 105.62 kB 107.44 kB +1.42% 19.95 kB 20.23 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js +1.72% 105.71 kB 107.53 kB +1.42% 19.98 kB 20.27 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js +1.72% 105.71 kB 107.53 kB +1.42% 19.98 kB 20.27 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js +1.71% 106.61 kB 108.43 kB +1.41% 19.90 kB 20.18 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js +1.71% 106.61 kB 108.43 kB +1.41% 19.90 kB 20.18 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js +1.70% 107.36 kB 109.18 kB +1.33% 20.39 kB 20.66 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js +1.69% 107.72 kB 109.54 kB +1.35% 20.33 kB 20.60 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js +1.69% 107.94 kB 109.77 kB +1.39% 20.16 kB 20.44 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js +1.69% 107.94 kB 109.77 kB +1.39% 20.16 kB 20.44 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js +1.66% 109.54 kB 111.37 kB +1.31% 20.78 kB 21.05 kB
oss-experimental/react-client/cjs/react-client-flight.development.js +1.66% 109.01 kB 110.81 kB +1.26% 20.17 kB 20.42 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js +1.66% 110.10 kB 111.92 kB +1.36% 20.91 kB 21.20 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js +1.64% 111.44 kB 113.27 kB +1.34% 21.13 kB 21.42 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js +1.63% 111.96 kB 113.78 kB +1.36% 21.16 kB 21.44 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js +1.61% 113.24 kB 115.07 kB +1.36% 21.49 kB 21.79 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js +1.59% 114.59 kB 116.42 kB +1.33% 21.64 kB 21.93 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js +1.58% 133.90 kB 136.02 kB +1.40% 31.39 kB 31.83 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js +1.58% 133.93 kB 136.04 kB +1.40% 31.41 kB 31.85 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js +1.57% 116.34 kB 118.16 kB +1.34% 21.99 kB 22.29 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js +1.57% 116.43 kB 118.25 kB +1.33% 22.03 kB 22.32 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js +1.55% 117.34 kB 119.16 kB +1.31% 21.91 kB 22.20 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js +1.54% 118.67 kB 120.49 kB +1.29% 22.16 kB 22.45 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js +1.45% 145.63 kB 147.75 kB +1.34% 34.24 kB 34.70 kB
oss-stable-semver/react-server/cjs/react-server-flight.development.js +0.47% 104.76 kB 105.26 kB +0.33% 19.55 kB 19.62 kB
oss-stable/react-server/cjs/react-server-flight.development.js +0.47% 104.76 kB 105.26 kB +0.33% 19.55 kB 19.62 kB
oss-experimental/react-server/cjs/react-server-flight.development.js +0.44% 111.59 kB 112.09 kB +0.32% 20.75 kB 20.82 kB
oss-experimental/react-markup/cjs/react-markup.react-server.development.js +0.43% 541.51 kB 543.81 kB +0.35% 97.20 kB 97.53 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-server.browser.development.js +0.34% 143.65 kB 144.14 kB +0.25% 26.79 kB 26.86 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-server.browser.development.js +0.34% 143.65 kB 144.14 kB +0.25% 26.79 kB 26.86 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-server.edge.development.js +0.33% 147.46 kB 147.96 kB +0.25% 27.38 kB 27.45 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-server.edge.development.js +0.33% 147.46 kB 147.96 kB +0.25% 27.38 kB 27.45 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-server.node.development.js +0.33% 148.05 kB 148.54 kB +0.24% 27.64 kB 27.71 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-server.node.development.js +0.33% 148.05 kB 148.54 kB +0.24% 27.64 kB 27.71 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-server.node.development.js +0.33% 148.07 kB 148.56 kB +0.23% 27.61 kB 27.68 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-server.node.development.js +0.33% 148.07 kB 148.56 kB +0.23% 27.61 kB 27.68 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-server.browser.development.js +0.33% 150.49 kB 150.99 kB +0.24% 27.99 kB 28.05 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.browser.development.js +0.33% 151.39 kB 151.88 kB +0.25% 28.11 kB 28.17 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.browser.development.js +0.33% 151.39 kB 151.88 kB +0.25% 28.11 kB 28.17 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.development.js +0.33% 151.93 kB 152.42 kB +0.26% 28.24 kB 28.31 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.development.js +0.33% 151.93 kB 152.42 kB +0.26% 28.24 kB 28.31 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.unbundled.development.js +0.32% 154.74 kB 155.23 kB +0.24% 28.73 kB 28.80 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.unbundled.development.js +0.32% 154.74 kB 155.23 kB +0.24% 28.73 kB 28.80 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-server.edge.development.js +0.32% 154.94 kB 155.44 kB +0.24% 28.68 kB 28.75 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-server.node.development.js +0.32% 155.19 kB 155.68 kB +0.22% 28.96 kB 29.02 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-server.node.development.js +0.32% 155.21 kB 155.70 kB +0.22% 28.96 kB 29.02 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js +0.32% 155.21 kB 155.71 kB +0.25% 28.73 kB 28.80 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js +0.32% 155.21 kB 155.71 kB +0.25% 28.73 kB 28.80 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.edge.development.js +0.32% 155.24 kB 155.73 kB +0.25% 28.72 kB 28.80 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.edge.development.js +0.32% 155.24 kB 155.73 kB +0.25% 28.72 kB 28.80 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.development.js +0.32% 155.88 kB 156.37 kB +0.26% 29.00 kB 29.08 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.development.js +0.32% 155.88 kB 156.37 kB +0.26% 29.00 kB 29.08 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js +0.32% 155.95 kB 156.44 kB +0.24% 29.02 kB 29.09 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js +0.32% 155.95 kB 156.44 kB +0.24% 29.02 kB 29.09 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.browser.development.js +0.31% 158.23 kB 158.73 kB +0.23% 29.36 kB 29.43 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.development.js +0.31% 158.78 kB 159.27 kB +0.23% 29.49 kB 29.55 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.unbundled.development.js +0.31% 161.88 kB 162.37 kB +0.23% 30.00 kB 30.07 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js +0.30% 162.69 kB 163.19 kB +0.22% 30.02 kB 30.09 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.edge.development.js +0.30% 162.72 kB 163.21 kB +0.22% 30.02 kB 30.09 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.development.js +0.30% 163.02 kB 163.51 kB +0.23% 30.29 kB 30.36 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js +0.30% 163.09 kB 163.58 kB +0.23% 30.30 kB 30.37 kB

Generated by 🚫 dangerJS against bcb36b8

Comment on lines 1286 to 1293
action = createFakeServerFunction(
functionName,
filename,
sourceMap,
line,
col,
enclosingLine,
enclosingCol,
env,
action,
Copy link
Collaborator

Choose a reason for hiding this comment

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

We want the fake function to be generated based on both like we do in ReactFlightClient.

Right now this causes devtools to point to the beginning of the module since that's the enclosing line number of the registerServerReference call.

CleanShot.2025-05-07.at.12.39.37.mp4

Before this change we pointed at the declaration of increment since that's where registerServerReference call sourcemaps to:

1   | 'use server'
      ^ maps to 'use server'
      enclosing line number
      we don't want that
... |
29  | registerServerReference(increment, "...", "increment");
      ^ maps maps to `function increment() {}`
      line number
      we want that

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 guess we never want the enclosing because the line in the location field always represents the enclosing, which is the only thing we encode here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Reverted that part.

Copy link
Collaborator

Choose a reason for hiding this comment

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

We don't need it for this specific case I believe but generally we'd still want the enclosing number for the case where bundlers move modules into functions that their runtime executes.

We already have this problem today where these functions pollute the stackframes of errors that happen during module evaluation e.g. at [app-rsc] [project]/app/page.tsx (app/page.tsx:1:2). We want the correct enclosing line number for that case as well so that we can map these function names to something appropriate i.e. no name so that the stackframe just ends up as at app/page.tsx:1:2.

Though one insight here is that for Server functions we never want to use the enclosing scope for name mapping but the actual location. The enclosing scope would map to the module when we want the name at the callsite. But I guess we're not even using sourcemaps to get the name today and instead use the transported original function name directly.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

There's never anything that executes inside the function so there's never anything that gets the name from source mapping. But if for example printing it in the console printed the name from the source mapped source then it would source map it but even then it would be correct because it is the enclosing line that we're modeling in the fake function. The registerServerReference is at the enclosing location and its callsite location is therefore modeling the enclosing location which we are then modeling with the fake function's enclosing location.

We just have to be careful if we do something like extract the enclosing and passing that as "location" meta data. I think maybe that's the modeling issue here. The server should actually encode the location as the enclosing line.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

If we don't have the ability to get enclosing line/column we encode it as
zero. This will point to the beginning of the file which is likely to cause
a miss in source mapping to an identifier which is better since it falls
back to getting the name of the function in that case instead.
@sebmarkbage sebmarkbage merged commit 4a70286 into facebook:main May 7, 2025
239 checks passed
github-actions bot pushed a commit that referenced this pull request May 7, 2025
… fake function (#33136)

Stacked on #33135.

This encodes the line/column of the enclosing function as part of the
stack traces. When that information is available.

I adjusted the fake function code generation so that the beginning of
the arrow function aligns with these as much as possible.

This ensures that when the browser tries to look up the line/column of
the enclosing function, such as for getting the function name, it gets
the right one. If we can't get the enclosing line/column, then we encode
it at the beginning of the file. This is likely to get a miss in the
source map identifiers, which means that the function name gets
extracted from the runtime name instead which is better.

Another thing where this is used is the in the Performance Track.
Ideally that would be fixed by
https://issues.chromium.org/u/1/issues/415968771 but the enclosing
information is useful for other things like the function name resolution
anyway.

We can also use this for the "View source for this element" in React
DevTools.

DiffTrain build for [4a70286](4a70286)
sebmarkbage added a commit that referenced this pull request May 7, 2025
…Site (#33141)

Follow up to #33136.

This clarifies in the types where the conversion happens from a CallSite
which we use to simulate getting the enclosing line/col to a
FunctionLocation which doesn't represent a CallSite but actually just
the function which only has an enclosing line/col.
github-actions bot pushed a commit that referenced this pull request May 7, 2025
…Site (#33141)

Follow up to #33136.

This clarifies in the types where the conversion happens from a CallSite
which we use to simulate getting the enclosing line/col to a
FunctionLocation which doesn't represent a CallSite but actually just
the function which only has an enclosing line/col.

DiffTrain build for [a437c99](a437c99)
sebmarkbage added a commit that referenced this pull request May 13, 2025
…ackTrace (#33143)

When we get the source location for "View source for this element" we
should be using the enclosing function of the callsite of the child. So
that we don't just point to some random line within the component.

This is similar to the technique in #33136.

This technique is now really better than the fake throw technique, when
available. So I now favor the owner technique. The only problem it's
only available in DEV and only if it has a child that's owned (and not
filtered).

We could implement this same technique for the error that's thrown in
the fake throwing solution. However, we really shouldn't need that at
all because for client components we should be able to call
`inspect(fn)` at least in Chrome which is even better.
github-actions bot pushed a commit that referenced this pull request May 13, 2025
…ackTrace (#33143)

When we get the source location for "View source for this element" we
should be using the enclosing function of the callsite of the child. So
that we don't just point to some random line within the component.

This is similar to the technique in #33136.

This technique is now really better than the fake throw technique, when
available. So I now favor the owner technique. The only problem it's
only available in DEV and only if it has a child that's owned (and not
filtered).

We could implement this same technique for the error that's thrown in
the fake throwing solution. However, we really shouldn't need that at
all because for client components we should be able to call
`inspect(fn)` at least in Chrome which is even better.

DiffTrain build for [997c7bc](997c7bc)
github-actions bot pushed a commit to code/lib-react that referenced this pull request May 13, 2025
…ackTrace (facebook#33143)

When we get the source location for "View source for this element" we
should be using the enclosing function of the callsite of the child. So
that we don't just point to some random line within the component.

This is similar to the technique in facebook#33136.

This technique is now really better than the fake throw technique, when
available. So I now favor the owner technique. The only problem it's
only available in DEV and only if it has a child that's owned (and not
filtered).

We could implement this same technique for the error that's thrown in
the fake throwing solution. However, we really shouldn't need that at
all because for client components we should be able to call
`inspect(fn)` at least in Chrome which is even better.

DiffTrain build for [997c7bc](facebook@997c7bc)
jackpope pushed a commit that referenced this pull request Jul 16, 2025
…ackTrace (#33143)

When we get the source location for "View source for this element" we
should be using the enclosing function of the callsite of the child. So
that we don't just point to some random line within the component.

This is similar to the technique in #33136.

This technique is now really better than the fake throw technique, when
available. So I now favor the owner technique. The only problem it's
only available in DEV and only if it has a child that's owned (and not
filtered).

We could implement this same technique for the error that's thrown in
the fake throwing solution. However, we really shouldn't need that at
all because for client components we should be able to call
`inspect(fn)` at least in Chrome which is even better.
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