react-native-windows 0.0.0-canary.479 → 0.0.0-canary.482

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.
@@ -100,7 +100,8 @@ namespace Microsoft.ReactNative
100
100
 
101
101
  DOC_STRING(
102
102
  "The name of the JavaScript bundle file to load. This should be a relative path from @.BundleRootPath. "
103
- "The `.bundle` extension will be appended to the end, when looking for the bundle file.")
103
+ "The `.bundle` extension will be appended to the end, when looking for the bundle file.\n"
104
+ "If using an embedded RCDATA resource, this identifies the resource ID that stores the bundle. See @.BundleRootPath.")
104
105
  DOC_DEFAULT("index.windows")
105
106
  String JavaScriptBundleFile { get; set; };
106
107
 
@@ -176,7 +177,16 @@ namespace Microsoft.ReactNative
176
177
  "If this is not provided, the value of @.JavaScriptBundleFile is used.")
177
178
  String DebugBundlePath { get; set; };
178
179
 
179
- DOC_STRING("Base path used for the location of the bundle.")
180
+ DOC_STRING(
181
+ "Base path used for the location of the bundle. \n"
182
+ "This can be an `ms-appx://` or `ms-appdata://` URI (if the app is UWP or packaged using MSIX), "
183
+ "a filesystem path, or a URI pointing at an embedded resource.\n"
184
+ "Examples:\n\n"
185
+ "- `ms-appx:///Bundle` - locates the bundle in the MSIX package. See [URI schemes](https://docs.microsoft.com/windows/uwp/app-resources/uri-schemes) for other UWP/MSIX valid URI formats."
186
+ "- `C:\\foo\\bar` - locates the bundle in the local filesystem. Note [UWP app file access permissions](https://docs.microsoft.com/windows/uwp/files/file-access-permissions)."
187
+ "- `resource://moduleName` - locates the bundle as an embedded RCDATA resource in moduleName. Specify the resource ID in @.JavaScriptBundleFile."
188
+ "- `resource://` - locates the bundle as an embedded RCDATA resource in the running process's module. Specify the resource ID in @.JavaScriptBundleFile."
189
+ )
180
190
  DOC_DEFAULT("ms-appx:///Bundle/")
181
191
  String BundleRootPath { get; set; };
182
192
 
@@ -15,6 +15,45 @@
15
15
 
