UNPKG

react-native-codegen

Version:
284 lines (267 loc) 8.58 kB
/** * 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(r, l) { var t = null == r ? null : ('undefined' != typeof Symbol && r[Symbol.iterator]) || r['@@iterator']; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (((i = (t = t.call(r)).next), 0 === l)) { if (Object(t) !== t) return; f = !1; } else for ( ; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0 ); } catch (r) { (o = !0), (n = r); } finally { try { if (!f && null != t.return && ((u = t.return()), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } const _require = require('./Utils'), createAliasResolver = _require.createAliasResolver, getModules = _require.getModules; const _require2 = require('../Utils'), indent = _require2.indent; const _require3 = require('../../parsers/flow/modules/utils'), unwrapNullable = _require3.unwrapNullable; const ModuleClassDeclarationTemplate = ({ hasteModuleName, moduleProperties, }) => { return `class JSI_EXPORT ${hasteModuleName}CxxSpecJSI : public TurboModule { protected: ${hasteModuleName}CxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker); public: ${indent(moduleProperties.join('\n'), 2)} };`; }; const ModuleSpecClassDeclarationTemplate = ({ hasteModuleName, moduleName, moduleProperties, }) => { return `template <typename T> class JSI_EXPORT ${hasteModuleName}CxxSpec : public TurboModule { public: jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &propName) override { return delegate_.get(rt, propName); } protected: ${hasteModuleName}CxxSpec(std::shared_ptr<CallInvoker> jsInvoker) : TurboModule("${moduleName}", jsInvoker), delegate_(static_cast<T*>(this), jsInvoker) {} private: class Delegate : public ${hasteModuleName}CxxSpecJSI { public: Delegate(T *instance, std::shared_ptr<CallInvoker> jsInvoker) : ${hasteModuleName}CxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} ${indent(moduleProperties.join('\n'), 4)} private: T *instance_; }; Delegate delegate_; };`; }; const FileTemplate = ({modules}) => { 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 <ReactCommon/TurboModule.h> #include <react/bridging/Bridging.h> namespace facebook { namespace react { ${modules.join('\n\n')} } // namespace react } // namespace facebook `; }; function translatePrimitiveJSTypeToCpp( nullableTypeAnnotation, createErrorMessage, resolveAlias, ) { const _unwrapNullable = unwrapNullable(nullableTypeAnnotation), _unwrapNullable2 = _slicedToArray(_unwrapNullable, 2), typeAnnotation = _unwrapNullable2[0], nullable = _unwrapNullable2[1]; let realTypeAnnotation = typeAnnotation; if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { realTypeAnnotation = resolveAlias(realTypeAnnotation.name); } function wrap(type) { return nullable ? `std::optional<${type}>` : type; } switch (realTypeAnnotation.type) { case 'ReservedTypeAnnotation': switch (realTypeAnnotation.name) { case 'RootTag': return wrap('double'); default: realTypeAnnotation.name; throw new Error(createErrorMessage(realTypeAnnotation.name)); } case 'VoidTypeAnnotation': return 'void'; case 'StringTypeAnnotation': return wrap('jsi::String'); case 'NumberTypeAnnotation': return wrap('double'); case 'DoubleTypeAnnotation': return wrap('double'); case 'FloatTypeAnnotation': return wrap('double'); case 'Int32TypeAnnotation': return wrap('int'); case 'BooleanTypeAnnotation': return wrap('bool'); case 'GenericObjectTypeAnnotation': return wrap('jsi::Object'); case 'ObjectTypeAnnotation': return wrap('jsi::Object'); case 'ArrayTypeAnnotation': return wrap('jsi::Array'); case 'FunctionTypeAnnotation': return wrap('jsi::Function'); case 'PromiseTypeAnnotation': return wrap('jsi::Value'); case 'MixedTypeAnnotation': return wrap('jsi::Value'); default: realTypeAnnotation.type; throw new Error(createErrorMessage(realTypeAnnotation.type)); } } function translatePropertyToCpp(prop, resolveAlias, abstract = false) { const _unwrapNullable3 = unwrapNullable(prop.typeAnnotation), _unwrapNullable4 = _slicedToArray(_unwrapNullable3, 1), propTypeAnnotation = _unwrapNullable4[0]; const params = propTypeAnnotation.params.map( param => `std::move(${param.name})`, ); const paramTypes = propTypeAnnotation.params.map(param => { const translatedParam = translatePrimitiveJSTypeToCpp( param.typeAnnotation, typeName => `Unsupported type for param "${param.name}" in ${prop.name}. Found: ${typeName}`, resolveAlias, ); return `${translatedParam} ${param.name}`; }); const returnType = translatePrimitiveJSTypeToCpp( propTypeAnnotation.returnTypeAnnotation, typeName => `Unsupported return type for ${prop.name}. Found: ${typeName}`, resolveAlias, ); // The first param will always be the runtime reference. paramTypes.unshift('jsi::Runtime &rt'); const method = `${returnType} ${prop.name}(${paramTypes.join(', ')})`; if (abstract) { return `virtual ${method} = 0;`; } return `${method} override { static_assert( bridging::getParameterCount(&T::${prop.name}) == ${paramTypes.length}, "Expected ${prop.name}(...) to have ${paramTypes.length} parameters"); return bridging::callFromJs<${returnType}>( rt, &T::${prop.name}, jsInvoker_, ${['instance_', ...params].join(', ')}); }`; } module.exports = { generate(libraryName, schema, packageName, assumeNonnull = false) { const nativeModules = getModules(schema); const modules = Object.keys(nativeModules).flatMap(hasteModuleName => { const _nativeModules$hasteM = nativeModules[hasteModuleName], aliases = _nativeModules$hasteM.aliases, properties = _nativeModules$hasteM.spec.properties, _nativeModules$hasteM2 = _slicedToArray( _nativeModules$hasteM.moduleNames, 1, ), moduleName = _nativeModules$hasteM2[0]; const resolveAlias = createAliasResolver(aliases); return [ ModuleClassDeclarationTemplate({ hasteModuleName, moduleProperties: properties.map(prop => translatePropertyToCpp(prop, resolveAlias, true), ), }), ModuleSpecClassDeclarationTemplate({ hasteModuleName, moduleName, moduleProperties: properties.map(prop => translatePropertyToCpp(prop, resolveAlias), ), }), ]; }); const fileName = `${libraryName}JSI.h`; const replacedTemplate = FileTemplate({ modules, }); return new Map([[fileName, replacedTemplate]]); }, };