You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

133 lines
2.9 KiB

'use strict';
var d = require('d')
, callable = require('es5-ext/object/valid-callable')
, apply = Function.prototype.apply, call = Function.prototype.call
, create = Object.create, defineProperty = Object.defineProperty
, defineProperties = Object.defineProperties
, hasOwnProperty = Object.prototype.hasOwnProperty
, descriptor = { configurable: true, enumerable: false, writable: true }
, on, once, off, emit, methods, descriptors, base;
on = function (type, listener) {
var data;
callable(listener);
if (!hasOwnProperty.call(this, '__ee__')) {
data = descriptor.value = create(null);
defineProperty(this, '__ee__', descriptor);
descriptor.value = null;
} else {
data = this.__ee__;
}
if (!data[type]) data[type] = listener;
else if (typeof data[type] === 'object') data[type].push(listener);
else data[type] = [data[type], listener];
return this;
};
once = function (type, listener) {
var once, self;
callable(listener);
self = this;
on.call(this, type, once = function () {
off.call(self, type, once);
apply.call(listener, this, arguments);
});
once.__eeOnceListener__ = listener;
return this;
};
off = function (type, listener) {
var data, listeners, candidate, i;
callable(listener);
if (!hasOwnProperty.call(this, '__ee__')) return this;
data = this.__ee__;
if (!data[type]) return this;
listeners = data[type];
if (typeof listeners === 'object') {
for (i = 0; (candidate = listeners[i]); ++i) {
if ((candidate === listener) ||
(candidate.__eeOnceListener__ === listener)) {
if (listeners.length === 2) data[type] = listeners[i ? 0 : 1];
else listeners.splice(i, 1);
}
}
} else {
if ((listeners === listener) ||
(listeners.__eeOnceListener__ === listener)) {
delete data[type];
}
}
return this;
};
emit = function (type) {
var i, l, listener, listeners, args;
if (!hasOwnProperty.call(this, '__ee__')) return;
listeners = this.__ee__[type];
if (!listeners) return;
if (typeof listeners === 'object') {
l = arguments.length;
args = new Array(l - 1);
for (i = 1; i < l; ++i) args[i - 1] = arguments[i];
listeners = listeners.slice();
for (i = 0; (listener = listeners[i]); ++i) {
apply.call(listener, this, args);
}
} else {
switch (arguments.length) {
case 1:
call.call(listeners, this);
break;
case 2:
call.call(listeners, this, arguments[1]);
break;
case 3:
call.call(listeners, this, arguments[1], arguments[2]);
break;
default:
l = arguments.length;
args = new Array(l - 1);
for (i = 1; i < l; ++i) {
args[i - 1] = arguments[i];
}
apply.call(listeners, this, args);
}
}
};
methods = {
on: on,
once: once,
off: off,
emit: emit
};
descriptors = {
on: d(on),
once: d(once),
off: d(off),
emit: d(emit)
};
base = defineProperties({}, descriptors);
module.exports = exports = function (o) {
return (o == null) ? create(base) : defineProperties(Object(o), descriptors);
};
exports.methods = methods;