mirror of
https://github.com/status-im/react-native.git
synced 2025-02-26 08:05:34 +00:00
Fixed NativeEventListener deregistration
Summary: The `EmitterSubscription.remove()` method was previously calling `this.subscriber.removeSubscription(this)` directly, bypassing the mechanism in `NativeEventEmitter` that keeps track of the number of subscriptions. This meant that native event modules (subclasses of `RCTEventEmitter`) would keep sending events even after all the listeners had been removed. This wasn't a huge overhead, since these modules are singletons and only send one message over the bridge per event, regardless of the number of listeners, but it's still undesirable. This fixes the problem by routing the `EmitterSubscription.remove()` method through the `EventEmitter` so that `NativeEventEmitter` can apply the additional native calls. I've also improved the architecture so that each `NativeEventEmitter` uses its own `EventEmitter`, but they currently all still share the same `EventSubscriptionVendor` so that legacy code which registers events via `RCTDeviceEventEmitter` still works. Reviewed By: vjeux Differential Revision: D3292361 fbshipit-source-id: d60e881d50351523d2112473703bea826641cdef
This commit is contained in:
parent
9a899bed65
commit
516bf7bd94
@ -14,7 +14,7 @@
|
|||||||
const BugReportingNativeModule = require('NativeModules').BugReporting;
|
const BugReportingNativeModule = require('NativeModules').BugReporting;
|
||||||
const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
||||||
|
|
||||||
import type {EmitterSubscription} from 'EventEmitter';
|
import type EmitterSubscription from 'EmitterSubscription';
|
||||||
|
|
||||||
type ExtraData = { [key: string]: string };
|
type ExtraData = { [key: string]: string };
|
||||||
type SourceCallback = () => string;
|
type SourceCallback = () => string;
|
||||||
@ -28,7 +28,7 @@ type SourceCallback = () => string;
|
|||||||
class BugReporting {
|
class BugReporting {
|
||||||
|
|
||||||
static _sources: Map<string, SourceCallback> = new Map();
|
static _sources: Map<string, SourceCallback> = new Map();
|
||||||
static _subscription: EmitterSubscription = null;
|
static _subscription: ?EmitterSubscription = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `init` is called in `AppRegistry.runApplication`, so you shouldn't have to worry about it.
|
* `init` is called in `AppRegistry.runApplication`, so you shouldn't have to worry about it.
|
||||||
|
62
Libraries/EventEmitter/EmitterSubscription.js
Normal file
62
Libraries/EventEmitter/EmitterSubscription.js
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
* @providesModule EmitterSubscription
|
||||||
|
* @noflow
|
||||||
|
* @typechecks
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const EventSubscription = require('EventSubscription');
|
||||||
|
|
||||||
|
import type EventEmitter from 'EventEmitter';
|
||||||
|
import type EventSubscriptionVendor from 'EventSubscriptionVendor';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EmitterSubscription represents a subscription with listener and context data.
|
||||||
|
*/
|
||||||
|
class EmitterSubscription extends EventSubscription {
|
||||||
|
|
||||||
|
emitter: EventEmitter;
|
||||||
|
listener: Function;
|
||||||
|
context: ?Object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {EventEmitter} emitter - The event emitter that registered this
|
||||||
|
* subscription
|
||||||
|
* @param {EventSubscriptionVendor} subscriber - The subscriber that controls
|
||||||
|
* this subscription
|
||||||
|
* @param {function} listener - Function to invoke when the specified event is
|
||||||
|
* emitted
|
||||||
|
* @param {*} context - Optional context object to use when invoking the
|
||||||
|
* listener
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
emitter: EventEmitter,
|
||||||
|
subscriber: EventSubscriptionVendor,
|
||||||
|
listener: Function,
|
||||||
|
context: ?Object
|
||||||
|
) {
|
||||||
|
super(subscriber);
|
||||||
|
this.emitter = emitter;
|
||||||
|
this.listener = listener;
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes this subscription from the emitter that registered it.
|
||||||
|
* Note: we're overriding the `remove()` method of EventSubscription here
|
||||||
|
* but deliberately not calling `super.remove()` as the responsibility
|
||||||
|
* for removing the subscription lies with the EventEmitter.
|
||||||
|
*/
|
||||||
|
remove() {
|
||||||
|
this.emitter.removeSubscription(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = EmitterSubscription;
|
@ -8,14 +8,13 @@
|
|||||||
*
|
*
|
||||||
* @providesModule EventEmitter
|
* @providesModule EventEmitter
|
||||||
* @noflow
|
* @noflow
|
||||||
* @typechecks
|
* @typecheck
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var EmitterSubscription = require('EmitterSubscription');
|
const EmitterSubscription = require('EmitterSubscription');
|
||||||
var ErrorUtils = require('ErrorUtils');
|
const EventSubscriptionVendor = require('EventSubscriptionVendor');
|
||||||
var EventSubscriptionVendor = require('EventSubscriptionVendor');
|
const emptyFunction = require('fbjs/lib/emptyFunction');
|
||||||
var emptyFunction = require('fbjs/lib/emptyFunction');
|
const invariant = require('fbjs/lib/invariant');
|
||||||
var invariant = require('fbjs/lib/invariant');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class EventEmitter
|
* @class EventEmitter
|
||||||
@ -31,11 +30,18 @@ var invariant = require('fbjs/lib/invariant');
|
|||||||
* more advanced emitter may use an EventHolder and EventFactory.
|
* more advanced emitter may use an EventHolder and EventFactory.
|
||||||
*/
|
*/
|
||||||
class EventEmitter {
|
class EventEmitter {
|
||||||
|
|
||||||
|
_subscriber: EventSubscriptionVendor;
|
||||||
|
_currentSubscription: ?EmitterSubscription;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
|
*
|
||||||
|
* @param {EventSubscriptionVendor} subscriber - Optional subscriber instance
|
||||||
|
* to use. If omitted, a new subscriber will be created for the emitter.
|
||||||
*/
|
*/
|
||||||
constructor() {
|
constructor(subscriber: ?EventSubscriptionVendor) {
|
||||||
this._subscriber = new EventSubscriptionVendor();
|
this._subscriber = subscriber || new EventSubscriptionVendor();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -53,10 +59,12 @@ class EventEmitter {
|
|||||||
* listener
|
* listener
|
||||||
*/
|
*/
|
||||||
addListener(
|
addListener(
|
||||||
eventType: String, listener, context: ?Object): EmitterSubscription {
|
eventType: string, listener: Function, context: ?Object): EmitterSubscription {
|
||||||
return this._subscriber.addSubscription(
|
|
||||||
|
return (this._subscriber.addSubscription(
|
||||||
eventType,
|
eventType,
|
||||||
new EmitterSubscription(this._subscriber, listener, context));
|
new EmitterSubscription(this, this._subscriber, listener, context)
|
||||||
|
) : any);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,10 +77,9 @@ class EventEmitter {
|
|||||||
* @param {*} context - Optional context object to use when invoking the
|
* @param {*} context - Optional context object to use when invoking the
|
||||||
* listener
|
* listener
|
||||||
*/
|
*/
|
||||||
once(eventType: String, listener, context: ?Object): EmitterSubscription {
|
once(eventType: string, listener: Function, context: ?Object): EmitterSubscription {
|
||||||
var emitter = this;
|
return this.addListener(eventType, () => {
|
||||||
return this.addListener(eventType, function() {
|
this.removeCurrentListener();
|
||||||
emitter.removeCurrentListener();
|
|
||||||
listener.apply(context, arguments);
|
listener.apply(context, arguments);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -84,7 +91,7 @@ class EventEmitter {
|
|||||||
* @param {?string} eventType - Optional name of the event whose registered
|
* @param {?string} eventType - Optional name of the event whose registered
|
||||||
* listeners to remove
|
* listeners to remove
|
||||||
*/
|
*/
|
||||||
removeAllListeners(eventType: ?String) {
|
removeAllListeners(eventType: ?string) {
|
||||||
this._subscriber.removeAllSubscriptions(eventType);
|
this._subscriber.removeAllSubscriptions(eventType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +121,19 @@ class EventEmitter {
|
|||||||
!!this._currentSubscription,
|
!!this._currentSubscription,
|
||||||
'Not in an emitting cycle; there is no current subscription'
|
'Not in an emitting cycle; there is no current subscription'
|
||||||
);
|
);
|
||||||
this._subscriber.removeSubscription(this._currentSubscription);
|
this.removeSubscription(this._currentSubscription);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a specific subscription. Called by the `remove()` method of the
|
||||||
|
* subscription itself to ensure any necessary cleanup is performed.
|
||||||
|
*/
|
||||||
|
removeSubscription(subscription: EmitterSubscription) {
|
||||||
|
invariant(
|
||||||
|
subscription.emitter === this,
|
||||||
|
'Subscription does not belong to this emitter.'
|
||||||
|
);
|
||||||
|
this._subscriber.removeSubscription(subscription);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -124,8 +143,8 @@ class EventEmitter {
|
|||||||
* @param {string} eventType - Name of the event to query
|
* @param {string} eventType - Name of the event to query
|
||||||
* @returns {array}
|
* @returns {array}
|
||||||
*/
|
*/
|
||||||
listeners(eventType: String): Array /* TODO: Array<EventSubscription> */ {
|
listeners(eventType: string): [EmitterSubscription] {
|
||||||
var subscriptions = this._subscriber.getSubscriptionsForType(eventType);
|
const subscriptions: ?[EmitterSubscription] = (this._subscriber.getSubscriptionsForType(eventType): any);
|
||||||
return subscriptions
|
return subscriptions
|
||||||
? subscriptions.filter(emptyFunction.thatReturnsTrue).map(
|
? subscriptions.filter(emptyFunction.thatReturnsTrue).map(
|
||||||
function(subscription) {
|
function(subscription) {
|
||||||
@ -148,13 +167,11 @@ class EventEmitter {
|
|||||||
*
|
*
|
||||||
* emitter.emit('someEvent', 'abc'); // logs 'abc'
|
* emitter.emit('someEvent', 'abc'); // logs 'abc'
|
||||||
*/
|
*/
|
||||||
emit(eventType: String) {
|
emit(eventType: string) {
|
||||||
var subscriptions = this._subscriber.getSubscriptionsForType(eventType);
|
const subscriptions: ?[EmitterSubscription] = (this._subscriber.getSubscriptionsForType(eventType): any);
|
||||||
if (subscriptions) {
|
if (subscriptions) {
|
||||||
var keys = Object.keys(subscriptions);
|
for (let i = 0, l = subscriptions.length; i < l; i++) {
|
||||||
for (var ii = 0; ii < keys.length; ii++) {
|
const subscription = subscriptions[i];
|
||||||
var key = keys[ii];
|
|
||||||
var subscription = subscriptions[key];
|
|
||||||
|
|
||||||
// The subscription may have been removed during this event loop.
|
// The subscription may have been removed during this event loop.
|
||||||
if (subscription) {
|
if (subscription) {
|
@ -1,22 +1,20 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<fb2bb5c1c402a097a7e1da7413526629>>
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
* This source code is licensed under the BSD-style license found in the
|
||||||
* !! This file is a check-in of a static_upstream project! !!
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
* !! !!
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
* !! You should not modify this file directly. Instead: !!
|
|
||||||
* !! 1) Use `fjs use-upstream` to temporarily replace this with !!
|
|
||||||
* !! the latest version from upstream. !!
|
|
||||||
* !! 2) Make your changes, test them, etc. !!
|
|
||||||
* !! 3) Use `fjs push-upstream` to copy your changes back to !!
|
|
||||||
* !! static_upstream. !!
|
|
||||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
||||||
*
|
*
|
||||||
* @providesModule EventEmitterWithHolding
|
* @providesModule EventEmitterWithHolding
|
||||||
* @typechecks
|
* @flow
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
import type EmitterSubscription from 'EmitterSubscription';
|
||||||
|
import type EventEmitter from 'EventEmitter';
|
||||||
|
import type EventHolder from 'EventHolder';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class EventEmitterWithHolding
|
* @class EventEmitterWithHolding
|
||||||
* @description
|
* @description
|
||||||
@ -30,6 +28,12 @@
|
|||||||
* that uses an emitter.
|
* that uses an emitter.
|
||||||
*/
|
*/
|
||||||
class EventEmitterWithHolding {
|
class EventEmitterWithHolding {
|
||||||
|
|
||||||
|
_emitter: EventEmitter;
|
||||||
|
_eventHolder: EventHolder;
|
||||||
|
_currentEventToken: ?Object;
|
||||||
|
_emittingHeldEvents: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {object} emitter - The object responsible for emitting the actual
|
* @param {object} emitter - The object responsible for emitting the actual
|
||||||
@ -37,7 +41,7 @@ class EventEmitterWithHolding {
|
|||||||
* @param {object} holder - The event holder that is responsible for holding
|
* @param {object} holder - The event holder that is responsible for holding
|
||||||
* and then emitting held events.
|
* and then emitting held events.
|
||||||
*/
|
*/
|
||||||
constructor(emitter, holder) {
|
constructor(emitter: EventEmitter, holder: EventHolder) {
|
||||||
this._emitter = emitter;
|
this._emitter = emitter;
|
||||||
this._eventHolder = holder;
|
this._eventHolder = holder;
|
||||||
this._currentEventToken = null;
|
this._currentEventToken = null;
|
||||||
@ -47,14 +51,14 @@ class EventEmitterWithHolding {
|
|||||||
/**
|
/**
|
||||||
* @see EventEmitter#addListener
|
* @see EventEmitter#addListener
|
||||||
*/
|
*/
|
||||||
addListener(eventType: String, listener, context: ?Object) {
|
addListener(eventType: string, listener: Function, context: ?Object) {
|
||||||
return this._emitter.addListener(eventType, listener, context);
|
return this._emitter.addListener(eventType, listener, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see EventEmitter#once
|
* @see EventEmitter#once
|
||||||
*/
|
*/
|
||||||
once(eventType: String, listener, context: ?Object) {
|
once(eventType: string, listener: Function, context: ?Object) {
|
||||||
return this._emitter.once(eventType, listener, context);
|
return this._emitter.once(eventType, listener, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,8 +83,8 @@ class EventEmitterWithHolding {
|
|||||||
* }); // logs 'abc'
|
* }); // logs 'abc'
|
||||||
*/
|
*/
|
||||||
addRetroactiveListener(
|
addRetroactiveListener(
|
||||||
eventType: String, listener, context: ?Object): EmitterSubscription {
|
eventType: string, listener: Function, context: ?Object): EmitterSubscription {
|
||||||
var subscription = this._emitter.addListener(eventType, listener, context);
|
const subscription = this._emitter.addListener(eventType, listener, context);
|
||||||
|
|
||||||
this._emittingHeldEvents = true;
|
this._emittingHeldEvents = true;
|
||||||
this._eventHolder.emitToListener(eventType, listener, context);
|
this._eventHolder.emitToListener(eventType, listener, context);
|
||||||
@ -92,7 +96,7 @@ class EventEmitterWithHolding {
|
|||||||
/**
|
/**
|
||||||
* @see EventEmitter#removeAllListeners
|
* @see EventEmitter#removeAllListeners
|
||||||
*/
|
*/
|
||||||
removeAllListeners(eventType: String) {
|
removeAllListeners(eventType: string) {
|
||||||
this._emitter.removeAllListeners(eventType);
|
this._emitter.removeAllListeners(eventType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,15 +110,15 @@ class EventEmitterWithHolding {
|
|||||||
/**
|
/**
|
||||||
* @see EventEmitter#listeners
|
* @see EventEmitter#listeners
|
||||||
*/
|
*/
|
||||||
listeners(eventType: String) /* TODO: Annotate return type here */ {
|
listeners(eventType: string) /* TODO: Annotate return type here */ {
|
||||||
return this._emitter.listeners(eventType);
|
return this._emitter.listeners(eventType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see EventEmitter#emit
|
* @see EventEmitter#emit
|
||||||
*/
|
*/
|
||||||
emit(eventType: String, a, b, c, d, e, _) {
|
emit(eventType: string, ...args: any) {
|
||||||
this._emitter.emit(eventType, a, b, c, d, e, _);
|
this._emitter.emit(eventType, ...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -132,12 +136,9 @@ class EventEmitterWithHolding {
|
|||||||
* console.log(message);
|
* console.log(message);
|
||||||
* }); // logs 'abc'
|
* }); // logs 'abc'
|
||||||
*/
|
*/
|
||||||
emitAndHold(eventType: String, a, b, c, d, e, _) {
|
emitAndHold(eventType: string, ...args: any) {
|
||||||
this._currentEventToken = this._eventHolder.holdEvent(
|
this._currentEventToken = this._eventHolder.holdEvent(eventType, ...args);
|
||||||
eventType,
|
this._emitter.emit(eventType, ...args);
|
||||||
a, b, c, d, e, _
|
|
||||||
);
|
|
||||||
this._emitter.emit(eventType, a, b, c, d, e, _);
|
|
||||||
this._currentEventToken = null;
|
this._currentEventToken = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +146,7 @@ class EventEmitterWithHolding {
|
|||||||
* @see EventHolder#releaseCurrentEvent
|
* @see EventHolder#releaseCurrentEvent
|
||||||
*/
|
*/
|
||||||
releaseCurrentEvent() {
|
releaseCurrentEvent() {
|
||||||
if (this._currentEventToken !== null) {
|
if (this._currentEventToken) {
|
||||||
this._eventHolder.releaseEvent(this._currentEventToken);
|
this._eventHolder.releaseEvent(this._currentEventToken);
|
||||||
} else if (this._emittingHeldEvents) {
|
} else if (this._emittingHeldEvents) {
|
||||||
this._eventHolder.releaseCurrentEvent();
|
this._eventHolder.releaseCurrentEvent();
|
||||||
@ -156,7 +157,7 @@ class EventEmitterWithHolding {
|
|||||||
* @see EventHolder#releaseEventType
|
* @see EventHolder#releaseEventType
|
||||||
* @param {string} eventType
|
* @param {string} eventType
|
||||||
*/
|
*/
|
||||||
releaseHeldEventType(eventType: String) {
|
releaseHeldEventType(eventType: string) {
|
||||||
this._eventHolder.releaseEventType(eventType);
|
this._eventHolder.releaseEventType(eventType);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,25 +1,23 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<0591836c443c735d24e61782320d3d16>>
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
* This source code is licensed under the BSD-style license found in the
|
||||||
* !! This file is a check-in of a static_upstream project! !!
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
* !! !!
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
* !! You should not modify this file directly. Instead: !!
|
|
||||||
* !! 1) Use `fjs use-upstream` to temporarily replace this with !!
|
|
||||||
* !! the latest version from upstream. !!
|
|
||||||
* !! 2) Make your changes, test them, etc. !!
|
|
||||||
* !! 3) Use `fjs push-upstream` to copy your changes back to !!
|
|
||||||
* !! static_upstream. !!
|
|
||||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
||||||
*
|
*
|
||||||
* @providesModule EventHolder
|
* @providesModule EventHolder
|
||||||
* @typechecks
|
* @flow
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var invariant = require('fbjs/lib/invariant');
|
const invariant = require('fbjs/lib/invariant');
|
||||||
|
|
||||||
class EventHolder {
|
class EventHolder {
|
||||||
|
|
||||||
|
_heldEvents: Object;
|
||||||
|
_currentEventKey: ?Object;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this._heldEvents = {};
|
this._heldEvents = {};
|
||||||
this._currentEventKey = null;
|
this._currentEventKey = null;
|
||||||
@ -46,14 +44,14 @@ class EventHolder {
|
|||||||
* }); //logs 'abc'
|
* }); //logs 'abc'
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
holdEvent(eventType: String, a, b, c, d, e, _) {
|
holdEvent(eventType: string, ...args: any) {
|
||||||
this._heldEvents[eventType] = this._heldEvents[eventType] || [];
|
this._heldEvents[eventType] = this._heldEvents[eventType] || [];
|
||||||
var eventsOfType = this._heldEvents[eventType];
|
const eventsOfType = this._heldEvents[eventType];
|
||||||
var key = {
|
const key = {
|
||||||
eventType: eventType,
|
eventType: eventType,
|
||||||
index: eventsOfType.length
|
index: eventsOfType.length
|
||||||
};
|
};
|
||||||
eventsOfType.push([a, b, c, d, e, _]);
|
eventsOfType.push(args);
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,12 +63,12 @@ class EventHolder {
|
|||||||
* @param {?object} context - Optional context object to use when invoking
|
* @param {?object} context - Optional context object to use when invoking
|
||||||
* the listener
|
* the listener
|
||||||
*/
|
*/
|
||||||
emitToListener(eventType: ?String , listener, context: ?Object) {
|
emitToListener(eventType: ?string , listener: Function, context: ?Object) {
|
||||||
var eventsOfType = this._heldEvents[eventType];
|
const eventsOfType = this._heldEvents[eventType];
|
||||||
if (!eventsOfType) {
|
if (!eventsOfType) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var origEventKey = this._currentEventKey;
|
const origEventKey = this._currentEventKey;
|
||||||
eventsOfType.forEach((/*?array*/ eventHeld, /*number*/ index) => {
|
eventsOfType.forEach((/*?array*/ eventHeld, /*number*/ index) => {
|
||||||
if (!eventHeld) {
|
if (!eventHeld) {
|
||||||
return;
|
return;
|
||||||
@ -97,7 +95,7 @@ class EventHolder {
|
|||||||
this._currentEventKey !== null,
|
this._currentEventKey !== null,
|
||||||
'Not in an emitting cycle; there is no current event'
|
'Not in an emitting cycle; there is no current event'
|
||||||
);
|
);
|
||||||
this.releaseEvent(this._currentEventKey);
|
this._currentEventKey && this.releaseEvent(this._currentEventKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -115,7 +113,7 @@ class EventHolder {
|
|||||||
*
|
*
|
||||||
* @param {string} type
|
* @param {string} type
|
||||||
*/
|
*/
|
||||||
releaseEventType(type: String) {
|
releaseEventType(type: string) {
|
||||||
this._heldEvents[type] = [];
|
this._heldEvents[type] = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
42
Libraries/EventEmitter/EventSubscription.js
Normal file
42
Libraries/EventEmitter/EventSubscription.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
* @providesModule EventSubscription
|
||||||
|
* @flow
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import type EventSubscriptionVendor from 'EventSubscriptionVendor';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EventSubscription represents a subscription to a particular event. It can
|
||||||
|
* remove its own subscription.
|
||||||
|
*/
|
||||||
|
class EventSubscription {
|
||||||
|
|
||||||
|
eventType: string;
|
||||||
|
key: number;
|
||||||
|
subscriber: EventSubscriptionVendor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {EventSubscriptionVendor} subscriber the subscriber that controls
|
||||||
|
* this subscription.
|
||||||
|
*/
|
||||||
|
constructor(subscriber: EventSubscriptionVendor) {
|
||||||
|
this.subscriber = subscriber;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes this subscription from the subscriber that controls it.
|
||||||
|
*/
|
||||||
|
remove() {
|
||||||
|
this.subscriber.removeSubscription(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = EventSubscription;
|
@ -1,23 +1,19 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<24d5cc1cdd24704296686faf89dd36cf>>
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
* This source code is licensed under the BSD-style license found in the
|
||||||
* !! This file is a check-in of a static_upstream project! !!
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
* !! !!
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
* !! You should not modify this file directly. Instead: !!
|
|
||||||
* !! 1) Use `fjs use-upstream` to temporarily replace this with !!
|
|
||||||
* !! the latest version from upstream. !!
|
|
||||||
* !! 2) Make your changes, test them, etc. !!
|
|
||||||
* !! 3) Use `fjs push-upstream` to copy your changes back to !!
|
|
||||||
* !! static_upstream. !!
|
|
||||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
||||||
*
|
*
|
||||||
* @providesModule EventSubscriptionVendor
|
* @providesModule EventSubscriptionVendor
|
||||||
* @typechecks
|
* @flow
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var invariant = require('fbjs/lib/invariant');
|
const invariant = require('fbjs/lib/invariant');
|
||||||
|
|
||||||
|
import type EventSubscription from 'EventSubscription';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EventSubscriptionVendor stores a set of EventSubscriptions that are
|
* EventSubscriptionVendor stores a set of EventSubscriptions that are
|
||||||
@ -25,6 +21,9 @@ var invariant = require('fbjs/lib/invariant');
|
|||||||
*/
|
*/
|
||||||
class EventSubscriptionVendor {
|
class EventSubscriptionVendor {
|
||||||
|
|
||||||
|
_subscriptionsForType: Object;
|
||||||
|
_currentSubscription: ?EventSubscription;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this._subscriptionsForType = {};
|
this._subscriptionsForType = {};
|
||||||
this._currentSubscription = null;
|
this._currentSubscription = null;
|
||||||
@ -37,14 +36,14 @@ class EventSubscriptionVendor {
|
|||||||
* @param {EventSubscription} subscription
|
* @param {EventSubscription} subscription
|
||||||
*/
|
*/
|
||||||
addSubscription(
|
addSubscription(
|
||||||
eventType: String, subscription: EventSubscription): EventSubscription {
|
eventType: string, subscription: EventSubscription): EventSubscription {
|
||||||
invariant(
|
invariant(
|
||||||
subscription.subscriber === this,
|
subscription.subscriber === this,
|
||||||
'The subscriber of the subscription is incorrectly set.');
|
'The subscriber of the subscription is incorrectly set.');
|
||||||
if (!this._subscriptionsForType[eventType]) {
|
if (!this._subscriptionsForType[eventType]) {
|
||||||
this._subscriptionsForType[eventType] = [];
|
this._subscriptionsForType[eventType] = [];
|
||||||
}
|
}
|
||||||
var key = this._subscriptionsForType[eventType].length;
|
const key = this._subscriptionsForType[eventType].length;
|
||||||
this._subscriptionsForType[eventType].push(subscription);
|
this._subscriptionsForType[eventType].push(subscription);
|
||||||
subscription.eventType = eventType;
|
subscription.eventType = eventType;
|
||||||
subscription.key = key;
|
subscription.key = key;
|
||||||
@ -57,7 +56,7 @@ class EventSubscriptionVendor {
|
|||||||
* @param {?string} eventType - Optional name of the event type whose
|
* @param {?string} eventType - Optional name of the event type whose
|
||||||
* registered supscriptions to remove, if null remove all subscriptions.
|
* registered supscriptions to remove, if null remove all subscriptions.
|
||||||
*/
|
*/
|
||||||
removeAllSubscriptions(eventType: ?String) {
|
removeAllSubscriptions(eventType: ?string) {
|
||||||
if (eventType === undefined) {
|
if (eventType === undefined) {
|
||||||
this._subscriptionsForType = {};
|
this._subscriptionsForType = {};
|
||||||
} else {
|
} else {
|
||||||
@ -72,10 +71,10 @@ class EventSubscriptionVendor {
|
|||||||
* @param {object} subscription
|
* @param {object} subscription
|
||||||
*/
|
*/
|
||||||
removeSubscription(subscription: Object) {
|
removeSubscription(subscription: Object) {
|
||||||
var eventType = subscription.eventType;
|
const eventType = subscription.eventType;
|
||||||
var key = subscription.key;
|
const key = subscription.key;
|
||||||
|
|
||||||
var subscriptionsForType = this._subscriptionsForType[eventType];
|
const subscriptionsForType = this._subscriptionsForType[eventType];
|
||||||
if (subscriptionsForType) {
|
if (subscriptionsForType) {
|
||||||
delete subscriptionsForType[key];
|
delete subscriptionsForType[key];
|
||||||
}
|
}
|
||||||
@ -93,7 +92,7 @@ class EventSubscriptionVendor {
|
|||||||
* @param {string} eventType
|
* @param {string} eventType
|
||||||
* @returns {?array}
|
* @returns {?array}
|
||||||
*/
|
*/
|
||||||
getSubscriptionsForType(eventType: String): ?Array {
|
getSubscriptionsForType(eventType: string): ?[EventSubscription] {
|
||||||
return this._subscriptionsForType[eventType];
|
return this._subscriptionsForType[eventType];
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,22 +1,17 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<7149bdac6fb48595f245ad6e76938e44>>
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
* This source code is licensed under the BSD-style license found in the
|
||||||
* !! This file is a check-in of a static_upstream project! !!
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
* !! !!
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
* !! You should not modify this file directly. Instead: !!
|
|
||||||
* !! 1) Use `fjs use-upstream` to temporarily replace this with !!
|
|
||||||
* !! the latest version from upstream. !!
|
|
||||||
* !! 2) Make your changes, test them, etc. !!
|
|
||||||
* !! 3) Use `fjs push-upstream` to copy your changes back to !!
|
|
||||||
* !! static_upstream. !!
|
|
||||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
||||||
*
|
*
|
||||||
* @providesModule EventValidator
|
* @providesModule EventValidator
|
||||||
|
* @flow
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var copyProperties = require('copyProperties');
|
const copyProperties = require('copyProperties');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EventValidator is designed to validate event types to make it easier to catch
|
* EventValidator is designed to validate event types to make it easier to catch
|
||||||
@ -27,7 +22,7 @@ var copyProperties = require('copyProperties');
|
|||||||
* mistyped the event name it will suggest what you might have meant to type in
|
* mistyped the event name it will suggest what you might have meant to type in
|
||||||
* the error message.
|
* the error message.
|
||||||
*/
|
*/
|
||||||
var EventValidator = {
|
const EventValidator = {
|
||||||
/**
|
/**
|
||||||
* @param {Object} emitter - The object responsible for emitting the actual
|
* @param {Object} emitter - The object responsible for emitting the actual
|
||||||
* events
|
* events
|
||||||
@ -35,12 +30,12 @@ var EventValidator = {
|
|||||||
* check for errors
|
* check for errors
|
||||||
* @return {Object} A new emitter with event type validation
|
* @return {Object} A new emitter with event type validation
|
||||||
* @example
|
* @example
|
||||||
* var types = {someEvent: true, anotherEvent: true};
|
* const types = {someEvent: true, anotherEvent: true};
|
||||||
* var emitter = EventValidator.addValidation(emitter, types);
|
* const emitter = EventValidator.addValidation(emitter, types);
|
||||||
*/
|
*/
|
||||||
addValidation: function(emitter: Object, types: Object) {
|
addValidation: function(emitter: Object, types: Object) {
|
||||||
var eventTypes = Object.keys(types);
|
const eventTypes = Object.keys(types);
|
||||||
var emitterWithValidation = Object.create(emitter);
|
const emitterWithValidation = Object.create(emitter);
|
||||||
|
|
||||||
copyProperties(emitterWithValidation, {
|
copyProperties(emitterWithValidation, {
|
||||||
emit: function emit(type, a, b, c, d, e, _) {
|
emit: function emit(type, a, b, c, d, e, _) {
|
||||||
@ -60,7 +55,7 @@ function assertAllowsEventType(type, allowedTypes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function errorMessageFor(type, allowedTypes) {
|
function errorMessageFor(type, allowedTypes) {
|
||||||
var message = 'Unknown event type "' + type + '". ';
|
let message = 'Unknown event type "' + type + '". ';
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
message += recommendationFor(type, allowedTypes);
|
message += recommendationFor(type, allowedTypes);
|
||||||
}
|
}
|
||||||
@ -71,7 +66,7 @@ function errorMessageFor(type, allowedTypes) {
|
|||||||
// Allow for good error messages
|
// Allow for good error messages
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
var recommendationFor = function (type, allowedTypes) {
|
var recommendationFor = function (type, allowedTypes) {
|
||||||
var closestTypeRecommendation = closestTypeFor(type, allowedTypes);
|
const closestTypeRecommendation = closestTypeFor(type, allowedTypes);
|
||||||
if (isCloseEnough(closestTypeRecommendation, type)) {
|
if (isCloseEnough(closestTypeRecommendation, type)) {
|
||||||
return 'Did you mean "' + closestTypeRecommendation.type + '"? ';
|
return 'Did you mean "' + closestTypeRecommendation.type + '"? ';
|
||||||
} else {
|
} else {
|
||||||
@ -80,7 +75,7 @@ if (__DEV__) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var closestTypeFor = function (type, allowedTypes) {
|
var closestTypeFor = function (type, allowedTypes) {
|
||||||
var typeRecommendations = allowedTypes.map(
|
const typeRecommendations = allowedTypes.map(
|
||||||
typeRecommendationFor.bind(this, type)
|
typeRecommendationFor.bind(this, type)
|
||||||
);
|
);
|
||||||
return typeRecommendations.sort(recommendationSort)[0];
|
return typeRecommendations.sort(recommendationSort)[0];
|
||||||
@ -108,8 +103,8 @@ if (__DEV__) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var damerauLevenshteinDistance = function (a, b) {
|
var damerauLevenshteinDistance = function (a, b) {
|
||||||
var i, j;
|
let i, j;
|
||||||
var d = [];
|
const d = [];
|
||||||
|
|
||||||
for (i = 0; i <= a.length; i++) {
|
for (i = 0; i <= a.length; i++) {
|
||||||
d[i] = [i];
|
d[i] = [i];
|
||||||
@ -121,7 +116,7 @@ if (__DEV__) {
|
|||||||
|
|
||||||
for (i = 1; i <= a.length; i++) {
|
for (i = 1; i <= a.length; i++) {
|
||||||
for (j = 1; j <= b.length; j++) {
|
for (j = 1; j <= b.length; j++) {
|
||||||
var cost = a.charAt(i - 1) === b.charAt(j - 1) ? 0 : 1;
|
const cost = a.charAt(i - 1) === b.charAt(j - 1) ? 0 : 1;
|
||||||
|
|
||||||
d[i][j] = Math.min(
|
d[i][j] = Math.min(
|
||||||
d[i - 1][j] + 1,
|
d[i - 1][j] + 1,
|
||||||
@ -130,8 +125,8 @@ if (__DEV__) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (i > 1 && j > 1 &&
|
if (i > 1 && j > 1 &&
|
||||||
a.charAt(i - 1) == b.charAt(j - 2) &&
|
a.charAt(i - 1) === b.charAt(j - 2) &&
|
||||||
a.charAt(i - 2) == b.charAt(j - 1)) {
|
a.charAt(i - 2) === b.charAt(j - 1)) {
|
||||||
d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + cost);
|
d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + cost);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,6 +11,7 @@
|
|||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const EventEmitter = require('EventEmitter');
|
||||||
const Platform = require('Platform');
|
const Platform = require('Platform');
|
||||||
const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
||||||
const invariant = require('fbjs/lib/invariant');
|
const invariant = require('fbjs/lib/invariant');
|
||||||
@ -21,45 +22,39 @@ import type EmitterSubscription from 'EmitterSubscription';
|
|||||||
* Abstract base class for implementing event-emitting modules. This implements
|
* Abstract base class for implementing event-emitting modules. This implements
|
||||||
* a subset of the standard EventEmitter node module API.
|
* a subset of the standard EventEmitter node module API.
|
||||||
*/
|
*/
|
||||||
class NativeEventEmitter {
|
class NativeEventEmitter extends EventEmitter {
|
||||||
|
|
||||||
_nativeModule: Object;
|
_nativeModule: Object;
|
||||||
|
|
||||||
constructor(nativeModule: Object) {
|
constructor(nativeModule: Object) {
|
||||||
|
super(RCTDeviceEventEmitter.sharedSubscriber);
|
||||||
if (Platform.OS === 'ios') {
|
if (Platform.OS === 'ios') {
|
||||||
invariant(nativeModule, 'Native module cannot be null.');
|
invariant(nativeModule, 'Native module cannot be null.');
|
||||||
this._nativeModule = nativeModule;
|
this._nativeModule = nativeModule;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addListener(eventType: string, listener: any, context: ?Object): EmitterSubscription {
|
addListener(eventType: string, listener: Function, context: ?Object): EmitterSubscription {
|
||||||
if (Platform.OS === 'ios') {
|
if (Platform.OS === 'ios') {
|
||||||
this._nativeModule.addListener(eventType);
|
this._nativeModule.addListener(eventType);
|
||||||
}
|
}
|
||||||
return RCTDeviceEventEmitter.nativeAddListener(eventType, listener, context);
|
return super.addListener(eventType, listener, context);
|
||||||
}
|
|
||||||
|
|
||||||
once(eventType: string, listener: any, context: ?Object): EmitterSubscription {
|
|
||||||
return this.addListener(eventType, () => {
|
|
||||||
this.removeCurrentListener();
|
|
||||||
listener.apply(context, arguments);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
removeAllListeners(eventType: string) {
|
removeAllListeners(eventType: string) {
|
||||||
invariant(eventType, 'eventType argument is required.');
|
invariant(eventType, 'eventType argument is required.');
|
||||||
if (Platform.OS === 'ios') {
|
if (Platform.OS === 'ios') {
|
||||||
const count = RCTDeviceEventEmitter.listeners(eventType).length;
|
const count = this.listeners(eventType).length;
|
||||||
this._nativeModule.removeListeners(count);
|
this._nativeModule.removeListeners(count);
|
||||||
}
|
}
|
||||||
RCTDeviceEventEmitter.removeAllListeners(eventType);
|
super.removeAllListeners(eventType);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeCurrentListener() {
|
removeSubscription(subscription: EmitterSubscription) {
|
||||||
if (Platform.OS === 'ios') {
|
if (Platform.OS === 'ios') {
|
||||||
this._nativeModule.removeListeners(1);
|
this._nativeModule.removeListeners(1);
|
||||||
}
|
}
|
||||||
RCTDeviceEventEmitter.removeCurrentListener();
|
super.removeSubscription(subscription);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -12,6 +12,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const EventEmitter = require('EventEmitter');
|
const EventEmitter = require('EventEmitter');
|
||||||
|
const EventSubscriptionVendor = require('EventSubscriptionVendor');
|
||||||
const BatchedBridge = require('BatchedBridge');
|
const BatchedBridge = require('BatchedBridge');
|
||||||
|
|
||||||
import type EmitterSubscription from 'EmitterSubscription';
|
import type EmitterSubscription from 'EmitterSubscription';
|
||||||
@ -22,7 +23,15 @@ import type EmitterSubscription from 'EmitterSubscription';
|
|||||||
*/
|
*/
|
||||||
class RCTDeviceEventEmitter extends EventEmitter {
|
class RCTDeviceEventEmitter extends EventEmitter {
|
||||||
|
|
||||||
addListener(eventType: string, listener: any, context: ?Object): EmitterSubscription {
|
sharedSubscriber: EventSubscriptionVendor;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
const sharedSubscriber = new EventSubscriptionVendor();
|
||||||
|
super(sharedSubscriber);
|
||||||
|
this.sharedSubscriber = sharedSubscriber;
|
||||||
|
}
|
||||||
|
|
||||||
|
addListener(eventType: string, listener: Function, context: ?Object): EmitterSubscription {
|
||||||
if (eventType.lastIndexOf('statusBar', 0) === 0) {
|
if (eventType.lastIndexOf('statusBar', 0) === 0) {
|
||||||
console.warn('`%s` event should be registered via the StatusBarIOS module', eventType);
|
console.warn('`%s` event should be registered via the StatusBarIOS module', eventType);
|
||||||
return require('StatusBarIOS').addListener(eventType, listener, context);
|
return require('StatusBarIOS').addListener(eventType, listener, context);
|
||||||
@ -34,8 +43,26 @@ class RCTDeviceEventEmitter extends EventEmitter {
|
|||||||
return super.addListener(eventType, listener, context);
|
return super.addListener(eventType, listener, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
nativeAddListener(eventType: string, listener: any, context: ?Object): EmitterSubscription {
|
removeAllListeners(eventType: ?string) {
|
||||||
return super.addListener(eventType, listener, context);
|
if (eventType) {
|
||||||
|
if (eventType.lastIndexOf('statusBar', 0) === 0) {
|
||||||
|
console.warn('statusBar events should be unregistered via the StatusBarIOS module');
|
||||||
|
return require('StatusBarIOS').removeAllListeners(eventType);
|
||||||
|
}
|
||||||
|
if (eventType.lastIndexOf('keyboard', 0) === 0) {
|
||||||
|
console.warn('keyboard events should be unregistered via the Keyboard module');
|
||||||
|
return require('Keyboard').removeAllListeners(eventType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.removeAllListeners(eventType);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeSubscription(subscription: EmitterSubscription) {
|
||||||
|
if (subscription.emitter !== this) {
|
||||||
|
subscription.emitter.removeSubscription(subscription);
|
||||||
|
} else {
|
||||||
|
super.removeSubscription(subscription);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -11,10 +11,14 @@
|
|||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var BatchedBridge = require('BatchedBridge');
|
const BatchedBridge = require('BatchedBridge');
|
||||||
var EventEmitter = require('EventEmitter');
|
const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
||||||
|
|
||||||
var RCTNativeAppEventEmitter = new EventEmitter();
|
/**
|
||||||
|
* Deprecated - subclass NativeEventEmitter to create granular event modules instead of
|
||||||
|
* adding all event listeners directly to RCTNativeAppEventEmitter.
|
||||||
|
*/
|
||||||
|
const RCTNativeAppEventEmitter = RCTDeviceEventEmitter;
|
||||||
|
|
||||||
BatchedBridge.registerCallableModule(
|
BatchedBridge.registerCallableModule(
|
||||||
'RCTNativeAppEventEmitter',
|
'RCTNativeAppEventEmitter',
|
@ -1,30 +1,25 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<c735038726af2daf584b3e7fb3950e8b>>
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
* This source code is licensed under the BSD-style license found in the
|
||||||
* !! This file is a check-in of a static_upstream project! !!
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
* !! !!
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
* !! You should not modify this file directly. Instead: !!
|
|
||||||
* !! 1) Use `fjs use-upstream` to temporarily replace this with !!
|
|
||||||
* !! the latest version from upstream. !!
|
|
||||||
* !! 2) Make your changes, test them, etc. !!
|
|
||||||
* !! 3) Use `fjs push-upstream` to copy your changes back to !!
|
|
||||||
* !! static_upstream. !!
|
|
||||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
||||||
*
|
*
|
||||||
* @providesModule mixInEventEmitter
|
* @providesModule mixInEventEmitter
|
||||||
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var EventEmitter = require('EventEmitter');
|
const EventEmitter = require('EventEmitter');
|
||||||
var EventEmitterWithHolding = require('EventEmitterWithHolding');
|
const EventEmitterWithHolding = require('EventEmitterWithHolding');
|
||||||
var EventHolder = require('EventHolder');
|
const EventHolder = require('EventHolder');
|
||||||
var EventValidator = require('EventValidator');
|
const EventValidator = require('EventValidator');
|
||||||
|
|
||||||
var copyProperties = require('copyProperties');
|
const copyProperties = require('copyProperties');
|
||||||
var invariant = require('fbjs/lib/invariant');
|
const invariant = require('fbjs/lib/invariant');
|
||||||
var keyOf = require('fbjs/lib/keyOf');
|
const keyOf = require('fbjs/lib/keyOf');
|
||||||
|
|
||||||
var TYPES_KEY = keyOf({__types: true});
|
const TYPES_KEY = keyOf({__types: true});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API to setup an object or constructor to be able to emit data events.
|
* API to setup an object or constructor to be able to emit data events.
|
||||||
@ -47,16 +42,16 @@ var TYPES_KEY = keyOf({__types: true});
|
|||||||
* mixInEventEmitter(Singleton, {lonely: true});
|
* mixInEventEmitter(Singleton, {lonely: true});
|
||||||
* Singleton.emit('lonely', true);
|
* Singleton.emit('lonely', true);
|
||||||
*/
|
*/
|
||||||
function mixInEventEmitter(klass, types) {
|
function mixInEventEmitter(cls: Function | Object, types: Object) {
|
||||||
invariant(types, 'Must supply set of valid event types');
|
invariant(types, 'Must supply set of valid event types');
|
||||||
|
|
||||||
// If this is a constructor, write to the prototype, otherwise write to the
|
// If this is a constructor, write to the prototype, otherwise write to the
|
||||||
// singleton object.
|
// singleton object.
|
||||||
var target = klass.prototype || klass;
|
const target = cls.prototype || cls;
|
||||||
|
|
||||||
invariant(!target.__eventEmitter, 'An active emitter is already mixed in');
|
invariant(!target.__eventEmitter, 'An active emitter is already mixed in');
|
||||||
|
|
||||||
var ctor = klass.constructor;
|
const ctor = cls.constructor;
|
||||||
if (ctor) {
|
if (ctor) {
|
||||||
invariant(
|
invariant(
|
||||||
ctor === Object || ctor === Function,
|
ctor === Object || ctor === Function,
|
||||||
@ -76,7 +71,7 @@ function mixInEventEmitter(klass, types) {
|
|||||||
copyProperties(target, EventEmitterMixin);
|
copyProperties(target, EventEmitterMixin);
|
||||||
}
|
}
|
||||||
|
|
||||||
var EventEmitterMixin = {
|
const EventEmitterMixin = {
|
||||||
emit: function(eventType, a, b, c, d, e, _) {
|
emit: function(eventType, a, b, c, d, e, _) {
|
||||||
return this.__getEventEmitter().emit(eventType, a, b, c, d, e, _);
|
return this.__getEventEmitter().emit(eventType, a, b, c, d, e, _);
|
||||||
},
|
},
|
||||||
@ -123,10 +118,10 @@ var EventEmitterMixin = {
|
|||||||
|
|
||||||
__getEventEmitter: function() {
|
__getEventEmitter: function() {
|
||||||
if (!this.__eventEmitter) {
|
if (!this.__eventEmitter) {
|
||||||
var emitter = new EventEmitter();
|
let emitter = new EventEmitter();
|
||||||
emitter = EventValidator.addValidation(emitter, this.__types);
|
emitter = EventValidator.addValidation(emitter, this.__types);
|
||||||
|
|
||||||
var holder = new EventHolder();
|
const holder = new EventHolder();
|
||||||
this.__eventEmitter = new EventEmitterWithHolding(emitter, holder);
|
this.__eventEmitter = new EventEmitterWithHolding(emitter, holder);
|
||||||
}
|
}
|
||||||
return this.__eventEmitter;
|
return this.__eventEmitter;
|
43
Libraries/vendor/emitter/EmitterSubscription.js
vendored
43
Libraries/vendor/emitter/EmitterSubscription.js
vendored
@ -1,43 +0,0 @@
|
|||||||
/**
|
|
||||||
* @generated SignedSource<<d17b6e5d9b7118fb0ed9169f579e5b8a>>
|
|
||||||
*
|
|
||||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
||||||
* !! This file is a check-in of a static_upstream project! !!
|
|
||||||
* !! !!
|
|
||||||
* !! You should not modify this file directly. Instead: !!
|
|
||||||
* !! 1) Use `fjs use-upstream` to temporarily replace this with !!
|
|
||||||
* !! the latest version from upstream. !!
|
|
||||||
* !! 2) Make your changes, test them, etc. !!
|
|
||||||
* !! 3) Use `fjs push-upstream` to copy your changes back to !!
|
|
||||||
* !! static_upstream. !!
|
|
||||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
||||||
*
|
|
||||||
* @providesModule EmitterSubscription
|
|
||||||
* @noflow
|
|
||||||
* @typechecks
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var EventSubscription = require('EventSubscription');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EmitterSubscription represents a subscription with listener and context data.
|
|
||||||
*/
|
|
||||||
class EmitterSubscription extends EventSubscription {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {EventSubscriptionVendor} subscriber - The subscriber that controls
|
|
||||||
* this subscription
|
|
||||||
* @param {function} listener - Function to invoke when the specified event is
|
|
||||||
* emitted
|
|
||||||
* @param {*} context - Optional context object to use when invoking the
|
|
||||||
* listener
|
|
||||||
*/
|
|
||||||
constructor(subscriber: EventSubscriptionVendor, listener, context: ?Object) {
|
|
||||||
super(subscriber);
|
|
||||||
this.listener = listener;
|
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = EmitterSubscription;
|
|
42
Libraries/vendor/emitter/EventSubscription.js
vendored
42
Libraries/vendor/emitter/EventSubscription.js
vendored
@ -1,42 +0,0 @@
|
|||||||
/**
|
|
||||||
* @generated SignedSource<<92108a17b1f3eee4b7e3dd7d484aa17a>>
|
|
||||||
*
|
|
||||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
||||||
* !! This file is a check-in of a static_upstream project! !!
|
|
||||||
* !! !!
|
|
||||||
* !! You should not modify this file directly. Instead: !!
|
|
||||||
* !! 1) Use `fjs use-upstream` to temporarily replace this with !!
|
|
||||||
* !! the latest version from upstream. !!
|
|
||||||
* !! 2) Make your changes, test them, etc. !!
|
|
||||||
* !! 3) Use `fjs push-upstream` to copy your changes back to !!
|
|
||||||
* !! static_upstream. !!
|
|
||||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
||||||
*
|
|
||||||
* @providesModule EventSubscription
|
|
||||||
* @typechecks
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EventSubscription represents a subscription to a particular event. It can
|
|
||||||
* remove its own subscription.
|
|
||||||
*/
|
|
||||||
class EventSubscription {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {EventSubscriptionVendor} subscriber the subscriber that controls
|
|
||||||
* this subscription.
|
|
||||||
*/
|
|
||||||
constructor(subscriber: EventSubscriptionVendor) {
|
|
||||||
this.subscriber = subscriber;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes this subscription from the subscriber that controls it.
|
|
||||||
*/
|
|
||||||
remove() {
|
|
||||||
this.subscriber.removeSubscription(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = EventSubscription;
|
|
@ -72,7 +72,9 @@ RCT_EXPORT_METHOD(addListener:(NSString *)eventName)
|
|||||||
|
|
||||||
RCT_EXPORT_METHOD(removeListeners:(NSInteger)count)
|
RCT_EXPORT_METHOD(removeListeners:(NSInteger)count)
|
||||||
{
|
{
|
||||||
RCTAssert(count <= _listenerCount, @"Attempted to remove more listeners than added");
|
if (RCT_DEBUG && count > _listenerCount) {
|
||||||
|
RCTLogError(@"Attempted to remove more %@ listeners than added", [self class]);
|
||||||
|
}
|
||||||
if (count == _listenerCount) {
|
if (count == _listenerCount) {
|
||||||
[self stopObserving];
|
[self stopObserving];
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user