/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow strict * @format */ 'use strict'; import type { Nullable, SchemaType, NativeModuleTypeAnnotation, NativeModuleFunctionTypeAnnotation, } from '../../CodegenSchema'; import type {AliasResolver} from './Utils'; const {createAliasResolver, getModules} = require('./Utils'); const {indent} = require('../Utils'); const {unwrapNullable} = require('../../parsers/flow/modules/utils'); type FilesOutput = Map; const ModuleClassDeclarationTemplate = ({ hasteModuleName, moduleProperties, }: $ReadOnly<{hasteModuleName: string, moduleProperties: string}>) => { return `class JSI_EXPORT ${hasteModuleName}CxxSpecJSI : public TurboModule { protected: ${hasteModuleName}CxxSpecJSI(std::shared_ptr jsInvoker); public: ${indent(moduleProperties, 2)} };`; }; const FileTemplate = ({ modules, }: $ReadOnly<{ modules: string, }>) => { return `/** * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). * * Do not edit this file as changes may cause incorrect behavior and will be lost * once the code is regenerated. * * ${'@'}generated by codegen project: GenerateModuleH.js */ #pragma once #include namespace facebook { namespace react { ${modules} } // namespace react } // namespace facebook `; }; function translatePrimitiveJSTypeToCpp( nullableTypeAnnotation: Nullable, createErrorMessage: (typeName: string) => string, resolveAlias: AliasResolver, ) { const [typeAnnotation] = unwrapNullable( nullableTypeAnnotation, ); let realTypeAnnotation = typeAnnotation; if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { realTypeAnnotation = resolveAlias(realTypeAnnotation.name); } switch (realTypeAnnotation.type) { case 'ReservedTypeAnnotation': switch (realTypeAnnotation.name) { case 'RootTag': return 'double'; default: (realTypeAnnotation.name: empty); throw new Error(createErrorMessage(realTypeAnnotation.name)); } case 'VoidTypeAnnotation': return 'void'; case 'StringTypeAnnotation': return 'jsi::String'; case 'NumberTypeAnnotation': return 'double'; case 'DoubleTypeAnnotation': return 'double'; case 'FloatTypeAnnotation': return 'double'; case 'Int32TypeAnnotation': return 'int'; case 'BooleanTypeAnnotation': return 'bool'; case 'GenericObjectTypeAnnotation': return 'jsi::Object'; case 'ObjectTypeAnnotation': return 'jsi::Object'; case 'ArrayTypeAnnotation': return 'jsi::Array'; case 'FunctionTypeAnnotation': return 'jsi::Function'; case 'PromiseTypeAnnotation': return 'jsi::Value'; default: (realTypeAnnotation.type: empty); throw new Error(createErrorMessage(realTypeAnnotation.type)); } } const propertyTemplate = 'virtual ::_RETURN_VALUE_:: ::_PROPERTY_NAME_::(jsi::Runtime &rt::_ARGS_::) = 0;'; module.exports = { generate( libraryName: string, schema: SchemaType, packageName?: string, assumeNonnull: boolean = false, ): FilesOutput { const nativeModules = getModules(schema); const modules = Object.keys(nativeModules) .map(hasteModuleName => { const { aliases, spec: {properties}, } = nativeModules[hasteModuleName]; const resolveAlias = createAliasResolver(aliases); const traversedProperties = properties .map(prop => { const [propTypeAnnotation] = unwrapNullable( prop.typeAnnotation, ); const traversedArgs = propTypeAnnotation.params .map(param => { const translatedParam = translatePrimitiveJSTypeToCpp( param.typeAnnotation, typeName => `Unsupported type for param "${param.name}" in ${prop.name}. Found: ${typeName}`, resolveAlias, ); const isObject = translatedParam.startsWith('jsi::'); return ( (isObject ? 'const ' + translatedParam + ' &' : translatedParam + ' ') + param.name ); }) .join(', '); return propertyTemplate .replace('::_PROPERTY_NAME_::', prop.name) .replace( '::_RETURN_VALUE_::', translatePrimitiveJSTypeToCpp( propTypeAnnotation.returnTypeAnnotation, typeName => `Unsupported return type for ${prop.name}. Found: ${typeName}`, resolveAlias, ), ) .replace( '::_ARGS_::', traversedArgs === '' ? '' : ', ' + traversedArgs, ); }) .join('\n'); return ModuleClassDeclarationTemplate({ hasteModuleName, moduleProperties: traversedProperties, }); }) .join('\n'); const fileName = `${libraryName}JSI.h`; const replacedTemplate = FileTemplate({modules}); return new Map([[fileName, replacedTemplate]]); }, };