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
			| 
								 
											3 years ago
										 
									 | 
							
								'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);
							 |