'use strict';

var slice       = require('es5-ext/lib/List/slice').call
  , invoke      = require('es5-ext/lib/Object/invoke').apply
  , describeAll = require('es5-ext/lib/Object/to-descriptors').call

  , ee, emit;

ee = describeAll({
	on: function (type, listener) {
		if (!this.ee) {
			Object.defineProperty(this, 'ee', { value: {} });
		}
		if (!this.ee[type]) {
			this.ee[type] = [];
		}
		this.ee[type].push(listener);
	},
	once: function (type, listener) {
		var un = this.off.bind(this);
		this.on(type, function self () {
			un(type, self);
			listener.apply(this, arguments);
		});
	},
	off: function (type, listener) {
		var index, ls = this.ee && this.ee[type];
		if (ls && ((index = ls.indexOf(listener)) !== -1)) {
			ls.splice(index, 1);
		}
	},
	emit: function (type) {
		if (this.ee && this.ee[type]) {
			this.ee[type].forEach(invoke(this, slice(arguments, 1)));
		}
	}
});

module.exports = function (o) {
	if (!o) {
		o = {};
	}

	return Object.defineProperties(o, ee);
};

@@ -769,24 +769,33 @@
 : function (
+emitter, 
 type) %7B%0A%09%09if
@@ -796,97 +796,355 @@
 %7B%0A%09%09
-if (this.ee && this.ee%5Btype%5D) %7B%0A%09%09%09this.ee%5Btype%5D.forEach(invoke(this, slice(arguments, 1)
+var args;%0A%09%09if (typeof emitter === 'string') %7B%0A%09%09%09type = emitter;%0A%09%09%09args = slice(arguments, 1);%0A%09%09%09emitter = null;%0A%09%09%7D else %7B%0A%09%09%09args = slice(arguments, 2);%0A%09%09%7D%0A%09%09if (this.ee && this.ee%5Btype%5D) %7B%0A%09%09%09this.ee%5Btype%5D.forEach(emitter ? function (listener) %7B%0A%09%09%09%09if (listener !== emitter) %7B%0A%09%09%09%09%09listener.call(this, args);%0A%09%09%09%09%7D%0A%09%09%09%7D : invoke(this, args
 ));%0A

Support for emitter argument in emit function. Emitter won't be notified with events he invoked.