Skip to content
Permalink
Browse files
Merge pull request #60 from brodybits/events-singleton
Cordova events singleton object
  • Loading branch information
Chris Brody committed Dec 20, 2018
2 parents 1bb65ca + cb62920 commit 1bbc93dc734cae7a60710007bbab1eb89cafe2b2
Showing 1 changed file with 51 additions and 42 deletions.
@@ -17,56 +17,65 @@
under the License.
*/

var EventEmitter = require('events').EventEmitter;
const EventEmitter = require('events').EventEmitter;

var INSTANCE = new EventEmitter();
INSTANCE.setMaxListeners(20);
var EVENTS_RECEIVER;
const MAX_LISTENERS = 20;

module.exports = INSTANCE;
const INSTANCE_KEY = Symbol.for('org.apache.cordova.common.CordovaEvents');

/**
* Sets up current instance to forward emitted events to another EventEmitter
* instance.
*
* @param {EventEmitter} [eventEmitter] The emitter instance to forward
* events to. Falsy value, when passed, disables forwarding.
*/
module.exports.forwardEventsTo = function (eventEmitter) {
let EVENTS_RECEIVER = null;

// If no argument is specified disable events forwarding
if (!eventEmitter) {
EVENTS_RECEIVER = undefined;
return;
}
class CordovaEventEmitter extends EventEmitter {
/**
* Sets up current instance to forward emitted events to another EventEmitter
* instance.
*
* @param {EventEmitter} [eventEmitter] The emitter instance to forward
* events to. Falsy value, when passed, disables forwarding.
*/
forwardEventsTo (eventEmitter) {
// If no argument is specified disable events forwarding
if (!eventEmitter) {
EVENTS_RECEIVER = undefined;
return;
}

if (!(eventEmitter instanceof EventEmitter)) { throw new Error('Cordova events can be redirected to another EventEmitter instance only'); }
if (!(eventEmitter instanceof EventEmitter)) {
throw new Error('Cordova events can be redirected to another EventEmitter instance only');
}

// CB-10940 Skipping forwarding to self to avoid infinite recursion.
// This is the case when the modules are npm-linked.
if (this !== eventEmitter) {
EVENTS_RECEIVER = eventEmitter;
} else {
// Reset forwarding if we are subscribing to self
EVENTS_RECEIVER = undefined;
// CB-10940 Skipping forwarding to self to avoid infinite recursion.
// This is the case when the modules are npm-linked.
if (this !== eventEmitter) {
EVENTS_RECEIVER = eventEmitter;
} else {
// Reset forwarding if we are subscribing to self
EVENTS_RECEIVER = undefined;
}
}
};

var emit = INSTANCE.emit;

/**
* This method replaces original 'emit' method to allow events forwarding.
*
* @return {eventEmitter} Current instance to allow calls chaining, as
* original 'emit' does
*/
module.exports.emit = function () {

var args = Array.prototype.slice.call(arguments);
/**
* Sets up current instance to forward emitted events to another EventEmitter
* instance.
*
* @param {EventEmitter} [eventEmitter] The emitter instance to forward
* events to. Falsy value, when passed, disables forwarding.
*/
emit (eventName, ...args) {
if (EVENTS_RECEIVER) {
EVENTS_RECEIVER.emit(eventName, ...args);
}

if (EVENTS_RECEIVER) {
EVENTS_RECEIVER.emit.apply(EVENTS_RECEIVER, args);
return super.emit(eventName, ...args);
}
}

// This singleton instance pattern is based on the ideas from
// https://derickbailey.com/2016/03/09/creating-a-true-singleton-in-node-js-with-es6-symbols/
if (Object.getOwnPropertySymbols(global).indexOf(INSTANCE_KEY) === -1) {
const events = new CordovaEventEmitter();
events.setMaxListeners(MAX_LISTENERS);
global[INSTANCE_KEY] = events;
}

return emit.apply(this, args);
};
module.exports = global[INSTANCE_KEY];

0 comments on commit 1bbc93d

Please sign in to comment.