diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js index a81655f3b8..16a1678751 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js @@ -26,33 +26,78 @@ const {unwrapNullable} = require('../../parsers/flow/modules/utils'); type FilesOutput = Map; -const propertyHeaderTemplate = - 'static facebook::jsi::Value __hostFunction_::_HASTE_MODULE_NAME_::SpecJSI_::_PROPERTY_NAME_::(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {'; +type JSReturnType = + | 'VoidKind' + | 'StringKind' + | 'BooleanKind' + | 'NumberKind' + | 'PromiseKind' + | 'ObjectKind' + | 'ArrayKind'; -const propertyCastTemplate = - 'static_cast(turboModule).invokeJavaMethod(rt, ::_KIND_::, "::_PROPERTY_NAME_::", "::_SIGNATURE_::", args, count);'; - -const propertyTemplate = ` -${propertyHeaderTemplate} - return ${propertyCastTemplate} +const HostFunctionTemplate = ({ + hasteModuleName, + propertyName, + jniSignature, + jsReturnType, +}: $ReadOnly<{| + hasteModuleName: string, + propertyName: string, + jniSignature: string, + jsReturnType: JSReturnType, +|}>) => { + return `static facebook::jsi::Value __hostFunction_${hasteModuleName}SpecJSI_${propertyName}(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeJavaMethod(rt, ${jsReturnType}, "${propertyName}", "${jniSignature}", args, count); }`; +}; -const propertyDefTemplate = - ' methodMap_["::_PROPERTY_NAME_::"] = MethodMetadata {::_ARGS_COUNT_::, __hostFunction_::_HASTE_MODULE_NAME_::SpecJSI_::_PROPERTY_NAME_::};'; - -const moduleTemplate = ` -::_TURBOMODULE_METHOD_INVOKERS_:: - -::_HASTE_MODULE_NAME_::SpecJSI::::_HASTE_MODULE_NAME_::SpecJSI(const JavaTurboModule::InitParams ¶ms) +const ModuleClassConstructorTemplate = ({ + hasteModuleName, + methods, +}: $ReadOnly<{| + hasteModuleName: string, + methods: $ReadOnlyArray<{| + propertyName: string, + argCount: number, + |}>, +|}>) => { + return ` +${hasteModuleName}SpecJSI::${hasteModuleName}SpecJSI(const JavaTurboModule::InitParams ¶ms) : JavaTurboModule(params) { -::_PROPERTIES_MAP_:: +${methods + .map(({propertyName, argCount}) => { + return ` methodMap_["${propertyName}"] = MethodMetadata {${argCount}, __hostFunction_${hasteModuleName}SpecJSI_${propertyName}};`; + }) + .join('\n')} }`.trim(); +}; -const oneModuleLookupTemplate = ` if (moduleName == "::_NATIVE_MODULE_NAME_::") { - return std::make_shared<::_HASTE_MODULE_NAME_::SpecJSI>(params); +const ModuleLookupTemplate = ({ + moduleName, + hasteModuleName, +}: $ReadOnly<{|moduleName: string, hasteModuleName: string|}>) => { + return ` if (moduleName == "${moduleName}") { + return std::make_shared<${hasteModuleName}SpecJSI>(params); }`; +}; -const template = ` +const FileTemplate = ({ + libraryName, + include, + modules, + moduleLookups, +}: $ReadOnly<{| + libraryName: string, + include: string, + modules: string, + moduleLookups: $ReadOnlyArray< + $ReadOnly<{| + hasteModuleName: string, + moduleName: string, + |}>, + >, +|}>) => { + return ` /** * ${'C'}opyright (c) Facebook, Inc. and its affiliates. * @@ -62,26 +107,27 @@ const template = ` * ${'@'}generated by codegen project: GenerateModuleJniCpp.js */ -#include ::_INCLUDE_:: +#include ${include} namespace facebook { namespace react { -::_MODULES_:: +${modules} -std::shared_ptr ::_LIBRARY_NAME_::_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms) { -::_MODULE_LOOKUP_:: +std::shared_ptr ${libraryName}_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams ¶ms) { +${moduleLookups.map(ModuleLookupTemplate).join('\n')} return nullptr; } } // namespace react } // namespace facebook `; +}; function translateReturnTypeToKind( nullableTypeAnnotation: Nullable, resolveAlias: AliasResolver, -): string { +): JSReturnType { const [typeAnnotation] = unwrapNullable( nullableTypeAnnotation, ); @@ -278,6 +324,7 @@ function translateMethodTypeToJniSignature( } function translateMethodForImplementation( + hasteModuleName: string, property: NativeModulePropertySchema, resolveAlias: AliasResolver, ): string { @@ -288,41 +335,20 @@ function translateMethodForImplementation( ); const {returnTypeAnnotation} = propertyTypeAnnotation; - const numberOfParams = - propertyTypeAnnotation.params.length + - (returnTypeAnnotation.type === 'PromiseTypeAnnotation' ? 1 : 0); - const translatedArguments = propertyTypeAnnotation.params - .map(param => param.name) - .concat( - returnTypeAnnotation.type === 'PromiseTypeAnnotation' ? ['promise'] : [], - ) - .slice(1) - .join(':') - .concat(':'); if ( property.name === 'getConstants' && returnTypeAnnotation.type === 'ObjectTypeAnnotation' && - returnTypeAnnotation.properties && returnTypeAnnotation.properties.length === 0 ) { return ''; } - return propertyTemplate - .replace( - /::_KIND_::/g, - translateReturnTypeToKind(returnTypeAnnotation, resolveAlias), - ) - .replace(/::_PROPERTY_NAME_::/g, property.name) - .replace( - /::_ARGS_::/g, - numberOfParams === 0 - ? '' - : (numberOfParams === 1 ? '' : ':') + translatedArguments, - ) - .replace( - /::_SIGNATURE_::/g, - translateMethodTypeToJniSignature(property, resolveAlias), - ); + + return HostFunctionTemplate({ + hasteModuleName, + propertyName: property.name, + jniSignature: translateMethodTypeToJniSignature(property, resolveAlias), + jsReturnType: translateReturnTypeToKind(returnTypeAnnotation, resolveAlias), + }); } module.exports = { @@ -351,14 +377,20 @@ module.exports = { const translatedMethods = properties .map(property => - translateMethodForImplementation(property, resolveAlias), + translateMethodForImplementation( + hasteModuleName, + property, + resolveAlias, + ), ) - .join('\n'); - return moduleTemplate - .replace(/::_TURBOMODULE_METHOD_INVOKERS_::/g, translatedMethods) - .replace( - '::_PROPERTIES_MAP_::', - properties + .join('\n\n'); + + return ( + translatedMethods + + '\n\n' + + ModuleClassConstructorTemplate({ + hasteModuleName, + methods: properties .map(({name: propertyName, typeAnnotation}) => { const [ {returnTypeAnnotation, params}, @@ -366,22 +398,27 @@ module.exports = { typeAnnotation, ); - return propertyName === 'getConstants' && + if ( + propertyName === 'getConstants' && returnTypeAnnotation.type === 'ObjectTypeAnnotation' && returnTypeAnnotation.properties && returnTypeAnnotation.properties.length === 0 - ? '' - : propertyDefTemplate - .replace(/::_PROPERTY_NAME_::/g, propertyName) - .replace(/::_ARGS_COUNT_::/g, params.length.toString()); + ) { + return null; + } + + return { + propertyName, + argCount: params.length, + }; }) - .join('\n'), - ) - .replace(/::_HASTE_MODULE_NAME_::/g, hasteModuleName); + .filter(Boolean), + }) + ); }) .join('\n'); - const moduleLookup = Object.keys(nativeModules) + const moduleLookups = Object.keys(nativeModules) .filter(hasteModuleName => { const module = nativeModules[hasteModuleName]; return !( @@ -401,24 +438,23 @@ module.exports = { } return 0; }) - .map(hasteModuleName => { - const {moduleNames} = nativeModules[hasteModuleName]; - return moduleNames - .map(nativeModuleName => - oneModuleLookupTemplate - .replace(/::_NATIVE_MODULE_NAME_::/g, nativeModuleName) - .replace(/::_HASTE_MODULE_NAME_::/g, hasteModuleName), - ) - .join('\n'); - }) - .join('\n'); + .flatMap<{|moduleName: string, hasteModuleName: string|}>( + (hasteModuleName: string) => { + const {moduleNames} = nativeModules[hasteModuleName]; + return moduleNames.map(moduleName => ({ + moduleName, + hasteModuleName, + })); + }, + ); const fileName = `${moduleSpecName}-generated.cpp`; - const replacedTemplate = template - .replace(/::_MODULES_::/g, modules) - .replace(/::_LIBRARY_NAME_::/g, libraryName) - .replace(/::_MODULE_LOOKUP_::/g, moduleLookup) - .replace(/::_INCLUDE_::/g, `"${moduleSpecName}.h"`); + const replacedTemplate = FileTemplate({ + modules: modules, + libraryName, + moduleLookups, + include: `"${moduleSpecName}.h"`, + }); return new Map([[fileName, replacedTemplate]]); }, }; diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap index 30df29b8c3..2e2db08c4c 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap @@ -17,7 +17,6 @@ Map { namespace facebook { namespace react { - static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_difficult(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, \\"difficult\\", \\"(Lcom/facebook/react/bridge/ReadableMap;)Lcom/facebook/react/bridge/WritableMap;\\", args, count); } @@ -117,7 +116,6 @@ static facebook::jsi::Value __hostFunction_AliasTurboModuleSpecJSI_cropImage(fac AliasTurboModuleSpecJSI::AliasTurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms) : JavaTurboModule(params) { - methodMap_[\\"cropImage\\"] = MethodMetadata {1, __hostFunction_AliasTurboModuleSpecJSI_cropImage}; } @@ -167,12 +165,10 @@ static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_delete NativeCameraRollManagerSpecJSI::NativeCameraRollManagerSpecJSI(const JavaTurboModule::InitParams ¶ms) : JavaTurboModule(params) { - methodMap_[\\"getPhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_getPhotos}; methodMap_[\\"saveToCameraRoll\\"] = MethodMetadata {2, __hostFunction_NativeCameraRollManagerSpecJSI_saveToCameraRoll}; methodMap_[\\"deletePhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_deletePhotos}; } - static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportFatalException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, \\"reportFatalException\\", \\"(Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;D)V\\", args, count); } @@ -235,7 +231,6 @@ Map { namespace facebook { namespace react { - static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, \\"getConstants\\", \\"()Ljava/util/Map;\\", args, count); } @@ -325,7 +320,6 @@ Map { namespace facebook { namespace react { - static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, \\"voidFunc\\", \\"()V\\", args, count); } @@ -342,7 +336,6 @@ static facebook::jsi::Value __hostFunction_NativeSampleTurboModule2SpecJSI_voidF NativeSampleTurboModule2SpecJSI::NativeSampleTurboModule2SpecJSI(const JavaTurboModule::InitParams ¶ms) : JavaTurboModule(params) { - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModule2SpecJSI_voidFunc}; }