mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Summary: We suspect that the re-registration of `ComponentDescriptorProvider`s during Bridge reloading might cause crashes in Fabric core. That happens because the re-registration process replaces already existing and being used ComponentDescriptors in the managed registries with the exact same new ones, which forces old ones to be deallocated and all pointers to them invalid. (On of the fundamental Fabric design decision is that `ShadowNode`s don't own/retain ComponentDescriptors.) It seems was already indirectly addressed in application code on iOS but still fixing that in the core is valuable. Android implementation does not use reactive component registration, so it was already fine. As the follow-up diff, we plan to remove "removing" capabilities from ComponentDescriptorRegistry and ComponentDescriptorProviderRegistry to make it even more future-proof. Changelog: [Internal] Fabric-specific internal change. Reviewed By: sammy-SC Differential Revision: D18273683 fbshipit-source-id: 7615627842855f078a3fdf3049f5511f59700972
96 lines
2.7 KiB
C++
96 lines
2.7 KiB
C++
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#include "ComponentDescriptorProviderRegistry.h"
|
|
|
|
namespace facebook {
|
|
namespace react {
|
|
|
|
void ComponentDescriptorProviderRegistry::add(
|
|
ComponentDescriptorProvider provider) const {
|
|
std::unique_lock<better::shared_mutex> lock(mutex_);
|
|
|
|
assert(
|
|
componentDescriptorProviders_.find(provider.handle) ==
|
|
componentDescriptorProviders_.end() &&
|
|
"Attempt to register an already registered ComponentDescriptorProvider.");
|
|
|
|
if (componentDescriptorProviders_.find(provider.handle) !=
|
|
componentDescriptorProviders_.end()) {
|
|
// Re-registering a provider makes no sense because it's copyable: already
|
|
// registered one is as good as any new can be.
|
|
return;
|
|
}
|
|
|
|
componentDescriptorProviders_.insert({provider.handle, provider});
|
|
|
|
for (auto const &weakRegistry : componentDescriptorRegistries_) {
|
|
auto registry = weakRegistry.lock();
|
|
if (!registry) {
|
|
continue;
|
|
}
|
|
|
|
registry->add(provider);
|
|
}
|
|
}
|
|
|
|
void ComponentDescriptorProviderRegistry::remove(
|
|
ComponentDescriptorProvider provider) const {
|
|
std::unique_lock<better::shared_mutex> lock(mutex_);
|
|
componentDescriptorProviders_.erase(provider.handle);
|
|
|
|
for (auto const &weakRegistry : componentDescriptorRegistries_) {
|
|
auto registry = weakRegistry.lock();
|
|
if (!registry) {
|
|
continue;
|
|
}
|
|
|
|
registry->remove(provider);
|
|
}
|
|
}
|
|
|
|
void ComponentDescriptorProviderRegistry::setComponentDescriptorProviderRequest(
|
|
ComponentDescriptorProviderRequest componentDescriptorProviderRequest)
|
|
const {
|
|
std::shared_lock<better::shared_mutex> lock(mutex_);
|
|
componentDescriptorProviderRequest_ = componentDescriptorProviderRequest;
|
|
}
|
|
|
|
void ComponentDescriptorProviderRegistry::request(
|
|
ComponentName componentName) const {
|
|
ComponentDescriptorProviderRequest componentDescriptorProviderRequest;
|
|
|
|
{
|
|
std::shared_lock<better::shared_mutex> lock(mutex_);
|
|
componentDescriptorProviderRequest = componentDescriptorProviderRequest_;
|
|
}
|
|
|
|
if (componentDescriptorProviderRequest) {
|
|
componentDescriptorProviderRequest(componentName);
|
|
}
|
|
}
|
|
|
|
ComponentDescriptorRegistry::Shared
|
|
ComponentDescriptorProviderRegistry::createComponentDescriptorRegistry(
|
|
ComponentDescriptorParameters const ¶meters) const {
|
|
std::shared_lock<better::shared_mutex> lock(mutex_);
|
|
|
|
auto registry =
|
|
std::make_shared<ComponentDescriptorRegistry const>(parameters, *this);
|
|
|
|
for (auto const &pair : componentDescriptorProviders_) {
|
|
registry->add(pair.second);
|
|
}
|
|
|
|
componentDescriptorRegistries_.push_back(registry);
|
|
|
|
return registry;
|
|
}
|
|
|
|
} // namespace react
|
|
} // namespace facebook
|