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

Enable passing Server References from Server to Client #26124

Merged
merged 5 commits into from Feb 10, 2023

Conversation

sebmarkbage
Copy link
Collaborator

@sebmarkbage sebmarkbage commented Feb 8, 2023

This is the first of a series of PRs, that let you pass functions, by reference, to the client and back. E.g. through Server Context. It's like client references but they're opaque on the client and resolved on the server.

To do this, for security, you must opt-in to exposing these functions to the client using the "use server" directive. The "use client" directive lets you enter the client from the server. The "use server" directive lets you enter the server from the client.

This works by tagging those functions as Server References. We could potentially expand this to other non-serializable or stateful objects too like classes.

This only implements server->server CJS imports and server->server ESM imports. We really should add a loader to the webpack plug-in for client->server imports too. I'll leave closures as an exercise for integrators.

You can't "call" a client reference on the server, however, you can "call" a server reference on the client. This invokes a callback on the Flight client options called callServer. This lets a router implement calling back to the server. Effectively creating an RPC. This is using JSON for serializing those arguments but more utils coming from client->server serialization.

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

react-sizebot commented Feb 8, 2023

Comparing: 6ddcbd4...b35a364

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 = 154.83 kB 154.83 kB = 49.12 kB 49.12 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js = 156.83 kB 156.83 kB = 49.73 kB 49.73 kB
facebook-www/ReactDOM-prod.classic.js = 533.54 kB 533.54 kB = 94.99 kB 94.99 kB
facebook-www/ReactDOM-prod.modern.js = 518.81 kB 518.81 kB = 92.84 kB 92.84 kB
oss-experimental/react-server-dom-webpack/esm/react-server-dom-webpack-node-loader.js +22.80% 10.01 kB 12.29 kB = 3.18 kB 3.11 kB
oss-stable-semver/react-server-dom-webpack/esm/react-server-dom-webpack-node-loader.js +22.80% 10.01 kB 12.29 kB = 3.18 kB 3.11 kB
oss-stable/react-server-dom-webpack/esm/react-server-dom-webpack-node-loader.js +22.80% 10.01 kB 12.29 kB = 3.18 kB 3.11 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.production.min.js +10.29% 6.56 kB 7.23 kB +7.72% 2.62 kB 2.82 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.production.min.js +10.29% 6.56 kB 7.23 kB +7.72% 2.62 kB 2.82 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.production.min.js +10.29% 6.56 kB 7.23 kB +7.72% 2.62 kB 2.82 kB
oss-experimental/react-server-dom-webpack/umd/react-server-dom-webpack-client.production.min.js +9.96% 6.77 kB 7.44 kB +7.66% 2.72 kB 2.93 kB
oss-stable-semver/react-server-dom-webpack/umd/react-server-dom-webpack-client.production.min.js +9.96% 6.77 kB 7.44 kB +7.66% 2.72 kB 2.93 kB
oss-stable/react-server-dom-webpack/umd/react-server-dom-webpack-client.production.min.js +9.96% 6.77 kB 7.44 kB +7.66% 2.72 kB 2.93 kB
facebook-www/ReactFlightDOMRelayClient-prod.classic.js +9.61% 10.92 kB 11.97 kB +7.14% 2.84 kB 3.05 kB
facebook-www/ReactFlightDOMRelayClient-prod.modern.js +9.61% 10.92 kB 11.97 kB +7.14% 2.84 kB 3.05 kB
facebook-relay/flight/ReactFlightNativeRelayClient-prod.js +9.60% 10.93 kB 11.98 kB +7.06% 2.85 kB 3.05 kB
facebook-relay/flight/ReactFlightNativeRelayClient-dev.js +9.21% 17.96 kB 19.61 kB +8.76% 4.73 kB 5.14 kB
facebook-www/ReactFlightDOMRelayClient-dev.classic.js +9.20% 17.88 kB 19.53 kB +8.84% 4.71 kB 5.12 kB
facebook-www/ReactFlightDOMRelayClient-dev.modern.js +9.20% 17.88 kB 19.53 kB +8.84% 4.71 kB 5.12 kB
oss-experimental/react-client/cjs/react-client-flight.development.js +8.69% 20.01 kB 21.75 kB +7.84% 5.37 kB 5.79 kB
oss-stable-semver/react-client/cjs/react-client-flight.development.js +8.69% 20.01 kB 21.75 kB +7.84% 5.37 kB 5.79 kB
oss-stable/react-client/cjs/react-client-flight.development.js +8.69% 20.01 kB 21.75 kB +7.84% 5.37 kB 5.79 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-server.production.min.js +8.65% 1.12 kB 1.22 kB +2.69% 0.56 kB 0.57 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-server.production.min.js +8.65% 1.12 kB 1.22 kB +2.69% 0.56 kB 0.57 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-server.production.min.js +8.65% 1.12 kB 1.22 kB +2.69% 0.56 kB 0.57 kB
oss-experimental/react-client/cjs/react-client-flight.production.min.js +8.34% 5.49 kB 5.95 kB +5.99% 2.21 kB 2.34 kB
oss-stable-semver/react-client/cjs/react-client-flight.production.min.js +8.34% 5.49 kB 5.95 kB +5.99% 2.21 kB 2.34 kB
oss-stable/react-client/cjs/react-client-flight.production.min.js +8.34% 5.49 kB 5.95 kB +5.99% 2.21 kB 2.34 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.development.js +7.81% 24.26 kB 26.15 kB +6.71% 6.35 kB 6.77 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.development.js +7.81% 24.26 kB 26.15 kB +6.71% 6.35 kB 6.77 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.development.js +7.81% 24.26 kB 26.15 kB +6.71% 6.35 kB 6.77 kB
oss-experimental/react-server-dom-webpack/umd/react-server-dom-webpack-client.development.js +7.65% 25.92 kB 27.90 kB +6.64% 6.48 kB 6.91 kB
oss-stable-semver/react-server-dom-webpack/umd/react-server-dom-webpack-client.development.js +7.65% 25.92 kB 27.90 kB +6.64% 6.48 kB 6.91 kB
oss-stable/react-server-dom-webpack/umd/react-server-dom-webpack-client.development.js +7.65% 25.92 kB 27.90 kB +6.64% 6.48 kB 6.91 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-server.development.js +5.88% 2.21 kB 2.34 kB +1.47% 0.88 kB 0.90 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-server.development.js +5.88% 2.21 kB 2.34 kB +1.47% 0.88 kB 0.90 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-server.development.js +5.88% 2.21 kB 2.34 kB +1.47% 0.88 kB 0.90 kB
oss-experimental/react-server/cjs/react-server-flight.production.min.js +2.91% 14.47 kB 14.89 kB +1.70% 5.29 kB 5.38 kB
oss-stable-semver/react-server/cjs/react-server-flight.production.min.js +2.91% 14.47 kB 14.89 kB +1.70% 5.29 kB 5.38 kB
oss-stable/react-server/cjs/react-server-flight.production.min.js +2.91% 14.47 kB 14.89 kB +1.70% 5.29 kB 5.38 kB
oss-experimental/react-server/cjs/react-server-flight.development.js +2.20% 63.59 kB 64.98 kB +1.36% 15.26 kB 15.47 kB
oss-stable-semver/react-server/cjs/react-server-flight.development.js +2.20% 63.59 kB 64.98 kB +1.36% 15.26 kB 15.47 kB
oss-stable/react-server/cjs/react-server-flight.development.js +2.20% 63.59 kB 64.98 kB +1.36% 15.26 kB 15.47 kB
oss-experimental/react-suspense-test-utils/cjs/react-suspense-test-utils.js = 1.57 kB 0.78 kB = 0.71 kB 0.51 kB
oss-stable-semver/react-suspense-test-utils/cjs/react-suspense-test-utils.js = 1.57 kB 0.78 kB = 0.71 kB 0.51 kB
oss-stable/react-suspense-test-utils/cjs/react-suspense-test-utils.js = 1.57 kB 0.78 kB = 0.71 kB 0.51 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-node-register.js = 9.21 kB 4.28 kB = 2.46 kB 1.47 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-node-register.js = 9.21 kB 4.28 kB = 2.46 kB 1.47 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-node-register.js = 9.21 kB 4.28 kB = 2.46 kB 1.47 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-plugin.js = 9.79 kB 3.91 kB = 3.07 kB 1.74 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-plugin.js = 9.79 kB 3.91 kB = 3.07 kB 1.74 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-plugin.js = 9.79 kB 3.91 kB = 3.07 kB 1.74 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
oss-experimental/react-server-dom-webpack/esm/react-server-dom-webpack-node-loader.js +22.80% 10.01 kB 12.29 kB = 3.18 kB 3.11 kB
oss-stable-semver/react-server-dom-webpack/esm/react-server-dom-webpack-node-loader.js +22.80% 10.01 kB 12.29 kB = 3.18 kB 3.11 kB
oss-stable/react-server-dom-webpack/esm/react-server-dom-webpack-node-loader.js +22.80% 10.01 kB 12.29 kB = 3.18 kB 3.11 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.production.min.js +10.29% 6.56 kB 7.23 kB +7.72% 2.62 kB 2.82 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.production.min.js +10.29% 6.56 kB 7.23 kB +7.72% 2.62 kB 2.82 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.production.min.js +10.29% 6.56 kB 7.23 kB +7.72% 2.62 kB 2.82 kB
oss-experimental/react-server-dom-webpack/umd/react-server-dom-webpack-client.production.min.js +9.96% 6.77 kB 7.44 kB +7.66% 2.72 kB 2.93 kB
oss-stable-semver/react-server-dom-webpack/umd/react-server-dom-webpack-client.production.min.js +9.96% 6.77 kB 7.44 kB +7.66% 2.72 kB 2.93 kB
oss-stable/react-server-dom-webpack/umd/react-server-dom-webpack-client.production.min.js +9.96% 6.77 kB 7.44 kB +7.66% 2.72 kB 2.93 kB
facebook-www/ReactFlightDOMRelayClient-prod.classic.js +9.61% 10.92 kB 11.97 kB +7.14% 2.84 kB 3.05 kB
facebook-www/ReactFlightDOMRelayClient-prod.modern.js +9.61% 10.92 kB 11.97 kB +7.14% 2.84 kB 3.05 kB
facebook-relay/flight/ReactFlightNativeRelayClient-prod.js +9.60% 10.93 kB 11.98 kB +7.06% 2.85 kB 3.05 kB
facebook-relay/flight/ReactFlightNativeRelayClient-dev.js +9.21% 17.96 kB 19.61 kB +8.76% 4.73 kB 5.14 kB
facebook-www/ReactFlightDOMRelayClient-dev.classic.js +9.20% 17.88 kB 19.53 kB +8.84% 4.71 kB 5.12 kB
facebook-www/ReactFlightDOMRelayClient-dev.modern.js +9.20% 17.88 kB 19.53 kB +8.84% 4.71 kB 5.12 kB
oss-experimental/react-client/cjs/react-client-flight.development.js +8.69% 20.01 kB 21.75 kB +7.84% 5.37 kB 5.79 kB
oss-stable-semver/react-client/cjs/react-client-flight.development.js +8.69% 20.01 kB 21.75 kB +7.84% 5.37 kB 5.79 kB
oss-stable/react-client/cjs/react-client-flight.development.js +8.69% 20.01 kB 21.75 kB +7.84% 5.37 kB 5.79 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-server.production.min.js +8.65% 1.12 kB 1.22 kB +2.69% 0.56 kB 0.57 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-server.production.min.js +8.65% 1.12 kB 1.22 kB +2.69% 0.56 kB 0.57 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-server.production.min.js +8.65% 1.12 kB 1.22 kB +2.69% 0.56 kB 0.57 kB
oss-experimental/react-client/cjs/react-client-flight.production.min.js +8.34% 5.49 kB 5.95 kB +5.99% 2.21 kB 2.34 kB
oss-stable-semver/react-client/cjs/react-client-flight.production.min.js +8.34% 5.49 kB 5.95 kB +5.99% 2.21 kB 2.34 kB
oss-stable/react-client/cjs/react-client-flight.production.min.js +8.34% 5.49 kB 5.95 kB +5.99% 2.21 kB 2.34 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.development.js +7.81% 24.26 kB 26.15 kB +6.71% 6.35 kB 6.77 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.development.js +7.81% 24.26 kB 26.15 kB +6.71% 6.35 kB 6.77 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.development.js +7.81% 24.26 kB 26.15 kB +6.71% 6.35 kB 6.77 kB
oss-experimental/react-server-dom-webpack/umd/react-server-dom-webpack-client.development.js +7.65% 25.92 kB 27.90 kB +6.64% 6.48 kB 6.91 kB
oss-stable-semver/react-server-dom-webpack/umd/react-server-dom-webpack-client.development.js +7.65% 25.92 kB 27.90 kB +6.64% 6.48 kB 6.91 kB
oss-stable/react-server-dom-webpack/umd/react-server-dom-webpack-client.development.js +7.65% 25.92 kB 27.90 kB +6.64% 6.48 kB 6.91 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-server.development.js +5.88% 2.21 kB 2.34 kB +1.47% 0.88 kB 0.90 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-server.development.js +5.88% 2.21 kB 2.34 kB +1.47% 0.88 kB 0.90 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-server.development.js +5.88% 2.21 kB 2.34 kB +1.47% 0.88 kB 0.90 kB
oss-experimental/react-server/cjs/react-server-flight.production.min.js +2.91% 14.47 kB 14.89 kB +1.70% 5.29 kB 5.38 kB
oss-stable-semver/react-server/cjs/react-server-flight.production.min.js +2.91% 14.47 kB 14.89 kB +1.70% 5.29 kB 5.38 kB
oss-stable/react-server/cjs/react-server-flight.production.min.js +2.91% 14.47 kB 14.89 kB +1.70% 5.29 kB 5.38 kB
oss-experimental/react-server/cjs/react-server-flight.development.js +2.20% 63.59 kB 64.98 kB +1.36% 15.26 kB 15.47 kB
oss-stable-semver/react-server/cjs/react-server-flight.development.js +2.20% 63.59 kB 64.98 kB +1.36% 15.26 kB 15.47 kB
oss-stable/react-server/cjs/react-server-flight.development.js +2.20% 63.59 kB 64.98 kB +1.36% 15.26 kB 15.47 kB
oss-stable-semver/react-server-dom-webpack/umd/react-server-dom-webpack-server.browser.production.min.js +1.83% 23.47 kB 23.90 kB +1.34% 8.26 kB 8.37 kB
oss-stable/react-server-dom-webpack/umd/react-server-dom-webpack-server.browser.production.min.js +1.83% 23.47 kB 23.90 kB +1.34% 8.26 kB 8.37 kB
oss-experimental/react-server-dom-webpack/umd/react-server-dom-webpack-server.browser.production.min.js +1.83% 23.51 kB 23.94 kB +1.38% 8.28 kB 8.39 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.production.min.js +1.81% 23.29 kB 23.71 kB +1.32% 8.17 kB 8.28 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.production.min.js +1.81% 23.29 kB 23.71 kB +1.32% 8.17 kB 8.28 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.production.min.js +1.81% 23.33 kB 23.75 kB +1.31% 8.19 kB 8.30 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.development.js +1.81% 87.34 kB 88.91 kB +1.20% 21.48 kB 21.74 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.development.js +1.81% 87.34 kB 88.91 kB +1.20% 21.48 kB 21.74 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.browser.development.js +1.80% 87.39 kB 88.97 kB +1.20% 21.50 kB 21.75 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js +1.80% 87.82 kB 89.39 kB +1.19% 21.62 kB 21.88 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js +1.80% 87.82 kB 89.39 kB +1.19% 21.62 kB 21.88 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.production.min.js +1.80% 23.45 kB 23.87 kB +1.24% 8.23 kB 8.34 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.production.min.js +1.80% 23.45 kB 23.87 kB +1.24% 8.23 kB 8.34 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js +1.79% 87.87 kB 89.45 kB +1.18% 21.64 kB 21.90 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.production.min.js +1.79% 23.50 kB 23.92 kB +1.31% 8.26 kB 8.36 kB
oss-stable-semver/react-server-dom-webpack/umd/react-server-dom-webpack-server.browser.development.js +1.79% 91.70 kB 93.34 kB +1.18% 21.74 kB 21.99 kB
oss-stable/react-server-dom-webpack/umd/react-server-dom-webpack-server.browser.development.js +1.79% 91.70 kB 93.34 kB +1.18% 21.74 kB 21.99 kB
oss-experimental/react-server-dom-webpack/umd/react-server-dom-webpack-server.browser.development.js +1.79% 91.76 kB 93.40 kB +1.18% 21.76 kB 22.01 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.production.min.js +1.78% 23.83 kB 24.25 kB +1.37% 8.33 kB 8.44 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.production.min.js +1.78% 23.83 kB 24.25 kB +1.37% 8.33 kB 8.44 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.production.min.js +1.77% 23.87 kB 24.29 kB +1.32% 8.35 kB 8.46 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js +1.77% 89.12 kB 90.70 kB +1.18% 21.72 kB 21.98 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js +1.77% 89.12 kB 90.70 kB +1.18% 21.72 kB 21.98 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js +1.77% 89.18 kB 90.76 kB +1.17% 21.74 kB 22.00 kB
facebook-relay/flight/ReactFlightNativeRelayServer-prod.js +0.58% 31.28 kB 31.46 kB +0.46% 7.34 kB 7.37 kB
facebook-www/ReactFlightDOMRelayServer-prod.classic.js +0.49% 36.83 kB 37.01 kB +0.40% 9.14 kB 9.18 kB
facebook-www/ReactFlightDOMRelayServer-prod.modern.js +0.49% 36.91 kB 37.09 kB +0.40% 9.18 kB 9.21 kB
facebook-relay/flight/ReactFlightNativeRelayServer-dev.js +0.44% 61.37 kB 61.64 kB +0.25% 14.93 kB 14.97 kB
facebook-www/ReactFlightDOMRelayServer-dev.classic.js +0.35% 76.93 kB 77.20 kB +0.20% 18.71 kB 18.74 kB
facebook-www/ReactFlightDOMRelayServer-dev.modern.js +0.35% 76.98 kB 77.25 kB +0.20% 18.73 kB 18.77 kB
oss-experimental/react-suspense-test-utils/cjs/react-suspense-test-utils.js = 1.57 kB 0.78 kB = 0.71 kB 0.51 kB
oss-stable-semver/react-suspense-test-utils/cjs/react-suspense-test-utils.js = 1.57 kB 0.78 kB = 0.71 kB 0.51 kB
oss-stable/react-suspense-test-utils/cjs/react-suspense-test-utils.js = 1.57 kB 0.78 kB = 0.71 kB 0.51 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-node-register.js = 9.21 kB 4.28 kB = 2.46 kB 1.47 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-node-register.js = 9.21 kB 4.28 kB = 2.46 kB 1.47 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-node-register.js = 9.21 kB 4.28 kB = 2.46 kB 1.47 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-plugin.js = 9.79 kB 3.91 kB = 3.07 kB 1.74 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-plugin.js = 9.79 kB 3.91 kB = 3.07 kB 1.74 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-plugin.js = 9.79 kB 3.91 kB = 3.07 kB 1.74 kB

