New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

penpal

Package Overview
Dependencies
Maintainers
1
Versions
65
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

penpal - npm Package Compare versions

Comparing version 2.7.2 to 3.0.0-alpha.1

76

dist/penpal.js

@@ -142,5 +142,6 @@ // Derived from https://github.com/umdjs/umd/blob/master/templates/amdWebGlobal.js

/**
* Creates an object with methods that match those defined by the remote. When these methods are
* Augments an object with methods that match those defined by the remote. When these methods are
* called, a "call" message will be sent to the remote, the remote's corresponding method will be
* executed, and the method's return value will be returned via a message.
* @param {Object} callSender Sender object that should be augmented with methods.
* @param {Object} info Information about the local and remote windows.

@@ -150,5 +151,5 @@ * @param {Array} methodNames Names of methods available to be called on the remote.

* connection.
* @returns {Object} An object with methods that may be called.
* @returns {Object} The call sender object with methods that may be called.
*/
var createCallSender = function createCallSender(info, methodNames, destructionPromise) {
var connectCallSender = function connectCallSender(callSender, info, methodNames, destructionPromise) {
var localName = info.localName,

@@ -161,3 +162,3 @@ local = info.local,

log(localName + ': Creating call sender');
log(localName + ': Connecting call sender');

@@ -201,6 +202,6 @@ var createMethodProxy = function createMethodProxy(methodName) {

return methodNames.reduce(function (api, methodName) {
methodNames.reduce(function (api, methodName) {
api[methodName] = createMethodProxy(methodName);
return api;
}, {});
}, callSender);
};

@@ -242,4 +243,5 @@

if (destroyed) {
// We have to throw the error after a timeout otherwise we're just continuing
// the promise chain with a failed promise.
// Some promise libraries, like RSVP, don't report uncaught errors without special
// handlers being added by the consumer. By throwing them asynchronously, they're
// guaranteed to hit the console. We may choose to change this behavior later.
setTimeout(function () {

@@ -272,2 +274,5 @@ throw new Error('Unable to send ' + methodName + '() reply due to destroyed connection');

// Some promise libraries, like RSVP, don't report uncaught errors without special
// handlers being added by the consumer. By throwing them asynchronously, they're
// guaranteed to hit the console. We may choose to change this behavior later.
setTimeout(function () {

@@ -288,2 +293,6 @@ throw err;

reject(err.toString());
// Some promise libraries, like RSVP, don't report uncaught errors without special
// handlers being added by the consumer. By throwing them asynchronously, they're
// guaranteed to hit the console. We may choose to change this behavior later.
setTimeout(function () {

@@ -321,3 +330,3 @@ throw err;

* @param {HTMLElement} [options.appendTo] The container to which the iframe should be appended.
* @param {Object} [options.methods] Methods that may be called by the iframe.
* @param {Object} [options.methods={}] Methods that may be called by the iframe.
* @return {Child}

@@ -350,8 +359,11 @@ */

var promise = new Penpal.Promise(function (resolve, reject) {
// We resolve the promise with the call sender. If the child reconnects (for example, after
// refreshing or navigating to another page that uses Penpal, we'll update the call sender
// with methods that match the latest provided by the child.
var callSender = {};
var methodNames = void 0;
var handleMessage = function handleMessage(event) {
if (event.source === child && event.origin === childOrigin && event.data.penpal === HANDSHAKE) {
log('Parent: Received handshake');
parent.removeEventListener(MESSAGE, handleMessage);
log('Parent: Sending handshake reply');

@@ -372,3 +384,15 @@

connectCallReceiver(info, methods, destructionPromise);
resolve(createCallSender(info, event.data.methodNames, destructionPromise));
// If we're reconnecting, remove methods from the previous connection.
if (methodNames) {
methodNames.forEach(function (methodName) {
delete callSender[methodName];
});
}
methodNames = event.data.methodNames;
connectCallSender(callSender, info, methodNames, destructionPromise);
resolve(callSender);
}

@@ -403,9 +427,9 @@ };

* @param {Object} options
* @param {string|Array} [options.parentOrigin] Valid parent origin used to restrict communication
* An array of parent origin strings is also supported.
* @param {Object} [options.methods] Methods that may be called by the parent window.
* @param {string} [options.parentOrigin=*] Valid parent origin used to restrict communication.
* @param {Object} [options.methods={}] Methods that may be called by the parent window.
* @return {Parent}
*/
Penpal.connectToParent = function (_ref2) {
var parentOrigin = _ref2.parentOrigin,
var _ref2$parentOrigin = _ref2.parentOrigin,
parentOrigin = _ref2$parentOrigin === undefined ? '*' : _ref2$parentOrigin,
_ref2$methods = _ref2.methods,

@@ -421,15 +445,6 @@ methods = _ref2$methods === undefined ? {} : _ref2$methods;

var parent = child.parent;
var targetParentOrigin = getOriginFromUrl(document.referrer);
if (parentOrigin !== undefined && !Array.isArray(parentOrigin)) {
parentOrigin = [parentOrigin];
}
if (parentOrigin !== undefined && parentOrigin.indexOf(targetParentOrigin) === -1) {
throw new Error('Child: parent\'s origin not in list of valid parent origins');
}
var promise = new Penpal.Promise(function (resolve, reject) {
var handleMessageEvent = function handleMessageEvent(event) {
if ((parentOrigin === undefined || parentOrigin.indexOf(event.origin) !== -1) && event.source === parent && event.data.penpal === HANDSHAKE_REPLY) {
if ((parentOrigin === '*' || parentOrigin === event.origin) && event.source === parent && event.data.penpal === HANDSHAKE_REPLY) {
log('Child: Received handshake reply');

@@ -446,4 +461,7 @@

var callSender = {};
connectCallReceiver(info, methods, destructionPromise);
resolve(createCallSender(info, event.data.methodNames, destructionPromise));
connectCallSender(callSender, info, event.data.methodNames, destructionPromise);
resolve(callSender);
}

@@ -464,3 +482,3 @@ };

methodNames: Object.keys(methods)
}, targetParentOrigin);
}, parentOrigin);
});

@@ -467,0 +485,0 @@

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

!function(e,n){var t={};!function(e){"use strict";function n(e){if(Array.isArray(e)){for(var n=0,t=Array(e.length);n<e.length;n++)t[n]=e[n];return t}return Array.from(e)}Object.defineProperty(e,"__esModule",{value:!0});var t="message",r={"http:":"80","https:":"443"},o=/^(https?:)?\/\/([^\/:]+)(:(\d+))?/,i={Promise:function(){try{return window?window.Promise:null}catch(e){return null}}(),debug:!1},a=function(){var e=0;return function(){return++e}}(),d=function(){for(var e=arguments.length,n=Array(e),t=0;t<e;t++)n[t]=arguments[t];if(i.debug){var r;(r=console).log.apply(r,["[Penpal]"].concat(n))}},c=function(e){var n=document.location,t=o.exec(e),i=void 0,a=void 0,d=void 0;return t?(i=t[1]?t[1]:n.protocol,a=t[2],d=t[4]):(i=n.protocol,a=n.hostname,d=n.port),i+"//"+a+(d&&d!==r[i]?":"+d:"")},l=function(e){var n=[];return e(function(){n.forEach(function(e){e()})}),{then:function(e){n.push(e)}}},u=function(e,n,r){var o=e.localName,c=e.local,l=e.remote,u=e.remoteOrigin,s=!1;d(o+": Creating call sender");var f=function(e){return function(){for(var n=arguments.length,r=Array(n),f=0;f<n;f++)r[f]=arguments[f];return d(o+": Sending "+e+"() call"),new i.Promise(function(n,i){if(s)return void i("Unable to send "+e+"() call due to destroyed connection");var f=a(),p=function r(a){a.source===l&&a.origin===u&&"reply"===a.data.penpal&&a.data.id===f&&(d(o+": Received "+e+"() reply"),c.removeEventListener(t,r),("fulfilled"===a.data.resolution?n:i)(a.data.returnValue))};c.addEventListener(t,p),l.postMessage({penpal:"call",id:f,methodName:e,args:r},u)})}};return r.then(function(){s=!0}),n.reduce(function(e,n){return e[n]=f(n),e},{})},s=function(e,r,o){var a=e.localName,c=e.local,l=e.remote,u=e.remoteOrigin,s=!1;d(a+": Connecting call receiver");var f=function(e){if(e.source===l&&e.origin===u&&"call"===e.data.penpal){var t=e.data,o=t.methodName,c=t.args,f=t.id;if(d(a+": Received "+o+"() call"),o in r){var p=function(e){return function(n){if(s)return void setTimeout(function(){throw new Error("Unable to send "+o+"() reply due to destroyed connection")});d(a+": Sending "+o+"() reply");try{l.postMessage({penpal:"reply",id:f,resolution:e,returnValue:n},u)}catch(e){"DataCloneError"===e.name&&l.postMessage({penpal:"reply",id:f,resolution:"rejected",returnValue:e.toString()},u),setTimeout(function(){throw e})}}};new i.Promise(function(e,t){try{e(r[o].apply(r,n(c)))}catch(e){t(e.toString()),setTimeout(function(){throw e})}}).then(p("fulfilled"),p("rejected"))}}};c.addEventListener(t,f),o.then(function(){s=!0,c.removeEventListener(t,f)})};i.connectToChild=function(e){var n=e.url,r=e.appendTo,o=e.methods,a=void 0===o?{}:o,f=void 0,p=new l(function(e){return f=e}),v=window,m=document.createElement("iframe");(r||document.body).appendChild(m),p.then(function(){m.parentNode&&m.parentNode.removeChild(m)});var h=m.contentWindow||m.contentDocument.parentWindow,g=c(n);return{promise:new i.Promise(function(e,r){var o=function n(r){if(r.source===h&&r.origin===g&&"handshake"===r.data.penpal){d("Parent: Received handshake"),v.removeEventListener(t,n),d("Parent: Sending handshake reply"),r.source.postMessage({penpal:"handshake-reply",methodNames:Object.keys(a)},r.origin);var o={localName:"parent",local:v,remote:h,remoteOrigin:r.origin};s(o,a,p),e(u(o,r.data.methodNames,p))}};v.addEventListener(t,o),p.then(function(){v.removeEventListener(t,o),r("Parent: Connection destroyed")}),d("Parent: Loading iframe"),m.src=n}),iframe:m,destroy:f}},i.connectToParent=function(e){var n=e.parentOrigin,r=e.methods,o=void 0===r?{}:r,a=void 0,f=new l(function(e){return a=e}),p=window,v=p.parent,m=c(document.referrer);if(void 0===n||Array.isArray(n)||(n=[n]),void 0!==n&&-1===n.indexOf(m))throw new Error("Child: parent's origin not in list of valid parent origins");return{promise:new i.Promise(function(e,r){var i=function r(i){if((void 0===n||-1!==n.indexOf(i.origin))&&i.source===v&&"handshake-reply"===i.data.penpal){d("Child: Received handshake reply"),p.removeEventListener(t,r);var a={localName:"child",local:p,remote:v,remoteOrigin:i.origin};s(a,o,f),e(u(a,i.data.methodNames,f))}};p.addEventListener(t,i),f.then(function(){p.removeEventListener(t,i),r("Child: Connection destroyed")}),d("Child: Sending handshake"),v.postMessage({penpal:"handshake",methodNames:Object.keys(o)},m)}),destroy:a}},e.default=i}(t),"function"==typeof define&&define.amd?define("Penpal",t.default):e.Penpal=t.default}(this);
!function(e,n){var t={};!function(e){"use strict";function n(e){if(Array.isArray(e)){for(var n=0,t=Array(e.length);n<e.length;n++)t[n]=e[n];return t}return Array.from(e)}Object.defineProperty(e,"__esModule",{value:!0});var t={"http:":"80","https:":"443"},r=/^(https?:)?\/\/([^\/:]+)(:(\d+))?/,o={Promise:function(){try{return window?window.Promise:null}catch(e){return null}}(),debug:!1},a=function(){var e=0;return function(){return++e}}(),i=function(){for(var e=arguments.length,n=Array(e),t=0;t<e;t++)n[t]=arguments[t];if(o.debug){var r;(r=console).log.apply(r,["[Penpal]"].concat(n))}},d=function(e){var n=document.location,o=r.exec(e),a=void 0,i=void 0,d=void 0;return o?(a=o[1]?o[1]:n.protocol,i=o[2],d=o[4]):(a=n.protocol,i=n.hostname,d=n.port),a+"//"+i+(d&&d!==t[a]?":"+d:"")},c=function(e){var n=[];return e(function(){n.forEach(function(e){e()})}),{then:function(e){n.push(e)}}},s=function(e,n,t,r){var d=n.localName,c=n.local,s=n.remote,l=n.remoteOrigin,u=!1;i(d+": Connecting call sender");var f=function(e){return function(){for(var n=arguments.length,t=Array(n),r=0;r<n;r++)t[r]=arguments[r];return i(d+": Sending "+e+"() call"),new o.Promise(function(n,r){if(u)return void r("Unable to send "+e+"() call due to destroyed connection");var o=a(),f=function t(a){a.source===s&&a.origin===l&&"reply"===a.data.penpal&&a.data.id===o&&(i(d+": Received "+e+"() reply"),c.removeEventListener("message",t),("fulfilled"===a.data.resolution?n:r)(a.data.returnValue))};c.addEventListener("message",f),s.postMessage({penpal:"call",id:o,methodName:e,args:t},l)})}};r.then(function(){u=!0}),t.reduce(function(e,n){return e[n]=f(n),e},e)},l=function(e,t,r){var a=e.localName,d=e.local,c=e.remote,s=e.remoteOrigin,l=!1;i(a+": Connecting call receiver");var u=function(e){if(e.source===c&&e.origin===s&&"call"===e.data.penpal){var r=e.data,d=r.methodName,u=r.args,f=r.id;if(i(a+": Received "+d+"() call"),d in t){var m=function(e){return function(n){if(l)return void setTimeout(function(){throw new Error("Unable to send "+d+"() reply due to destroyed connection")});i(a+": Sending "+d+"() reply");try{c.postMessage({penpal:"reply",id:f,resolution:e,returnValue:n},s)}catch(e){"DataCloneError"===e.name&&c.postMessage({penpal:"reply",id:f,resolution:"rejected",returnValue:e.toString()},s),setTimeout(function(){throw e})}}};new o.Promise(function(e,r){try{e(t[d].apply(t,n(u)))}catch(e){r(e.toString()),setTimeout(function(){throw e})}}).then(m("fulfilled"),m("rejected"))}}};d.addEventListener("message",u),r.then(function(){l=!0,d.removeEventListener("message",u)})};o.connectToChild=function(e){var n=e.url,t=e.appendTo,r=e.methods,a=void 0===r?{}:r,u=void 0,f=new c(function(e){return u=e}),m=window,p=document.createElement("iframe");(t||document.body).appendChild(p),f.then(function(){p.parentNode&&p.parentNode.removeChild(p)});var h=p.contentWindow||p.contentDocument.parentWindow,v=d(n);return{promise:new o.Promise(function(e,t){var r={},o=void 0,d=function(n){if(n.source===h&&n.origin===v&&"handshake"===n.data.penpal){i("Parent: Received handshake"),i("Parent: Sending handshake reply"),n.source.postMessage({penpal:"handshake-reply",methodNames:Object.keys(a)},n.origin);var t={localName:"parent",local:m,remote:h,remoteOrigin:n.origin};l(t,a,f),o&&o.forEach(function(e){delete r[e]}),o=n.data.methodNames,s(r,t,o,f),e(r)}};m.addEventListener("message",d),f.then(function(){m.removeEventListener("message",d),t("Parent: Connection destroyed")}),i("Parent: Loading iframe"),p.src=n}),iframe:p,destroy:u}},o.connectToParent=function(e){var n=e.parentOrigin,t=void 0===n?"*":n,r=e.methods,a=void 0===r?{}:r,d=void 0,u=new c(function(e){return d=e}),f=window,m=f.parent;return{promise:new o.Promise(function(e,n){var r=function n(r){if(("*"===t||t===r.origin)&&r.source===m&&"handshake-reply"===r.data.penpal){i("Child: Received handshake reply"),f.removeEventListener("message",n);var o={localName:"child",local:f,remote:m,remoteOrigin:r.origin},d={};l(o,a,u),s(d,o,r.data.methodNames,u),e(d)}};f.addEventListener("message",r),u.then(function(){f.removeEventListener("message",r),n("Child: Connection destroyed")}),i("Child: Sending handshake"),m.postMessage({penpal:"handshake",methodNames:Object.keys(a)},t)}),destroy:d}},e.default=o}(t),"function"==typeof define&&define.amd?define("Penpal",t.default):e.Penpal=t.default}(this);

@@ -128,5 +128,6 @@ 'use strict';

/**
* Creates an object with methods that match those defined by the remote. When these methods are
* Augments an object with methods that match those defined by the remote. When these methods are
* called, a "call" message will be sent to the remote, the remote's corresponding method will be
* executed, and the method's return value will be returned via a message.
* @param {Object} callSender Sender object that should be augmented with methods.
* @param {Object} info Information about the local and remote windows.

@@ -136,5 +137,5 @@ * @param {Array} methodNames Names of methods available to be called on the remote.

* connection.
* @returns {Object} An object with methods that may be called.
* @returns {Object} The call sender object with methods that may be called.
*/
var createCallSender = function createCallSender(info, methodNames, destructionPromise) {
var connectCallSender = function connectCallSender(callSender, info, methodNames, destructionPromise) {
var localName = info.localName,

@@ -147,3 +148,3 @@ local = info.local,

log(localName + ': Creating call sender');
log(localName + ': Connecting call sender');

@@ -187,6 +188,6 @@ var createMethodProxy = function createMethodProxy(methodName) {

return methodNames.reduce(function (api, methodName) {
methodNames.reduce(function (api, methodName) {
api[methodName] = createMethodProxy(methodName);
return api;
}, {});
}, callSender);
};

@@ -228,4 +229,5 @@

if (destroyed) {
// We have to throw the error after a timeout otherwise we're just continuing
// the promise chain with a failed promise.
// Some promise libraries, like RSVP, don't report uncaught errors without special
// handlers being added by the consumer. By throwing them asynchronously, they're
// guaranteed to hit the console. We may choose to change this behavior later.
setTimeout(function () {

@@ -258,2 +260,5 @@ throw new Error('Unable to send ' + methodName + '() reply due to destroyed connection');

// Some promise libraries, like RSVP, don't report uncaught errors without special
// handlers being added by the consumer. By throwing them asynchronously, they're
// guaranteed to hit the console. We may choose to change this behavior later.
setTimeout(function () {

@@ -274,2 +279,6 @@ throw err;

reject(err.toString());
// Some promise libraries, like RSVP, don't report uncaught errors without special
// handlers being added by the consumer. By throwing them asynchronously, they're
// guaranteed to hit the console. We may choose to change this behavior later.
setTimeout(function () {

@@ -307,3 +316,3 @@ throw err;

* @param {HTMLElement} [options.appendTo] The container to which the iframe should be appended.
* @param {Object} [options.methods] Methods that may be called by the iframe.
* @param {Object} [options.methods={}] Methods that may be called by the iframe.
* @return {Child}

@@ -336,8 +345,11 @@ */

var promise = new Penpal.Promise(function (resolve, reject) {
// We resolve the promise with the call sender. If the child reconnects (for example, after
// refreshing or navigating to another page that uses Penpal, we'll update the call sender
// with methods that match the latest provided by the child.
var callSender = {};
var methodNames = void 0;
var handleMessage = function handleMessage(event) {
if (event.source === child && event.origin === childOrigin && event.data.penpal === HANDSHAKE) {
log('Parent: Received handshake');
parent.removeEventListener(MESSAGE, handleMessage);
log('Parent: Sending handshake reply');

@@ -358,3 +370,15 @@

connectCallReceiver(info, methods, destructionPromise);
resolve(createCallSender(info, event.data.methodNames, destructionPromise));
// If we're reconnecting, remove methods from the previous connection.
if (methodNames) {
methodNames.forEach(function (methodName) {
delete callSender[methodName];
});
}
methodNames = event.data.methodNames;
connectCallSender(callSender, info, methodNames, destructionPromise);
resolve(callSender);
}

@@ -389,9 +413,9 @@ };

* @param {Object} options
* @param {string|Array} [options.parentOrigin] Valid parent origin used to restrict communication
* An array of parent origin strings is also supported.
* @param {Object} [options.methods] Methods that may be called by the parent window.
* @param {string} [options.parentOrigin=*] Valid parent origin used to restrict communication.
* @param {Object} [options.methods={}] Methods that may be called by the parent window.
* @return {Parent}
*/
Penpal.connectToParent = function (_ref2) {
var parentOrigin = _ref2.parentOrigin,
var _ref2$parentOrigin = _ref2.parentOrigin,
parentOrigin = _ref2$parentOrigin === undefined ? '*' : _ref2$parentOrigin,
_ref2$methods = _ref2.methods,

@@ -407,15 +431,6 @@ methods = _ref2$methods === undefined ? {} : _ref2$methods;

var parent = child.parent;
var targetParentOrigin = getOriginFromUrl(document.referrer);
if (parentOrigin !== undefined && !Array.isArray(parentOrigin)) {
parentOrigin = [parentOrigin];
}
if (parentOrigin !== undefined && parentOrigin.indexOf(targetParentOrigin) === -1) {
throw new Error('Child: parent\'s origin not in list of valid parent origins');
}
var promise = new Penpal.Promise(function (resolve, reject) {
var handleMessageEvent = function handleMessageEvent(event) {
if ((parentOrigin === undefined || parentOrigin.indexOf(event.origin) !== -1) && event.source === parent && event.data.penpal === HANDSHAKE_REPLY) {
if ((parentOrigin === '*' || parentOrigin === event.origin) && event.source === parent && event.data.penpal === HANDSHAKE_REPLY) {
log('Child: Received handshake reply');

@@ -432,4 +447,7 @@

var callSender = {};
connectCallReceiver(info, methods, destructionPromise);
resolve(createCallSender(info, event.data.methodNames, destructionPromise));
connectCallSender(callSender, info, event.data.methodNames, destructionPromise);
resolve(callSender);
}

@@ -450,3 +468,3 @@ };

methodNames: Object.keys(methods)
}, targetParentOrigin);
}, parentOrigin);
});

@@ -453,0 +471,0 @@

{
"name": "penpal",
"version": "2.7.2",
"version": "3.0.0-alpha.1",
"description": "A promise-based library for communicating with iframes via postMessage.",

@@ -27,2 +27,3 @@ "author": "Aaron Hardy <aaron@aaronhardy.com>",

"test:watch": "npm run build && parallelshell 'npm run build:watch -- --skip-initial-run' './scripts/test.js --watch'",
"test:sauce": "npm run build && ./scripts/test.js --sauce",
"prepublish": "npm run build"

@@ -50,2 +51,3 @@ },

"karma-jasmine": "^1.0.2",
"karma-sauce-launcher": "^1.2.0",
"mkdirp": "^0.5.1",

@@ -52,0 +54,0 @@ "parallelshell": "^2.0.0",

@@ -1,3 +0,5 @@

[![npm version](https://badge.fury.io/js/penpal.svg)](https://badge.fury.io/js/penpal)
[![npm version](https://badge.fury.io/js/penpal.svg)](https://badge.fury.io/js/penpal) [![Build Status](https://travis-ci.org/Aaronius/penpal.svg?branch=master)](https://travis-ci.org/Aaronius/penpal)
[![Build Status](https://saucelabs.com/browser-matrix/Aaronius9erPenpalMaster.svg)](https://saucelabs.com/u/Aaronius9erPenpalMaster)
# Penpal

@@ -108,3 +110,3 @@

`options.parentOrigin` (optional) The origin of the parent window which your iframe will be communicating with. If this is not provided, communication will not be restricted to any particular parent origin resulting in any webpage being able to load your webpage into an iframe and communicate with it. This is typically a string, however an array of strings is also supported if you expect to communicate with multiple parent origins.
`options.parentOrigin` (optional) The origin of the parent window which your iframe will be communicating with. If this is not provided, communication will not be restricted to any particular parent origin resulting in any webpage being able to load your webpage into an iframe and communicate with it.

@@ -129,5 +131,11 @@ `options.methods` (optional) An object containing methods which should be exposed for the parent window to call. The keys of the object are the method names and the values are the functions. If a function requires asynchronous processing to determine its return value, make the function immediately return a promise and resolve the promise once the value has been determined.

## Reconnection
If the child iframe attempts to reconnect with the parent, the parent will accept the new connection. This could happen, for example, if a user refreshes the child iframe or navigates within the iframe to a different page that also uses Penpal. In this case, the `child` object the parent received when the initial connection was established will be updated with the new methods provided by the child iframe.
NOTE: Currently there is no API to notify consumers of a reconnection. If this is important for you, please file an issue and explain why it would be beneficial to you.
## Supported Browsers
Penpal is designed to run successfully on Internet Explorer 10 and higher as well as recent versions of Chrome, Firefox, Safari, etc. It wouldn't take much to support Internet Explorer 9, but let's move the web forward.
Penpal is designed to run successfully on the most recent versions of Internet Explorer, Edge, Chrome, Firefox, and Safari.

@@ -139,3 +147,3 @@ ## Inspiration

* [Postmate](https://github.com/dollarshaveclub/postmate)
* [JSChannel](https://github.com/mozilla/jschannel)
* [JSChannel](https://ginthub.com/mozilla/jschannel)

@@ -142,0 +150,0 @@ ## License

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