Skip to content

Commit e81fcfe

Browse files
authored
[Flight] Expose registerServerReference from the client builds (#32534)
This is used to register Server References that exist in the current environment but also exists in the server it might call into. Such as a remote server. If the value comes from the remote server in the first place then this is called automatically to ensure that you can pass a reference back to where it came from - even if the `serverModuleMap` option is used. This was already the case when `serverModuleMap` wasn't passed. This is how you can pass server references back to the server. However, when we added `serverModuleMap` that pass was skipped because we were getting real functions instead of proxies. For functions that wasn't yet passed from the remote server to the current server, we can register them eagerly just like we do for `import('/server').registerServerReference()`. You can now also do this with `import('/client').registerServerReference()`. We could make them shared so you only have to do this once but it might not be possible to pass to the remote server and the remote server might not even be the same RSC renderer. Therefore I split them. It's up to the compiler whether it should do that or not. It has to know that any function you might call might be able to receive it. This is currently global to a specific RSC renderer.
1 parent aac177c commit e81fcfe

File tree

16 files changed

+141
-38
lines changed

16 files changed

+141
-38
lines changed

packages/react-client/src/ReactFlightClient.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ import {
6464
rendererPackageName,
6565
} from './ReactFlightClientConfig';
6666

67-
import {createBoundServerReference} from './ReactFlightReplyClient';
67+
import {
68+
createBoundServerReference,
69+
registerBoundServerReference,
70+
} from './ReactFlightReplyClient';
6871

6972
import {readTemporaryReference} from './ReactFlightTemporaryReferences';
7073

@@ -1096,7 +1099,14 @@ function loadServerReference<A: Iterable<any>, T>(
10961099
let promise: null | Thenable<any> = preloadModule(serverReference);
10971100
if (!promise) {
10981101
if (!metaData.bound) {
1099-
return (requireModule(serverReference): any);
1102+
const resolvedValue = (requireModule(serverReference): any);
1103+
registerBoundServerReference(
1104+
resolvedValue,
1105+
metaData.id,
1106+
metaData.bound,
1107+
response._encodeFormAction,
1108+
);
1109+
return resolvedValue;
11001110
} else {
11011111
promise = Promise.resolve(metaData.bound);
11021112
}
@@ -1128,6 +1138,13 @@ function loadServerReference<A: Iterable<any>, T>(
11281138
resolvedValue = resolvedValue.bind.apply(resolvedValue, boundArgs);
11291139
}
11301140

1141+
registerBoundServerReference(
1142+
resolvedValue,
1143+
metaData.id,
1144+
metaData.bound,
1145+
response._encodeFormAction,
1146+
);
1147+
11311148
parentObject[key] = resolvedValue;
11321149

11331150
// If this is the root object for a model reference, where `handler.value`

packages/react-client/src/ReactFlightReplyClient.js

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,11 +1125,12 @@ function createFakeServerFunction<A: Iterable<any>, T>(
11251125
}
11261126
}
11271127

1128-
function registerServerReference(
1129-
proxy: any,
1130-
reference: {id: ServerReferenceId, bound: null | Thenable<Array<any>>},
1128+
export function registerBoundServerReference<T: Function>(
1129+
reference: T,
1130+
id: ServerReferenceId,
1131+
bound: null | Thenable<Array<any>>,
11311132
encodeFormAction: void | EncodeFormActionCallback,
1132-
) {
1133+
): void {
11331134
// Expose encoder for use by SSR, as well as a special bind that can be used to
11341135
// keep server capabilities.
11351136
if (usedWithSSR) {
@@ -1147,13 +1148,22 @@ function registerServerReference(
11471148
encodeFormAction,
11481149
);
11491150
};
1150-
Object.defineProperties((proxy: any), {
1151+
Object.defineProperties((reference: any), {
11511152
$$FORM_ACTION: {value: $$FORM_ACTION},
11521153
$$IS_SIGNATURE_EQUAL: {value: isSignatureEqual},
11531154
bind: {value: bind},
11541155
});
11551156
}
1156-
knownServerReferences.set(proxy, reference);
1157+
knownServerReferences.set(reference, {id, bound});
1158+
}
1159+
1160+
export function registerServerReference<T: Function>(
1161+
reference: T,
1162+
id: ServerReferenceId,
1163+
encodeFormAction?: EncodeFormActionCallback,
1164+
): ServerReference<T> {
1165+
registerBoundServerReference(reference, id, null, encodeFormAction);
1166+
return reference;
11571167
}
11581168

11591169
// $FlowFixMe[method-unbinding]
@@ -1258,7 +1268,7 @@ export function createBoundServerReference<A: Iterable<any>, T>(
12581268
);
12591269
}
12601270
}
1261-
registerServerReference(action, {id, bound}, encodeFormAction);
1271+
registerBoundServerReference(action, id, bound, encodeFormAction);
12621272
return action;
12631273
}
12641274

@@ -1358,6 +1368,6 @@ export function createServerReference<A: Iterable<any>, T>(
13581368
);
13591369
}
13601370
}
1361-
registerServerReference(action, {id, bound: null}, encodeFormAction);
1371+
registerBoundServerReference(action, id, null, encodeFormAction);
13621372
return action;
13631373
}

