summaryrefslogtreecommitdiffstats
path: root/toolkit/components/normandy/lib/EventEmitter.sys.mjs
blob: 551fc4d6b22b2841de8481a7afe0a6835af66252 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/* 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/. */

import { LogManager } from "resource://normandy/lib/LogManager.sys.mjs";

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

export var EventEmitter = function () {
  const listeners = {};

  return {
    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) {
          // Clone event so it can't by modified by the handler
          let eventToPass = event;
          if (typeof event === "object") {
            eventToPass = Object.assign({}, event);
          }
          cb(eventToPass);
        }
      });
    },

    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);
    },
  };
};