From af971834b5c016994e6a59db20d1b2ad4d8fd765 Mon Sep 17 00:00:00 2001 From: Sundaram Ramaswamy Date: Tue, 25 Nov 2025 15:47:37 +0530 Subject: [PATCH 1/4] Initialize Xaml on demand only for module authors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Drop XamlHost component - Exposing this means both app and module authors can use any Xaml but we want to enable Xaml hosting only for module authors for now and for this we don’t need XamlHost. * Initialize `XamlApplication`, which loads Xaml framework (costyl), when there’s at least one component requesting Xaml support through `ReactNativeComponentBuilder::XamlSupport` --- ...ndows-73f0d63e-63d7-4322-b402-83e1c0c092e8.json | 7 +++++++ .../ReactCompositionViewComponentBuilder.cpp | 8 ++++++++ .../ReactCompositionViewComponentBuilder.h | 3 +++ .../Fabric/WindowsComponentDescriptorRegistry.cpp | 7 +++++++ .../Fabric/WindowsComponentDescriptorRegistry.h | 3 +++ .../IReactViewComponentBuilder.idl | 1 + vnext/Microsoft.ReactNative/IXamlProvider.idl | 11 ----------- vnext/Microsoft.ReactNative/ReactNativeHost.cpp | 5 +++++ vnext/Shared/Shared.vcxitems | 11 ----------- vnext/overrides.json | 14 +------------- .../Libraries/Components/Xaml/XamlHost.d.ts | 13 ------------- .../Libraries/Components/Xaml/XamlHost.windows.js | 7 ------- vnext/src-win/index.windows.js | 3 --- vnext/src-win/index.windows.js.flow | 1 - 14 files changed, 35 insertions(+), 59 deletions(-) create mode 100644 change/react-native-windows-73f0d63e-63d7-4322-b402-83e1c0c092e8.json delete mode 100644 vnext/Microsoft.ReactNative/IXamlProvider.idl delete mode 100644 vnext/src-win/Libraries/Components/Xaml/XamlHost.d.ts delete mode 100644 vnext/src-win/Libraries/Components/Xaml/XamlHost.windows.js diff --git a/change/react-native-windows-73f0d63e-63d7-4322-b402-83e1c0c092e8.json b/change/react-native-windows-73f0d63e-63d7-4322-b402-83e1c0c092e8.json new file mode 100644 index 00000000000..70df7564ea4 --- /dev/null +++ b/change/react-native-windows-73f0d63e-63d7-4322-b402-83e1c0c092e8.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "comment": "Initialize Xaml on demand only for module authors", + "packageName": "react-native-windows", + "email": "suramaswamy@microsoft.com", + "dependentChangeType": "none" +} diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp index 83b25e3c727..52c262423b5 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp @@ -227,6 +227,14 @@ void ReactCompositionViewComponentBuilder::SetUnmountChildComponentViewHandler( m_unmountChildComponentViewHandler = impl; } +bool ReactCompositionViewComponentBuilder::XamlSupport() const noexcept { + return m_xamlSupport; +} + +void ReactCompositionViewComponentBuilder::XamlSupport(bool isRequired) noexcept { + m_xamlSupport = isRequired; +} + const UnmountChildComponentViewDelegate &ReactCompositionViewComponentBuilder::UnmountChildComponentViewHandler() const noexcept { return m_unmountChildComponentViewHandler; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h index f9d9ab9a227..fa5ec618baf 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h @@ -39,6 +39,8 @@ struct ReactCompositionViewComponentBuilder void SetUpdateEventEmitterHandler(UpdateEventEmitterDelegate impl) noexcept; void SetMountChildComponentViewHandler(MountChildComponentViewDelegate impl) noexcept; void SetUnmountChildComponentViewHandler(UnmountChildComponentViewDelegate impl) noexcept; + bool XamlSupport() const noexcept; + void XamlSupport(bool isRequired) noexcept; public: // Composition::IReactCompositionViewComponentBuilder void SetViewComponentViewInitializer(const ViewComponentViewInitializer &initializer) noexcept; @@ -108,6 +110,7 @@ struct ReactCompositionViewComponentBuilder winrt::Microsoft::ReactNative::Composition::Experimental::IVisualToMountChildrenIntoDelegate m_visualToMountChildrenIntoHandler; UpdateLayoutMetricsDelegate m_updateLayoutMetricsHandler; + bool m_xamlSupport{false}; }; } // namespace winrt::Microsoft::ReactNative::Composition diff --git a/vnext/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.cpp b/vnext/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.cpp index b3c0fc9815e..3e28a348ecd 100644 --- a/vnext/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.cpp @@ -54,6 +54,13 @@ bool WindowsComponentDescriptorRegistry::hasComponentProvider(const std::string return std::find(m_componentNames.begin(), m_componentNames.end(), name) != m_componentNames.end(); } +bool WindowsComponentDescriptorRegistry::isXamlSupportRequired() const noexcept { + return std::any_of(m_builderByName.cbegin(), m_builderByName.cend(), [](const auto& pair) -> bool { + return winrt::get_self(pair.second) + ->XamlSupport(); + }); +} + void WindowsComponentDescriptorRegistry::Add( winrt::hstring componentName, winrt::Microsoft::ReactNative::ReactViewComponentProvider const &provider) noexcept { diff --git a/vnext/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.h b/vnext/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.h index f29dc581841..68ede8eb6e5 100644 --- a/vnext/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.h +++ b/vnext/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.h @@ -34,6 +34,9 @@ struct WindowsComponentDescriptorRegistry { bool hasComponentProvider(const std::string &name) noexcept; + // Returns true if any component requested for XAML support. + bool isXamlSupportRequired() const noexcept; + private: void add(const facebook::react::ComponentDescriptorProvider &provider) noexcept; diff --git a/vnext/Microsoft.ReactNative/IReactViewComponentBuilder.idl b/vnext/Microsoft.ReactNative/IReactViewComponentBuilder.idl index fa2197a0596..2b60aa7e6cd 100644 --- a/vnext/Microsoft.ReactNative/IReactViewComponentBuilder.idl +++ b/vnext/Microsoft.ReactNative/IReactViewComponentBuilder.idl @@ -124,6 +124,7 @@ namespace Microsoft.ReactNative void SetUpdateEventEmitterHandler(UpdateEventEmitterDelegate impl); void SetMountChildComponentViewHandler(MountChildComponentViewDelegate impl); void SetUnmountChildComponentViewHandler(UnmountChildComponentViewDelegate impl); + Boolean XamlSupport { get; set; }; }; // [exclusiveto(ShadowNode)] diff --git a/vnext/Microsoft.ReactNative/IXamlProvider.idl b/vnext/Microsoft.ReactNative/IXamlProvider.idl deleted file mode 100644 index eb20e3cc3fb..00000000000 --- a/vnext/Microsoft.ReactNative/IXamlProvider.idl +++ /dev/null @@ -1,11 +0,0 @@ - -#include "DocString.h" - -namespace Microsoft.ReactNative.Xaml { -[webhosthidden] -interface IXamlControl { - DOC_STRING( - "Native components that want to be Xaml-based can implement IXamlControl to allow their object to be parented to a XamlHost.") - Microsoft.UI.Xaml.UIElement GetXamlElement(); -}; -} // namespace Microsoft.ReactNative.Xaml diff --git a/vnext/Microsoft.ReactNative/ReactNativeHost.cpp b/vnext/Microsoft.ReactNative/ReactNativeHost.cpp index 543a0c7d441..0b8cad9e629 100644 --- a/vnext/Microsoft.ReactNative/ReactNativeHost.cpp +++ b/vnext/Microsoft.ReactNative/ReactNativeHost.cpp @@ -13,6 +13,7 @@ #include #include "IReactContext.h" #include "ReactInstanceSettings.h" +#include "XamlApplication.h" #include #include @@ -102,6 +103,10 @@ IAsyncAction ReactNativeHost::ReloadInstance() noexcept { } } + if (componentregistry->isXamlSupportRequired()) { + winrt::Microsoft::ReactNative::Xaml::implementation::XamlApplication::EnsureCreated(); + } + ReactPropertyBag(m_instanceSettings.Properties()).Set(ReactNativeHostProperty(), get_weak()); Mso::React::ReactOptions reactOptions{}; diff --git a/vnext/Shared/Shared.vcxitems b/vnext/Shared/Shared.vcxitems index 3568b832da0..2caa172e37d 100644 --- a/vnext/Shared/Shared.vcxitems +++ b/vnext/Shared/Shared.vcxitems @@ -139,11 +139,6 @@ true $(ReactNativeWindowsDir)Microsoft.ReactNative\XamlApplication.idl Code - - - true - $(ReactNativeWindowsDir)Microsoft.ReactNative\XamlApplication.idl - Code @@ -248,11 +243,6 @@ true $(MSBuildThisFileDirectory)..\Microsoft.ReactNative\XamlApplication.idl Code - - - true - $(MSBuildThisFileDirectory)..\Microsoft.ReactNative\XamlApplication.idl - Code $(MSBuildThisFileDirectory)..\Microsoft.ReactNative\IJSValueReader.idl @@ -612,7 +602,6 @@ - diff --git a/vnext/overrides.json b/vnext/overrides.json index eb3e0884bcb..28cba06257f 100644 --- a/vnext/overrides.json +++ b/vnext/overrides.json @@ -694,18 +694,6 @@ "file": "src-win/src/private/specs_DEPRECATED/modules/NativePlatformConstantsWindows.js", "baseFile": "packages/react-native/src/private/specs_DEPRECATED/modules/NativePlatformConstantsAndroid.js", "baseHash": "365c5df75b38b129d364af3f6700cb206ce5bd2a" - }, - { - "type": "platform", - "file": "src-win/Libraries/Components/Xaml/XamlHost.d.ts" - }, - { - "type": "platform", - "file": "src-win/Libraries/Components/Xaml/XamlHost.windows.js" - }, - { - "type": "platform", - "file": "src-win/src/private/specs_DEPRECATED/components/Xaml/XamlHostNativeComponent.js" } ] -} \ No newline at end of file +} diff --git a/vnext/src-win/Libraries/Components/Xaml/XamlHost.d.ts b/vnext/src-win/Libraries/Components/Xaml/XamlHost.d.ts deleted file mode 100644 index a69cfafe0be..00000000000 --- a/vnext/src-win/Libraries/Components/Xaml/XamlHost.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * Licensed under the MIT License. - * @format - * @flow - */ -/// -import type {ViewProps} from 'react-native'; -export interface XamlHostProps extends ViewProps { - label: string; -} -declare const _default: import('react-native/Libraries/Utilities/codegenNativeComponent').NativeComponentType; -export default _default; diff --git a/vnext/src-win/Libraries/Components/Xaml/XamlHost.windows.js b/vnext/src-win/Libraries/Components/Xaml/XamlHost.windows.js deleted file mode 100644 index 723810b17a4..00000000000 --- a/vnext/src-win/Libraries/Components/Xaml/XamlHost.windows.js +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @format - * @flow - */ - -import XamlHost from '../../../src/private/specs_DEPRECATED/components/Xaml/XamlHostNativeComponent'; -export default XamlHost; diff --git a/vnext/src-win/index.windows.js b/vnext/src-win/index.windows.js index 8f368fe05fe..14ac2344540 100644 --- a/vnext/src-win/index.windows.js +++ b/vnext/src-win/index.windows.js @@ -372,9 +372,6 @@ module.exports = { get AppTheme() { return require('./Libraries/AppTheme/AppTheme').AppTheme; }, - get XamlHost() { - return require('./Libraries/Components/Xaml/XamlHost').default; - }, } as ReactNativePublicAPI; if (__DEV__) { diff --git a/vnext/src-win/index.windows.js.flow b/vnext/src-win/index.windows.js.flow index d601455ba73..6942181c0c3 100644 --- a/vnext/src-win/index.windows.js.flow +++ b/vnext/src-win/index.windows.js.flow @@ -469,7 +469,6 @@ export {HandledEventPhase } from './Libraries/Components/View/ViewPropTypes' export {default as ViewWindows} from './Libraries/Components/View/View'; export {AppTheme} from './Libraries/AppTheme/AppTheme'; -export {default as XamlHost} from './Libraries/Components/Xaml/XamlHost'; // End Windows Specific exports // #endregion From 713a72efdd2553d9f48cf5cf41b211ef186199e4 Mon Sep 17 00:00:00 2001 From: Sundaram Ramaswamy Date: Thu, 27 Nov 2025 20:17:47 +0530 Subject: [PATCH 2/4] Fix ReactWindows-Desktop build break MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `//vnect/Shared/Shared.vcxitems` is included by two project: 1. `//vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj` 2. `//vnext/Desktop/React.Windows.Desktop.vcxproj` (2) is a static library that breaks due to compiler errors due to `ReactNativeHost.cpp` including `XamlApplication.h` which in turn includes `Xaml.XamlApplication.g.*` which requires `XamlApplication.idl` to be generating them. This won’t happen due to the project type of (2). Wrap `XamlApplication`-related code in a macro and define it only for (1). --- vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj | 1 + vnext/Microsoft.ReactNative/ReactNativeHost.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj index c7e8956734c..f72f867ded9 100644 --- a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +++ b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj @@ -124,6 +124,7 @@ DISABLE_XAML_GENERATED_MAIN; REACTWINDOWS_BUILD; RN_PLATFORM=windows; + RNW_XAML_ISLAND; NOMINMAX; FOLLY_CFG_NO_COROUTINES; FOLLY_NO_CONFIG; diff --git a/vnext/Microsoft.ReactNative/ReactNativeHost.cpp b/vnext/Microsoft.ReactNative/ReactNativeHost.cpp index 0b8cad9e629..a7b03a1388d 100644 --- a/vnext/Microsoft.ReactNative/ReactNativeHost.cpp +++ b/vnext/Microsoft.ReactNative/ReactNativeHost.cpp @@ -13,7 +13,9 @@ #include #include "IReactContext.h" #include "ReactInstanceSettings.h" +#ifdef RNW_XAML_ISLAND #include "XamlApplication.h" +#endif // RNW_XAML_ISLAND #include #include @@ -103,9 +105,11 @@ IAsyncAction ReactNativeHost::ReloadInstance() noexcept { } } +#ifdef RNW_XAML_ISLAND if (componentregistry->isXamlSupportRequired()) { winrt::Microsoft::ReactNative::Xaml::implementation::XamlApplication::EnsureCreated(); } +#endif // RNW_XAML_ISLAND ReactPropertyBag(m_instanceSettings.Properties()).Set(ReactNativeHostProperty(), get_weak()); From 7b56e3b985f0eceb1cb9adfbf4d2d899dc0d144b Mon Sep 17 00:00:00 2001 From: Sundaram Ramaswamy Date: Fri, 28 Nov 2025 10:20:55 +0530 Subject: [PATCH 3/4] [Minor] Fix formatting with yarn format --- .../Fabric/WindowsComponentDescriptorRegistry.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.cpp b/vnext/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.cpp index 3e28a348ecd..e8f311702f2 100644 --- a/vnext/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.cpp @@ -55,10 +55,11 @@ bool WindowsComponentDescriptorRegistry::hasComponentProvider(const std::string } bool WindowsComponentDescriptorRegistry::isXamlSupportRequired() const noexcept { - return std::any_of(m_builderByName.cbegin(), m_builderByName.cend(), [](const auto& pair) -> bool { - return winrt::get_self(pair.second) + return std::any_of(m_builderByName.cbegin(), m_builderByName.cend(), [](const auto &pair) -> bool { + return winrt::get_self( + pair.second) ->XamlSupport(); - }); + }); } void WindowsComponentDescriptorRegistry::Add( From ad9be9d441b38945cc4397c98255d06f9f7be922 Mon Sep 17 00:00:00 2001 From: Sundaram Ramaswamy Date: Fri, 28 Nov 2025 10:46:16 +0530 Subject: [PATCH 4/4] Remove XamlHostNativeComponent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Missed to remove this in the first commit. This would expose the XamlHost tag to JS/TS which we don’t want yet. --- .../Xaml/XamlHostNativeComponent.js | 20 ------------------- 1 file changed, 20 deletions(-) delete mode 100644 vnext/src-win/src/private/specs_DEPRECATED/components/Xaml/XamlHostNativeComponent.js diff --git a/vnext/src-win/src/private/specs_DEPRECATED/components/Xaml/XamlHostNativeComponent.js b/vnext/src-win/src/private/specs_DEPRECATED/components/Xaml/XamlHostNativeComponent.js deleted file mode 100644 index f1a9ed9c96a..00000000000 --- a/vnext/src-win/src/private/specs_DEPRECATED/components/Xaml/XamlHostNativeComponent.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * Licensed under the MIT License. - * @format - * @flow - */ - -'use strict'; - -import type {ViewProps} from 'react-native'; -import {codegenNativeComponent} from 'react-native'; -import type {HostComponent} from '../../../../../src/private/types/HostComponent'; - -type XamlHostProps = $ReadOnly<{| - ...ViewProps, -|}>; - -type NativeType = HostComponent; - -export default (codegenNativeComponent('XamlHost'): NativeType);