| 'use strict'; | 
|   | 
| var common = require('./common'); | 
| var EventEmitter = require('../').EventEmitter; | 
| var once = require('../').once; | 
| var has = require('has'); | 
| var assert = require('assert'); | 
|   | 
| function Event(type) { | 
|   this.type = type; | 
| } | 
|   | 
| function EventTargetMock() { | 
|   this.events = {}; | 
|   | 
|   this.addEventListener = common.mustCall(this.addEventListener); | 
|   this.removeEventListener = common.mustCall(this.removeEventListener); | 
| } | 
|   | 
| EventTargetMock.prototype.addEventListener = function addEventListener(name, listener, options) { | 
|   if (!(name in this.events)) { | 
|     this.events[name] = { listeners: [], options: options || {} } | 
|   } | 
|   this.events[name].listeners.push(listener); | 
| }; | 
|   | 
| EventTargetMock.prototype.removeEventListener = function removeEventListener(name, callback) { | 
|   if (!(name in this.events)) { | 
|     return; | 
|   } | 
|   var event = this.events[name]; | 
|   var stack = event.listeners; | 
|   | 
|   for (var i = 0, l = stack.length; i < l; i++) { | 
|     if (stack[i] === callback) { | 
|       stack.splice(i, 1); | 
|       if (stack.length === 0) { | 
|         delete this.events[name]; | 
|       } | 
|       return; | 
|     } | 
|   } | 
| }; | 
|   | 
| EventTargetMock.prototype.dispatchEvent = function dispatchEvent(arg) { | 
|   if (!(arg.type in this.events)) { | 
|     return true; | 
|   } | 
|   | 
|   var event = this.events[arg.type]; | 
|   var stack = event.listeners.slice(); | 
|   | 
|   for (var i = 0, l = stack.length; i < l; i++) { | 
|     stack[i].call(null, arg); | 
|     if (event.options.once) { | 
|       this.removeEventListener(arg.type, stack[i]); | 
|     } | 
|   } | 
|   return !arg.defaultPrevented; | 
| }; | 
|   | 
| function onceAnEvent() { | 
|   var ee = new EventEmitter(); | 
|   | 
|   process.nextTick(function () { | 
|     ee.emit('myevent', 42); | 
|   }); | 
|   | 
|   return once(ee, 'myevent').then(function (args) { | 
|     var value = args[0] | 
|     assert.strictEqual(value, 42); | 
|     assert.strictEqual(ee.listenerCount('error'), 0); | 
|     assert.strictEqual(ee.listenerCount('myevent'), 0); | 
|   }); | 
| } | 
|   | 
| function onceAnEventWithTwoArgs() { | 
|   var ee = new EventEmitter(); | 
|   | 
|   process.nextTick(function () { | 
|     ee.emit('myevent', 42, 24); | 
|   }); | 
|   | 
|   return once(ee, 'myevent').then(function (value) { | 
|     assert.strictEqual(value.length, 2); | 
|     assert.strictEqual(value[0], 42); | 
|     assert.strictEqual(value[1], 24); | 
|   }); | 
| } | 
|   | 
| function catchesErrors() { | 
|   var ee = new EventEmitter(); | 
|   | 
|   var expected = new Error('kaboom'); | 
|   var err; | 
|   process.nextTick(function () { | 
|     ee.emit('error', expected); | 
|   }); | 
|   | 
|   return once(ee, 'myevent').then(function () { | 
|     throw new Error('should reject') | 
|   }, function (err) { | 
|     assert.strictEqual(err, expected); | 
|     assert.strictEqual(ee.listenerCount('error'), 0); | 
|     assert.strictEqual(ee.listenerCount('myevent'), 0); | 
|   }); | 
| } | 
|   | 
| function stopListeningAfterCatchingError() { | 
|   var ee = new EventEmitter(); | 
|   | 
|   var expected = new Error('kaboom'); | 
|   var err; | 
|   process.nextTick(function () { | 
|     ee.emit('error', expected); | 
|     ee.emit('myevent', 42, 24); | 
|   }); | 
|   | 
|   // process.on('multipleResolves', common.mustNotCall()); | 
|   | 
|   return once(ee, 'myevent').then(common.mustNotCall, function (err) { | 
|     // process.removeAllListeners('multipleResolves'); | 
|     assert.strictEqual(err, expected); | 
|     assert.strictEqual(ee.listenerCount('error'), 0); | 
|     assert.strictEqual(ee.listenerCount('myevent'), 0); | 
|   }); | 
| } | 
|   | 
| function onceError() { | 
|   var ee = new EventEmitter(); | 
|   | 
|   var expected = new Error('kaboom'); | 
|   process.nextTick(function () { | 
|     ee.emit('error', expected); | 
|   }); | 
|   | 
|   var promise = once(ee, 'error'); | 
|   assert.strictEqual(ee.listenerCount('error'), 1); | 
|   return promise.then(function (args) { | 
|     var err = args[0] | 
|     assert.strictEqual(err, expected); | 
|     assert.strictEqual(ee.listenerCount('error'), 0); | 
|     assert.strictEqual(ee.listenerCount('myevent'), 0); | 
|   }); | 
| } | 
|   | 
| function onceWithEventTarget() { | 
|   var et = new EventTargetMock(); | 
|   var event = new Event('myevent'); | 
|   process.nextTick(function () { | 
|     et.dispatchEvent(event); | 
|   }); | 
|   return once(et, 'myevent').then(function (args) { | 
|     var value = args[0]; | 
|     assert.strictEqual(value, event); | 
|     assert.strictEqual(has(et.events, 'myevent'), false); | 
|   }); | 
| } | 
|   | 
| function onceWithEventTargetError() { | 
|   var et = new EventTargetMock(); | 
|   var error = new Event('error'); | 
|   process.nextTick(function () { | 
|     et.dispatchEvent(error); | 
|   }); | 
|   return once(et, 'error').then(function (args) { | 
|     var err = args[0]; | 
|     assert.strictEqual(err, error); | 
|     assert.strictEqual(has(et.events, 'error'), false); | 
|   }); | 
| } | 
|   | 
| function prioritizesEventEmitter() { | 
|   var ee = new EventEmitter(); | 
|   ee.addEventListener = assert.fail; | 
|   ee.removeAllListeners = assert.fail; | 
|   process.nextTick(function () { | 
|     ee.emit('foo'); | 
|   }); | 
|   return once(ee, 'foo'); | 
| } | 
|   | 
| var allTests = [ | 
|   onceAnEvent(), | 
|   onceAnEventWithTwoArgs(), | 
|   catchesErrors(), | 
|   stopListeningAfterCatchingError(), | 
|   onceError(), | 
|   onceWithEventTarget(), | 
|   onceWithEventTargetError(), | 
|   prioritizesEventEmitter() | 
| ]; | 
|   | 
| var hasBrowserEventTarget = false; | 
| try { | 
|   hasBrowserEventTarget = typeof (new window.EventTarget().addEventListener) === 'function' && | 
|     new window.Event('xyz').type === 'xyz'; | 
| } catch (err) {} | 
|   | 
| if (hasBrowserEventTarget) { | 
|   var onceWithBrowserEventTarget = function onceWithBrowserEventTarget() { | 
|     var et = new window.EventTarget(); | 
|     var event = new window.Event('myevent'); | 
|     process.nextTick(function () { | 
|       et.dispatchEvent(event); | 
|     }); | 
|     return once(et, 'myevent').then(function (args) { | 
|       var value = args[0]; | 
|       assert.strictEqual(value, event); | 
|       assert.strictEqual(has(et.events, 'myevent'), false); | 
|     }); | 
|   } | 
|   | 
|   var onceWithBrowserEventTargetError = function onceWithBrowserEventTargetError() { | 
|     var et = new window.EventTarget(); | 
|     var error = new window.Event('error'); | 
|     process.nextTick(function () { | 
|       et.dispatchEvent(error); | 
|     }); | 
|     return once(et, 'error').then(function (args) { | 
|       var err = args[0]; | 
|       assert.strictEqual(err, error); | 
|       assert.strictEqual(has(et.events, 'error'), false); | 
|     }); | 
|   } | 
|   | 
|   common.test.comment('Testing with browser built-in EventTarget'); | 
|   allTests.push([ | 
|     onceWithBrowserEventTarget(), | 
|     onceWithBrowserEventTargetError() | 
|   ]); | 
| } | 
|   | 
| module.exports = Promise.all(allTests); |