Skip to content

Commit

Permalink
Merge pull request browserify#40 from cedx/master
Browse files Browse the repository at this point in the history
Update to Node.js 8 events API
  • Loading branch information
Gozala authored Jan 30, 2018
2 parents 623b6f5 + 535b0c6 commit 580b99a
Show file tree
Hide file tree
Showing 16 changed files with 1,119 additions and 486 deletions.
572 changes: 379 additions & 193 deletions events.js

Large diffs are not rendered by default.

104 changes: 76 additions & 28 deletions tests/add-listeners.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,45 +19,93 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

var common = require('./common');
var assert = require('assert');
var events = require('../');
var EventEmitter = require('../');

var e = new events.EventEmitter();
{
var ee = new EventEmitter();
var events_new_listener_emitted = [];
var listeners_new_listener_emitted = [];

var events_new_listener_emited = [];
var listeners_new_listener_emited = [];
var times_hello_emited = 0;
// Sanity check
assert.strictEqual(ee.addListener, ee.on);

// sanity check
assert.equal(e.addListener, e.on);
ee.on('newListener', function(event, listener) {
// Don't track newListener listeners.
if (event === 'newListener')
return;

e.on('newListener', function(event, listener) {
console.log('newListener: ' + event);
events_new_listener_emited.push(event);
listeners_new_listener_emited.push(listener);
});
events_new_listener_emitted.push(event);
listeners_new_listener_emitted.push(listener);
});

function hello(a, b) {
console.log('hello');
times_hello_emited += 1;
assert.equal('a', a);
assert.equal('b', b);
}
e.on('hello', hello);
var hello = common.mustCall(function(a, b) {
assert.strictEqual('a', a);
assert.strictEqual('b', b);
});

ee.once('newListener', function(name, listener) {
assert.strictEqual(name, 'hello');
assert.strictEqual(listener, hello);

var foo = function() {};
e.once('foo', foo);
var listeners = this.listeners('hello');
assert.ok(Array.isArray(listeners));
assert.strictEqual(listeners.length, 0);
});

console.log('start');
ee.on('hello', hello);
ee.once('foo', assert.fail);

e.emit('hello', 'a', 'b');
assert.ok(Array.isArray(events_new_listener_emitted));
assert.strictEqual(events_new_listener_emitted.length, 2);
assert.strictEqual(events_new_listener_emitted[0], 'hello');
assert.strictEqual(events_new_listener_emitted[1], 'foo');

assert.ok(Array.isArray(listeners_new_listener_emitted));
assert.strictEqual(listeners_new_listener_emitted.length, 2);
assert.strictEqual(listeners_new_listener_emitted[0], hello);
assert.strictEqual(listeners_new_listener_emitted[1], assert.fail);

ee.emit('hello', 'a', 'b');
}

// just make sure that this doesn't throw:
var f = new events.EventEmitter();
f.setMaxListeners(0);
{
var f = new EventEmitter();

f.setMaxListeners(0);
}

{
var listen1 = function() {};
var listen2 = function() {};
var ee = new EventEmitter();

ee.once('newListener', function() {
var listeners = ee.listeners('hello');
assert.ok(Array.isArray(listeners));
assert.strictEqual(listeners.length, 0);
ee.once('newListener', function() {
var listeners = ee.listeners('hello');
assert.ok(Array.isArray(listeners));
assert.strictEqual(listeners.length, 0);
});
ee.on('hello', listen2);
});
ee.on('hello', listen1);
// The order of listeners on an event is not always the order in which the
// listeners were added.
var listeners = ee.listeners('hello');
assert.ok(Array.isArray(listeners));
assert.strictEqual(listeners.length, 2);
assert.strictEqual(listeners[0], listen2);
assert.strictEqual(listeners[1], listen1);
}

assert.deepEqual(['hello', 'foo'], events_new_listener_emited);
assert.deepEqual([hello, foo], listeners_new_listener_emited);
assert.equal(1, times_hello_emited);
// Verify that the listener must be a function
assert.throws(function() {
var ee = new EventEmitter();

ee.on('foo', null);
}, /^TypeError: "listener" argument must be a function$/);
107 changes: 57 additions & 50 deletions tests/check-listener-leaks.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,68 +19,75 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

var common = require('./common');
var assert = require('assert');
var events = require('../');

var e = new events.EventEmitter();

