Skip to content

Commit 8aab00e

Browse files
Adam Ernstmeta-codesync[bot]
authored andcommitted
RCTEventEmitter: minor fix to callableJSModule check (#57182)
Summary: Pull Request resolved: #57182 Guard against possibly deallocated RCTCallableJSModules. Changelog: [Internal] Reviewed By: fkgozali, javache Differential Revision: D108361186 fbshipit-source-id: 33f325742571b473ee12736afd80aff2bb717665
1 parent df6de4f commit 8aab00e

1 file changed

Lines changed: 30 additions & 10 deletions

File tree

packages/react-native/React/Modules/RCTEventEmitter.m

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@
1414
@implementation RCTEventEmitter {
1515
NSInteger _listenerCount;
1616
BOOL _observationDisabled;
17+
// Set to YES when -setCallableJSModules: is called with a non-nil value.
18+
// _callableJSModules is weak and can return to nil after wiring (e.g. on
19+
// host teardown) while this instance lives on, so the current value of
20+
// _callableJSModules can't tell us whether we were ever set up correctly.
21+
// This flag can.
22+
BOOL _callableJSModulesWasInitialized;
1723
}
1824

1925
@synthesize callableJSModules = _callableJSModules;
@@ -40,15 +46,14 @@ - (instancetype)initWithDisabledObservation
4046

4147
- (void)sendEventWithName:(NSString *)eventName body:(id)body
4248
{
43-
// Assert that subclasses of RCTEventEmitter does not have `@synthesize _callableJSModules`
44-
// which would cause _callableJSModules in the parent RCTEventEmitter to be nil.
4549
RCTAssert(
46-
_callableJSModules != nil,
47-
@"Error when sending event: %@ with body: %@. "
50+
_callableJSModulesWasInitialized,
51+
@"Error when sending event: %@ (listenerCount: %lld) with body: %@. "
4852
"RCTCallableJSModules is not set. This is probably because you've "
4953
"explicitly synthesized the RCTCallableJSModules in %@, even though it's inherited "
5054
"from RCTEventEmitter.",
5155
eventName,
56+
(long long)_listenerCount,
5257
body,
5358
[self class]);
5459

@@ -60,14 +65,29 @@ - (void)sendEventWithName:(NSString *)eventName body:(id)body
6065
[[self supportedEvents] componentsJoinedByString:@"`, `"]);
6166
}
6267

63-
BOOL shouldEmitEvent = (_observationDisabled || _listenerCount > 0);
68+
// _callableJSModules is weak, so read it exactly once into a strong local.
69+
RCTCallableJSModules *callableJSModules = _callableJSModules;
70+
if (!callableJSModules) {
71+
RCTLogWarn(@"Sending `%@` but callableJSModules is nil, bridge was probably torn down", eventName);
72+
return;
73+
}
6474

65-
if (shouldEmitEvent && _callableJSModules) {
66-
[_callableJSModules invokeModule:@"RCTDeviceEventEmitter"
67-
method:@"emit"
68-
withArgs:body ? @[ eventName, body ] : @[ eventName ]];
69-
} else {
75+
BOOL shouldEmitEvent = (_observationDisabled || _listenerCount > 0);
76+
if (!shouldEmitEvent) {
7077
RCTLogWarn(@"Sending `%@` with no listeners registered.", eventName);
78+
return;
79+
}
80+
81+
[callableJSModules invokeModule:@"RCTDeviceEventEmitter"
82+
method:@"emit"
83+
withArgs:body ? @[ eventName, body ] : @[ eventName ]];
84+
}
85+
86+
- (void)setCallableJSModules:(RCTCallableJSModules *)callableJSModules
87+
{
88+
_callableJSModules = callableJSModules;
89+
if (callableJSModules != nil) {
90+
_callableJSModulesWasInitialized = YES;
7191
}
7292
}
7393

0 commit comments

Comments
 (0)