Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

crosstab

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

crosstab - npm Package Compare versions

Comparing version 0.2.5 to 0.2.6

2

bower.json
{
"name": "crosstab",
"version": "v0.2.5",
"version": "v0.2.6",
"homepage": "https://github.com/tejacques/crosstab",

@@ -5,0 +5,0 @@ "authors": [

{
"name": "crosstab",
"version": "0.2.5",
"version": "0.2.6",
"description": "A utility library for cross-tab communication using localStorage.",

@@ -5,0 +5,0 @@ "author": "Tom Jacques <tejacques@gmail.com>",

@@ -57,3 +57,3 @@ # crosstab [![NPM version][npm-img]][npm-url] [![Build Status][travis-img]][travis-url]

crosstab registers event handlers like this:
crosstab registers and unregisters event handlers like this:

@@ -70,8 +70,8 @@ ```JavaScript

var message = {
id: util.generateId(), // The unique ID of this message
event: event, // The name of the event
data: data, // The data to pass
destination: destination, // The destination tab
origin: crosstab.id, // The origin tab
timestamp: util.now() // The time the message was created
id: string, // The unique ID of this message
event: string, // The name of the event
data: any, // The data passed
destination: string, // The destination tab
origin: string, // The origin tab
timestamp: number // The time the message was created
};

@@ -86,13 +86,59 @@ ```

I wanted to be able to have robust cross tab communication for the purpose of resource sharing (such as websockets). Though there are some libraries which have a similar goal, they all had subtle issues. This library aims to be the most correct it can be for supported browsers. This library was created with inspiration from the excellent [intercom.js](https://github.com/diy/intercom.js/) library, and addresses several of it's shortcomings:
I wanted to be able to have robust cross tab communication for the purpose of resource sharing (such as websockets). Though there are some libraries which have a similar goal, they all had subtle issues. This library aims to be the most correct it can be for supported browsers. This library was created with inspiration from the [intercom.js](https://github.com/diy/intercom.js/) library, and addresses several of it's shortcomings by dropping support for IE8 and using a lockless system that is entirely event driven. IE8 can still be used with crosstab by using the [tejacques/IE8-EventListener](https://github.com/tejacques/IE8-EventListener) EventListener polyfill
* intercom.js doesn't implement proper locking.
* does not guarantee that one tab holds the lock at a time (in fact this is impossible to guarantee flat out, but can be guaranteed within defined execution times).
* locking on functions that throw will break.
* Updates to any localStorage item will cause the locks to attempt to be acquired instead of only removals of the lock.
* in trying to support IE8 message broadcasting in intercom.js has a race condition where messages can be dropped.
* intercom.js leaks memory by maintaining a state of every message id received (also in an attempt to support IE8)
Contributing
------------
crosstab solves these issues by dropping support for IE8 and using a lockless system that is entirely event driven (IE8 cannot pass messages via localStorage events, which is why intercom.js requires locking, because it supports IE8).
Contributions are welcome and encouraged, you can contribute in several different ways, by filing issues, commenting on discussions, or contributing code.
### Filing issues ###
Please use the issue tracker for discussions and bug reports. For bug reports, please include as much detail as possible.
These will help determine/resolve your issue:
* Clear description of the problem or unexpexted behavior
* Clear description of the expected result or output
* Steps to reproduce
* Steps you have taken to debug it yourself
* Minimal reproducible example with self contained and runnable JS code
### Contributing Code ###
#### Project Workflow ####
We use roughly the [Github Workflow](https://guides.github.com/introduction/flow/). You should:
* Create an issue for the feature/bug
* Fork the project
* Create a new branch
* Commit changes
* Submit a pull request to the master branch
#### Tests ####
Tests can be run with the following command:
```.sh
grunt test
```
* Tests must pass
* Tests should be added for each bug/feature that is added
* All tests should be self-contained
* If test is determined to be too difficult to create for an issue, there does not need to be a test for it
#### Getting Started ####
```.sh
git clone https://github.com/tejacques/crosstab
cd crosstab
npm install
grunt
```
You can now access:
* Examples: [http://localhost:9000](http://localhost:9000)
* Tests: [http://localhost:9000/test/mocha_test.html](http://localhost:9000/test/mocha_test.html)
[downloads-img]: https://img.shields.io/npm/dm/crosstab.svg

@@ -99,0 +145,0 @@ [npm-url]: https://npmjs.org/package/crosstab

/*!
* crosstab JavaScript Library v0.2.5
* crosstab JavaScript Library v0.2.6
* https://github.com/tejacques/crosstab

@@ -79,6 +79,20 @@ *

util.forEachObj = function (thing, fn) {
for (var key in thing) {
if (thing.hasOwnProperty(key)) {
fn.call(thing, thing[key], key);
var toString = Object.prototype.toString;
util.isArray = Array.isArray || function (arr) {
return arr instanceof Array;
};
util.isNumber = function (num) {
return typeof num === 'number';
};
util.isFunction = function (fn) {
return typeof fn === 'function';
};
util.forEachObj = function (obj, fn) {
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
fn.call(obj, obj[key], key);
}

@@ -88,5 +102,6 @@ }

util.forEachArr = function (thing, fn) {
for (var i = 0; i < thing.length; i++) {
fn.call(thing, thing[i], i);
util.forEachArr = function (arr, fn) {
var len = arr.length
for (var i = 0; i < len; i++) {
fn.call(arr, arr[i], i, arr);
}

@@ -96,3 +111,3 @@ };

util.forEach = function (thing, fn) {
if (Object.prototype.toString.call(thing) === '[object Array]') {
if (util.isArray(thing)) {
util.forEachArr(thing, fn);

@@ -114,3 +129,3 @@ } else {

util.filter = function (thing, fn) {
var isArr = Object.prototype.toString.call(thing) === '[object Array]';
var isArr = util.isArray(thing);
var res = isArr ? [] : {};

@@ -149,19 +164,67 @@

// --- Events ---
// node.js style events, with the main difference being object based
// rather than array based, as well as being able to add/remove
// events by key.
// node.js style events, with the main difference being able
// to add/remove events by key.
util.createEventHandler = function () {
var events = {};
var subscribeKeyToListener = {};
var findHandlerByKey = function(event, key) {
var handler;
if (subscribeKeyToListener[event]) {
handler = subscribeKeyToListener[event][key];
}
return handler;
};
var findHandlerIndex = function (event, listener) {
var listenerIndex = -1;
var eventList = events[event];
if (eventList && listener) {
var len = eventList.length || 0;
for(var i = 0; i < len; i++) {
if (eventList[i] === listener) {
listenerIndex = i;
break;
}
}
}
return listenerIndex;
};
var addListener = function (event, listener, key) {
key = key || listener;
var handlers = listeners(event);
handlers[key] = listener;
return key;
var storedHandler = findHandlerByKey(event, key);
var listenerIndex;
if (storedHandler === undefined) {
listenerIndex = handlers.length;
handlers[listenerIndex] = listener;
if (!subscribeKeyToListener[event]) {
(subscribeKeyToListener[event] = {});
}
if (key) {
subscribeKeyToListener[event][key] = listener;
}
} else {
listenerIndex = findHandlerIndex(event, storedHandler);
handlers[listenerIndex] = listener;
}
return key || listener;
};
var removeListener = function (event, key) {
if (events[event] && events[event][key]) {
delete events[event][key];
var handler = util.isFunction(key)
? key
: findHandlerByKey(event, key);
var listenerIndex = findHandlerIndex(event, handler);
if (listenerIndex === -1) return false;
if (events[event] && events[event][listenerIndex]) {
events[event].splice(listenerIndex, 1);
delete subscribeKeyToListener[event][key];
return true;

@@ -173,9 +236,18 @@ }

var removeAllListeners = function (event) {
var successful = false;
if (event) {
if (events[event]) {
delete events[event];
successful = true;
}
if (subscribeKeyToListener[event]) {
delete subscribeKeyToListener[event];
successful = successful && true;
}
} else {
events = {};
subscribeKeyToListener = {};
successful = true;
}
return successful;
};

@@ -188,3 +260,3 @@

util.forEach(handlers, function (listener) {
if (typeof (listener) === 'function') {
if (util.isFunction(listener)) {
listener.apply(this, args);

@@ -197,4 +269,3 @@ }

// Generate a unique id for this listener
var handlers = listeners(event);
while (!key || handlers[key]) {
while (!key || (findHandlerByKey(event, key) !== undefined)) {
key = util.generateId();

@@ -213,10 +284,24 @@ }

var listeners = function (event) {
var handlers = events[event] = events[event] || {};
var handlers = events[event] = events[event] || [];
return handlers;
};
var destructor = function() {
removeAllListeners();
};
return {
addListener: addListener,
destructor: destructor,
on: addListener,
off: removeListener,
off: function(event, key) {
var argsLen = arguments.length;
if (!argsLen) {
return removeAllListeners();
} else if (argsLen === 1) {
return removeAllListeners(event);
} else {
return removeListener(event, key);
}
},
once: once,

@@ -243,3 +328,4 @@ emit: emit,

removeListener: eventHandler.removeListener,
removeAllListeners: eventHandler.removeAllListeners
removeAllListeners: eventHandler.removeAllListeners,
destructor: eventHandler.destructor
};

@@ -304,3 +390,4 @@

function beforeUnload() {
function unload() {
crosstab.stopKeepalive = true;
var numTabs = 0;

@@ -319,2 +406,4 @@ util.forEach(util.tabs, function (tab, key) {

}
util.events.destructor();
}

@@ -483,2 +572,3 @@

crosstab.once = util.events.once;
crosstab.off = util.events.off;

@@ -620,3 +710,3 @@ // --- Crosstab supported ---

window.addEventListener('storage', onStorageEvent, false);
window.addEventListener('beforeunload', beforeUnload, false);
window.addEventListener('unload', unload, false);

@@ -623,0 +713,0 @@ util.events.on('PING', function (message) {

@@ -80,3 +80,3 @@ // =========== Iframe Tools ==============

it ('should be a function', function () {
it('should be a function', function () {
expect(window.crosstab).to.be.a('function');

@@ -102,2 +102,86 @@ });

it('should invoke event listeners in the order they added', function () {
var msg = "TestMessage";
var order = [];
// http://stackoverflow.com/questions/280713/elements-order-in-a-for-in-loop
crosstab.on('test', function(message) {
expect((message || {}).data).to.be(msg);
order.push(2);
}, 'second');
crosstab.on('test', function(message) {
order.push(3);
}, '3');
crosstab.on('test', function(message) {
order.push(1);
}, 'first');
crosstab.on('test', function(message) {
expect((message || {}).data).to.be(msg);
order.push(101);
});
crosstab.on('test', function(message) {
order.push(102);
});
crosstab.broadcast('test', msg);
expect(order).to.eql([2, 3, 1, 101, 102]);
});
it('should not invoke event listener after unsubscribing', function() {
var msg = "test";
var received;
var offSuccessful;
var listeners = crosstab.util.events.listeners;
// -------------------------------
// unsubscribe with event + key
// -------------------------------
var evt1 = 'test-1';
crosstab.on(evt1, function(message) {
received = message.data + '-1';
}, 'first');
crosstab.broadcast(evt1, msg);
expect(received).to.eql(msg + '-1');
// unsubscribe with event + non-exist key
received = undefined;
offSuccessful = crosstab.off(evt1, 'non-exist');
expect(offSuccessful).to.eql(false);
crosstab.broadcast(evt1, msg);
expect(received).to.eql(msg + '-1');
// unsubscribe with event + key
var listenersLen = listeners(evt1).length;
received = undefined;
offSuccessful = crosstab.off(evt1, 'first');
expect(offSuccessful).to.eql(true);
crosstab.broadcast(evt1, msg);
expect(received).to.be(undefined);
expect(listeners(evt1).length).to.be(listenersLen-1);
// -------------------------------
// unsubscribe with event
// -------------------------------
var evt2 = 'test-2';
crosstab.on(evt2, function(message) {
received = message.data + '-1';
}, 'first');
crosstab.broadcast(evt2, msg);
expect(received).to.eql(msg + '-1');
// unsubcribe with non-exist event
received = undefined;
offSuccessful = crosstab.off('non-exist');
expect(offSuccessful).to.eql(false);
crosstab.broadcast(evt2, msg);
expect(received).to.eql(msg + '-1');
// unscribe with event
received = undefined;
offSuccessful = crosstab.off(evt2);
expect(offSuccessful).to.eql(true);
crosstab.broadcast(evt2, msg);
expect(received).to.be(undefined);
});
it('should only trigger callback once for crosstab.once', function () {

@@ -104,0 +188,0 @@ var msg = "TestOnce";

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc