browser/extensions/shield-recipe-client/lib/EventEmitter.jsm
author Kris Maglione <maglione.k@gmail.com>
Wed, 24 Jan 2018 15:48:47 -0800
changeset 455769 d4a7c018420e408fbe0a13ffddd2861623fda5a7
parent 400059 705c76502231517ea3c065d17eb86a80a7e11279
child 455772 cc87ad81ff86109c7ea0187424fa9a8ed3b4af6c
permissions -rw-r--r--
Bug 1431533: Part 5a - Auto-rewrite code to use ChromeUtils import methods. r=florian MozReview-Commit-ID: 8V1ZT53ReiP

/* 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";

const {utils: Cu} = Components;
ChromeUtils.import("resource://shield-recipe-client/lib/LogManager.jsm");

this.EXPORTED_SYMBOLS = ["EventEmitter"];

const log = LogManager.getLogger("event-emitter");

this.EventEmitter = function(sandboxManager) {
  const listeners = {};

  return {
    createSandboxedEmitter() {
      return sandboxManager.cloneInto({
        on: this.on.bind(this),
        off: this.off.bind(this),
        once: this.once.bind(this),
      }, {cloneFunctions: true});
    },

    emit(eventName, event) {
      // Fire events async
      Promise.resolve()
        .then(() => {
          if (!(eventName in listeners)) {
            log.debug(`EventEmitter: Event fired with no listeners: ${eventName}`);
            return;
          }
          // Clone callbacks array to avoid problems with mutation while iterating
          const callbacks = Array.from(listeners[eventName]);
          for (const cb of callbacks) {
            cb(sandboxManager.cloneInto(event));
          }
        });
    },

    on(eventName, callback) {
      if (!(eventName in listeners)) {
        listeners[eventName] = [];
      }
      listeners[eventName].push(callback);
    },

    off(eventName, callback) {
      if (eventName in listeners) {
        const index = listeners[eventName].indexOf(callback);
        if (index !== -1) {
          listeners[eventName].splice(index, 1);
        }
      }
    },

    once(eventName, callback) {
      const inner = event => {
        callback(event);
        this.off(eventName, inner);
      };
      this.on(eventName, inner);
    },
  };
};