mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Bridgeless: Fix unstable_hasComponent
Summary: unstable_hasComponent(component) first registers the component with react native, if possible. Then, it returns you whether registration succeeded. ## Problem For unregistered components, the initial call returns false. But, all subsequent calls return true. The reason why: After the initial call fails, react native registers unimplemented view under that component name. So, all subsequent calls return true. ## Solution Just record the initial loopup result. And always return that initial lookup result from this method. Changelog: [iOS][Fixed] Fix bug: unstable_hasComponent(*) = true for unregistered components for n > 1th call. Reviewed By: yungsters Differential Revision: D73127468 fbshipit-source-id: ee30bde486a6bb970f40f654c65a8946452f49b3
This commit is contained in:
committed by
Facebook GitHub Bot
parent
f144b53122
commit
fa9d082747
@@ -48,12 +48,6 @@ void RCTInstallNativeComponentRegistryBinding(facebook::jsi::Runtime &runtime);
|
||||
*/
|
||||
- (void)registerComponentViewClass:(Class<RCTComponentViewProtocol>)componentViewClass;
|
||||
|
||||
/**
|
||||
* Registers component if there is a matching class. Returns true if it matching class is found or the component has
|
||||
* already been registered, false otherwise.
|
||||
*/
|
||||
- (BOOL)registerComponentIfPossible:(const std::string &)componentName;
|
||||
|
||||
/**
|
||||
* Creates a component view with given component handle.
|
||||
*/
|
||||
|
||||
@@ -45,12 +45,18 @@
|
||||
using namespace facebook;
|
||||
using namespace facebook::react;
|
||||
|
||||
@interface RCTComponentViewFactory ()
|
||||
- (void)_registerComponentIfPossible:(const std::string &)name;
|
||||
- (BOOL)_wasComponentRegistered:(const std::string &)name;
|
||||
@end
|
||||
|
||||
// Allow JS runtime to register native components as needed. For static view configs.
|
||||
void RCTInstallNativeComponentRegistryBinding(facebook::jsi::Runtime &runtime)
|
||||
{
|
||||
auto hasComponentProvider = [](const std::string &name) -> bool {
|
||||
return [[RCTComponentViewFactory currentComponentViewFactory]
|
||||
registerComponentIfPossible:componentNameByReactViewName(name)];
|
||||
auto globalComponentViewFactory = [RCTComponentViewFactory currentComponentViewFactory];
|
||||
[globalComponentViewFactory _registerComponentIfPossible:name];
|
||||
return [globalComponentViewFactory _wasComponentRegistered:name];
|
||||
};
|
||||
bindHasComponentProvider(runtime, std::move(hasComponentProvider));
|
||||
}
|
||||
@@ -62,7 +68,7 @@ static Class<RCTComponentViewProtocol> RCTComponentViewClassWithName(const char
|
||||
|
||||
@implementation RCTComponentViewFactory {
|
||||
std::unordered_map<ComponentHandle, RCTComponentViewClassDescriptor> _componentViewClasses;
|
||||
std::unordered_set<std::string> _registeredComponentsNames;
|
||||
std::unordered_map<std::string, bool> _registrationStatusMap;
|
||||
ComponentDescriptorProviderRegistry _providerRegistry;
|
||||
std::shared_mutex _mutex;
|
||||
}
|
||||
@@ -81,7 +87,7 @@ static Class<RCTComponentViewProtocol> RCTComponentViewClassWithName(const char
|
||||
|
||||
componentViewFactory->_providerRegistry.setComponentDescriptorProviderRequest(
|
||||
[](ComponentName requestedComponentName) {
|
||||
[componentViewFactory registerComponentIfPossible:requestedComponentName];
|
||||
[componentViewFactory _registerComponentIfPossible:requestedComponentName];
|
||||
});
|
||||
});
|
||||
|
||||
@@ -106,11 +112,16 @@ static Class<RCTComponentViewProtocol> RCTComponentViewClassWithName(const char
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
- (BOOL)registerComponentIfPossible:(const std::string &)name
|
||||
- (BOOL)_wasComponentRegistered:(const std::string &)name
|
||||
{
|
||||
if (_registeredComponentsNames.find(name) != _registeredComponentsNames.end()) {
|
||||
// Component has already been registered.
|
||||
return YES;
|
||||
auto registrationResult = _registrationStatusMap.find(name);
|
||||
return registrationResult != _registrationStatusMap.end() && (registrationResult->second);
|
||||
}
|
||||
|
||||
- (void)_registerComponentIfPossible:(const std::string &)name
|
||||
{
|
||||
if (_registrationStatusMap.find(name) != _registrationStatusMap.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Paper name: we prepare this variables to warn the user
|
||||
@@ -122,7 +133,7 @@ static Class<RCTComponentViewProtocol> RCTComponentViewClassWithName(const char
|
||||
Class<RCTComponentViewProtocol> klass = RCTComponentViewClassWithName(name.c_str());
|
||||
if (klass) {
|
||||
[self registerComponentViewClass:klass];
|
||||
return YES;
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback 2: Ask the provider and check in the dictionary provided
|
||||
@@ -133,7 +144,7 @@ static Class<RCTComponentViewProtocol> RCTComponentViewClassWithName(const char
|
||||
klass = self.thirdPartyFabricComponentsProvider.thirdPartyFabricComponents[objcName];
|
||||
if (klass) {
|
||||
[self registerComponentViewClass:klass];
|
||||
return YES;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,12 +164,13 @@ static Class<RCTComponentViewProtocol> RCTComponentViewClassWithName(const char
|
||||
auto componentHandle = reinterpret_cast<ComponentHandle>(componentName);
|
||||
auto constructor = [RCTLegacyViewManagerInteropComponentView componentDescriptorProvider].constructor;
|
||||
|
||||
[self _addDescriptorToProviderRegistry:ComponentDescriptorProvider{
|
||||
componentHandle, componentName, flavor, constructor}];
|
||||
auto provider = ComponentDescriptorProvider{componentHandle, componentName, flavor, constructor};
|
||||
|
||||
_providerRegistry.add(provider);
|
||||
_componentViewClasses[componentHandle] =
|
||||
[self _componentViewClassDescriptorFromClass:[RCTLegacyViewManagerInteropComponentView class]];
|
||||
return YES;
|
||||
_registrationStatusMap.insert({provider.name, true});
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback 4: use <UnimplementedView> if component doesn't exist.
|
||||
@@ -166,15 +178,12 @@ static Class<RCTComponentViewProtocol> RCTComponentViewClassWithName(const char
|
||||
auto componentName = ComponentName{flavor->c_str()};
|
||||
auto componentHandle = reinterpret_cast<ComponentHandle>(componentName);
|
||||
auto constructor = [RCTUnimplementedViewComponentView componentDescriptorProvider].constructor;
|
||||
auto provider = ComponentDescriptorProvider{componentHandle, componentName, flavor, constructor};
|
||||
|
||||
[self _addDescriptorToProviderRegistry:ComponentDescriptorProvider{
|
||||
componentHandle, componentName, flavor, constructor}];
|
||||
|
||||
_providerRegistry.add(provider);
|
||||
_componentViewClasses[componentHandle] =
|
||||
[self _componentViewClassDescriptorFromClass:[RCTUnimplementedViewComponentView class]];
|
||||
|
||||
// No matching class exists for `name`.
|
||||
return NO;
|
||||
_registrationStatusMap.insert({provider.name, false});
|
||||
}
|
||||
|
||||
- (void)registerComponentViewClass:(Class<RCTComponentViewProtocol>)componentViewClass
|
||||
@@ -182,23 +191,18 @@ static Class<RCTComponentViewProtocol> RCTComponentViewClassWithName(const char
|
||||
RCTAssert(componentViewClass, @"RCTComponentViewFactory: Provided `componentViewClass` is `nil`.");
|
||||
std::unique_lock lock(_mutex);
|
||||
|
||||
auto componentDescriptorProvider = [componentViewClass componentDescriptorProvider];
|
||||
_componentViewClasses[componentDescriptorProvider.handle] =
|
||||
[self _componentViewClassDescriptorFromClass:componentViewClass];
|
||||
[self _addDescriptorToProviderRegistry:componentDescriptorProvider];
|
||||
auto provider = [componentViewClass componentDescriptorProvider];
|
||||
_componentViewClasses[provider.handle] = [self _componentViewClassDescriptorFromClass:componentViewClass];
|
||||
_providerRegistry.add(provider);
|
||||
_registrationStatusMap.insert({provider.name, true});
|
||||
|
||||
auto supplementalComponentDescriptorProviders = [componentViewClass supplementalComponentDescriptorProviders];
|
||||
for (const auto &provider : supplementalComponentDescriptorProviders) {
|
||||
[self _addDescriptorToProviderRegistry:provider];
|
||||
for (const auto &supplementalProvider : supplementalComponentDescriptorProviders) {
|
||||
_providerRegistry.add(supplementalProvider);
|
||||
_registrationStatusMap.insert({supplementalProvider.name, true});
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_addDescriptorToProviderRegistry:(const ComponentDescriptorProvider &)provider
|
||||
{
|
||||
_registeredComponentsNames.insert(provider.name);
|
||||
_providerRegistry.add(provider);
|
||||
}
|
||||
|
||||
- (RCTComponentViewDescriptor)createComponentViewWithComponentHandle:(facebook::react::ComponentHandle)componentHandle
|
||||
{
|
||||
RCTAssertMainQueue();
|
||||
|
||||
Reference in New Issue
Block a user