Generated by 🚫 dangerJS against b35a364

@sebmarkbage sebmarkbage force-pushed the serverreferences branch 2 times, most recently from c05caee to b2c90c0 Compare February 8, 2023 03:50
const PROMISE_PROTOTYPE = Promise.prototype;

// Patch bind on the server to ensure that this creates another
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this a convenience or necessity? Having bind work on them. Why only bind? What happens if you wrap and call inside instead? I guess it’s a normal function then.

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 you wrap in a closure, then that closure needs to opt back into "use server" so it's just like any other closure. bind is special because it's the only thing that creates a built-in closure.

@sebmarkbage sebmarkbage force-pushed the serverreferences branch 3 times, most recently from ee97b02 to f928095 Compare February 9, 2023 18:22
As well as a callback for invoking them.
This is not needed on the client since just regular bind works there.
Module is ambiguous since there's both client and server modules.
It also actually refers to a specific export name.
Wired up an example of how to call into the server
Comment on lines +7 to +21
fetch('http://localhost:3001'),
{
callServer(id, args) {
const response = fetch('http://localhost:3001', {
method: 'POST',
cors: 'cors',
headers: {
'rsc-action': JSON.stringify({filepath: id.id, name: id.name}),
},
body: JSON.stringify(args),
});
return ReactServerDOMReader.createFromFetch(response);
},
}
);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is pretty cool tbh.

