diff --git a/change/react-native-windows-5043a4f4-852a-453e-bc08-627cb97f1f1a.json b/change/react-native-windows-5043a4f4-852a-453e-bc08-627cb97f1f1a.json new file mode 100644 index 00000000000..b160a3e72e7 --- /dev/null +++ b/change/react-native-windows-5043a4f4-852a-453e-bc08-627cb97f1f1a.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Pass RuntimeSchedulerCallInvoker to C++ TurboModule initialization", + "packageName": "react-native-windows", + "email": "erozell@outlook.com", + "dependentChangeType": "patch" +} diff --git a/vnext/Microsoft.ReactNative.Cxx/TurboModuleProvider.cpp b/vnext/Microsoft.ReactNative.Cxx/TurboModuleProvider.cpp index 383f09ad44b..a0076438432 100644 --- a/vnext/Microsoft.ReactNative.Cxx/TurboModuleProvider.cpp +++ b/vnext/Microsoft.ReactNative.Cxx/TurboModuleProvider.cpp @@ -6,6 +6,12 @@ namespace winrt::Microsoft::ReactNative { +ReactPropertyId>> CallInvokerProperty() noexcept { + ReactPropertyId>> propId{ + L"ReactNative.JSI", L"CallInvoker"}; + return propId; +} + // CallInvoker implementation based on JSDispatcher. struct AbiCallInvoker final : facebook::react::CallInvoker { AbiCallInvoker(IReactDispatcher const &jsDispatcher) : m_jsDispatcher(jsDispatcher) {} @@ -24,9 +30,23 @@ struct AbiCallInvoker final : facebook::react::CallInvoker { IReactDispatcher m_jsDispatcher{nullptr}; }; -// Creates CallInvoker based on JSDispatcher. -std::shared_ptr MakeAbiCallInvoker(IReactDispatcher const &jsDispatcher) noexcept { - return std::make_shared(jsDispatcher); +std::shared_ptr GetCallInvokerFromContext(IReactContext const &context) noexcept { + // Try to get the CallInvoker instance from Context + const auto callInvokerPropertyValue = ReactPropertyBag{context.Properties()}.Get(CallInvokerProperty()); + const auto weakCallInvoker = + callInvokerPropertyValue ? callInvokerPropertyValue.Value() : std::weak_ptr{}; + if (const auto callInvoker = weakCallInvoker.lock()) { + return callInvoker; + } + + // Fallback to creating CallInvoker based on JSDispatcher. + return std::make_shared(context.JSDispatcher()); +} + +void SetCallInvoker( + IReactPropertyBag const &properties, + std::weak_ptr const &value) noexcept { + ReactPropertyBag{properties}.Set(CallInvokerProperty(), value); } } // namespace winrt::Microsoft::ReactNative diff --git a/vnext/Microsoft.ReactNative.Cxx/TurboModuleProvider.h b/vnext/Microsoft.ReactNative.Cxx/TurboModuleProvider.h index 6df9293c1ea..c7de3981891 100644 --- a/vnext/Microsoft.ReactNative.Cxx/TurboModuleProvider.h +++ b/vnext/Microsoft.ReactNative.Cxx/TurboModuleProvider.h @@ -10,8 +10,10 @@ namespace winrt::Microsoft::ReactNative { -// Creates CallInvoker based on JSDispatcher. -std::shared_ptr MakeAbiCallInvoker(IReactDispatcher const &jsDispatcher) noexcept; +void SetCallInvoker( + IReactPropertyBag const &properties, + std::weak_ptr const &callInvoker) noexcept; +std::shared_ptr GetCallInvokerFromContext(IReactContext const &context) noexcept; template < typename TTurboModule, @@ -23,7 +25,7 @@ void AddTurboModuleProvider(IReactPackageBuilder const &packageBuilder, std::wst // We expect the initializer to be called immediately for TurboModules moduleBuilder.AddInitializer([&abiTurboModule](IReactContext const &context) mutable { TryGetOrCreateContextRuntime(ReactContext{context}); // Ensure the JSI runtime is created. - auto callInvoker = MakeAbiCallInvoker(context.JSDispatcher()); + auto callInvoker = GetCallInvokerFromContext(context); auto turboModule = std::make_shared(callInvoker); abiTurboModule = winrt::make(std::move(turboModule)); }); diff --git a/vnext/Shared/OInstance.cpp b/vnext/Shared/OInstance.cpp index ece2c869a9c..fca719cd406 100644 --- a/vnext/Shared/OInstance.cpp +++ b/vnext/Shared/OInstance.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include "PackagerConnection.h" @@ -513,10 +514,13 @@ InstanceImpl::InstanceImpl( if (runtimeScheduler) { RuntimeSchedulerBinding::createAndInstallIfNeeded(*runtimeHolder->getRuntime(), runtimeScheduler); } - auto turboModuleManager = std::make_shared( - turboModuleRegistry, - runtimeScheduler ? std::make_shared(runtimeScheduler) - : innerInstance->getJSCallInvoker()); + + const auto callInvoker = runtimeScheduler ? std::make_shared(runtimeScheduler) + : innerInstance->getJSCallInvoker(); + + auto turboModuleManager = std::make_shared(turboModuleRegistry, callInvoker); + + SetCallInvoker(propertyBag, callInvoker); // TODO: The binding here should also add the proxys that convert cxxmodules into turbomodules // [@vmoroz] Note, that we must not use the RN TurboCxxModule.h code because it uses global