Skip to content

Conversation

unstubbable
Copy link
Collaborator

@unstubbable unstubbable commented Mar 10, 2025

This is a follow-up for #32534 to ensure that calling registerServerReference from the client builds with a server reference does not overwrite the bind method that was previously defined by the Flight Server.

As was already the case with #32534, the compiler must ensure that the client-side registerServerReference is called after the server-side registerServerReference is called.

As a follow-up for facebook#32534 this ensures that
calling `registerServerReference` from the client
builds with a server reference does not overwrite the `bind` method that
was previously defined by the Flight Server.

As was already the case with facebook#32534, the compiler must ensure that the
client-side `registerServerReference` is called after the server-side
`registerServerReference` is called.
@react-sizebot
Copy link

react-sizebot commented Mar 10, 2025

Comparing: d331ba0...f0f4bed

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.83 kB 1.83 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 518.54 kB 518.54 kB = 92.45 kB 92.45 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 = 589.31 kB 589.31 kB = 104.91 kB 104.91 kB
facebook-www/ReactDOM-prod.classic.js = 642.76 kB 642.76 kB = 113.01 kB 113.01 kB
facebook-www/ReactDOM-prod.modern.js = 633.08 kB 633.08 kB = 111.44 kB 111.44 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-client/cjs/react-client-flight.production.js +0.90% 57.59 kB 58.12 kB +0.90% 10.71 kB 10.81 kB
oss-stable/react-client/cjs/react-client-flight.production.js +0.90% 57.62 kB 58.14 kB +0.90% 10.73 kB 10.83 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js +0.90% 54.16 kB 54.65 kB +0.73% 11.12 kB 11.20 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js +0.90% 54.16 kB 54.65 kB +0.73% 11.12 kB 11.20 kB
oss-experimental/react-client/cjs/react-client-flight.production.js +0.90% 58.08 kB 58.60 kB +0.83% 10.81 kB 10.90 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js +0.89% 54.71 kB 55.19 kB +0.71% 11.21 kB 11.29 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js +0.89% 54.90 kB 55.39 kB +0.76% 11.24 kB 11.32 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js +0.89% 54.90 kB 55.39 kB +0.76% 11.24 kB 11.32 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js +0.88% 55.44 kB 55.93 kB +0.76% 11.33 kB 11.41 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js +0.88% 55.69 kB 56.18 kB +0.70% 11.43 kB 11.51 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js +0.88% 55.69 kB 56.18 kB +0.70% 11.43 kB 11.51 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js +0.87% 56.24 kB 56.73 kB +0.69% 11.52 kB 11.60 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js +0.85% 57.23 kB 57.72 kB +0.81% 11.70 kB 11.80 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js +0.85% 57.23 kB 57.72 kB +0.81% 11.70 kB 11.80 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js +0.85% 57.77 kB 58.26 kB +0.78% 11.79 kB 11.88 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js +0.83% 58.72 kB 59.21 kB +0.77% 12.01 kB 12.10 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js +0.83% 58.72 kB 59.21 kB +0.77% 12.01 kB 12.10 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js +0.83% 58.81 kB 59.30 kB +0.77% 12.04 kB 12.13 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js +0.83% 58.81 kB 59.30 kB +0.77% 12.04 kB 12.13 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js +0.83% 59.27 kB 59.76 kB +0.76% 12.10 kB 12.19 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js +0.82% 59.35 kB 59.84 kB +0.76% 12.12 kB 12.22 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.production.js +0.82% 59.74 kB 60.23 kB +0.78% 11.99 kB 12.09 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.production.js +0.82% 59.74 kB 60.23 kB +0.78% 11.99 kB 12.09 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.production.js +0.81% 60.27 kB 60.76 kB +0.76% 12.09 kB 12.18 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js +0.80% 60.92 kB 61.41 kB +0.78% 12.23 kB 12.33 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js +0.80% 60.92 kB 61.41 kB +0.78% 12.23 kB 12.33 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js +0.80% 61.44 kB 61.93 kB +0.77% 12.32 kB 12.42 kB
oss-stable-semver/react-client/cjs/react-client-flight.development.js +0.56% 97.20 kB 97.75 kB +0.48% 17.83 kB 17.92 kB
oss-stable/react-client/cjs/react-client-flight.development.js +0.56% 97.23 kB 97.77 kB +0.48% 17.86 kB 17.95 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js +0.55% 99.67 kB 100.21 kB +0.37% 18.90 kB 18.97 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js +0.55% 99.67 kB 100.21 kB +0.37% 18.90 kB 18.97 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js +0.55% 100.18 kB 100.73 kB +0.38% 18.92 kB 18.99 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js +0.55% 100.18 kB 100.73 kB +0.38% 18.92 kB 18.99 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js +0.54% 101.47 kB 102.02 kB +0.36% 19.23 kB 19.30 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js +0.54% 101.47 kB 102.02 kB +0.36% 19.23 kB 19.30 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js +0.53% 102.82 kB 103.37 kB +0.43% 19.39 kB 19.47 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js +0.53% 102.82 kB 103.37 kB +0.43% 19.39 kB 19.47 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js +0.52% 104.57 kB 105.11 kB +0.42% 19.70 kB 19.78 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js +0.52% 104.57 kB 105.11 kB +0.42% 19.70 kB 19.78 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js +0.52% 104.66 kB 105.20 kB +0.43% 19.74 kB 19.82 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js +0.52% 104.66 kB 105.20 kB +0.43% 19.74 kB 19.82 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js +0.52% 105.56 kB 106.11 kB +0.43% 19.65 kB 19.74 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js +0.52% 105.56 kB 106.11 kB +0.43% 19.65 kB 19.74 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js +0.51% 106.89 kB 107.44 kB +0.42% 19.91 kB 19.99 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js +0.51% 106.89 kB 107.44 kB +0.42% 19.91 kB 19.99 kB
oss-experimental/react-client/cjs/react-client-flight.development.js +0.51% 107.05 kB 107.60 kB +0.48% 19.91 kB 20.00 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js +0.50% 109.48 kB 110.03 kB +0.40% 20.90 kB 20.99 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js +0.50% 110.00 kB 110.54 kB +0.43% 20.92 kB 21.01 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js +0.49% 111.29 kB 111.83 kB +0.40% 21.26 kB 21.35 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js +0.49% 112.64 kB 113.18 kB +0.44% 21.39 kB 21.48 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js +0.48% 114.38 kB 114.93 kB +0.44% 21.75 kB 21.84 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js +0.48% 114.47 kB 115.02 kB +0.42% 21.79 kB 21.88 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.unbundled.development.js +0.47% 115.38 kB 115.93 kB +0.44% 21.66 kB 21.75 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js +0.47% 116.71 kB 117.26 kB +0.42% 21.92 kB 22.01 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js +0.40% 82.40 kB 82.72 kB +0.54% 17.26 kB 17.36 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js +0.40% 82.40 kB 82.72 kB +0.54% 17.26 kB 17.36 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js +0.39% 83.13 kB 83.46 kB +0.53% 17.38 kB 17.47 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js +0.34% 50.56 kB 50.74 kB +0.45% 10.23 kB 10.28 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js +0.34% 50.56 kB 50.74 kB +0.45% 10.23 kB 10.28 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js +0.34% 50.78 kB 50.95 kB +0.44% 10.34 kB 10.39 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js +0.34% 50.78 kB 50.95 kB +0.44% 10.34 kB 10.39 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js +0.34% 51.11 kB 51.28 kB +0.44% 10.32 kB 10.37 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js +0.34% 51.32 kB 51.50 kB +0.43% 10.43 kB 10.48 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js +0.33% 52.69 kB 52.86 kB +0.41% 10.74 kB 10.78 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js +0.33% 52.69 kB 52.86 kB +0.41% 10.74 kB 10.78 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js +0.33% 53.12 kB 53.29 kB +0.41% 10.84 kB 10.88 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js +0.33% 53.12 kB 53.29 kB +0.41% 10.84 kB 10.88 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js +0.32% 53.23 kB 53.41 kB +0.42% 10.83 kB 10.87 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js +0.32% 53.67 kB 53.84 kB +0.42% 10.93 kB 10.98 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js +0.25% 133.94 kB 134.27 kB +0.33% 31.20 kB 31.30 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js +0.25% 133.96 kB 134.30 kB +0.33% 31.23 kB 31.33 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js +0.23% 145.52 kB 145.85 kB +0.31% 34.11 kB 34.21 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js +0.21% 95.86 kB 96.07 kB +0.25% 18.15 kB 18.20 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js +0.21% 95.91 kB 96.12 kB +0.25% 18.18 kB 18.22 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js +0.21% 96.22 kB 96.43 kB +0.25% 18.12 kB 18.16 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js +0.21% 96.27 kB 96.48 kB +0.25% 18.14 kB 18.19 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js +0.21% 98.05 kB 98.25 kB +0.26% 18.54 kB 18.59 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js +0.21% 98.10 kB 98.30 kB +0.26% 18.56 kB 18.61 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js +0.21% 98.61 kB 98.81 kB +0.28% 18.67 kB 18.73 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js +0.21% 98.66 kB 98.86 kB +0.28% 18.70 kB 18.75 kB

