Skip to content

Commit 6577f47

Browse files
Simplify C++ TM base classes (#54059)
Summary: Changelog: [Internal] Right now for a simple spec as ``` import type {CodegenTypes, TurboModule} from 'react-native'; import {TurboModuleRegistry} from 'react-native'; export type ScreenshotManagerOptions = CodegenTypes.UnsafeObject; export interface Spec extends TurboModule { +getConstants: () => {}; takeScreenshot( id: string, options: ScreenshotManagerOptions, ): Promise<string>; } const NativeModule = TurboModuleRegistry.get<Spec>('ScreenshotManager'); export function takeScreenshot( id: string, options: ScreenshotManagerOptions, ): Promise<string> { if (NativeModule != null) { return NativeModule.takeScreenshot(id, options); } return Promise.reject(); } ``` we generate **TWO** `facebook::react::TurboModule` sub classes (`NativeScreenshotManagerCxxSpecJSI` and `NativeScreenshotManagerCxxSpec`) to construct ONE C++ TM. In particular header ``` #pragma once #include <ReactCommon/TurboModule.h> #include <react/bridging/Bridging.h> namespace facebook::react { class JSI_EXPORT NativeScreenshotManagerCxxSpecJSI : public TurboModule { protected: NativeScreenshotManagerCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker); public: virtual jsi::Object getConstants(jsi::Runtime& rt) = 0; virtual jsi::Value takeScreenshot(jsi::Runtime& rt, jsi::String id, jsi::Object options) = 0; }; template <typename T> class JSI_EXPORT NativeScreenshotManagerCxxSpec : public TurboModule { public: jsi::Value create(jsi::Runtime& rt, const jsi::PropNameID& propName) override { return delegate_.create(rt, propName); } std::vector<jsi::PropNameID> getPropertyNames( jsi::Runtime& runtime) override { return delegate_.getPropertyNames(runtime); } static constexpr std::string_view kModuleName = "ScreenshotManager"; protected: NativeScreenshotManagerCxxSpec(std::shared_ptr<CallInvoker> jsInvoker) : TurboModule( std::string{NativeScreenshotManagerCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast<T*>(this), jsInvoker) {} private: class Delegate : public NativeScreenshotManagerCxxSpecJSI { public: Delegate(T* instance, std::shared_ptr<CallInvoker> jsInvoker) : NativeScreenshotManagerCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} jsi::Object getConstants(jsi::Runtime& rt) override { static_assert( bridging::getParameterCount(&T::getConstants) == 1, "Expected getConstants(...) to have 1 parameters"); return bridging::callFromJs<jsi::Object>( rt, &T::getConstants, jsInvoker_, instance_); } jsi::Value takeScreenshot( jsi::Runtime& rt, jsi::String id, jsi::Object options) override { static_assert( bridging::getParameterCount(&T::takeScreenshot) == 3, "Expected takeScreenshot(...) to have 3 parameters"); return bridging::callFromJs<jsi::Value>( rt, &T::takeScreenshot, jsInvoker_, instance_, std::move(id), std::move(options)); } private: friend class NativeScreenshotManagerCxxSpec; T* instance_; }; Delegate delegate_; }; } // namespace facebook::react ``` and cpp ``` #include "AppSpecsJSI.h" namespace facebook::react { static jsi::Value __hostFunction_NativeScreenshotManagerCxxSpecJSI_getConstants( jsi::Runtime& rt, TurboModule& turboModule, const jsi::Value* args, size_t count) { return static_cast<NativeScreenshotManagerCxxSpecJSI*>(&turboModule) ->getConstants(rt); } static jsi::Value __hostFunction_NativeScreenshotManagerCxxSpecJSI_takeScreenshot( jsi::Runtime& rt, TurboModule& turboModule, const jsi::Value* args, size_t count) { return static_cast<NativeScreenshotManagerCxxSpecJSI*>(&turboModule) ->takeScreenshot( rt, count <= 0 ? throw jsi::JSError( rt, "Expected argument in position 0 to be passed") : args[0].asString(rt), count <= 1 ? throw jsi::JSError( rt, "Expected argument in position 1 to be passed") : args[1].asObject(rt)); } NativeScreenshotManagerCxxSpecJSI::NativeScreenshotManagerCxxSpecJSI( std::shared_ptr<CallInvoker> jsInvoker) : TurboModule("ScreenshotManager", jsInvoker) { methodMap_["getConstants"] = MethodMetadata{ 0, __hostFunction_NativeScreenshotManagerCxxSpecJSI_getConstants}; methodMap_["takeScreenshot"] = MethodMetadata{ 2, __hostFunction_NativeScreenshotManagerCxxSpecJSI_takeScreenshot}; } } // namespace facebook::react ``` The goal of this change is to simplify that and only have **ONE** `facebook::react::TurboModule` base class for a concrete Cxx TM as this header ``` /* * 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. */ #pragma once template <typename T> class JSI_EXPORT NativeScreenshotManagerCxxSpec : public TurboModule { public: static constexpr std::string_view kModuleName = "ScreenshotManager"; protected: NativeScreenshotManagerCxxSpec(std::shared_ptr<CallInvoker> jsInvoker) : TurboModule(std::string{NativeScreenshotManagerCxxSpec::kModuleName}, jsInvoker) { methodMap_["getConstants"] = MethodMetadata {.argCount = 0, .invoker = __getConstantsJSI}; methodMap_["takeScreenshot"] = MethodMetadata {.argCount = 2, .invoker = __takeScreenshotJSI}; } private: static jsi::Value __getConstantsJSI(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* /*args*/, size_t /*count*/) { static_assert( bridging::getParameterCount(&T::getConstants) == 1, "Expected getConstants(...) to have 1 parameters"); auto* self = static_cast<T*>(&turboModule); return bridging::callFromJs<jsi::Object>(rt, &T::getConstants, self->jsInvoker_, self); } static jsi::Value __takeScreenshotJSI(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_assert( bridging::getParameterCount(&T::takeScreenshot) == 3, "Expected takeScreenshot(...) to have 3 parameters"); auto* self = static_cast<T*>(&turboModule); return bridging::callFromJs<jsi::Value>(rt, &T::takeScreenshot, self->jsInvoker_, self, count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asString(rt), count <= 1 ? throw jsi::JSError(rt, "Expected argument in position 1 to be passed") : args[1].asObject(rt)); } }; ``` This reduces the generated code from 101 lines to 31 % - **REDUCTION of 2/3** ## Use of a private member ` std::shared_ptr<CallInvoker> jsInvoker_;` on GitHub https://github.com/search?q=std%3A%3Ashared_ptr%3CCallInvoker%3E+jsInvoker_%3B+NOT+path%3AReactCommon+NOT+path%3ATurboModule.h+NOT+path%3ACallbackWrapper.h+NOT+path%3A.svn_base+language%3AC%2B%2B+NOT+path%3A.cpp&type=code -> None in a code-gen TurboModule Differential Revision: D83810977
1 parent 419ef71 commit 6577f47

File tree

9 files changed

+2917
-6905
lines changed

9 files changed

+2917
-6905
lines changed

packages/react-native-codegen/e2e/deep_imports/__tests__/modules/GenerateModuleCpp-test.js

Lines changed: 0 additions & 51 deletions
This file was deleted.

packages/react-native-codegen/e2e/deep_imports/__tests__/modules/__snapshots__/GenerateModuleCpp-test.js.snap

Lines changed: 0 additions & 1643 deletions
This file was deleted.

0 commit comments

Comments
 (0)