packages/react-server-dom-esm/src/client/ReactFlightDOMClientBrowser.js

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ import {
2525
injectIntoDevTools,
2626
} from 'react-client/src/ReactFlightClient';
2727

28-
import {
29-
processReply,
28+
import {processReply} from 'react-client/src/ReactFlightReplyClient';
29+
30+
export {
3031
createServerReference,
32+
registerServerReference,
3133
} from 'react-client/src/ReactFlightReplyClient';
3234

3335
import type {TemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';
@@ -151,12 +153,7 @@ function encodeReply(
151153
});
152154
}
153155

154-
export {
155-
createFromFetch,
156-
createFromReadableStream,
157-
encodeReply,
158-
createServerReference,
159-
};
156+
export {createFromFetch, createFromReadableStream, encodeReply};
160157

161158
if (__DEV__) {
162159
injectIntoDevTools();

packages/react-server-dom-esm/src/client/ReactFlightDOMClientNode.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import {
2626

2727
import {createServerReference as createServerReferenceImpl} from 'react-client/src/ReactFlightReplyClient';
2828

29+
export {registerServerReference} from 'react-client/src/ReactFlightReplyClient';
30+
2931
function noServerCall() {
3032
throw new Error(
3133
'Server Functions cannot be called during initial render. ' +

packages/react-server-dom-parcel/src/client/ReactFlightDOMClientBrowser.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import {
2626
createServerReference as createServerReferenceImpl,
2727
} from 'react-client/src/ReactFlightReplyClient';
2828

29+
export {registerServerReference} from 'react-client/src/ReactFlightReplyClient';
30+
2931
import type {TemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';
3032

3133
export {createTemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';

packages/react-server-dom-parcel/src/client/ReactFlightDOMClientEdge.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import {
2525
createServerReference as createServerReferenceImpl,
2626
} from 'react-client/src/ReactFlightReplyClient';
2727

28+
export {registerServerReference} from 'react-client/src/ReactFlightReplyClient';
29+
2830
import type {TemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';
2931

3032
export {createTemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';

packages/react-server-dom-parcel/src/client/ReactFlightDOMClientNode.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import {
2121

2222
import {createServerReference as createServerReferenceImpl} from 'react-client/src/ReactFlightReplyClient';
2323

24+
export {registerServerReference} from 'react-client/src/ReactFlightReplyClient';
25+
2426
function findSourceMapURL(filename: string, environmentName: string) {
2527
const devServer = parcelRequire.meta.devServer;
2628
if (devServer != null) {

packages/react-server-dom-turbopack/src/client/ReactFlightDOMClientBrowser.js

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ import {
2525
injectIntoDevTools,
2626
} from 'react-client/src/ReactFlightClient';
2727

28-
import {
29-
processReply,
28+
import {processReply} from 'react-client/src/ReactFlightReplyClient';
29+
30+
export {
3031
createServerReference,
32+
registerServerReference,
3133
} from 'react-client/src/ReactFlightReplyClient';
3234

3335
import type {TemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';
@@ -150,12 +152,7 @@ function encodeReply(
150152
});
151153
}
152154

153-
export {
154-
createFromFetch,
155-
createFromReadableStream,
156-
encodeReply,
157-
createServerReference,
158-
};
155+
export {createFromFetch, createFromReadableStream, encodeReply};
159156

160157
if (__DEV__) {
161158
injectIntoDevTools();

packages/react-server-dom-turbopack/src/client/ReactFlightDOMClientEdge.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ import {
4141
createServerReference as createServerReferenceImpl,
4242
} from 'react-client/src/ReactFlightReplyClient';
4343

44+
export {registerServerReference} from 'react-client/src/ReactFlightReplyClient';
45+
4446
import type {TemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';
4547

4648
export {createTemporaryReferenceSet} from 'react-client/src/ReactFlightTemporaryReferences';

packages/react-server-dom-turbopack/src/client/ReactFlightDOMClientNode.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ import {
3838

3939
import {createServerReference as createServerReferenceImpl} from 'react-client/src/ReactFlightReplyClient';
4040

41+
export {registerServerReference} from 'react-client/src/ReactFlightReplyClient';
42+
4143
function noServerCall() {
4244
throw new Error(
4345
'Server Functions cannot be called during initial render. ' +

0 commit comments

Comments
 (0)