Skip to content

Commit f5b8d93

Browse files
authored
[Flight] Serialize top-level Date (#31163)
renderModelDesctructive can sometimes be called direclty on Date values. When this happens we don't first call toJSON on the Date value so we need to explicitly handle the case where where the rendered value is a Date instance as well. This change updates renderModelDesctructive to account for sometimes receiving Date instances directly.
1 parent de43d56 commit f5b8d93

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

packages/react-client/src/__tests__/ReactFlight-test.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,18 @@ describe('ReactFlight', () => {
661661
`);
662662
});
663663

664+
it('can transport Date as a top-level value', async () => {
665+
const date = new Date(0);
666+
const transport = ReactNoopFlightServer.render(date);
667+
668+
let readValue;
669+
await act(async () => {
670+
readValue = await ReactNoopFlightClient.read(transport);
671+
});
672+
673+
expect(readValue).toEqual(date);
674+
});
675+
664676
it('can transport Error objects as values', async () => {
665677
function ComponentClient({prop}) {
666678
return `

packages/react-server/src/ReactFlightServer.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1962,6 +1962,12 @@ function serializeUndefined(): string {
19621962
return '$undefined';
19631963
}
19641964

1965+
function serializeDate(date: Date): string {
1966+
// JSON.stringify automatically calls Date.prototype.toJSON which calls toISOString.
1967+
// We need only tack on a $D prefix.
1968+
return '$D' + date.toJSON();
1969+
}
1970+
19651971
function serializeDateFromDateJSON(dateJSON: string): string {
19661972
// JSON.stringify automatically calls Date.prototype.toJSON which calls toISOString.
19671973
// We need only tack on a $D prefix.
@@ -2779,6 +2785,14 @@ function renderModelDestructive(
27792785
}
27802786
}
27812787

2788+
// We put the Date check low b/c most of the time Date's will already have been serialized
2789+
// before we process it in this function but when rendering a Date() as a top level it can
2790+
// end up being a Date instance here. This is rare so we deprioritize it by putting it deep
2791+
// in this function
2792+
if (value instanceof Date) {
2793+
return serializeDate(value);
2794+
}
2795+
27822796
// Verify that this is a simple plain object.
27832797
const proto = getPrototypeOf(value);
27842798
if (
@@ -3646,6 +3660,10 @@ function renderConsoleValue(
36463660
return serializeBigInt(value);
36473661
}
36483662

3663+
if (value instanceof Date) {
3664+
return serializeDate(value);
3665+
}
3666+
36493667
return 'unknown type ' + typeof value;
36503668
}
36513669

0 commit comments

Comments
 (0)