16
16
  namespace Microsoft::ReactNative {
17
17
 
18
+ std::string GetBundleFromEmbeddedResource(winrt::hstring str) {
19
+ winrt::Windows::Foundation::Uri uri(str);
20
+ auto moduleName = uri.Host();
21
+ auto path = uri.Path();
22
+ // skip past the leading / slash
23
+ auto resourceName = path.c_str() + 1;
24
+
25
+ auto hmodule = GetModuleHandle(moduleName != L"" ? moduleName.c_str() : nullptr);
26
+ if (!hmodule) {
27
+ throw std::invalid_argument(fmt::format("Couldn't find module {}", winrt::to_string(moduleName)));
28
+ }
29
+
30
+ auto resource = FindResourceW(hmodule, resourceName, RT_RCDATA);
31
+ if (!resource) {
32
+ throw std::invalid_argument(fmt::format(
33
+ "Couldn't find resource {} in module {}", winrt::to_string(resourceName), winrt::to_string(moduleName)));
34
+ }
35
+
36
+ auto hglobal = LoadResource(hmodule, resource);
37
+ if (!hglobal) {
38
+ throw std::invalid_argument(fmt::format(
39
+ "Couldn't load resource {} in module {}", winrt::to_string(resourceName), winrt::to_string(moduleName)));
40
+ }
41
+
42
+ auto start = static_cast<char *>(LockResource(hglobal));
43
+ if (!start) {
44
+ throw std::invalid_argument(fmt::format(
45
+ "Couldn't lock resource {} in module {}", winrt::to_string(resourceName), winrt::to_string(moduleName)));
46
+ }
47
+
48
+ auto size = SizeofResource(hmodule, resource);
49
+ if (!size) {
50
+ throw std::invalid_argument(fmt::format(
51
+ "Couldn't get size of resource {} in module {}", winrt::to_string(resourceName), winrt::to_string(moduleName)));
52
+ }
53
+
54
+ return std::string(start, start + size);
55
+ }
56
+
18
57
  std::future<std::string> LocalBundleReader::LoadBundleAsync(const std::string &bundleUri) {
19
58
  winrt::hstring str(Microsoft::Common::Unicode::Utf8ToUtf16(bundleUri));
20
59
 
@@ -26,6 +65,8 @@ std::future<std::string> LocalBundleReader::LoadBundleAsync(const std::string &b
26
65
  if (bundleUri._Starts_with("ms-app")) {
27
66
  winrt::Windows::Foundation::Uri uri(str);
28
67
  file = co_await winrt::Windows::Storage::StorageFile::GetFileFromApplicationUriAsync(uri);
68
+ } else if (bundleUri._Starts_with("resource://")) {
69
+ co_return GetBundleFromEmbeddedResource(str);
29
70
  } else {
30
71
  file = co_await winrt::Windows::Storage::StorageFile::GetFileFromPathAsync(str);
31
72
  }
@@ -8,16 +8,50 @@
8
8
 
9
9
  #include "CppWinRTIncludes.h"
10
10
 
11
+ extern "C" {
12
+ HMODULE
13
+ WINAPI
14
+ WINRT_IMPL_GetModuleHandleW(_In_opt_ LPCWSTR lpModuleName);
15
+ }
16
+
17
+ #ifndef WINRT_IMPL_LINK
18
+ #ifdef _M_HYBRID
19
+ #define WINRT_IMPL_LINK(function, count) \
20
+ __pragma(comment(linker, "/alternatename:#WINRT_IMPL_" #function "@" #count "=#" #function "@" #count))
21
+ #elif _M_ARM64EC
22
+ #define WINRT_IMPL_LINK(function, count) \
23
+ __pragma(comment(linker, "/alternatename:#WINRT_IMPL_" #function "=#" #function))
24
+ #elif _M_IX86
25
+ #define WINRT_IMPL_LINK(function, count) \
26
+ __pragma(comment(linker, "/alternatename:_WINRT_IMPL_" #function "@" #count "=_" #function "@" #count))
27
+ #else
28
+ #define WINRT_IMPL_LINK(function, count) __pragma(comment(linker, "/alternatename:WINRT_IMPL_" #function "=" #function))
29
+ #endif
30
+ #endif
31
+ WINRT_IMPL_LINK(GetModuleHandleW, 4);
32
+ #undef WINRT_IMPL_LINK
33
+
11
34
  namespace XAML_CPPWINRT_NAMESPACE {
12
35
 
13
36
  // Return Application::Current() when it is present or nullptr otherwise.
14
37
  // It does not throw exception as Application::Current() does.
15
38
  inline Application TryGetCurrentApplication() noexcept {
16
- auto applicationStatics = get_activation_factory<IApplicationStatics>(name_of<Application>());
17
- auto abiApplicationStatics = static_cast<impl::abi_t<IApplicationStatics> *>(get_abi(applicationStatics));
18
- void *value{};
19
- abiApplicationStatics->get_Current(&value);
20
- return Application{value, take_ownership_from_abi};
39
+ #ifndef USE_WINUI3
40
+ constexpr auto xamlDll = L"Windows.UI.Xaml.dll";
41
+ #else
42
+ constexpr auto xamlDll = L"Microsoft.UI.Xaml.dll";
43
+ #endif
44
+
45
+ if (auto xamlIsLoaded = WINRT_IMPL_GetModuleHandleW(xamlDll)) {
46
+ auto applicationStatics = get_activation_factory<IApplicationStatics>(name_of<Application>());
47
+ auto abiApplicationStatics = static_cast<impl::abi_t<IApplicationStatics> *>(get_abi(applicationStatics));
48
+ void *value{};
49
+ abiApplicationStatics->get_Current(&value);
50
+ return Application{value, take_ownership_from_abi};
51
+ } else {
52
+ // If we don't have XAML loaded, we are not a XAML app
53
+ return nullptr;
54
+ }
21
55
  }
22
56
 
23
57
  } // namespace XAML_CPPWINRT_NAMESPACE
@@ -10,7 +10,7 @@
10
10
  -->
11
11
  <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
12
12
  <PropertyGroup>
13
- <ReactNativeWindowsVersion>0.0.0-canary.479</ReactNativeWindowsVersion>
13
+ <ReactNativeWindowsVersion>0.0.0-canary.482</ReactNativeWindowsVersion>
14
14
  <ReactNativeWindowsMajor>0</ReactNativeWindowsMajor>
15
15
  <ReactNativeWindowsMinor>0</ReactNativeWindowsMinor>
16
16
  <ReactNativeWindowsPatch>0</ReactNativeWindowsPatch>
@@ -95,7 +95,7 @@ function CheckVS {
95
95
  [String[]]$output = & $vsWhere -version $vsver -requires $vsComponents -property productPath
96
96
 
97
97
  if (($output.Count -eq 0) -or (!(Test-Path $output[0]))) {
98
- Write-Debug No Retail versions of Visual Studio found, trying pre-release...
98
+ Write-Debug "No Retail versions of Visual Studio found, trying pre-release..."
99
99
  [String[]]$output = & $vsWhere -version $vsver -requires $vsComponents -property productPath -prerelease
100
100
  }
101
101
  if ($output.Count -gt 1) {
@@ -184,7 +184,7 @@ function CheckCppWinRT_VSIX {
184
184
  [String[]]$vsPath = & $vsWhere -version $vsver -property installationPath;
185
185
 
186
186
  if (($vsPath.Count -eq 0) -or (!(Test-Path $vsPath[0]))) {
187
- Write-Debug No Retail versions of Visual Studio found, trying pre-release...
187
+ Write-Debug "No Retail versions of Visual Studio found, trying pre-release..."
188
188
  [String[]]$vsPath = & $vsWhere -version $vsver -property installationPath -prerelease
189
189
  }
190
190
 
@@ -208,7 +208,7 @@ function InstallCppWinRT_VSIX {
208
208
  [String[]]$productPath = & $vsWhere -version $vsver -property productPath
209
209
 
210
210
  if (($productPath.Count -eq 0) -or (!(Test-Path $productPath[0]))) {
211
- Write-Debug No Retail versions of Visual Studio found, trying pre-release...
211
+ Write-Debug "No Retail versions of Visual Studio found, trying pre-release..."
212
212
  [String[]]$productPath = & $vsWhere -version $vsver -property productPath -prerelease
213
213
  }
214
214
 
@@ -69,13 +69,13 @@ std::future<std::pair<std::string, bool>> GetJavaScriptFromServerAsync(const std
69
69
 
70
70
  HRESULT hr = asyncRequest.ErrorCode();
71
71
  if (FAILED(hr)) {
72
- std::ostringstream sstream;
72
+ std::string error;
73
73
  if (hr == WININET_E_CANNOT_CONNECT) {
74
- sstream << "A connection with the server " << url << " could not be established\n\nIs the packager running?";
74
+ error = fmt::format("A connection with the server {} could not be established.\n\nIs the packager running?", url);
75
75
  } else {
76
- sstream << "Error " << std::hex << static_cast<int>(asyncRequest.ErrorCode()) << " downloading " << url;
76
+ error = fmt::format("Error 0x{:x} downloading {}.", static_cast<int>(asyncRequest.ErrorCode()), url);
77
77
  }
78
- co_return std::make_pair(sstream.str(), false);
78
+ co_return std::make_pair(error, false);
79
79
  }
80
80
 
81
81
  winrt::Windows::Web::Http::HttpResponseMessage response = asyncRequest.GetResults();
@@ -88,15 +88,15 @@ std::future<std::pair<std::string, bool>> GetJavaScriptFromServerAsync(const std
88
88
  uint32_t len = reader.UnconsumedBufferLength();
89
89
  std::string result;
90
90
  if (len > 0 || response.IsSuccessStatusCode()) {
91
- std::vector<uint8_t> data;
91
+ std::string data;
92
92
  data.resize(len);
93
- reader.ReadBytes(winrt::array_view(data.data(), data.data() + len));
94
- data.resize(len);
95
- result = std::string(data.begin(), data.end());
93
+ auto buf = reinterpret_cast<uint8_t *>(data.data());
94
+ static_assert(
95
+ sizeof(buf[0]) == sizeof(data[0]), "perf optimization relies on uint8_t and char being the same size");
96
+ reader.ReadBytes(winrt::array_view(buf, buf + len));
97
+ result = std::move(data);
96
98
  } else {
97
- std::ostringstream sstream;
98
- sstream << "HTTP Error " << static_cast<int>(response.StatusCode()) << " downloading " << url;
99
- result = sstream.str();
99
+ result = fmt::format("HTTP Error {} downloading {}.", static_cast<int>(response.StatusCode()), url);
100
100
  }
101
101
 
102
102
  co_return std::make_pair(std::move(result), response.IsSuccessStatusCode());
@@ -509,7 +509,15 @@ void InstanceImpl::loadBundleInternal(std::string &&jsBundleRelativePath, bool s
509
509
  std::string bundlePath = (fs::path(m_devSettings->bundleRootPath) / jsBundleRelativePath).string();
510
510
  auto bundleString = FileMappingBigString::fromPath(bundlePath);
511
511
  #else
512
- std::string bundlePath = (fs::path(m_devSettings->bundleRootPath) / (jsBundleRelativePath + ".bundle")).string();
512
+ std::string bundlePath;
513
+ if (m_devSettings->bundleRootPath._Starts_with("resource://")) {
514
+ auto uri = winrt::Windows::Foundation::Uri(
515
+ winrt::to_hstring(m_devSettings->bundleRootPath), winrt::to_hstring(jsBundleRelativePath));
516
+ bundlePath = winrt::to_string(uri.ToString());
517
+ } else {
518
+ bundlePath = (fs::path(m_devSettings->bundleRootPath) / (jsBundleRelativePath + ".bundle")).string();
519
+ }
520
+
513
521
  auto bundleString = std::make_unique<::Microsoft::ReactNative::StorageFileBigString>(bundlePath);
514
522
  #endif
515
523
  m_innerInstance->loadScriptFromString(std::move(bundleString), std::move(jsBundleRelativePath), synchronously);
@@ -517,11 +525,9 @@ void InstanceImpl::loadBundleInternal(std::string &&jsBundleRelativePath, bool s
517
525
  } catch (const std::exception &e) {
518
526
  m_devSettings->errorCallback(e.what());
519
527
  } catch (const winrt::hresult_error &hrerr) {
520
- std::stringstream ss;
521
- ss << "[" << std::hex << std::showbase << std::setw(8) << static_cast<uint32_t>(hrerr.code()) << "] "
522
- << winrt::to_string(hrerr.message());
528
+ auto error = fmt::format("[0x{:0>8x}] {}", static_cast<uint32_t>(hrerr.code()), winrt::to_string(hrerr.message()));
523
529
 
524
- m_devSettings->errorCallback(std::move(ss.str()));
530
+ m_devSettings->errorCallback(std::move(error));
525
531
  }
526
532
  }
527
533
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-windows",
3
- "version": "0.0.0-canary.479",
3
+ "version": "0.0.0-canary.482",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,7 +26,7 @@
26
26
  "@react-native-community/cli": "^7.0.3",
27
27
  "@react-native-community/cli-platform-android": "^7.0.1",
28
28
  "@react-native-community/cli-platform-ios": "^7.0.1",
29
- "@react-native-windows/cli": "0.0.0-canary.122",
29
+ "@react-native-windows/cli": "0.0.0-canary.123",
30
30
  "@react-native-windows/virtualized-list": "0.0.0-canary.36",
31
31
  "@react-native/assets": "1.0.0",
32
32
  "@react-native/normalize-color": "2.0.0",
@@ -74,7 +74,7 @@ typedef int LogSeverity;
74
74
  inline void FlushLogFiles(LogSeverity min_severity) {}
75
75
 
76
76
  #define google GlogStub
77
- static const int INFO = 1;
77
+ static const int GLOG_INFO = 1;
78
78
 
79
79
  #endif
80
80
 
@@ -1,64 +0,0 @@
1
- /*
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- // No header guards since it is legitimately possible to include this file more
9
- // than once with and without REACT_NATIVE_DEBUG.
10
-
11
- // react_native_assert allows us to opt-in to specific asserts on Android and
12
- // test before moving on. When all issues have been found, maybe we can use
13
- // `UNDEBUG` flag to disable NDEBUG in debug builds on Android.
14
-
15
- #include "flags.h"
16
-
17
- #undef react_native_assert
18
-
19
- #ifndef REACT_NATIVE_DEBUG
20
-
21
- #define react_native_assert(e) ((void)0)
22
-
23
- #else // REACT_NATIVE_DEBUG
24
-
25
- #ifdef __ANDROID__
26
-
27
- #include <android/log.h>
28
-
29
- #ifdef __cplusplus
30
- extern "C" {
31
- #endif // __cplusplus
32
- void react_native_assert_fail(
33
- const char *func,
34
- const char *file,
35
- int line,
36
- const char *expr);
37
- #ifdef __cplusplus
38
- }
39
- #endif // __cpusplus
40
-
41
- #define react_native_assert(e) \
42
- ((e) ? (void)0 : react_native_assert_fail(__func__, __FILE__, __LINE__, #e))
43
-
44
- #else // __ANDROID__
45
-
46
- #include <glog/logging.h>
47
- #include <cassert>
48
-
49
- // For all platforms, but iOS+Xcode especially: flush logs because some might be
50
- // lost on iOS if an assert is hit right after this. If you are trying to debug
51
- // something actively and have added lots of LOG statements to track down an
52
- // issue, there is race between flushing the final logs and stopping execution
53
- // when the assert hits. Thus, if we know an assert will fail, we force flushing
54
- // to happen right before the assert.
55
- #define react_native_assert(cond) \
56
- if (!(cond)) { \
57
- LOG(ERROR) << "react_native_assert failure: " << #cond; \
58
- google::FlushLogFiles(google::INFO); \
59
- assert(cond); \
60
- }
61
-
62
- #endif // platforms besides __ANDROID__
63
-
64
- #endif // REACT_NATIVE_DEBUG
@@ -1,310 +0,0 @@
1
- /*
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- #include "StubViewTree.h"
9
-
10
- #include <glog/logging.h>
11
- #include <react/debug/react_native_assert.h>
12
-
13
- #ifdef STUB_VIEW_TREE_VERBOSE
14
- #define STUB_VIEW_LOG(code) code
15
- #else
16
- #define STUB_VIEW_LOG(code)
17
- #endif
18
-
19
- namespace facebook {
20
- namespace react {
21
-
22
- StubViewTree::StubViewTree(ShadowView const &shadowView) {
23
- auto view = std::make_shared<StubView>();
24
- view->update(shadowView);
25
- rootTag = shadowView.tag;
26
- registry[shadowView.tag] = view;
27
- }
28
-
29
- StubView const &StubViewTree::getRootStubView() const {
30
- return *registry.at(rootTag);
31
- }
32
-
33
- StubView const &StubViewTree::getStubView(Tag tag) const {
34
- return *registry.at(tag);
35
- }
36
-
37
- size_t StubViewTree::size() const {
38
- return registry.size();
39
- }
40
-
41
- void StubViewTree::mutate(ShadowViewMutationList const &mutations) {
42
- STUB_VIEW_LOG({ LOG(ERROR) << "StubView: Mutating Begin"; });
43
- for (auto const &mutation : mutations) {
44
- switch (mutation.type) {
45
- case ShadowViewMutation::Create: {
46
- react_native_assert(mutation.parentShadowView == ShadowView{});
47
- react_native_assert(mutation.oldChildShadowView == ShadowView{});
48
- react_native_assert(mutation.newChildShadowView.props);
49
- auto stubView = std::make_shared<StubView>();
50
- stubView->update(mutation.newChildShadowView);
51
- auto tag = mutation.newChildShadowView.tag;
52
- STUB_VIEW_LOG({
53
- LOG(ERROR) << "StubView: Create [" << tag << "] ##"
54
- << std::hash<ShadowView>{}((ShadowView)*stubView);
55
- });
56
- react_native_assert(registry.find(tag) == registry.end());
57
- registry[tag] = stubView;
58
- break;
59
- }
60
-
61
- case ShadowViewMutation::Delete: {
62
- STUB_VIEW_LOG({
63
- LOG(ERROR) << "StubView: Delete [" << mutation.oldChildShadowView.tag
64
- << "] ##"
65
- << std::hash<ShadowView>{}(mutation.oldChildShadowView);
66
- });
67
- react_native_assert(mutation.parentShadowView == ShadowView{});
68
- react_native_assert(mutation.newChildShadowView == ShadowView{});
69
- auto tag = mutation.oldChildShadowView.tag;
70
- react_native_assert(registry.find(tag) != registry.end());
71
- auto stubView = registry[tag];
72
- if ((ShadowView)(*stubView) != mutation.oldChildShadowView) {
73
- LOG(ERROR)
74
- << "StubView: ASSERT FAILURE: DELETE mutation assertion failure: oldChildShadowView does not match stubView: ["
75
- << mutation.oldChildShadowView.tag << "] stub hash: ##"
76
- << std::hash<ShadowView>{}((ShadowView)*stubView)
77
- << " old mutation hash: ##"
78
- << std::hash<ShadowView>{}(mutation.oldChildShadowView);
79
- #ifdef RN_DEBUG_STRING_CONVERTIBLE
80
- LOG(ERROR) << "StubView: "
81
- << getDebugPropsDescription((ShadowView)*stubView, {});
82
- LOG(ERROR) << "OldChildShadowView: "
83
- << getDebugPropsDescription(
84
- mutation.oldChildShadowView, {});
85
- #endif
86
- }
87
- react_native_assert(
88
- (ShadowView)(*stubView) == mutation.oldChildShadowView);
89
- registry.erase(tag);
90
- break;
91
- }
92
-
93
- case ShadowViewMutation::Insert: {
94
- if (!mutation.mutatedViewIsVirtual()) {
95
- react_native_assert(mutation.oldChildShadowView == ShadowView{});
96
- auto parentTag = mutation.parentShadowView.tag;
97
- auto childTag = mutation.newChildShadowView.tag;
98
- if (registry.find(parentTag) == registry.end()) {
99
- LOG(ERROR)
100
- << "StubView: ASSERT FAILURE: INSERT mutation assertion failure: parentTag not found: ["
101
- << parentTag << "] inserting child: [" << childTag << "]";
102
- }
103
- if (registry.find(childTag) == registry.end()) {
104
- LOG(ERROR)
105
- << "StubView: ASSERT FAILURE: INSERT mutation assertion failure: childTag not found: ["
106
- << parentTag << "] inserting child: [" << childTag << "]";
107
- }
108
- react_native_assert(registry.find(parentTag) != registry.end());
109
- auto parentStubView = registry[parentTag];
110
- react_native_assert(registry.find(childTag) != registry.end());
111
- auto childStubView = registry[childTag];
112
- childStubView->update(mutation.newChildShadowView);
113
- STUB_VIEW_LOG({
114
- LOG(ERROR) << "StubView: Insert [" << childTag << "] into ["
115
- << parentTag << "] @" << mutation.index << "("
116
- << parentStubView->children.size() << " children)";
117
- });
118
- react_native_assert(childStubView->parentTag == NO_VIEW_TAG);
119
- react_native_assert(
120
- mutation.index >= 0 &&
121
- parentStubView->children.size() >=
122
- static_cast<size_t>(mutation.index));
123
- childStubView->parentTag = parentTag;
124
- parentStubView->children.insert(
125
- parentStubView->children.begin() + mutation.index, childStubView);
126
- } else {
127
- auto childTag = mutation.newChildShadowView.tag;
128
- react_native_assert(registry.find(childTag) != registry.end());
129
- auto childStubView = registry[childTag];
130
- childStubView->update(mutation.newChildShadowView);
131
- }
132
- break;
133
- }
134
-
135
- case ShadowViewMutation::Remove: {
136
- if (!mutation.mutatedViewIsVirtual()) {
137
- react_native_assert(mutation.newChildShadowView == ShadowView{});
138
- auto parentTag = mutation.parentShadowView.tag;
139
- auto childTag = mutation.oldChildShadowView.tag;
140
- if (registry.find(parentTag) == registry.end()) {
141
- LOG(ERROR)
142
- << "StubView: ASSERT FAILURE: REMOVE mutation assertion failure: parentTag not found: ["
143
- << parentTag << "] removing child: [" << childTag << "]";
144
- }
145
- react_native_assert(registry.find(parentTag) != registry.end());
146
- auto parentStubView = registry[parentTag];
147
- STUB_VIEW_LOG({
148
- LOG(ERROR) << "StubView: Remove [" << childTag << "] from ["
149
- << parentTag << "] @" << mutation.index << " with "
150
- << parentStubView->children.size() << " children";
151
- });
152
- react_native_assert(
153
- mutation.index >= 0 &&
154
- parentStubView->children.size() >
155
- static_cast<size_t>(mutation.index));
156
- react_native_assert(registry.find(childTag) != registry.end());
157
- auto childStubView = registry[childTag];
158
- if ((ShadowView)(*childStubView) != mutation.oldChildShadowView) {
159
- LOG(ERROR)
160
- << "StubView: ASSERT FAILURE: REMOVE mutation assertion failure: oldChildShadowView does not match oldStubView: ["
161
- << mutation.oldChildShadowView.tag << "] stub hash: ##"
162
- << std::hash<ShadowView>{}((ShadowView)*childStubView)
163
- << " old mutation hash: ##"
164
- << std::hash<ShadowView>{}(mutation.oldChildShadowView);
165
- #ifdef RN_DEBUG_STRING_CONVERTIBLE
166
- LOG(ERROR) << "ChildStubView: "
167
- << getDebugPropsDescription(
168
- (ShadowView)*childStubView, {});
169
- LOG(ERROR) << "OldChildShadowView: "
170
- << getDebugPropsDescription(
171
- mutation.oldChildShadowView, {});
172
- #endif
173
- }
174
- react_native_assert(
175
- (ShadowView)(*childStubView) == mutation.oldChildShadowView);
176
- react_native_assert(childStubView->parentTag == parentTag);
177
- STUB_VIEW_LOG({
178
- std::string strChildList = "";
179
- int i = 0;
180
- for (auto const &child : parentStubView->children) {
181
- strChildList.append(std::to_string(i));
182
- strChildList.append(":");
183
- strChildList.append(std::to_string(child->tag));
184
- strChildList.append(", ");
185
- i++;
186
- }
187
- LOG(ERROR) << "StubView: BEFORE REMOVE: Children of " << parentTag
188
- << ": " << strChildList;
189
- });
190
- react_native_assert(
191
- mutation.index >= 0 &&
192
- parentStubView->children.size() >
193
- static_cast<size_t>(mutation.index) &&
194
- parentStubView->children[mutation.index]->tag ==
195
- childStubView->tag);
196
- childStubView->parentTag = NO_VIEW_TAG;
197
- parentStubView->children.erase(
198
- parentStubView->children.begin() + mutation.index);
199
- }
200
- break;
201
- }
202
-
203
- case ShadowViewMutation::Update: {
204
- STUB_VIEW_LOG({
205
- LOG(ERROR) << "StubView: Update [" << mutation.newChildShadowView.tag
206
- << "] old hash: ##"
207
- << std::hash<ShadowView>{}(mutation.oldChildShadowView)
208
- << " new hash: ##"
209
- << std::hash<ShadowView>{}(mutation.newChildShadowView);
210
- });
211
- react_native_assert(mutation.oldChildShadowView.tag != 0);
212
- react_native_assert(mutation.newChildShadowView.tag != 0);
213
- react_native_assert(mutation.newChildShadowView.props);
214
- react_native_assert(
215
- mutation.newChildShadowView.tag == mutation.oldChildShadowView.tag);
216
- react_native_assert(
217
- registry.find(mutation.newChildShadowView.tag) != registry.end());
218
- auto oldStubView = registry[mutation.newChildShadowView.tag];
219
- react_native_assert(oldStubView->tag != 0);
220
- if ((ShadowView)(*oldStubView) != mutation.oldChildShadowView) {
221
- LOG(ERROR)
222
- << "StubView: ASSERT FAILURE: UPDATE mutation assertion failure: oldChildShadowView does not match oldStubView: ["
223
- << mutation.oldChildShadowView.tag << "] old stub hash: ##"
224
- << std::hash<ShadowView>{}((ShadowView)*oldStubView)
225
- << " old mutation hash: ##"
226
- << std::hash<ShadowView>{}(mutation.oldChildShadowView);
227
- #ifdef RN_DEBUG_STRING_CONVERTIBLE
228
- LOG(ERROR) << "OldStubView: "
229
- << getDebugPropsDescription((ShadowView)*oldStubView, {});
230
- LOG(ERROR) << "OldChildShadowView: "
231
- << getDebugPropsDescription(
232
- mutation.oldChildShadowView, {});
233
- #endif
234
- }
235
- react_native_assert(
236
- (ShadowView)(*oldStubView) == mutation.oldChildShadowView);
237
- oldStubView->update(mutation.newChildShadowView);
238
-
239
- // Hash for stub view and the ShadowView should be identical - this
240
- // tests that StubView and ShadowView hash are equivalent.
241
- react_native_assert(
242
- std::hash<ShadowView>{}((ShadowView)*oldStubView) ==
243
- std::hash<ShadowView>{}(mutation.newChildShadowView));
244
-
245
- break;
246
- }
247
- }
248
- }
249
- STUB_VIEW_LOG({ LOG(ERROR) << "StubView: Mutating End"; });
250
-
251
- // For iOS especially: flush logs because some might be lost on iOS if an
252
- // assert is hit right after this.
253
- google::FlushLogFiles(google::INFO);
254
- }
255
-
256
- bool operator==(StubViewTree const &lhs, StubViewTree const &rhs) {
257
- if (lhs.registry.size() != rhs.registry.size()) {
258
- STUB_VIEW_LOG({
259
- LOG(ERROR) << "Registry sizes are different. Sizes: LHS: "
260
- << lhs.registry.size() << " RHS: " << rhs.registry.size();
261
-
262
- [&](std::ostream &stream) -> std::ostream & {
263
- stream << "Tags in LHS: ";
264
- for (auto const &pair : lhs.registry) {
265
- auto &lhsStubView = *lhs.registry.at(pair.first);
266
- stream << "[" << lhsStubView.tag << "]##"
267
- << std::hash<ShadowView>{}((ShadowView)lhsStubView) << " ";
268
- }
269
- return stream;
270
- }(LOG(ERROR));
271
-
272
- [&](std::ostream &stream) -> std::ostream & {
273
- stream << "Tags in RHS: ";
274
- for (auto const &pair : rhs.registry) {
275
- auto &rhsStubView = *rhs.registry.at(pair.first);
276
- stream << "[" << rhsStubView.tag << "]##"
277
- << std::hash<ShadowView>{}((ShadowView)rhsStubView) << " ";
278
- }
279
- return stream;
280
- }(LOG(ERROR));
281
- });
282
-
283
- return false;
284
- }
285
-
286
- for (auto const &pair : lhs.registry) {
287
- auto &lhsStubView = *lhs.registry.at(pair.first);
288
- auto &rhsStubView = *rhs.registry.at(pair.first);
289
-
290
- if (lhsStubView != rhsStubView) {
291
- STUB_VIEW_LOG({
292
- LOG(ERROR) << "Registry entries are different. LHS: ["
293
- << lhsStubView.tag << "] ##"
294
- << std::hash<ShadowView>{}((ShadowView)lhsStubView)
295
- << " RHS: [" << rhsStubView.tag << "] ##"
296
- << std::hash<ShadowView>{}((ShadowView)rhsStubView);
297
- });
298
- return false;
299
- }
300
- }
301
-
302
- return true;
303
- }
304
-
305
- bool operator!=(StubViewTree const &lhs, StubViewTree const &rhs) {
306
- return !(lhs == rhs);
307
- }
308
-
309
- } // namespace react
310
- } // namespace facebook