addon-sdk/source/lib/sdk/event/core.js

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 "use strict";
     7 module.metadata = {
     8   "stability": "unstable"
     9 };
    11 const UNCAUGHT_ERROR = 'An error event was emitted for which there was no listener.';
    12 const BAD_LISTENER = 'The event listener must be a function.';
    14 const { ns } = require('../core/namespace');
    16 const event = ns();
    18 const EVENT_TYPE_PATTERN = /^on([A-Z]\w+$)/;
    19 exports.EVENT_TYPE_PATTERN = EVENT_TYPE_PATTERN;
    21 // Utility function to access given event `target` object's event listeners for
    22 // the specific event `type`. If listeners for this type does not exists they
    23 // will be created.
    24 const observers = function observers(target, type) {
    25   if (!target) throw TypeError("Event target must be an object");
    26   let listeners = event(target);
    27   return type in listeners ? listeners[type] : listeners[type] = [];
    28 };
    30 /**
    31  * Registers an event `listener` that is called every time events of
    32  * specified `type` is emitted on the given event `target`.
    33  * @param {Object} target
    34  *    Event target object.
    35  * @param {String} type
    36  *    The type of event.
    37  * @param {Function} listener
    38  *    The listener function that processes the event.
    39  */
    40 function on(target, type, listener) {
    41   if (typeof(listener) !== 'function')
    42     throw new Error(BAD_LISTENER);
    44   let listeners = observers(target, type);
    45   if (!~listeners.indexOf(listener))
    46     listeners.push(listener);
    47 }
    48 exports.on = on;
    50 /**
    51  * Registers an event `listener` that is called only the next time an event
    52  * of the specified `type` is emitted on the given event `target`.
    53  * @param {Object} target
    54  *    Event target object.
    55  * @param {String} type
    56  *    The type of the event.
    57  * @param {Function} listener
    58  *    The listener function that processes the event.
    59  */
    60 function once(target, type, listener) {
    61   on(target, type, function observer(...args) {
    62     off(target, type, observer);
    63     listener.apply(target, args);
    64   });
    65 }
    66 exports.once = once;
    68 /**
    69  * Execute each of the listeners in order with the supplied arguments.
    70  * All the exceptions that are thrown by listeners during the emit
    71  * are caught and can be handled by listeners of 'error' event. Thrown
    72  * exceptions are passed as an argument to an 'error' event listener.
    73  * If no 'error' listener is registered exception will be logged into an
    74  * error console.
    75  * @param {Object} target
    76  *    Event target object.
    77  * @param {String} type
    78  *    The type of event.
    79  * @params {Object|Number|String|Boolean} args
    80  *    Arguments that will be passed to listeners.
    81  */
    82 function emit (target, type, ...args) {
    83   let state = observers(target, type);
    84   let listeners = state.slice();
    85   let count = listeners.length;
    86   let index = 0;
    88   // If error event and there are no handlers then print error message
    89   // into a console.
    90   if (count === 0 && type === 'error') console.exception(args[0]);
    91   while (index < count) {
    92     try {
    93       let listener = listeners[index];
    94       // Dispatch only if listener is still registered.
    95       if (~state.indexOf(listener))
    96         listener.apply(target, args);
    97     }
    98     catch (error) {
    99       // If exception is not thrown by a error listener and error listener is
   100       // registered emit `error` event. Otherwise dump exception to the console.
   101       if (type !== 'error') emit(target, 'error', error);
   102       else console.exception(error);
   103     }
   104     index++;
   105   }
   106    // Also emit on `"*"` so that one could listen for all events.
   107   if (type !== '*') emit(target, '*', type, ...args);
   108 }
   109 exports.emit = emit;
   111 /**
   112  * Removes an event `listener` for the given event `type` on the given event
   113  * `target`. If no `listener` is passed removes all listeners of the given
   114  * `type`. If `type` is not passed removes all the listeners of the given
   115  * event `target`.
   116  * @param {Object} target
   117  *    The event target object.
   118  * @param {String} type
   119  *    The type of event.
   120  * @param {Function} listener
   121  *    The listener function that processes the event.
   122  */
   123 function off(target, type, listener) {
   124   let length = arguments.length;
   125   if (length === 3) {
   126     let listeners = observers(target, type);
   127     let index = listeners.indexOf(listener);
   128     if (~index)
   129       listeners.splice(index, 1);
   130   }
   131   else if (length === 2) {
   132     observers(target, type).splice(0);
   133   }
   134   else if (length === 1) {
   135     let listeners = event(target);
   136     Object.keys(listeners).forEach(type => delete listeners[type]);
   137   }
   138 }
   139 exports.off = off;
   141 /**
   142  * Returns a number of event listeners registered for the given event `type`
   143  * on the given event `target`.
   144  */
   145 function count(target, type) {
   146   return observers(target, type).length;
   147 }
   148 exports.count = count;
   150 /**
   151  * Registers listeners on the given event `target` from the given `listeners`
   152  * dictionary. Iterates over the listeners and if property name matches name
   153  * pattern `onEventType` and property is a function, then registers it as
   154  * an `eventType` listener on `target`.
   155  *
   156  * @param {Object} target
   157  *    The type of event.
   158  * @param {Object} listeners
   159  *    Dictionary of listeners.
   160  */
   161 function setListeners(target, listeners) {
   162   Object.keys(listeners || {}).forEach(key => {
   163     let match = EVENT_TYPE_PATTERN.exec(key);
   164     let type = match && match[1].toLowerCase();
   165     if (!type) return;
   167     let listener = listeners[key];
   168     if (typeof(listener) === 'function')
   169       on(target, type, listener);
   170   });
   171 }
   172 exports.setListeners = setListeners;

mercurial