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

sysend

Package Overview
Dependencies
Maintainers
1
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sysend - npm Package Compare versions

Comparing version 1.3.5 to 1.4.0

sysend.d.ts

3

package.json
{
"name": "sysend",
"version": "1.3.5",
"version": "1.4.0",
"description": "Send messages to other tabs/windows in the same browser",
"main": "sysend.js",
"typings": "sysend.d.ts",
"scripts": {

@@ -7,0 +8,0 @@ },

@@ -1,9 +0,9 @@

[![Sysend.js Logo](https://github.com/jcubic/sysend.js/blob/master/assets/logo.svg?raw=true)](https://github.com/jcubic/sysend.js)
![Sysend.js Logo](https://github.com/jcubic/sysend.js/blob/master/assets/logo.svg?raw=true)
[![npm](https://img.shields.io/badge/npm-1.3.5-blue.svg)](https://www.npmjs.com/package/sysend)
![bower](https://img.shields.io/badge/bower-1.3.5-yellow.svg)
[![npm](https://img.shields.io/badge/npm-1.4.0-blue.svg)](https://www.npmjs.com/package/sysend)
![bower](https://img.shields.io/badge/bower-1.4.0-yellow.svg)
![downloads](https://img.shields.io/npm/dt/sysend.svg)
[![jsdelivr](https://img.shields.io/jsdelivr/npm/hm/sysend)](https://www.jsdelivr.com/package/npm/sysend)
# Send messages between browser tabs
# [Send messages between browser tabs](https://github.com/jcubic/sysend.js/)

@@ -14,3 +14,3 @@ sysend.js is a small library that allows to send messages between pages that are

If your browser don't support BroadcastChannel (see [Can I Use](https://caniuse.com/#feat=broadcastchannel))
then you can send any object that can be serialized to JSON with BroadcastChannel you can send any object
then you can send any object that can be serialized to JSON. With BroadcastChannel you can send any object
(it will not be serialized to string but the values are limited to the ones that can be copied by

@@ -20,3 +20,2 @@ the [structured cloning algorithm](https://html.spec.whatwg.org/multipage/structured-data.html#structured-clone)).

Tested on:

@@ -28,2 +27,10 @@

## Note about Safari 7+ and Cross-Domain communication
All cross-domain communication is disabled by default with Safari 7+.
Because of a feature that block 3rd party tracking for iframe, and any
iframe used for cross-domain communication runs in sandboxed environment.
That's why this library like any other solution for cross-domain comunication,
don't work on Safari.
## Installation

@@ -61,3 +68,2 @@

```javascript
window.onload = function() {

@@ -84,5 +90,16 @@ sysend.on('foo', function(message) {

if you want to send custom data you can use serializer (new in 1.4.0).
Example serializer can be [json-dry](https://github.com/11ways/json-dry).
```javascript
sysend.serializer(function(data) {
return Dry.stringify(data);
}, function(string) {
return Dry.parse(string);
});
````
## Demo
Open this [demo page](http://jcubic.pl/sysend.php) in two tabs/windows.
Open this [demo page](http://jcubic.pl/sysend.php) in two tabs/windows (there is also link to other domain).

@@ -93,6 +110,7 @@ ## API

* on(name, callback) - callback(object, name) - add event of specified name
* off(name [, callback]) - remove callback
* broadcast(name [, object]) - send object and fire all events with specified name (in different pages that register callback using on). You can also just send notification without object
* proxy(url) - create iframe proxy for different domain, the targer domain/url should have [proxy.html](https://github.com/jcubic/sysend.js/blob/master/proxy.html) file. If url domain is the same as page domain, it's ignored. So you can put both proxy calls on both domains (new in 1.3.0)
* `on(name, callback)` - `callback(object, name)` - add event of specified name
* `off(name [, callback])` - remove callback
* `broadcast(name [, object])` - send object and fire all events with specified name (in different pages that register callback using on). You can also just send notification without object
* `proxy(url)` - create iframe proxy for different domain, the targer domain/url should have [proxy.html](https://github.com/jcubic/sysend.js/blob/master/proxy.html) file. If url domain is the same as page domain, it's ignored. So you can put both proxy calls on both domains (new in 1.3.0)
* `serializer(to_string, from_string)` - add serializer and deserializer functions (new in 1.4.0)

@@ -99,0 +117,0 @@ ## License

/**@license
* sysend.js - send messages between browser windows/tabs version 1.3.5
* sysend.js - send messages between browser windows/tabs version 1.4.0
*

@@ -25,58 +25,3 @@ * Copyright (C) 2014-2021 Jakub T. Jankiewicz <https://jcubic.pl/me>

var random_value = Math.random();
// we use id because storage event is not executed if message was not
// changed, and we want it if user send same object twice (before it will
// be removed)
var id = 0;
// we need to clean up localStorage if broadcast on unload
// because setTimeout will never fire, even setTimeout 0
var re = new RegExp('^' + uniq_prefix);
for(var key in localStorage) {
if (key.match(re)) {
localStorage.removeItem(key);
}
}
function get(key) {
return localStorage.getItem(uniq_prefix + key);
}
function set(key, value) {
// storage event is not fired when value is set first time
if (id == 0) {
localStorage.setItem(uniq_prefix + key, random_value);
}
localStorage.setItem(uniq_prefix + key, value);
}
function remove(key) {
localStorage.removeItem(uniq_prefix + key);
}
function to_json(input) {
// save random_value in storage to fix issue in IE that storage event
// is fired on same page where setItem was called
var obj = [id++, random_value];
// undefined in array get stringified as null
if (typeof input != 'undefined') {
obj.push(input);
}
return JSON.stringify(obj);
}
function from_json(json) {
return JSON.parse(json);
}
var host = (function() {
var a = document.createElement('a');
return function(url) {
a.href = url;
return a.host;
};
})();
function send_to_iframes(key, data) {
// propagate events to iframes
iframes.forEach(function(iframe) {
var payload = {
name: uniq_prefix,
key: key,
data: data
};
iframe.window.postMessage(JSON.stringify(payload), "*");
});
}
var serializer = {};
// object with user events as keys and values arrays of callback functions

@@ -87,61 +32,16 @@ var callbacks = {};

var channel;
if (typeof window.BroadcastChannel === 'function') {
channel = new window.BroadcastChannel(uniq_prefix);
channel.addEventListener('message', function(event) {
if (event.target.name === uniq_prefix) {
var key = event.data && event.data.name;
if (callbacks[key]) {
callbacks[key].forEach(function(fn) {
fn(event.data.data, key);
});
}
}
});
} else {
window.addEventListener('storage', function(e) {
// prevent event to be executed on remove in IE
if (e.key.match(re) && index++ % 2 === 0) {
var key = e.key.replace(re, '');
if (callbacks[key]) {
var value = e.newValue || get(key);
if (value && value != random_value) {
var obj = JSON.parse(value);
if (obj && obj[1] != random_value) {
// don't call on remove
callbacks[key].forEach(function(fn) {
fn(obj[2], key);
});
}
}
}
}
}, false);
}
// ref: https://stackoverflow.com/a/326076/387194
function is_iframe() {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
if (is_iframe()) {
window.addEventListener('message', function(e) {
if (typeof e.data === 'string' && e.data.match(prefix_re)) {
try {
var payload = JSON.parse(e.data);
if (payload && payload.name === uniq_prefix) {
sysend.broadcast(payload.key, payload.data);
}
} catch(e) {
// ignore wrong JSON, the message don't came from Sysend
// even that the string have unix_prefix, this is just in case
}
}
});
}
return {
// we use id because storage event is not executed if message was not
// changed, and we want it if user send same object twice (before it will
// be removed)
var id = 0;
// -------------------------------------------------------------------------
init();
// -------------------------------------------------------------------------
var serialize = make_process(serializer, 'to');
var unserialize = make_process(serializer, 'from');
// -------------------------------------------------------------------------
var sysend = {
broadcast: function(event, message) {
if (channel) {
channel.postMessage({name: event, data: message});
channel.postMessage({name: event, data: serialize(message)});
} else {

@@ -156,2 +56,10 @@ set(event, to_json(message));

},
serializer: function(to, from) {
if (typeof to !== 'function' || typeof from !== 'function') {
throw new Error('sysend::serializer: Invalid argument, expecting' +
' function');
}
serializer.to = to;
serializer.from = from;
},
proxy: function(url) {

@@ -168,3 +76,4 @@ if (typeof url === 'string' && host(url) !== window.location.host) {

setTimeout(function() {
throw new Error('html proxy file not found on "' + url + '" url');
throw new Error('html proxy file not found on "' + url +
'" url');
}, 0);

@@ -175,2 +84,4 @@ iframe.removeEventListener('error', handler);

var win;
// fix for Safari
// https://stackoverflow.com/q/42632188/387194
try {

@@ -208,2 +119,171 @@ win = iframe.contentWindow;

};
// -------------------------------------------------------------------------
function get(key) {
return localStorage.getItem(uniq_prefix + key);
}
// -------------------------------------------------------------------------
function set(key, value) {
// storage event is not fired when value is set first time
if (id == 0) {
localStorage.setItem(uniq_prefix + key, random_value);
}
localStorage.setItem(uniq_prefix + key, value);
}
// -------------------------------------------------------------------------
function remove(key) {
localStorage.removeItem(uniq_prefix + key);
}
// -------------------------------------------------------------------------
function make_process(object, prop) {
var labels = {
from: 'Unserialize',
to: 'Serialize'
};
var prefix_message = labels[prop] + ' Error: ';
return function(data) {
var fn = object[prop];
try {
if (fn) {
return fn(data);
}
return data;
} catch (e) {
console.warn(prefix_message + e.message);
}
};
}
// -------------------------------------------------------------------------
// ref: https://stackoverflow.com/a/326076/387194
// -------------------------------------------------------------------------
function is_iframe() {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
// -------------------------------------------------------------------------
function send_to_iframes(key, data) {
// propagate events to iframes
iframes.forEach(function(iframe) {
var payload = {
name: uniq_prefix,
key: key,
data: data
};
iframe.window.postMessage(JSON.stringify(payload), "*");
});
}
// -------------------------------------------------------------------------
function to_json(input) {
// save random_value in storage to fix issue in IE that storage event
// is fired on same page where setItem was called
var obj = [id++, random_value];
// undefined in array get stringified as null
if (typeof input != 'undefined') {
obj.push(input);
}
var data = serialize(obj);
if (data === obj) {
return JSON.stringify(obj);
}
return data;
}
// -------------------------------------------------------------------------
function from_json(json) {
var result = unserialize(json);
if (result === json) {
return JSON.parse(json);
}
return result;
}
// -------------------------------------------------------------------------
var host = (function() {
if (typeof URL !== 'undefined') {
return function(url) {
url = new URL(url);
return url.host;
};
}
var a = document.createElement('a');
return function(url) {
a.href = url;
return a.host;
};
})();
// -------------------------------------------------------------------------
function invoke(key, data) {
callbacks[key].forEach(function(fn) {
fn(data, key);
});
}
// -------------------------------------------------------------------------
function is_private_mode() {
try {
localStorage.setItem(uniq_prefix, 1);
localStorage.removeItem(uniq_prefix);
return false;
} catch (e) {
return true;
}
}
// -------------------------------------------------------------------------
function init() {
// we need to clean up localStorage if broadcast called on unload
// because setTimeout will never fire, even setTimeout 0
var re = new RegExp('^' + uniq_prefix);
for(var key in localStorage) {
if (key.match(re)) {
localStorage.removeItem(key);
}
}
if (typeof window.BroadcastChannel === 'function') {
channel = new window.BroadcastChannel(uniq_prefix);
channel.addEventListener('message', function(event) {
if (event.target.name === uniq_prefix) {
var key = event.data && event.data.name;
if (callbacks[key]) {
invoke(key, unserialize(event.data.data));
}
}
});
} else if (is_private_mode()) {
console.warn('Your browser don\'t support localStorgage. ' +
'In Safari this is most of the time because ' +
'of "Private Browsing Mode"');
} else {
window.addEventListener('storage', function(e) {
// prevent event to be executed on remove in IE
if (e.key.match(re) && index++ % 2 === 0) {
var key = e.key.replace(re, '');
if (callbacks[key]) {
var value = e.newValue || get(key);
if (value && value != random_value) {
var obj = from_json(value);
// don't call on remove
if (obj && obj[1] != random_value) {
invoke(key, obj[2]);
}
}
}
}
}, false);
}
if (is_iframe()) {
window.addEventListener('message', function(e) {
if (typeof e.data === 'string' && e.data.match(prefix_re)) {
try {
var payload = JSON.parse(e.data);
if (payload && payload.name === uniq_prefix) {
sysend.broadcast(payload.key, unserialize(payload.data));
}
} catch(e) {
// ignore wrong JSON, the message don't came from Sysend
// even that the string have unix_prefix, this is just in case
}
}
});
}
}
return sysend;
});
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