localNames.set(node.declaration.id.name, 'default');
localTypes.set(node.declaration.id.name, 'function');
} else {
// TODO: This needs to be rewritten inline because it doesn't have a local name.
Copy link
Collaborator

Choose a reason for hiding this comment

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

makes sense, maybe could error for now so if someone discovers it they get an error message

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'm hesitant to add any errors in this one since it's just a pass through and you can use it server->server. E.g. a nested object wouldn't error. Besides, nobody actually uses this.

Copy link
Collaborator

@acdlite acdlite left a comment

Choose a reason for hiding this comment

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

Exciting stuff! Might be parts I missed since I'm not as familiar with this code but I think it all makes sense to me

@sebmarkbage sebmarkbage merged commit ef9f6e7 into facebook:main Feb 10, 2023
2 checks passed
github-actions bot pushed a commit that referenced this pull request Feb 10, 2023
This is the first of a series of PRs, that let you pass functions, by
reference, to the client and back. E.g. through Server Context. It's
like client references but they're opaque on the client and resolved on
the server.

To do this, for security, you must opt-in to exposing these functions to
the client using the `"use server"` directive. The `"use client"`
directive lets you enter the client from the server. The `"use server"`
directive lets you enter the server from the client.

This works by tagging those functions as Server References. We could
potentially expand this to other non-serializable or stateful objects
too like classes.

This only implements server->server CJS imports and server->server ESM
imports. We really should add a loader to the webpack plug-in for
client->server imports too. I'll leave closures as an exercise for
integrators.

You can't "call" a client reference on the server, however, you can
"call" a server reference on the client. This invokes a callback on the
Flight client options called `callServer`. This lets a router implement
calling back to the server. Effectively creating an RPC. This is using
JSON for serializing those arguments but more utils coming from
client->server serialization.

DiffTrain build for [ef9f6e7](ef9f6e7)
[View git log for this commit](https://github.com/facebook/react/commits/ef9f6e77b8ef968eee659ae797da4bdc07bbbde3)
Function.prototype.bind = (function bind(this: any, self: any) {
// $FlowFixMe[unsupported-syntax]
const newFn = originalBind.apply(this, arguments);
if (this.$$typeof === SERVER_REFERENCE) {
Copy link

@naugtur naugtur Feb 14, 2023

Choose a reason for hiding this comment

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

@sebmarkbage Since you already control the functions you need the special behavior for, judging by the $$typeof presence, there's no need to override the global prototype to preserve it across bind calls. bind preserves the prototype chain.

const SERVER_REFERENCE = Symbol.for('server');

const put$$On = (fn) => {
    const ServerFunctionProto = Object.create(Function.prototype);
    ServerFunctionProto.$$typeof = SERVER_REFERENCE;
    Object.setPrototypeOf(fn, ServerFunctionProto);
}
// a function
const prebind = (a) => {
    console.log(`hello ${a}!`);
};
// the moment in time you control what the function is
put$$On(prebind);

// bind called elsewhere
const newFunction = prebind.bind({}, 'world')

console.log(newFunction.$$typeof)
newFunction()

prints

Symbol(server)
hello world!

I might be missing context, but if I can help avoid one more intrinsic prototype override, it's worth a try.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Luckily this isn’t the real implementation. This is just a reference implementation and then frameworks/bundlers do it differently. This is just showing an example.

Also, keep in mind that this file patches all .js imports using a deprecated Node.js api. Are you not concerned about that? 😛

We could probably get away with defining it as non-enumerable prop on the object along with the rest. setPrototypeOf has some really unfortunate consequences in VMs and doesn’t really help anything.

The issue with these techniques is always that the way people access these in indirections aren’t always the same. Eg libraries do Function.prototype.bind.call(…) to be clever which wouldn’t be caught by this technique.

This feature is non-essential though so probably ok.

@brillout
Copy link
Contributor

Pardon me if I missed it, but is this part of any RFC? As the author of Telefunc (an RPC implementation) I'd be very curious to know more about this. If I'm not mistaken this means I can deeply integrate Telefunc with React?

That'd be great, because Telefunc's official recommendation for SSR data is to use the framework's built-in mechanism instead of Telefunc (e.g. Next.js recommendation). It'd be great if tools like Telefunc can take over of the entire client-server communication.

Also, I wonder if the "use server" part can be implemented independently of the "use client" part, which would fit the architecture of vite-plugin-ssr + Telefunc. (I'm vite-plugin-ssr's author as well.)

I really like React becoming a "platform to build delightful frameworks". A proliferation of frameworks is paramount for increased competition and innovation 🦾. Exciting times.

@gaearon
Copy link
Collaborator

gaearon commented Feb 14, 2023

There'll be an RFC once a few more pieces are fleshed out. We typically submit RFCs we're relatively confident in, which requires prototyping and some early attempts to use it.

facebook-github-bot pushed a commit to facebook/react-native that referenced this pull request Feb 15, 2023
Summary:
This sync includes the following changes:
- **[86c8c8db7](facebook/react@86c8c8db7 )**: test: Don't retry flushActWork if flushUntilNextPaint threw ([#26121](facebook/react#26121)) //<Sebastian Silbermann>//
- **[64acd3918](facebook/react@64acd3918 )**: remove unguarded getRootNode call ([#26152](facebook/react#26152)) //<Josh Story>//
- **[71cace4d3](facebook/react@71cace4d3 )**: Migrate testRunner from jasmine2 to jest-circus ([#26144](facebook/react#26144)) //<Ming Ye>//
- **[c8510227c](facebook/react@c8510227c )**: Treat displayName as undefined ([#26148](facebook/react#26148)) //<Sebastian Markbåge>//
- **[55542bc73](facebook/react@55542bc73 )**: Update jest printBasicPrototype config ([#26142](facebook/react#26142)) //<Ming Ye>//
- **[6396b6641](facebook/react@6396b6641 )**: Model Float on Hoistables semantics ([#26106](facebook/react#26106)) //<Josh Story>//
- **[ef9f6e77b](facebook/react@ef9f6e77b )**: Enable passing Server References from Server to Client ([#26124](facebook/react#26124)) //<Sebastian Markbåge>//
- **[35698311d](facebook/react@35698311d )**: Update jest escapeString config ([#26140](facebook/react#26140)) //<Ming Ye>//
- **[6ddcbd4f9](facebook/react@6ddcbd4f9 )**: [flow] enable LTI inference mode ([#26104](facebook/react#26104)) //<Jan Kassens>//
- **[53b1f69ba](facebook/react@53b1f69ba )**: Implement unstable_getBoundingClientRect in RN Fabric refs ([#26137](facebook/react#26137)) //<Rubén Norte>//
- **[594093496](facebook/react@594093496 )**: Update to Jest 29 ([#26088](facebook/react#26088)) //<Ming Ye>//
- **[28fcae062](facebook/react@28fcae062 )**: Add support for SVG `transformOrigin` prop ([#26130](facebook/react#26130)) //<Aravind D>//
- **[3ff1540e9](facebook/react@3ff1540e9 )**: Prefer JSX in ReactNoop assertions (to combat out-of-memory test runs) ([#26127](facebook/react#26127)) //<Sebastian Silbermann>//
- **[01a0c4e12](facebook/react@01a0c4e12 )**: Add Edge Server Builds for workerd / edge-light ([#26116](facebook/react#26116)) //<Sebastian Markbåge>//
- **[f0cf832e1](facebook/react@f0cf832e1 )**: Update Flight Fixture to "use client" instead of .client.js ([#26118](facebook/react#26118)) //<Sebastian Markbåge>//
- **[03a216070](facebook/react@03a216070 )**: Rename "dom" fork to "dom-node" and "bun" fork to "dom-bun" ([#26117](facebook/react#26117)) //<Sebastian Markbåge>//
- **[4bf2113a1](facebook/react@4bf2113a1 )**: Revert "Move the Webpack manifest config to one level deeper ([#26083](facebook/react#26083))"  ([#26111](facebook/react#26111)) //<Sebastian Markbåge>//
- **[2ef24145e](facebook/react@2ef24145e )**: [flow] upgrade to 0.199.0 ([#26096](facebook/react#26096)) //<Jan Kassens>//
- **[922dd7ba5](facebook/react@922dd7ba5 )**: Revert the outer module object to an object ([#26093](facebook/react#26093)) //<Sebastian Markbåge>//
- **[9d111ffdf](facebook/react@9d111ffdf )**: Serialize Promises through Flight ([#26086](facebook/react#26086)) //<Sebastian Markbåge>//
- **[0ba4698c7](facebook/react@0ba4698c7 )**: Fix async test in React reconciler ([#26087](facebook/react#26087)) //<Ming Ye>//
- **[8c234c0de](facebook/react@8c234c0de )**: Move the Webpack manifest config to one level deeper ([#26083](facebook/react#26083)) //<Sebastian Markbåge>//
- **[977bccd24](facebook/react@977bccd24 )**: Refactor Flight Encoding ([#26082](facebook/react#26082)) //<Sebastian Markbåge>//
- **[d7bb524ad](facebook/react@d7bb524ad )**: [cleanup] Remove unused package jest-mock-scheduler ([#26084](facebook/react#26084)) //<Ming Ye>//
- **[6b3083266](facebook/react@6b3083266 )**: Upgrade prettier ([#26081](facebook/react#26081)) //<Jan Kassens>//
- **[1f5ce59dd](facebook/react@1f5ce59dd )**: [cleanup] fully roll out warnAboutSpreadingKeyToJSX ([#26080](facebook/react#26080)) //<Jan Kassens>//

Changelog:
[General][Changed] - React Native sync for revisions 48b687f...fccf3a9

jest_e2e[run_all_tests]

Reviewed By: rubennorte

Differential Revision: D43305607

fbshipit-source-id: 8da7567ca2a182f4be27788935c2da30a731f83b
OlimpiaZurek pushed a commit to OlimpiaZurek/react-native that referenced this pull request May 22, 2023
Summary:
This sync includes the following changes:
- **[86c8c8db7](facebook/react@86c8c8db7 )**: test: Don't retry flushActWork if flushUntilNextPaint threw ([facebook#26121](facebook/react#26121)) //<Sebastian Silbermann>//
- **[64acd3918](facebook/react@64acd3918 )**: remove unguarded getRootNode call ([facebook#26152](facebook/react#26152)) //<Josh Story>//
- **[71cace4d3](facebook/react@71cace4d3 )**: Migrate testRunner from jasmine2 to jest-circus ([facebook#26144](facebook/react#26144)) //<Ming Ye>//
- **[c8510227c](facebook/react@c8510227c )**: Treat displayName as undefined ([facebook#26148](facebook/react#26148)) //<Sebastian Markbåge>//
- **[55542bc73](facebook/react@55542bc73 )**: Update jest printBasicPrototype config ([facebook#26142](facebook/react#26142)) //<Ming Ye>//
- **[6396b6641](facebook/react@6396b6641 )**: Model Float on Hoistables semantics ([facebook#26106](facebook/react#26106)) //<Josh Story>//
- **[ef9f6e77b](facebook/react@ef9f6e77b )**: Enable passing Server References from Server to Client ([facebook#26124](facebook/react#26124)) //<Sebastian Markbåge>//
- **[35698311d](facebook/react@35698311d )**: Update jest escapeString config ([facebook#26140](facebook/react#26140)) //<Ming Ye>//
- **[6ddcbd4f9](facebook/react@6ddcbd4f9 )**: [flow] enable LTI inference mode ([facebook#26104](facebook/react#26104)) //<Jan Kassens>//
- **[53b1f69ba](facebook/react@53b1f69ba )**: Implement unstable_getBoundingClientRect in RN Fabric refs ([facebook#26137](facebook/react#26137)) //<Rubén Norte>//
- **[594093496](facebook/react@594093496 )**: Update to Jest 29 ([facebook#26088](facebook/react#26088)) //<Ming Ye>//
- **[28fcae062](facebook/react@28fcae062 )**: Add support for SVG `transformOrigin` prop ([facebook#26130](facebook/react#26130)) //<Aravind D>//
- **[3ff1540e9](facebook/react@3ff1540e9 )**: Prefer JSX in ReactNoop assertions (to combat out-of-memory test runs) ([facebook#26127](facebook/react#26127)) //<Sebastian Silbermann>//
- **[01a0c4e12](facebook/react@01a0c4e12 )**: Add Edge Server Builds for workerd / edge-light ([facebook#26116](facebook/react#26116)) //<Sebastian Markbåge>//
- **[f0cf832e1](facebook/react@f0cf832e1 )**: Update Flight Fixture to "use client" instead of .client.js ([facebook#26118](facebook/react#26118)) //<Sebastian Markbåge>//
- **[03a216070](facebook/react@03a216070 )**: Rename "dom" fork to "dom-node" and "bun" fork to "dom-bun" ([facebook#26117](facebook/react#26117)) //<Sebastian Markbåge>//
- **[4bf2113a1](facebook/react@4bf2113a1 )**: Revert "Move the Webpack manifest config to one level deeper ([facebook#26083](facebook/react#26083))"  ([facebook#26111](facebook/react#26111)) //<Sebastian Markbåge>//
- **[2ef24145e](facebook/react@2ef24145e )**: [flow] upgrade to 0.199.0 ([facebook#26096](facebook/react#26096)) //<Jan Kassens>//
- **[922dd7ba5](facebook/react@922dd7ba5 )**: Revert the outer module object to an object ([facebook#26093](facebook/react#26093)) //<Sebastian Markbåge>//
- **[9d111ffdf](facebook/react@9d111ffdf )**: Serialize Promises through Flight ([facebook#26086](facebook/react#26086)) //<Sebastian Markbåge>//
- **[0ba4698c7](facebook/react@0ba4698c7 )**: Fix async test in React reconciler ([facebook#26087](facebook/react#26087)) //<Ming Ye>//
- **[8c234c0de](facebook/react@8c234c0de )**: Move the Webpack manifest config to one level deeper ([facebook#26083](facebook/react#26083)) //<Sebastian Markbåge>//
- **[977bccd24](facebook/react@977bccd24 )**: Refactor Flight Encoding ([facebook#26082](facebook/react#26082)) //<Sebastian Markbåge>//
- **[d7bb524ad](facebook/react@d7bb524ad )**: [cleanup] Remove unused package jest-mock-scheduler ([facebook#26084](facebook/react#26084)) //<Ming Ye>//
- **[6b3083266](facebook/react@6b3083266 )**: Upgrade prettier ([facebook#26081](facebook/react#26081)) //<Jan Kassens>//
- **[1f5ce59dd](facebook/react@1f5ce59dd )**: [cleanup] fully roll out warnAboutSpreadingKeyToJSX ([facebook#26080](facebook/react#26080)) //<Jan Kassens>//

Changelog:
[General][Changed] - React Native sync for revisions 48b687f...fccf3a9

jest_e2e[run_all_tests]

Reviewed By: rubennorte

Differential Revision: D43305607

fbshipit-source-id: 8da7567ca2a182f4be27788935c2da30a731f83b
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.

None yet

7 participants