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