diff --git a/packages/react-client/src/__tests__/ReactFlight-test.js b/packages/react-client/src/__tests__/ReactFlight-test.js index 857ce99868d9b..35fe8fef0354d 100644 --- a/packages/react-client/src/__tests__/ReactFlight-test.js +++ b/packages/react-client/src/__tests__/ReactFlight-test.js @@ -661,6 +661,18 @@ describe('ReactFlight', () => { `); }); + it('can transport Date as a top-level value', async () => { + const date = new Date(0); + const transport = ReactNoopFlightServer.render(date); + + let readValue; + await act(async () => { + readValue = await ReactNoopFlightClient.read(transport); + }); + + expect(readValue).toEqual(date); + }); + it('can transport Error objects as values', async () => { function ComponentClient({prop}) { return ` diff --git a/packages/react-server/src/ReactFlightServer.js b/packages/react-server/src/ReactFlightServer.js index 5db03d628146f..0b1a4d3c7fee1 100644 --- a/packages/react-server/src/ReactFlightServer.js +++ b/packages/react-server/src/ReactFlightServer.js @@ -1962,6 +1962,12 @@ function serializeUndefined(): string { return '$undefined'; } +function serializeDate(date: Date): string { + // JSON.stringify automatically calls Date.prototype.toJSON which calls toISOString. + // We need only tack on a $D prefix. + return '$D' + date.toJSON(); +} + function serializeDateFromDateJSON(dateJSON: string): string { // JSON.stringify automatically calls Date.prototype.toJSON which calls toISOString. // We need only tack on a $D prefix. @@ -2779,6 +2785,14 @@ function renderModelDestructive( } } + // We put the Date check low b/c most of the time Date's will already have been serialized + // before we process it in this function but when rendering a Date() as a top level it can + // end up being a Date instance here. This is rare so we deprioritize it by putting it deep + // in this function + if (value instanceof Date) { + return serializeDate(value); + } + // Verify that this is a simple plain object. const proto = getPrototypeOf(value); if ( @@ -3646,6 +3660,10 @@ function renderConsoleValue( return serializeBigInt(value); } + if (value instanceof Date) { + return serializeDate(value); + } + return 'unknown type ' + typeof value; }