@@ -15,6 +15,7 @@ import type {
15
15
SchemaType ,
16
16
NativeModuleTypeAnnotation ,
17
17
NativeModuleFunctionTypeAnnotation ,
18
+ NativeModulePropertyShape ,
18
19
} from '../../CodegenSchema' ;
19
20
20
21
import type { AliasResolver } from './Utils' ;
@@ -27,21 +28,58 @@ type FilesOutput = Map<string, string>;
27
28
const ModuleClassDeclarationTemplate = ( {
28
29
hasteModuleName,
29
30
moduleProperties,
30
- } : $ReadOnly < { hasteModuleName : string , moduleProperties : string } > ) => {
31
+ } : $ReadOnly < { hasteModuleName : string , moduleProperties : string [ ] } > ) => {
31
32
return `class JSI_EXPORT ${ hasteModuleName } CxxSpecJSI : public TurboModule {
32
33
protected:
33
34
${ hasteModuleName } CxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker);
34
35
35
36
public:
36
- ${ indent ( moduleProperties , 2 ) }
37
+ ${ indent ( moduleProperties . join ( '\n' ) , 2 ) }
37
38
38
39
};` ;
39
40
} ;
40
41
42
+ const ModuleSpecClassDeclarationTemplate = ( {
43
+ hasteModuleName,
44
+ moduleName,
45
+ moduleProperties,
46
+ } : $ReadOnly < {
47
+ hasteModuleName : string ,
48
+ moduleName : string ,
49
+ moduleProperties : string [ ] ,
50
+ } > ) => {
51
+ return `template <typename T>
52
+ class JSI_EXPORT ${ hasteModuleName } CxxSpec : public TurboModule {
53
+ public:
54
+ jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &propName) override {
55
+ return delegate_.get(rt, propName);
56
+ }
57
+
58
+ protected:
59
+ ${ hasteModuleName } CxxSpec(std::shared_ptr<CallInvoker> jsInvoker)
60
+ : TurboModule("${ moduleName } ", jsInvoker),
61
+ delegate_(static_cast<T*>(this), jsInvoker) {}
62
+
63
+ private:
64
+ class Delegate : public ${ hasteModuleName } CxxSpecJSI {
65
+ public:
66
+ Delegate(T *instance, std::shared_ptr<CallInvoker> jsInvoker) :
67
+ ${ hasteModuleName } CxxSpecJSI(std::move(jsInvoker)), instance_(instance) {}
68
+
69
+ ${ indent ( moduleProperties . join ( '\n' ) , 4 ) }
70
+
71
+ private:
72
+ T *instance_;
73
+ };
74
+
75
+ Delegate delegate_;
76
+ };` ;
77
+ } ;
78
+
41
79
const FileTemplate = ( {
42
80
modules,
43
81
} : $ReadOnly < {
44
- modules : string ,
82
+ modules : string [ ] ,
45
83
} > ) => {
46
84
return `/**
47
85
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
@@ -55,11 +93,12 @@ const FileTemplate = ({
55
93
#pragma once
56
94
57
95
#include <ReactCommon/TurboModule.h>
96
+ #include <react/bridging/Bridging.h>
58
97
59
98
namespace facebook {
60
99
namespace react {
61
100
62
- ${ modules }
101
+ ${ modules . join ( '\n\n' ) }
63
102
64
103
} // namespace react
65
104
} // namespace facebook
@@ -118,8 +157,52 @@ function translatePrimitiveJSTypeToCpp(
118
157
}
119
158
}
120
159
121
- const propertyTemplate =
122
- 'virtual ::_RETURN_VALUE_:: ::_PROPERTY_NAME_::(jsi::Runtime &rt::_ARGS_::) = 0;' ;
160
+ function translatePropertyToCpp (
161
+ prop : NativeModulePropertyShape ,
162
+ resolveAlias : AliasResolver ,
163
+ abstract : boolean = false ,
164
+ ) {
165
+ const [ propTypeAnnotation ] =
166
+ unwrapNullable < NativeModuleFunctionTypeAnnotation > ( prop . typeAnnotation ) ;
167
+
168
+ const params = propTypeAnnotation . params . map (
169
+ param => `std::move(${ param . name } )` ,
170
+ ) ;
171
+
172
+ const paramTypes = propTypeAnnotation . params . map ( param => {
173
+ const translatedParam = translatePrimitiveJSTypeToCpp (
174
+ param . typeAnnotation ,
175
+ typeName =>
176
+ `Unsupported type for param "${ param . name } " in ${ prop . name } . Found: ${ typeName } ` ,
177
+ resolveAlias ,
178
+ ) ;
179
+ return `${ translatedParam } ${ param . name } ` ;
180
+ } ) ;
181
+
182
+ const returnType = translatePrimitiveJSTypeToCpp (
183
+ propTypeAnnotation . returnTypeAnnotation ,
184
+ typeName => `Unsupported return type for ${ prop . name } . Found: ${ typeName } ` ,
185
+ resolveAlias ,
186
+ ) ;
187
+
188
+ // The first param will always be the runtime reference.
189
+ paramTypes . unshift ( 'jsi::Runtime &rt' ) ;
190
+
191
+ const method = `${ returnType } ${ prop . name } (${ paramTypes . join ( ', ' ) } )` ;
192
+
193
+ if ( abstract ) {
194
+ return `virtual ${ method } = 0;` ;
195
+ }
196
+
197
+ return `${ method } override {
198
+ static_assert(
199
+ bridging::getParameterCount(&T::${ prop . name } ) == ${ paramTypes . length } ,
200
+ "Expected ${ prop . name } (...) to have ${ paramTypes . length } parameters");
201
+
202
+ return bridging::callFromJs<${ returnType } >(
203
+ rt, &T::${ prop . name } , jsInvoker_, ${ [ 'instance_' , ...params ] . join ( ', ' ) } );
204
+ }` ;
205
+ }
123
206
124
207
module . exports = {
125
208
generate (
@@ -130,55 +213,30 @@ module.exports = {
130
213
) : FilesOutput {
131
214
const nativeModules = getModules ( schema ) ;
132
215
133
- const modules = Object . keys ( nativeModules )
134
- . map ( hasteModuleName => {
135
- const {
136
- aliases,
137
- spec : { properties} ,
138
- } = nativeModules [ hasteModuleName ] ;
139
- const resolveAlias = createAliasResolver ( aliases ) ;
140
-
141
- const traversedProperties = properties
142
- . map ( prop => {
143
- const [ propTypeAnnotation ] =
144
- unwrapNullable < NativeModuleFunctionTypeAnnotation > (
145
- prop . typeAnnotation ,
146
- ) ;
147
- const traversedArgs = propTypeAnnotation . params
148
- . map ( param => {
149
- const translatedParam = translatePrimitiveJSTypeToCpp (
150
- param . typeAnnotation ,
151
- typeName =>
152
- `Unsupported type for param "${ param . name } " in ${ prop . name } . Found: ${ typeName } ` ,
153
- resolveAlias ,
154
- ) ;
155
- return `${ translatedParam } ${ param . name } ` ;
156
- } )
157
- . join ( ', ' ) ;
158
- return propertyTemplate
159
- . replace ( '::_PROPERTY_NAME_::' , prop . name )
160
- . replace (
161
- '::_RETURN_VALUE_::' ,
162
- translatePrimitiveJSTypeToCpp (
163
- propTypeAnnotation . returnTypeAnnotation ,
164
- typeName =>
165
- `Unsupported return type for ${ prop . name } . Found: ${ typeName } ` ,
166
- resolveAlias ,
167
- ) ,
168
- )
169
- . replace (
170
- '::_ARGS_::' ,
171
- traversedArgs === '' ? '' : ', ' + traversedArgs ,
172
- ) ;
173
- } )
174
- . join ( '\n' ) ;
175
-
176
- return ModuleClassDeclarationTemplate ( {
216
+ const modules = Object . keys ( nativeModules ) . flatMap ( hasteModuleName => {
217
+ const {
218
+ aliases,
219
+ spec : { properties} ,
220
+ moduleNames : [ moduleName ] ,
221
+ } = nativeModules [ hasteModuleName ] ;
222
+ const resolveAlias = createAliasResolver ( aliases ) ;
223
+
224
+ return [
225
+ ModuleClassDeclarationTemplate ( {
226
+ hasteModuleName,
227
+ moduleProperties : properties . map ( prop =>
228
+ translatePropertyToCpp ( prop , resolveAlias , true ) ,
229
+ ) ,
230
+ } ) ,
231
+ ModuleSpecClassDeclarationTemplate ( {
177
232
hasteModuleName,
178
- moduleProperties : traversedProperties ,
179
- } ) ;
180
- } )
181
- . join ( '\n' ) ;
233
+ moduleName,
234
+ moduleProperties : properties . map ( prop =>
235
+ translatePropertyToCpp ( prop , resolveAlias ) ,
236
+ ) ,
237
+ } ) ,
238
+ ] ;
239
+ } ) ;
182
240
183
241
const fileName = `${libraryName } JSI . h `;
184
242
const replacedTemplate = FileTemplate ( { modules} ) ;
0 commit comments