diff --git a/packages/react-native-codegen-typescript-test/src/__tests__/simple-scenario-frontend-test.ts b/packages/react-native-codegen-typescript-test/src/__tests__/simple-scenario-frontend-test.ts index fc76245db8b..13f9ce4fa75 100644 --- a/packages/react-native-codegen-typescript-test/src/__tests__/simple-scenario-frontend-test.ts +++ b/packages/react-native-codegen-typescript-test/src/__tests__/simple-scenario-frontend-test.ts @@ -29,6 +29,7 @@ export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); excludedPlatforms: undefined, moduleName: 'SampleTurboModule', spec: { + eventEmitters: [], properties: [], }, type: 'NativeModule', diff --git a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap index 6ddc5f1e2eb..87023c8259b 100644 --- a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap +++ b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap @@ -43,11 +43,14 @@ protected: : TurboModule(std::string{NativeArrayTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeArrayTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeArrayTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeArrayTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Array getArray(jsi::Runtime &rt, jsi::Array a) override { static_assert( @@ -75,6 +78,7 @@ private: } private: + friend class NativeArrayTurboModuleCxxSpec; T *instance_; }; @@ -106,11 +110,14 @@ protected: : TurboModule(std::string{NativeBooleanTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeBooleanTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeBooleanTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeBooleanTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } bool getBoolean(jsi::Runtime &rt, bool arg) override { static_assert( @@ -130,6 +137,7 @@ private: } private: + friend class NativeBooleanTurboModuleCxxSpec; T *instance_; }; @@ -161,11 +169,14 @@ protected: : TurboModule(std::string{NativeCallbackTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeCallbackTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeCallbackTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeCallbackTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } void getValueWithCallback(jsi::Runtime &rt, jsi::Function callback) override { static_assert( @@ -185,6 +196,7 @@ private: } private: + friend class NativeCallbackTurboModuleCxxSpec; T *instance_; }; @@ -456,11 +468,14 @@ protected: : TurboModule(std::string{NativeEnumTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeEnumTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeEnumTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeEnumTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::String getStatusRegular(jsi::Runtime &rt, jsi::Object statusProp) override { static_assert( @@ -512,6 +527,7 @@ private: } private: + friend class NativeEnumTurboModuleCxxSpec; T *instance_; }; @@ -547,11 +563,14 @@ protected: : TurboModule(std::string{NativeNullableTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeNullableTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeNullableTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeNullableTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } std::optional getBool(jsi::Runtime &rt, std::optional a) override { static_assert( @@ -603,6 +622,7 @@ private: } private: + friend class NativeNullableTurboModuleCxxSpec; T *instance_; }; @@ -634,11 +654,14 @@ protected: : TurboModule(std::string{NativeNumberTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeNumberTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeNumberTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeNumberTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } double getNumber(jsi::Runtime &rt, double arg) override { static_assert( @@ -658,6 +681,7 @@ private: } private: + friend class NativeNumberTurboModuleCxxSpec; T *instance_; }; @@ -692,11 +716,14 @@ protected: : TurboModule(std::string{NativeObjectTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeObjectTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeObjectTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeObjectTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getGenericObject(jsi::Runtime &rt, jsi::Object arg) override { static_assert( @@ -740,6 +767,7 @@ private: } private: + friend class NativeObjectTurboModuleCxxSpec; T *instance_; }; @@ -770,11 +798,14 @@ protected: : TurboModule(std::string{NativeOptionalObjectTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeOptionalObjectTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeOptionalObjectTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeOptionalObjectTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getConstants(jsi::Runtime &rt) override { static_assert( @@ -786,6 +817,7 @@ private: } private: + friend class NativeOptionalObjectTurboModuleCxxSpec; T *instance_; }; @@ -868,11 +900,14 @@ protected: : TurboModule(std::string{NativePartialAnnotationTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativePartialAnnotationTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativePartialAnnotationTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativePartialAnnotationTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getSomeObj(jsi::Runtime &rt) override { static_assert( @@ -908,6 +943,7 @@ private: } private: + friend class NativePartialAnnotationTurboModuleCxxSpec; T *instance_; }; @@ -939,11 +975,14 @@ protected: : TurboModule(std::string{NativePromiseTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativePromiseTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativePromiseTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativePromiseTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Value getValueWithPromise(jsi::Runtime &rt, bool error) override { static_assert( @@ -963,6 +1002,7 @@ private: } private: + friend class NativePromiseTurboModuleCxxSpec; T *instance_; }; @@ -1045,11 +1085,14 @@ protected: : TurboModule(std::string{NativeSampleTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeSampleTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getConstants(jsi::Runtime &rt) override { static_assert( @@ -1157,6 +1200,7 @@ private: } private: + friend class NativeSampleTurboModuleCxxSpec; T *instance_; }; @@ -1239,11 +1283,14 @@ protected: : TurboModule(std::string{NativeSampleTurboModuleArraysCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeSampleTurboModuleArraysCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeSampleTurboModuleArraysCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeSampleTurboModuleArraysCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getConstants(jsi::Runtime &rt) override { static_assert( @@ -1351,6 +1398,7 @@ private: } private: + friend class NativeSampleTurboModuleArraysCxxSpec; T *instance_; }; @@ -1433,11 +1481,14 @@ protected: : TurboModule(std::string{NativeSampleTurboModuleNullableCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeSampleTurboModuleNullableCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeSampleTurboModuleNullableCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeSampleTurboModuleNullableCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getConstants(jsi::Runtime &rt) override { static_assert( @@ -1545,6 +1596,7 @@ private: } private: + friend class NativeSampleTurboModuleNullableCxxSpec; T *instance_; }; @@ -1629,11 +1681,14 @@ protected: : TurboModule(std::string{NativeSampleTurboModuleNullableAndOptionalCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeSampleTurboModuleNullableAndOptionalCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeSampleTurboModuleNullableAndOptionalCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeSampleTurboModuleNullableAndOptionalCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getConstants(jsi::Runtime &rt) override { static_assert( @@ -1741,6 +1796,7 @@ private: } private: + friend class NativeSampleTurboModuleNullableAndOptionalCxxSpec; T *instance_; }; @@ -1825,11 +1881,14 @@ protected: : TurboModule(std::string{NativeSampleTurboModuleOptionalCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeSampleTurboModuleOptionalCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeSampleTurboModuleOptionalCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeSampleTurboModuleOptionalCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getConstants(jsi::Runtime &rt) override { static_assert( @@ -1937,6 +1996,7 @@ private: } private: + friend class NativeSampleTurboModuleOptionalCxxSpec; T *instance_; }; @@ -1968,11 +2028,14 @@ protected: : TurboModule(std::string{NativeStringTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeStringTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeStringTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeStringTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::String getString(jsi::Runtime &rt, jsi::String arg) override { static_assert( @@ -1992,6 +2055,7 @@ private: } private: + friend class NativeStringTurboModuleCxxSpec; T *instance_; }; @@ -2045,11 +2109,14 @@ protected: : TurboModule(std::string{NativeArrayTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeArrayTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeArrayTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeArrayTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Array getArray(jsi::Runtime &rt, jsi::Array a) override { static_assert( @@ -2077,6 +2144,7 @@ private: } private: + friend class NativeArrayTurboModuleCxxSpec; T *instance_; }; @@ -2108,11 +2176,14 @@ protected: : TurboModule(std::string{NativeBooleanTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeBooleanTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeBooleanTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeBooleanTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } bool getBoolean(jsi::Runtime &rt, bool arg) override { static_assert( @@ -2132,6 +2203,7 @@ private: } private: + friend class NativeBooleanTurboModuleCxxSpec; T *instance_; }; @@ -2163,11 +2235,14 @@ protected: : TurboModule(std::string{NativeCallbackTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeCallbackTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeCallbackTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeCallbackTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } void getValueWithCallback(jsi::Runtime &rt, jsi::Function callback) override { static_assert( @@ -2187,6 +2262,7 @@ private: } private: + friend class NativeCallbackTurboModuleCxxSpec; T *instance_; }; @@ -2458,11 +2534,14 @@ protected: : TurboModule(std::string{NativeEnumTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeEnumTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeEnumTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeEnumTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::String getStatusRegular(jsi::Runtime &rt, jsi::Object statusProp) override { static_assert( @@ -2514,6 +2593,7 @@ private: } private: + friend class NativeEnumTurboModuleCxxSpec; T *instance_; }; @@ -2549,11 +2629,14 @@ protected: : TurboModule(std::string{NativeNullableTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeNullableTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeNullableTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeNullableTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } std::optional getBool(jsi::Runtime &rt, std::optional a) override { static_assert( @@ -2605,6 +2688,7 @@ private: } private: + friend class NativeNullableTurboModuleCxxSpec; T *instance_; }; @@ -2636,11 +2720,14 @@ protected: : TurboModule(std::string{NativeNumberTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeNumberTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeNumberTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeNumberTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } double getNumber(jsi::Runtime &rt, double arg) override { static_assert( @@ -2660,6 +2747,7 @@ private: } private: + friend class NativeNumberTurboModuleCxxSpec; T *instance_; }; @@ -2694,11 +2782,14 @@ protected: : TurboModule(std::string{NativeObjectTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeObjectTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeObjectTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeObjectTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getGenericObject(jsi::Runtime &rt, jsi::Object arg) override { static_assert( @@ -2742,6 +2833,7 @@ private: } private: + friend class NativeObjectTurboModuleCxxSpec; T *instance_; }; @@ -2772,11 +2864,14 @@ protected: : TurboModule(std::string{NativeOptionalObjectTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeOptionalObjectTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeOptionalObjectTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeOptionalObjectTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getConstants(jsi::Runtime &rt) override { static_assert( @@ -2788,6 +2883,7 @@ private: } private: + friend class NativeOptionalObjectTurboModuleCxxSpec; T *instance_; }; @@ -2870,11 +2966,14 @@ protected: : TurboModule(std::string{NativePartialAnnotationTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativePartialAnnotationTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativePartialAnnotationTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativePartialAnnotationTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getSomeObj(jsi::Runtime &rt) override { static_assert( @@ -2910,6 +3009,7 @@ private: } private: + friend class NativePartialAnnotationTurboModuleCxxSpec; T *instance_; }; @@ -2941,11 +3041,14 @@ protected: : TurboModule(std::string{NativePromiseTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativePromiseTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativePromiseTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativePromiseTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Value getValueWithPromise(jsi::Runtime &rt, bool error) override { static_assert( @@ -2965,6 +3068,7 @@ private: } private: + friend class NativePromiseTurboModuleCxxSpec; T *instance_; }; @@ -3047,11 +3151,14 @@ protected: : TurboModule(std::string{NativeSampleTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeSampleTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getConstants(jsi::Runtime &rt) override { static_assert( @@ -3159,6 +3266,7 @@ private: } private: + friend class NativeSampleTurboModuleCxxSpec; T *instance_; }; @@ -3241,11 +3349,14 @@ protected: : TurboModule(std::string{NativeSampleTurboModuleArraysCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeSampleTurboModuleArraysCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeSampleTurboModuleArraysCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeSampleTurboModuleArraysCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getConstants(jsi::Runtime &rt) override { static_assert( @@ -3353,6 +3464,7 @@ private: } private: + friend class NativeSampleTurboModuleArraysCxxSpec; T *instance_; }; @@ -3435,11 +3547,14 @@ protected: : TurboModule(std::string{NativeSampleTurboModuleNullableCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeSampleTurboModuleNullableCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeSampleTurboModuleNullableCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeSampleTurboModuleNullableCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getConstants(jsi::Runtime &rt) override { static_assert( @@ -3547,6 +3662,7 @@ private: } private: + friend class NativeSampleTurboModuleNullableCxxSpec; T *instance_; }; @@ -3631,11 +3747,14 @@ protected: : TurboModule(std::string{NativeSampleTurboModuleNullableAndOptionalCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeSampleTurboModuleNullableAndOptionalCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeSampleTurboModuleNullableAndOptionalCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeSampleTurboModuleNullableAndOptionalCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getConstants(jsi::Runtime &rt) override { static_assert( @@ -3743,6 +3862,7 @@ private: } private: + friend class NativeSampleTurboModuleNullableAndOptionalCxxSpec; T *instance_; }; @@ -3827,11 +3947,14 @@ protected: : TurboModule(std::string{NativeSampleTurboModuleOptionalCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeSampleTurboModuleOptionalCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeSampleTurboModuleOptionalCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeSampleTurboModuleOptionalCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getConstants(jsi::Runtime &rt) override { static_assert( @@ -3939,6 +4062,7 @@ private: } private: + friend class NativeSampleTurboModuleOptionalCxxSpec; T *instance_; }; @@ -3970,11 +4094,14 @@ protected: : TurboModule(std::string{NativeStringTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeStringTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeStringTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeStringTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::String getString(jsi::Runtime &rt, jsi::String arg) override { static_assert( @@ -3994,6 +4121,7 @@ private: } private: + friend class NativeStringTurboModuleCxxSpec; T *instance_; }; diff --git a/packages/react-native-codegen/src/CodegenSchema.d.ts b/packages/react-native-codegen/src/CodegenSchema.d.ts index 4f70a19c0ea..29982cf41d6 100644 --- a/packages/react-native-codegen/src/CodegenSchema.d.ts +++ b/packages/react-native-codegen/src/CodegenSchema.d.ts @@ -58,6 +58,11 @@ export interface MixedTypeAnnotation { readonly type: 'MixedTypeAnnotation'; } +export interface EventEmitterTypeAnnotation { + readonly type: 'EventEmitterTypeAnnotation'; + readonly typeAnnotation: NativeModuleBaseTypeAnnotation; +} + export interface FunctionTypeAnnotation { readonly type: 'FunctionTypeAnnotation'; readonly params: readonly NamedShape

[]; @@ -241,6 +246,7 @@ export interface NativeModuleSchema { } export interface NativeModuleSpec { + readonly eventEmitters: readonly NativeModuleEventEmitterShape[]; readonly properties: readonly NativeModulePropertyShape[]; } @@ -248,6 +254,8 @@ export type NativeModulePropertyShape = NamedShape< Nullable >; +export type NativeModuleEventEmitterShape = NamedShape; + export interface NativeModuleEnumMap { readonly [enumName: string]: NativeModuleEnumDeclarationWithMembers; } diff --git a/packages/react-native-codegen/src/CodegenSchema.js b/packages/react-native-codegen/src/CodegenSchema.js index 8553aa323c9..f0c745e8a9e 100644 --- a/packages/react-native-codegen/src/CodegenSchema.js +++ b/packages/react-native-codegen/src/CodegenSchema.js @@ -61,6 +61,11 @@ export type MixedTypeAnnotation = $ReadOnly<{ type: 'MixedTypeAnnotation', }>; +type EventEmitterTypeAnnotation = $ReadOnly<{ + type: 'EventEmitterTypeAnnotation', + typeAnnotation: NativeModuleBaseTypeAnnotation, +}>; + type FunctionTypeAnnotation<+P, +R> = $ReadOnly<{ type: 'FunctionTypeAnnotation', params: $ReadOnlyArray>, @@ -242,9 +247,13 @@ export type NativeModuleSchema = $ReadOnly<{ }>; type NativeModuleSpec = $ReadOnly<{ + eventEmitters: $ReadOnlyArray, properties: $ReadOnlyArray, }>; +export type NativeModuleEventEmitterShape = + NamedShape; + export type NativeModulePropertyShape = NamedShape< Nullable, >; diff --git a/packages/react-native-codegen/src/generators/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/generators/__test_fixtures__/fixtures.js index 8678249f5a8..74bd5becf72 100644 --- a/packages/react-native-codegen/src/generators/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/generators/__test_fixtures__/fixtures.js @@ -44,6 +44,7 @@ const SCHEMA_WITH_TM_AND_FC: SchemaType = { aliasMap: {}, enumMap: {}, spec: { + eventEmitters: [], properties: [ { name: 'add', diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js index ed6bab4d96b..66ccda7e4d6 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js @@ -18,6 +18,7 @@ import type { NativeModuleEnumMap, NativeModuleEnumMembers, NativeModuleEnumMemberType, + NativeModuleEventEmitterShape, NativeModuleFunctionTypeAnnotation, NativeModulePropertyShape, NativeModuleTypeAnnotation, @@ -28,7 +29,7 @@ import type {AliasResolver} from './Utils'; const {unwrapNullable} = require('../../parsers/parsers-commons'); const {wrapOptional} = require('../TypeUtils/Cxx'); -const {getEnumName, toSafeCppString} = require('../Utils'); +const {getEnumName, toPascalCase, toSafeCppString} = require('../Utils'); const {indent} = require('../Utils'); const { createAliasResolver, @@ -64,10 +65,12 @@ public: const ModuleSpecClassDeclarationTemplate = ({ hasteModuleName, moduleName, + moduleEventEmitters, moduleProperties, }: $ReadOnly<{ hasteModuleName: string, moduleName: string, + moduleEventEmitters: EventEmitterCpp[], moduleProperties: string[], }>) => { return `template @@ -83,16 +86,20 @@ protected: ${hasteModuleName}CxxSpec(std::shared_ptr jsInvoker) : TurboModule(std::string{${hasteModuleName}CxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} +${moduleEventEmitters.map(e => e.emitFunction).join('\n')} private: class Delegate : public ${hasteModuleName}CxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - ${hasteModuleName}CxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + ${hasteModuleName}CxxSpecJSI(std::move(jsInvoker)), instance_(instance) { +${moduleEventEmitters.map(e => e.registerEventEmitter).join('\n')} + } ${indent(moduleProperties.join('\n'), 4)} private: + friend class ${hasteModuleName}CxxSpec; T *instance_; }; @@ -460,7 +467,7 @@ function translatePropertyToCpp( resolveAlias: AliasResolver, enumMap: NativeModuleEnumMap, abstract: boolean = false, -) { +): string { const [propTypeAnnotation] = unwrapNullable(prop.typeAnnotation); @@ -511,6 +518,69 @@ function translatePropertyToCpp( }`; } +type EventEmitterCpp = { + isVoidTypeAnnotation: boolean, + templateName: string, + registerEventEmitter: string, + emitFunction: string, +}; + +function translateEventEmitterToCpp( + moduleName: string, + eventEmitter: NativeModuleEventEmitterShape, + resolveAlias: AliasResolver, + enumMap: NativeModuleEnumMap, +): EventEmitterCpp { + const isVoidTypeAnnotation = + eventEmitter.typeAnnotation.typeAnnotation.type === 'VoidTypeAnnotation'; + const templateName = `${toPascalCase(eventEmitter.name)}Type`; + const jsiType = translatePrimitiveJSTypeToCpp( + moduleName, + null, + eventEmitter.typeAnnotation.typeAnnotation, + false, + typeName => + `Unsupported type for eventEmitter "${eventEmitter.name}" in ${moduleName}. Found: ${typeName}`, + resolveAlias, + enumMap, + ); + const isArray = jsiType === 'jsi::Array'; + return { + isVoidTypeAnnotation: isVoidTypeAnnotation, + templateName: isVoidTypeAnnotation ? `/*${templateName}*/` : templateName, + registerEventEmitter: ` eventEmitterMap_["${ + eventEmitter.name + }"] = std::make_shared>();`, + emitFunction: ` + ${ + isVoidTypeAnnotation ? '' : `template ` + }void emit${toPascalCase(eventEmitter.name)}(${ + isVoidTypeAnnotation + ? '' + : `${isArray ? `std::vector<${templateName}>` : templateName} value` + }) {${ + isVoidTypeAnnotation + ? '' + : ` + static_assert(bridging::supportsFromJs<${ + isArray ? `std::vector<${templateName}>` : templateName + }, ${jsiType}>, "value cannnot be converted to ${jsiType}");` + } + std::static_pointer_cast>(delegate_.eventEmitterMap_["${eventEmitter.name}"])->emit(${ + isVoidTypeAnnotation + ? '' + : `[jsInvoker = jsInvoker_, eventValue = value](jsi::Runtime& rt) -> jsi::Value { + return bridging::toJs(rt, eventValue, jsInvoker); + }` + }); + }`, + }; +} + module.exports = { generate( libraryName: string, @@ -522,12 +592,8 @@ module.exports = { const nativeModules = getModules(schema); const modules = Object.keys(nativeModules).flatMap(hasteModuleName => { - const { - aliasMap, - enumMap, - spec: {properties}, - moduleName, - } = nativeModules[hasteModuleName]; + const {aliasMap, enumMap, spec, moduleName} = + nativeModules[hasteModuleName]; const resolveAlias = createAliasResolver(aliasMap); const structs = createStructsString( hasteModuleName, @@ -540,7 +606,7 @@ module.exports = { return [ ModuleClassDeclarationTemplate({ hasteModuleName, - moduleProperties: properties.map(prop => + moduleProperties: spec.properties.map(prop => translatePropertyToCpp( hasteModuleName, prop, @@ -555,7 +621,15 @@ module.exports = { ModuleSpecClassDeclarationTemplate({ hasteModuleName, moduleName, - moduleProperties: properties.map(prop => + moduleEventEmitters: spec.eventEmitters.map(eventEmitter => + translateEventEmitterToCpp( + moduleName, + eventEmitter, + resolveAlias, + enumMap, + ), + ), + moduleProperties: spec.properties.map(prop => translatePropertyToCpp( hasteModuleName, prop, diff --git a/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js index 387126e40ed..0ba48581e2e 100644 --- a/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js @@ -19,6 +19,7 @@ const EMPTY_NATIVE_MODULES: SchemaType = { aliasMap: {}, enumMap: {}, spec: { + eventEmitters: [], properties: [], }, moduleName: 'SampleTurboModule', @@ -83,6 +84,7 @@ const SIMPLE_NATIVE_MODULES: SchemaType = { }, }, spec: { + eventEmitters: [], properties: [ { name: 'getConstants', @@ -412,6 +414,7 @@ const TWO_MODULES_DIFFERENT_FILES: SchemaType = { aliasMap: {}, enumMap: {}, spec: { + eventEmitters: [], properties: [ { name: 'voidFunc', @@ -433,6 +436,7 @@ const TWO_MODULES_DIFFERENT_FILES: SchemaType = { aliasMap: {}, enumMap: {}, spec: { + eventEmitters: [], properties: [ { name: 'getConstants', @@ -471,6 +475,7 @@ const COMPLEX_OBJECTS: SchemaType = { aliasMap: {}, enumMap: {}, spec: { + eventEmitters: [], properties: [ { name: 'difficult', @@ -927,6 +932,7 @@ const NATIVE_MODULES_WITH_TYPE_ALIASES: SchemaType = { }, enumMap: {}, spec: { + eventEmitters: [], properties: [ { name: 'getConstants', @@ -1212,6 +1218,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { }, enumMap: {}, spec: { + eventEmitters: [], properties: [ { name: 'getConstants', @@ -1408,6 +1415,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { }, enumMap: {}, spec: { + eventEmitters: [], properties: [ { name: 'reportFatalException', @@ -1829,6 +1837,7 @@ const CXX_ONLY_NATIVE_MODULES: SchemaType = { }, }, spec: { + eventEmitters: [], properties: [ { name: 'getArray', @@ -2414,6 +2423,7 @@ const SAMPLE_WITH_UPPERCASE_NAME: SchemaType = { enumMap: {}, aliasMap: {}, spec: { + eventEmitters: [], properties: [], }, moduleName: 'SampleTurboModule', diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap index 60382a6b75c..ad2183e4e3d 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap @@ -42,15 +42,19 @@ protected: : TurboModule(std::string{NativeSampleTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeSampleTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } private: + friend class NativeSampleTurboModuleCxxSpec; T *instance_; }; @@ -110,11 +114,14 @@ protected: : TurboModule(std::string{NativeSampleTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeSampleTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object difficult(jsi::Runtime &rt, jsi::Object A) override { static_assert( @@ -174,6 +181,7 @@ private: } private: + friend class NativeSampleTurboModuleCxxSpec; T *instance_; }; @@ -706,11 +714,14 @@ protected: : TurboModule(std::string{NativeSampleTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeSampleTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Array getArray(jsi::Runtime &rt, jsi::Array arg) override { static_assert( @@ -930,6 +941,7 @@ private: } private: + friend class NativeSampleTurboModuleCxxSpec; T *instance_; }; @@ -983,15 +995,19 @@ protected: : TurboModule(std::string{NativeSampleTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeSampleTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } private: + friend class NativeSampleTurboModuleCxxSpec; T *instance_; }; @@ -1120,11 +1136,14 @@ protected: : TurboModule(std::string{AliasTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public AliasTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - AliasTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + AliasTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getConstants(jsi::Runtime &rt) override { static_assert( @@ -1144,6 +1163,7 @@ private: } private: + friend class AliasTurboModuleCxxSpec; T *instance_; }; @@ -1461,11 +1481,14 @@ protected: : TurboModule(std::string{NativeCameraRollManagerCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeCameraRollManagerCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeCameraRollManagerCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeCameraRollManagerCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getConstants(jsi::Runtime &rt) override { static_assert( @@ -1501,6 +1524,7 @@ private: } private: + friend class NativeCameraRollManagerCxxSpec; T *instance_; }; @@ -1701,11 +1725,14 @@ protected: : TurboModule(std::string{NativeExceptionsManagerCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeExceptionsManagerCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeExceptionsManagerCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeExceptionsManagerCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } void reportFatalException(jsi::Runtime &rt, jsi::String message, jsi::Array stack, double exceptionId) override { static_assert( @@ -1749,6 +1776,7 @@ private: } private: + friend class NativeExceptionsManagerCxxSpec; T *instance_; }; @@ -1902,11 +1930,14 @@ protected: : TurboModule(std::string{NativeSampleTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeSampleTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getConstants(jsi::Runtime &rt) override { static_assert( @@ -2022,6 +2053,7 @@ private: } private: + friend class NativeSampleTurboModuleCxxSpec; T *instance_; }; @@ -2075,11 +2107,14 @@ protected: : TurboModule(std::string{NativeSampleTurboModuleCxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeSampleTurboModuleCxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } void voidFunc(jsi::Runtime &rt) override { static_assert( @@ -2091,6 +2126,7 @@ private: } private: + friend class NativeSampleTurboModuleCxxSpec; T *instance_; }; @@ -2122,11 +2158,14 @@ protected: : TurboModule(std::string{NativeSampleTurboModule2CxxSpec::kModuleName}, jsInvoker), delegate_(reinterpret_cast(this), jsInvoker) {} + private: class Delegate : public NativeSampleTurboModule2CxxSpecJSI { public: Delegate(T *instance, std::shared_ptr jsInvoker) : - NativeSampleTurboModule2CxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + NativeSampleTurboModule2CxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } jsi::Object getConstants(jsi::Runtime &rt) override { static_assert( @@ -2146,6 +2185,7 @@ private: } private: + friend class NativeSampleTurboModule2CxxSpec; T *instance_; }; diff --git a/packages/react-native-codegen/src/parsers/__tests__/parsers-commons-test.js b/packages/react-native-codegen/src/parsers/__tests__/parsers-commons-test.js index 44e25e76876..f563d695cac 100644 --- a/packages/react-native-codegen/src/parsers/__tests__/parsers-commons-test.js +++ b/packages/react-native-codegen/src/parsers/__tests__/parsers-commons-test.js @@ -401,7 +401,7 @@ describe('buildSchemaFromConfigType', () => { type: 'NativeModule', aliasMap: {}, enumMap: {}, - spec: {properties: []}, + spec: {eventEmitters: [], properties: []}, moduleName: '', }; @@ -836,6 +836,7 @@ describe('buildSchema', () => { aliasMap: {}, enumMap: {}, spec: { + eventEmitters: [], properties: [ { name: 'getArray', @@ -1247,6 +1248,7 @@ describe('buildModuleSchema', () => { excludedPlatforms: undefined, moduleName: 'SampleTurboModule', spec: { + eventEmitters: [], properties: [ { name: 'getArray', diff --git a/packages/react-native-codegen/src/parsers/error-utils.js b/packages/react-native-codegen/src/parsers/error-utils.js index 55cafa1ba8f..04992093992 100644 --- a/packages/react-native-codegen/src/parsers/error-utils.js +++ b/packages/react-native-codegen/src/parsers/error-utils.js @@ -26,6 +26,8 @@ const { UnsupportedArrayElementTypeAnnotationParserError, UnsupportedFunctionParamTypeAnnotationParserError, UnsupportedFunctionReturnTypeAnnotationParserError, + UnsupportedModuleEventEmitterPropertyParserError, + UnsupportedModuleEventEmitterTypePropertyParserError, UnsupportedModulePropertyParserError, UnsupportedObjectPropertyValueTypeAnnotationParserError, UntypedModuleRegistryCallParserError, @@ -155,6 +157,46 @@ function throwIfUntypedModule( } } +function throwIfEventEmitterTypeIsUnsupported( + nativeModuleName: string, + propertyName: string, + propertyValueType: string, + parser: Parser, + nullable: boolean, + untyped: boolean, + cxxOnly: boolean, +) { + if (nullable || untyped || !cxxOnly) { + throw new UnsupportedModuleEventEmitterPropertyParserError( + nativeModuleName, + propertyName, + propertyValueType, + parser.language(), + nullable, + untyped, + cxxOnly, + ); + } +} + +function throwIfEventEmitterEventTypeIsUnsupported( + nativeModuleName: string, + propertyName: string, + propertyValueType: string, + parser: Parser, + nullable: boolean, +) { + if (nullable) { + throw new UnsupportedModuleEventEmitterTypePropertyParserError( + nativeModuleName, + propertyName, + propertyValueType, + parser.language(), + nullable, + ); + } +} + function throwIfModuleTypeIsUnsupported( nativeModuleName: string, propertyValue: $FlowFixMe, @@ -363,6 +405,8 @@ module.exports = { throwIfWrongNumberOfCallExpressionArgs, throwIfIncorrectModuleRegistryCallTypeParameterParserError, throwIfUntypedModule, + throwIfEventEmitterTypeIsUnsupported, + throwIfEventEmitterEventTypeIsUnsupported, throwIfModuleTypeIsUnsupported, throwIfMoreThanOneModuleInterfaceParserError, throwIfUnsupportedFunctionParamTypeAnnotationParserError, diff --git a/packages/react-native-codegen/src/parsers/errors.js b/packages/react-native-codegen/src/parsers/errors.js index 6a13264b2c8..dde9cf45ac5 100644 --- a/packages/react-native-codegen/src/parsers/errors.js +++ b/packages/react-native-codegen/src/parsers/errors.js @@ -76,6 +76,44 @@ class MoreThanOneModuleInterfaceParserError extends ParserError { } } +class UnsupportedModuleEventEmitterTypePropertyParserError extends ParserError { + constructor( + nativeModuleName: string, + propertyValue: $FlowFixMe, + propertyName: string, + language: ParserType, + nullable: boolean, + ) { + super( + nativeModuleName, + propertyValue, + `Property '${propertyName}' is an EventEmitter and must have a non nullable eventType`, + ); + } +} + +class UnsupportedModuleEventEmitterPropertyParserError extends ParserError { + constructor( + nativeModuleName: string, + propertyValue: $FlowFixMe, + propertyName: string, + language: ParserType, + nullable: boolean, + untyped: boolean, + cxxOnly: boolean, + ) { + let message = `${language} interfaces extending TurboModule must only contain 'FunctionTypeAnnotation's or non nullable 'EventEmitter's. Further the EventEmitter property `; + if (nullable) { + message += `'${propertyValue}' must non nullable.`; + } else if (untyped) { + message += `'${propertyValue}' must have a concrete or void eventType.`; + } else if (cxxOnly) { + message += `'${propertyValue}' is only supported in C++ Turbo Modules.`; + } + super(nativeModuleName, propertyValue, message); + } +} + class UnsupportedModulePropertyParserError extends ParserError { constructor( nativeModuleName: string, @@ -87,7 +125,7 @@ class UnsupportedModulePropertyParserError extends ParserError { super( nativeModuleName, propertyValue, - `${language} interfaces extending TurboModule must only contain 'FunctionTypeAnnotation's. Property '${propertyName}' refers to a '${invalidPropertyValueType}'.`, + `${language} interfaces extending TurboModule must only contain 'FunctionTypeAnnotation's or non nullable 'EventEmitter's. Property '${propertyName}' refers to a '${invalidPropertyValueType}'.`, ); } } @@ -416,6 +454,8 @@ module.exports = { UnsupportedFunctionReturnTypeAnnotationParserError, UnsupportedEnumDeclarationParserError, UnsupportedUnionTypeAnnotationParserError, + UnsupportedModuleEventEmitterTypePropertyParserError, + UnsupportedModuleEventEmitterPropertyParserError, UnsupportedModulePropertyParserError, UnsupportedObjectPropertyTypeAnnotationParserError, UnsupportedObjectPropertyValueTypeAnnotationParserError, diff --git a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap index b7a36d9a0b1..2552fe938d4 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap +++ b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap @@ -15,7 +15,7 @@ exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_ARR exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_ARRAY_WITH_NO_TYPE_FOR_CONTENT_AS_PARAM 1`] = `"Module NativeSampleTurboModule: Generic 'Array' must have type parameters."`; -exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_NOT_ONLY_METHODS 1`] = `"Module NativeSampleTurboModule: Flow interfaces extending TurboModule must only contain 'FunctionTypeAnnotation's. Property 'sampleBool' refers to a 'BooleanTypeAnnotation'."`; +exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_NOT_ONLY_METHODS 1`] = `"Module NativeSampleTurboModule: Flow interfaces extending TurboModule must only contain 'FunctionTypeAnnotation's or non nullable 'EventEmitter's. Property 'sampleBool' refers to a 'BooleanTypeAnnotation'."`; exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_PROMISE_WITHOUT_TYPE 1`] = `"Module NativeSampleTurboModule: Generic 'Promise' must have type parameters."`; @@ -35,6 +35,7 @@ exports[`RN Codegen Flow Parser can generate fixture ANDROID_ONLY_NATIVE_MODULE 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [] }, 'moduleName': 'SampleTurboModuleAndroid', @@ -182,6 +183,7 @@ exports[`RN Codegen Flow Parser can generate fixture CXX_ONLY_NATIVE_MODULE 1`] } }, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getCallback', @@ -419,6 +421,7 @@ exports[`RN Codegen Flow Parser can generate fixture EMPTY_NATIVE_MODULE 1`] = ` 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [] }, 'moduleName': 'SampleTurboModule' @@ -485,6 +488,7 @@ exports[`RN Codegen Flow Parser can generate fixture IOS_ONLY_NATIVE_MODULE 1`] } }, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getEnums', @@ -578,6 +582,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_ALIASES }, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getNumber', @@ -742,6 +747,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_ARRAY_WI 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getArray', @@ -784,6 +790,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_ARRAY_WI 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getArray', @@ -820,6 +827,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_BASIC_AR 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getArray', @@ -887,6 +895,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_BASIC_PA 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'passBool', @@ -980,6 +989,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_CALLBACK 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getValueWithCallback', @@ -1041,6 +1051,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_COMPLEX_ 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getArray', @@ -1101,6 +1112,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_COMPLEX_ 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getObject', @@ -1314,6 +1326,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_COMPLEX_ 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getConstants', @@ -1419,6 +1432,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_FLOAT_AN 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getInt', @@ -1508,6 +1522,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_NESTED_A }, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'foo1', @@ -1566,6 +1581,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_NULLABLE 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'voidFunc', @@ -1618,6 +1634,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_OBJECT_W }, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getConstants', @@ -1715,6 +1732,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_PARTIALS }, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getSomeObj', @@ -1827,6 +1845,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_PARTIALS }, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getPartialPartial', @@ -1916,6 +1935,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_PROMISE }, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getValueWithPromise', @@ -1976,6 +1996,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_ROOT_TAG 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getRootTag', @@ -2014,6 +2035,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_SIMPLE_O 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getObject', @@ -2050,6 +2072,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_UNION 1` 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getUnion', @@ -2112,6 +2135,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_UNSAFE_O 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getUnsafeObject', @@ -2186,6 +2210,7 @@ exports[`RN Codegen Flow Parser can generate fixture PROMISE_WITH_COMMONLY_USED_ }, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'returnStringArray', diff --git a/packages/react-native-codegen/src/parsers/parsers-commons.js b/packages/react-native-codegen/src/parsers/parsers-commons.js index 60344ab0b25..ec60b17dcc6 100644 --- a/packages/react-native-codegen/src/parsers/parsers-commons.js +++ b/packages/react-native-codegen/src/parsers/parsers-commons.js @@ -17,6 +17,7 @@ import type { NativeModuleAliasMap, NativeModuleBaseTypeAnnotation, NativeModuleEnumMap, + NativeModuleEventEmitterShape, NativeModuleFunctionTypeAnnotation, NativeModuleParamTypeAnnotation, NativeModulePropertyShape, @@ -40,6 +41,8 @@ import type { const { throwIfConfigNotfound, + throwIfEventEmitterEventTypeIsUnsupported, + throwIfEventEmitterTypeIsUnsupported, throwIfIncorrectModuleRegistryCallArgument, throwIfIncorrectModuleRegistryCallTypeParameterParserError, throwIfModuleInterfaceIsMisnamed, @@ -470,6 +473,63 @@ function buildPropertySchema( }; } +function buildEventEmitterSchema( + hasteModuleName: string, + // TODO(T108222691): [TS] Use flow-types for @babel/parser + // TODO(T71778680): [Flow] This is an ObjectTypeProperty containing either: + // - a FunctionTypeAnnotation or GenericTypeAnnotation + // - a NullableTypeAnnoation containing a FunctionTypeAnnotation or GenericTypeAnnotation + // Flow type this node + property: $FlowFixMe, + types: TypeDeclarationMap, + aliasMap: {...NativeModuleAliasMap}, + enumMap: {...NativeModuleEnumMap}, + tryParse: ParserErrorCapturer, + cxxOnly: boolean, + translateTypeAnnotation: $FlowFixMe, + parser: Parser, +): NativeModuleEventEmitterShape { + let {key, value} = property; + const eventemitterName: string = key.name; + + const resolveTypeAnnotationFN = parser.getResolveTypeAnnotationFN(); + const [typeAnnotation, typeAnnotationNullable] = unwrapNullable(value); + const typeAnnotationUntyped = + value.typeParameters.params.length === 1 && + value.typeParameters.params[0].type === 'ObjectTypeAnnotation' && + value.typeParameters.params[0].properties.length === 0; + + throwIfEventEmitterTypeIsUnsupported( + hasteModuleName, + key.name, + typeAnnotation.type, + parser, + typeAnnotationNullable, + typeAnnotationUntyped, + cxxOnly, + ); + const eventTypeResolutionStatus = resolveTypeAnnotationFN( + typeAnnotation.typeParameters.params[0], + types, + parser, + ); + throwIfEventEmitterEventTypeIsUnsupported( + hasteModuleName, + key.name, + eventTypeResolutionStatus.typeAnnotation, + parser, + eventTypeResolutionStatus.nullable, + ); + return { + name: eventemitterName, + optional: false, + typeAnnotation: { + type: 'EventEmitterTypeAnnotation', + typeAnnotation: {type: eventTypeResolutionStatus.typeAnnotation.type}, + }, + }; +} + function buildSchemaFromConfigType( configType: 'module' | 'component' | 'none', filename: ?string, @@ -719,6 +779,10 @@ const buildModuleSchema = ( const properties: $ReadOnlyArray<$FlowFixMe> = language === 'Flow' ? moduleSpec.body.properties : moduleSpec.body.body; + type PropertyShape = + | {type: 'eventEmitter', value: NativeModuleEventEmitterShape} + | {type: 'method', value: NativeModulePropertyShape}; + // $FlowFixMe[missing-type-arg] const nativeModuleSchema = properties .filter( @@ -730,23 +794,44 @@ const buildModuleSchema = ( .map(property => { const enumMap: {...NativeModuleEnumMap} = {}; + const isEventEmitter = + property?.value?.type === 'GenericTypeAnnotation' && + property?.value?.id?.name === 'EventEmitter'; return tryParse(() => ({ aliasMap, enumMap, - propertyShape: buildPropertySchema( - hasteModuleName, - property, - types, - aliasMap, - enumMap, - tryParse, - cxxOnly, - translateTypeAnnotation, - parser, - ), + propertyShape: isEventEmitter + ? { + type: 'eventEmitter', + value: buildEventEmitterSchema( + hasteModuleName, + property, + types, + aliasMap, + enumMap, + tryParse, + cxxOnly, + translateTypeAnnotation, + parser, + ), + } + : { + type: 'method', + value: buildPropertySchema( + hasteModuleName, + property, + types, + aliasMap, + enumMap, + tryParse, + cxxOnly, + translateTypeAnnotation, + parser, + ), + }, })); }) .filter(Boolean) @@ -756,7 +841,12 @@ const buildModuleSchema = ( aliasMap: {...moduleSchema.aliasMap, ...aliasMap}, enumMap: {...moduleSchema.enumMap, ...enumMap}, spec: { - properties: [...moduleSchema.spec.properties, propertyShape], + eventEmitters: [...moduleSchema.spec.eventEmitters].concat( + propertyShape.type === 'eventEmitter' ? [propertyShape.value] : [], + ), + properties: [...moduleSchema.spec.properties].concat( + propertyShape.type === 'method' ? [propertyShape.value] : [], + ), }, moduleName: moduleSchema.moduleName, excludedPlatforms: moduleSchema.excludedPlatforms, @@ -765,7 +855,7 @@ const buildModuleSchema = ( type: 'NativeModule', aliasMap: {}, enumMap: {}, - spec: {properties: []}, + spec: {eventEmitters: [], properties: []}, moduleName, excludedPlatforms: excludedPlatforms.length !== 0 ? [...excludedPlatforms] : undefined, @@ -776,7 +866,10 @@ const buildModuleSchema = ( type: 'NativeModule', aliasMap: getSortedObject(nativeModuleSchema.aliasMap), enumMap: getSortedObject(nativeModuleSchema.enumMap), - spec: {properties: nativeModuleSchema.spec.properties.sort()}, + spec: { + eventEmitters: nativeModuleSchema.spec.eventEmitters.sort(), + properties: nativeModuleSchema.spec.properties.sort(), + }, moduleName, excludedPlatforms: nativeModuleSchema.excludedPlatforms, }; diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap b/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap index fb386a50243..ef3bfc9cf60 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap +++ b/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap @@ -8,7 +8,7 @@ exports[`RN Codegen TypeScript Parser Fails with error message NATIVE_MODULES_WI exports[`RN Codegen TypeScript Parser Fails with error message NATIVE_MODULES_WITH_ARRAY_WITH_NO_TYPE_FOR_CONTENT_AS_PARAM 1`] = `"Module NativeSampleTurboModule: Generic 'Array' must have type parameters."`; -exports[`RN Codegen TypeScript Parser Fails with error message NATIVE_MODULES_WITH_NOT_ONLY_METHODS 1`] = `"Module NativeSampleTurboModule: TypeScript interfaces extending TurboModule must only contain 'FunctionTypeAnnotation's. Property 'sampleBool' refers to a 'TSBooleanKeyword'."`; +exports[`RN Codegen TypeScript Parser Fails with error message NATIVE_MODULES_WITH_NOT_ONLY_METHODS 1`] = `"Module NativeSampleTurboModule: TypeScript interfaces extending TurboModule must only contain 'FunctionTypeAnnotation's or non nullable 'EventEmitter's. Property 'sampleBool' refers to a 'TSBooleanKeyword'."`; exports[`RN Codegen TypeScript Parser Fails with error message NATIVE_MODULES_WITH_PROMISE_WITHOUT_TYPE 1`] = `"Module NativeSampleTurboModule: Generic 'Promise' must have type parameters."`; @@ -26,6 +26,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture ANDROID_ONLY_NATIVE_M 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [] }, 'moduleName': 'SampleTurboModuleAndroid', @@ -173,6 +174,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture CXX_ONLY_NATIVE_MODUL } }, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getCallback', @@ -410,6 +412,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture EMPTY_NATIVE_MODULE 1 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [] }, 'moduleName': 'SampleTurboModule' @@ -476,6 +479,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture IOS_ONLY_NATIVE_MODUL } }, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getEnums', @@ -569,6 +573,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_AL }, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getNumber', @@ -733,6 +738,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_AR 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getArray', @@ -775,6 +781,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_AR 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getArray', @@ -811,6 +818,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_AR 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getArray', @@ -853,6 +861,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_AR 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getArray', @@ -889,6 +898,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_BA 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getArray', @@ -956,6 +966,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_BA 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getArray', @@ -1023,6 +1034,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_BA 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'passBool', @@ -1116,6 +1128,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_CA 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getValueWithCallback', @@ -1177,6 +1190,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_CO 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getArray', @@ -1237,6 +1251,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_CO 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getArray', @@ -1297,6 +1312,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_CO 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getObject', @@ -1510,6 +1526,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_CO 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getConstants', @@ -1615,6 +1632,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_FL 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getInt', @@ -1720,6 +1738,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_IN }, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'foo1', @@ -1812,6 +1831,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_NE }, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'foo1', @@ -1974,6 +1994,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_NE }, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'foo1', @@ -2032,6 +2053,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_NU 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'voidFunc', @@ -2084,6 +2106,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_OB }, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getConstants', @@ -2181,6 +2204,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_PA }, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getSomeObj', @@ -2293,6 +2317,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_PA }, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getPartialPartial', @@ -2382,6 +2407,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_PR }, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getValueWithPromise', @@ -2442,6 +2468,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_RO 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getRootTag', @@ -2480,6 +2507,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_SI 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getObject', @@ -2516,6 +2544,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_UN 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getUnion', @@ -2578,6 +2607,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_UN 'aliasMap': {}, 'enumMap': {}, 'spec': { + 'eventEmitters': [], 'properties': [ { 'name': 'getUnsafeObject', diff --git a/packages/react-native/ReactCommon/react/bridging/EventEmitter.h b/packages/react-native/ReactCommon/react/bridging/EventEmitter.h index 33bec2cedbb..e2c8977302f 100644 --- a/packages/react-native/ReactCommon/react/bridging/EventEmitter.h +++ b/packages/react-native/ReactCommon/react/bridging/EventEmitter.h @@ -85,6 +85,15 @@ class AsyncEventEmitter : public IAsyncEventEmitter { AsyncEventEmitter(const AsyncEventEmitter&) = delete; AsyncEventEmitter& operator=(const AsyncEventEmitter&) = delete; + void emit(std::function&& converter) { + std::lock_guard lock(state_->mutex); + for (auto& [_, listener] : state_->listeners) { + listener.call([converter](jsi::Runtime& rt, jsi::Function& jsFunction) { + jsFunction.call(rt, converter(rt)); + }); + } + } + void emit(Args... value) { std::lock_guard lock(state_->mutex); for (const auto& [_, listener] : state_->listeners) { diff --git a/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.cpp b/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.cpp index 3359083bde0..512562c29d8 100644 --- a/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.cpp +++ b/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.cpp @@ -470,6 +470,7 @@ TEST_F(BridgingTest, eventEmitterTest) { EXPECT_TRUE(eventEmitter.state_->listeners.contains(1)); EXPECT_TRUE(eventEmitter.state_->listeners.contains(2)); + // emit with args EXPECT_NO_THROW(eventEmitter.emit({"four", "five", "six"})); flushQueue(); @@ -518,7 +519,12 @@ TEST_F(BridgingTest, eventEmitterTest) { } flushQueue(); - EXPECT_NO_THROW(eventEmitter.emit({"ten", "eleven", "twelve"})); + // Emit with function + EXPECT_NO_THROW(eventEmitter.emit( + [jsInvoker = invoker, + value = {"ten", "eleven", "twelve"}](jsi::Runtime& rt) -> jsi::Value { + return bridging::toJs(rt, value, jsInvoker); + })); flushQueue(); // no new data as listeners had been removed diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h index aad026af97b..66cb28a652c 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h @@ -7,12 +7,14 @@ #pragma once +#include #include #include #include #include +#include namespace facebook::react { @@ -89,6 +91,8 @@ class JSI_EXPORT TurboModule : public facebook::jsi::HostObject { size_t count); }; std::unordered_map methodMap_; + std::unordered_map> + eventEmitterMap_; using ArgFactory = std::function& args)>; @@ -122,12 +126,9 @@ class JSI_EXPORT TurboModule : public facebook::jsi::HostObject { jsi::Runtime& runtime, const jsi::PropNameID& propName) { std::string propNameUtf8 = propName.utf8(runtime); - auto p = methodMap_.find(propNameUtf8); - if (p == methodMap_.end()) { - // Method was not found, let JS decide what to do. - return facebook::jsi::Value::undefined(); - } else { - const MethodMetadata& meta = p->second; + if (auto methodIter = methodMap_.find(propNameUtf8); + methodIter != methodMap_.end()) { + const MethodMetadata& meta = methodIter->second; return jsi::Function::createFromHostFunction( runtime, propName, @@ -137,7 +138,12 @@ class JSI_EXPORT TurboModule : public facebook::jsi::HostObject { [[maybe_unused]] const jsi::Value& thisVal, const jsi::Value* args, size_t count) { return meta.invoker(rt, *this, args, count); }); + } else if (auto eventEmitterIter = eventEmitterMap_.find(propNameUtf8); + eventEmitterIter != eventEmitterMap_.end()) { + return eventEmitterIter->second->get(runtime, jsInvoker_); } + // Neither Method nor EventEmitter were not found, let JS decide what to do. + return facebook::jsi::Value::undefined(); } private: