Skip to content

Commit

Permalink
[Flight] Serialize top-level Date (#31163)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
gnoff authored Oct 10, 2024
1 parent de43d56 commit f5b8d93
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
12 changes: 12 additions & 0 deletions packages/react-client/src/__tests__/ReactFlight-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 `
Expand Down
18 changes: 18 additions & 0 deletions packages/react-server/src/ReactFlightServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 (
Expand Down Expand Up @@ -3646,6 +3660,10 @@ function renderConsoleValue(
return serializeBigInt(value);
}

if (value instanceof Date) {
return serializeDate(value);
}

return 'unknown type ' + typeof value;
}

Expand Down

0 comments on commit f5b8d93

Please sign in to comment.