Generated by 🚫 dangerJS against b96a651

Function,
{id: ServerReferenceId, bound: null | Thenable<Array<any>>},
> = new WeakMap();
type ServerReferenceMetaData = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

The terminology here is a bit unclear but ClientReferenceMetadata is actually the equivalent of ServerReferenceId. I.e. excluding the bound arguments. We should really have bound client references too.

Originally I intended to refer to the Metadata + Bound arguments as a "Reference" inside the payload itself because it's overloaded both in terms of the first class object exposed to user space and references to various IDs in the payload format.

This pairing of bound arguments + the id/metadata should probably have its own name. Maybe ServerReferenceClosure?

// 'react-server/src/ReactFlightServerConfig', but that can only be imported
// in a react-server environment.
function isServerReference(reference: Object): boolean {
return reference.$$typeof === Symbol.for('react.server.reference');
Copy link
Collaborator

Choose a reason for hiding this comment

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

This isn't good enough to support environments that have custom server reference first class types (like Meta does and all bundlers ideally should have).

But I doubt brand checking is actually the right strategy anyway.

}
// Expose encoder for use by SSR, as well as a special bind that can be used to
// keep server capabilities.
if (usedWithSSR) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

$$FORM_ACTION and $$IS_SIGNATURE_EQUAL should never be included in a non-SSR build and we definitely don't want to include the extra code in browser builds sent to clients.

