-
Notifications
You must be signed in to change notification settings - Fork 5
/
events.cljs
99 lines (85 loc) · 3.09 KB
/
events.cljs
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
(ns redlobster.events)
;; Protocol
(defprotocol IEventEmitter
(on [emitter event listener])
(once [emitter event listener])
(remove-listener [emitter event listener])
(remove-all-listeners [emitter])
(remove-all-listeners [emitter event])
(listeners [emitter event])
(emit [emitter event data]))
;; Utility functions
(defn unpack-event [event]
(if (keyword? event)
(name event)
event))
(defn wrap-once [emitter event listener]
(fn once-off [x]
(listener x)
(remove-listener emitter event once-off)))
;; Default implementation
(defn- def-add-listener [type listener]
(fn [this]
(let [listeners (or (get this type) #{})]
(assoc this type (conj listeners listener)))))
(defn- def-rem-listener [type listener]
(fn [this]
(let [listeners (or (get this type) #{})]
(assoc this type (disj listeners listener)))))
(deftype DefaultEventEmitter [events]
IEventEmitter
(on [this event listener]
(swap! events (def-add-listener event listener)))
(once [this event listener]
(set! (.-__redlobster_event_once listener) true)
(swap! events (def-add-listener event listener)))
(remove-listener [this event listener]
(swap! events (def-rem-listener event listener)))
(remove-all-listeners [this]
(reset! events {}))
(remove-all-listeners [this event]
(swap! events #(dissoc % event)))
(listeners [this event]
(get @events event))
(emit [this event data]
(doseq [listener (listeners this event)]
(listener data)
(when (.-__redlobster_event_once listener)
(remove-listener this event listener)))))
;; Implementations
(def ^:private implementations
[(fn impl-node []
(try
(let [EventEmitter (.-EventEmitter (js/require "events"))]
{:constructor (fn [] (EventEmitter.))
:type :node
:init
(fn []
(extend-protocol IEventEmitter
EventEmitter
(on [emitter event listener]
(.on emitter (unpack-event event) listener))
(once [emitter event listener]
(.once emitter (unpack-event event) listener))
(remove-listener [emitter event listener]
(.removeListener emitter (unpack-event event) listener))
(remove-all-listeners [emitter]
(.removeAllListeners emitter))
(remove-all-listeners [emitter event]
(.removeAllListeners emitter (unpack-event event)))
(listeners [emitter event]
(js->clj (.listeners emitter (unpack-event event))))
(emit [emitter event data]
(.emit emitter (unpack-event event) data))))})
(catch js/Error e nil)))
(fn impl-default []
{:constructor (fn [] (DefaultEventEmitter. (atom {})))
:type :default
:init (fn [])})])
;; Initialise the first available implementation
(let [emitter (some #(%) implementations)]
(if (nil? emitter) (throw (js/Error. "No supported EventEmitter found"))
(do
(def event-emitter (:constructor emitter))
(def emitter-type (:type emitter))
((:init emitter)))))