| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 | 
							- /* This Source Code Form is subject to the terms of the Mozilla Public
 
-  * License, v. 2.0. If a copy of the MPL was not distributed with this
 
-  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
- "use strict";
 
- module.metadata = {
 
-   "stability": "unstable"
 
- };
 
- const UNCAUGHT_ERROR = 'An error event was emitted for which there was no listener.';
 
- const BAD_LISTENER = 'The event listener must be a function.';
 
- const { ns } = require('../core/namespace');
 
- const event = ns();
 
- const EVENT_TYPE_PATTERN = /^on([A-Z]\w+$)/;
 
- exports.EVENT_TYPE_PATTERN = EVENT_TYPE_PATTERN;
 
- // Utility function to access given event `target` object's event listeners for
 
- // the specific event `type`. If listeners for this type does not exists they
 
- // will be created.
 
- const observers = function observers(target, type) {
 
-   if (!target) throw TypeError("Event target must be an object");
 
-   let listeners = event(target);
 
-   return type in listeners ? listeners[type] : listeners[type] = [];
 
- };
 
- /**
 
-  * Registers an event `listener` that is called every time events of
 
-  * specified `type` is emitted on the given event `target`.
 
-  * @param {Object} target
 
-  *    Event target object.
 
-  * @param {String} type
 
-  *    The type of event.
 
-  * @param {Function} listener
 
-  *    The listener function that processes the event.
 
-  */
 
- function on(target, type, listener) {
 
-   if (typeof(listener) !== 'function')
 
-     throw new Error(BAD_LISTENER);
 
-   let listeners = observers(target, type);
 
-   if (!~listeners.indexOf(listener))
 
-     listeners.push(listener);
 
- }
 
- exports.on = on;
 
- /**
 
-  * Registers an event `listener` that is called only the next time an event
 
-  * of the specified `type` is emitted on the given event `target`.
 
-  * @param {Object} target
 
-  *    Event target object.
 
-  * @param {String} type
 
-  *    The type of the event.
 
-  * @param {Function} listener
 
-  *    The listener function that processes the event.
 
-  */
 
- function once(target, type, listener) {
 
-   on(target, type, function observer(...args) {
 
-     off(target, type, observer);
 
-     listener.apply(target, args);
 
-   });
 
- }
 
- exports.once = once;
 
- /**
 
-  * Execute each of the listeners in order with the supplied arguments.
 
-  * All the exceptions that are thrown by listeners during the emit
 
-  * are caught and can be handled by listeners of 'error' event. Thrown
 
-  * exceptions are passed as an argument to an 'error' event listener.
 
-  * If no 'error' listener is registered exception will be logged into an
 
-  * error console.
 
-  * @param {Object} target
 
-  *    Event target object.
 
-  * @param {String} type
 
-  *    The type of event.
 
-  * @params {Object|Number|String|Boolean} args
 
-  *    Arguments that will be passed to listeners.
 
-  */
 
- function emit (target, type, ...args) {
 
-   let state = observers(target, type);
 
-   let listeners = state.slice();
 
-   let count = listeners.length;
 
-   let index = 0;
 
-   // If error event and there are no handlers then print error message
 
-   // into a console.
 
-   if (count === 0 && type === 'error') console.exception(args[0]);
 
-   while (index < count) {
 
-     try {
 
-       let listener = listeners[index];
 
-       // Dispatch only if listener is still registered.
 
-       if (~state.indexOf(listener))
 
-         listener.apply(target, args);
 
-     }
 
-     catch (error) {
 
-       // If exception is not thrown by a error listener and error listener is
 
-       // registered emit `error` event. Otherwise dump exception to the console.
 
-       if (type !== 'error') emit(target, 'error', error);
 
-       else console.exception(error);
 
-     }
 
-     index++;
 
-   }
 
-    // Also emit on `"*"` so that one could listen for all events.
 
-   if (type !== '*') emit(target, '*', type, ...args);
 
- }
 
- exports.emit = emit;
 
- /**
 
-  * Removes an event `listener` for the given event `type` on the given event
 
-  * `target`. If no `listener` is passed removes all listeners of the given
 
-  * `type`. If `type` is not passed removes all the listeners of the given
 
-  * event `target`.
 
-  * @param {Object} target
 
-  *    The event target object.
 
-  * @param {String} type
 
-  *    The type of event.
 
-  * @param {Function} listener
 
-  *    The listener function that processes the event.
 
-  */
 
- function off(target, type, listener) {
 
-   let length = arguments.length;
 
-   if (length === 3) {
 
-     let listeners = observers(target, type);
 
-     let index = listeners.indexOf(listener);
 
-     if (~index)
 
-       listeners.splice(index, 1);
 
-   }
 
-   else if (length === 2) {
 
-     observers(target, type).splice(0);
 
-   }
 
-   else if (length === 1) {
 
-     let listeners = event(target);
 
-     Object.keys(listeners).forEach(type => delete listeners[type]);
 
-   }
 
- }
 
- exports.off = off;
 
- /**
 
-  * Returns a number of event listeners registered for the given event `type`
 
-  * on the given event `target`.
 
-  */
 
- function count(target, type) {
 
-   return observers(target, type).length;
 
- }
 
- exports.count = count;
 
- /**
 
-  * Registers listeners on the given event `target` from the given `listeners`
 
-  * dictionary. Iterates over the listeners and if property name matches name
 
-  * pattern `onEventType` and property is a function, then registers it as
 
-  * an `eventType` listener on `target`.
 
-  *
 
-  * @param {Object} target
 
-  *    The type of event.
 
-  * @param {Object} listeners
 
-  *    Dictionary of listeners.
 
-  */
 
- function setListeners(target, listeners) {
 
-   Object.keys(listeners || {}).forEach(key => {
 
-     let match = EVENT_TYPE_PATTERN.exec(key);
 
-     let type = match && match[1].toLowerCase();
 
-     if (!type) return;
 
-     let listener = listeners[key];
 
-     if (typeof(listener) === 'function')
 
-       on(target, type, listener);
 
-   });
 
- }
 
- exports.setListeners = setListeners;
 
 
  |