diff --git a/Libraries/EventEmitter/NativeEventEmitter.js b/Libraries/EventEmitter/NativeEventEmitter.js index e04bc5f95d06c5..298a3eea2f8831 100644 --- a/Libraries/EventEmitter/NativeEventEmitter.js +++ b/Libraries/EventEmitter/NativeEventEmitter.js @@ -22,15 +22,29 @@ type NativeModule = { ... }; +type NativeEventEmitterOptions = $ReadOnly<{| + __SECRET_DISABLE_CALLS_INTO_MODULE_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: boolean, +|}>; + +const DEFAULT_NATIVE_EVENT_EMITTER_OPTIONS = { + __SECRET_DISABLE_CALLS_INTO_MODULE_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: false, +}; + /** * Abstract base class for implementing event-emitting modules. This implements * a subset of the standard EventEmitter node module API. */ export default class NativeEventEmitter extends EventEmitter { _nativeModule: ?NativeModule; + _disableCallsIntoModule: boolean; - constructor(nativeModule: ?NativeModule) { + constructor( + nativeModule: ?NativeModule, + options: NativeEventEmitterOptions = DEFAULT_NATIVE_EVENT_EMITTER_OPTIONS, + ) { super(RCTDeviceEventEmitter.sharedSubscriber); + this._disableCallsIntoModule = + options.__SECRET_DISABLE_CALLS_INTO_MODULE_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; if (Platform.OS === 'ios') { invariant(nativeModule, 'Native module cannot be null.'); this._nativeModule = nativeModule; @@ -42,7 +56,7 @@ export default class NativeEventEmitter extends EventEmitter { listener: Function, context: ?Object, ): EventSubscription { - if (this._nativeModule != null) { + if (this._nativeModule != null && !this._disableCallsIntoModule) { this._nativeModule.addListener(eventType); } return super.addListener(eventType, listener, context); @@ -51,14 +65,14 @@ export default class NativeEventEmitter extends EventEmitter { removeAllListeners(eventType: string) { invariant(eventType, 'eventType argument is required.'); const count = this.listenerCount(eventType); - if (this._nativeModule != null) { + if (this._nativeModule != null && !this._disableCallsIntoModule) { this._nativeModule.removeListeners(count); } super.removeAllListeners(eventType); } removeSubscription(subscription: EventSubscription) { - if (this._nativeModule != null) { + if (this._nativeModule != null && !this._disableCallsIntoModule) { this._nativeModule.removeListeners(1); } super.removeSubscription(subscription); diff --git a/Libraries/Network/RCTNetworking.ios.js b/Libraries/Network/RCTNetworking.ios.js index 92ef33394316a3..bc1081aab357d6 100644 --- a/Libraries/Network/RCTNetworking.ios.js +++ b/Libraries/Network/RCTNetworking.ios.js @@ -18,7 +18,14 @@ import type {RequestBody} from './convertRequestBody'; class RCTNetworking extends NativeEventEmitter { constructor() { - super(NativeNetworkingIOS); + const disableCallsIntoModule = + typeof global.__disableRCTNetworkingExtraneousModuleCalls === 'function' + ? global.__disableRCTNetworkingExtraneousModuleCalls() + : false; + + super(NativeNetworkingIOS, { + __SECRET_DISABLE_CALLS_INTO_MODULE_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: disableCallsIntoModule, + }); } sendRequest(