mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 00:20:04 +01:00
[Flight] Allow Temporary References to be awaited (#34084)
Fixes #33534. `.then` method can be tested when you await a value that's not a Promise. For regular Client References we have a way to mark those as "async" and yield a reference to the unwrapped value in case it's a Promise on the Client. However, the realization is that we never serialize Promises as opaque when passed from the client to the server. If a Promise is passed, then it would've been deserialized as a Promise (while still registered as a temporary reference) and not one of these Proxy objects. Technically it could be a non-function value on the client which would be wrong but you're not supposed to dot into it in the first place. So we can just assume it's `undefined`.
This commit is contained in:
parent
1d163962b2
commit
c499adf8c8
|
|
@ -438,6 +438,50 @@ describe('ReactFlightDOMReply', () => {
|
|||
expect(response.obj).toBe(obj);
|
||||
});
|
||||
|
||||
it('can return an opaque object through an async function', async () => {
|
||||
function fn() {
|
||||
return 'this is a client function';
|
||||
}
|
||||
|
||||
const args = [fn];
|
||||
|
||||
const temporaryReferences =
|
||||
ReactServerDOMClient.createTemporaryReferenceSet();
|
||||
const body = await ReactServerDOMClient.encodeReply(args, {
|
||||
temporaryReferences,
|
||||
});
|
||||
|
||||
const temporaryReferencesServer =
|
||||
ReactServerDOMServer.createTemporaryReferenceSet();
|
||||
const serverPayload = await ReactServerDOMServer.decodeReply(
|
||||
body,
|
||||
webpackServerMap,
|
||||
{temporaryReferences: temporaryReferencesServer},
|
||||
);
|
||||
|
||||
async function action(arg) {
|
||||
return arg;
|
||||
}
|
||||
|
||||
const stream = await serverAct(() =>
|
||||
ReactServerDOMServer.renderToReadableStream(
|
||||
{
|
||||
result: action.apply(null, serverPayload),
|
||||
},
|
||||
null,
|
||||
{temporaryReferences: temporaryReferencesServer},
|
||||
),
|
||||
);
|
||||
const response = await ReactServerDOMClient.createFromReadableStream(
|
||||
stream,
|
||||
{
|
||||
temporaryReferences,
|
||||
},
|
||||
);
|
||||
|
||||
expect(await response.result).toBe(fn);
|
||||
});
|
||||
|
||||
it('should supports streaming ReadableStream with objects', async () => {
|
||||
let controller1;
|
||||
let controller2;
|
||||
|
|
|
|||
|
|
@ -70,8 +70,12 @@ const proxyHandlers = {
|
|||
`Instead, you can export a Client Component wrapper ` +
|
||||
`that itself renders a Client Context Provider.`,
|
||||
);
|
||||
// Allow returning a temporary reference from an async function
|
||||
case 'then':
|
||||
// Allow returning a temporary reference from an async function
|
||||
// Unlike regular Client References, a Promise would never have been serialized as
|
||||
// an opaque Temporary Reference, but instead would have been serialized as a
|
||||
// Promise on the server and so doesn't hit this path. So we can assume this wasn't
|
||||
// a Promise on the client.
|
||||
return undefined;
|
||||
}
|
||||
throw new Error(
|
||||
|
|
|
|||
|
|
@ -1,36 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @emails react-core
|
||||
* @jest-environment node
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
let ReactFlightServerTemporaryReferences;
|
||||
|
||||
describe('ReactFlightServerTemporaryReferences', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
ReactFlightServerTemporaryReferences = require('react-server/src/ReactFlightServerTemporaryReferences');
|
||||
});
|
||||
|
||||
it('can return a temporary reference from an async function', async () => {
|
||||
const temporaryReferenceSet =
|
||||
ReactFlightServerTemporaryReferences.createTemporaryReferenceSet();
|
||||
const temporaryReference =
|
||||
ReactFlightServerTemporaryReferences.createTemporaryReference(
|
||||
temporaryReferenceSet,
|
||||
'test',
|
||||
);
|
||||
|
||||
async function foo() {
|
||||
return temporaryReference;
|
||||
}
|
||||
|
||||
await expect(foo()).resolves.toBe(temporaryReference);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user