Skip to content

Commit 64dc39f

Browse files
christophpurrermeta-codesync[bot]
authored andcommitted
Add BigInt Type Support for Turbo Module Code Generation (#56016)
Summary: Pull Request resolved: #56016 This diff extends the React Native codegen to support BigIntTypeAnnotation. This type enables Turbo Modules to handle 64-bit integers safely by using JavaScript BigInt on the JS side and `facebook::react::BigInt` on native C++ platforms (with Java `long` for Android JNI). Changes: - Added BigIntTypeAnnotation to CodegenSchema.js - Added emitBigInt parser function in parsers-primitives.js - Added TSBigIntKeyword mapping in TypeScript parser - Updated GenerateModuleH.js for C++ header generation with `BigInt` param/return type and `jsi::BigInt` callFromJs return type - Updated GenerateModuleJavaSpec.js — BigInt maps to 'long' for JNI params but throws "not supported" for Java spec generation (not yet supported) - Updated GenerateModuleJniCpp.js with BigIntKind return type - Updated Objective-C generators: serializeMethod.js, StructCollector.js, serializeConstantsStruct.js, serializeRegularStruct.js - Updated compatibility check: ErrorFormatting.js, SortTypeAnnotations.js, TypeDiffing.js Example Turbo Module definition: ```javascript export interface Spec extends TurboModule { +getBigInt: (arg: bigint) => bigint; } ``` Changelog: [General][Added] - Add BigInt Type Support for Turbo Module Code Generation Differential Revision: D95232267
1 parent 987a941 commit 64dc39f

File tree

13 files changed

+74
-1
lines changed

13 files changed

+74
-1
lines changed

packages/react-native-codegen/src/CodegenSchema.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ export type Int32TypeAnnotation = Readonly<{
4242
type: 'Int32TypeAnnotation',
4343
}>;
4444

45+
export type BigIntTypeAnnotation = Readonly<{
46+
type: 'BigIntTypeAnnotation',
47+
}>;
48+
4549
export type NumberLiteralTypeAnnotation = Readonly<{
4650
type: 'NumberLiteralTypeAnnotation',
4751
value: number,
@@ -418,6 +422,7 @@ export type NativeModuleBaseTypeAnnotation =
418422
| NumberLiteralTypeAnnotation
419423
| BooleanLiteralTypeAnnotation
420424
| Int32TypeAnnotation
425+
| BigIntTypeAnnotation
421426
| DoubleTypeAnnotation
422427
| FloatTypeAnnotation
423428
| BooleanTypeAnnotation

packages/react-native-codegen/src/generators/modules/GenerateModuleH.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ function serializeArg(
119119
return wrap(val => `${val}.asNumber()`);
120120
case 'Int32TypeAnnotation':
121121
return wrap(val => `${val}.asNumber()`);
122+
case 'BigIntTypeAnnotation':
123+
return wrap(val => `jsi::Value(rt, ${val})`);
122124
case 'NumberLiteralTypeAnnotation':
123125
return wrap(val => `${val}.asNumber()`);
124126
case 'ArrayTypeAnnotation':
@@ -267,6 +269,8 @@ function translatePrimitiveJSTypeToCpp(
267269
return wrapOptional('double', isRequired);
268270
case 'Int32TypeAnnotation':
269271
return wrapOptional('int', isRequired);
272+
case 'BigIntTypeAnnotation':
273+
return wrapOptional('BigInt', isRequired);
270274
case 'BooleanTypeAnnotation':
271275
return wrapOptional('bool', isRequired);
272276
case 'BooleanLiteralTypeAnnotation':
@@ -601,6 +605,12 @@ function translateFunctionToCpp(
601605
enumMap,
602606
);
603607

608+
// BigInt methods return BigInt from C++, but the callFromJs template
609+
// parameter must be jsi::BigInt so the bridging layer converts via
610+
// Bridging<BigInt>::toJs -> jsi::BigInt -> jsi::Value.
611+
const callFromJsReturnType =
612+
returnType === 'BigInt' ? 'jsi::BigInt' : returnType;
613+
604614
let methodCallArgs = [...args].join(',\n ');
605615
if (methodCallArgs.length > 0) {
606616
methodCallArgs = `,\n ${methodCallArgs}`;
@@ -610,7 +620,7 @@ function translateFunctionToCpp(
610620
static_assert(
611621
bridging::getParameterCount(&T::${prop.name}) == ${paramTypes.length},
612622
"Expected ${prop.name}(...) to have ${paramTypes.length} parameters");
613-
${!isVoid ? (!isNullable ? 'return ' : 'auto result = ') : ''}bridging::callFromJs<${returnType}>(rt, &T::${prop.name}, static_cast<${hasteModuleName}CxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule)${methodCallArgs});${!isVoid ? (!isNullable ? '' : 'return result ? jsi::Value(std::move(*result)) : jsi::Value::null();') : 'return jsi::Value::undefined();'}\n }`;
623+
${!isVoid ? (!isNullable ? 'return ' : 'auto result = ') : ''}bridging::callFromJs<${callFromJsReturnType}>(rt, &T::${prop.name}, static_cast<${hasteModuleName}CxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule)${methodCallArgs});${!isVoid ? (!isNullable ? '' : 'return result ? jsi::Value(std::move(*result)) : jsi::Value::null();') : 'return jsi::Value::undefined();'}\n }`;
614624
}
615625
616626
type EventEmitterCpp = {

packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ function translateEventEmitterTypeToJavaType(
155155
case 'DoubleTypeAnnotation':
156156
case 'Int32TypeAnnotation':
157157
return 'double';
158+
case 'BigIntTypeAnnotation':
159+
imports.add('java.math.BigInteger');
160+
return 'BigInteger';
158161
case 'BooleanTypeAnnotation':
159162
case 'BooleanLiteralTypeAnnotation':
160163
return 'boolean';
@@ -267,6 +270,12 @@ function translateFunctionParamToJavaType(
267270
case 'FunctionTypeAnnotation':
268271
imports.add('com.facebook.react.bridge.Callback');
269272
return wrapOptional('Callback', isRequired);
273+
case 'BigIntTypeAnnotation':
274+
throw new Error(
275+
createErrorMessage(
276+
`${realTypeAnnotation.type} is not supported in Java TurboModules yet`,
277+
),
278+
);
270279
default:
271280
realTypeAnnotation.type as 'MixedTypeAnnotation';
272281
throw new Error(createErrorMessage(realTypeAnnotation.type));
@@ -361,6 +370,12 @@ function translateFunctionReturnTypeToJavaType(
361370
case 'ArrayTypeAnnotation':
362371
imports.add('com.facebook.react.bridge.WritableArray');
363372
return wrapOptional('WritableArray', isRequired);
373+
case 'BigIntTypeAnnotation':
374+
throw new Error(
375+
createErrorMessage(
376+
`${realTypeAnnotation.type} is not supported in Java TurboModules yet`,
377+
),
378+
);
364379
default:
365380
realTypeAnnotation.type as 'MixedTypeAnnotation';
366381
throw new Error(createErrorMessage(realTypeAnnotation.type));
@@ -443,6 +458,8 @@ function getFalsyReturnStatementFromReturnType(
443458
return 'return null;';
444459
case 'ArrayTypeAnnotation':
445460
return 'return null;';
461+
case 'BigIntTypeAnnotation':
462+
throw new Error(createErrorMessage(realTypeAnnotation.type));
446463
default:
447464
realTypeAnnotation.type as 'MixedTypeAnnotation';
448465
throw new Error(createErrorMessage(realTypeAnnotation.type));

packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type JSReturnType =
3333
| 'StringKind'
3434
| 'BooleanKind'
3535
| 'NumberKind'
36+
| 'BigIntKind'
3637
| 'PromiseKind'
3738
| 'ObjectKind'
3839
| 'ArrayKind';
@@ -208,6 +209,8 @@ function translateReturnTypeToKind(
208209
return 'NumberKind';
209210
case 'Int32TypeAnnotation':
210211
return 'NumberKind';
212+
case 'BigIntTypeAnnotation':
213+
return 'BigIntKind';
211214
case 'PromiseTypeAnnotation':
212215
return 'PromiseKind';
213216
case 'GenericObjectTypeAnnotation':
@@ -295,6 +298,10 @@ function translateParamTypeToJniType(
295298
return !isRequired ? 'Ljava/lang/Double;' : 'D';
296299
case 'Int32TypeAnnotation':
297300
return !isRequired ? 'Ljava/lang/Double;' : 'D';
301+
case 'BigIntTypeAnnotation':
302+
throw new Error(
303+
`${realTypeAnnotation.type} is not supported in Java TurboModules yet`,
304+
);
298305
case 'GenericObjectTypeAnnotation':
299306
return 'Lcom/facebook/react/bridge/ReadableMap;';
300307
case 'ObjectTypeAnnotation':
@@ -379,6 +386,10 @@ function translateReturnTypeToJniType(
379386
return nullable ? 'Ljava/lang/Double;' : 'D';
380387
case 'Int32TypeAnnotation':
381388
return nullable ? 'Ljava/lang/Double;' : 'D';
389+
case 'BigIntTypeAnnotation':
390+
throw new Error(
391+
`${realTypeAnnotation.type} is not supported in Java TurboModules yet`,
392+
);
382393
case 'PromiseTypeAnnotation':
383394
return 'Lcom/facebook/react/bridge/Promise;';
384395
case 'GenericObjectTypeAnnotation':

packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/StructCollector.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
'use strict';
1212

1313
import type {
14+
BigIntTypeAnnotation,
1415
BooleanLiteralTypeAnnotation,
1516
BooleanTypeAnnotation,
1617
DoubleTypeAnnotation,
@@ -72,6 +73,7 @@ export type StructTypeAnnotation =
7273
| NumberLiteralTypeAnnotation
7374
| BooleanLiteralTypeAnnotation
7475
| Int32TypeAnnotation
76+
| BigIntTypeAnnotation
7577
| DoubleTypeAnnotation
7678
| FloatTypeAnnotation
7779
| BooleanTypeAnnotation

packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeConstantsStruct.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ function toObjCValue(
115115
return wrapPrimitive('double');
116116
case 'Int32TypeAnnotation':
117117
return wrapPrimitive('double');
118+
case 'BigIntTypeAnnotation':
119+
return value;
118120
case 'DoubleTypeAnnotation':
119121
return wrapPrimitive('double');
120122
case 'BooleanTypeAnnotation':

packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeRegularStruct.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ function toObjCValue(
106106
return RCTBridgingTo('Double');
107107
case 'Int32TypeAnnotation':
108108
return RCTBridgingTo('Double');
109+
case 'BigIntTypeAnnotation':
110+
return RCTBridgingTo('NSNumber');
109111
case 'DoubleTypeAnnotation':
110112
return RCTBridgingTo('Double');
111113
case 'BooleanTypeAnnotation':

packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/serializeMethod.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ type ReturnJSType =
5151
| 'ObjectKind'
5252
| 'ArrayKind'
5353
| 'NumberKind'
54+
| 'BigIntKind'
5455
| 'StringKind';
5556

5657
export type MethodSerializationOutput = Readonly<{
@@ -272,6 +273,8 @@ function getParamObjCType(
272273
return notStruct(isRequired ? 'double' : 'NSNumber *');
273274
case 'Int32TypeAnnotation':
274275
return notStruct(isRequired ? 'NSInteger' : 'NSNumber *');
276+
case 'BigIntTypeAnnotation':
277+
return notStruct(wrapOptional('NSNumber *', !nullable));
275278
case 'BooleanTypeAnnotation':
276279
return notStruct(isRequired ? 'BOOL' : 'NSNumber *');
277280
case 'BooleanLiteralTypeAnnotation':
@@ -353,6 +356,8 @@ function getReturnObjCType(
353356
return wrapOptional('NSNumber *', isRequired);
354357
case 'Int32TypeAnnotation':
355358
return wrapOptional('NSNumber *', isRequired);
359+
case 'BigIntTypeAnnotation':
360+
return wrapOptional('NSNumber *', isRequired);
356361
case 'BooleanTypeAnnotation':
357362
return wrapOptional('NSNumber *', isRequired);
358363
case 'BooleanLiteralTypeAnnotation':
@@ -427,6 +432,8 @@ function getReturnJSType(
427432
return 'NumberKind';
428433
case 'Int32TypeAnnotation':
429434
return 'NumberKind';
435+
case 'BigIntTypeAnnotation':
436+
return 'BigIntKind';
430437
case 'BooleanTypeAnnotation':
431438
return 'BooleanKind';
432439
case 'BooleanLiteralTypeAnnotation':

packages/react-native-codegen/src/parsers/parsers-primitives.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
'use strict';
1212

1313
import type {
14+
BigIntTypeAnnotation,
1415
BooleanLiteralTypeAnnotation,
1516
BooleanTypeAnnotation,
1617
DoubleTypeAnnotation,
@@ -87,6 +88,12 @@ function emitInt32Prop(
8788
};
8889
}
8990

91+
function emitBigInt(nullable: boolean): Nullable<BigIntTypeAnnotation> {
92+
return wrapNullable(nullable, {
93+
type: 'BigIntTypeAnnotation',
94+
});
95+
}
96+
9097
function emitNumber(
9198
nullable: boolean,
9299
): Nullable<NativeModuleNumberTypeAnnotation> {
@@ -652,6 +659,8 @@ function emitCommonTypes(
652659
const typeMap = {
653660
Stringish: emitStringish,
654661
Int32: emitInt32,
662+
BigInt: emitBigInt,
663+
BigIntTypeAnnotation: emitBigInt,
655664
Double: emitDouble,
656665
Float: emitFloat,
657666
UnsafeObject: emitGenericObject,

packages/react-native-codegen/src/parsers/typescript/parser.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,8 @@ class TypeScriptParser implements Parser {
393393
return 'ArrayTypeAnnotation';
394394
case 'TSBooleanKeyword':
395395
return 'BooleanTypeAnnotation';
396+
case 'TSBigIntKeyword':
397+
return 'BigIntTypeAnnotation';
396398
case 'TSNumberKeyword':
397399
return 'NumberTypeAnnotation';
398400
case 'TSVoidKeyword':

0 commit comments

Comments
 (0)