Skip to content

Commit f4d99d6

Browse files
RSNarafacebook-github-bot
authored andcommitted
Reland: [rn][ios] Bridgeless: Fix unstable_hasComponent (#51053)
Summary: Pull Request resolved: #51053 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, cipolleschi Differential Revision: D73949864 fbshipit-source-id: ac5b6fc373cb1b2436045ae1f78391f0712bca17
1 parent c514333 commit f4d99d6

File tree

2 files changed

+36
-37
lines changed

2 files changed

+36
-37
lines changed

packages/react-native/React/Fabric/Mounting/RCTComponentViewFactory.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,6 @@ void RCTInstallNativeComponentRegistryBinding(facebook::jsi::Runtime &runtime);
4848
*/
4949
- (void)registerComponentViewClass:(Class<RCTComponentViewProtocol>)componentViewClass;
5050

51-
/**
52-
* Registers component if there is a matching class. Returns true if it matching class is found or the component has
53-
* already been registered, false otherwise.
54-
*/
55-
- (BOOL)registerComponentIfPossible:(const std::string &)componentName;
56-
5751
/**
5852
* Creates a component view with given component handle.
5953
*/

packages/react-native/React/Fabric/Mounting/RCTComponentViewFactory.mm

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,19 @@
4545
using namespace facebook;
4646
using namespace facebook::react;
4747

48+
@interface RCTComponentViewFactory ()
49+
- (void)_registerComponentIfPossible:(const std::string &)name;
50+
- (BOOL)_wasComponentRegistered:(const std::string &)name;
51+
@end
52+
4853
// Allow JS runtime to register native components as needed. For static view configs.
4954
void RCTInstallNativeComponentRegistryBinding(facebook::jsi::Runtime &runtime)
5055
{
5156
auto hasComponentProvider = [](const std::string &name) -> bool {
52-
return [[RCTComponentViewFactory currentComponentViewFactory]
53-
registerComponentIfPossible:componentNameByReactViewName(name)];
57+
auto globalComponentViewFactory = [RCTComponentViewFactory currentComponentViewFactory];
58+
auto actualName = componentNameByReactViewName(name);
59+
[globalComponentViewFactory _registerComponentIfPossible:actualName];
60+
return [globalComponentViewFactory _wasComponentRegistered:actualName];
5461
};
5562
bindHasComponentProvider(runtime, std::move(hasComponentProvider));
5663
}
@@ -62,7 +69,7 @@ void RCTInstallNativeComponentRegistryBinding(facebook::jsi::Runtime &runtime)
6269

6370
@implementation RCTComponentViewFactory {
6471
std::unordered_map<ComponentHandle, RCTComponentViewClassDescriptor> _componentViewClasses;
65-
std::unordered_set<std::string> _registeredComponentsNames;
72+
std::unordered_map<std::string, bool> _registrationStatusMap;
6673
ComponentDescriptorProviderRegistry _providerRegistry;
6774
std::shared_mutex _mutex;
6875
}
@@ -81,7 +88,7 @@ + (RCTComponentViewFactory *)currentComponentViewFactory
8188

8289
componentViewFactory->_providerRegistry.setComponentDescriptorProviderRequest(
8390
[](ComponentName requestedComponentName) {
84-
[componentViewFactory registerComponentIfPossible:requestedComponentName];
91+
[componentViewFactory _registerComponentIfPossible:requestedComponentName];
8592
});
8693
});
8794

@@ -106,11 +113,16 @@ - (RCTComponentViewClassDescriptor)_componentViewClassDescriptorFromClass:(Class
106113
#pragma clang diagnostic pop
107114
}
108115

