diff --git a/change/react-native-windows-2020-04-30-08-22-39-MS_RemoveReactAppRefCountHack.json b/change/react-native-windows-2020-04-30-08-22-39-MS_RemoveReactAppRefCountHack.json new file mode 100644 index 00000000000..0faac8416ae --- /dev/null +++ b/change/react-native-windows-2020-04-30-08-22-39-MS_RemoveReactAppRefCountHack.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Removed the ref count work around from classes derived from ReactApplications", + "packageName": "react-native-windows", + "email": "vmorozov@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-30T15:22:39.524Z" +} diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/App.cpp b/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/App.cpp index d5c23ef61ce..6cbc618bc3b 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/App.cpp +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleAppCPP/App.cpp @@ -39,11 +39,6 @@ App::App() noexcept { PackageProviders().Append(winrt::SampleLibraryCS::ReactPackageProvider()); InitializeComponent(); - - // This works around a cpp/winrt bug with composable/aggregable types tracked - // by 22116519 - AddRef(); - m_inner.as<::IUnknown>()->Release(); } } // namespace winrt::SampleAppCpp::implementation diff --git a/vnext/Microsoft.ReactNative/ReactApplication.cpp b/vnext/Microsoft.ReactNative/ReactApplication.cpp index 38c271ddb6c..a4f2d1d4e93 100644 --- a/vnext/Microsoft.ReactNative/ReactApplication.cpp +++ b/vnext/Microsoft.ReactNative/ReactApplication.cpp @@ -4,6 +4,7 @@ #include "pch.h" #include "ReactApplication.h" #include "ReactApplication.g.cpp" + #include "Modules/LinkingManagerModule.h" #include "ReactNativeHost.h" @@ -22,7 +23,16 @@ using namespace xaml::Navigation; namespace winrt::Microsoft::ReactNative::implementation { -ReactApplication::ReactApplication() noexcept { +ReactApplication::ReactApplication() = default; + +ReactApplication::ReactApplication(IInspectable const &outer) noexcept : ReactApplication{} { + // The factory is usually called in the base generated class. We call it here to pass correct + // 'outer' interface to enable inheritance from the ReactApplication class in user code. + impl::call_factory([&](xaml::IApplicationFactory const &f) { + [[maybe_unused]] auto winrt_impl_discarded = + f.CreateInstance(outer ? outer : static_cast(*this), this->m_inner); + }); + Suspending({this, &ReactApplication::OnSuspending}); #if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION @@ -111,7 +121,7 @@ void ReactApplication::OnActivated(IActivatedEventArgs const &e) { } void ReactApplication::OnLaunched(LaunchActivatedEventArgs const &e) { - Super::OnLaunched(e); + base_type::OnLaunched(e); // auto args = std::wstring(e.Arguments().c_str()); this->OnCreate(e); } diff --git a/vnext/Microsoft.ReactNative/ReactApplication.h b/vnext/Microsoft.ReactNative/ReactApplication.h index 1bb0e357aa8..b17d031257b 100644 --- a/vnext/Microsoft.ReactNative/ReactApplication.h +++ b/vnext/Microsoft.ReactNative/ReactApplication.h @@ -4,15 +4,55 @@ #pragma once #include "ReactApplication.g.h" +#include #include "ReactNativeHost.h" namespace winrt::Microsoft::ReactNative::implementation { -struct ReactApplication : ReactApplicationT { - using Super = ReactApplicationT; +// NoDefaultCtorReactApplication_base is a copy of the generated ReactApplication_base +// without the default constructor where it calls a factory for the base type. +// This is done to fix the aggregation issue in types inheriting from the ReactApplication. +// We call the factory in the ReactApplication constructor where we can pass correct +// 'outer' interface. +// +// This class must match the generated ReactApplication_base. +// It must be updated if the shape of generated ReactApplication_base is changed in future. +// The only difference is that this class has no default constructor. +template +struct __declspec(empty_bases) NoDefaultCtorReactApplication_base + : implements< + D, + Microsoft::ReactNative::ReactApplication, + composable, + composing, + xaml::IApplicationOverrides, + xaml::IApplicationOverrides2, + I...>, + impl::require, + impl::base, + xaml::IApplicationOverridesT, + xaml::IApplicationOverrides2T { + using base_type = NoDefaultCtorReactApplication_base; + using class_type = Microsoft::ReactNative::ReactApplication; + using implements_type = typename NoDefaultCtorReactApplication_base::implements_type; + using implements_type::implements_type; + using composable_base = xaml::Application; + + hstring GetRuntimeClassName() const { + return L"Microsoft.ReactNative.ReactApplication"; + } + protected: + using dispatch = impl::dispatch_to_overridable; + auto overridable() noexcept { + return dispatch::overridable(static_cast(*this)); + } +}; + +struct ReactApplication : NoDefaultCtorReactApplication_base { public: // ReactApplication ABI API - ReactApplication() noexcept; + ReactApplication(); + ReactApplication(IInspectable const &outer) noexcept; ReactNative::ReactInstanceSettings InstanceSettings() noexcept; void InstanceSettings(ReactNative::ReactInstanceSettings const &value) noexcept; @@ -57,6 +97,13 @@ struct ReactApplication : ReactApplicationT { namespace winrt::Microsoft::ReactNative::factory_implementation { -struct ReactApplication : ReactApplicationT {}; +// Override the CreateInstance method to pass baseInterface to the ReactApplication constructor +// to support correct COM aggregation that is need to inherit from the ReactApplication. +struct ReactApplication : ReactApplicationT { + auto CreateInstance(IInspectable const &baseInterface, IInspectable &innerInterface) { + return impl::composable_factory::template CreateInstance< + Microsoft::ReactNative::ReactApplication>(baseInterface, innerInterface, baseInterface); + } +}; } // namespace winrt::Microsoft::ReactNative::factory_implementation diff --git a/vnext/local-cli/generator-windows/templates/cpp/src/App.cpp b/vnext/local-cli/generator-windows/templates/cpp/src/App.cpp index e79bb0b7dd8..15b8fe539bf 100644 --- a/vnext/local-cli/generator-windows/templates/cpp/src/App.cpp +++ b/vnext/local-cli/generator-windows/templates/cpp/src/App.cpp @@ -36,11 +36,6 @@ App::App() noexcept REACT_REGISTER_NATIVE_MODULE_PACKAGES(); //code-gen macro from autolink InitializeComponent(); - - // This works around a cpp/winrt bug with composable/aggregable types tracked - // by 22116519 - AddRef(); - m_inner.as<::IUnknown>()->Release(); }