Skip to content

Commit e2cd77b

Browse files
eps1lonAndyPengc12
authored andcommitted
[Flight] Add support BigInt support (facebook#26479)
## Summary Adds support for sending `BigInt` to Flight and Flight Reply ## How did you test this change? - added tests
1 parent 356b30f commit e2cd77b

File tree

11 files changed

+51
-7
lines changed

11 files changed

+51
-7
lines changed

.eslintrc.js

+3
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,9 @@ module.exports = {
449449
$ReadOnlyArray: 'readonly',
450450
$Shape: 'readonly',
451451
AnimationFrameID: 'readonly',
452+
// For Flow type annotation. Only `BigInt` is valid at runtime.
453+
bigint: 'readonly',
454+
BigInt: 'readonly',
452455
Class: 'readonly',
453456
ClientRect: 'readonly',
454457
CopyInspectedElementPath: 'readonly',

packages/react-client/src/ReactFlightClient.js

+4
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,10 @@ export function parseModelString(
564564
// Special encoding for `undefined` which can't be serialized as JSON otherwise.
565565
return undefined;
566566
}
567+
case 'n': {
568+
// BigInt
569+
return BigInt(value.substring(2));
570+
}
567571
default: {
568572
// We assume that anything else is a reference ID.
569573
const id = parseInt(value.substring(1), 16);

packages/react-client/src/ReactFlightReplyClient.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ function serializeUndefined(): string {
7575
return '$undefined';
7676
}
7777

78+
function serializeBigInt(n: bigint): string {
79+
return '$n' + n.toString(10);
80+
}
81+
7882
function escapeStringValue(value: string): string {
7983
if (value[0] === '$') {
8084
// We need to escape $ prefixed strings since we use those to encode
@@ -264,9 +268,7 @@ export function processReply(
264268
}
265269

266270
if (typeof value === 'bigint') {
267-
throw new Error(
268-
`BigInt (${value}) is not yet supported as an argument to a Server Function.`,
269-
);
271+
return serializeBigInt(value);
270272
}
271273

272274
throw new Error(

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

+19
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,25 @@ describe('ReactFlight', () => {
229229
expect(ReactNoop).toMatchRenderedOutput(null);
230230
});
231231

232+
it('can transport BigInt', async () => {
233+
function ComponentClient({prop}) {
234+
return `prop: ${prop} (${typeof prop})`;
235+
}
236+
const Component = clientReference(ComponentClient);
237+
238+
const model = <Component prop={90071992547409910000n} />;
239+
240+
const transport = ReactNoopFlightServer.render(model);
241+
242+
await act(async () => {
243+
ReactNoop.render(await ReactNoopFlightClient.read(transport));
244+
});
245+
246+
expect(ReactNoop).toMatchRenderedOutput(
247+
'prop: 90071992547409910000 (bigint)',
248+
);
249+
});
250+
232251
it('can render a lazy component as a shared component on the server', async () => {
233252
function SharedComponent({text}) {
234253
return (

packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMReply-test.js

+7
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,11 @@ describe('ReactFlightDOMReply', () => {
7575
}
7676
expect(items).toEqual(['A', 'B', 'C']);
7777
});
78+
79+
it('can pass a BigInt as a reply', async () => {
80+
const body = await ReactServerDOMClient.encodeReply(90071992547409910000n);
81+
const n = await ReactServerDOMServer.decodeReply(body, webpackServerMap);
82+
83+
expect(n).toEqual(90071992547409910000n);
84+
});
7885
});

packages/react-server/src/ReactFlightReplyServer.js

+4
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,10 @@ function parseModelString(
402402
// Special encoding for `undefined` which can't be serialized as JSON otherwise.
403403
return undefined;
404404
}
405+
case 'n': {
406+
// BigInt
407+
return BigInt(value.substring(2));
408+
}
405409
default: {
406410
// We assume that anything else is a reference ID.
407411
const id = parseInt(value.substring(1), 16);

packages/react-server/src/ReactFlightServer.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,10 @@ function serializeUndefined(): string {
553553
return '$undefined';
554554
}
555555

556+
function serializeBigInt(n: bigint): string {
557+
return '$n' + n.toString(10);
558+
}
559+
556560
function serializeClientReference(
557561
request: Request,
558562
parent:
@@ -931,10 +935,7 @@ export function resolveModelToJSON(
931935
}
932936

933937
if (typeof value === 'bigint') {
934-
throw new Error(
935-
`BigInt (${value}) is not yet supported in Client Component props.` +
936-
describeObjectForErrorMessage(parent, key),
937-
);
938+
return serializeBigInt(value);
938939
}
939940

940941
throw new Error(

scripts/rollup/validate/eslintrc.esm.js

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ module.exports = {
77
},
88
globals: {
99
// ES 6
10+
BigInt: 'readonly',
1011
Map: 'readonly',
1112
Set: 'readonly',
1213
Proxy: 'readonly',

scripts/rollup/validate/eslintrc.fb.js

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ module.exports = {
77
},
88
globals: {
99
// ES6
10+
BigInt: 'readonly',
1011
Map: 'readonly',
1112
Set: 'readonly',
1213
Symbol: 'readonly',

scripts/rollup/validate/eslintrc.rn.js

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ module.exports = {
77
},
88
globals: {
99
// ES6
10+
BigInt: 'readonly',
1011
Map: 'readonly',
1112
Set: 'readonly',
1213
Symbol: 'readonly',

scripts/rollup/validate/eslintrc.umd.js

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module.exports = {
66
},
77
globals: {
88
// ES6
9+
BigInt: 'readonly',
910
Map: 'readonly',
1011
Set: 'readonly',
1112
Symbol: 'readonly',

0 commit comments

Comments
 (0)