Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example of using Meta's c++ JSI codegen #10745

Draft
wants to merge 20 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 24 additions & 12 deletions packages/@react-native-windows/codegen/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,26 +208,38 @@ export function generate(
methodonly,
});

const generateJsiModuleH = require(path.resolve(rncodegenPath, 'lib/generators/modules/GenerateModuleH')).generate;
const generateJsiModuleCpp = require(path.resolve(rncodegenPath, 'lib/generators/modules/GenerateModuleCpp')).generate;
const generatorPropsH =
require('react-native-tscodegen/lib/rncodegen/src/generators/components/GeneratePropsH').generate;
require(path.resolve(rncodegenPath, 'lib/generators/components/GeneratePropsH')).generate;
const generatorPropsCPP =
require('react-native-tscodegen/lib/rncodegen/src/generators/components/GeneratePropsCPP').generate;
require(path.resolve(rncodegenPath, 'lib/generators/components/GeneratePropsCPP')).generate;
const generatorShadowNodeH =
require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateShadowNodeH').generate;
require(path.resolve(rncodegenPath, 'lib/generators/components/GenerateShadowNodeH')).generate;
const generatorShadowNodeCPP =
require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateShadowNodeCPP').generate;
require(path.resolve(rncodegenPath, 'lib/generators/components/GenerateShadowNodeCPP')).generate;
const generatorComponentDescriptorH =
require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateComponentDescriptorH').generate;
require(path.resolve(rncodegenPath, 'lib/generators/components/GenerateComponentDescriptorH')).generate;
const generatorEventEmitterH =
require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateEventEmitterH').generate;
require(path.resolve(rncodegenPath, 'lib/generators/components/GenerateEventEmitterH')).generate;
const generatorEventEmitterCPP =
require('react-native-tscodegen/lib/rncodegen/src/generators/components/GenerateEventEmitterCpp').generate;
require(path.resolve(rncodegenPath, 'lib/generators/components/GenerateEventEmitterCpp')).generate;

normalizeFileMap(
generateNM2(libraryName, schema, moduleSpecName),
outputDirectory,
generatedFiles,
);
const moduleGenerators = [
generateNM2,
generateJsiModuleH,
generateJsiModuleCpp,
];


moduleGenerators.forEach(generator => {
const generated: Map<string, string> = generator(
libraryName,
schema,
moduleSpecName,
);
normalizeFileMap(generated, outputDirectory, generatedFiles);
});

