diff --git a/packages/react-native/ReactCommon/react/bridging/Class.h b/packages/react-native/ReactCommon/react/bridging/Class.h index 61fa82e338c..0d0fcd49e8b 100644 --- a/packages/react-native/ReactCommon/react/bridging/Class.h +++ b/packages/react-native/ReactCommon/react/bridging/Class.h @@ -41,7 +41,7 @@ T callFromJs( rt, fromJs(rt, std::forward(args), jsInvoker)...); return jsi::Value(); - } else if constexpr (is_jsi_v) { + } else if constexpr (is_jsi_v || supportsToJs) { static_assert(supportsToJs, "Incompatible return type"); return toJs( @@ -49,7 +49,6 @@ T callFromJs( (instance->*method)( rt, fromJs(rt, std::forward(args), jsInvoker)...), jsInvoker); - } else if constexpr (is_optional_jsi_v) { static_assert( is_optional_v diff --git a/packages/react-native/ReactCommon/react/bridging/tests/ClassTest.cpp b/packages/react-native/ReactCommon/react/bridging/tests/ClassTest.cpp index dfcf9f29ec5..f01b9f5c07d 100644 --- a/packages/react-native/ReactCommon/react/bridging/tests/ClassTest.cpp +++ b/packages/react-native/ReactCommon/react/bridging/tests/ClassTest.cpp @@ -92,4 +92,62 @@ TEST_F(BridgingTest, callFromJsTest) { EXPECT_TRUE(called); } +struct MethodReturnTypeCastingTestObject { + public: + explicit MethodReturnTypeCastingTestObject(int value) : value_(value) {} + + int toInteger() const { + return value_; + } + + private: + int value_; +}; + +template <> +struct Bridging { + static MethodReturnTypeCastingTestObject fromJs( + jsi::Runtime& /*rt*/, + const jsi::Value& value) { + return MethodReturnTypeCastingTestObject( + static_cast(value.asNumber())); + } + + static int toJs( + jsi::Runtime& /*rt*/, + const MethodReturnTypeCastingTestObject& value) { + return value.toInteger(); + } +}; + +struct MethodReturnTypeCastingTestClass { + explicit MethodReturnTypeCastingTestClass( + std::shared_ptr invoker) + : invoker_(std::move(invoker)) {} + + // This is the key, return type is not a primitive, but an object with defined + // bridging template. + MethodReturnTypeCastingTestObject + add(jsi::Runtime& /*unused*/, int a, int b) { + return MethodReturnTypeCastingTestObject(a + b); + } + + private: + std::shared_ptr invoker_; +}; + +TEST_F(BridgingTest, methodReturnTypeCastingTest) { + auto instance = MethodReturnTypeCastingTestClass(invoker); + + EXPECT_EQ( + 2, + bridging::callFromJs( + rt, + &MethodReturnTypeCastingTestClass::add, + invoker, + &instance, + 1, + 1)); +} + } // namespace facebook::react