109-
- (BOOL)registerComponentIfPossible:(const std::string &)name
116+
- (BOOL)_wasComponentRegistered:(const std::string &)name
110117
{
111-
if (_registeredComponentsNames.find(name) != _registeredComponentsNames.end()) {
112-
// Component has already been registered.
113-
return YES;
118+
auto registrationResult = _registrationStatusMap.find(name);
119+
return registrationResult != _registrationStatusMap.end() && (registrationResult->second);
120+
}
121+
122+
- (void)_registerComponentIfPossible:(const std::string &)name
123+
{
124+
if (_registrationStatusMap.find(name) != _registrationStatusMap.end()) {
125+
return;
114126
}
115127

116128
// Paper name: we prepare this variables to warn the user
@@ -122,7 +134,7 @@ - (BOOL)registerComponentIfPossible:(const std::string &)name
122134
Class<RCTComponentViewProtocol> klass = RCTComponentViewClassWithName(name.c_str());
123135
if (klass) {
124136
[self registerComponentViewClass:klass];
125-
return YES;
137+
return;
126138
}
127139

128140
// Fallback 2: Ask the provider and check in the dictionary provided
@@ -133,7 +145,7 @@ - (BOOL)registerComponentIfPossible:(const std::string &)name
133145
klass = self.thirdPartyFabricComponentsProvider.thirdPartyFabricComponents[objcName];
134146
if (klass) {
135147
[self registerComponentViewClass:klass];
136-
return YES;
148+
return;
137149
}
138150
}
139151

@@ -153,52 +165,45 @@ - (BOOL)registerComponentIfPossible:(const std::string &)name
153165
auto componentHandle = reinterpret_cast<ComponentHandle>(componentName);
154166
auto constructor = [RCTLegacyViewManagerInteropComponentView componentDescriptorProvider].constructor;
155167

156-
[self _addDescriptorToProviderRegistry:ComponentDescriptorProvider{
157-
componentHandle, componentName, flavor, constructor}];
168+
auto provider = ComponentDescriptorProvider{componentHandle, componentName, flavor, constructor};
158169

170+
_providerRegistry.add(provider);
159171
_componentViewClasses[componentHandle] =
160172
[self _componentViewClassDescriptorFromClass:[RCTLegacyViewManagerInteropComponentView class]];
161-
return YES;
173+
_registrationStatusMap.insert({provider.name, true});
174+
return;
162175
}
163176

164177
// Fallback 4: use <UnimplementedView> if component doesn't exist.
165178
auto flavor = std::make_shared<const std::string>(name);
166179
auto componentName = ComponentName{flavor->c_str()};
167180
auto componentHandle = reinterpret_cast<ComponentHandle>(componentName);
168181
auto constructor = [RCTUnimplementedViewComponentView componentDescriptorProvider].constructor;
182+
auto provider = ComponentDescriptorProvider{componentHandle, componentName, flavor, constructor};
169183

170-
[self _addDescriptorToProviderRegistry:ComponentDescriptorProvider{
171-
componentHandle, componentName, flavor, constructor}];
172-
184+
_providerRegistry.add(provider);
173185
_componentViewClasses[componentHandle] =
174186
[self _componentViewClassDescriptorFromClass:[RCTUnimplementedViewComponentView class]];
175-
176-
// No matching class exists for `name`.
177-
return NO;
187+
_registrationStatusMap.insert({provider.name, false});
178188
}
179189

180190
- (void)registerComponentViewClass:(Class<RCTComponentViewProtocol>)componentViewClass
181191
{
182192
RCTAssert(componentViewClass, @"RCTComponentViewFactory: Provided `componentViewClass` is `nil`.");
183193
std::unique_lock lock(_mutex);
184194

185-
auto componentDescriptorProvider = [componentViewClass componentDescriptorProvider];
186-
_componentViewClasses[componentDescriptorProvider.handle] =
187-
[self _componentViewClassDescriptorFromClass:componentViewClass];
188-
[self _addDescriptorToProviderRegistry:componentDescriptorProvider];
195+
auto provider = [componentViewClass componentDescriptorProvider];
196+
_componentViewClasses[provider.handle] = [self _componentViewClassDescriptorFromClass:componentViewClass];
197+
_providerRegistry.add(provider);
198+
_registrationStatusMap.insert({provider.name, true});
189199

190200
auto supplementalComponentDescriptorProviders = [componentViewClass supplementalComponentDescriptorProviders];
191-
for (const auto &provider : supplementalComponentDescriptorProviders) {
192-
[self _addDescriptorToProviderRegistry:provider];
201+
for (const auto &supplementalProvider : supplementalComponentDescriptorProviders) {
202+
_providerRegistry.add(supplementalProvider);
203+
_registrationStatusMap.insert({supplementalProvider.name, true});
193204
}
194205
}
195206

196-
- (void)_addDescriptorToProviderRegistry:(const ComponentDescriptorProvider &)provider
197-
{
198-
_registeredComponentsNames.insert(provider.name);
199-
_providerRegistry.add(provider);
200-
}
201-
202207
- (RCTComponentViewDescriptor)createComponentViewWithComponentHandle:(facebook::react::ComponentHandle)componentHandle
203208
{
204209
RCTAssertMainQueue();

0 commit comments

Comments
 (0)