diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js index 919eba79edc..919612328ba 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js @@ -24,32 +24,60 @@ const {unwrapNullable} = require('../../parsers/flow/modules/utils'); type FilesOutput = Map; -const propertyHeaderTemplate = - 'static jsi::Value __hostFunction_::_HASTE_MODULE_NAME_::CxxSpecJSI_::_PROPERTY_NAME_::(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {'; +const HostFunctionTemplate = ({ + hasteModuleName, + methodName, + isVoid, + args, +}: $ReadOnly<{ + hasteModuleName: string, + methodName: string, + isVoid: boolean, + args: Array, +}>) => { + const methodCallArgs = ['rt', ...args].join(', '); + const methodCall = `static_cast<${hasteModuleName}CxxSpecJSI *>(&turboModule)->${methodName}(${methodCallArgs});`; -const propertyCastTemplate = - 'static_cast<::_HASTE_MODULE_NAME_::CxxSpecJSI *>(&turboModule)->::_PROPERTY_NAME_::(rt::_ARGS_::);'; - -const nonvoidPropertyTemplate = `${propertyHeaderTemplate} - return ${propertyCastTemplate} -}`.trim(); - -const voidPropertyTemplate = `${propertyHeaderTemplate} - ${propertyCastTemplate} - return jsi::Value::undefined(); + return `static jsi::Value __hostFunction_${hasteModuleName}CxxSpecJSI_${methodName}(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {${ + isVoid ? `\n ${methodCall}` : '' + } + return ${isVoid ? 'jsi::Value::undefined();' : methodCall} }`; +}; -const proprertyDefTemplate = - ' methodMap_["::_PROPERTY_NAME_::"] = MethodMetadata {::_ARGS_COUNT_::, __hostFunction_::_HASTE_MODULE_NAME_::CxxSpecJSI_::_PROPERTY_NAME_::};'; +const ModuleTemplate = ({ + hasteModuleName, + hostFunctions, + moduleName, + methods, +}: $ReadOnly<{| + hasteModuleName: string, + hostFunctions: $ReadOnlyArray, + moduleName: string, + methods: $ReadOnlyArray< + $ReadOnly<{|methodName: string, paramCount: number|}>, + >, +|}>) => { + return `${hostFunctions.join('\n')} -const moduleTemplate = `::_MODULE_PROPERTIES_:: +${hasteModuleName}CxxSpecJSI::${hasteModuleName}CxxSpecJSI(std::shared_ptr jsInvoker) + : TurboModule("${moduleName}", jsInvoker) { +${methods + .map(({methodName, paramCount}) => { + return ` methodMap_["${methodName}"] = MethodMetadata {${paramCount}, __hostFunction_${hasteModuleName}CxxSpecJSI_${methodName}};`; + }) + .join('\n')} +}`; +}; -::_HASTE_MODULE_NAME_::CxxSpecJSI::::_HASTE_MODULE_NAME_::CxxSpecJSI(std::shared_ptr jsInvoker) - : TurboModule("::_NATIVE_MODULE_NAME_::", jsInvoker) { -::_PROPERTIES_MAP_:: -}`.trim(); - -const template = `/** +const FileTemplate = ({ + libraryName, + modules, +}: $ReadOnly<{ + libraryName: string, + modules: string, +}>) => { + return `/** * ${'C'}opyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -58,19 +86,20 @@ const template = `/** * ${'@'}generated by codegen project: GenerateModuleH.js */ -#include +#include namespace facebook { namespace react { -::_MODULES_:: +${modules} } // namespace react } // namespace facebook `; +}; -function traverseArg( +function serializeArg( arg: NativeModuleMethodParamSchema, index: number, resolveAlias: AliasResolver, @@ -127,7 +156,8 @@ function traverseArg( } } -function traverseProperty( +function serializePropertyIntoHostFunction( + hasteModuleName: string, property: NativeModulePropertySchema, resolveAlias: AliasResolver, ): string { @@ -136,16 +166,17 @@ function traverseProperty( ] = unwrapNullable( property.typeAnnotation, ); - const propertyTemplate = - propertyTypeAnnotation.returnTypeAnnotation.type === 'VoidTypeAnnotation' - ? voidPropertyTemplate - : nonvoidPropertyTemplate; - const traversedArgs = propertyTypeAnnotation.params - .map((p, i) => traverseArg(p, i, resolveAlias)) - .join(', '); - return propertyTemplate - .replace(/::_PROPERTY_NAME_::/g, property.name) - .replace(/::_ARGS_::/g, traversedArgs === '' ? '' : ', ' + traversedArgs); + const isVoid = + propertyTypeAnnotation.returnTypeAnnotation.type === 'VoidTypeAnnotation'; + + return HostFunctionTemplate({ + hasteModuleName, + methodName: property.name, + isVoid, + args: propertyTypeAnnotation.params.map((p, i) => + serializeArg(p, i, resolveAlias), + ), + }); } module.exports = { @@ -157,7 +188,7 @@ module.exports = { const nativeModules = getModules(schema); const modules = Object.keys(nativeModules) - .map(hasteModuleName => { + .map((hasteModuleName: string) => { const nativeModule = nativeModules[hasteModuleName]; const { aliases, @@ -165,39 +196,37 @@ module.exports = { moduleNames, } = nativeModule; const resolveAlias = createAliasResolver(aliases); - const traversedProperties = properties - .map(property => traverseProperty(property, resolveAlias)) - .join('\n'); - return ( - moduleTemplate - .replace(/::_MODULE_PROPERTIES_::/g, traversedProperties) - // TODO: What happens when there are more than one NativeModule requires? - .replace('::_NATIVE_MODULE_NAME_::', moduleNames[0]) - .replace( - '::_PROPERTIES_MAP_::', - properties - .map( - ({ - name: propertyName, - typeAnnotation: nullableTypeAnnotation, - }) => { - const [{params}] = unwrapNullable(nullableTypeAnnotation); - return proprertyDefTemplate - .replace(/::_PROPERTY_NAME_::/g, propertyName) - .replace(/::_ARGS_COUNT_::/g, params.length.toString()); - }, - ) - .join('\n'), - ) - .replace(/::_HASTE_MODULE_NAME_::/g, hasteModuleName) + const hostFunctions = properties.map(property => + serializePropertyIntoHostFunction( + hasteModuleName, + property, + resolveAlias, + ), ); + + return ModuleTemplate({ + hasteModuleName, + hostFunctions, + // TODO: What happens when there are more than one NativeModule requires? + moduleName: moduleNames[0], + methods: properties.map( + ({name: propertyName, typeAnnotation: nullableTypeAnnotation}) => { + const [{params}] = unwrapNullable(nullableTypeAnnotation); + return { + methodName: propertyName, + paramCount: params.length, + }; + }, + ), + }); }) .join('\n'); const fileName = 'NativeModules.cpp'; - const replacedTemplate = template - .replace(/::_MODULES_::/g, modules) - .replace(/::_LIBRARY_NAME_::/g, libraryName); + const replacedTemplate = FileTemplate({ + modules, + libraryName, + }); return new Map([[fileName, replacedTemplate]]); }, };