Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 23 additions & 8 deletions packages/react-native/React/Modules/RCTEventEmitter.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@
@implementation RCTEventEmitter {
NSInteger _listenerCount;
BOOL _observationDisabled;
// Set to YES when -setCallableJSModules: is called with a non-nil value.
// _callableJSModules is weak and can return to nil after wiring (e.g. on
// host teardown) while this instance lives on, so the current value of
// _callableJSModules can't tell us whether we were ever set up correctly.
// This flag can.
BOOL _callableJSModulesWasInitialized;
}

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

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

Expand All @@ -62,15 +67,25 @@ - (void)sendEventWithName:(NSString *)eventName body:(id)body

BOOL shouldEmitEvent = (_observationDisabled || _listenerCount > 0);

if (shouldEmitEvent && _callableJSModules) {
[_callableJSModules invokeModule:@"RCTDeviceEventEmitter"
method:@"emit"
withArgs:body ? @[ eventName, body ] : @[ eventName ]];
// _callableJSModules is weak, so read it exactly once into a strong local.
RCTCallableJSModules *callableJSModules = _callableJSModules;
if (shouldEmitEvent && callableJSModules) {
[callableJSModules invokeModule:@"RCTDeviceEventEmitter"
method:@"emit"
withArgs:body ? @[ eventName, body ] : @[ eventName ]];
} else {
RCTLogWarn(@"Sending `%@` with no listeners registered.", eventName);
}
}

- (void)setCallableJSModules:(RCTCallableJSModules *)callableJSModules
{
_callableJSModules = callableJSModules;
if (callableJSModules != nil) {
_callableJSModulesWasInitialized = YES;
}
}

- (void)startObserving
{
// Does nothing
Expand Down
Loading