// default
for (var i = 0; i < 10; i++) {
e.on('default', function() {});
}
assert.ok(!e._events['default'].hasOwnProperty('warned'));
e.on('default', function() {});
assert.ok(e._events['default'].warned);
{
var e = new events.EventEmitter();

// specific
e.setMaxListeners(5);
for (var i = 0; i < 5; i++) {
e.on('specific', function() {});
}
assert.ok(!e._events['specific'].hasOwnProperty('warned'));
e.on('specific', function() {});
assert.ok(e._events['specific'].warned);
for (var i = 0; i < 10; i++) {
e.on('default', common.mustNotCall());
}
assert.ok(!e._events['default'].hasOwnProperty('warned'));
e.on('default', common.mustNotCall());
assert.ok(e._events['default'].warned);

// specific
e.setMaxListeners(5);
for (var i = 0; i < 5; i++) {
e.on('specific', common.mustNotCall());
}
assert.ok(!e._events['specific'].hasOwnProperty('warned'));
e.on('specific', common.mustNotCall());
assert.ok(e._events['specific'].warned);

// only one
e.setMaxListeners(1);
e.on('only one', function() {});
assert.ok(!e._events['only one'].hasOwnProperty('warned'));
e.on('only one', function() {});
assert.ok(e._events['only one'].hasOwnProperty('warned'));
// only one
e.setMaxListeners(1);
e.on('only one', common.mustNotCall());
assert.ok(!e._events['only one'].hasOwnProperty('warned'));
e.on('only one', common.mustNotCall());
assert.ok(e._events['only one'].hasOwnProperty('warned'));

// unlimited
e.setMaxListeners(0);
for (var i = 0; i < 1000; i++) {
e.on('unlimited', function() {});
// unlimited
e.setMaxListeners(0);
for (var i = 0; i < 1000; i++) {
e.on('unlimited', common.mustNotCall());
}
assert.ok(!e._events['unlimited'].hasOwnProperty('warned'));
}
assert.ok(!e._events['unlimited'].hasOwnProperty('warned'));

// process-wide
events.EventEmitter.defaultMaxListeners = 42;
e = new events.EventEmitter();
{
events.EventEmitter.defaultMaxListeners = 42;
var e = new events.EventEmitter();

for (var i = 0; i < 42; ++i) {
e.on('fortytwo', function() {});
}
assert.ok(!e._events['fortytwo'].hasOwnProperty('warned'));
e.on('fortytwo', function() {});
assert.ok(e._events['fortytwo'].hasOwnProperty('warned'));
delete e._events['fortytwo'].warned;
for (var i = 0; i < 42; ++i) {
e.on('fortytwo', common.mustNotCall());
}
assert.ok(!e._events['fortytwo'].hasOwnProperty('warned'));
e.on('fortytwo', common.mustNotCall());
assert.ok(e._events['fortytwo'].hasOwnProperty('warned'));
delete e._events['fortytwo'].warned;

events.EventEmitter.defaultMaxListeners = 44;
e.on('fortytwo', function() {});
assert.ok(!e._events['fortytwo'].hasOwnProperty('warned'));
e.on('fortytwo', function() {});
assert.ok(e._events['fortytwo'].hasOwnProperty('warned'));
events.EventEmitter.defaultMaxListeners = 44;
e.on('fortytwo', common.mustNotCall());
assert.ok(!e._events['fortytwo'].hasOwnProperty('warned'));
e.on('fortytwo', common.mustNotCall());
assert.ok(e._events['fortytwo'].hasOwnProperty('warned'));
}

// but _maxListeners still has precedence over defaultMaxListeners
events.EventEmitter.defaultMaxListeners = 42;
e = new events.EventEmitter();
e.setMaxListeners(1);
e.on('uno', function() {});
assert.ok(!e._events['uno'].hasOwnProperty('warned'));
e.on('uno', function() {});
assert.ok(e._events['uno'].hasOwnProperty('warned'));
{
events.EventEmitter.defaultMaxListeners = 42;
var e = new events.EventEmitter();
e.setMaxListeners(1);
e.on('uno', common.mustNotCall());
assert.ok(!e._events['uno'].hasOwnProperty('warned'));
e.on('uno', common.mustNotCall());
assert.ok(e._events['uno'].hasOwnProperty('warned'));

// chainable
assert.strictEqual(e, e.setMaxListeners(1));
// chainable
assert.strictEqual(e, e.setMaxListeners(1));
}
86 changes: 68 additions & 18 deletions tests/common.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,92 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

var assert = require('assert');

var noop = function() {};

var mustCallChecks = [];

function runCallChecks() {
var failed_count = 0;
for (var i=0 ; i< mustCallChecks.length; ++i) {
var context = mustCallChecks[i];
if (context.actual === context.expected) {
continue;
function runCallChecks(exitCode) {
if (exitCode !== 0) return;

var failed = mustCallChecks.filter(function(context) {
if ('minimum' in context) {
context.messageSegment = 'at least ' + context.minimum;
return context.actual < context.minimum;
} else {
context.messageSegment = 'exactly ' + context.exact;
return context.actual !== context.exact;
}
});

failed_count++;
console.log('Mismatched %s function calls. Expected %d, actual %d.',
context.name,
context.expected,
context.actual);
failed.forEach(function(context) {
console.log('Mismatched %s function calls. Expected %s, actual %d.',
context.name,
context.messageSegment,
context.actual);
console.log(context.stack.split('\n').slice(2).join('\n'));
}
});

assert(failed_count === 0);
assert.strictEqual(failed.length, 0);
}

after(runCallChecks);
exports.mustCall = function(fn, exact) {
return _mustCallInner(fn, exact, 'exact');
};

function _mustCallInner(fn, criteria, field) {
if (typeof criteria == 'undefined') criteria = 1;

exports.mustCall = function(fn, expected) {
if (typeof expected !== 'number') expected = 1;
if (typeof fn === 'number') {
criteria = fn;
fn = noop;
} else if (fn === undefined) {
fn = noop;
}

if (typeof criteria !== 'number')
throw new TypeError('Invalid ' + field + ' value: ' + criteria);

var context = {
expected: expected,
actual: 0,
stack: (new Error).stack,
stack: (new Error()).stack,
name: fn.name || '<anonymous>'
};

context[field] = criteria;

// add the exit listener only once to avoid listener leak warnings
if (mustCallChecks.length === 0) after(function() { runCallChecks(0); });

mustCallChecks.push(context);

return function() {
context.actual++;
return fn.apply(this, arguments);
};
}

exports.mustNotCall = function(msg) {
return function mustNotCall() {
assert.fail(msg || 'function should not have been called');
};
};
2 changes: 1 addition & 1 deletion tests/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ var require = function(file) {
test(file, function() {
orig_require(file);
});
}
};

require('./add-listeners.js');
require('./check-listener-leaks.js');
Expand Down
1 change: 1 addition & 0 deletions tests/listener-count.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

require('./common');
var assert = require('assert');
var EventEmitter = require('../');

Expand Down
Loading

0 comments on commit 580b99a

Please sign in to comment.