2015-01-30 01:10:49 +00:00
|
|
|
/**
|
2016-05-16 11:04:37 +00:00
|
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
|
|
|
* All rights reserved.
|
2015-01-30 01:10:49 +00:00
|
|
|
*
|
2016-05-16 11:04:37 +00:00
|
|
|
* 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.
|
2015-01-30 01:10:49 +00:00
|
|
|
*
|
|
|
|
* @providesModule mixInEventEmitter
|
2016-05-16 11:04:37 +00:00
|
|
|
* @flow
|
2015-01-30 01:10:49 +00:00
|
|
|
*/
|
|
|
|
|
2016-05-16 11:04:37 +00:00
|
|
|
const EventEmitter = require('EventEmitter');
|
|
|
|
const EventEmitterWithHolding = require('EventEmitterWithHolding');
|
|
|
|
const EventHolder = require('EventHolder');
|
|
|
|
const EventValidator = require('EventValidator');
|
2015-01-30 01:10:49 +00:00
|
|
|
|
2016-05-16 11:04:37 +00:00
|
|
|
const copyProperties = require('copyProperties');
|
|
|
|
const invariant = require('fbjs/lib/invariant');
|
|
|
|
const keyOf = require('fbjs/lib/keyOf');
|
2015-01-30 01:10:49 +00:00
|
|
|
|
2016-05-16 11:04:37 +00:00
|
|
|
const TYPES_KEY = keyOf({__types: true});
|
2015-01-30 01:10:49 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* API to setup an object or constructor to be able to emit data events.
|
|
|
|
*
|
|
|
|
* @example
|
|
|
|
* function Dog() { ...dog stuff... }
|
|
|
|
* mixInEventEmitter(Dog, {bark: true});
|
|
|
|
*
|
|
|
|
* var puppy = new Dog();
|
|
|
|
* puppy.addListener('bark', function (volume) {
|
|
|
|
* console.log('Puppy', this, 'barked at volume:', volume);
|
|
|
|
* });
|
|
|
|
* puppy.emit('bark', 'quiet');
|
|
|
|
* // Puppy <puppy> barked at volume: quiet
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* // A "singleton" object may also be commissioned:
|
|
|
|
*
|
|
|
|
* var Singleton = {};
|
|
|
|
* mixInEventEmitter(Singleton, {lonely: true});
|
|
|
|
* Singleton.emit('lonely', true);
|
|
|
|
*/
|
2016-05-16 11:04:37 +00:00
|
|
|
function mixInEventEmitter(cls: Function | Object, types: Object) {
|
2015-01-30 01:10:49 +00:00
|
|
|
invariant(types, 'Must supply set of valid event types');
|
|
|
|
|
|
|
|
// If this is a constructor, write to the prototype, otherwise write to the
|
|
|
|
// singleton object.
|
2016-05-16 11:04:37 +00:00
|
|
|
const target = cls.prototype || cls;
|
2015-01-30 01:10:49 +00:00
|
|
|
|
2016-01-21 15:22:20 +00:00
|
|
|
invariant(!target.__eventEmitter, 'An active emitter is already mixed in');
|
|
|
|
|
2016-05-16 11:04:37 +00:00
|
|
|
const ctor = cls.constructor;
|
2015-01-30 01:10:49 +00:00
|
|
|
if (ctor) {
|
|
|
|
invariant(
|
|
|
|
ctor === Object || ctor === Function,
|
|
|
|
'Mix EventEmitter into a class, not an instance'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Keep track of the provided types, union the types if they already exist,
|
|
|
|
// which allows for prototype subclasses to provide more types.
|
|
|
|
if (target.hasOwnProperty(TYPES_KEY)) {
|
|
|
|
copyProperties(target.__types, types);
|
|
|
|
} else if (target.__types) {
|
|
|
|
target.__types = copyProperties({}, target.__types, types);
|
|
|
|
} else {
|
|
|
|
target.__types = types;
|
|
|
|
}
|
|
|
|
copyProperties(target, EventEmitterMixin);
|
|
|
|
}
|
|
|
|
|
2016-05-16 11:04:37 +00:00
|
|
|
const EventEmitterMixin = {
|
2015-01-30 01:10:49 +00:00
|
|
|
emit: function(eventType, a, b, c, d, e, _) {
|
|
|
|
return this.__getEventEmitter().emit(eventType, a, b, c, d, e, _);
|
|
|
|
},
|
|
|
|
|
|
|
|
emitAndHold: function(eventType, a, b, c, d, e, _) {
|
|
|
|
return this.__getEventEmitter().emitAndHold(eventType, a, b, c, d, e, _);
|
|
|
|
},
|
|
|
|
|
|
|
|
addListener: function(eventType, listener, context) {
|
|
|
|
return this.__getEventEmitter().addListener(eventType, listener, context);
|
|
|
|
},
|
|
|
|
|
|
|
|
once: function(eventType, listener, context) {
|
|
|
|
return this.__getEventEmitter().once(eventType, listener, context);
|
|
|
|
},
|
|
|
|
|
|
|
|
addRetroactiveListener: function(eventType, listener, context) {
|
|
|
|
return this.__getEventEmitter().addRetroactiveListener(
|
|
|
|
eventType,
|
|
|
|
listener,
|
|
|
|
context
|
|
|
|
);
|
|
|
|
},
|
|
|
|
|
|
|
|
addListenerMap: function(listenerMap, context) {
|
|
|
|
return this.__getEventEmitter().addListenerMap(listenerMap, context);
|
|
|
|
},
|
|
|
|
|
|
|
|
addRetroactiveListenerMap: function(listenerMap, context) {
|
|
|
|
return this.__getEventEmitter().addListenerMap(listenerMap, context);
|
|
|
|
},
|
|
|
|
|
|
|
|
removeAllListeners: function() {
|
|
|
|
this.__getEventEmitter().removeAllListeners();
|
|
|
|
},
|
|
|
|
|
|
|
|
removeCurrentListener: function() {
|
|
|
|
this.__getEventEmitter().removeCurrentListener();
|
|
|
|
},
|
|
|
|
|
|
|
|
releaseHeldEventType: function(eventType) {
|
|
|
|
this.__getEventEmitter().releaseHeldEventType(eventType);
|
|
|
|
},
|
|
|
|
|
|
|
|
__getEventEmitter: function() {
|
|
|
|
if (!this.__eventEmitter) {
|
2016-05-16 11:04:37 +00:00
|
|
|
let emitter = new EventEmitter();
|
2015-01-30 01:10:49 +00:00
|
|
|
emitter = EventValidator.addValidation(emitter, this.__types);
|
|
|
|
|
2016-05-16 11:04:37 +00:00
|
|
|
const holder = new EventHolder();
|
2015-01-30 01:10:49 +00:00
|
|
|
this.__eventEmitter = new EventEmitterWithHolding(emitter, holder);
|
|
|
|
}
|
|
|
|
return this.__eventEmitter;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = mixInEventEmitter;
|