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.
		
		
		
		
		
			
		
			
				
					
					
						
							235 lines
						
					
					
						
							6.0 KiB
						
					
					
				
			
		
		
	
	
							235 lines
						
					
					
						
							6.0 KiB
						
					
					
				| '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);
 |