-
Notifications
You must be signed in to change notification settings - Fork 24.9k
Commit 588233c
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: D838109771 parent 4598eb2 commit 588233cCopy full SHA for 588233c
File tree
Expand file treeCollapse file tree
9 files changed
+2917
-6905
lines changedFilter options
- packages/react-native-codegen
- e2e/deep_imports/__tests__/modules
- __snapshots__
- src/generators
- modules
- __tests__
- __snapshots__
Expand file treeCollapse file tree
9 files changed
+2917
-6905
lines changedCollapse file: packages/react-native-codegen/e2e/deep_imports/__tests__/modules/GenerateModuleCpp-test.js
packages/react-native-codegen/e2e/deep_imports/__tests__/modules/GenerateModuleCpp-test.js
Copy file name to clipboardExpand all lines: packages/react-native-codegen/e2e/deep_imports/__tests__/modules/GenerateModuleCpp-test.js-51Lines changed: 0 additions & 51 deletions
This file was deleted.
Collapse file: packages/react-native-codegen/e2e/deep_imports/__tests__/modules/__snapshots__/GenerateModuleCpp-test.js.snap
packages/react-native-codegen/e2e/deep_imports/__tests__/modules/__snapshots__/GenerateModuleCpp-test.js.snap
Copy file name to clipboardExpand all lines: packages/react-native-codegen/e2e/deep_imports/__tests__/modules/__snapshots__/GenerateModuleCpp-test.js.snap-1,643Lines changed: 0 additions & 1643 deletions
This file was deleted.
0 commit comments