if (ts) {
normalizeFileMap(
Expand Down
101 changes: 101 additions & 0 deletions packages/sample-apps/codegen/NativeMyJsiModuleSpec.g.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@

/*
* This file is auto-generated from a NativeModule spec file in js.
*
* This is a C++ Spec class that should be used with MakeTurboModuleProvider to register native modules
* in a way that also verifies at compile time that the native module matches the interface required
* by the TurboModule JS spec.
*/
#pragma once
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pragma

This file does not look right yet. I guess it is still a TODO item.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whats wrong with it? -- This should be the NM2 spec for the same module. (We happen to be using the c++ JSI spec to implement it in this case rather than this one)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does it work? I do not see generated code with the custom attributes. The spec cannot be verified if there are no custom attributes.


#include "NativeModules.h"
#include <tuple>

namespace SampleLibraryCodegen {

REACT_STRUCT(MyJsiModuleSpec_Constants)
struct MyJsiModuleSpec_Constants {
REACT_FIELD(const1)
bool const1;
REACT_FIELD(const2)
double const2;
REACT_FIELD(const3)
std::string const3;
};

struct MyJsiModuleSpec : winrt::Microsoft::ReactNative::TurboModuleSpec {
static constexpr auto constants = std::tuple{
TypedConstant<MyJsiModuleSpec_Constants>{0},
};
static constexpr auto methods = std::tuple{
Method<void() noexcept>{0, L"voidFunc"},
SyncMethod<bool(bool) noexcept>{1, L"getBool"},
SyncMethod<double(double) noexcept>{2, L"getNumber"},
SyncMethod<std::string(std::string) noexcept>{3, L"getString"},
SyncMethod<::React::JSValueArray(::React::JSValueArray) noexcept>{4, L"getArray"},
SyncMethod<::React::JSValue(::React::JSValue) noexcept>{5, L"getObject"},
SyncMethod<::React::JSValue(double, std::string, ::React::JSValue) noexcept>{6, L"getValue"},
Method<void(Callback<std::string>) noexcept>{7, L"getValueWithCallback"},
Method<void(bool, Promise<::React::JSValue>) noexcept>{8, L"getValueWithPromise"},
};

template <class TModule>
static constexpr void ValidateModule() noexcept {
constexpr auto constantCheckResults = CheckConstants<TModule, MyJsiModuleSpec>();
constexpr auto methodCheckResults = CheckMethods<TModule, MyJsiModuleSpec>();

REACT_SHOW_CONSTANT_SPEC_ERRORS(
0,
"MyJsiModuleSpec_Constants",
" REACT_GET_CONSTANTS(GetConstants) MyJsiModuleSpec_Constants GetConstants() noexcept {/*implementation*/}\n"
" REACT_GET_CONSTANTS(GetConstants) static MyJsiModuleSpec_Constants GetConstants() noexcept {/*implementation*/}\n");

REACT_SHOW_METHOD_SPEC_ERRORS(
0,
"voidFunc",
" REACT_METHOD(voidFunc) void voidFunc() noexcept { /* implementation */ }\n"
" REACT_METHOD(voidFunc) static void voidFunc() noexcept { /* implementation */ }\n");
REACT_SHOW_METHOD_SPEC_ERRORS(
1,
"getBool",
" REACT_SYNC_METHOD(getBool) bool getBool(bool arg) noexcept { /* implementation */ }\n"
" REACT_SYNC_METHOD(getBool) static bool getBool(bool arg) noexcept { /* implementation */ }\n");
REACT_SHOW_METHOD_SPEC_ERRORS(
2,
"getNumber",
" REACT_SYNC_METHOD(getNumber) double getNumber(double arg) noexcept { /* implementation */ }\n"
" REACT_SYNC_METHOD(getNumber) static double getNumber(double arg) noexcept { /* implementation */ }\n");
REACT_SHOW_METHOD_SPEC_ERRORS(
3,
"getString",
" REACT_SYNC_METHOD(getString) std::string getString(std::string arg) noexcept { /* implementation */ }\n"
" REACT_SYNC_METHOD(getString) static std::string getString(std::string arg) noexcept { /* implementation */ }\n");
REACT_SHOW_METHOD_SPEC_ERRORS(
4,
"getArray",
" REACT_SYNC_METHOD(getArray) ::React::JSValueArray getArray(::React::JSValueArray && arg) noexcept { /* implementation */ }\n"
" REACT_SYNC_METHOD(getArray) static ::React::JSValueArray getArray(::React::JSValueArray && arg) noexcept { /* implementation */ }\n");
REACT_SHOW_METHOD_SPEC_ERRORS(
5,
"getObject",
" REACT_SYNC_METHOD(getObject) ::React::JSValue getObject(::React::JSValue && arg) noexcept { /* implementation */ }\n"
" REACT_SYNC_METHOD(getObject) static ::React::JSValue getObject(::React::JSValue && arg) noexcept { /* implementation */ }\n");
REACT_SHOW_METHOD_SPEC_ERRORS(
6,
"getValue",
" REACT_SYNC_METHOD(getValue) ::React::JSValue getValue(double x, std::string y, ::React::JSValue && z) noexcept { /* implementation */ }\n"
" REACT_SYNC_METHOD(getValue) static ::React::JSValue getValue(double x, std::string y, ::React::JSValue && z) noexcept { /* implementation */ }\n");
REACT_SHOW_METHOD_SPEC_ERRORS(
7,
"getValueWithCallback",
" REACT_METHOD(getValueWithCallback) void getValueWithCallback(std::function<void(std::string)> const & callback) noexcept { /* implementation */ }\n"
" REACT_METHOD(getValueWithCallback) static void getValueWithCallback(std::function<void(std::string)> const & callback) noexcept { /* implementation */ }\n");
REACT_SHOW_METHOD_SPEC_ERRORS(
8,
"getValueWithPromise",
" REACT_METHOD(getValueWithPromise) void getValueWithPromise(bool error, ::React::ReactPromise<::React::JSValue> &&result) noexcept { /* implementation */ }\n"
" REACT_METHOD(getValueWithPromise) static void getValueWithPromise(bool error, ::React::ReactPromise<::React::JSValue> &&result) noexcept { /* implementation */ }\n");
}
};

} // namespace SampleLibraryCodegen
110 changes: 110 additions & 0 deletions packages/sample-apps/codegen/SampleAppJSI-generated.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/**
* 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
*/

#include "SampleAppJSI.h"

namespace facebook {
namespace react {

static jsi::Value __hostFunction_NativeMyJsiModuleCxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeMyJsiModuleCxxSpecJSI *>(&turboModule)->getConstants(rt);
}
static jsi::Value __hostFunction_NativeMyJsiModuleCxxSpecJSI_voidFunc(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeMyJsiModuleCxxSpecJSI *>(&turboModule)->voidFunc(rt);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeMyJsiModuleCxxSpecJSI_getBool(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeMyJsiModuleCxxSpecJSI *>(&turboModule)->getBool(rt, args[0].asBool());
}
static jsi::Value __hostFunction_NativeMyJsiModuleCxxSpecJSI_getNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeMyJsiModuleCxxSpecJSI *>(&turboModule)->getNumber(rt, args[0].asNumber());
}
static jsi::Value __hostFunction_NativeMyJsiModuleCxxSpecJSI_getString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeMyJsiModuleCxxSpecJSI *>(&turboModule)->getString(rt, args[0].asString(rt));
}
static jsi::Value __hostFunction_NativeMyJsiModuleCxxSpecJSI_getArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeMyJsiModuleCxxSpecJSI *>(&turboModule)->getArray(rt, args[0].asObject(rt).asArray(rt));
}
static jsi::Value __hostFunction_NativeMyJsiModuleCxxSpecJSI_getObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeMyJsiModuleCxxSpecJSI *>(&turboModule)->getObject(rt, args[0].asObject(rt));
}
static jsi::Value __hostFunction_NativeMyJsiModuleCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeMyJsiModuleCxxSpecJSI *>(&turboModule)->getValue(rt, args[0].asNumber(), args[1].asString(rt), args[2].asObject(rt));
}
static jsi::Value __hostFunction_NativeMyJsiModuleCxxSpecJSI_getValueWithCallback(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeMyJsiModuleCxxSpecJSI *>(&turboModule)->getValueWithCallback(rt, args[0].asObject(rt).asFunction(rt));
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeMyJsiModuleCxxSpecJSI_getValueWithPromise(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeMyJsiModuleCxxSpecJSI *>(&turboModule)->getValueWithPromise(rt, args[0].asBool());
}

NativeMyJsiModuleCxxSpecJSI::NativeMyJsiModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule("MyJsiModule", jsInvoker) {
methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeMyJsiModuleCxxSpecJSI_getConstants};
methodMap_["voidFunc"] = MethodMetadata {0, __hostFunction_NativeMyJsiModuleCxxSpecJSI_voidFunc};
methodMap_["getBool"] = MethodMetadata {1, __hostFunction_NativeMyJsiModuleCxxSpecJSI_getBool};
methodMap_["getNumber"] = MethodMetadata {1, __hostFunction_NativeMyJsiModuleCxxSpecJSI_getNumber};
methodMap_["getString"] = MethodMetadata {1, __hostFunction_NativeMyJsiModuleCxxSpecJSI_getString};
methodMap_["getArray"] = MethodMetadata {1, __hostFunction_NativeMyJsiModuleCxxSpecJSI_getArray};
methodMap_["getObject"] = MethodMetadata {1, __hostFunction_NativeMyJsiModuleCxxSpecJSI_getObject};
methodMap_["getValue"] = MethodMetadata {3, __hostFunction_NativeMyJsiModuleCxxSpecJSI_getValue};
methodMap_["getValueWithCallback"] = MethodMetadata {1, __hostFunction_NativeMyJsiModuleCxxSpecJSI_getValueWithCallback};
methodMap_["getValueWithPromise"] = MethodMetadata {1, __hostFunction_NativeMyJsiModuleCxxSpecJSI_getValueWithPromise};
}
static jsi::Value __hostFunction_NativeMyModuleCxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeMyModuleCxxSpecJSI *>(&turboModule)->getConstants(rt);
}
static jsi::Value __hostFunction_NativeMyModuleCxxSpecJSI_voidFunc(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeMyModuleCxxSpecJSI *>(&turboModule)->voidFunc(rt);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeMyModuleCxxSpecJSI_getBool(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeMyModuleCxxSpecJSI *>(&turboModule)->getBool(rt, args[0].asBool());
}
static jsi::Value __hostFunction_NativeMyModuleCxxSpecJSI_getNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeMyModuleCxxSpecJSI *>(&turboModule)->getNumber(rt, args[0].asNumber());
}
static jsi::Value __hostFunction_NativeMyModuleCxxSpecJSI_getString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeMyModuleCxxSpecJSI *>(&turboModule)->getString(rt, args[0].asString(rt));
}
static jsi::Value __hostFunction_NativeMyModuleCxxSpecJSI_getArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeMyModuleCxxSpecJSI *>(&turboModule)->getArray(rt, args[0].asObject(rt).asArray(rt));
}
static jsi::Value __hostFunction_NativeMyModuleCxxSpecJSI_getObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeMyModuleCxxSpecJSI *>(&turboModule)->getObject(rt, args[0].asObject(rt));
}
static jsi::Value __hostFunction_NativeMyModuleCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeMyModuleCxxSpecJSI *>(&turboModule)->getValue(rt, args[0].asNumber(), args[1].asString(rt), args[2].asObject(rt));
}
static jsi::Value __hostFunction_NativeMyModuleCxxSpecJSI_getValueWithCallback(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeMyModuleCxxSpecJSI *>(&turboModule)->getValueWithCallback(rt, args[0].asObject(rt).asFunction(rt));
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeMyModuleCxxSpecJSI_getValueWithPromise(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeMyModuleCxxSpecJSI *>(&turboModule)->getValueWithPromise(rt, args[0].asBool());
}

NativeMyModuleCxxSpecJSI::NativeMyModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule("MyModule", jsInvoker) {
methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeMyModuleCxxSpecJSI_getConstants};
methodMap_["voidFunc"] = MethodMetadata {0, __hostFunction_NativeMyModuleCxxSpecJSI_voidFunc};
methodMap_["getBool"] = MethodMetadata {1, __hostFunction_NativeMyModuleCxxSpecJSI_getBool};
methodMap_["getNumber"] = MethodMetadata {1, __hostFunction_NativeMyModuleCxxSpecJSI_getNumber};
methodMap_["getString"] = MethodMetadata {1, __hostFunction_NativeMyModuleCxxSpecJSI_getString};
methodMap_["getArray"] = MethodMetadata {1, __hostFunction_NativeMyModuleCxxSpecJSI_getArray};
methodMap_["getObject"] = MethodMetadata {1, __hostFunction_NativeMyModuleCxxSpecJSI_getObject};
methodMap_["getValue"] = MethodMetadata {3, __hostFunction_NativeMyModuleCxxSpecJSI_getValue};
methodMap_["getValueWithCallback"] = MethodMetadata {1, __hostFunction_NativeMyModuleCxxSpecJSI_getValueWithCallback};
methodMap_["getValueWithPromise"] = MethodMetadata {1, __hostFunction_NativeMyModuleCxxSpecJSI_getValueWithPromise};
}


} // namespace react
} // namespace facebook
Loading