From 9444f7e862625fece29b3feb5103c028e5afee9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20Kapa=C5=82a?= Date: Wed, 2 Jul 2025 19:17:46 +0200 Subject: [PATCH 1/6] Update ComponentDescriptorProviderRegistry.cpp --- .../ComponentDescriptorProviderRegistry.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp b/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp index 0a949f0fb081ce..5afdf8471f33e7 100644 --- a/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp +++ b/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp @@ -71,10 +71,19 @@ ComponentDescriptorProviderRegistry::createComponentDescriptorRegistry( auto registry = std::make_shared( parameters, *this, parameters.contextContainer); + // for (const auto& pair : componentDescriptorProviders_) { + // registry->add(pair.second); + // } + + std::vector providers; + providers.reserve(componentDescriptorProviders_.size()); for (const auto& pair : componentDescriptorProviders_) { - registry->add(pair.second); + providers.push_back(pair.second); } + // 2) enqueue async add + registry->addMultipleAsync(std::move(providers)); + componentDescriptorRegistries_.push_back(registry); return registry; From 0f21b710667018fa07dc5d8cbdb41ec49fcafcb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20Kapa=C5=82a?= Date: Wed, 2 Jul 2025 19:19:52 +0200 Subject: [PATCH 2/6] Update ComponentDescriptorRegistry.h --- .../renderer/componentregistry/ComponentDescriptorRegistry.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.h b/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.h index 20bce41f2dcf47..44c564fe76f929 100644 --- a/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.h +++ b/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.h @@ -15,6 +15,7 @@ #include #include #include +#include namespace facebook::react { @@ -40,6 +41,8 @@ class ComponentDescriptorRegistry { const ComponentDescriptorProviderRegistry& providerRegistry, ContextContainer::Shared contextContainer); + void addMultipleAsync(std::vector providers) const; + /* * This is broken. Please do not use. * If you requesting a ComponentDescriptor and unsure that it's there, you are From 92eb06749bd024ed7616b58453dc17fc6ea6faeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20Kapa=C5=82a?= Date: Wed, 2 Jul 2025 19:22:05 +0200 Subject: [PATCH 3/6] Update ComponentDescriptorProviderRegistry.cpp --- .../ComponentDescriptorProviderRegistry.cpp | 187 ++++++++++++------ 1 file changed, 129 insertions(+), 58 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp b/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp index 5afdf8471f33e7..83e80df578148b 100644 --- a/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp +++ b/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp @@ -5,88 +5,159 @@ * LICENSE file in the root directory of this source tree. */ -#include "ComponentDescriptorProviderRegistry.h" +#include "ComponentDescriptorRegistry.h" + +#include "componentNameByReactViewName.h" + +#include +#include +#include +#include +#include +#include +#include namespace facebook::react { -void ComponentDescriptorProviderRegistry::add( - const ComponentDescriptorProvider& provider) const { - std::unique_lock lock(mutex_); +ComponentDescriptorRegistry::ComponentDescriptorRegistry( + ComponentDescriptorParameters parameters, + const ComponentDescriptorProviderRegistry& providerRegistry, + ContextContainer::Shared contextContainer) + : parameters_(std::move(parameters)), + providerRegistry_(providerRegistry), + contextContainer_(std::move(contextContainer)) {} + +void ComponentDescriptorRegistry::addMultipleAsync( + std::vector providers) const { + // Copy everything we need before the thread starts + auto parametersCopy = parameters_; + auto contextContainerCopy = contextContainer_; + + // Start thread immediately + std::thread([this, providers = std::move(providers), parametersCopy, contextContainerCopy]() { + std::unique_lock lock(mutex_); + + for (const auto& provider : providers) { + auto componentDescriptor = provider.constructor( + {parametersCopy.eventDispatcher, + contextContainerCopy, + provider.flavor}); + + react_native_assert(componentDescriptor->getComponentHandle() == provider.handle); + react_native_assert(componentDescriptor->getComponentName() == provider.name); + + auto sharedComponentDescriptor = + std::shared_ptr(std::move(componentDescriptor)); + + _registryByHandle[provider.handle] = sharedComponentDescriptor; + _registryByName[provider.name] = sharedComponentDescriptor; + } + }).detach(); +} - /* - // TODO: T57583139 - The assert is temporarily disabled to reduce the volume of the signal. - 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; - } +void ComponentDescriptorRegistry::add( + ComponentDescriptorProvider componentDescriptorProvider) const { + std::unique_lock lock(mutex_); - componentDescriptorProviders_.insert({provider.handle, provider}); + auto componentDescriptor = componentDescriptorProvider.constructor( + {parameters_.eventDispatcher, + parameters_.contextContainer, + componentDescriptorProvider.flavor}); + react_native_assert( + componentDescriptor->getComponentHandle() == + componentDescriptorProvider.handle); + react_native_assert( + componentDescriptor->getComponentName() == + componentDescriptorProvider.name); + + auto sharedComponentDescriptor = std::shared_ptr( + std::move(componentDescriptor)); + _registryByHandle[componentDescriptorProvider.handle] = + sharedComponentDescriptor; + _registryByName[componentDescriptorProvider.name] = sharedComponentDescriptor; +} - for (const auto& weakRegistry : componentDescriptorRegistries_) { - auto registry = weakRegistry.lock(); - if (!registry) { - continue; - } +void ComponentDescriptorRegistry::registerComponentDescriptor( + const SharedComponentDescriptor& componentDescriptor) const { + ComponentHandle componentHandle = componentDescriptor->getComponentHandle(); + _registryByHandle[componentHandle] = componentDescriptor; - registry->add(provider); - } + ComponentName componentName = componentDescriptor->getComponentName(); + _registryByName[componentName] = componentDescriptor; } -void ComponentDescriptorProviderRegistry::setComponentDescriptorProviderRequest( - ComponentDescriptorProviderRequest componentDescriptorProviderRequest) - const { +const ComponentDescriptor& ComponentDescriptorRegistry::at( + const std::string& componentName) const { std::shared_lock lock(mutex_); - componentDescriptorProviderRequest_ = - std::move(componentDescriptorProviderRequest); -} -void ComponentDescriptorProviderRegistry::request( - ComponentName componentName) const { - ComponentDescriptorProviderRequest componentDescriptorProviderRequest; + auto unifiedComponentName = componentNameByReactViewName(componentName); + + auto it = _registryByName.find(unifiedComponentName); + if (it == _registryByName.end()) { + lock.unlock(); + providerRegistry_.request(unifiedComponentName.c_str()); + lock.lock(); - { - std::shared_lock lock(mutex_); - componentDescriptorProviderRequest = componentDescriptorProviderRequest_; + it = _registryByName.find(unifiedComponentName); + + /* + * TODO: T54849676 + * Uncomment the `assert` after the following block that checks + * `_fallbackComponentDescriptor` is no longer needed. The assert assumes + * that `componentDescriptorProviderRequest` is always not null and register + * some component on every single request. + */ + // assert(it != _registryByName.end()); } - if (componentDescriptorProviderRequest) { - componentDescriptorProviderRequest(componentName); + if (it == _registryByName.end()) { + auto componentDescriptor = std::make_shared< + const UnstableLegacyViewManagerAutomaticComponentDescriptor>( + parameters_, unifiedComponentName); + registerComponentDescriptor(componentDescriptor); + return *_registryByName.find(unifiedComponentName)->second; } + + return *it->second; } -ComponentDescriptorRegistry::Shared -ComponentDescriptorProviderRegistry::createComponentDescriptorRegistry( - const ComponentDescriptorParameters& parameters) const { +const ComponentDescriptor* ComponentDescriptorRegistry:: + findComponentDescriptorByHandle_DO_NOT_USE_THIS_IS_BROKEN( + ComponentHandle componentHandle) const { std::shared_lock lock(mutex_); - auto registry = std::make_shared( - parameters, *this, parameters.contextContainer); + auto iterator = _registryByHandle.find(componentHandle); + if (iterator == _registryByHandle.end()) { + return nullptr; + } - // for (const auto& pair : componentDescriptorProviders_) { - // registry->add(pair.second); - // } + return iterator->second.get(); +} - std::vector providers; - providers.reserve(componentDescriptorProviders_.size()); - for (const auto& pair : componentDescriptorProviders_) { - providers.push_back(pair.second); - } +const ComponentDescriptor& ComponentDescriptorRegistry::at( + ComponentHandle componentHandle) const { + std::shared_lock lock(mutex_); - // 2) enqueue async add - registry->addMultipleAsync(std::move(providers)); + return *_registryByHandle.at(componentHandle); +} + +bool ComponentDescriptorRegistry::hasComponentDescriptorAt( + ComponentHandle componentHandle) const { + std::shared_lock lock(mutex_); - componentDescriptorRegistries_.push_back(registry); + auto iterator = _registryByHandle.find(componentHandle); + return iterator != _registryByHandle.end(); +} + +void ComponentDescriptorRegistry::setFallbackComponentDescriptor( + const SharedComponentDescriptor& descriptor) { + _fallbackComponentDescriptor = descriptor; + registerComponentDescriptor(descriptor); +} - return registry; +ComponentDescriptor::Shared +ComponentDescriptorRegistry::getFallbackComponentDescriptor() const { + return _fallbackComponentDescriptor; } } // namespace facebook::react From c5ae26625263f3da961deaa6a37756dacb282fb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20Kapa=C5=82a?= Date: Wed, 2 Jul 2025 19:30:51 +0200 Subject: [PATCH 4/6] Update ComponentDescriptorRegistry.cpp --- .../ComponentDescriptorRegistry.cpp | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp b/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp index 3c5487b240de68..83e80df578148b 100644 --- a/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp +++ b/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp @@ -27,6 +27,34 @@ ComponentDescriptorRegistry::ComponentDescriptorRegistry( providerRegistry_(providerRegistry), contextContainer_(std::move(contextContainer)) {} +void ComponentDescriptorRegistry::addMultipleAsync( + std::vector providers) const { + // Copy everything we need before the thread starts + auto parametersCopy = parameters_; + auto contextContainerCopy = contextContainer_; + + // Start thread immediately + std::thread([this, providers = std::move(providers), parametersCopy, contextContainerCopy]() { + std::unique_lock lock(mutex_); + + for (const auto& provider : providers) { + auto componentDescriptor = provider.constructor( + {parametersCopy.eventDispatcher, + contextContainerCopy, + provider.flavor}); + + react_native_assert(componentDescriptor->getComponentHandle() == provider.handle); + react_native_assert(componentDescriptor->getComponentName() == provider.name); + + auto sharedComponentDescriptor = + std::shared_ptr(std::move(componentDescriptor)); + + _registryByHandle[provider.handle] = sharedComponentDescriptor; + _registryByName[provider.name] = sharedComponentDescriptor; + } + }).detach(); +} + void ComponentDescriptorRegistry::add( ComponentDescriptorProvider componentDescriptorProvider) const { std::unique_lock lock(mutex_); From 9c72ce1cf0e28016b955a393332289d80b742856 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20Kapa=C5=82a?= Date: Wed, 2 Jul 2025 19:32:47 +0200 Subject: [PATCH 5/6] Update ComponentDescriptorProviderRegistry.cpp --- .../ComponentDescriptorProviderRegistry.cpp | 187 ++++++------------ 1 file changed, 58 insertions(+), 129 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp b/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp index 83e80df578148b..5afdf8471f33e7 100644 --- a/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp +++ b/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp @@ -5,159 +5,88 @@ * LICENSE file in the root directory of this source tree. */ -#include "ComponentDescriptorRegistry.h" - -#include "componentNameByReactViewName.h" - -#include -#include -#include -#include -#include -#include -#include +#include "ComponentDescriptorProviderRegistry.h" namespace facebook::react { -ComponentDescriptorRegistry::ComponentDescriptorRegistry( - ComponentDescriptorParameters parameters, - const ComponentDescriptorProviderRegistry& providerRegistry, - ContextContainer::Shared contextContainer) - : parameters_(std::move(parameters)), - providerRegistry_(providerRegistry), - contextContainer_(std::move(contextContainer)) {} - -void ComponentDescriptorRegistry::addMultipleAsync( - std::vector providers) const { - // Copy everything we need before the thread starts - auto parametersCopy = parameters_; - auto contextContainerCopy = contextContainer_; - - // Start thread immediately - std::thread([this, providers = std::move(providers), parametersCopy, contextContainerCopy]() { - std::unique_lock lock(mutex_); - - for (const auto& provider : providers) { - auto componentDescriptor = provider.constructor( - {parametersCopy.eventDispatcher, - contextContainerCopy, - provider.flavor}); - - react_native_assert(componentDescriptor->getComponentHandle() == provider.handle); - react_native_assert(componentDescriptor->getComponentName() == provider.name); - - auto sharedComponentDescriptor = - std::shared_ptr(std::move(componentDescriptor)); - - _registryByHandle[provider.handle] = sharedComponentDescriptor; - _registryByName[provider.name] = sharedComponentDescriptor; - } - }).detach(); -} - -void ComponentDescriptorRegistry::add( - ComponentDescriptorProvider componentDescriptorProvider) const { +void ComponentDescriptorProviderRegistry::add( + const ComponentDescriptorProvider& provider) const { std::unique_lock lock(mutex_); - auto componentDescriptor = componentDescriptorProvider.constructor( - {parameters_.eventDispatcher, - parameters_.contextContainer, - componentDescriptorProvider.flavor}); - react_native_assert( - componentDescriptor->getComponentHandle() == - componentDescriptorProvider.handle); - react_native_assert( - componentDescriptor->getComponentName() == - componentDescriptorProvider.name); - - auto sharedComponentDescriptor = std::shared_ptr( - std::move(componentDescriptor)); - _registryByHandle[componentDescriptorProvider.handle] = - sharedComponentDescriptor; - _registryByName[componentDescriptorProvider.name] = sharedComponentDescriptor; -} + /* + // TODO: T57583139 + The assert is temporarily disabled to reduce the volume of the signal. + 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}); -void ComponentDescriptorRegistry::registerComponentDescriptor( - const SharedComponentDescriptor& componentDescriptor) const { - ComponentHandle componentHandle = componentDescriptor->getComponentHandle(); - _registryByHandle[componentHandle] = componentDescriptor; + for (const auto& weakRegistry : componentDescriptorRegistries_) { + auto registry = weakRegistry.lock(); + if (!registry) { + continue; + } - ComponentName componentName = componentDescriptor->getComponentName(); - _registryByName[componentName] = componentDescriptor; + registry->add(provider); + } } -const ComponentDescriptor& ComponentDescriptorRegistry::at( - const std::string& componentName) const { +void ComponentDescriptorProviderRegistry::setComponentDescriptorProviderRequest( + ComponentDescriptorProviderRequest componentDescriptorProviderRequest) + const { std::shared_lock lock(mutex_); + componentDescriptorProviderRequest_ = + std::move(componentDescriptorProviderRequest); +} - auto unifiedComponentName = componentNameByReactViewName(componentName); - - auto it = _registryByName.find(unifiedComponentName); - if (it == _registryByName.end()) { - lock.unlock(); - providerRegistry_.request(unifiedComponentName.c_str()); - lock.lock(); - - it = _registryByName.find(unifiedComponentName); +void ComponentDescriptorProviderRegistry::request( + ComponentName componentName) const { + ComponentDescriptorProviderRequest componentDescriptorProviderRequest; - /* - * TODO: T54849676 - * Uncomment the `assert` after the following block that checks - * `_fallbackComponentDescriptor` is no longer needed. The assert assumes - * that `componentDescriptorProviderRequest` is always not null and register - * some component on every single request. - */ - // assert(it != _registryByName.end()); + { + std::shared_lock lock(mutex_); + componentDescriptorProviderRequest = componentDescriptorProviderRequest_; } - if (it == _registryByName.end()) { - auto componentDescriptor = std::make_shared< - const UnstableLegacyViewManagerAutomaticComponentDescriptor>( - parameters_, unifiedComponentName); - registerComponentDescriptor(componentDescriptor); - return *_registryByName.find(unifiedComponentName)->second; + if (componentDescriptorProviderRequest) { + componentDescriptorProviderRequest(componentName); } - - return *it->second; } -const ComponentDescriptor* ComponentDescriptorRegistry:: - findComponentDescriptorByHandle_DO_NOT_USE_THIS_IS_BROKEN( - ComponentHandle componentHandle) const { +ComponentDescriptorRegistry::Shared +ComponentDescriptorProviderRegistry::createComponentDescriptorRegistry( + const ComponentDescriptorParameters& parameters) const { std::shared_lock lock(mutex_); - auto iterator = _registryByHandle.find(componentHandle); - if (iterator == _registryByHandle.end()) { - return nullptr; - } - - return iterator->second.get(); -} - -const ComponentDescriptor& ComponentDescriptorRegistry::at( - ComponentHandle componentHandle) const { - std::shared_lock lock(mutex_); + auto registry = std::make_shared( + parameters, *this, parameters.contextContainer); - return *_registryByHandle.at(componentHandle); -} + // for (const auto& pair : componentDescriptorProviders_) { + // registry->add(pair.second); + // } -bool ComponentDescriptorRegistry::hasComponentDescriptorAt( - ComponentHandle componentHandle) const { - std::shared_lock lock(mutex_); + std::vector providers; + providers.reserve(componentDescriptorProviders_.size()); + for (const auto& pair : componentDescriptorProviders_) { + providers.push_back(pair.second); + } - auto iterator = _registryByHandle.find(componentHandle); - return iterator != _registryByHandle.end(); -} + // 2) enqueue async add + registry->addMultipleAsync(std::move(providers)); -void ComponentDescriptorRegistry::setFallbackComponentDescriptor( - const SharedComponentDescriptor& descriptor) { - _fallbackComponentDescriptor = descriptor; - registerComponentDescriptor(descriptor); -} + componentDescriptorRegistries_.push_back(registry); -ComponentDescriptor::Shared -ComponentDescriptorRegistry::getFallbackComponentDescriptor() const { - return _fallbackComponentDescriptor; + return registry; } } // namespace facebook::react From abe6da82bd417b1764785febf95cbcd4ed56561e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20Kapa=C5=82a?= Date: Wed, 27 Aug 2025 14:02:30 +0200 Subject: [PATCH 6/6] Attach current thread to JNI environment --- .../renderer/componentregistry/ComponentDescriptorRegistry.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp b/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp index 83e80df578148b..29d6da109f6fca 100644 --- a/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp +++ b/packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp @@ -16,6 +16,8 @@ #include #include #include +#include + namespace facebook::react { @@ -35,6 +37,7 @@ void ComponentDescriptorRegistry::addMultipleAsync( // Start thread immediately std::thread([this, providers = std::move(providers), parametersCopy, contextContainerCopy]() { + facebook::jni::Environment::ensureCurrentThreadIsAttached(); std::unique_lock lock(mutex_); for (const auto& provider : providers) {