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
2 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);
|