123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. 'use strict';
  2. var has = Object.prototype.hasOwnProperty;
  3. /**
  4. * An auto incrementing id which we can use to create "unique" Ultron instances
  5. * so we can track the event emitters that are added through the Ultron
  6. * interface.
  7. *
  8. * @type {Number}
  9. * @private
  10. */
  11. var id = 0;
  12. /**
  13. * Ultron is high-intelligence robot. It gathers intelligence so it can start improving
  14. * upon his rudimentary design. It will learn from your EventEmitting patterns
  15. * and exterminate them.
  16. *
  17. * @constructor
  18. * @param {EventEmitter} ee EventEmitter instance we need to wrap.
  19. * @api public
  20. */
  21. function Ultron(ee) {
  22. if (!(this instanceof Ultron)) return new Ultron(ee);
  23. this.id = id++;
  24. this.ee = ee;
  25. }
  26. /**
  27. * Register a new EventListener for the given event.
  28. *
  29. * @param {String} event Name of the event.
  30. * @param {Functon} fn Callback function.
  31. * @param {Mixed} context The context of the function.
  32. * @returns {Ultron}
  33. * @api public
  34. */
  35. Ultron.prototype.on = function on(event, fn, context) {
  36. fn.__ultron = this.id;
  37. this.ee.on(event, fn, context);
  38. return this;
  39. };
  40. /**
  41. * Add an EventListener that's only called once.
  42. *
  43. * @param {String} event Name of the event.
  44. * @param {Function} fn Callback function.
  45. * @param {Mixed} context The context of the function.
  46. * @returns {Ultron}
  47. * @api public
  48. */
  49. Ultron.prototype.once = function once(event, fn, context) {
  50. fn.__ultron = this.id;
  51. this.ee.once(event, fn, context);
  52. return this;
  53. };
  54. /**
  55. * Remove the listeners we assigned for the given event.
  56. *
  57. * @returns {Ultron}
  58. * @api public
  59. */
  60. Ultron.prototype.remove = function remove() {
  61. var args = arguments
  62. , ee = this.ee
  63. , event;
  64. //
  65. // When no event names are provided we assume that we need to clear all the
  66. // events that were assigned through us.
  67. //
  68. if (args.length === 1 && 'string' === typeof args[0]) {
  69. args = args[0].split(/[, ]+/);
  70. } else if (!args.length) {
  71. if (ee.eventNames) {
  72. args = ee.eventNames();
  73. } else if (ee._events) {
  74. args = [];
  75. for (event in ee._events) {
  76. if (has.call(ee._events, event)) args.push(event);
  77. }
  78. if (Object.getOwnPropertySymbols) {
  79. args = args.concat(Object.getOwnPropertySymbols(ee._events));
  80. }
  81. }
  82. }
  83. for (var i = 0; i < args.length; i++) {
  84. var listeners = ee.listeners(args[i]);
  85. for (var j = 0; j < listeners.length; j++) {
  86. event = listeners[j];
  87. //
  88. // Once listeners have a `listener` property that stores the real listener
  89. // in the EventEmitter that ships with Node.js.
  90. //
  91. if (event.listener) {
  92. if (event.listener.__ultron !== this.id) continue;
  93. } else if (event.__ultron !== this.id) {
  94. continue;
  95. }
  96. ee.removeListener(args[i], event);
  97. }
  98. }
  99. return this;
  100. };
  101. /**
  102. * Destroy the Ultron instance, remove all listeners and release all references.
  103. *
  104. * @returns {Boolean}
  105. * @api public
  106. */
  107. Ultron.prototype.destroy = function destroy() {
  108. if (!this.ee) return false;
  109. this.remove();
  110. this.ee = null;
  111. return true;
  112. };
  113. //
  114. // Expose the module.
  115. //
  116. module.exports = Ultron;