diff --git a/change/react-native-windows-9a3751a7-f0ff-4185-92d1-608aa823c32a.json b/change/react-native-windows-9a3751a7-f0ff-4185-92d1-608aa823c32a.json
new file mode 100644
index 00000000000..e9722590fb6
--- /dev/null
+++ b/change/react-native-windows-9a3751a7-f0ff-4185-92d1-608aa823c32a.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "Enable Blob module in UWP",
+ "packageName": "react-native-windows",
+ "email": "julio.rocha@microsoft.com",
+ "dependentChangeType": "patch"
+}
diff --git a/packages/e2e-test-app/windows/RNTesterApp/RNTesterApp.csproj b/packages/e2e-test-app/windows/RNTesterApp/RNTesterApp.csproj
index 233cf98f096..5ce671711ff 100644
--- a/packages/e2e-test-app/windows/RNTesterApp/RNTesterApp.csproj
+++ b/packages/e2e-test-app/windows/RNTesterApp/RNTesterApp.csproj
@@ -145,7 +145,7 @@
-
+
6.2.9
@@ -165,4 +165,4 @@
-
+
\ No newline at end of file
diff --git a/packages/e2e-test-app/windows/RNTesterApp/packages.lock.json b/packages/e2e-test-app/windows/RNTesterApp/packages.lock.json
index 3ac0f02233b..9abc7b4fd8d 100644
--- a/packages/e2e-test-app/windows/RNTesterApp/packages.lock.json
+++ b/packages/e2e-test-app/windows/RNTesterApp/packages.lock.json
@@ -22,9 +22,9 @@
},
"ReactNative.Hermes.Windows": {
"type": "Direct",
- "requested": "[0.11.0-ms.6, )",
- "resolved": "0.11.0-ms.6",
- "contentHash": "7KGeDHh4QR4ua5+aSNAfuhj1sF2PBJbTHJ9m520xo1GZZRW4cxJlyNDNjW5t/sFGeHWw/Uhs7ZrWE2maL9BOEw=="
+ "requested": "[0.12.1, )",
+ "resolved": "0.12.1",
+ "contentHash": "0yjt0Y2pNfqw7qUiV5Q3W8hZ2HuS3HiS135c/ILLXeRXLpQMmfq1NS3oBZ1oMZy94gSfgP9QZ/862T3qUTES1A=="
},
"XamlTreeDump": {
"type": "Direct",
@@ -32,6 +32,11 @@
"resolved": "1.0.9",
"contentHash": "rvh/RZghhSG28PDL1dw56nTZRN0/ViV2TIja/ykU9FHn0gtM8pwtgD8Ebo1nobu0QnSjn8Cg6Ncu39VV19rkrw=="
},
+ "boost": {
+ "type": "Transitive",
+ "resolved": "1.76.0",
+ "contentHash": "p+w3YvNdXL8Cu9Fzrmexssu0tZbWxuf6ywsQqHjDlKFE5ojXHof1HIyMC3zDLfLnh80dIeFcEUAuR2Asg/XHRA=="
+ },
"Microsoft.Net.Native.Compiler": {
"type": "Transitive",
"resolved": "2.2.7-rel-27913-00",
@@ -56,7 +61,17 @@
"Microsoft.NETCore.Platforms": {
"type": "Transitive",
"resolved": "2.1.0",
- "contentHash": "ok+RPAtESz/9MUXeIEz6Lv5XAGQsaNmEYXMsgVALj4D7kqC8gveKWXWXbufLySR2fWrwZf8smyN5RmHu0e4BHA=="
+ "contentHash": "GmkKfoyerqmsHMn7OZj0AKpcBabD+GaafqphvX2Mw406IwiJRy1pKcKqdCfKJfYmkRyJ6+e+RaUylgdJoDa1jQ=="
+ },
+ "Microsoft.Windows.CppWinRT": {
+ "type": "Transitive",
+ "resolved": "2.0.211028.7",
+ "contentHash": "JBGI0c3WLoU6aYJRy9Qo0MLDQfObEp+d4nrhR95iyzf7+HOgjRunHDp/6eGFREd7xq3OI1mll9ecJrMfzBvlyg=="
+ },
+ "Microsoft.Windows.SDK.BuildTools": {
+ "type": "Transitive",
+ "resolved": "10.0.22000.194",
+ "contentHash": "4L0P3zqut466SIqT3VBeLTNUQTxCBDOrTRymRuROCRJKazcK7ibLz9yAO1nKWRt50ttCj39oAa2Iuz9ZTDmLlg=="
},
"NETStandard.Library": {
"type": "Transitive",
@@ -134,11 +149,39 @@
"contentHash": "qF6RRZKaflI+LR1YODNyWYjq5YoX8IJ2wx5y8O+AW2xO+1t/Q6Mm+jQ38zJbWnmXbrcOqUYofn7Y3/KC6lTLBQ=="
},
"automationchannel": {
+ "type": "Project",
+ "dependencies": {
+ "Microsoft.ReactNative": "1.0.0",
+ "Microsoft.UI.Xaml": "2.7.0",
+ "Microsoft.Windows.CppWinRT": "2.0.211028.7"
+ }
+ },
+ "common": {
"type": "Project"
},
- "microsoft.reactnative": {
+ "fmt": {
"type": "Project"
},
+ "folly": {
+ "type": "Project",
+ "dependencies": {
+ "boost": "1.76.0",
+ "fmt": "1.0.0"
+ }
+ },
+ "microsoft.reactnative": {
+ "type": "Project",
+ "dependencies": {
+ "Common": "1.0.0",
+ "Folly": "1.0.0",
+ "Microsoft.UI.Xaml": "2.7.0",
+ "Microsoft.Windows.CppWinRT": "2.0.211028.7",
+ "Microsoft.Windows.SDK.BuildTools": "10.0.22000.194",
+ "ReactCommon": "1.0.0",
+ "ReactNative.Hermes.Windows": "0.12.1",
+ "boost": "1.76.0"
+ }
+ },
"microsoft.reactnative.managed": {
"type": "Project",
"dependencies": {
@@ -146,16 +189,25 @@
"Microsoft.ReactNative": "1.0.0"
}
},
+ "reactcommon": {
+ "type": "Project",
+ "dependencies": {
+ "Folly": "1.0.0",
+ "boost": "1.76.0"
+ }
+ },
"reactnativepicker": {
"type": "Project",
"dependencies": {
- "Microsoft.ReactNative": "1.0.0"
+ "Microsoft.ReactNative": "1.0.0",
+ "Microsoft.UI.Xaml": "2.7.0"
}
},
"reactnativexaml": {
"type": "Project",
"dependencies": {
- "Microsoft.ReactNative": "1.0.0"
+ "Microsoft.ReactNative": "1.0.0",
+ "Microsoft.UI.Xaml": "2.7.0"
}
}
},
diff --git a/vnext/Microsoft.ReactNative/Base/CoreNativeModules.cpp b/vnext/Microsoft.ReactNative/Base/CoreNativeModules.cpp
index a2a2c9d3b36..9522dc4b59a 100644
--- a/vnext/Microsoft.ReactNative/Base/CoreNativeModules.cpp
+++ b/vnext/Microsoft.ReactNative/Base/CoreNativeModules.cpp
@@ -19,8 +19,12 @@
namespace Microsoft::ReactNative {
+using winrt::Microsoft::ReactNative::ReactPropertyBag;
+
namespace {
+using winrt::Microsoft::ReactNative::ReactPropertyId;
+
bool HasPackageIdentity() noexcept {
static const bool hasPackageIdentity = []() noexcept {
auto packageStatics = winrt::get_activation_factory(
@@ -35,6 +39,13 @@ bool HasPackageIdentity() noexcept {
return hasPackageIdentity;
}
+ReactPropertyId HttpUseMonolithicModuleProperty() noexcept {
+ static ReactPropertyId propId{
+ L"ReactNative.Http"
+ L"UseMonolithicModule"};
+ return propId;
+}
+
} // namespace
std::vector GetCoreModules(
@@ -50,11 +61,25 @@ std::vector GetCoreModules(
[props = context->Properties()]() { return Microsoft::React::CreateHttpModule(props); },
jsMessageQueue);
+ if (!ReactPropertyBag(context->Properties()).Get(HttpUseMonolithicModuleProperty())) {
+ modules.emplace_back(
+ Microsoft::React::GetBlobModuleName(),
+ [props = context->Properties()]() { return Microsoft::React::CreateBlobModule(props); },
+ batchingUIMessageQueue);
+
+ modules.emplace_back(
+ Microsoft::React::GetFileReaderModuleName(),
+ [props = context->Properties()]() { return Microsoft::React::CreateFileReaderModule(props); },
+ batchingUIMessageQueue);
+ }
+
modules.emplace_back(
"Timing",
[batchingUIMessageQueue]() { return facebook::react::CreateTimingModule(batchingUIMessageQueue); },
batchingUIMessageQueue);
+ // Note: `context` is moved to remove the reference from the current scope.
+ // This should either be the last usage of `context`, or the std::move call should happen later in this method.
modules.emplace_back(
NativeAnimatedModule::name,
[context = std::move(context)]() mutable { return std::make_unique(std::move(context)); },
diff --git a/vnext/Shared/OInstance.cpp b/vnext/Shared/OInstance.cpp
index 329e79e9693..033639f7b30 100644
--- a/vnext/Shared/OInstance.cpp
+++ b/vnext/Shared/OInstance.cpp
@@ -545,6 +545,7 @@ std::vector> InstanceImpl::GetDefaultNativeModules
std::vector> modules;
auto transitionalProps{ReactPropertyBagHelper::CreatePropertyBag()};
+#if (defined(_MSC_VER) && !defined(WINRT))
modules.push_back(std::make_unique(
m_innerInstance,
Microsoft::React::GetHttpModuleName(),
@@ -552,6 +553,7 @@ std::vector> InstanceImpl::GetDefaultNativeModules
return Microsoft::React::CreateHttpModule(transitionalProps);
},
nativeQueue));
+#endif
modules.push_back(std::make_unique(
m_innerInstance,
@@ -619,8 +621,13 @@ std::vector> InstanceImpl::GetDefaultNativeModules
[]() { return std::make_unique(); },
nativeQueue));
- // #10036 - Blob module not supported in UWP. Need to define property bag lifetime and onwership.
- if (Microsoft::React::GetRuntimeOptionBool("Blob.EnableModule")) {
+ // These modules are instantiated separately in MSRN (Universal Windows).
+ // When there are module name colisions, the last one registered is used.
+ // If this code is enabled, we will have unused module instances.
+ // Also, MSRN has a different property bag mechanism incompatible with this method's transitionalProps variable.
+#if (defined(_MSC_VER) && !defined(WINRT))
+ if (Microsoft::React::GetRuntimeOptionBool("Blob.EnableModule") &&
+ !Microsoft::React::GetRuntimeOptionBool("Http.UseMonolithicModule")) {
modules.push_back(std::make_unique(
m_innerInstance,
Microsoft::React::GetBlobModuleName(),
@@ -633,6 +640,7 @@ std::vector> InstanceImpl::GetDefaultNativeModules
[transitionalProps]() { return Microsoft::React::CreateFileReaderModule(transitionalProps); },
nativeQueue));
}
+#endif
return modules;
}