Skip to content

Commit

Permalink
New: First implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
phated committed May 14, 2018
1 parent 04349af commit 80358e3
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 0 deletions.
60 changes: 60 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
'use strict';

var EventEmitter = require('events').EventEmitter;

var namespace = '__sparklesEventEmitter';

var ee = new EventEmitter();

ee.setMaxListeners(0);

function attach(type, listener){
// node will never fire the newListener on itself,
// so only check for remove/detach combo
if(type === 'removeListener' && listener === detach){
return;
}

if(!global[namespace]){
global[namespace] = ee;
}
}

function detach(){
var events = Object.keys(ee._events);
var removeListeners = ee.listeners('removeListener');
var newListeners = ee.listeners('newListener');

if(events.length > 2){
return;
}

if(removeListeners.length !== 1){
return;
}

if(newListeners.length !== 1 && events.length !== 1){
return;
}

delete global[namespace];

process.nextTick(rewire);
}

function rewire(){
var removeListeners = ee.listeners('removeListener');
var newListeners = ee.listeners('newListener');

if(!removeListeners.length){
ee.on('removeListener', detach);
}

if(!newListeners.length){
ee.on('newListener', attach);
}
}

rewire();

module.exports = ee;
30 changes: 30 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "sparkles",
"version": "1.0.0",
"description": "Namespaced global event emitter",
"main": "index.js",
"scripts": {
"test": "lab -cv"
},
"repository": {
"type": "git",
"url": "https://github.com/phated/sparkles"
},
"keywords": [
"global",
"ee",
"events",
"emitter",
"namespaced"
],
"author": "Blaine Bublitz <blaine@iceddev.com> (http://iceddev.com/)",
"license": "MIT",
"bugs": {
"url": "https://github.com/phated/sparkles/issues"
},
"homepage": "https://github.com/phated/sparkles",
"dependencies": {
"code": "^1.2.1",
"lab": "^5.1.0"
}
}
70 changes: 70 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
'use strict';

var lab = exports.lab = require('lab').script();
var describe = lab.describe;
var it = lab.it;
var before = lab.before;
var beforeEach = lab.beforeEach;
var after = lab.after;
var afterEach = lab.afterEach;
var expect = require('code').expect;

var sparkles = require('../');

function noop(){}

function noop2(){}

describe('sparkles', function(){

it('will attach an event emitter to global upon the first `on` call', function(done){
expect(global.__sparklesEventEmitter).to.not.exist();
sparkles.on('test', noop);
expect(global.__sparklesEventEmitter).to.exist();
done();
});

it('removes the event emitter from global if no more listeners exist it', function(done){
expect(global.__sparklesEventEmitter).to.exist();
sparkles.removeListener('test', noop);
expect(global.__sparklesEventEmitter).to.not.exist();
done();
});

it('even works with removeAllListeners', function(done){
expect(global.__sparklesEventEmitter).to.not.exist();
sparkles.on('test1', noop);
sparkles.on('test2', noop2);
expect(global.__sparklesEventEmitter).to.exist();
sparkles.removeAllListeners();
expect(global.__sparklesEventEmitter).to.not.exist();
done();
});

it('gracefully handles newListeners being added', function(done){
expect(global.__sparklesEventEmitter).to.not.exist();
sparkles.on('newListener', noop);
expect(global.__sparklesEventEmitter).to.exist();
sparkles.removeAllListeners('newListener');
expect(global.__sparklesEventEmitter).to.not.exist();
done();
});

it('gracefully handles removeListeners being added', function(done){
expect(global.__sparklesEventEmitter).to.not.exist();
sparkles.on('removeListener', noop);
sparkles.on('removeListener', noop2);
expect(global.__sparklesEventEmitter).to.exist();
sparkles.removeListener('removeListener', noop);
expect(global.__sparklesEventEmitter).to.exist();
done();
});

it('recovers from removeAllListeners on removeListener', function(done){
sparkles.removeAllListeners('removeListener');
process.nextTick(function(){
expect(sparkles.listeners('removeListener')).to.have.length(1);
done();
});
});
});

0 comments on commit 80358e3

Please sign in to comment.