@samitouri / QOS-React / commits / f5b8d9378b

[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.

Josh Story committed Oct 9, 2024 at 20:29 UTC f5b8d9378b36e7e2bb9b908752e6a9d250a44c84
2 files changed +30
packages/react-client/src/__tests__/ReactFlight-test.js
+12
@@ -661,6 +661,18 @@ describe('ReactFlight', () => {
661 `);
662 });
663
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 +
676 it('can transport Error objects as values', async () => {
677 function ComponentClient({prop}) {
678 return `
packages/react-server/src/ReactFlightServer.js
+18
@@ -1962,6 +1962,12 @@ function serializeUndefined(): string {
1962 return '$undefined';
1963 }
1964
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 +
1971 function serializeDateFromDateJSON(dateJSON: string): string {
1972 // JSON.stringify automatically calls Date.prototype.toJSON which calls toISOString.
1973 // We need only tack on a $D prefix.
@@ -2779,6 +2785,14 @@ function renderModelDestructive(
2785 }
2786 }
2787
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 +
2796 // Verify that this is a simple plain object.
2797 const proto = getPrototypeOf(value);
2798 if (
@@ -3646,6 +3660,10 @@ function renderConsoleValue(
3660 return serializeBigInt(value);
3661 }
3662
3663 + if (value instanceof Date) {
3664 + return serializeDate(value);
3665 + }
3666 +
3667 return 'unknown type ' + typeof value;
3668 }
3669