react-native-windows 0.83.0 → 0.83.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Common/unicode.cpp +36 -0
- package/Common/unicode.h +8 -0
- package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp +6 -4
- package/Microsoft.ReactNative/Fabric/Composition/TextDrawing.cpp +1 -1
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/WindowsTextLayoutManager.cpp +1 -1
- package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +3 -2
- package/Microsoft.ReactNative/ReactNativeAppBuilder.idl +3 -0
- package/Microsoft.ReactNative/Utils/LocalBundleReader.cpp +33 -25
- package/Microsoft.ReactNative/Utils/LocalBundleReader.h +5 -3
- package/Microsoft.ReactNative/Utils/UwpScriptStore.cpp +2 -2
- package/Microsoft.ReactNative/Utils/UwpScriptStore.h +3 -2
- package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems +16 -0
- package/Microsoft.ReactNative.Managed/Microsoft.ReactNative.Managed.csproj +3 -3
- package/Microsoft.ReactNative.Managed.CodeGen/Microsoft.ReactNative.Managed.CodeGen.csproj +10 -10
- package/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Debug.pubxml +1 -1
- package/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Release.pubxml +1 -1
- package/PropertySheets/Generated/PackageVersion.g.props +3 -3
- package/PropertySheets/React.Cpp.props +4 -3
- package/PropertySheets/WinUI.props +2 -2
- package/Scripts/JustMyXaml.ps1 +8 -8
- package/Scripts/UnitTest.ps1 +3 -1
- package/Scripts/creaternwapp.cmd +12 -2
- package/Scripts/creaternwlib.cmd +12 -2
- package/Scripts/rnw-dependencies.ps1 +15 -16
- package/Shared/DevSupportManager.cpp +55 -48
- package/Shared/DevSupportManager.h +0 -1
- package/Shared/Modules/IWebSocketModuleContentHandler.h +15 -0
- package/Shared/Modules/WebSocketModule.cpp +8 -3
- package/Shared/Networking/DefaultBlobResource.cpp +37 -0
- package/Shared/Networking/DefaultBlobResource.h +12 -0
- package/Shared/Networking/WinRTWebSocketResource.h +5 -1
- package/just-task.js +13 -2
- package/package.json +5 -5
- package/templates/cpp-app/windows/MyApp/MyApp.vcxproj +1 -1
- package/templates/cpp-lib/windows/MyLib/MyLib.vcxproj +1 -1
package/Common/unicode.cpp
CHANGED
|
@@ -93,6 +93,42 @@ std::wstring Utf8ToUtf16(const std::string &utf8) {
|
|
|
93
93
|
return Utf8ToUtf16(utf8.c_str(), utf8.length());
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
size_t Utf8ToUtf16Length(const char *utf8, size_t utf8Len) {
|
|
97
|
+
if (utf8Len == 0) {
|
|
98
|
+
return 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (utf8Len > static_cast<size_t>((std::numeric_limits<int>::max)())) {
|
|
102
|
+
throw std::overflow_error("Length of input string to Utf8ToUtf16Length() must fit into an int.");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const int utf8Length = static_cast<int>(utf8Len);
|
|
106
|
+
|
|
107
|
+
constexpr DWORD flags = 0;
|
|
108
|
+
|
|
109
|
+
const int utf16Length = ::MultiByteToWideChar(
|
|
110
|
+
CP_UTF8, // Source string is in UTF-8.
|
|
111
|
+
flags, // Conversion flags.
|
|
112
|
+
utf8, // Source UTF-8 string pointer.
|
|
113
|
+
utf8Length, // Length of the source UTF-8 string, in chars.
|
|
114
|
+
nullptr, // Do not convert, just request the size.
|
|
115
|
+
0 // Request size of destination buffer, in wchar_ts.
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
if (utf16Length == 0) {
|
|
119
|
+
throw UnicodeConversionException(
|
|
120
|
+
"Cannot get result string length when converting from UTF-8 to UTF-16 "
|
|
121
|
+
"(MultiByteToWideChar failed).",
|
|
122
|
+
GetLastError());
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return static_cast<size_t>(utf16Length);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
size_t Utf8ToUtf16Length(const std::string &utf8) {
|
|
129
|
+
return Utf8ToUtf16Length(utf8.c_str(), utf8.length());
|
|
130
|
+
}
|
|
131
|
+
|
|
96
132
|
#if _HAS_CXX17
|
|
97
133
|
std::wstring Utf8ToUtf16(const std::string_view &utf8) {
|
|
98
134
|
return Utf8ToUtf16(utf8.data(), utf8.length());
|
package/Common/unicode.h
CHANGED
|
@@ -55,6 +55,14 @@ class UnicodeConversionException : public std::runtime_error {
|
|
|
55
55
|
/* (4) */ std::wstring Utf8ToUtf16(const std::string_view &utf8);
|
|
56
56
|
#endif
|
|
57
57
|
|
|
58
|
+
// The following functions return the length of the UTF-16 string that would
|
|
59
|
+
// result from converting the input UTF-8 string, without actually performing
|
|
60
|
+
// the conversion or allocating a temporary std::wstring. This is useful in
|
|
61
|
+
// hot paths where only the length is needed (e.g. DirectWrite text ranges).
|
|
62
|
+
//
|
|
63
|
+
size_t Utf8ToUtf16Length(const char *utf8, size_t utf8Len);
|
|
64
|
+
size_t Utf8ToUtf16Length(const std::string &utf8);
|
|
65
|
+
|
|
58
66
|
// The following functions convert UTF-16BE strings to UTF-8 strings. Their
|
|
59
67
|
// behaviors mirror those of the above Utf8ToUtf16 functions.
|
|
60
68
|
//
|
|
@@ -153,11 +153,12 @@ facebook::react::SharedViewEventEmitter ParagraphComponentView::eventEmitterAtPo
|
|
|
153
153
|
uint32_t textPosition = metrics.textPosition;
|
|
154
154
|
|
|
155
155
|
for (auto fragment : m_attributedStringBox.getValue().getFragments()) {
|
|
156
|
-
|
|
156
|
+
uint32_t utf16Length = static_cast<uint32_t>(::Microsoft::Common::Unicode::Utf8ToUtf16Length(fragment.string));
|
|
157
|
+
if (textPosition < utf16Length) {
|
|
157
158
|
return std::static_pointer_cast<const facebook::react::ViewEventEmitter>(
|
|
158
159
|
fragment.parentShadowView.eventEmitter);
|
|
159
160
|
}
|
|
160
|
-
textPosition -=
|
|
161
|
+
textPosition -= utf16Length;
|
|
161
162
|
}
|
|
162
163
|
}
|
|
163
164
|
}
|
|
@@ -210,10 +211,11 @@ bool ParagraphComponentView::IsTextSelectableAtPoint(facebook::react::Point pt)
|
|
|
210
211
|
|
|
211
212
|
// Finds which fragment contains this text position
|
|
212
213
|
for (auto fragment : m_attributedStringBox.getValue().getFragments()) {
|
|
213
|
-
|
|
214
|
+
uint32_t utf16Length = static_cast<uint32_t>(::Microsoft::Common::Unicode::Utf8ToUtf16Length(fragment.string));
|
|
215
|
+
if (textPosition < utf16Length) {
|
|
214
216
|
return true;
|
|
215
217
|
}
|
|
216
|
-
textPosition -=
|
|
218
|
+
textPosition -= utf16Length;
|
|
217
219
|
}
|
|
218
220
|
}
|
|
219
221
|
}
|
|
@@ -66,7 +66,7 @@ void RenderText(
|
|
|
66
66
|
unsigned int position = 0;
|
|
67
67
|
unsigned int length = 0;
|
|
68
68
|
for (auto fragment : attributedString.getFragments()) {
|
|
69
|
-
length = static_cast<UINT32>(fragment.string
|
|
69
|
+
length = static_cast<UINT32>(::Microsoft::Common::Unicode::Utf8ToUtf16Length(fragment.string));
|
|
70
70
|
DWRITE_TEXT_RANGE range = {position, length};
|
|
71
71
|
if (fragment.textAttributes.foregroundColor &&
|
|
72
72
|
(fragment.textAttributes.foregroundColor != textAttributes.foregroundColor) ||
|
|
@@ -267,7 +267,7 @@ void WindowsTextLayoutManager::GetTextLayout(
|
|
|
267
267
|
attachments.push_back(attachment);
|
|
268
268
|
position += 1;
|
|
269
269
|
} else {
|
|
270
|
-
unsigned int length = static_cast<UINT32>(fragment.string
|
|
270
|
+
unsigned int length = static_cast<UINT32>(Microsoft::Common::Unicode::Utf8ToUtf16Length(fragment.string));
|
|
271
271
|
DWRITE_TEXT_RANGE range = {position, length};
|
|
272
272
|
TextAttributes attributes = fragment.textAttributes;
|
|
273
273
|
DWRITE_FONT_STYLE fragmentStyle = DWRITE_FONT_STYLE_NORMAL;
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<ProjectName>Microsoft.ReactNative</ProjectName>
|
|
11
11
|
<RootNamespace>Microsoft.ReactNative</RootNamespace>
|
|
12
12
|
<DefaultLanguage>en-US</DefaultLanguage>
|
|
13
|
-
<MinimumVisualStudioVersion>
|
|
13
|
+
<MinimumVisualStudioVersion>18.0</MinimumVisualStudioVersion>
|
|
14
14
|
<AppContainerApplication>true</AppContainerApplication>
|
|
15
15
|
<ApplicationType>Windows Store</ApplicationType>
|
|
16
16
|
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
|
@@ -96,7 +96,8 @@
|
|
|
96
96
|
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
|
97
97
|
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
|
98
98
|
<WarningLevel>Level4</WarningLevel>
|
|
99
|
-
<AdditionalOptions
|
|
99
|
+
<AdditionalOptions>%(AdditionalOptions) /bigobj /ZH:SHA_256</AdditionalOptions>
|
|
100
|
+
<AdditionalOptions Condition="$(PlatformToolsetVersion)<145">%(AdditionalOptions) /await</AdditionalOptions>
|
|
100
101
|
<AdditionalIncludeDirectories>
|
|
101
102
|
$(FmtDir)\include;
|
|
102
103
|
$(ReactNativeWindowsDir)Microsoft.ReactNative;
|
|
@@ -3,6 +3,7 @@ import "ReactNativeHost.idl";
|
|
|
3
3
|
import "ReactNativeIsland.idl";
|
|
4
4
|
import "ReactInstanceSettings.idl";
|
|
5
5
|
import "IReactPackageProvider.idl";
|
|
6
|
+
import "ReactNativeWindow.idl";
|
|
6
7
|
|
|
7
8
|
#include "DocString.h"
|
|
8
9
|
|
|
@@ -14,6 +15,8 @@ namespace Microsoft.ReactNative {
|
|
|
14
15
|
// Properties
|
|
15
16
|
Microsoft.UI.Windowing.AppWindow AppWindow {get;};
|
|
16
17
|
|
|
18
|
+
ReactNativeWindow ReactNativeWindow {get;};
|
|
19
|
+
|
|
17
20
|
ReactNativeHost ReactNativeHost {get;};
|
|
18
21
|
|
|
19
22
|
ReactViewOptions ReactViewOptions {get;};
|
|
@@ -54,7 +54,29 @@ std::string GetBundleFromEmbeddedResource(const winrt::Windows::Foundation::Uri
|
|
|
54
54
|
return std::string(start, start + size);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
namespace {
|
|
58
|
+
|
|
59
|
+
std::string BufferToString(const winrt::Windows::Storage::Streams::IBuffer &buffer) {
|
|
60
|
+
std::string result(buffer.Length(), '\0');
|
|
61
|
+
if (!result.empty()) {
|
|
62
|
+
auto reader = winrt::Windows::Storage::Streams::DataReader::FromBuffer(buffer);
|
|
63
|
+
reader.ReadBytes(winrt::array_view<uint8_t>{
|
|
64
|
+
reinterpret_cast<uint8_t *>(&result[0]), reinterpret_cast<uint8_t *>(&result[result.length()])});
|
|
65
|
+
}
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
winrt::Windows::Storage::Streams::IBuffer BytesToBuffer(const void *data, uint32_t size) {
|
|
70
|
+
winrt::Windows::Storage::Streams::DataWriter writer;
|
|
71
|
+
auto bytes = static_cast<const uint8_t *>(data);
|
|
72
|
+
writer.WriteBytes(winrt::array_view<const uint8_t>(bytes, bytes + size));
|
|
73
|
+
return writer.DetachBuffer();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
} // namespace
|
|
77
|
+
|
|
78
|
+
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::Streams::IBuffer>
|
|
79
|
+
LocalBundleReader::LoadBundleAsync(const std::wstring bundleUri) {
|
|
58
80
|
try {
|
|
59
81
|
co_await winrt::resume_background();
|
|
60
82
|
|
|
@@ -66,41 +88,26 @@ std::future<std::string> LocalBundleReader::LoadBundleAsync(const std::wstring b
|
|
|
66
88
|
file = co_await winrt::Windows::Storage::StorageFile::GetFileFromApplicationUriAsync(uri);
|
|
67
89
|
} else if (bundleUri.starts_with(L"resource://")) {
|
|
68
90
|
winrt::Windows::Foundation::Uri uri(bundleUri);
|
|
69
|
-
|
|
91
|
+
auto bytes = GetBundleFromEmbeddedResource(uri);
|
|
92
|
+
co_return BytesToBuffer(bytes.data(), static_cast<uint32_t>(bytes.size()));
|
|
70
93
|
} else {
|
|
71
94
|
file = co_await winrt::Windows::Storage::StorageFile::GetFileFromPathAsync(bundleUri);
|
|
72
95
|
}
|
|
73
96
|
|
|
74
|
-
|
|
75
|
-
// roundtrip.
|
|
76
|
-
auto fileBuffer{co_await winrt::Windows::Storage::FileIO::ReadBufferAsync(file)};
|
|
77
|
-
auto dataReader{winrt::Windows::Storage::Streams::DataReader::FromBuffer(fileBuffer)};
|
|
78
|
-
|
|
79
|
-
// No need to use length + 1, STL guarantees that string storage is null-terminated.
|
|
80
|
-
std::string script(fileBuffer.Length(), '\0');
|
|
81
|
-
|
|
82
|
-
// Construct the array_view to slice into the first fileBuffer.Length bytes.
|
|
83
|
-
// DataReader.ReadBytes will read as many bytes as are present in the
|
|
84
|
-
// array_view. The backing string has fileBuffer.Length() + 1 bytes, without
|
|
85
|
-
// an explicit end it will read 1 byte to many and throw.
|
|
86
|
-
dataReader.ReadBytes(winrt::array_view<uint8_t>{
|
|
87
|
-
reinterpret_cast<uint8_t *>(&script[0]), reinterpret_cast<uint8_t *>(&script[script.length()])});
|
|
88
|
-
dataReader.Close();
|
|
89
|
-
|
|
90
|
-
co_return script;
|
|
97
|
+
co_return co_await winrt::Windows::Storage::FileIO::ReadBufferAsync(file);
|
|
91
98
|
}
|
|
92
99
|
// RuntimeScheduler only handles std::exception or jsi::JSError
|
|
93
|
-
catch (winrt::hresult_error const &
|
|
94
|
-
throw
|
|
100
|
+
catch (winrt::hresult_error const &) {
|
|
101
|
+
throw;
|
|
95
102
|
}
|
|
96
103
|
}
|
|
97
104
|
|
|
98
105
|
std::string LocalBundleReader::LoadBundle(const std::wstring &bundlePath) {
|
|
99
|
-
return LoadBundleAsync(bundlePath).get();
|
|
106
|
+
return BufferToString(LoadBundleAsync(bundlePath).get());
|
|
100
107
|
}
|
|
101
108
|
|
|
102
109
|
StorageFileBigString::StorageFileBigString(const std::wstring &path) {
|
|
103
|
-
|
|
110
|
+
m_pendingLoad = LocalBundleReader::LoadBundleAsync(path);
|
|
104
111
|
}
|
|
105
112
|
|
|
106
113
|
bool StorageFileBigString::isAscii() const {
|
|
@@ -118,8 +125,9 @@ size_t StorageFileBigString::size() const {
|
|
|
118
125
|
}
|
|
119
126
|
|
|
120
127
|
void StorageFileBigString::ensure() const {
|
|
121
|
-
if (
|
|
122
|
-
m_string =
|
|
128
|
+
if (m_pendingLoad) {
|
|
129
|
+
m_string = BufferToString(m_pendingLoad.get());
|
|
130
|
+
m_pendingLoad = nullptr;
|
|
123
131
|
}
|
|
124
132
|
}
|
|
125
133
|
|
|
@@ -3,14 +3,16 @@
|
|
|
3
3
|
|
|
4
4
|
#pragma once
|
|
5
5
|
#include <cxxreact/JSBigString.h>
|
|
6
|
-
#include <
|
|
6
|
+
#include <winrt/Windows.Foundation.h>
|
|
7
|
+
#include <winrt/Windows.Storage.Streams.h>
|
|
7
8
|
#include <string>
|
|
8
9
|
|
|
9
10
|
namespace Microsoft::ReactNative {
|
|
10
11
|
|
|
11
12
|
class LocalBundleReader {
|
|
12
13
|
public:
|
|
13
|
-
static
|
|
14
|
+
static winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::Streams::IBuffer> LoadBundleAsync(
|
|
15
|
+
const std::wstring bundlePath);
|
|
14
16
|
static std::string LoadBundle(const std::wstring &bundlePath);
|
|
15
17
|
};
|
|
16
18
|
|
|
@@ -24,7 +26,7 @@ class StorageFileBigString : public facebook::react::JSBigString {
|
|
|
24
26
|
void ensure() const;
|
|
25
27
|
|
|
26
28
|
private:
|
|
27
|
-
mutable
|
|
29
|
+
mutable winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::Streams::IBuffer> m_pendingLoad;
|
|
28
30
|
mutable std::string m_string;
|
|
29
31
|
};
|
|
30
32
|
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
#include <winrt/Windows.Foundation.h>
|
|
5
5
|
#include <winrt/Windows.Storage.FileProperties.h>
|
|
6
6
|
#include <winrt/Windows.Storage.h>
|
|
7
|
-
#include <future>
|
|
8
7
|
#include "Unicode.h"
|
|
9
8
|
|
|
10
9
|
namespace winrt {
|
|
@@ -43,7 +42,8 @@ facebook::jsi::ScriptVersion_t UwpScriptStore::getScriptVersion(const std::strin
|
|
|
43
42
|
return version;
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
|
|
45
|
+
winrt::Windows::Foundation::IAsyncOperation<facebook::jsi::ScriptVersion_t> UwpScriptStore::getScriptVersionAsync(
|
|
46
|
+
const std::string &bundleUri) {
|
|
47
47
|
co_await winrt::resume_background();
|
|
48
48
|
|
|
49
49
|
const winrt::hstring fileUrl(Microsoft::Common::Unicode::Utf8ToUtf16("ms-appx:///Bundle/" + bundleUri + ".bundle"));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
#include <JSI/ScriptStore.h>
|
|
3
|
-
#include <
|
|
3
|
+
#include <winrt/Windows.Foundation.h>
|
|
4
4
|
|
|
5
5
|
namespace Microsoft::ReactNative {
|
|
6
6
|
|
|
@@ -16,7 +16,8 @@ class UwpScriptStore : public facebook::jsi::ScriptStore {
|
|
|
16
16
|
static facebook::jsi::ScriptVersion_t GetFileVersion(const std::wstring &filePath);
|
|
17
17
|
|
|
18
18
|
private:
|
|
19
|
-
|
|
19
|
+
winrt::Windows::Foundation::IAsyncOperation<facebook::jsi::ScriptVersion_t> getScriptVersionAsync(
|
|
20
|
+
const std::string &bundleUri);
|
|
20
21
|
};
|
|
21
22
|
|
|
22
23
|
} // namespace Microsoft::ReactNative
|
|
@@ -158,6 +158,22 @@
|
|
|
158
158
|
</ClCompile>
|
|
159
159
|
<ClCompile Include="$(NodeApiJsiSrcDir)NodeApiJsiRuntime.cpp">
|
|
160
160
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
|
161
|
+
<!--
|
|
162
|
+
Workaround for a Visual Studio 2026 (v145) C++ optimizer bug. With
|
|
163
|
+
optimizations on, this translation unit is miscompiled such that the
|
|
164
|
+
pointer-value-scope teardown in NodeApiJsiRuntime hands Hermes a stale
|
|
165
|
+
napi_value, crashing in hermes!JSProxy::defineOwnProperty (via
|
|
166
|
+
napi_create_reference) during rapid UI updates - e.g. the
|
|
167
|
+
e2e-test-app-fabric visitAllPages test. Building this file without
|
|
168
|
+
optimization (verified equivalent to `#pragma optimize("", off)`)
|
|
169
|
+
avoids it. We must also opt out of /GL here so the disabled
|
|
170
|
+
optimization survives link-time code generation. NodeApiJsiRuntime.cpp
|
|
171
|
+
is externally provided, so the workaround lives here rather than in the
|
|
172
|
+
source. Scoped to v145+ (the bug does not reproduce on v143); remove
|
|
173
|
+
when the compiler bug is fixed.
|
|
174
|
+
-->
|
|
175
|
+
<Optimization Condition="$(PlatformToolsetVersion)>=145">Disabled</Optimization>
|
|
176
|
+
<WholeProgramOptimization Condition="$(PlatformToolsetVersion)>=145">false</WholeProgramOptimization>
|
|
161
177
|
</ClCompile>
|
|
162
178
|
</ItemGroup>
|
|
163
179
|
<ItemGroup Condition="'$(BuildMSRNCxxNodeApiJsiLoader)' != 'false'">
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
|
16
16
|
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.22621.0</TargetPlatformVersion>
|
|
17
17
|
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
|
18
|
-
<MinimumVisualStudioVersion>
|
|
18
|
+
<MinimumVisualStudioVersion>18.0</MinimumVisualStudioVersion>
|
|
19
19
|
<FileAlignment>512</FileAlignment>
|
|
20
20
|
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
|
21
21
|
<DocumentationFile>bin\$(Platform)\$(Configuration)\Microsoft.ReactNative.Managed.XML</DocumentationFile>
|
|
@@ -150,8 +150,8 @@
|
|
|
150
150
|
</ItemGroup>
|
|
151
151
|
</When>
|
|
152
152
|
</Choose>
|
|
153
|
-
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '
|
|
154
|
-
<VisualStudioVersion>
|
|
153
|
+
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '18.0' ">
|
|
154
|
+
<VisualStudioVersion>18.0</VisualStudioVersion>
|
|
155
155
|
</PropertyGroup>
|
|
156
156
|
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
|
|
157
157
|
<Target Name="Deploy" />
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<PropertyGroup>
|
|
4
4
|
<OutputType>Exe</OutputType>
|
|
5
5
|
|
|
6
|
-
<TargetFramework>
|
|
6
|
+
<TargetFramework>net10.0</TargetFramework>
|
|
7
7
|
<Platforms>x64;x86;ARM64</Platforms>
|
|
8
8
|
<RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>
|
|
9
9
|
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.3.1" />
|
|
32
32
|
<PackageReference Include="RuntimeContracts" Version="0.3.0" />
|
|
33
33
|
|
|
34
|
-
<!--
|
|
35
|
-
NuGet decides to pull in packages with issues. There is no seeming way to diagnose why NuGet is pulling in those versions.
|
|
34
|
+
<!--
|
|
35
|
+
NuGet decides to pull in packages with issues. There is no seeming way to diagnose why NuGet is pulling in those versions.
|
|
36
36
|
Running restore with -Verbosity Detailed and environment variables:
|
|
37
37
|
* NUGET_RESTORE_MSBUILD_ARGS=/bl:c:\temp\nuget.binlog
|
|
38
38
|
* NUGET_RESTORE_MSBUILD_VERBOSITY=diag
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
<PackageReference Include="System.Private.Uri" Version="4.3.2" />
|
|
43
43
|
</ItemGroup>
|
|
44
44
|
|
|
45
|
-
<!--
|
|
45
|
+
<!--
|
|
46
46
|
This target is used to ensure the tool is deployed and can be used from source.
|
|
47
47
|
It will return all deployed files so the caller can implement incrementality properly
|
|
48
48
|
-->
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
</ItemGroup>
|
|
54
54
|
</Target>
|
|
55
55
|
|
|
56
|
-
<!--
|
|
56
|
+
<!--
|
|
57
57
|
This target returns the location of the deployed executable.
|
|
58
58
|
-->
|
|
59
59
|
<Target Name="GetPublishedToolPath" DependsOnTargets="PublishTool" Returns="@(_PublishedToolExecutable)">
|
|
@@ -62,13 +62,13 @@
|
|
|
62
62
|
</ItemGroup>
|
|
63
63
|
</Target>
|
|
64
64
|
|
|
65
|
-
<!--
|
|
65
|
+
<!--
|
|
66
66
|
This is used during the PR build to ensure we have the artifacts published during the build.
|
|
67
67
|
-->
|
|
68
|
-
<Target
|
|
69
|
-
Name="PublishToolDuringBuild"
|
|
70
|
-
DependsOnTargets="Publish"
|
|
71
|
-
AfterTargets="Build"
|
|
68
|
+
<Target
|
|
69
|
+
Name="PublishToolDuringBuild"
|
|
70
|
+
DependsOnTargets="Publish"
|
|
71
|
+
AfterTargets="Build"
|
|
72
72
|
Condition="'$(PublishToolDuringBuild)' == 'true'">
|
|
73
73
|
</Target>
|
|
74
74
|
|
package/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Debug.pubxml
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<PublishProtocol>FileSystem</PublishProtocol>
|
|
7
7
|
<Configuration>Debug</Configuration>
|
|
8
8
|
<Platform>x64</Platform>
|
|
9
|
-
<TargetFramework>
|
|
9
|
+
<TargetFramework>net10.0</TargetFramework>
|
|
10
10
|
<PublishDir>$(OutDir)publish</PublishDir>
|
|
11
11
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
|
12
12
|
<SelfContained>true</SelfContained>
|
package/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Release.pubxml
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<PublishProtocol>FileSystem</PublishProtocol>
|
|
7
7
|
<Configuration>Release</Configuration>
|
|
8
8
|
<Platform>x64</Platform>
|
|
9
|
-
<TargetFramework>
|
|
9
|
+
<TargetFramework>net10.0</TargetFramework>
|
|
10
10
|
<PublishDir>$(OutDir)publish</PublishDir>
|
|
11
11
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
|
12
12
|
<SelfContained>true</SelfContained>
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
-->
|
|
11
11
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
12
12
|
<PropertyGroup>
|
|
13
|
-
<ReactNativeWindowsVersion>0.83.
|
|
13
|
+
<ReactNativeWindowsVersion>0.83.2</ReactNativeWindowsVersion>
|
|
14
14
|
<ReactNativeWindowsMajor>0</ReactNativeWindowsMajor>
|
|
15
15
|
<ReactNativeWindowsMinor>83</ReactNativeWindowsMinor>
|
|
16
|
-
<ReactNativeWindowsPatch>
|
|
16
|
+
<ReactNativeWindowsPatch>2</ReactNativeWindowsPatch>
|
|
17
17
|
<ReactNativeWindowsCanary>false</ReactNativeWindowsCanary>
|
|
18
|
-
<ReactNativeWindowsCommitId>
|
|
18
|
+
<ReactNativeWindowsCommitId>83f78a8cf0b1226d7a9b78a1b18538e91cfd82c2</ReactNativeWindowsCommitId>
|
|
19
19
|
</PropertyGroup>
|
|
20
20
|
</Project>
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
|
|
44
44
|
<PropertyGroup Label="ExternalDependencies">
|
|
45
45
|
<!-- Google Test Adapter -->
|
|
46
|
-
<!--
|
|
47
|
-
<Force-Enable-Microsoft-googletest-v140-windesktop-msvcstl-static-rt-dyn>
|
|
46
|
+
<!-- If ApplicationType is set, adapter include paths won't be set for MSVC 14.0 (v140) or later -->
|
|
47
|
+
<Force-Enable-Microsoft-googletest-v140-windesktop-msvcstl-static-rt-dyn>true</Force-Enable-Microsoft-googletest-v140-windesktop-msvcstl-static-rt-dyn>
|
|
48
48
|
</PropertyGroup>
|
|
49
49
|
|
|
50
50
|
<!--
|
|
@@ -136,7 +136,8 @@
|
|
|
136
136
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
|
137
137
|
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
|
138
138
|
<ShowIncludes Condition="'$(ShowIncludes)'=='true'">true</ShowIncludes>
|
|
139
|
-
<AdditionalOptions>/utf-8 %(AdditionalOptions)
|
|
139
|
+
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
|
140
|
+
<AdditionalOptions Condition="$(PlatformToolsetVersion)<145">%(AdditionalOptions) /await</AdditionalOptions>
|
|
140
141
|
<ControlFlowGuard>Guard</ControlFlowGuard>
|
|
141
142
|
<SpectreMitigation>Spectre</SpectreMitigation>
|
|
142
143
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
3
3
|
<PropertyGroup Label="WinUI3 versioning">
|
|
4
4
|
|
|
5
|
-
<!--
|
|
5
|
+
<!--
|
|
6
6
|
Internal versions are typically only located at: https://microsoft.visualstudio.com/DefaultCollection/ProjectReunion/_artifacts/feed/Project.Reunion.nuget.internal/NuGet/Microsoft.WindowsAppSDK/versions
|
|
7
7
|
For local testing of internal versions, modify WinUI3ExperimentalVersion, and comment out the additional nuget source in NuGet.Config
|
|
8
8
|
When this version is updated, be sure to update the default for the enableInternalFeed parameter of /.ado/templates/enable-experimental-winui3.yml
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<WinUI3ExperimentalVersion Condition="'$(WinUI3ExperimentalVersion)'==''">2.0.0-experimental3</WinUI3ExperimentalVersion>
|
|
11
11
|
<!-- This value is also used by the CLI, see /packages/@react-native-windows/cli/.../autolinkWindows.ts -->
|
|
12
12
|
<WinUI3Version Condition="'$(WinUI3Version)'=='' AND '$(UseExperimentalWinUI3)'=='true'">$(WinUI3ExperimentalVersion)</WinUI3Version>
|
|
13
|
-
<WinUI3Version Condition="'$(WinUI3Version)'==''">1.8.
|
|
13
|
+
<WinUI3Version Condition="'$(WinUI3Version)'==''">1.8.260508005</WinUI3Version>
|
|
14
14
|
<!-- This is needed to prevent build errors with WinAppSDK >= 1.7 trying to double build WindowsAppRuntimeAutoInitializer.cpp -->
|
|
15
15
|
<WindowsAppSdkAutoInitialize Condition="'$(WindowsAppSdkAutoInitialize)'=='' And $([MSBuild]::VersionGreaterThan('$(WinUI3Version)', '1.7.0'))">false</WindowsAppSdkAutoInitialize>
|
|
16
16
|
</PropertyGroup>
|
package/Scripts/JustMyXaml.ps1
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# This script enables or disables VS
|
|
1
|
+
# This script enables or disables VS 2026's JustMyXaml feature
|
|
2
2
|
[CmdletBinding()]
|
|
3
3
|
param([bool]$Enable)
|
|
4
4
|
|
|
@@ -7,14 +7,14 @@ if (!([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
$instanceId = & "$(${env:ProgramFiles(x86)})\Microsoft Visual Studio\Installer\vswhere.exe" -property instanceId
|
|
10
|
-
$hiveFile = "$($env:LocalAppData)\Microsoft\VisualStudio\
|
|
11
|
-
& reg.exe load HKLM\
|
|
12
|
-
New-PSDrive -Name
|
|
13
|
-
$currentValue = (Get-ItemProperty
|
|
10
|
+
$hiveFile = "$($env:LocalAppData)\Microsoft\VisualStudio\18.0_$instanceId\privateregistry.bin"
|
|
11
|
+
& reg.exe load HKLM\VS2026_HIVE $hiveFile | Out-Null
|
|
12
|
+
New-PSDrive -Name VS2026 -PSProvider Registry -Root HKLM\VS2026_HIVE -ErrorAction Stop | Out-Null
|
|
13
|
+
$currentValue = (Get-ItemProperty VS2026:\Software\Microsoft\VisualStudio\18.0_$instanceId\Debugger -Name EnableXamlVisualDiagnosticsJustMyXaml).EnableXamlVisualDiagnosticsJustMyXaml
|
|
14
14
|
if ($currentValue -eq 0) { $currentValue = $false; } else { $currentValue = $true; }
|
|
15
15
|
Write-Host "Current value: $currentValue"
|
|
16
16
|
if ($Enable) { $newValue = 1; } else { $newValue = 0; }
|
|
17
|
-
Set-ItemProperty
|
|
17
|
+
Set-ItemProperty VS2026:\Software\Microsoft\VisualStudio\18.0_$instanceId\Debugger -Name EnableXamlVisualDiagnosticsJustMyXaml -Value $newValue -Type DWord
|
|
18
18
|
Write-Host "New value: $Enable"
|
|
19
|
-
Remove-PSDrive -Name
|
|
20
|
-
& reg.exe unload HKLM\
|
|
19
|
+
Remove-PSDrive -Name VS2026
|
|
20
|
+
& reg.exe unload HKLM\VS2026_HIVE | Out-Null
|
package/Scripts/UnitTest.ps1
CHANGED
|
@@ -23,7 +23,9 @@ param (
|
|
|
23
23
|
"ReactCommon.UnitTests\ReactCommon.UnitTests.exe")
|
|
24
24
|
),
|
|
25
25
|
|
|
26
|
-
[System.IO.FileInfo] $VsTest =
|
|
26
|
+
[System.IO.FileInfo] $VsTest =
|
|
27
|
+
"$(& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath)\" +
|
|
28
|
+
"Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe"
|
|
27
29
|
)
|
|
28
30
|
|
|
29
31
|
if ($Include.Count) {
|
package/Scripts/creaternwapp.cmd
CHANGED
|
@@ -103,7 +103,7 @@ if "%R_VERSION%"=="" (
|
|
|
103
103
|
for /f "delims=" %%a in ('npm show react-native-windows@%RNW_VERSION% devDependencies.react') do @set R_VERSION=%%a
|
|
104
104
|
)
|
|
105
105
|
|
|
106
|
-
@echo creaternwapp.cmd Determining concrete versions for react@%R_VERSION%, react-native@%RN_VERSION%, @react-native-community/cli@%RNCLI_VERSION%, and react-native-windows@%RNW_VERSION%
|
|
106
|
+
@echo creaternwapp.cmd Determining concrete versions for react@%R_VERSION%, react-native@%RN_VERSION%, @react-native-community/cli@%RNCLI_VERSION%, and react-native-windows@%RNW_VERSION%
|
|
107
107
|
for /f "delims=" %%a in ('npm show react-native-windows@%RNW_VERSION% version') do @set RNW_VERSION=%%a
|
|
108
108
|
for /f "delims=" %%a in ('npm show react-native@%RN_VERSION% version') do @set RN_VERSION=%%a
|
|
109
109
|
for /f "delims=" %%a in ('npm show @react-native-community/cli@%RNCLI_VERSION% version') do @set RNCLI_VERSION=%%a
|
|
@@ -178,10 +178,20 @@ call git commit -m "add rnw dependency"
|
|
|
178
178
|
@echo creaternwapp.cmd Running init-windows with: npx --yes @react-native-community/cli@%RNCLI_VERSION% init-windows --template %RNW_TEMPLATE_TYPE% --overwrite --logging
|
|
179
179
|
call npx --yes @react-native-community/cli@%RNCLI_VERSION% init-windows --template %RNW_TEMPLATE_TYPE% --overwrite --logging
|
|
180
180
|
|
|
181
|
+
if %ERRORLEVEL% neq 0 (
|
|
182
|
+
@echo creaternwapp.cmd init-windows command not available from react-native CLI, falling back to react-native-windows-init
|
|
183
|
+
call npx --yes react-native-windows-init@%RNW_VERSION% --template %RNW_TEMPLATE_TYPE% --overwrite --logging
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
if %ERRORLEVEL% neq 0 (
|
|
187
|
+
@echo creaternwapp.cmd: Unable to initialize Windows project
|
|
188
|
+
exit /b %ERRORLEVEL%
|
|
189
|
+
)
|
|
190
|
+
|
|
181
191
|
@echo creaternwapp.cmd Done, see new %RNW_TEMPLATE_TYPE% project in %CD% with react@%R_VERSION%, react-native@%RN_VERSION%, and react-native-windows@%RNW_VERSION%
|
|
182
192
|
|
|
183
193
|
popd
|
|
184
194
|
|
|
185
195
|
endlocal
|
|
186
196
|
|
|
187
|
-
exit /b %ERRORLEVEL%
|
|
197
|
+
exit /b %ERRORLEVEL%
|
package/Scripts/creaternwlib.cmd
CHANGED
|
@@ -108,7 +108,7 @@ if "%R_VERSION%"=="" (
|
|
|
108
108
|
for /f "delims=" %%a in ('npm show react-native-windows@%RNW_VERSION% devDependencies.react') do @set R_VERSION=%%a
|
|
109
109
|
)
|
|
110
110
|
|
|
111
|
-
@echo creaternwlib.cmd Determining concrete versions for react@%R_VERSION%, react-native@%RN_VERSION%, and react-native-windows@%RNW_VERSION%
|
|
111
|
+
@echo creaternwlib.cmd Determining concrete versions for react@%R_VERSION%, react-native@%RN_VERSION%, and react-native-windows@%RNW_VERSION%
|
|
112
112
|
for /f "delims=" %%a in ('npm show react-native-windows@%RNW_VERSION% version') do @set RNW_VERSION=%%a
|
|
113
113
|
for /f "delims=" %%a in ('npm show react-native@%RN_VERSION% version') do @set RN_VERSION=%%a
|
|
114
114
|
for /f "delims=" %%a in ('npm show @react-native-community/cli@%RNCLI_VERSION% version') do @set RNCLI_VERSION=%%a
|
|
@@ -167,10 +167,20 @@ call git commit -m "chore: add rnw dependency"
|
|
|
167
167
|
@echo creaternwlib.cmd Running init-windows with: yarn react-native init-windows --template %RNW_TEMPLATE_TYPE% --overwrite --logging
|
|
168
168
|
call yarn react-native init-windows --template %RNW_TEMPLATE_TYPE% --overwrite --logging
|
|
169
169
|
|
|
170
|
+
if %ERRORLEVEL% neq 0 (
|
|
171
|
+
@echo creaternwlib.cmd init-windows command not available from react-native CLI, falling back to react-native-windows-init
|
|
172
|
+
call npx --yes react-native-windows-init@%RNW_VERSION% --template %RNW_TEMPLATE_TYPE% --overwrite --logging
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
if %ERRORLEVEL% neq 0 (
|
|
176
|
+
@echo creaternwlib.cmd: Unable to initialize Windows project
|
|
177
|
+
exit /b %ERRORLEVEL%
|
|
178
|
+
)
|
|
179
|
+
|
|
170
180
|
@echo creaternwlib.cmd Done, see new %RNW_TEMPLATE_TYPE% project in %CD% with react@%R_VERSION%, react-native@%RN_VERSION%, and react-native-windows@%RNW_VERSION%
|
|
171
181
|
|
|
172
182
|
popd
|
|
173
183
|
|
|
174
184
|
endlocal
|
|
175
185
|
|
|
176
|
-
exit /b %ERRORLEVEL%
|
|
186
|
+
exit /b %ERRORLEVEL%
|
|
@@ -8,7 +8,7 @@ param(
|
|
|
8
8
|
[string]$Check = [CheckId]::All,
|
|
9
9
|
|
|
10
10
|
[Parameter(ValueFromRemainingArguments)]
|
|
11
|
-
[ValidateSet('appDev', 'rnwDev', 'buildLab', '
|
|
11
|
+
[ValidateSet('appDev', 'rnwDev', 'buildLab', 'vs2026', 'clone')]
|
|
12
12
|
[String[]]$Tags = @('appDev'),
|
|
13
13
|
[switch]$Enterprise = $false
|
|
14
14
|
)
|
|
@@ -94,7 +94,6 @@ $vsComponents = @('Microsoft.Component.MSBuild',
|
|
|
94
94
|
$vcToolsComponent,
|
|
95
95
|
'Microsoft.VisualStudio.ComponentGroup.UWP.Support',
|
|
96
96
|
'Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core',
|
|
97
|
-
'Microsoft.VisualStudio.Component.Windows10SDK.19041',
|
|
98
97
|
'Microsoft.VisualStudio.Component.Windows11SDK.22621');
|
|
99
98
|
|
|
100
99
|
# UWP.VC is not needed to build the projects with msbuild, but the VS IDE requires it.
|
|
@@ -113,12 +112,12 @@ $wingetver = "1.7.11261";
|
|
|
113
112
|
|
|
114
113
|
# The minimum VS version to check for
|
|
115
114
|
# Note: For install to work, whatever min version you specify here must be met by the current package available on winget.
|
|
116
|
-
$vsver = "
|
|
115
|
+
$vsver = "18.6.1";
|
|
117
116
|
|
|
118
117
|
# The exact .NET SDK version to check for
|
|
119
|
-
$dotnetver = "
|
|
118
|
+
$dotnetver = "10.0";
|
|
120
119
|
# Version name of the winget package
|
|
121
|
-
$wingetDotNetVer = "
|
|
120
|
+
$wingetDotNetVer = "10";
|
|
122
121
|
|
|
123
122
|
$v = [System.Environment]::OSVersion.Version;
|
|
124
123
|
if ($env:Agent_BuildDirectory) {
|
|
@@ -242,9 +241,9 @@ function InstallVS {
|
|
|
242
241
|
|
|
243
242
|
if ($Enterprise) {
|
|
244
243
|
# The CI machines need the enterprise version of VS as that is what is hardcoded in all the scripts
|
|
245
|
-
WinGetInstall Microsoft.VisualStudio.
|
|
244
|
+
WinGetInstall Microsoft.VisualStudio.Enterprise
|
|
246
245
|
} else {
|
|
247
|
-
WinGetInstall Microsoft.VisualStudio.
|
|
246
|
+
WinGetInstall Microsoft.VisualStudio.Community
|
|
248
247
|
}
|
|
249
248
|
|
|
250
249
|
$vsWhere = Get-VSWhere;
|
|
@@ -458,8 +457,8 @@ $requirements = @(
|
|
|
458
457
|
},
|
|
459
458
|
@{
|
|
460
459
|
Id=[CheckId]::VSUWP;
|
|
461
|
-
Name = "Visual Studio
|
|
462
|
-
Tags = @('appDev', '
|
|
460
|
+
Name = "Visual Studio 2026 (>= $vsver) & req. components";
|
|
461
|
+
Tags = @('appDev', 'vs2026');
|
|
463
462
|
Valid = { CheckVS; }
|
|
464
463
|
Install = { InstallVS };
|
|
465
464
|
HasVerboseOutput = $true;
|
|
@@ -491,7 +490,7 @@ $requirements = @(
|
|
|
491
490
|
$downloadPath = "$env:TEMP\WindowsApplicationDriver.msi"
|
|
492
491
|
Write-Verbose "Downloading WinAppDriver from $url";
|
|
493
492
|
Invoke-WebRequest -UseBasicParsing $url -OutFile $downloadPath
|
|
494
|
-
|
|
493
|
+
|
|
495
494
|
# SDL Compliance: Verify signature (Work Item 58386093)
|
|
496
495
|
$signature = Get-AuthenticodeSignature $downloadPath
|
|
497
496
|
if ($signature.Status -ne "Valid") {
|
|
@@ -499,10 +498,10 @@ $requirements = @(
|
|
|
499
498
|
throw "WinAppDriver signature verification failed"
|
|
500
499
|
}
|
|
501
500
|
if ($signature.SignerCertificate.Subject -notlike "*Microsoft*") {
|
|
502
|
-
Remove-Item $downloadPath -ErrorAction SilentlyContinue
|
|
501
|
+
Remove-Item $downloadPath -ErrorAction SilentlyContinue
|
|
503
502
|
throw "WinAppDriver not signed by Microsoft"
|
|
504
503
|
}
|
|
505
|
-
|
|
504
|
+
|
|
506
505
|
& $downloadPath /q
|
|
507
506
|
Remove-Item $downloadPath -ErrorAction SilentlyContinue
|
|
508
507
|
};
|
|
@@ -600,7 +599,7 @@ function WinGetInstall {
|
|
|
600
599
|
Write-Verbose "Executing `winget install `"$wingetPackage`"";
|
|
601
600
|
& winget install "$wingetPackage" --accept-source-agreements --accept-package-agreements
|
|
602
601
|
}
|
|
603
|
-
|
|
602
|
+
|
|
604
603
|
# Refresh PATH environment variable to pick up newly installed tools
|
|
605
604
|
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
|
606
605
|
}
|
|
@@ -693,12 +692,12 @@ foreach ($req in $filteredRequirements)
|
|
|
693
692
|
try {
|
|
694
693
|
$validAfterInstall = Invoke-Command $req.Valid;
|
|
695
694
|
} catch { }
|
|
696
|
-
|
|
695
|
+
|
|
697
696
|
if ($validAfterInstall) {
|
|
698
697
|
$Installed++;
|
|
699
698
|
continue; # go to the next item
|
|
700
699
|
}
|
|
701
|
-
|
|
700
|
+
|
|
702
701
|
if ($LASTEXITCODE -ne 0) {
|
|
703
702
|
throw "Last exit code was non-zero: $LASTEXITCODE - $outputFromInstall";
|
|
704
703
|
}
|
|
@@ -737,4 +736,4 @@ if ($NeedsRerun -ne 0) {
|
|
|
737
736
|
$Tags | Out-File $MarkerFile;
|
|
738
737
|
if (!$ShellInvocation) { Read-Host 'Press Enter to exit' }
|
|
739
738
|
exit 0;
|
|
740
|
-
}
|
|
739
|
+
}
|
|
@@ -33,7 +33,6 @@
|
|
|
33
33
|
#include <cxxreact/MessageQueueThread.h>
|
|
34
34
|
#pragma warning(pop)
|
|
35
35
|
|
|
36
|
-
#include <future>
|
|
37
36
|
#include <mutex>
|
|
38
37
|
|
|
39
38
|
#include <AppModel.h>
|
|
@@ -47,61 +46,59 @@ using namespace facebook::react;
|
|
|
47
46
|
|
|
48
47
|
namespace Microsoft::ReactNative {
|
|
49
48
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::Streams::IBuffer> GetJavaScriptFromServerAsync(
|
|
50
|
+
const std::string &url) {
|
|
51
|
+
try {
|
|
52
|
+
winrt::Windows::Web::Http::Filters::HttpBaseProtocolFilter filter;
|
|
53
|
+
filter.CacheControl().ReadBehavior(winrt::Windows::Web::Http::Filters::HttpCacheReadBehavior::NoCache);
|
|
54
|
+
winrt::Windows::Web::Http::HttpClient httpClient(filter);
|
|
55
|
+
winrt::Windows::Foundation::Uri uri(Microsoft::Common::Unicode::Utf8ToUtf16(url));
|
|
55
56
|
|
|
56
|
-
|
|
57
|
+
co_await winrt::resume_background();
|
|
57
58
|
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
winrt::Windows::Web::Http::HttpRequestMessage request(winrt::Windows::Web::Http::HttpMethod::Get(), uri);
|
|
60
|
+
auto asyncRequest = httpClient.SendRequestAsync(request);
|
|
60
61
|
#ifdef DEFAULT_CPPWINRT_EXCEPTIONS
|
|
61
|
-
try {
|
|
62
62
|
winrt::Windows::Web::Http::HttpResponseMessage response = co_await asyncRequest;
|
|
63
|
-
} catch (winrt::hresult_error const &e) {
|
|
64
|
-
co_return std::make_pair(
|
|
65
|
-
Microsoft::Common::Unicode::Utf16ToUtf8(e.message().c_str(), e.message().size()).c_str(), false);
|
|
66
|
-
}
|
|
67
63
|
#else
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
64
|
+
co_await lessthrow_await_adapter<winrt::Windows::Foundation::IAsyncOperationWithProgress<
|
|
65
|
+
winrt::Windows::Web::Http::HttpResponseMessage,
|
|
66
|
+
winrt::Windows::Web::Http::HttpProgress>>{asyncRequest};
|
|
67
|
+
|
|
68
|
+
HRESULT hr = asyncRequest.ErrorCode();
|
|
69
|
+
if (FAILED(hr)) {
|
|
70
|
+
std::string error;
|
|
71
|
+
if (hr == WININET_E_CANNOT_CONNECT) {
|
|
72
|
+
error =
|
|
73
|
+
fmt::format("A connection with the server {} could not be established.\n\nIs the packager running?", url);
|
|
74
|
+
} else {
|
|
75
|
+
error = fmt::format("Error 0x{:x} downloading {}.", static_cast<int>(asyncRequest.ErrorCode()), url);
|
|
76
|
+
}
|
|
77
|
+
throw winrt::hresult_error(E_FAIL, winrt::to_hstring(error));
|
|
79
78
|
}
|
|
80
|
-
co_return std::make_pair(error, false);
|
|
81
|
-
}
|
|
82
79
|
|
|
83
|
-
|
|
80
|
+
winrt::Windows::Web::Http::HttpResponseMessage response = asyncRequest.GetResults();
|
|
84
81
|
#endif
|
|
85
82
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
} else {
|
|
101
|
-
result = fmt::format("HTTP Error {} downloading {}.", static_cast<int>(response.StatusCode()), url);
|
|
102
|
-
}
|
|
83
|
+
winrt::Windows::Storage::Streams::IBuffer buffer = co_await response.Content().ReadAsBufferAsync();
|
|
84
|
+
|
|
85
|
+
if (!response.IsSuccessStatusCode()) {
|
|
86
|
+
std::string error;
|
|
87
|
+
if (buffer.Length() > 0) {
|
|
88
|
+
auto reader = winrt::Windows::Storage::Streams::DataReader::FromBuffer(buffer);
|
|
89
|
+
error.resize(buffer.Length());
|
|
90
|
+
auto buf = reinterpret_cast<uint8_t *>(error.data());
|
|
91
|
+
reader.ReadBytes(winrt::array_view(buf, buf + buffer.Length()));
|
|
92
|
+
} else {
|
|
93
|
+
error = fmt::format("HTTP Error {} downloading {}.", static_cast<int>(response.StatusCode()), url);
|
|
94
|
+
}
|
|
95
|
+
throw winrt::hresult_error(E_FAIL, winrt::to_hstring(error));
|
|
96
|
+
}
|
|
103
97
|
|
|
104
|
-
|
|
98
|
+
co_return buffer;
|
|
99
|
+
} catch (winrt::hresult_error const &) {
|
|
100
|
+
throw;
|
|
101
|
+
}
|
|
105
102
|
}
|
|
106
103
|
|
|
107
104
|
void LaunchDevTools(const facebook::react::DevSettings &settings) {
|
|
@@ -185,7 +182,8 @@ std::string GetPackageName(const std::string &bundleAppId) {
|
|
|
185
182
|
return packageName;
|
|
186
183
|
}
|
|
187
184
|
|
|
188
|
-
|
|
185
|
+
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Web::Http::HttpStatusCode> PollForLiveReload(
|
|
186
|
+
const std::string &url) {
|
|
189
187
|
winrt::Windows::Web::Http::HttpClient httpClient;
|
|
190
188
|
winrt::Windows::Foundation::Uri uri(Microsoft::Common::Unicode::Utf8ToUtf16(url));
|
|
191
189
|
httpClient.DefaultRequestHeaders().Connection().TryParseAdd(L"keep-alive");
|
|
@@ -299,7 +297,16 @@ std::pair<std::string, bool> GetJavaScriptFromServer(
|
|
|
299
297
|
inlineSourceMap,
|
|
300
298
|
hermesBytecodeVersion);
|
|
301
299
|
try {
|
|
302
|
-
|
|
300
|
+
auto buffer = GetJavaScriptFromServerAsync(bundleUrl).get();
|
|
301
|
+
std::string result(buffer.Length(), '\0');
|
|
302
|
+
if (!result.empty()) {
|
|
303
|
+
auto reader = winrt::Windows::Storage::Streams::DataReader::FromBuffer(buffer);
|
|
304
|
+
reader.ReadBytes(winrt::array_view<uint8_t>{
|
|
305
|
+
reinterpret_cast<uint8_t *>(&result[0]), reinterpret_cast<uint8_t *>(&result[result.length()])});
|
|
306
|
+
}
|
|
307
|
+
return std::make_pair(std::move(result), true);
|
|
308
|
+
} catch (std::exception const &e) {
|
|
309
|
+
return std::make_pair(std::string{"Error: "} + e.what(), false);
|
|
303
310
|
} catch (winrt::hresult_error const &e) {
|
|
304
311
|
return std::make_pair(
|
|
305
312
|
"Error: " + Microsoft::Common::Unicode::Utf16ToUtf8(e.message().c_str(), e.message().size()), false);
|
|
@@ -18,11 +18,26 @@ namespace Microsoft::React {
|
|
|
18
18
|
struct IWebSocketModuleContentHandler {
|
|
19
19
|
virtual ~IWebSocketModuleContentHandler() noexcept {}
|
|
20
20
|
|
|
21
|
+
/// Returns true if this handler should process messages for the given socket.
|
|
22
|
+
virtual bool CanHandleSocket(int64_t socketId) noexcept = 0;
|
|
23
|
+
|
|
21
24
|
virtual void ProcessMessage(std::string &&message, winrt::Microsoft::ReactNative::JSValueObject ¶ms) noexcept = 0;
|
|
22
25
|
|
|
23
26
|
virtual void ProcessMessage(
|
|
24
27
|
std::vector<uint8_t> &&message,
|
|
25
28
|
winrt::Microsoft::ReactNative::JSValueObject ¶ms) noexcept = 0;
|
|
29
|
+
|
|
30
|
+
/// Check CanHandleSocket() then ProcessMessage() in one call.
|
|
31
|
+
/// Returns true if the message was handled.
|
|
32
|
+
virtual bool TryProcessMessage(
|
|
33
|
+
int64_t socketId,
|
|
34
|
+
std::string &&message,
|
|
35
|
+
winrt::Microsoft::ReactNative::JSValueObject ¶ms) noexcept = 0;
|
|
36
|
+
|
|
37
|
+
virtual bool TryProcessMessage(
|
|
38
|
+
int64_t socketId,
|
|
39
|
+
std::vector<uint8_t> &&message,
|
|
40
|
+
winrt::Microsoft::ReactNative::JSValueObject ¶ms) noexcept = 0;
|
|
26
41
|
};
|
|
27
42
|
|
|
28
43
|
} // namespace Microsoft::React
|
|
@@ -84,6 +84,7 @@ shared_ptr<IWebSocketResource> WebSocketTurboModule::CreateResource(int64_t id,
|
|
|
84
84
|
if (auto prop = propBag.Get(BlobModuleContentHandlerPropertyId()))
|
|
85
85
|
contentHandler = prop.Value().lock();
|
|
86
86
|
|
|
87
|
+
bool handled = false;
|
|
87
88
|
if (contentHandler) {
|
|
88
89
|
if (isBinary) {
|
|
89
90
|
auto buffer = CryptographicBuffer::DecodeFromBase64String(winrt::to_hstring(message));
|
|
@@ -91,11 +92,15 @@ shared_ptr<IWebSocketResource> WebSocketTurboModule::CreateResource(int64_t id,
|
|
|
91
92
|
CryptographicBuffer::CopyToByteArray(buffer, arr);
|
|
92
93
|
auto data = vector<uint8_t>(arr.begin(), arr.end());
|
|
93
94
|
|
|
94
|
-
contentHandler->
|
|
95
|
+
handled = contentHandler->TryProcessMessage(id, std::move(data), args);
|
|
95
96
|
} else {
|
|
96
|
-
contentHandler->
|
|
97
|
+
handled = contentHandler->TryProcessMessage(id, string{message}, args);
|
|
97
98
|
}
|
|
98
|
-
}
|
|
99
|
+
}
|
|
100
|
+
// When the content handler processes the message, it takes ownership of the
|
|
101
|
+
// payload and populates args itself (e.g. as a blob reference), so we only
|
|
102
|
+
// fall back to setting args["data"] when no handler claimed the message.
|
|
103
|
+
if (!handled) {
|
|
99
104
|
args["data"] = message;
|
|
100
105
|
}
|
|
101
106
|
|
|
@@ -221,6 +221,11 @@ BlobWebSocketModuleContentHandler::BlobWebSocketModuleContentHandler(shared_ptr<
|
|
|
221
221
|
|
|
222
222
|
#pragma region IWebSocketModuleContentHandler
|
|
223
223
|
|
|
224
|
+
bool BlobWebSocketModuleContentHandler::CanHandleSocket(int64_t socketId) noexcept /*override*/ {
|
|
225
|
+
scoped_lock lock{m_mutex};
|
|
226
|
+
return m_socketIds.find(socketId) != m_socketIds.end();
|
|
227
|
+
}
|
|
228
|
+
|
|
224
229
|
void BlobWebSocketModuleContentHandler::ProcessMessage(
|
|
225
230
|
string &&message,
|
|
226
231
|
msrn::JSValueObject ¶ms) noexcept /*override*/
|
|
@@ -241,6 +246,38 @@ void BlobWebSocketModuleContentHandler::ProcessMessage(
|
|
|
241
246
|
params[blobKeys.Type] = blobKeys.Blob;
|
|
242
247
|
}
|
|
243
248
|
|
|
249
|
+
bool BlobWebSocketModuleContentHandler::TryProcessMessage(
|
|
250
|
+
int64_t socketId,
|
|
251
|
+
string &&message,
|
|
252
|
+
msrn::JSValueObject ¶ms) noexcept /*override*/
|
|
253
|
+
{
|
|
254
|
+
scoped_lock lock{m_mutex};
|
|
255
|
+
if (m_socketIds.find(socketId) == m_socketIds.end())
|
|
256
|
+
return false;
|
|
257
|
+
|
|
258
|
+
params[blobKeys.Data] = std::move(message);
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
bool BlobWebSocketModuleContentHandler::TryProcessMessage(
|
|
263
|
+
int64_t socketId,
|
|
264
|
+
vector<uint8_t> &&message,
|
|
265
|
+
msrn::JSValueObject ¶ms) noexcept /*override*/
|
|
266
|
+
{
|
|
267
|
+
scoped_lock lock{m_mutex};
|
|
268
|
+
if (m_socketIds.find(socketId) == m_socketIds.end())
|
|
269
|
+
return false;
|
|
270
|
+
|
|
271
|
+
auto blob = msrn::JSValueObject{
|
|
272
|
+
{blobKeys.Offset, 0},
|
|
273
|
+
{blobKeys.Size, message.size()},
|
|
274
|
+
{blobKeys.BlobId, m_blobPersistor->StoreMessage(std::move(message))}};
|
|
275
|
+
|
|
276
|
+
params[blobKeys.Data] = std::move(blob);
|
|
277
|
+
params[blobKeys.Type] = blobKeys.Blob;
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
|
|
244
281
|
#pragma endregion IWebSocketModuleContentHandler
|
|
245
282
|
|
|
246
283
|
void BlobWebSocketModuleContentHandler::Register(int64_t socketID) noexcept {
|
|
@@ -51,11 +51,23 @@ class BlobWebSocketModuleContentHandler final : public IWebSocketModuleContentHa
|
|
|
51
51
|
|
|
52
52
|
#pragma region IWebSocketModuleContentHandler
|
|
53
53
|
|
|
54
|
+
bool CanHandleSocket(int64_t socketId) noexcept override;
|
|
55
|
+
|
|
54
56
|
void ProcessMessage(std::string &&message, winrt::Microsoft::ReactNative::JSValueObject ¶ms) noexcept override;
|
|
55
57
|
|
|
56
58
|
void ProcessMessage(std::vector<uint8_t> &&message, winrt::Microsoft::ReactNative::JSValueObject ¶ms) noexcept
|
|
57
59
|
override;
|
|
58
60
|
|
|
61
|
+
bool TryProcessMessage(
|
|
62
|
+
int64_t socketId,
|
|
63
|
+
std::string &&message,
|
|
64
|
+
winrt::Microsoft::ReactNative::JSValueObject ¶ms) noexcept override;
|
|
65
|
+
|
|
66
|
+
bool TryProcessMessage(
|
|
67
|
+
int64_t socketId,
|
|
68
|
+
std::vector<uint8_t> &&message,
|
|
69
|
+
winrt::Microsoft::ReactNative::JSValueObject ¶ms) noexcept override;
|
|
70
|
+
|
|
59
71
|
#pragma endregion IWebSocketModuleContentHandler
|
|
60
72
|
|
|
61
73
|
void Register(int64_t socketID) noexcept;
|
|
@@ -27,8 +27,12 @@ class WinRTWebSocketResource2 : public IWebSocketResource,
|
|
|
27
27
|
void operator=(const TaskSequencer &) = delete;
|
|
28
28
|
|
|
29
29
|
private:
|
|
30
|
+
// `experimental` is deprecated starting Visual Studio 2026
|
|
31
|
+
#if _MSC_VER >= 1951
|
|
32
|
+
using CoroHandle = std::coroutine_handle<>;
|
|
33
|
+
#else
|
|
30
34
|
using CoroHandle = std::experimental::coroutine_handle<>;
|
|
31
|
-
|
|
35
|
+
#endif
|
|
32
36
|
struct Suspender {
|
|
33
37
|
CoroHandle m_handle;
|
|
34
38
|
|
package/just-task.js
CHANGED
|
@@ -25,6 +25,7 @@ const fs = require('fs');
|
|
|
25
25
|
const {
|
|
26
26
|
registerNuGetRestoreTask,
|
|
27
27
|
} = require('@rnw-scripts/just-task/nuget-restore-task');
|
|
28
|
+
const {findPowerShell} = require('@react-native-windows/find-dotnet-tools');
|
|
28
29
|
|
|
29
30
|
option('production');
|
|
30
31
|
option('clean');
|
|
@@ -46,9 +47,9 @@ function codegen(test) {
|
|
|
46
47
|
|
|
47
48
|
function layoutMSRNCxx() {
|
|
48
49
|
if (require('os').platform() === 'win32') {
|
|
49
|
-
const powershell =
|
|
50
|
+
const powershell = findPowerShell();
|
|
50
51
|
execSync(
|
|
51
|
-
|
|
52
|
+
`"${powershell}" -NoProfile .\\Scripts\\Tfs\\Layout-MSRN-Headers.ps1 -GenerateLocalCxx`,
|
|
52
53
|
{
|
|
53
54
|
env: process.env,
|
|
54
55
|
},
|
|
@@ -84,12 +85,22 @@ registerNuGetRestoreTask({
|
|
|
84
85
|
scriptArguments: ['-SkipLockDeletion'],
|
|
85
86
|
});
|
|
86
87
|
|
|
88
|
+
function installDotnetToolsTask() {
|
|
89
|
+
execSync(
|
|
90
|
+
`dotnet tool restore --tool-manifest ${path.resolve(__dirname, 'dotnet-tools.json')}`,
|
|
91
|
+
{env: process.env},
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
task('installDotnetTools', installDotnetToolsTask);
|
|
96
|
+
|
|
87
97
|
task(
|
|
88
98
|
'build',
|
|
89
99
|
series(
|
|
90
100
|
condition('clean', () => argv().clean),
|
|
91
101
|
'copyRNLibraries',
|
|
92
102
|
'copyReadmeAndLicenseFromRoot',
|
|
103
|
+
condition('installDotnetTools', () => !process.env.TF_BUILD),
|
|
93
104
|
'layoutMSRNCxx',
|
|
94
105
|
'compileTsPlatformOverrides',
|
|
95
106
|
'restoreNuGetPackages',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-windows",
|
|
3
|
-
"version": "0.83.
|
|
3
|
+
"version": "0.83.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@react-native-community/cli": "20.0.0",
|
|
27
27
|
"@react-native-community/cli-platform-android": "20.0.0",
|
|
28
28
|
"@react-native-community/cli-platform-ios": "20.0.0",
|
|
29
|
-
"@react-native-windows/cli": "0.83.
|
|
29
|
+
"@react-native-windows/cli": "0.83.2",
|
|
30
30
|
"@react-native/assets": "1.0.0",
|
|
31
31
|
"@react-native/assets-registry": "0.83.4",
|
|
32
32
|
"@react-native/codegen": "0.83.4",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"yargs": "^17.6.2"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
|
-
"@react-native-windows/codegen": "0.83.
|
|
72
|
+
"@react-native-windows/codegen": "0.83.1",
|
|
73
73
|
"@react-native/metro-config": "0.83.4",
|
|
74
74
|
"@rnw-scripts/babel-react-native-config": "0.0.0",
|
|
75
75
|
"@rnw-scripts/eslint-config": "1.2.38",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"prettier": "2.8.8",
|
|
87
87
|
"react": "19.2.0",
|
|
88
88
|
"react-native": "0.83.4",
|
|
89
|
-
"react-native-platform-override": "0.83.
|
|
89
|
+
"react-native-platform-override": "0.83.1",
|
|
90
90
|
"react-refresh": "^0.14.0",
|
|
91
91
|
"typescript": "5.0.4"
|
|
92
92
|
},
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
"react-native": "^0.83.0"
|
|
97
97
|
},
|
|
98
98
|
"beachball": {
|
|
99
|
-
"defaultNpmTag": "
|
|
99
|
+
"defaultNpmTag": "v0.83-stable",
|
|
100
100
|
"disallowedChangeTypes": [
|
|
101
101
|
"major",
|
|
102
102
|
"minor",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
<PropertyGroup Label="Configuration">
|
|
51
51
|
<ConfigurationType>Application</ConfigurationType>
|
|
52
52
|
<CharacterSet>Unicode</CharacterSet>
|
|
53
|
-
<PlatformToolset>
|
|
53
|
+
<PlatformToolset>v145</PlatformToolset>
|
|
54
54
|
</PropertyGroup>
|
|
55
55
|
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
|
56
56
|
<UseDebugLibraries>true</UseDebugLibraries>
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
<PropertyGroup Label="Configuration">
|
|
50
50
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
51
51
|
<CharacterSet>Unicode</CharacterSet>
|
|
52
|
-
<PlatformToolset>
|
|
52
|
+
<PlatformToolset>v145</PlatformToolset>
|
|
53
53
|
<GenerateManifest>false</GenerateManifest>
|
|
54
54
|
</PropertyGroup>
|
|
55
55
|
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|