770e75743a1cdfc72ef953333def1cea338d395e
[platform/upstream/iotjs.git] / src / js / events.js
1 /* Copyright 2015-present Samsung Electronics Co., Ltd. and other contributors
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16
17 var util = require('util');
18
19
20 function EventEmitter() {
21   this._events = {};
22 };
23
24 module.exports.EventEmitter = EventEmitter;
25
26
27 EventEmitter.prototype.emit = function(type) {
28   if (!this._events) {
29     this._events = {};
30   }
31
32   // About to emit 'error' event but there are no listeners for it.
33   if (type === 'error' && !this._events.error) {
34     var err = arguments[1];
35     if (err instanceof Error) {
36       throw err;
37     } else {
38       throw Error("Uncaught 'error' event");
39     }
40     return false;
41   }
42
43   var listeners = this._events[type];
44   if (util.isArray(listeners)) {
45     listeners = listeners.slice();
46     var len = arguments.length;
47     var args = new Array(len - 1);
48     for (var i = 1; i < len; ++i) {
49       args[i - 1] = arguments[i];
50     }
51     for (var i = 0; i < listeners.length; ++i) {
52       listeners[i].apply(this, args);
53     }
54     return true;
55   }
56
57   return false;
58 };
59
60
61 EventEmitter.prototype.addListener = function(type, listener) {
62   if (!util.isFunction(listener)) {
63     throw new TypeError('listener must be a function');
64   }
65
66   if (!this._events) {
67     this._events = {};
68   }
69   if (!this._events[type]) {
70     this._events[type] = [];
71   }
72
73   this._events[type].push(listener);
74
75   return this;
76 };
77
78
79 EventEmitter.prototype.on = EventEmitter.prototype.addListener;
80
81
82 EventEmitter.prototype.once = function(type, listener) {
83   if (!util.isFunction(listener)) {
84     throw new TypeError('listener must be a function');
85   }
86
87   var f = function() {
88     // here `this` is this not global, because EventEmitter binds event object
89     // for this when it calls back the handler.
90     this.removeListener(f.type, f);
91     f.listener.apply(this, arguments);
92   };
93
94   f.type = type;
95   f.listener = listener;
96
97   this.on(type, f);
98
99   return this;
100 };
101
102
103 EventEmitter.prototype.removeListener = function(type, listener) {
104   if (!util.isFunction(listener)) {
105     throw new TypeError('listener must be a function');
106   }
107
108   var list = this._events[type];
109   if (Array.isArray(list)) {
110     for (var i = list.length - 1; i >= 0; --i) {
111       if (list[i] == listener ||
112           (list[i].listener && list[i].listener == listener)) {
113         list.splice(i, 1);
114         break;
115       }
116     }
117   }
118
119   return this;
120
121 };
122
123
124 EventEmitter.prototype.removeAllListeners = function(type) {
125   if (arguments.length === 0) {
126     this._events = {};
127   } else {
128     delete this._events[type];
129   }
130
131   return this;
132 };