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