In fact, we really need to build a separate version of the Flight Clients for react-server and non-react-server environments because these should really never be in any react-server environment.

We cheat in other places like:

https://github.com/facebook/react/blob/main/packages/react-client/src/ReactFlightClient.js#L104-L113

This is going to get us in trouble eventually.

registerBoundServerReference(reference, id, null, encodeFormAction);
const bound =
isServerReference(reference) && reference.$$bound
? Promise.resolve(reference.$$bound)
Copy link
Collaborator

Choose a reason for hiding this comment

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

We can't make these assumptions about the structure of a Server Reference here. It's up to the bundler.

In fact, these should not even be expandos. I've been meaning to move all the fields on Server/Client References onto WeakMaps since they're internal state owned by the server and should be opaque to the surrounding environment - including Flight's Client.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also, if it is bound already then it's used incorrectly and should be an error (if it was even possible to check).

Because registerServerReference should always be called on the original function, not the closure. It represents the raw function and not the closure.

I.e. to create a bound function you need to pass the original function to both both registerServerReferences before binding it.

ReactFlightClient.registerServerReference(ReactFlightServer.registerServerReferenace(fn, ...), ...).bind(...)

function defineBind<T: Function>(reference: T) {
// TODO: Instead of checking if it's a server reference, we could also use
// `reference.hasOwnProperty('bind')`.
const originalBind = isServerReference(reference)
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 even have to check. We can just assume that it has a bind since it's a function. Otherwise something has gone terribly wrong and if not we probably shouldn't add one.

The principle here is this should be opaque to the environment and as long as we just call through it should work as usual.

In fact, you should really be able to have the same function in multiple server environments too which would be possible if we moved the expandos to WeakMaps.

So this could be bound for the Flight Client, Flight Server ESM and Flight Webpack all at once.

? reference.bind
: FunctionBind;

function bind(): Function {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This shouldn't use a closure. You should be able to have referenceA.bind === referenceB.bind and eventually this should just go on the Function.prototype. Conceptually it's on the Function.prototype and the more native it moves into bundlers and then in the browser it will be.

It's also important semantically because you should be getting all information about the reference from this and not anything from the closure. Native functions aren't bound to anything.

@unstubbable unstubbable merged commit 2398554 into facebook:main Mar 11, 2025
194 checks passed
@unstubbable unstubbable deleted the hl/register-server-reference-client-bind branch March 12, 2025 11:16
huozhi pushed a commit to vercel/next.js that referenced this pull request Mar 12, 2025
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