/** * 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. * * * @format */ 'use strict'; function _slicedToArray(arr, i) { return ( _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest() ); } function _nonIterableRest() { throw new TypeError( 'Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.', ); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === 'string') return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === 'Object' && o.constructor) n = o.constructor.name; if (n === 'Map' || n === 'Set') return Array.from(o); if (n === 'Arguments' || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : ('undefined' != typeof Symbol && arr[Symbol.iterator]) || arr['@@iterator']; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (((_x = (_i = _i.call(arr)).next), 0 === i)) { if (Object(_i) !== _i) return; _n = !1; } else for ( ; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0 ); } catch (err) { (_d = !0), (_e = err); } finally { try { if (!_n && null != _i.return && ((_r = _i.return()), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } const _require = require('./Utils'), createAliasResolver = _require.createAliasResolver, getModules = _require.getModules; const _require2 = require('../../parsers/parsers-commons'), unwrapNullable = _require2.unwrapNullable; const HostFunctionTemplate = ({ hasteModuleName, propertyName, jniSignature, jsReturnType, }) => { return `static facebook::jsi::Value __hostFunction_${hasteModuleName}SpecJSI_${propertyName}(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { static jmethodID cachedMethodId = nullptr; return static_cast(turboModule).invokeJavaMethod(rt, ${jsReturnType}, "${propertyName}", "${jniSignature}", args, count, cachedMethodId); }`; }; const ModuleClassConstructorTemplate = ({hasteModuleName, methods}) => { return ` ${hasteModuleName}SpecJSI::${hasteModuleName}SpecJSI(const JavaTurboModule::InitParams ¶ms) : JavaTurboModule(params) { ${methods .map(({propertyName, argCount}) => { return ` methodMap_["${propertyName}"] = MethodMetadata {${argCount}, __hostFunction_${hasteModuleName}SpecJSI_${propertyName}};`; }) .join('\n')} }`.trim(); }; const ModuleLookupTemplate = ({moduleName, hasteModuleName}) => { return ` if (moduleName == "${moduleName}") { return std::make_shared<${hasteModuleName}SpecJSI>(params); }`; }; const FileTemplate = ({libraryName, include, modules, moduleLookups}) => { 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: GenerateModuleJniCpp.js */ #include ${include} namespace facebook { namespace react { ${modules} 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, resolveAlias) { const _unwrapNullable = unwrapNullable(nullableTypeAnnotation), _unwrapNullable2 = _slicedToArray(_unwrapNullable, 1), typeAnnotation = _unwrapNullable2[0]; let realTypeAnnotation = typeAnnotation; if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { realTypeAnnotation = resolveAlias(realTypeAnnotation.name); } switch (realTypeAnnotation.type) { case 'ReservedTypeAnnotation': switch (realTypeAnnotation.name) { case 'RootTag': return 'NumberKind'; default: realTypeAnnotation.name; throw new Error( `Invalid ReservedFunctionValueTypeName name, got ${realTypeAnnotation.name}`, ); } case 'VoidTypeAnnotation': return 'VoidKind'; case 'StringTypeAnnotation': return 'StringKind'; case 'BooleanTypeAnnotation': return 'BooleanKind'; case 'EnumDeclaration': switch (typeAnnotation.memberType) { case 'NumberTypeAnnotation': return 'NumberKind'; case 'StringTypeAnnotation': return 'StringKind'; default: throw new Error( `Unknown enum prop type for returning value, found: ${realTypeAnnotation.type}"`, ); } case 'UnionTypeAnnotation': switch (typeAnnotation.memberType) { case 'NumberTypeAnnotation': return 'NumberKind'; case 'ObjectTypeAnnotation': return 'ObjectKind'; case 'StringTypeAnnotation': return 'StringKind'; default: throw new Error( `Unsupported union member returning value, found: ${realTypeAnnotation.memberType}"`, ); } case 'NumberTypeAnnotation': return 'NumberKind'; case 'DoubleTypeAnnotation': return 'NumberKind'; case 'FloatTypeAnnotation': return 'NumberKind'; case 'Int32TypeAnnotation': return 'NumberKind'; case 'PromiseTypeAnnotation': return 'PromiseKind'; case 'GenericObjectTypeAnnotation': return 'ObjectKind'; case 'ObjectTypeAnnotation': return 'ObjectKind'; case 'ArrayTypeAnnotation': return 'ArrayKind'; default: realTypeAnnotation.type; throw new Error( `Unknown prop type for returning value, found: ${realTypeAnnotation.type}"`, ); } } function translateParamTypeToJniType(param, resolveAlias) { const optional = param.optional, nullableTypeAnnotation = param.typeAnnotation; const _unwrapNullable3 = unwrapNullable(nullableTypeAnnotation), _unwrapNullable4 = _slicedToArray(_unwrapNullable3, 2), typeAnnotation = _unwrapNullable4[0], nullable = _unwrapNullable4[1]; const isRequired = !optional && !nullable; let realTypeAnnotation = typeAnnotation; if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { realTypeAnnotation = resolveAlias(realTypeAnnotation.name); } switch (realTypeAnnotation.type) { case 'ReservedTypeAnnotation': switch (realTypeAnnotation.name) { case 'RootTag': return !isRequired ? 'Ljava/lang/Double;' : 'D'; default: realTypeAnnotation.name; throw new Error( `Invalid ReservedFunctionValueTypeName name, got ${realTypeAnnotation.name}`, ); } case 'StringTypeAnnotation': return 'Ljava/lang/String;'; case 'BooleanTypeAnnotation': return !isRequired ? 'Ljava/lang/Boolean;' : 'Z'; case 'EnumDeclaration': switch (typeAnnotation.memberType) { case 'NumberTypeAnnotation': return !isRequired ? 'Ljava/lang/Double;' : 'D'; case 'StringTypeAnnotation': return 'Ljava/lang/String;'; default: throw new Error( `Unknown enum prop type for method arg, found: ${realTypeAnnotation.type}"`, ); } case 'UnionTypeAnnotation': switch (typeAnnotation.memberType) { case 'NumberTypeAnnotation': return !isRequired ? 'Ljava/lang/Double;' : 'D'; case 'ObjectTypeAnnotation': return 'Lcom/facebook/react/bridge/ReadableMap;'; case 'StringTypeAnnotation': return 'Ljava/lang/String;'; default: throw new Error( `Unsupported union prop value, found: ${realTypeAnnotation.memberType}"`, ); } case 'NumberTypeAnnotation': return !isRequired ? 'Ljava/lang/Double;' : 'D'; case 'DoubleTypeAnnotation': return !isRequired ? 'Ljava/lang/Double;' : 'D'; case 'FloatTypeAnnotation': return !isRequired ? 'Ljava/lang/Double;' : 'D'; case 'Int32TypeAnnotation': return !isRequired ? 'Ljava/lang/Double;' : 'D'; case 'GenericObjectTypeAnnotation': return 'Lcom/facebook/react/bridge/ReadableMap;'; case 'ObjectTypeAnnotation': return 'Lcom/facebook/react/bridge/ReadableMap;'; case 'ArrayTypeAnnotation': return 'Lcom/facebook/react/bridge/ReadableArray;'; case 'FunctionTypeAnnotation': return 'Lcom/facebook/react/bridge/Callback;'; default: realTypeAnnotation.type; throw new Error( `Unknown prop type for method arg, found: ${realTypeAnnotation.type}"`, ); } } function translateReturnTypeToJniType(nullableTypeAnnotation, resolveAlias) { const _unwrapNullable5 = unwrapNullable(nullableTypeAnnotation), _unwrapNullable6 = _slicedToArray(_unwrapNullable5, 2), typeAnnotation = _unwrapNullable6[0], nullable = _unwrapNullable6[1]; let realTypeAnnotation = typeAnnotation; if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { realTypeAnnotation = resolveAlias(realTypeAnnotation.name); } switch (realTypeAnnotation.type) { case 'ReservedTypeAnnotation': switch (realTypeAnnotation.name) { case 'RootTag': return nullable ? 'Ljava/lang/Double;' : 'D'; default: realTypeAnnotation.name; throw new Error( `Invalid ReservedFunctionValueTypeName name, got ${realTypeAnnotation.name}`, ); } case 'VoidTypeAnnotation': return 'V'; case 'StringTypeAnnotation': return 'Ljava/lang/String;'; case 'BooleanTypeAnnotation': return nullable ? 'Ljava/lang/Boolean;' : 'Z'; case 'EnumDeclaration': switch (typeAnnotation.memberType) { case 'NumberTypeAnnotation': return nullable ? 'Ljava/lang/Double;' : 'D'; case 'StringTypeAnnotation': return 'Ljava/lang/String;'; default: throw new Error( `Unknown enum prop type for method return type, found: ${realTypeAnnotation.type}"`, ); } case 'UnionTypeAnnotation': switch (typeAnnotation.memberType) { case 'NumberTypeAnnotation': return nullable ? 'Ljava/lang/Double;' : 'D'; case 'ObjectTypeAnnotation': return 'Lcom/facebook/react/bridge/WritableMap;'; case 'StringTypeAnnotation': return 'Ljava/lang/String;'; default: throw new Error( `Unsupported union member type, found: ${realTypeAnnotation.memberType}"`, ); } case 'NumberTypeAnnotation': return nullable ? 'Ljava/lang/Double;' : 'D'; case 'DoubleTypeAnnotation': return nullable ? 'Ljava/lang/Double;' : 'D'; case 'FloatTypeAnnotation': return nullable ? 'Ljava/lang/Double;' : 'D'; case 'Int32TypeAnnotation': return nullable ? 'Ljava/lang/Double;' : 'D'; case 'PromiseTypeAnnotation': return 'Lcom/facebook/react/bridge/Promise;'; case 'GenericObjectTypeAnnotation': return 'Lcom/facebook/react/bridge/WritableMap;'; case 'ObjectTypeAnnotation': return 'Lcom/facebook/react/bridge/WritableMap;'; case 'ArrayTypeAnnotation': return 'Lcom/facebook/react/bridge/WritableArray;'; default: realTypeAnnotation.type; throw new Error( `Unknown prop type for method return type, found: ${realTypeAnnotation.type}"`, ); } } function translateMethodTypeToJniSignature(property, resolveAlias) { const name = property.name, typeAnnotation = property.typeAnnotation; let _unwrapNullable7 = unwrapNullable(typeAnnotation), _unwrapNullable8 = _slicedToArray(_unwrapNullable7, 1), _unwrapNullable8$ = _unwrapNullable8[0], returnTypeAnnotation = _unwrapNullable8$.returnTypeAnnotation, params = _unwrapNullable8$.params; params = [...params]; let processedReturnTypeAnnotation = returnTypeAnnotation; const isPromiseReturn = returnTypeAnnotation.type === 'PromiseTypeAnnotation'; if (isPromiseReturn) { processedReturnTypeAnnotation = { type: 'VoidTypeAnnotation', }; } const argsSignatureParts = params.map(t => { return translateParamTypeToJniType(t, resolveAlias); }); if (isPromiseReturn) { // Additional promise arg for this case. argsSignatureParts.push( translateReturnTypeToJniType(returnTypeAnnotation, resolveAlias), ); } const argsSignature = argsSignatureParts.join(''); const returnSignature = name === 'getConstants' ? 'Ljava/util/Map;' : translateReturnTypeToJniType( processedReturnTypeAnnotation, resolveAlias, ); return `(${argsSignature})${returnSignature}`; } function translateMethodForImplementation( hasteModuleName, property, resolveAlias, ) { const _unwrapNullable9 = unwrapNullable(property.typeAnnotation), _unwrapNullable10 = _slicedToArray(_unwrapNullable9, 1), propertyTypeAnnotation = _unwrapNullable10[0]; const returnTypeAnnotation = propertyTypeAnnotation.returnTypeAnnotation; if ( property.name === 'getConstants' && returnTypeAnnotation.type === 'ObjectTypeAnnotation' && returnTypeAnnotation.properties.length === 0 ) { return ''; } return HostFunctionTemplate({ hasteModuleName, propertyName: property.name, jniSignature: translateMethodTypeToJniSignature(property, resolveAlias), jsReturnType: translateReturnTypeToKind(returnTypeAnnotation, resolveAlias), }); } module.exports = { generate(libraryName, schema, packageName, assumeNonnull = false) { const nativeModules = getModules(schema); const modules = Object.keys(nativeModules) .filter(hasteModuleName => { const module = nativeModules[hasteModuleName]; return !( module.excludedPlatforms != null && module.excludedPlatforms.includes('android') ); }) .sort() .map(hasteModuleName => { const _nativeModules$hasteM = nativeModules[hasteModuleName], aliasMap = _nativeModules$hasteM.aliasMap, properties = _nativeModules$hasteM.spec.properties; const resolveAlias = createAliasResolver(aliasMap); const translatedMethods = properties .map(property => translateMethodForImplementation( hasteModuleName, property, resolveAlias, ), ) .join('\n\n'); return ( translatedMethods + '\n\n' + ModuleClassConstructorTemplate({ hasteModuleName, methods: properties .map(({name: propertyName, typeAnnotation}) => { const _unwrapNullable11 = unwrapNullable(typeAnnotation), _unwrapNullable12 = _slicedToArray(_unwrapNullable11, 1), _unwrapNullable12$ = _unwrapNullable12[0], returnTypeAnnotation = _unwrapNullable12$.returnTypeAnnotation, params = _unwrapNullable12$.params; if ( propertyName === 'getConstants' && returnTypeAnnotation.type === 'ObjectTypeAnnotation' && returnTypeAnnotation.properties && returnTypeAnnotation.properties.length === 0 ) { return null; } return { propertyName, argCount: params.length, }; }) .filter(Boolean), }) ); }) .join('\n'); const moduleLookups = Object.keys(nativeModules) .filter(hasteModuleName => { const module = nativeModules[hasteModuleName]; return !( module.excludedPlatforms != null && module.excludedPlatforms.includes('android') ); }) .sort((a, b) => { const nameA = nativeModules[a].moduleName; const nameB = nativeModules[b].moduleName; if (nameA < nameB) { return -1; } else if (nameA > nameB) { return 1; } return 0; }) .map(hasteModuleName => ({ moduleName: nativeModules[hasteModuleName].moduleName, hasteModuleName, })); const fileName = `${libraryName}-generated.cpp`; const replacedTemplate = FileTemplate({ modules: modules, libraryName: libraryName.replace(/-/g, '_'), moduleLookups, include: `"${libraryName}.h"`, }); return new Map([[`jni/${fileName}`, replacedTemplate]]); }, };