diff --git a/.eslintrc.js b/.eslintrc.js
index 11560a5a..fab50622 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,9 +1,10 @@
/* @flow */
module.exports = {
- 'extends': './node_modules/@krakenjs/grumbler-scripts/config/.eslintrc-browser.js',
+ extends:
+ "./node_modules/@krakenjs/grumbler-scripts/config/.eslintrc-browser.js",
- 'globals': {
- __POST_ROBOT__: true
- }
-};
\ No newline at end of file
+ globals: {
+ __POST_ROBOT__: true,
+ },
+};
diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml
index e497e2e7..80619fc6 100644
--- a/.github/workflows/main.yaml
+++ b/.github/workflows/main.yaml
@@ -16,8 +16,8 @@ jobs:
- name: ⎔ Setup node
uses: actions/setup-node@v2
with:
- node-version: '14'
- registry-url: 'https://registry.npmjs.org'
+ node-version: "14"
+ registry-url: "https://registry.npmjs.org"
- name: 📥 Download deps
uses: bahmutov/npm-install@v1
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 918c6df6..1be39548 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -1,32 +1,32 @@
name: "publish to npm"
on: workflow_dispatch
jobs:
- main:
- runs-on: ubuntu-latest
- steps:
- - name: ⬇️ Checkout repo
- uses: actions/checkout@v2
- with:
- token: ${{ secrets.ACCESS_TOKEN }}
- fetch-depth: 0
+ main:
+ runs-on: ubuntu-latest
+ steps:
+ - name: ⬇️ Checkout repo
+ uses: actions/checkout@v2
+ with:
+ token: ${{ secrets.ACCESS_TOKEN }}
+ fetch-depth: 0
- - name: ⎔ Setup node
- # sets up the .npmrc file to publish to npm
- uses: actions/setup-node@v2
- with:
- node-version: "14"
- registry-url: "https://registry.npmjs.org"
+ - name: ⎔ Setup node
+ # sets up the .npmrc file to publish to npm
+ uses: actions/setup-node@v2
+ with:
+ node-version: "14"
+ registry-url: "https://registry.npmjs.org"
- - name: 📥 Download deps
- uses: bahmutov/npm-install@v1
- with:
- useLockFile: false
+ - name: 📥 Download deps
+ uses: bahmutov/npm-install@v1
+ with:
+ useLockFile: false
- - name: Configure git user
- run: |
- git config --global user.email ${{ github.actor }}@users.noreply.github.com
- git config --global user.name ${{ github.actor }}
- - name: ▶️ Run release
- run: npm run release
- env:
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+ - name: Configure git user
+ run: |
+ git config --global user.email ${{ github.actor }}@users.noreply.github.com
+ git config --global user.name ${{ github.actor }}
+ - name: ▶️ Run release
+ run: npm run release
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
diff --git a/.husky/.gitignore b/.husky/.gitignore
new file mode 100644
index 00000000..31354ec1
--- /dev/null
+++ b/.husky/.gitignore
@@ -0,0 +1 @@
+_
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100755
index 00000000..36af2198
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1,4 @@
+#!/bin/sh
+. "$(dirname "$0")/_/husky.sh"
+
+npx lint-staged
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 00000000..b7edac54
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,5 @@
+build
+dist
+coverage
+flow-typed
+CHANGELOG.md
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 00000000..0967ef42
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1 @@
+{}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ad580c9f..cb572415 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -6,7 +6,9 @@ Feel free to raise a pull request to us. Our team would review your proposed mod
your changes into our code. Ideas and other comments are also welcome.
## Getting Started
+
1. Create your own [fork](https://help.github.com/articles/fork-a-repo) of this [repository](../../fork).
+
```bash
# Clone it
$ git clone git@github.com:me/post-robot.git
@@ -30,12 +32,14 @@ $ npm run-script cover
```
## Making Changes
+
1. Make sure that your changes adhere to the current coding conventions used throughout the project, indentation, accurate comments, etc.
2. Lint your code regularly and ensure it passes prior to submitting a PR:
-`$ npm run lint`.
+ `$ npm run lint`.
3. Ensure existing tests pass (`$ npm test`) and include test cases which fail without your change and succeed with it.
## Submitting Changes
+
1. Ensure that no errors are generated by ESLint.
2. Commit your changes in logical chunks, i.e. keep your changes small per single commit.
3. Locally merge (or rebase) the upstream branch into your topic branch: `$ git pull upstream && git merge`.
diff --git a/README.md b/README.md
index b49da9b2..cd22f962 100644
--- a/README.md
+++ b/README.md
@@ -43,75 +43,73 @@ post-robot will serialize and deserialize the following data types in messages:
```javascript
// Set up a listener
-postRobot.on('getUser', function(event) {
+postRobot.on("getUser", function (event) {
+ // Have it return some data to the calling window
- // Have it return some data to the calling window
+ return {
+ id: 1234,
+ name: "Zippy the Pinhead",
- return {
- id: 1234,
- name: 'Zippy the Pinhead',
-
- // Yep, we're even returning a function to the other window!
+ // Yep, we're even returning a function to the other window!
- logout: function() {
- return $currentUser.logout();
- }
- };
+ logout: function () {
+ return $currentUser.logout();
+ },
+ };
});
```
```javascript
// Call the listener, on a different window, on a different domain
-postRobot.send(someWindow, 'getUser', { id: 1337 }).then(function(event) {
+postRobot
+ .send(someWindow, "getUser", { id: 1337 })
+ .then(function (event) {
var user = event.data;
- console.log(event.source, event.origin, 'Got user:', user);
+ console.log(event.source, event.origin, "Got user:", user);
// Call the user.logout function from the other window!
user.logout();
-
-}).catch(function(err) {
-
+ })
+ .catch(function (err) {
// Handle any errors that stopped our call from going through
console.error(err);
-});
+ });
```
## Listener with promise response
```javascript
-postRobot.on('getUser', function(event) {
-
- return getUser(event.data.id).then(function(user) {
- return {
- name: user.name
- };
- });
+postRobot.on("getUser", function (event) {
+ return getUser(event.data.id).then(function (user) {
+ return {
+ name: user.name,
+ };
+ });
});
```
## One-off listener
```javascript
-postRobot.once('getUser', function(event) {
-
- return {
- name: 'Noggin the Nog'
- };
+postRobot.once("getUser", function (event) {
+ return {
+ name: "Noggin the Nog",
+ };
});
```
## Cancelling a listener
```javascript
-var listener = postRobot.on('getUser', function(event) {
- return {
- id: event.data.id,
- name: 'Zippy the Pinhead'
- };
+var listener = postRobot.on("getUser", function (event) {
+ return {
+ id: event.data.id,
+ name: "Zippy the Pinhead",
+ };
});
listener.cancel();
@@ -120,65 +118,67 @@ listener.cancel();
## Listen for messages from a specific window
```javascript
-postRobot.on('getUser', { window: window.parent }, function(event) {
-
- return {
- name: 'Guybrush Threepwood'
- };
+postRobot.on("getUser", { window: window.parent }, function (event) {
+ return {
+ name: "Guybrush Threepwood",
+ };
});
```
## Listen for messages from a specific domain
```javascript
-postRobot.on('getUser', { domain: 'http://zombo.com' }, function(event) {
-
- return {
- name: 'Manny Calavera'
- };
+postRobot.on("getUser", { domain: "http://zombo.com" }, function (event) {
+ return {
+ name: "Manny Calavera",
+ };
});
```
## Set a timeout for a response
```javascript
-postRobot.send(someWindow, 'getUser', { id: 1337 }, { timeout: 5000 }).then(function(event) {
- console.log(event.source, event.origin, 'Got user:', event.data.name);
-
-}).catch(function(err) {
+postRobot
+ .send(someWindow, "getUser", { id: 1337 }, { timeout: 5000 })
+ .then(function (event) {
+ console.log(event.source, event.origin, "Got user:", event.data.name);
+ })
+ .catch(function (err) {
console.error(err);
-});
+ });
```
## Send a message to a specific domain
```javascript
-postRobot.send(someWindow, 'getUser', { id: 1337 }, { domain: 'http://zombo.com' }).then(function(event) {
- console.log(event.source, event.origin, 'Got user:', event.data.name);
-});
+postRobot
+ .send(someWindow, "getUser", { id: 1337 }, { domain: "http://zombo.com" })
+ .then(function (event) {
+ console.log(event.source, event.origin, "Got user:", event.data.name);
+ });
```
## Async / Await
```javascript
-postRobot.on('getUser', async ({ source, origin, data }) => {
-
- let user = await getUser(data.id);
+postRobot.on("getUser", async ({ source, origin, data }) => {
+ let user = await getUser(data.id);
- return {
- id: data.id,
- name: user.name
- };
+ return {
+ id: data.id,
+ name: user.name,
+ };
});
```
```javascript
try {
- let { source, origin, data } = await postRobot.send(someWindow, `getUser`, { id: 1337 });
- console.log(source, origin, 'Got user:', data.name);
-
+ let { source, origin, data } = await postRobot.send(someWindow, `getUser`, {
+ id: 1337,
+ });
+ console.log(source, origin, "Got user:", data.name);
} catch (err) {
- console.error(err);
+ console.error(err);
}
```
@@ -188,21 +188,27 @@ For security reasons, it is recommended that you always explicitly specify the w
to and send messages to. This creates a secure message channel that only works between two windows on the specified domain:
```javascript
-postRobot.on('getUser', { window: childWindow, domain: 'http://zombo.com' }, function(event) {
+postRobot.on(
+ "getUser",
+ { window: childWindow, domain: "http://zombo.com" },
+ function (event) {
return {
- id: event.data.id,
- name: 'Frodo'
+ id: event.data.id,
+ name: "Frodo",
};
-});
+ }
+);
```
```javascript
-postRobot.send(someWindow, 'getUser', { id: 1337 }, { domain: 'http://zombo.com' }).then(function(event) {
- console.log(event.source, event.origin, 'Got user:', event.data.name);
-
-}).catch(function(err) {
+postRobot
+ .send(someWindow, "getUser", { id: 1337 }, { domain: "http://zombo.com" })
+ .then(function (event) {
+ console.log(event.source, event.origin, "Got user:", event.data.name);
+ })
+ .catch(function (err) {
console.error(err);
-});
+ });
```
## Functions
@@ -212,25 +218,25 @@ Post robot lets you send across functions in your data payload, fairly seamlessl
For example:
```javascript
-postRobot.on('getUser', function(event) {
- return {
- id: event.data.id,
- name: 'Nogbad the Bad',
-
- logout: function() {
- currentUser.logout();
- }
- };
+postRobot.on("getUser", function (event) {
+ return {
+ id: event.data.id,
+ name: "Nogbad the Bad",
+
+ logout: function () {
+ currentUser.logout();
+ },
+ };
});
```
```javascript
-postRobot.send(myWindow, 'getUser', { id: 1337 }).then(function(event) {
- var user = event.data;
+postRobot.send(myWindow, "getUser", { id: 1337 }).then(function (event) {
+ var user = event.data;
- user.logout().then(function() {
- console.log('User was logged out');
- });
+ user.logout().then(function () {
+ console.log("User was logged out");
+ });
});
```
@@ -239,7 +245,6 @@ original window, calls the function that was passed, then messages back with the
Because this uses post-messaging behind the scenes and is therefore always async, `user.logout()` will **always** return a promise, and must be `.then`'d or `await`ed.
-
## Parent to popup messaging
Unfortunately, IE blocks direct post messaging between a parent window and a popup, on different domains.
@@ -265,7 +270,6 @@ In order to use post-robot in IE9+ with popup windows, you will need to set up a
+---------------------+
```
-
a. Use the special `ie` build of post-robot: `dist/post-robot.ie.js`.
b. Create a bridge path on the domain of your popup, for example `http://yy.com/bridge.html`, and include post-robot:
@@ -278,7 +282,7 @@ c. In the parent page on `xx.com` which opens the popup, include the following j
```html
```
diff --git a/SECURITY.md b/SECURITY.md
index 90c26620..b539e641 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -2,14 +2,14 @@
We take security very seriously and ask that you follow the following process.
-
## Contact us
-If you think you may have found a security bug we ask that you privately send the details to DL-PP-Kraken-Js@paypal.com. Please make sure to use a descriptive title in the email.
+If you think you may have found a security bug we ask that you privately send the details to DL-PP-Kraken-Js@paypal.com. Please make sure to use a descriptive title in the email.
## Expectations
-We will generally get back to you within **24 hours**, but a more detailed response may take up to **48 hours**. If you feel we're not responding back in time, please send us a message *without detail* on Twitter [@kraken_js](https://twitter.com/kraken_js).
+We will generally get back to you within **24 hours**, but a more detailed response may take up to **48 hours**. If you feel we're not responding back in time, please send us a message _without detail_ on Twitter [@kraken_js](https://twitter.com/kraken_js).
## History
+
No reported issues
diff --git a/babel.config.js b/babel.config.js
index 21cfb34d..ad6fa58b 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -2,5 +2,5 @@
// eslint-disable-next-line import/no-commonjs
module.exports = {
- extends: '@krakenjs/grumbler-scripts/config/.babelrc-node'
+ extends: "@krakenjs/grumbler-scripts/config/.babelrc-node",
};
diff --git a/commitlint.config.js b/commitlint.config.js
index e0e1077c..ddde86f2 100644
--- a/commitlint.config.js
+++ b/commitlint.config.js
@@ -2,5 +2,5 @@
/* eslint import/no-commonjs: off */
module.exports = {
- extends: [ '@commitlint/config-conventional' ]
+ extends: ["@commitlint/config-conventional"],
};
diff --git a/demo/bridge.htm b/demo/bridge.htm
index 1aeecb0b..5bbed12f 100644
--- a/demo/bridge.htm
+++ b/demo/bridge.htm
@@ -1,7 +1,7 @@
diff --git a/demo/child.htm b/demo/child.htm
index 154ba81e..0be86231 100644
--- a/demo/child.htm
+++ b/demo/child.htm
@@ -1,24 +1,22 @@
-
diff --git a/demo/parent.htm b/demo/parent.htm
index a72cb856..04bf1d74 100644
--- a/demo/parent.htm
+++ b/demo/parent.htm
@@ -7,18 +7,22 @@
diff --git a/globals.js b/globals.js
index f155e7fa..dd19a5c4 100644
--- a/globals.js
+++ b/globals.js
@@ -1,18 +1,18 @@
/* @flow */
/* eslint import/no-commonjs: 0 */
-const pkg = require('./package.json');
+const pkg = require("./package.json");
const formatVersion = (version) => {
- return version.replace(/[^\d]+/g, '_');
+ return version.replace(/[^\d]+/g, "_");
};
module.exports = {
- __POST_ROBOT__: {
- __GLOBAL_KEY__: `__post_robot_${ formatVersion(pkg.version) }__`,
- __AUTO_SETUP__: true,
- __IE_POPUP_SUPPORT__: true,
- __GLOBAL_MESSAGE_SUPPORT__: true,
- __SCRIPT_NAMESPACE__: false
- }
+ __POST_ROBOT__: {
+ __GLOBAL_KEY__: `__post_robot_${formatVersion(pkg.version)}__`,
+ __AUTO_SETUP__: true,
+ __IE_POPUP_SUPPORT__: true,
+ __GLOBAL_MESSAGE_SUPPORT__: true,
+ __SCRIPT_NAMESPACE__: false,
+ },
};
diff --git a/index.js b/index.js
index 3028580a..83a56e84 100644
--- a/index.js
+++ b/index.js
@@ -1,7 +1,7 @@
/* @flow */
// $FlowFixMe
-module.exports = require('./dist/post-robot'); // eslint-disable-line import/no-commonjs
+module.exports = require("./dist/post-robot"); // eslint-disable-line import/no-commonjs
// $FlowFixMe
module.exports.default = module.exports; // eslint-disable-line import/no-commonjs
diff --git a/karma.conf.js b/karma.conf.js
index 9ff6d4e4..dcb52b59 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -1,16 +1,15 @@
/* @flow */
/* eslint import/no-default-export: off */
-import { getKarmaConfig } from '@krakenjs/grumbler-scripts/config/karma.conf';
+import { getKarmaConfig } from "@krakenjs/grumbler-scripts/config/karma.conf";
-import { WEBPACK_CONFIG_TEST } from './webpack.config';
+import { WEBPACK_CONFIG_TEST } from "./webpack.config";
-export default function configKarma(karma : Object) {
+export default function configKarma(karma: Object) {
+ const karmaConfig = getKarmaConfig(karma, {
+ basePath: __dirname,
+ webpack: WEBPACK_CONFIG_TEST,
+ });
- const karmaConfig = getKarmaConfig(karma, {
- basePath: __dirname,
- webpack: WEBPACK_CONFIG_TEST
- });
-
- karma.set(karmaConfig);
+ karma.set(karmaConfig);
}
diff --git a/package.json b/package.json
index 53e71600..fd4ef043 100644
--- a/package.json
+++ b/package.json
@@ -8,10 +8,12 @@
"lint": "eslint src/ test/ *.js",
"flow-typed": "rm -rf flow-typed && flow-typed install",
"flow": "flow",
+ "format": "prettier --write --ignore-unknown .",
+ "format:check": "prettier --check .",
"karma": "cross-env NODE_ENV=test babel-node --plugins=transform-es2015-modules-commonjs ./node_modules/.bin/karma start",
"babel": "babel src/ --out-dir dist/module",
"webpack": "babel-node --config-file ./node_modules/@krakenjs/grumbler-scripts/config/.babelrc-node --plugins=transform-es2015-modules-commonjs ./node_modules/.bin/webpack --display-optimization-bailout --progress",
- "test": "npm run lint && npm run flow-typed && npm run flow && npm run karma",
+ "test": "npm run format:check && npm run lint && npm run flow-typed && npm run flow && npm run karma",
"build": "npm run test && npm run babel && npm run webpack -- $@",
"clean": "rimraf dist coverage",
"reinstall": "rimraf flow-typed && rimraf node_modules && npm install && flow-typed install",
@@ -89,10 +91,12 @@
"devDependencies": {
"@commitlint/cli": "^16.2.1",
"@commitlint/config-conventional": "^16.2.1",
- "@krakenjs/grumbler-scripts": "^6.0.2",
+ "@krakenjs/grumbler-scripts": "^7.0.0",
"flow-bin": "0.155.0",
"husky": "^7.0.4",
+ "lint-staged": "^12.4.0",
"mocha": "^4",
+ "prettier": "^2.6.2",
"standard-version": "^9.3.2"
},
"dependencies": {
@@ -101,5 +105,8 @@
"@krakenjs/cross-domain-utils": "^3.0.0",
"@krakenjs/universal-serialize": "^2.0.0",
"@krakenjs/zalgo-promise": "^2.0.0"
+ },
+ "lint-staged": {
+ "*": "prettier --write --ignore-unknown"
}
}
diff --git a/src/bridge/bridge.js b/src/bridge/bridge.js
index 6d563a6c..c6468fb2 100644
--- a/src/bridge/bridge.js
+++ b/src/bridge/bridge.js
@@ -1,89 +1,108 @@
/* @flow */
-import { type ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-import { getParent, isWindowClosed, type CrossDomainWindowType } from '@krakenjs/cross-domain-utils/src';
-import { noop, uniqueID } from '@krakenjs/belter/src';
+import { type ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+import {
+ getParent,
+ isWindowClosed,
+ type CrossDomainWindowType,
+} from "@krakenjs/cross-domain-utils/src";
+import { noop, uniqueID } from "@krakenjs/belter/src";
-import { MESSAGE_NAME, WILDCARD } from '../conf';
-import { getGlobal, globalStore } from '../global';
-import type { SendType, ResponseMessageEvent } from '../types';
+import { MESSAGE_NAME, WILDCARD } from "../conf";
+import { getGlobal, globalStore } from "../global";
+import type { SendType, ResponseMessageEvent } from "../types";
function cleanTunnelWindows() {
- const tunnelWindows = globalStore('tunnelWindows');
+ const tunnelWindows = globalStore("tunnelWindows");
- for (const key of tunnelWindows.keys()) {
- const tunnelWindow = tunnelWindows[key];
+ for (const key of tunnelWindows.keys()) {
+ const tunnelWindow = tunnelWindows[key];
- try {
- noop(tunnelWindow.source);
- } catch (err) {
- tunnelWindows.del(key);
- continue;
- }
+ try {
+ noop(tunnelWindow.source);
+ } catch (err) {
+ tunnelWindows.del(key);
+ continue;
+ }
- if (isWindowClosed(tunnelWindow.source)) {
- tunnelWindows.del(key);
- }
+ if (isWindowClosed(tunnelWindow.source)) {
+ tunnelWindows.del(key);
}
+ }
}
type TunnelWindowDataType = {|
- name : string,
- source : CrossDomainWindowType,
- canary : () => void,
- sendMessage : (message : string) => void
+ name: string,
+ source: CrossDomainWindowType,
+ canary: () => void,
+ sendMessage: (message: string) => void,
|};
-function addTunnelWindow({ name, source, canary, sendMessage } : TunnelWindowDataType) : string {
- cleanTunnelWindows();
- const id = uniqueID();
- const tunnelWindows = globalStore('tunnelWindows');
- tunnelWindows.set(id, { name, source, canary, sendMessage });
- return id;
+function addTunnelWindow({
+ name,
+ source,
+ canary,
+ sendMessage,
+}: TunnelWindowDataType): string {
+ cleanTunnelWindows();
+ const id = uniqueID();
+ const tunnelWindows = globalStore("tunnelWindows");
+ tunnelWindows.set(id, { name, source, canary, sendMessage });
+ return id;
}
-export function setupOpenTunnelToParent({ send } : {| send : SendType |}) {
- getGlobal(window).openTunnelToParent = function openTunnelToParent({ name, source, canary, sendMessage } : TunnelWindowDataType) : ZalgoPromise {
-
- const tunnelWindows = globalStore('tunnelWindows');
- const parentWindow = getParent(window);
-
- if (!parentWindow) {
- throw new Error(`No parent window found to open tunnel to`);
- }
-
- const id = addTunnelWindow({ name, source, canary, sendMessage });
-
- return send(parentWindow, MESSAGE_NAME.OPEN_TUNNEL, {
-
- name,
-
- sendMessage() {
-
- const tunnelWindow = tunnelWindows.get(id);
-
- try {
- // IE gets antsy if you try to even reference a closed window
- noop(tunnelWindow && tunnelWindow.source);
- } catch (err) {
- tunnelWindows.del(id);
- return;
- }
-
- if (!tunnelWindow || !tunnelWindow.source || isWindowClosed(tunnelWindow.source)) {
- return;
- }
-
- try {
- tunnelWindow.canary();
- } catch (err) {
- return;
- }
-
- // $FlowFixMe[object-this-reference]
- tunnelWindow.sendMessage.apply(this, arguments);
- }
-
- }, { domain: WILDCARD });
- };
+export function setupOpenTunnelToParent({ send }: {| send: SendType |}) {
+ getGlobal(window).openTunnelToParent = function openTunnelToParent({
+ name,
+ source,
+ canary,
+ sendMessage,
+ }: TunnelWindowDataType): ZalgoPromise {
+ const tunnelWindows = globalStore("tunnelWindows");
+ const parentWindow = getParent(window);
+
+ if (!parentWindow) {
+ throw new Error(`No parent window found to open tunnel to`);
+ }
+
+ const id = addTunnelWindow({ name, source, canary, sendMessage });
+
+ return send(
+ parentWindow,
+ MESSAGE_NAME.OPEN_TUNNEL,
+ {
+ name,
+
+ sendMessage() {
+ const tunnelWindow = tunnelWindows.get(id);
+
+ try {
+ // IE gets antsy if you try to even reference a closed window
+ noop(tunnelWindow && tunnelWindow.source);
+ } catch (err) {
+ tunnelWindows.del(id);
+ return;
+ }
+
+ if (
+ !tunnelWindow ||
+ !tunnelWindow.source ||
+ isWindowClosed(tunnelWindow.source)
+ ) {
+ return;
+ }
+
+ try {
+ tunnelWindow.canary();
+ } catch (err) {
+ return;
+ }
+
+ // $FlowFixMe[object-this-reference]
+ tunnelWindow.sendMessage.apply(this, arguments);
+ },
+ },
+ { domain: WILDCARD }
+ );
+ };
}
diff --git a/src/bridge/child.js b/src/bridge/child.js
index c1526e04..cc4e8e8f 100644
--- a/src/bridge/child.js
+++ b/src/bridge/child.js
@@ -1,117 +1,150 @@
/* @flow */
-import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-import { isSameDomain, getOpener, getDomain, getFrameByName, assertSameDomain, type CrossDomainWindowType } from '@krakenjs/cross-domain-utils/src';
-import { noop } from '@krakenjs/belter/src';
-
-import { getGlobal, windowStore } from '../global';
-import type { OnType, SendType, ReceiveMessageType } from '../types';
-
-import { needsBridge, registerRemoteWindow, rejectRemoteSendMessage, registerRemoteSendMessage, getBridgeName } from './common';
-
-function awaitRemoteBridgeForWindow (win : CrossDomainWindowType) : ZalgoPromise {
- return windowStore('remoteBridgeAwaiters').getOrSet(win, () => {
- return ZalgoPromise.try(() => {
- const frame = getFrameByName(win, getBridgeName(getDomain()));
-
- if (!frame) {
- return;
- }
-
- if (isSameDomain(frame) && getGlobal(assertSameDomain(frame))) {
- return frame;
- }
-
- return new ZalgoPromise(resolve => {
-
- let interval;
- let timeout; // eslint-disable-line prefer-const
-
- interval = setInterval(() => { // eslint-disable-line prefer-const
- if (frame && isSameDomain(frame) && getGlobal(assertSameDomain(frame))) {
- clearInterval(interval);
- clearTimeout(timeout);
- return resolve(frame);
- }
- }, 100);
-
- timeout = setTimeout(() => {
- clearInterval(interval);
- return resolve();
- }, 2000);
- });
- });
+import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+import {
+ isSameDomain,
+ getOpener,
+ getDomain,
+ getFrameByName,
+ assertSameDomain,
+ type CrossDomainWindowType,
+} from "@krakenjs/cross-domain-utils/src";
+import { noop } from "@krakenjs/belter/src";
+
+import { getGlobal, windowStore } from "../global";
+import type { OnType, SendType, ReceiveMessageType } from "../types";
+
+import {
+ needsBridge,
+ registerRemoteWindow,
+ rejectRemoteSendMessage,
+ registerRemoteSendMessage,
+ getBridgeName,
+} from "./common";
+
+function awaitRemoteBridgeForWindow(
+ win: CrossDomainWindowType
+): ZalgoPromise {
+ return windowStore("remoteBridgeAwaiters").getOrSet(win, () => {
+ return ZalgoPromise.try(() => {
+ const frame = getFrameByName(win, getBridgeName(getDomain()));
+
+ if (!frame) {
+ return;
+ }
+
+ if (isSameDomain(frame) && getGlobal(assertSameDomain(frame))) {
+ return frame;
+ }
+
+ return new ZalgoPromise((resolve) => {
+ let interval;
+ // eslint-disable-next-line prefer-const
+ let timeout;
+
+ // eslint-disable-next-line prefer-const
+ interval = setInterval(() => {
+ if (
+ frame &&
+ isSameDomain(frame) &&
+ getGlobal(assertSameDomain(frame))
+ ) {
+ clearInterval(interval);
+ clearTimeout(timeout);
+ return resolve(frame);
+ }
+ }, 100);
+
+ timeout = setTimeout(() => {
+ clearInterval(interval);
+ return resolve();
+ }, 2000);
+ });
});
+ });
}
-export function openTunnelToOpener({ on, send, receiveMessage } : {| on : OnType, send : SendType, receiveMessage : ReceiveMessageType |}) : ZalgoPromise {
- return ZalgoPromise.try(() => {
- const opener = getOpener(window);
-
- if (!opener || !needsBridge({ win: opener })) {
- return;
- }
-
- registerRemoteWindow(opener);
-
- return awaitRemoteBridgeForWindow(opener).then(bridge => {
-
- if (!bridge) {
- return rejectRemoteSendMessage(opener, new Error(`Can not register with opener: no bridge found in opener`));
+export function openTunnelToOpener({
+ on,
+ send,
+ receiveMessage,
+}: {|
+ on: OnType,
+ send: SendType,
+ receiveMessage: ReceiveMessageType,
+|}): ZalgoPromise {
+ return ZalgoPromise.try(() => {
+ const opener = getOpener(window);
+
+ if (!opener || !needsBridge({ win: opener })) {
+ return;
+ }
+
+ registerRemoteWindow(opener);
+
+ return awaitRemoteBridgeForWindow(opener).then((bridge) => {
+ if (!bridge) {
+ return rejectRemoteSendMessage(
+ opener,
+ new Error(`Can not register with opener: no bridge found in opener`)
+ );
+ }
+
+ if (!window.name) {
+ return rejectRemoteSendMessage(
+ opener,
+ new Error(`Can not register with opener: window does not have a name`)
+ );
+ }
+
+ return getGlobal(assertSameDomain(bridge))
+ .openTunnelToParent({
+ name: window.name,
+
+ source: window,
+
+ canary() {
+ // pass
+ },
+
+ sendMessage(message) {
+ try {
+ noop(window);
+ } catch (err) {
+ return;
}
- if (!window.name) {
- return rejectRemoteSendMessage(opener, new Error(`Can not register with opener: window does not have a name`));
+ if (!window || window.closed) {
+ return;
}
- return getGlobal(assertSameDomain(bridge)).openTunnelToParent({
-
- name: window.name,
-
- source: window,
-
- canary() {
- // pass
+ try {
+ receiveMessage(
+ {
+ data: message,
+ // $FlowFixMe[object-this-reference]
+ origin: this.origin,
+ // $FlowFixMe[object-this-reference]
+ source: this.source,
},
-
- sendMessage(message) {
-
- try {
- noop(window);
- } catch (err) {
- return;
- }
-
- if (!window || window.closed) {
- return;
- }
-
- try {
- receiveMessage({
- data: message,
- // $FlowFixMe[object-this-reference]
- origin: this.origin,
- // $FlowFixMe[object-this-reference]
- source: this.source
- }, { on, send });
- } catch (err) {
- ZalgoPromise.reject(err);
- }
- }
-
- }).then(({ source, origin, data }) => {
-
- if (source !== opener) {
- throw new Error(`Source does not match opener`);
- }
-
- registerRemoteSendMessage(source, origin, data.sendMessage);
-
- }).catch(err => {
-
- rejectRemoteSendMessage(opener, err);
- throw err;
- });
+ { on, send }
+ );
+ } catch (err) {
+ ZalgoPromise.reject(err);
+ }
+ },
+ })
+ .then(({ source, origin, data }) => {
+ if (source !== opener) {
+ throw new Error(`Source does not match opener`);
+ }
+
+ registerRemoteSendMessage(source, origin, data.sendMessage);
+ })
+ .catch((err) => {
+ rejectRemoteSendMessage(opener, err);
+ throw err;
});
});
+ });
}
diff --git a/src/bridge/common.js b/src/bridge/common.js
index a468ae24..b7903bb6 100644
--- a/src/bridge/common.js
+++ b/src/bridge/common.js
@@ -1,142 +1,181 @@
/* @flow */
-import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-import { getDomain, isSameDomain, isOpener, isSameTopWindow, matchDomain, getUserAgent, getDomainFromUrl, type CrossDomainWindowType } from '@krakenjs/cross-domain-utils/src';
-import { noop } from '@krakenjs/belter/src';
-
-import { BRIDGE_NAME_PREFIX } from '../conf';
-import { windowStore } from '../global';
-
-export function needsBridgeForBrowser() : boolean {
-
- if (getUserAgent(window).match(/MSIE|trident|edge\/12|edge\/13/i)) {
- return true;
- }
+import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+import {
+ getDomain,
+ isSameDomain,
+ isOpener,
+ isSameTopWindow,
+ matchDomain,
+ getUserAgent,
+ getDomainFromUrl,
+ type CrossDomainWindowType,
+} from "@krakenjs/cross-domain-utils/src";
+import { noop } from "@krakenjs/belter/src";
+
+import { BRIDGE_NAME_PREFIX } from "../conf";
+import { windowStore } from "../global";
+
+export function needsBridgeForBrowser(): boolean {
+ if (getUserAgent(window).match(/MSIE|trident|edge\/12|edge\/13/i)) {
+ return true;
+ }
- return false;
+ return false;
}
-export function needsBridgeForWin(win : CrossDomainWindowType) : boolean {
-
- if (!isSameTopWindow(window, win)) {
- return true;
- }
+export function needsBridgeForWin(win: CrossDomainWindowType): boolean {
+ if (!isSameTopWindow(window, win)) {
+ return true;
+ }
- return false;
+ return false;
}
-export function needsBridgeForDomain(domain : ?string, win : ?CrossDomainWindowType) : boolean {
-
- if (domain) {
- if (getDomain() !== getDomainFromUrl(domain)) {
- return true;
- }
- } else if (win) {
- if (!isSameDomain(win)) {
- return true;
- }
+export function needsBridgeForDomain(
+ domain: ?string,
+ win: ?CrossDomainWindowType
+): boolean {
+ if (domain) {
+ if (getDomain() !== getDomainFromUrl(domain)) {
+ return true;
}
+ } else if (win) {
+ if (!isSameDomain(win)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
-export function needsBridge({ win, domain } : {| win? : CrossDomainWindowType, domain? : string |}) : boolean {
-
- if (!needsBridgeForBrowser()) {
- return false;
- }
+export function needsBridge({
+ win,
+ domain,
+}: {|
+ win?: CrossDomainWindowType,
+ domain?: string,
+|}): boolean {
+ if (!needsBridgeForBrowser()) {
+ return false;
+ }
- if (domain && !needsBridgeForDomain(domain, win)) {
- return false;
- }
+ if (domain && !needsBridgeForDomain(domain, win)) {
+ return false;
+ }
- if (win && !needsBridgeForWin(win)) {
- return false;
- }
+ if (win && !needsBridgeForWin(win)) {
+ return false;
+ }
- return true;
+ return true;
}
-export function getBridgeName(domain : string) : string {
-
- domain = domain || getDomainFromUrl(domain);
+export function getBridgeName(domain: string): string {
+ domain = domain || getDomainFromUrl(domain);
- const sanitizedDomain = domain.replace(/[^a-zA-Z0-9]+/g, '_');
+ const sanitizedDomain = domain.replace(/[^a-zA-Z0-9]+/g, "_");
- const id = `${ BRIDGE_NAME_PREFIX }_${ sanitizedDomain }`;
+ const id = `${BRIDGE_NAME_PREFIX}_${sanitizedDomain}`;
- return id;
+ return id;
}
-export function isBridge() : boolean {
- return Boolean(window.name && window.name === getBridgeName(getDomain()));
+export function isBridge(): boolean {
+ return Boolean(window.name && window.name === getBridgeName(getDomain()));
}
-export const documentBodyReady : ZalgoPromise = new ZalgoPromise(resolve => {
-
+export const documentBodyReady: ZalgoPromise =
+ new ZalgoPromise((resolve) => {
if (window.document && window.document.body) {
- return resolve(window.document.body);
+ return resolve(window.document.body);
}
const interval = setInterval(() => {
- if (window.document && window.document.body) {
- clearInterval(interval);
- return resolve(window.document.body);
- }
+ if (window.document && window.document.body) {
+ clearInterval(interval);
+ return resolve(window.document.body);
+ }
}, 10);
-});
+ });
-export function registerRemoteWindow(win : CrossDomainWindowType) {
- const remoteWindowPromises = windowStore('remoteWindowPromises');
- remoteWindowPromises.getOrSet(win, () => new ZalgoPromise());
+export function registerRemoteWindow(win: CrossDomainWindowType) {
+ const remoteWindowPromises = windowStore("remoteWindowPromises");
+ remoteWindowPromises.getOrSet(win, () => new ZalgoPromise());
}
-export function findRemoteWindow(win : CrossDomainWindowType) : ZalgoPromise<(remoteWin : CrossDomainWindowType, message : string, remoteDomain : string) => void> {
- const remoteWindowPromises = windowStore('remoteWindowPromises');
- const remoteWinPromise = remoteWindowPromises.get(win);
-
- if (!remoteWinPromise) {
- throw new Error(`Remote window promise not found`);
- }
-
- return remoteWinPromise;
+export function findRemoteWindow(
+ win: CrossDomainWindowType
+): ZalgoPromise<
+ (
+ remoteWin: CrossDomainWindowType,
+ message: string,
+ remoteDomain: string
+ ) => void
+> {
+ const remoteWindowPromises = windowStore("remoteWindowPromises");
+ const remoteWinPromise = remoteWindowPromises.get(win);
+
+ if (!remoteWinPromise) {
+ throw new Error(`Remote window promise not found`);
+ }
+
+ return remoteWinPromise;
}
type SendMessageType = {|
- (string) : void,
- fireAndForget : (string) => void
+ (string): void,
+ fireAndForget: (string) => void,
|};
-export function registerRemoteSendMessage(win : CrossDomainWindowType, domain : string, sendMessage : SendMessageType) {
- const sendMessageWrapper = (remoteWin : CrossDomainWindowType, remoteDomain : string, message : string) => {
- if (remoteWin !== win) {
- throw new Error(`Remote window does not match window`);
- }
+export function registerRemoteSendMessage(
+ win: CrossDomainWindowType,
+ domain: string,
+ sendMessage: SendMessageType
+) {
+ const sendMessageWrapper = (
+ remoteWin: CrossDomainWindowType,
+ remoteDomain: string,
+ message: string
+ ) => {
+ if (remoteWin !== win) {
+ throw new Error(`Remote window does not match window`);
+ }
- if (!matchDomain(remoteDomain, domain)) {
- throw new Error(`Remote domain ${ remoteDomain } does not match domain ${ domain }`);
- }
+ if (!matchDomain(remoteDomain, domain)) {
+ throw new Error(
+ `Remote domain ${remoteDomain} does not match domain ${domain}`
+ );
+ }
- sendMessage.fireAndForget(message);
- };
+ sendMessage.fireAndForget(message);
+ };
- findRemoteWindow(win).resolve(sendMessageWrapper);
+ findRemoteWindow(win).resolve(sendMessageWrapper);
}
-export function rejectRemoteSendMessage(win : CrossDomainWindowType, err : Error) {
- findRemoteWindow(win).reject(err).catch(noop);
+export function rejectRemoteSendMessage(
+ win: CrossDomainWindowType,
+ err: Error
+) {
+ findRemoteWindow(win).reject(err).catch(noop);
}
-export function sendBridgeMessage(win : CrossDomainWindowType, domain : string, message : string) : ZalgoPromise {
-
- const messagingChild = isOpener(window, win);
- const messagingParent = isOpener(win, window);
-
- if (!messagingChild && !messagingParent) {
- throw new Error(`Can only send messages to and from parent and popup windows`);
- }
-
- return findRemoteWindow(win).then(sendMessage => {
- return sendMessage(win, domain, message);
- });
+export function sendBridgeMessage(
+ win: CrossDomainWindowType,
+ domain: string,
+ message: string
+): ZalgoPromise {
+ const messagingChild = isOpener(window, win);
+ const messagingParent = isOpener(win, window);
+
+ if (!messagingChild && !messagingParent) {
+ throw new Error(
+ `Can only send messages to and from parent and popup windows`
+ );
+ }
+
+ return findRemoteWindow(win).then((sendMessage) => {
+ return sendMessage(win, domain, message);
+ });
}
diff --git a/src/bridge/index.js b/src/bridge/index.js
index 8fa61b11..9c0f542e 100644
--- a/src/bridge/index.js
+++ b/src/bridge/index.js
@@ -1,8 +1,7 @@
/* @flow */
-
-export * from './bridge';
-export * from './child';
-export * from './common';
-export * from './parent';
-export * from './setup';
+export * from "./bridge";
+export * from "./child";
+export * from "./common";
+export * from "./parent";
+export * from "./setup";
diff --git a/src/bridge/parent.js b/src/bridge/parent.js
index fc7f3303..60ae9c74 100644
--- a/src/bridge/parent.js
+++ b/src/bridge/parent.js
@@ -1,243 +1,298 @@
/* @flow */
-import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-import { getDomain, getFrameByName, isWindowClosed, getDomainFromUrl, normalizeMockUrl, type CrossDomainWindowType } from '@krakenjs/cross-domain-utils/src';
-
-import { BRIDGE_TIMEOUT, MESSAGE_NAME } from '../conf';
-import { awaitWindowHello } from '../lib';
-import { windowStore, globalStore } from '../global';
-import type { OnType, SendType, ReceiveMessageType } from '../types';
-
-import { getBridgeName, documentBodyReady, registerRemoteSendMessage, registerRemoteWindow } from './common';
+import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+import {
+ getDomain,
+ getFrameByName,
+ isWindowClosed,
+ getDomainFromUrl,
+ normalizeMockUrl,
+ type CrossDomainWindowType,
+} from "@krakenjs/cross-domain-utils/src";
+
+import { BRIDGE_TIMEOUT, MESSAGE_NAME } from "../conf";
+import { awaitWindowHello } from "../lib";
+import { windowStore, globalStore } from "../global";
+import type { OnType, SendType, ReceiveMessageType } from "../types";
+
+import {
+ getBridgeName,
+ documentBodyReady,
+ registerRemoteSendMessage,
+ registerRemoteWindow,
+} from "./common";
type WinDetails = {|
- win : CrossDomainWindowType,
- domain? : ?string,
- name? : ?string
+ win: CrossDomainWindowType,
+ domain?: ?string,
+ name?: ?string,
|};
-export function listenForOpenTunnel({ on, send, receiveMessage } : {| on : OnType, send : SendType, receiveMessage : ReceiveMessageType |}) {
- const popupWindowsByName = globalStore('popupWindowsByName');
-
- on(MESSAGE_NAME.OPEN_TUNNEL, ({ source, origin, data }) => {
- const bridgePromise = globalStore('bridges').get(origin);
-
- if (!bridgePromise) {
- throw new Error(`Can not find bridge promise for domain ${ origin }`);
- }
-
- return bridgePromise.then(bridge => {
- if (source !== bridge) {
- throw new Error(`Message source does not matched registered bridge for domain ${ origin }`);
- }
-
- if (!data.name) {
- throw new Error(`Register window expected to be passed window name`);
- }
-
- if (!data.sendMessage) {
- throw new Error(`Register window expected to be passed sendMessage method`);
- }
-
- if (!popupWindowsByName.has(data.name)) {
- throw new Error(`Window with name ${ data.name } does not exist, or was not opened by this window`);
- }
-
- const getWindowDetails = () : WinDetails => {
- const winDetails = popupWindowsByName.get(data.name);
- // $FlowFixMe
- return winDetails;
- };
-
- if (!getWindowDetails().domain) {
- throw new Error(`We do not have a registered domain for window ${ data.name }`);
- }
-
- if (getWindowDetails().domain !== origin) {
- throw new Error(`Message origin ${ origin } does not matched registered window origin ${ getWindowDetails().domain || 'unknown' }`);
- }
-
- registerRemoteSendMessage(getWindowDetails().win, origin, data.sendMessage);
-
- return {
- sendMessage(message) {
-
- if (!window || window.closed) {
- return;
- }
-
- if (!getWindowDetails()) {
- return;
- }
-
- const domain = getWindowDetails().domain;
-
- if (!domain) {
- return;
- }
-
- try {
- receiveMessage({
- data: message,
- origin: domain,
- source: getWindowDetails().win
- }, { on, send });
- } catch (err) {
- ZalgoPromise.reject(err);
- }
- }
- };
- });
+export function listenForOpenTunnel({
+ on,
+ send,
+ receiveMessage,
+}: {|
+ on: OnType,
+ send: SendType,
+ receiveMessage: ReceiveMessageType,
+|}) {
+ const popupWindowsByName = globalStore("popupWindowsByName");
+
+ on(MESSAGE_NAME.OPEN_TUNNEL, ({ source, origin, data }) => {
+ const bridgePromise = globalStore("bridges").get(origin);
+
+ if (!bridgePromise) {
+ throw new Error(`Can not find bridge promise for domain ${origin}`);
+ }
+
+ return bridgePromise.then((bridge) => {
+ if (source !== bridge) {
+ throw new Error(
+ `Message source does not matched registered bridge for domain ${origin}`
+ );
+ }
+
+ if (!data.name) {
+ throw new Error(`Register window expected to be passed window name`);
+ }
+
+ if (!data.sendMessage) {
+ throw new Error(
+ `Register window expected to be passed sendMessage method`
+ );
+ }
+
+ if (!popupWindowsByName.has(data.name)) {
+ throw new Error(
+ `Window with name ${data.name} does not exist, or was not opened by this window`
+ );
+ }
+
+ const getWindowDetails = (): WinDetails => {
+ const winDetails = popupWindowsByName.get(data.name);
+ // $FlowFixMe
+ return winDetails;
+ };
+
+ if (!getWindowDetails().domain) {
+ throw new Error(
+ `We do not have a registered domain for window ${data.name}`
+ );
+ }
+
+ if (getWindowDetails().domain !== origin) {
+ throw new Error(
+ `Message origin ${origin} does not matched registered window origin ${
+ getWindowDetails().domain || "unknown"
+ }`
+ );
+ }
+
+ registerRemoteSendMessage(
+ getWindowDetails().win,
+ origin,
+ data.sendMessage
+ );
+
+ return {
+ sendMessage(message) {
+ if (!window || window.closed) {
+ return;
+ }
+
+ if (!getWindowDetails()) {
+ return;
+ }
+
+ const domain = getWindowDetails().domain;
+
+ if (!domain) {
+ return;
+ }
+
+ try {
+ receiveMessage(
+ {
+ data: message,
+ origin: domain,
+ source: getWindowDetails().win,
+ },
+ { on, send }
+ );
+ } catch (err) {
+ ZalgoPromise.reject(err);
+ }
+ },
+ };
});
+ });
}
-function openBridgeFrame(name : string, url : string) : HTMLIFrameElement {
-
- const iframe = document.createElement(`iframe`);
+function openBridgeFrame(name: string, url: string): HTMLIFrameElement {
+ const iframe = document.createElement(`iframe`);
- iframe.setAttribute(`name`, name);
- iframe.setAttribute(`id`, name);
+ iframe.setAttribute(`name`, name);
+ iframe.setAttribute(`id`, name);
- iframe.setAttribute(`style`, `display: none; margin: 0; padding: 0; border: 0px none; overflow: hidden;`);
- iframe.setAttribute(`frameborder`, `0`);
- iframe.setAttribute(`border`, `0`);
- iframe.setAttribute(`scrolling`, `no`);
- iframe.setAttribute(`allowTransparency`, `true`);
+ iframe.setAttribute(
+ `style`,
+ `display: none; margin: 0; padding: 0; border: 0px none; overflow: hidden;`
+ );
+ iframe.setAttribute(`frameborder`, `0`);
+ iframe.setAttribute(`border`, `0`);
+ iframe.setAttribute(`scrolling`, `no`);
+ iframe.setAttribute(`allowTransparency`, `true`);
- iframe.setAttribute(`tabindex`, `-1`);
- iframe.setAttribute(`hidden`, `true`);
- iframe.setAttribute(`title`, ``);
- iframe.setAttribute(`role`, `presentation`);
+ iframe.setAttribute(`tabindex`, `-1`);
+ iframe.setAttribute(`hidden`, `true`);
+ iframe.setAttribute(`title`, ``);
+ iframe.setAttribute(`role`, `presentation`);
- iframe.src = url;
+ iframe.src = url;
- return iframe;
+ return iframe;
}
-export function hasBridge(url : string, domain : string) : boolean {
- const bridges = globalStore('bridges');
- return bridges.has(domain || getDomainFromUrl(url));
+export function hasBridge(url: string, domain: string): boolean {
+ const bridges = globalStore("bridges");
+ return bridges.has(domain || getDomainFromUrl(url));
}
-export function openBridge(url : string, domain : string) : ZalgoPromise {
- const bridges = globalStore('bridges');
- const bridgeFrames = globalStore('bridgeFrames');
-
- domain = domain || getDomainFromUrl(url);
-
- return bridges.getOrSet(domain, () => ZalgoPromise.try(() => {
-
- if (getDomain() === domain) {
- throw new Error(`Can not open bridge on the same domain as current domain: ${ domain }`);
- }
-
- const name = getBridgeName(domain);
- const frame = getFrameByName(window, name);
-
- if (frame) {
- throw new Error(`Frame with name ${ name } already exists on page`);
- }
-
- const iframe = openBridgeFrame(name, url);
- bridgeFrames.set(domain, iframe);
-
- return documentBodyReady.then(body => {
-
- body.appendChild(iframe);
- const bridge = iframe.contentWindow;
-
- return new ZalgoPromise((resolve, reject) => {
-
- iframe.addEventListener('load', resolve);
- iframe.addEventListener('error', reject);
-
- }).then(() => {
-
- return awaitWindowHello(bridge, BRIDGE_TIMEOUT, `Bridge ${ url }`);
-
- }).then(() => {
-
- return bridge;
- });
- });
- }));
+export function openBridge(
+ url: string,
+ domain: string
+): ZalgoPromise {
+ const bridges = globalStore("bridges");
+ const bridgeFrames = globalStore("bridgeFrames");
+
+ domain = domain || getDomainFromUrl(url);
+
+ return bridges.getOrSet(domain, () =>
+ ZalgoPromise.try(() => {
+ if (getDomain() === domain) {
+ throw new Error(
+ `Can not open bridge on the same domain as current domain: ${domain}`
+ );
+ }
+
+ const name = getBridgeName(domain);
+ const frame = getFrameByName(window, name);
+
+ if (frame) {
+ throw new Error(`Frame with name ${name} already exists on page`);
+ }
+
+ const iframe = openBridgeFrame(name, url);
+ bridgeFrames.set(domain, iframe);
+
+ return documentBodyReady.then((body) => {
+ body.appendChild(iframe);
+ const bridge = iframe.contentWindow;
+
+ return new ZalgoPromise((resolve, reject) => {
+ iframe.addEventListener("load", resolve);
+ iframe.addEventListener("error", reject);
+ })
+ .then(() => {
+ return awaitWindowHello(bridge, BRIDGE_TIMEOUT, `Bridge ${url}`);
+ })
+ .then(() => {
+ return bridge;
+ });
+ });
+ })
+ );
}
-export function linkWindow({ win, name, domain } : WinDetails) : WinDetails {
- const popupWindowsByName = globalStore('popupWindowsByName');
- const popupWindowsByWin = windowStore('popupWindowsByWin');
+export function linkWindow({ win, name, domain }: WinDetails): WinDetails {
+ const popupWindowsByName = globalStore("popupWindowsByName");
+ const popupWindowsByWin = windowStore("popupWindowsByWin");
- for (const winName of popupWindowsByName.keys()) {
- const details = popupWindowsByName.get(winName);
- if (!details || isWindowClosed(details.win)) {
- popupWindowsByName.del(winName);
- }
+ for (const winName of popupWindowsByName.keys()) {
+ const details = popupWindowsByName.get(winName);
+ if (!details || isWindowClosed(details.win)) {
+ popupWindowsByName.del(winName);
}
+ }
- if (isWindowClosed(win)) {
- return { win, name, domain };
+ if (isWindowClosed(win)) {
+ return { win, name, domain };
+ }
+
+ const details = popupWindowsByWin.getOrSet(win, (): WinDetails => {
+ if (!name) {
+ return { win };
}
- const details = popupWindowsByWin.getOrSet(win, () : WinDetails => {
- if (!name) {
- return { win };
- }
-
- // $FlowFixMe
- return popupWindowsByName.getOrSet(name, () : WinDetails => {
- return { win, name };
- });
+ // $FlowFixMe
+ return popupWindowsByName.getOrSet(name, (): WinDetails => {
+ return { win, name };
});
+ });
- if (details.win && details.win !== win) {
- throw new Error(`Different window already linked for window: ${ name || 'undefined' }`);
- }
+ if (details.win && details.win !== win) {
+ throw new Error(
+ `Different window already linked for window: ${name || "undefined"}`
+ );
+ }
- if (name) {
- details.name = name;
- popupWindowsByName.set(name, details);
- }
+ if (name) {
+ details.name = name;
+ popupWindowsByName.set(name, details);
+ }
- if (domain) {
- details.domain = domain;
- registerRemoteWindow(win);
- }
+ if (domain) {
+ details.domain = domain;
+ registerRemoteWindow(win);
+ }
- popupWindowsByWin.set(win, details);
-
- return details;
+ popupWindowsByWin.set(win, details);
+
+ return details;
}
-export function linkUrl(win : CrossDomainWindowType, url : string) {
- linkWindow({ win, domain: getDomainFromUrl(url) });
+export function linkUrl(win: CrossDomainWindowType, url: string) {
+ linkWindow({ win, domain: getDomainFromUrl(url) });
}
export function listenForWindowOpen() {
- const windowOpen = window.open;
-
- window.open = function windowOpenWrapper(url : string, name : string, options : string, last : mixed) : mixed {
- const win = windowOpen.call(this, normalizeMockUrl(url), name, options, last);
-
- if (!win) {
- return win;
- }
-
- linkWindow({ win, name, domain: url ? getDomainFromUrl(url) : null });
-
- return win;
- };
+ const windowOpen = window.open;
+
+ window.open = function windowOpenWrapper(
+ url: string,
+ name: string,
+ options: string,
+ last: mixed
+ ): mixed {
+ const win = windowOpen.call(
+ this,
+ normalizeMockUrl(url),
+ name,
+ options,
+ last
+ );
+
+ if (!win) {
+ return win;
+ }
+
+ linkWindow({ win, name, domain: url ? getDomainFromUrl(url) : null });
+
+ return win;
+ };
}
export function destroyBridges() {
- const bridges = globalStore('bridges');
- const bridgeFrames = globalStore('bridgeFrames');
-
- for (const domain of bridgeFrames.keys()) {
- const frame = bridgeFrames.get(domain);
- if (frame && frame.parentNode) {
- frame.parentNode.removeChild(frame);
- }
+ const bridges = globalStore("bridges");
+ const bridgeFrames = globalStore("bridgeFrames");
+
+ for (const domain of bridgeFrames.keys()) {
+ const frame = bridgeFrames.get(domain);
+ if (frame && frame.parentNode) {
+ frame.parentNode.removeChild(frame);
}
- bridgeFrames.reset();
- bridges.reset();
+ }
+ bridgeFrames.reset();
+ bridges.reset();
}
diff --git a/src/bridge/setup.js b/src/bridge/setup.js
index 81373af3..91fbec66 100644
--- a/src/bridge/setup.js
+++ b/src/bridge/setup.js
@@ -1,14 +1,22 @@
/* @flow */
-import type { OnType, SendType, ReceiveMessageType } from '../types';
+import type { OnType, SendType, ReceiveMessageType } from "../types";
-import { listenForWindowOpen, listenForOpenTunnel } from './parent';
-import { setupOpenTunnelToParent } from './bridge';
-import { openTunnelToOpener } from './child';
+import { listenForWindowOpen, listenForOpenTunnel } from "./parent";
+import { setupOpenTunnelToParent } from "./bridge";
+import { openTunnelToOpener } from "./child";
-export function setupBridge({ on, send, receiveMessage } : {| on : OnType, send : SendType, receiveMessage : ReceiveMessageType |}) {
- listenForWindowOpen();
- listenForOpenTunnel({ on, send, receiveMessage });
- setupOpenTunnelToParent({ send });
- openTunnelToOpener({ on, send, receiveMessage });
+export function setupBridge({
+ on,
+ send,
+ receiveMessage,
+}: {|
+ on: OnType,
+ send: SendType,
+ receiveMessage: ReceiveMessageType,
+|}) {
+ listenForWindowOpen();
+ listenForOpenTunnel({ on, send, receiveMessage });
+ setupOpenTunnelToParent({ send });
+ openTunnelToOpener({ on, send, receiveMessage });
}
diff --git a/src/clean.js b/src/clean.js
index 9c6542ea..58b0f2a9 100644
--- a/src/clean.js
+++ b/src/clean.js
@@ -1,13 +1,24 @@
/* @flow */
-import { type CrossDomainWindowType, isWindowClosed } from '@krakenjs/cross-domain-utils/src';
-import { noop } from '@krakenjs/belter/src';
+import {
+ type CrossDomainWindowType,
+ isWindowClosed,
+} from "@krakenjs/cross-domain-utils/src";
+import { noop } from "@krakenjs/belter/src";
-import { windowStore } from './global';
+import { windowStore } from "./global";
-export function cleanUpWindow(win : CrossDomainWindowType) {
- const requestPromises = windowStore('requestPromises');
- for (const promise of requestPromises.get(win, [])) {
- promise.reject(new Error(`Window ${ isWindowClosed(win) ? 'closed' : 'cleaned up' } before response`)).catch(noop);
- }
+export function cleanUpWindow(win: CrossDomainWindowType) {
+ const requestPromises = windowStore("requestPromises");
+ for (const promise of requestPromises.get(win, [])) {
+ promise
+ .reject(
+ new Error(
+ `Window ${
+ isWindowClosed(win) ? "closed" : "cleaned up"
+ } before response`
+ )
+ )
+ .catch(noop);
+ }
}
diff --git a/src/conf/config.js b/src/conf/config.js
index 55d44cab..3e56999a 100644
--- a/src/conf/config.js
+++ b/src/conf/config.js
@@ -5,5 +5,5 @@ export const CHILD_WINDOW_TIMEOUT = 5000;
export const ACK_TIMEOUT = 2000;
export const ACK_TIMEOUT_KNOWN = 10000;
-export const RES_TIMEOUT : number = __TEST__ ? 2000 : -1;
+export const RES_TIMEOUT: number = __TEST__ ? 2000 : -1;
export const RESPONSE_CYCLE_TIME = 500;
diff --git a/src/conf/constants.js b/src/conf/constants.js
index 2192b1b3..84fc1fe9 100644
--- a/src/conf/constants.js
+++ b/src/conf/constants.js
@@ -1,40 +1,41 @@
/* @flow */
export const MESSAGE_TYPE = {
- REQUEST: ('postrobot_message_request' : 'postrobot_message_request'),
- RESPONSE: ('postrobot_message_response' : 'postrobot_message_response'),
- ACK: ('postrobot_message_ack' : 'postrobot_message_ack')
+ REQUEST: ("postrobot_message_request": "postrobot_message_request"),
+ RESPONSE: ("postrobot_message_response": "postrobot_message_response"),
+ ACK: ("postrobot_message_ack": "postrobot_message_ack"),
};
export const MESSAGE_ACK = {
- SUCCESS: ('success' : 'success'),
- ERROR: ('error' : 'error')
+ SUCCESS: ("success": "success"),
+ ERROR: ("error": "error"),
};
export const MESSAGE_NAME = {
- METHOD: ('postrobot_method' : 'postrobot_method'),
- HELLO: ('postrobot_hello' : 'postrobot_hello'),
- OPEN_TUNNEL: ('postrobot_open_tunnel' : 'postrobot_open_tunnel')
+ METHOD: ("postrobot_method": "postrobot_method"),
+ HELLO: ("postrobot_hello": "postrobot_hello"),
+ OPEN_TUNNEL: ("postrobot_open_tunnel": "postrobot_open_tunnel"),
};
export const SEND_STRATEGY = {
- POST_MESSAGE: ('postrobot_post_message' : 'postrobot_post_message'),
- BRIDGE: ('postrobot_bridge' : 'postrobot_bridge'),
- GLOBAL: ('postrobot_global' : 'postrobot_global')
+ POST_MESSAGE: ("postrobot_post_message": "postrobot_post_message"),
+ BRIDGE: ("postrobot_bridge": "postrobot_bridge"),
+ GLOBAL: ("postrobot_global": "postrobot_global"),
};
-export const BRIDGE_NAME_PREFIX = '__postrobot_bridge__';
-export const POSTROBOT_PROXY = '__postrobot_proxy__';
+export const BRIDGE_NAME_PREFIX = "__postrobot_bridge__";
+export const POSTROBOT_PROXY = "__postrobot_proxy__";
-export const WILDCARD = '*';
+export const WILDCARD = "*";
export const SERIALIZATION_TYPE = {
- CROSS_DOMAIN_ZALGO_PROMISE: ('cross_domain_zalgo_promise' : 'cross_domain_zalgo_promise'),
- CROSS_DOMAIN_FUNCTION: ('cross_domain_function' : 'cross_domain_function'),
- CROSS_DOMAIN_WINDOW: ('cross_domain_window' : 'cross_domain_window')
+ CROSS_DOMAIN_ZALGO_PROMISE:
+ ("cross_domain_zalgo_promise": "cross_domain_zalgo_promise"),
+ CROSS_DOMAIN_FUNCTION: ("cross_domain_function": "cross_domain_function"),
+ CROSS_DOMAIN_WINDOW: ("cross_domain_window": "cross_domain_window"),
};
export const METHOD = {
- GET: ('get' : 'get'),
- POST: ('post' : 'post')
+ GET: ("get": "get"),
+ POST: ("post": "post"),
};
diff --git a/src/conf/index.js b/src/conf/index.js
index 871c272c..59515b3c 100644
--- a/src/conf/index.js
+++ b/src/conf/index.js
@@ -1,4 +1,4 @@
/* @flow */
-export * from './config';
-export * from './constants';
+export * from "./config";
+export * from "./constants";
diff --git a/src/declarations.js b/src/declarations.js
index 270c4eee..aeb45c6d 100644
--- a/src/declarations.js
+++ b/src/declarations.js
@@ -1,11 +1,11 @@
/* @flow */
-declare var __POST_ROBOT__ : {|
- __GLOBAL_KEY__ : string,
- __AUTO_SETUP__ : boolean,
- __IE_POPUP_SUPPORT__ : boolean,
- __GLOBAL_MESSAGE_SUPPORT__ : boolean,
- __SCRIPT_NAMESPACE__ : boolean
+declare var __POST_ROBOT__: {|
+ __GLOBAL_KEY__: string,
+ __AUTO_SETUP__: boolean,
+ __IE_POPUP_SUPPORT__: boolean,
+ __GLOBAL_MESSAGE_SUPPORT__: boolean,
+ __SCRIPT_NAMESPACE__: boolean,
|};
-declare var __TEST__ : boolean;
+declare var __TEST__: boolean;
diff --git a/src/drivers/index.js b/src/drivers/index.js
index e4e27689..434c47e1 100644
--- a/src/drivers/index.js
+++ b/src/drivers/index.js
@@ -1,5 +1,5 @@
/* @flow */
-export * from './receive';
-export * from './send';
-export * from './listeners';
+export * from "./receive";
+export * from "./send";
+export * from "./listeners";
diff --git a/src/drivers/listeners.js b/src/drivers/listeners.js
index 30efb1bf..e313725a 100644
--- a/src/drivers/listeners.js
+++ b/src/drivers/listeners.js
@@ -1,237 +1,299 @@
/* @flow */
-import { type ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-import { matchDomain, type CrossDomainWindowType, type DomainMatcher } from '@krakenjs/cross-domain-utils/src';
-import { isRegex, getOrSet, noop } from '@krakenjs/belter/src';
-
-import { getWildcard, type WildCard, globalStore, windowStore } from '../global';
-import { WILDCARD } from '../conf';
-import { ProxyWindow } from '../serialize/window';
+import { type ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+import {
+ matchDomain,
+ type CrossDomainWindowType,
+ type DomainMatcher,
+} from "@krakenjs/cross-domain-utils/src";
+import { isRegex, getOrSet, noop } from "@krakenjs/belter/src";
+
+import {
+ getWildcard,
+ type WildCard,
+ globalStore,
+ windowStore,
+} from "../global";
+import { WILDCARD } from "../conf";
+import { ProxyWindow } from "../serialize/window";
export function resetListeners() {
- const responseListeners = globalStore('responseListeners');
- const erroredResponseListeners = globalStore('erroredResponseListeners');
- responseListeners.reset();
- erroredResponseListeners.reset();
+ const responseListeners = globalStore("responseListeners");
+ const erroredResponseListeners = globalStore("erroredResponseListeners");
+ responseListeners.reset();
+ erroredResponseListeners.reset();
}
-const __DOMAIN_REGEX__ = '__domain_regex__';
+const __DOMAIN_REGEX__ = "__domain_regex__";
export type RequestListenerType = {|
- handler : ({| source : CrossDomainWindowType, origin : string, data : mixed |}) => (mixed | ZalgoPromise),
- handleError : (err : mixed) => void
+ handler: ({|
+ source: CrossDomainWindowType,
+ origin: string,
+ data: mixed,
+ |}) => mixed | ZalgoPromise,
+ handleError: (err: mixed) => void,
|};
export type ResponseListenerType = {|
- name : string,
- win : CrossDomainWindowType,
- domain : DomainMatcher,
- promise : ZalgoPromise<*>,
- ack? : ?boolean,
- cancelled? : ?boolean
+ name: string,
+ win: CrossDomainWindowType,
+ domain: DomainMatcher,
+ promise: ZalgoPromise<*>,
+ ack?: ?boolean,
+ cancelled?: ?boolean,
|};
-export function addResponseListener(hash : string, listener : ResponseListenerType) {
- const responseListeners = globalStore('responseListeners');
- responseListeners.set(hash, listener);
+export function addResponseListener(
+ hash: string,
+ listener: ResponseListenerType
+) {
+ const responseListeners = globalStore("responseListeners");
+ responseListeners.set(hash, listener);
}
-export function getResponseListener(hash : string) : ?ResponseListenerType {
- const responseListeners = globalStore('responseListeners');
- return responseListeners.get(hash);
+export function getResponseListener(hash: string): ?ResponseListenerType {
+ const responseListeners = globalStore("responseListeners");
+ return responseListeners.get(hash);
}
-export function deleteResponseListener(hash : string) {
- const responseListeners = globalStore('responseListeners');
- responseListeners.del(hash);
+export function deleteResponseListener(hash: string) {
+ const responseListeners = globalStore("responseListeners");
+ responseListeners.del(hash);
}
export function cancelResponseListeners() {
- const responseListeners = globalStore('responseListeners');
- for (const hash of responseListeners.keys()) {
- const listener = responseListeners.get(hash);
- if (listener) {
- listener.cancelled = true;
- }
- responseListeners.del(hash);
+ const responseListeners = globalStore("responseListeners");
+ for (const hash of responseListeners.keys()) {
+ const listener = responseListeners.get(hash);
+ if (listener) {
+ listener.cancelled = true;
}
+ responseListeners.del(hash);
+ }
}
-export function markResponseListenerErrored(hash : string) {
- const erroredResponseListeners = globalStore('erroredResponseListeners');
- erroredResponseListeners.set(hash, true);
+export function markResponseListenerErrored(hash: string) {
+ const erroredResponseListeners = globalStore("erroredResponseListeners");
+ erroredResponseListeners.set(hash, true);
}
-export function isResponseListenerErrored(hash : string) : boolean {
- const erroredResponseListeners = globalStore('erroredResponseListeners');
- return erroredResponseListeners.has(hash);
+export function isResponseListenerErrored(hash: string): boolean {
+ const erroredResponseListeners = globalStore("erroredResponseListeners");
+ return erroredResponseListeners.has(hash);
}
-export function getRequestListener({ name, win, domain } : {| name : string, win : ?(CrossDomainWindowType | WildCard), domain : ?(string | RegExp) |}) : ?RequestListenerType {
- const requestListeners = windowStore('requestListeners');
-
- if (win === WILDCARD) {
- win = null;
+export function getRequestListener({
+ name,
+ win,
+ domain,
+}: {|
+ name: string,
+ win: ?(CrossDomainWindowType | WildCard),
+ domain: ?(string | RegExp),
+|}): ?RequestListenerType {
+ const requestListeners = windowStore("requestListeners");
+
+ if (win === WILDCARD) {
+ win = null;
+ }
+
+ if (domain === WILDCARD) {
+ domain = null;
+ }
+
+ if (!name) {
+ throw new Error(`Name required to get request listener`);
+ }
+
+ for (const winQualifier of [win, getWildcard()]) {
+ if (!winQualifier) {
+ continue;
}
- if (domain === WILDCARD) {
- domain = null;
- }
+ const nameListeners = requestListeners.get(winQualifier);
- if (!name) {
- throw new Error(`Name required to get request listener`);
+ if (!nameListeners) {
+ continue;
}
- for (const winQualifier of [ win, getWildcard() ]) {
- if (!winQualifier) {
- continue;
- }
-
- const nameListeners = requestListeners.get(winQualifier);
+ const domainListeners = nameListeners[name];
- if (!nameListeners) {
- continue;
- }
+ if (!domainListeners) {
+ continue;
+ }
- const domainListeners = nameListeners[name];
+ if (domain && typeof domain === "string") {
+ if (domainListeners[domain]) {
+ return domainListeners[domain];
+ }
- if (!domainListeners) {
- continue;
- }
-
- if (domain && typeof domain === 'string') {
- if (domainListeners[domain]) {
- return domainListeners[domain];
- }
-
- if (domainListeners[__DOMAIN_REGEX__]) {
- for (const { regex, listener } of domainListeners[__DOMAIN_REGEX__]) {
- if (matchDomain(regex, domain)) {
- return listener;
- }
- }
- }
+ if (domainListeners[__DOMAIN_REGEX__]) {
+ for (const { regex, listener } of domainListeners[__DOMAIN_REGEX__]) {
+ if (matchDomain(regex, domain)) {
+ return listener;
+ }
}
+ }
+ }
- if (domainListeners[WILDCARD]) {
- return domainListeners[WILDCARD];
- }
+ if (domainListeners[WILDCARD]) {
+ return domainListeners[WILDCARD];
}
+ }
}
// eslint-disable-next-line complexity
-export function addRequestListener({ name, win: winCandidate, domain } : {| name : string, win : ?(CrossDomainWindowType | WildCard | ProxyWindow), domain : ?DomainMatcher |}, listener : RequestListenerType) : {| cancel : () => void |} {
- const requestListeners = windowStore('requestListeners');
-
- if (!name || typeof name !== 'string') {
- throw new Error(`Name required to add request listener`);
- }
-
+export function addRequestListener(
+ {
+ name,
+ win: winCandidate,
+ domain,
+ }: {|
+ name: string,
+ win: ?(CrossDomainWindowType | WildCard | ProxyWindow),
+ domain: ?DomainMatcher,
+ |},
+ listener: RequestListenerType
+): {| cancel: () => void |} {
+ const requestListeners = windowStore("requestListeners");
+
+ if (!name || typeof name !== "string") {
+ throw new Error(`Name required to add request listener`);
+ }
+
+ if (
+ winCandidate &&
+ winCandidate !== WILDCARD &&
// $FlowFixMe
- if (winCandidate && winCandidate !== WILDCARD && ProxyWindow.isProxyWindow(winCandidate)) {
- // $FlowFixMe
- const proxyWin : ProxyWindow = winCandidate;
-
- const requestListenerPromise = proxyWin.awaitWindow().then(actualWin => {
- return addRequestListener({ name, win: actualWin, domain }, listener);
- });
-
- return {
- cancel: () => {
- requestListenerPromise.then(requestListener => requestListener.cancel(), noop);
- }
- };
- }
-
+ ProxyWindow.isProxyWindow(winCandidate)
+ ) {
// $FlowFixMe
- let win : ?(CrossDomainWindowType | WildCard) = winCandidate;
-
- if (Array.isArray(win)) {
- const listenersCollection = [];
-
- for (const item of win) {
- listenersCollection.push(addRequestListener({ name, domain, win: item }, listener));
- }
+ const proxyWin: ProxyWindow = winCandidate;
- return {
- cancel() {
- for (const cancelListener of listenersCollection) {
- cancelListener.cancel();
- }
- }
- };
- }
+ const requestListenerPromise = proxyWin.awaitWindow().then((actualWin) => {
+ return addRequestListener({ name, win: actualWin, domain }, listener);
+ });
- if (Array.isArray(domain)) {
- const listenersCollection = [];
+ return {
+ cancel: () => {
+ requestListenerPromise.then(
+ (requestListener) => requestListener.cancel(),
+ noop
+ );
+ },
+ };
+ }
- for (const item of domain) {
- listenersCollection.push(addRequestListener({ name, win, domain: item }, listener));
- }
+ // $FlowFixMe
+ let win: ?(CrossDomainWindowType | WildCard) = winCandidate;
- return {
- cancel() {
- for (const cancelListener of listenersCollection) {
- cancelListener.cancel();
- }
- }
- };
- }
+ if (Array.isArray(win)) {
+ const listenersCollection = [];
- const existingListener = getRequestListener({ name, win, domain });
-
- if (!win || win === WILDCARD) {
- win = getWildcard();
+ for (const item of win) {
+ listenersCollection.push(
+ addRequestListener({ name, domain, win: item }, listener)
+ );
}
- domain = domain || WILDCARD;
- const strDomain = domain.toString();
-
- if (existingListener) {
- if (win && domain) {
- throw new Error(`Request listener already exists for ${ name } on domain ${ domain.toString() } for ${ win === getWildcard() ? 'wildcard' : 'specified' } window`);
- } else if (win) {
- throw new Error(`Request listener already exists for ${ name } for ${ win === getWildcard() ? 'wildcard' : 'specified' } window`);
- } else if (domain) {
- throw new Error(`Request listener already exists for ${ name } on domain ${ domain.toString() }`);
- } else {
- throw new Error(`Request listener already exists for ${ name }`);
+ return {
+ cancel() {
+ for (const cancelListener of listenersCollection) {
+ cancelListener.cancel();
}
- }
-
- const winNameListeners = requestListeners.getOrSet(win, () => ({}));
- const winNameDomainListeners = getOrSet(winNameListeners, name, () => ({}));
+ },
+ };
+ }
- let winNameDomainRegexListeners;
- let winNameDomainRegexListener;
+ if (Array.isArray(domain)) {
+ const listenersCollection = [];
- if (isRegex(domain)) {
- winNameDomainRegexListeners = getOrSet(winNameDomainListeners, __DOMAIN_REGEX__, () => []);
- winNameDomainRegexListener = { regex: domain, listener };
- winNameDomainRegexListeners.push(winNameDomainRegexListener);
- } else {
- winNameDomainListeners[strDomain] = listener;
+ for (const item of domain) {
+ listenersCollection.push(
+ addRequestListener({ name, win, domain: item }, listener)
+ );
}
return {
- cancel() {
- delete winNameDomainListeners[strDomain];
-
- if (winNameDomainRegexListener) {
- winNameDomainRegexListeners.splice(winNameDomainRegexListeners.indexOf(winNameDomainRegexListener, 1));
-
- if (!winNameDomainRegexListeners.length) {
- delete winNameDomainListeners[__DOMAIN_REGEX__];
- }
- }
-
- if (!Object.keys(winNameDomainListeners).length) {
- delete winNameListeners[name];
- }
-
- if (win && !Object.keys(winNameListeners).length) {
- requestListeners.del(win);
- }
+ cancel() {
+ for (const cancelListener of listenersCollection) {
+ cancelListener.cancel();
}
+ },
};
+ }
+
+ const existingListener = getRequestListener({ name, win, domain });
+
+ if (!win || win === WILDCARD) {
+ win = getWildcard();
+ }
+
+ domain = domain || WILDCARD;
+ const strDomain = domain.toString();
+
+ if (existingListener) {
+ if (win && domain) {
+ throw new Error(
+ `Request listener already exists for ${name} on domain ${domain.toString()} for ${
+ win === getWildcard() ? "wildcard" : "specified"
+ } window`
+ );
+ } else if (win) {
+ throw new Error(
+ `Request listener already exists for ${name} for ${
+ win === getWildcard() ? "wildcard" : "specified"
+ } window`
+ );
+ } else if (domain) {
+ throw new Error(
+ `Request listener already exists for ${name} on domain ${domain.toString()}`
+ );
+ } else {
+ throw new Error(`Request listener already exists for ${name}`);
+ }
+ }
+
+ const winNameListeners = requestListeners.getOrSet(win, () => ({}));
+ const winNameDomainListeners = getOrSet(winNameListeners, name, () => ({}));
+
+ let winNameDomainRegexListeners;
+ let winNameDomainRegexListener;
+
+ if (isRegex(domain)) {
+ winNameDomainRegexListeners = getOrSet(
+ winNameDomainListeners,
+ __DOMAIN_REGEX__,
+ () => []
+ );
+ winNameDomainRegexListener = { regex: domain, listener };
+ winNameDomainRegexListeners.push(winNameDomainRegexListener);
+ } else {
+ winNameDomainListeners[strDomain] = listener;
+ }
+
+ return {
+ cancel() {
+ delete winNameDomainListeners[strDomain];
+
+ if (winNameDomainRegexListener) {
+ winNameDomainRegexListeners.splice(
+ winNameDomainRegexListeners.indexOf(winNameDomainRegexListener, 1)
+ );
+
+ if (!winNameDomainRegexListeners.length) {
+ delete winNameDomainListeners[__DOMAIN_REGEX__];
+ }
+ }
+
+ if (!Object.keys(winNameDomainListeners).length) {
+ delete winNameListeners[name];
+ }
+
+ if (win && !Object.keys(winNameListeners).length) {
+ requestListeners.del(win);
+ }
+ },
+ };
}
diff --git a/src/drivers/receive/index.js b/src/drivers/receive/index.js
index abaf92e4..ffd3cdf4 100644
--- a/src/drivers/receive/index.js
+++ b/src/drivers/receive/index.js
@@ -1,164 +1,204 @@
/* @flow */
-import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-import { isWindowClosed, type CrossDomainWindowType, getDomain, isSameTopWindow, PROTOCOL } from '@krakenjs/cross-domain-utils/src';
-import { addEventListener, noop } from '@krakenjs/belter/src';
+import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+import {
+ isWindowClosed,
+ type CrossDomainWindowType,
+ getDomain,
+ isSameTopWindow,
+ PROTOCOL,
+} from "@krakenjs/cross-domain-utils/src";
+import { addEventListener, noop } from "@krakenjs/belter/src";
+
+import type { Message } from "../types";
+import { MESSAGE_TYPE } from "../../conf";
+import { markWindowKnown, needsGlobalMessagingForBrowser } from "../../lib";
+import { deserializeMessage } from "../../serialize";
+import { getGlobal, globalStore, getGlobalKey } from "../../global";
+import type {
+ OnType,
+ SendType,
+ MessageEvent,
+ CancelableType,
+} from "../../types";
+
+import { handleRequest, handleResponse, handleAck } from "./types";
+
+function deserializeMessages(
+ message: string,
+ source: CrossDomainWindowType,
+ origin: string,
+ { on, send }: {| on: OnType, send: SendType |}
+): ?$ReadOnlyArray {
+ let parsedMessage;
+
+ try {
+ parsedMessage = deserializeMessage(source, origin, message, { on, send });
+ } catch (err) {
+ return;
+ }
+
+ if (!parsedMessage) {
+ return;
+ }
+
+ if (typeof parsedMessage !== "object" || parsedMessage === null) {
+ return;
+ }
+
+ const parseMessages = parsedMessage[getGlobalKey()];
+
+ if (!Array.isArray(parseMessages)) {
+ return;
+ }
+
+ return parseMessages;
+}
-import type { Message } from '../types';
-import { MESSAGE_TYPE } from '../../conf';
-import { markWindowKnown, needsGlobalMessagingForBrowser } from '../../lib';
-import { deserializeMessage } from '../../serialize';
-import { getGlobal, globalStore, getGlobalKey } from '../../global';
-import type { OnType, SendType, MessageEvent, CancelableType } from '../../types';
+export function receiveMessage(
+ event: MessageEvent,
+ { on, send }: {| on: OnType, send: SendType |}
+) {
+ const receivedMessages = globalStore("receivedMessages");
-import { handleRequest, handleResponse, handleAck } from './types';
+ try {
+ if (!window || window.closed || !event.source) {
+ return;
+ }
+ } catch (err) {
+ return;
+ }
-function deserializeMessages(message : string, source : CrossDomainWindowType, origin : string, { on, send } : {| on : OnType, send : SendType |}) : ?$ReadOnlyArray {
- let parsedMessage;
+ let { source, origin, data } = event;
- try {
- parsedMessage = deserializeMessage(source, origin, message, { on, send });
- } catch (err) {
- return;
+ if (__TEST__) {
+ if (isWindowClosed(source)) {
+ return;
}
- if (!parsedMessage) {
- return;
- }
+ // $FlowFixMe
+ origin = getDomain(source);
+ }
- if (typeof parsedMessage !== 'object' || parsedMessage === null) {
- return;
- }
+ const messages = deserializeMessages(data, source, origin, { on, send });
- const parseMessages = parsedMessage[getGlobalKey()];
+ if (!messages) {
+ return;
+ }
- if (!Array.isArray(parseMessages)) {
- return;
+ markWindowKnown(source);
+
+ for (const message of messages) {
+ if (receivedMessages.has(message.id)) {
+ return;
}
- return parseMessages;
-}
+ receivedMessages.set(message.id, true);
+
+ if (isWindowClosed(source) && !message.fireAndForget) {
+ return;
+ }
-export function receiveMessage(event : MessageEvent, { on, send } : {| on : OnType, send : SendType |}) {
- const receivedMessages = globalStore('receivedMessages');
+ if (message.origin.indexOf(PROTOCOL.FILE) === 0) {
+ origin = `${PROTOCOL.FILE}//`;
+ }
try {
- if (!window || window.closed || !event.source) {
- return;
- }
+ if (message.type === MESSAGE_TYPE.REQUEST) {
+ handleRequest(source, origin, message, { on, send });
+ } else if (message.type === MESSAGE_TYPE.RESPONSE) {
+ handleResponse(source, origin, message);
+ } else if (message.type === MESSAGE_TYPE.ACK) {
+ handleAck(source, origin, message);
+ }
} catch (err) {
- return;
+ setTimeout(() => {
+ throw err;
+ }, 0);
}
+ }
+}
- let { source, origin, data } = event;
+export function setupGlobalReceiveMessage({
+ on,
+ send,
+}: {|
+ on: OnType,
+ send: SendType,
+|}) {
+ const global = getGlobal();
+ global.receiveMessage =
+ global.receiveMessage ||
+ ((message) => receiveMessage(message, { on, send }));
+}
- if (__TEST__) {
- if (isWindowClosed(source)) {
- return;
- }
+type ListenerEvent = {|
+ source: CrossDomainWindowType,
+ origin: string,
+ data: string,
+ sourceElement: CrossDomainWindowType,
+ originalEvent?: {| origin: string |},
+|};
- // $FlowFixMe
- origin = getDomain(source);
+export function messageListener(
+ event: ListenerEvent,
+ { on, send }: {| on: OnType, send: SendType |}
+) {
+ ZalgoPromise.try(() => {
+ try {
+ noop(event.source);
+ } catch (err) {
+ return;
}
- const messages = deserializeMessages(data, source, origin, { on, send });
+ const source = event.source || event.sourceElement;
+ let origin =
+ event.origin || (event.originalEvent && event.originalEvent.origin);
+ const data = event.data;
- if (!messages) {
- return;
+ if (origin === "null") {
+ origin = `${PROTOCOL.FILE}//`;
}
- markWindowKnown(source);
-
- for (const message of messages) {
- if (receivedMessages.has(message.id)) {
- return;
- }
-
- receivedMessages.set(message.id, true);
-
- if (isWindowClosed(source) && !message.fireAndForget) {
- return;
- }
-
- if (message.origin.indexOf(PROTOCOL.FILE) === 0) {
- origin = `${ PROTOCOL.FILE }//`;
- }
-
- try {
- if (message.type === MESSAGE_TYPE.REQUEST) {
- handleRequest(source, origin, message, { on, send });
- } else if (message.type === MESSAGE_TYPE.RESPONSE) {
- handleResponse(source, origin, message);
- } else if (message.type === MESSAGE_TYPE.ACK) {
- handleAck(source, origin, message);
- }
- } catch (err) {
- setTimeout(() => {
- throw err;
- }, 0);
- }
+ if (!source) {
+ return;
}
-}
-export function setupGlobalReceiveMessage({ on, send } : {| on : OnType, send : SendType |}) {
- const global = getGlobal();
- global.receiveMessage = global.receiveMessage || (message => receiveMessage(message, { on, send }));
-}
+ if (!origin) {
+ throw new Error(`Post message did not have origin domain`);
+ }
-type ListenerEvent = {|
- source : CrossDomainWindowType,
- origin : string,
- data : string,
- sourceElement : CrossDomainWindowType,
- originalEvent? : {| origin : string |}
-|};
+ if (__TEST__) {
+ if (
+ needsGlobalMessagingForBrowser() &&
+ isSameTopWindow(source, window) === false
+ ) {
+ return;
+ }
+ }
-export function messageListener(event : ListenerEvent, { on, send } : {| on : OnType, send : SendType |}) {
- ZalgoPromise.try(() => {
- try {
- noop(event.source);
- } catch (err) {
- return;
- }
-
- const source = event.source || event.sourceElement;
- let origin = event.origin || (event.originalEvent && event.originalEvent.origin);
- const data = event.data;
-
- if (origin === 'null') {
- origin = `${ PROTOCOL.FILE }//`;
- }
-
- if (!source) {
- return;
- }
-
- if (!origin) {
- throw new Error(`Post message did not have origin domain`);
- }
-
- if (__TEST__) {
- if (needsGlobalMessagingForBrowser() && isSameTopWindow(source, window) === false) {
- return;
- }
- }
-
- receiveMessage({ source, origin, data }, { on, send });
- });
+ receiveMessage({ source, origin, data }, { on, send });
+ });
}
-export function listenForMessages({ on, send } : {| on : OnType, send : SendType |}) : CancelableType {
- return globalStore().getOrSet('postMessageListener', () => {
- return addEventListener(window, 'message', event => {
- // $FlowFixMe
- messageListener(event, { on, send });
- });
+export function listenForMessages({
+ on,
+ send,
+}: {|
+ on: OnType,
+ send: SendType,
+|}): CancelableType {
+ return globalStore().getOrSet("postMessageListener", () => {
+ return addEventListener(window, "message", (event) => {
+ // $FlowFixMe
+ messageListener(event, { on, send });
});
+ });
}
export function stopListenForMessages() {
- const listener = globalStore().get('postMessageListener');
- if (listener) {
- listener.cancel();
- }
+ const listener = globalStore().get("postMessageListener");
+ if (listener) {
+ listener.cancel();
+ }
}
diff --git a/src/drivers/receive/types.js b/src/drivers/receive/types.js
index d6b88dd8..34c9d408 100644
--- a/src/drivers/receive/types.js
+++ b/src/drivers/receive/types.js
@@ -1,171 +1,242 @@
/* @flow */
-import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-import { getDomain, isWindowClosed, matchDomain, stringifyDomainPattern, type CrossDomainWindowType } from '@krakenjs/cross-domain-utils/src';
-import { noop, stringifyError, uniqueID } from '@krakenjs/belter/src';
-
-import { MESSAGE_TYPE, MESSAGE_ACK, MESSAGE_NAME } from '../../conf';
-import { sendMessage } from '../send';
-import { getRequestListener, getResponseListener, deleteResponseListener, isResponseListenerErrored } from '../listeners';
-import type { RequestMessage, AckResponseMessage, ResponseMessage } from '../types';
-import type { OnType, SendType } from '../../types';
-
-export function handleRequest(source : CrossDomainWindowType, origin : string, message : RequestMessage, { on, send } : {| on : OnType, send : SendType |}) : ZalgoPromise {
-
- const options = getRequestListener({ name: message.name, win: source, domain: origin });
-
- const logName = (message.name === MESSAGE_NAME.METHOD && message.data && typeof message.data.name === 'string') ? `${ message.data.name }()` : message.name;
-
- if (__DEBUG__) {
- // eslint-disable-next-line no-console
- console.info('receive::req', logName, origin, '\n\n', message.data);
- }
-
- function sendAck() : ZalgoPromise {
- return ZalgoPromise.flush().then(() => {
- if (message.fireAndForget || isWindowClosed(source)) {
- return;
- }
-
- try {
- return sendMessage(source, origin, {
- id: uniqueID(),
- origin: getDomain(window),
- type: MESSAGE_TYPE.ACK,
- hash: message.hash,
- name: message.name
- }, { on, send });
- } catch (err) {
- throw new Error(`Send ack message failed for ${ logName } in ${ getDomain() }\n\n${ stringifyError(err) }`);
- }
- });
- }
-
-
- function sendResponse(ack : $Values, data : ?Object, error : ?mixed) : ZalgoPromise {
- return ZalgoPromise.flush().then(() => {
- if (message.fireAndForget || isWindowClosed(source)) {
- return;
- }
-
- if (__DEBUG__) {
- if (ack === MESSAGE_ACK.SUCCESS) {
- console.info('respond::res', logName, origin, '\n\n', data); // eslint-disable-line no-console
- } else if (ack === MESSAGE_ACK.ERROR) {
- console.error('respond::err', logName, origin, '\n\n', error); // eslint-disable-line no-console
- }
- }
-
- try {
- return sendMessage(source, origin, {
- id: uniqueID(),
- origin: getDomain(window),
- type: MESSAGE_TYPE.RESPONSE,
- hash: message.hash,
- name: message.name,
- ack,
- data,
- error
- }, { on, send });
- } catch (err) {
- throw new Error(`Send response message failed for ${ logName } in ${ getDomain() }\n\n${ stringifyError(err) }`);
- }
- });
- }
-
-
- return ZalgoPromise.all([
- sendAck(),
-
- ZalgoPromise.try(() => {
-
- if (!options) {
- throw new Error(`No handler found for post message: ${ message.name } from ${ origin } in ${ window.location.protocol }//${ window.location.host }${ window.location.pathname }`);
- }
-
- const data = message.data;
-
- return options.handler({ source, origin, data });
-
- }).then(data => {
- return sendResponse(MESSAGE_ACK.SUCCESS, data);
-
- }, error => {
- return sendResponse(MESSAGE_ACK.ERROR, null, error);
- })
-
- ]).then(noop).catch(err => {
- if (options && options.handleError) {
- return options.handleError(err);
- } else {
- throw err;
- }
+import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+import {
+ getDomain,
+ isWindowClosed,
+ matchDomain,
+ stringifyDomainPattern,
+ type CrossDomainWindowType,
+} from "@krakenjs/cross-domain-utils/src";
+import { noop, stringifyError, uniqueID } from "@krakenjs/belter/src";
+
+import { MESSAGE_TYPE, MESSAGE_ACK, MESSAGE_NAME } from "../../conf";
+import { sendMessage } from "../send";
+import {
+ getRequestListener,
+ getResponseListener,
+ deleteResponseListener,
+ isResponseListenerErrored,
+} from "../listeners";
+import type {
+ RequestMessage,
+ AckResponseMessage,
+ ResponseMessage,
+} from "../types";
+import type { OnType, SendType } from "../../types";
+
+export function handleRequest(
+ source: CrossDomainWindowType,
+ origin: string,
+ message: RequestMessage,
+ { on, send }: {| on: OnType, send: SendType |}
+): ZalgoPromise {
+ const options = getRequestListener({
+ name: message.name,
+ win: source,
+ domain: origin,
+ });
+
+ const logName =
+ message.name === MESSAGE_NAME.METHOD &&
+ message.data &&
+ typeof message.data.name === "string"
+ ? `${message.data.name}()`
+ : message.name;
+
+ if (__DEBUG__) {
+ // eslint-disable-next-line no-console
+ console.info("receive::req", logName, origin, "\n\n", message.data);
+ }
+
+ function sendAck(): ZalgoPromise {
+ return ZalgoPromise.flush().then(() => {
+ if (message.fireAndForget || isWindowClosed(source)) {
+ return;
+ }
+
+ try {
+ return sendMessage(
+ source,
+ origin,
+ {
+ id: uniqueID(),
+ origin: getDomain(window),
+ type: MESSAGE_TYPE.ACK,
+ hash: message.hash,
+ name: message.name,
+ },
+ { on, send }
+ );
+ } catch (err) {
+ throw new Error(
+ `Send ack message failed for ${logName} in ${getDomain()}\n\n${stringifyError(
+ err
+ )}`
+ );
+ }
});
-}
-
-export function handleAck(source : CrossDomainWindowType, origin : string, message : AckResponseMessage) {
-
- if (isResponseListenerErrored(message.hash)) {
+ }
+
+ function sendResponse(
+ ack: $Values,
+ data: ?Object,
+ error: ?mixed
+ ): ZalgoPromise {
+ return ZalgoPromise.flush().then(() => {
+ if (message.fireAndForget || isWindowClosed(source)) {
return;
- }
-
- const options = getResponseListener(message.hash);
+ }
- if (!options) {
- throw new Error(`No handler found for post message ack for message: ${ message.name } from ${ origin } in ${ window.location.protocol }//${ window.location.host }${ window.location.pathname }`);
- }
-
- try {
- if (!matchDomain(options.domain, origin)) {
- throw new Error(`Ack origin ${ origin } does not match domain ${ options.domain.toString() }`);
- }
-
- if (source !== options.win) {
- throw new Error(`Ack source does not match registered window`);
+ if (__DEBUG__) {
+ if (ack === MESSAGE_ACK.SUCCESS) {
+ console.info("respond::res", logName, origin, "\n\n", data); // eslint-disable-line no-console
+ } else if (ack === MESSAGE_ACK.ERROR) {
+ console.error("respond::err", logName, origin, "\n\n", error); // eslint-disable-line no-console
}
- } catch (err) {
- options.promise.reject(err);
- }
-
- options.ack = true;
+ }
+
+ try {
+ return sendMessage(
+ source,
+ origin,
+ {
+ id: uniqueID(),
+ origin: getDomain(window),
+ type: MESSAGE_TYPE.RESPONSE,
+ hash: message.hash,
+ name: message.name,
+ ack,
+ data,
+ error,
+ },
+ { on, send }
+ );
+ } catch (err) {
+ throw new Error(
+ `Send response message failed for ${logName} in ${getDomain()}\n\n${stringifyError(
+ err
+ )}`
+ );
+ }
+ });
+ }
+
+ return ZalgoPromise.all([
+ sendAck(),
+
+ ZalgoPromise.try(() => {
+ if (!options) {
+ throw new Error(
+ `No handler found for post message: ${message.name} from ${origin} in ${window.location.protocol}//${window.location.host}${window.location.pathname}`
+ );
+ }
+
+ const data = message.data;
+
+ return options.handler({ source, origin, data });
+ }).then(
+ (data) => {
+ return sendResponse(MESSAGE_ACK.SUCCESS, data);
+ },
+ (error) => {
+ return sendResponse(MESSAGE_ACK.ERROR, null, error);
+ }
+ ),
+ ])
+ .then(noop)
+ .catch((err) => {
+ if (options && options.handleError) {
+ return options.handleError(err);
+ } else {
+ throw err;
+ }
+ });
}
-export function handleResponse(source : CrossDomainWindowType, origin : string, message : ResponseMessage) : void | ZalgoPromise {
-
- if (isResponseListenerErrored(message.hash)) {
- return;
- }
+export function handleAck(
+ source: CrossDomainWindowType,
+ origin: string,
+ message: AckResponseMessage
+) {
+ if (isResponseListenerErrored(message.hash)) {
+ return;
+ }
- const options = getResponseListener(message.hash);
+ const options = getResponseListener(message.hash);
- if (!options) {
- throw new Error(`No handler found for post message response for message: ${ message.name } from ${ origin } in ${ window.location.protocol }//${ window.location.host }${ window.location.pathname }`);
- }
+ if (!options) {
+ throw new Error(
+ `No handler found for post message ack for message: ${message.name} from ${origin} in ${window.location.protocol}//${window.location.host}${window.location.pathname}`
+ );
+ }
+ try {
if (!matchDomain(options.domain, origin)) {
- throw new Error(`Response origin ${ origin } does not match domain ${ stringifyDomainPattern(options.domain) }`);
+ throw new Error(
+ `Ack origin ${origin} does not match domain ${options.domain.toString()}`
+ );
}
if (source !== options.win) {
- throw new Error(`Response source does not match registered window`);
+ throw new Error(`Ack source does not match registered window`);
}
+ } catch (err) {
+ options.promise.reject(err);
+ }
- deleteResponseListener(message.hash);
-
- const logName = (message.name === MESSAGE_NAME.METHOD && message.data && typeof message.data.name === 'string') ? `${ message.data.name }()` : message.name;
-
- if (message.ack === MESSAGE_ACK.ERROR) {
- if (__DEBUG__) {
- console.error('receive::err', logName, origin, '\n\n', message.error); // eslint-disable-line no-console
- }
-
- options.promise.reject(message.error);
+ options.ack = true;
+}
- } else if (message.ack === MESSAGE_ACK.SUCCESS) {
- if (__DEBUG__) {
- console.info('receive::res', logName, origin, '\n\n', message.data); // eslint-disable-line no-console
- }
+export function handleResponse(
+ source: CrossDomainWindowType,
+ origin: string,
+ message: ResponseMessage
+): void | ZalgoPromise {
+ if (isResponseListenerErrored(message.hash)) {
+ return;
+ }
+
+ const options = getResponseListener(message.hash);
+
+ if (!options) {
+ throw new Error(
+ `No handler found for post message response for message: ${message.name} from ${origin} in ${window.location.protocol}//${window.location.host}${window.location.pathname}`
+ );
+ }
+
+ if (!matchDomain(options.domain, origin)) {
+ throw new Error(
+ `Response origin ${origin} does not match domain ${stringifyDomainPattern(
+ options.domain
+ )}`
+ );
+ }
+
+ if (source !== options.win) {
+ throw new Error(`Response source does not match registered window`);
+ }
+
+ deleteResponseListener(message.hash);
+
+ const logName =
+ message.name === MESSAGE_NAME.METHOD &&
+ message.data &&
+ typeof message.data.name === "string"
+ ? `${message.data.name}()`
+ : message.name;
+
+ if (message.ack === MESSAGE_ACK.ERROR) {
+ if (__DEBUG__) {
+ console.error("receive::err", logName, origin, "\n\n", message.error); // eslint-disable-line no-console
+ }
- options.promise.resolve({ source, origin, data: message.data });
+ options.promise.reject(message.error);
+ } else if (message.ack === MESSAGE_ACK.SUCCESS) {
+ if (__DEBUG__) {
+ console.info("receive::res", logName, origin, "\n\n", message.data); // eslint-disable-line no-console
}
+
+ options.promise.resolve({ source, origin, data: message.data });
+ }
}
diff --git a/src/drivers/send/index.js b/src/drivers/send/index.js
index 21f42277..25ea4e9b 100644
--- a/src/drivers/send/index.js
+++ b/src/drivers/send/index.js
@@ -1,57 +1,80 @@
/* @flow */
-import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-import { isWindowClosed, type CrossDomainWindowType } from '@krakenjs/cross-domain-utils/src';
-import { stringifyError, noop } from '@krakenjs/belter/src';
+import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+import {
+ isWindowClosed,
+ type CrossDomainWindowType,
+} from "@krakenjs/cross-domain-utils/src";
+import { stringifyError, noop } from "@krakenjs/belter/src";
-import { serializeMessage } from '../../serialize';
-import { windowStore, getGlobalKey } from '../../global';
-import type { Message, PackedMessages } from '../types';
-import type { OnType, SendType } from '../../types';
+import { serializeMessage } from "../../serialize";
+import { windowStore, getGlobalKey } from "../../global";
+import type { Message, PackedMessages } from "../types";
+import type { OnType, SendType } from "../../types";
-import { SEND_MESSAGE_STRATEGIES } from './strategies';
+import { SEND_MESSAGE_STRATEGIES } from "./strategies";
-function packMessages(messages : $ReadOnlyArray) : PackedMessages {
- return {
- [ getGlobalKey() ]: messages
- };
+function packMessages(messages: $ReadOnlyArray): PackedMessages {
+ return {
+ [getGlobalKey()]: messages,
+ };
}
-export function sendMessage(win : CrossDomainWindowType, domain : string, message : Message, { on, send } : {| on : OnType, send : SendType |}) : ZalgoPromise {
- return ZalgoPromise.try(() => {
- const messageBuffer = windowStore();
+export function sendMessage(
+ win: CrossDomainWindowType,
+ domain: string,
+ message: Message,
+ { on, send }: {| on: OnType, send: SendType |}
+): ZalgoPromise {
+ return ZalgoPromise.try(() => {
+ const messageBuffer = windowStore();
- const domainBuffer = messageBuffer.getOrSet(win, () => ({}));
+ const domainBuffer = messageBuffer.getOrSet(win, () => ({}));
- domainBuffer.buffer = domainBuffer.buffer || [];
- domainBuffer.buffer.push(message);
+ domainBuffer.buffer = domainBuffer.buffer || [];
+ domainBuffer.buffer.push(message);
- domainBuffer.flush = domainBuffer.flush || ZalgoPromise.flush().then(() => {
- if (isWindowClosed(win)) {
- throw new Error('Window is closed');
- }
+ domainBuffer.flush =
+ domainBuffer.flush ||
+ ZalgoPromise.flush().then(() => {
+ if (isWindowClosed(win)) {
+ throw new Error("Window is closed");
+ }
- const serializedMessage = serializeMessage(win, domain, packMessages(domainBuffer.buffer || []), { on, send });
- delete domainBuffer.buffer;
+ const serializedMessage = serializeMessage(
+ win,
+ domain,
+ packMessages(domainBuffer.buffer || []),
+ { on, send }
+ );
+ delete domainBuffer.buffer;
- const strategies = Object.keys(SEND_MESSAGE_STRATEGIES);
- const errors = [];
+ const strategies = Object.keys(SEND_MESSAGE_STRATEGIES);
+ const errors = [];
- for (const strategyName of strategies) {
- try {
- SEND_MESSAGE_STRATEGIES[strategyName](win, serializedMessage, domain);
- } catch (err) {
- errors.push(err);
- }
- }
+ for (const strategyName of strategies) {
+ try {
+ SEND_MESSAGE_STRATEGIES[strategyName](
+ win,
+ serializedMessage,
+ domain
+ );
+ } catch (err) {
+ errors.push(err);
+ }
+ }
- if (errors.length === strategies.length) {
- throw new Error(`All post-robot messaging strategies failed:\n\n${ errors.map((err, i) => `${ i }. ${ stringifyError(err) }`).join('\n\n') }`);
- }
- });
+ if (errors.length === strategies.length) {
+ throw new Error(
+ `All post-robot messaging strategies failed:\n\n${errors
+ .map((err, i) => `${i}. ${stringifyError(err)}`)
+ .join("\n\n")}`
+ );
+ }
+ });
- return domainBuffer.flush.then(() => {
- delete domainBuffer.flush;
- });
- }).then(noop);
+ return domainBuffer.flush.then(() => {
+ delete domainBuffer.flush;
+ });
+ }).then(noop);
}
diff --git a/src/drivers/send/strategies.js b/src/drivers/send/strategies.js
index cef4bd5d..35410293 100644
--- a/src/drivers/send/strategies.js
+++ b/src/drivers/send/strategies.js
@@ -1,97 +1,136 @@
/* @flow */
-import { isSameDomain, isSameTopWindow, isActuallySameDomain, getActualDomain,
- getDomain, type CrossDomainWindowType, PROTOCOL } from '@krakenjs/cross-domain-utils/src';
-
-import { SEND_STRATEGY, WILDCARD } from '../../conf';
-import { needsGlobalMessagingForBrowser } from '../../lib';
-import { getGlobal } from '../../global';
-import { sendBridgeMessage, needsBridgeForBrowser, isBridge } from '../../bridge';
+import {
+ isSameDomain,
+ isSameTopWindow,
+ isActuallySameDomain,
+ getActualDomain,
+ getDomain,
+ type CrossDomainWindowType,
+ PROTOCOL,
+} from "@krakenjs/cross-domain-utils/src";
+
+import { SEND_STRATEGY, WILDCARD } from "../../conf";
+import { needsGlobalMessagingForBrowser } from "../../lib";
+import { getGlobal } from "../../global";
+import {
+ sendBridgeMessage,
+ needsBridgeForBrowser,
+ isBridge,
+} from "../../bridge";
type SendStrategies = {|
- [$Values] : (CrossDomainWindowType, string, string) => void
+ [$Values]: (
+ CrossDomainWindowType,
+ string,
+ string
+ ) => void,
|};
-export const SEND_MESSAGE_STRATEGIES : SendStrategies = {};
-
-SEND_MESSAGE_STRATEGIES[SEND_STRATEGY.POST_MESSAGE] = (win : CrossDomainWindowType, serializedMessage : string, domain : string) => {
- if (domain.indexOf(PROTOCOL.FILE) === 0) {
- domain = WILDCARD;
+export const SEND_MESSAGE_STRATEGIES: SendStrategies = {};
+
+SEND_MESSAGE_STRATEGIES[SEND_STRATEGY.POST_MESSAGE] = (
+ win: CrossDomainWindowType,
+ serializedMessage: string,
+ domain: string
+) => {
+ if (domain.indexOf(PROTOCOL.FILE) === 0) {
+ domain = WILDCARD;
+ }
+
+ if (__TEST__) {
+ if (
+ needsGlobalMessagingForBrowser() &&
+ isSameTopWindow(window, win) === false
+ ) {
+ return;
}
- if (__TEST__) {
- if (needsGlobalMessagingForBrowser() && isSameTopWindow(window, win) === false) {
- return;
- }
+ if (domain.indexOf(PROTOCOL.MOCK) === 0) {
+ if (!isActuallySameDomain(win)) {
+ throw new Error(
+ `Attempting to send message to mock domain ${domain}, but window is actually cross-domain`
+ );
+ }
- if (domain.indexOf(PROTOCOL.MOCK) === 0) {
- if (!isActuallySameDomain(win)) {
- throw new Error(`Attempting to send message to mock domain ${ domain }, but window is actually cross-domain`);
- }
+ // $FlowFixMe
+ const windowDomain = getDomain(win);
- // $FlowFixMe
- const windowDomain = getDomain(win);
-
- if (windowDomain !== domain) {
- throw new Error(`Mock domain target ${ domain } does not match window domain ${ windowDomain }`);
- }
+ if (windowDomain !== domain) {
+ throw new Error(
+ `Mock domain target ${domain} does not match window domain ${windowDomain}`
+ );
+ }
- // $FlowFixMe
- domain = getActualDomain(win);
-
- }
+ // $FlowFixMe
+ domain = getActualDomain(win);
}
+ }
- win.postMessage(serializedMessage, domain);
+ win.postMessage(serializedMessage, domain);
};
if (__POST_ROBOT__.__IE_POPUP_SUPPORT__) {
+ SEND_MESSAGE_STRATEGIES[SEND_STRATEGY.BRIDGE] = (
+ win: CrossDomainWindowType,
+ serializedMessage: string,
+ domain: string
+ ) => {
+ if (!needsBridgeForBrowser() && !isBridge()) {
+ throw new Error(`Bridge not needed for browser`);
+ }
- SEND_MESSAGE_STRATEGIES[SEND_STRATEGY.BRIDGE] = (win : CrossDomainWindowType, serializedMessage : string, domain : string) => {
-
- if (!needsBridgeForBrowser() && !isBridge()) {
- throw new Error(`Bridge not needed for browser`);
- }
-
- if (isSameDomain(win)) {
- throw new Error(`Post message through bridge disabled between same domain windows`);
- }
+ if (isSameDomain(win)) {
+ throw new Error(
+ `Post message through bridge disabled between same domain windows`
+ );
+ }
- if (isSameTopWindow(window, win) !== false) {
- throw new Error(`Can only use bridge to communicate between two different windows, not between frames`);
- }
+ if (isSameTopWindow(window, win) !== false) {
+ throw new Error(
+ `Can only use bridge to communicate between two different windows, not between frames`
+ );
+ }
- sendBridgeMessage(win, domain, serializedMessage);
- };
+ sendBridgeMessage(win, domain, serializedMessage);
+ };
}
-if (__POST_ROBOT__.__IE_POPUP_SUPPORT__ || __POST_ROBOT__.__GLOBAL_MESSAGE_SUPPORT__) {
-
- SEND_MESSAGE_STRATEGIES[SEND_STRATEGY.GLOBAL] = (win : CrossDomainWindowType, serializedMessage : string) => {
-
- if (!needsGlobalMessagingForBrowser()) {
- throw new Error(`Global messaging not needed for browser`);
- }
+if (
+ __POST_ROBOT__.__IE_POPUP_SUPPORT__ ||
+ __POST_ROBOT__.__GLOBAL_MESSAGE_SUPPORT__
+) {
+ SEND_MESSAGE_STRATEGIES[SEND_STRATEGY.GLOBAL] = (
+ win: CrossDomainWindowType,
+ serializedMessage: string
+ ) => {
+ if (!needsGlobalMessagingForBrowser()) {
+ throw new Error(`Global messaging not needed for browser`);
+ }
- if (!isSameDomain(win)) {
- throw new Error(`Post message through global disabled between different domain windows`);
- }
+ if (!isSameDomain(win)) {
+ throw new Error(
+ `Post message through global disabled between different domain windows`
+ );
+ }
- if (isSameTopWindow(window, win) !== false) {
- throw new Error(`Can only use global to communicate between two different windows, not between frames`);
- }
+ if (isSameTopWindow(window, win) !== false) {
+ throw new Error(
+ `Can only use global to communicate between two different windows, not between frames`
+ );
+ }
- // $FlowFixMe
- const foreignGlobal = getGlobal(win);
+ // $FlowFixMe
+ const foreignGlobal = getGlobal(win);
- if (!foreignGlobal) {
- throw new Error(`Can not find postRobot global on foreign window`);
- }
+ if (!foreignGlobal) {
+ throw new Error(`Can not find postRobot global on foreign window`);
+ }
- foreignGlobal.receiveMessage({
- source: window,
- origin: getDomain(),
- data: serializedMessage
- });
- };
+ foreignGlobal.receiveMessage({
+ source: window,
+ origin: getDomain(),
+ data: serializedMessage,
+ });
+ };
}
diff --git a/src/drivers/types.js b/src/drivers/types.js
index f6b80b45..dbb5a92a 100644
--- a/src/drivers/types.js
+++ b/src/drivers/types.js
@@ -1,38 +1,38 @@
/* @flow */
-import { MESSAGE_TYPE, MESSAGE_ACK } from '../conf';
+import { MESSAGE_TYPE, MESSAGE_ACK } from "../conf";
export type RequestMessage = {|
- id : string,
- origin : string,
- type : typeof MESSAGE_TYPE.REQUEST,
- name : string,
- hash : string,
- data : mixed,
- fireAndForget? : boolean
+ id: string,
+ origin: string,
+ type: typeof MESSAGE_TYPE.REQUEST,
+ name: string,
+ hash: string,
+ data: mixed,
+ fireAndForget?: boolean,
|};
export type AckResponseMessage = {|
- id : string,
- origin : string,
- type : typeof MESSAGE_TYPE.ACK,
- name : string,
- hash : string
+ id: string,
+ origin: string,
+ type: typeof MESSAGE_TYPE.ACK,
+ name: string,
+ hash: string,
|};
export type ResponseMessage = {|
- id : string,
- origin : string,
- type : typeof MESSAGE_TYPE.RESPONSE,
- ack : $Values,
- name : string,
- hash : string,
- data : ?mixed,
- error : ?mixed
+ id: string,
+ origin: string,
+ type: typeof MESSAGE_TYPE.RESPONSE,
+ ack: $Values,
+ name: string,
+ hash: string,
+ data: ?mixed,
+ error: ?mixed,
|};
export type Message = RequestMessage | AckResponseMessage | ResponseMessage;
export type PackedMessages = {|
- [ typeof __POST_ROBOT__.__GLOBAL_KEY__ ] : $ReadOnlyArray
+ [typeof __POST_ROBOT__.__GLOBAL_KEY__]: $ReadOnlyArray,
|};
diff --git a/src/global.js b/src/global.js
index 7dab3fe8..d1e7dff5 100644
--- a/src/global.js
+++ b/src/global.js
@@ -1,127 +1,137 @@
/* @flow */
-import { type CrossDomainWindowType, type SameDomainWindowType } from '@krakenjs/cross-domain-utils/src';
-import { WeakMap } from '@krakenjs/cross-domain-safe-weakmap/src';
-import { getOrSet, getCurrentScriptUID } from '@krakenjs/belter/src';
-
-export function getGlobalKey() : string {
- if (__POST_ROBOT__.__SCRIPT_NAMESPACE__) {
- return `${ __POST_ROBOT__.__GLOBAL_KEY__ }_${ getCurrentScriptUID() }`;
- } else {
- return __POST_ROBOT__.__GLOBAL_KEY__;
- }
+import {
+ type CrossDomainWindowType,
+ type SameDomainWindowType,
+} from "@krakenjs/cross-domain-utils/src";
+import { WeakMap } from "@krakenjs/cross-domain-safe-weakmap/src";
+import { getOrSet, getCurrentScriptUID } from "@krakenjs/belter/src";
+
+export function getGlobalKey(): string {
+ if (__POST_ROBOT__.__SCRIPT_NAMESPACE__) {
+ return `${__POST_ROBOT__.__GLOBAL_KEY__}_${getCurrentScriptUID()}`;
+ } else {
+ return __POST_ROBOT__.__GLOBAL_KEY__;
+ }
}
-export function getGlobal(win : SameDomainWindowType = window) : Object {
- const globalKey = getGlobalKey();
+export function getGlobal(win: SameDomainWindowType = window): Object {
+ const globalKey = getGlobalKey();
- if (win !== window) {
- return win[globalKey];
- }
- const global : Object = win[globalKey] = win[globalKey] || {};
- return global;
+ if (win !== window) {
+ return win[globalKey];
+ }
+ const global: Object = (win[globalKey] = win[globalKey] || {});
+ return global;
}
export function deleteGlobal() {
- const globalKey = getGlobalKey();
- delete window[globalKey];
+ const globalKey = getGlobalKey();
+ delete window[globalKey];
}
type ObjectGetter = () => Object;
-const getObj : ObjectGetter = () => ({});
+const getObj: ObjectGetter = () => ({});
type GetOrSet = ((string, () => T) => T) & ((string, () => void) => void);
type GlobalStore = {|
- get : ((string, T) => T) & ((string, void) => T | void),
- set : (string, T) => T,
- has : (string) => boolean,
- del : (string) => void,
- getOrSet : GetOrSet,
- reset : () => void,
- keys : () => $ReadOnlyArray
+ get: ((string, T) => T) & ((string, void) => T | void),
+ set: (string, T) => T,
+ has: (string) => boolean,
+ del: (string) => void,
+ getOrSet: GetOrSet,
+ reset: () => void,
+ keys: () => $ReadOnlyArray,
|};
-export function globalStore(key? : string = 'store', defStore? : ObjectGetter = getObj) : GlobalStore {
- return getOrSet(getGlobal(), key, () => {
- let store = defStore();
-
- return {
- has: (storeKey) => {
- return store.hasOwnProperty(storeKey);
- },
- get: (storeKey, defVal) => {
- // $FlowFixMe
- return store.hasOwnProperty(storeKey) ? store[storeKey] : defVal;
- },
- set: (storeKey, val) => {
- store[storeKey] = val;
- return val;
- },
- del: (storeKey) => {
- delete store[storeKey];
- },
- getOrSet: (storeKey, getter) => {
- // $FlowFixMe
- return getOrSet(store, storeKey, getter);
- },
- reset: () => {
- store = defStore();
- },
- keys: () => {
- return Object.keys(store);
- }
- };
- });
+export function globalStore(
+ key?: string = "store",
+ defStore?: ObjectGetter = getObj
+): GlobalStore {
+ return getOrSet(getGlobal(), key, () => {
+ let store = defStore();
+
+ return {
+ has: (storeKey) => {
+ return store.hasOwnProperty(storeKey);
+ },
+ get: (storeKey, defVal) => {
+ // $FlowFixMe
+ return store.hasOwnProperty(storeKey) ? store[storeKey] : defVal;
+ },
+ set: (storeKey, val) => {
+ store[storeKey] = val;
+ return val;
+ },
+ del: (storeKey) => {
+ delete store[storeKey];
+ },
+ getOrSet: (storeKey, getter) => {
+ // $FlowFixMe
+ return getOrSet(store, storeKey, getter);
+ },
+ reset: () => {
+ store = defStore();
+ },
+ keys: () => {
+ return Object.keys(store);
+ },
+ };
+ });
}
export class WildCard {}
-export function getWildcard() : WildCard {
- const global = getGlobal();
- global.WINDOW_WILDCARD = global.WINDOW_WILDCARD || new WildCard();
- return global.WINDOW_WILDCARD;
+export function getWildcard(): WildCard {
+ const global = getGlobal();
+ global.WINDOW_WILDCARD = global.WINDOW_WILDCARD || new WildCard();
+ return global.WINDOW_WILDCARD;
}
type WindowStore = {|
- get : ((CrossDomainWindowType | WildCard, T) => T) & ((CrossDomainWindowType | WildCard, void) => T | void),
- set : (CrossDomainWindowType | WildCard, T) => T,
- has : (CrossDomainWindowType | WildCard) => boolean,
- del : (CrossDomainWindowType | WildCard) => void,
- getOrSet : (CrossDomainWindowType | WildCard, () => T) => T
+ get: ((CrossDomainWindowType | WildCard, T) => T) &
+ ((CrossDomainWindowType | WildCard, void) => T | void),
+ set: (CrossDomainWindowType | WildCard, T) => T,
+ has: (CrossDomainWindowType | WildCard) => boolean,
+ del: (CrossDomainWindowType | WildCard) => void,
+ getOrSet: (CrossDomainWindowType | WildCard, () => T) => T,
|};
-export function windowStore(key? : string = 'store', defStore? : ObjectGetter = getObj) : WindowStore {
- return globalStore('windowStore').getOrSet(key, () => {
- const winStore = new WeakMap();
-
- const getStore = (win : CrossDomainWindowType | WildCard) : ObjectGetter => {
- return winStore.getOrSet(win, defStore);
- };
-
- return {
- has: (win) => {
- const store = getStore(win);
- return store.hasOwnProperty(key);
- },
- get: (win, defVal) => {
- const store = getStore(win);
- // $FlowFixMe
- return store.hasOwnProperty(key) ? store[key] : defVal;
- },
- set: (win, val) => {
- const store = getStore(win);
- store[key] = val;
- return val;
- },
- del: (win) => {
- const store = getStore(win);
- delete store[key];
- },
- getOrSet: (win, getter) => {
- const store = getStore(win);
- return getOrSet(store, key, getter);
- }
- };
- });
+export function windowStore(
+ key?: string = "store",
+ defStore?: ObjectGetter = getObj
+): WindowStore {
+ return globalStore("windowStore").getOrSet(key, () => {
+ const winStore = new WeakMap();
+
+ const getStore = (win: CrossDomainWindowType | WildCard): ObjectGetter => {
+ return winStore.getOrSet(win, defStore);
+ };
+
+ return {
+ has: (win) => {
+ const store = getStore(win);
+ return store.hasOwnProperty(key);
+ },
+ get: (win, defVal) => {
+ const store = getStore(win);
+ // $FlowFixMe
+ return store.hasOwnProperty(key) ? store[key] : defVal;
+ },
+ set: (win, val) => {
+ const store = getStore(win);
+ store[key] = val;
+ return val;
+ },
+ del: (win) => {
+ const store = getStore(win);
+ delete store[key];
+ },
+ getOrSet: (win, getter) => {
+ const store = getStore(win);
+ return getOrSet(store, key, getter);
+ },
+ };
+ });
}
diff --git a/src/index.js b/src/index.js
index 9329af0a..bc68e2e1 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,26 +1,55 @@
/* @flow */
-import { setup } from './setup';
-import { setupBridge, openBridge, linkWindow, linkUrl, isBridge, needsBridge, needsBridgeForBrowser, hasBridge,
- needsBridgeForWin, needsBridgeForDomain, destroyBridges } from './bridge';
+import { setup } from "./setup";
+import {
+ setupBridge,
+ openBridge,
+ linkWindow,
+ linkUrl,
+ isBridge,
+ needsBridge,
+ needsBridgeForBrowser,
+ hasBridge,
+ needsBridgeForWin,
+ needsBridgeForDomain,
+ destroyBridges,
+} from "./bridge";
-export { ZalgoPromise as Promise } from '@krakenjs/zalgo-promise/src';
+export { ZalgoPromise as Promise } from "@krakenjs/zalgo-promise/src";
-export * from './types';
-export { ProxyWindow } from './serialize';
-export { setup, destroy, serializeMessage, deserializeMessage, createProxyWindow, toProxyWindow } from './setup';
-export { on, once, send } from './public';
-export { markWindowKnown } from './lib';
-export { cleanUpWindow } from './clean';
+export * from "./types";
+export { ProxyWindow } from "./serialize";
+export {
+ setup,
+ destroy,
+ serializeMessage,
+ deserializeMessage,
+ createProxyWindow,
+ toProxyWindow,
+} from "./setup";
+export { on, once, send } from "./public";
+export { markWindowKnown } from "./lib";
+export { cleanUpWindow } from "./clean";
// $FlowFixMe
export let bridge;
if (__POST_ROBOT__.__IE_POPUP_SUPPORT__) {
- bridge = { setupBridge, openBridge, linkWindow, linkUrl, isBridge, needsBridge,
- needsBridgeForBrowser, hasBridge, needsBridgeForWin, needsBridgeForDomain, destroyBridges };
+ bridge = {
+ setupBridge,
+ openBridge,
+ linkWindow,
+ linkUrl,
+ isBridge,
+ needsBridge,
+ needsBridgeForBrowser,
+ hasBridge,
+ needsBridgeForWin,
+ needsBridgeForDomain,
+ destroyBridges,
+ };
}
if (__POST_ROBOT__.__AUTO_SETUP__) {
- setup();
+ setup();
}
diff --git a/src/lib/compat.js b/src/lib/compat.js
index b4b3bbc1..a33fd880 100644
--- a/src/lib/compat.js
+++ b/src/lib/compat.js
@@ -1,12 +1,11 @@
/* @flow */
-import { getUserAgent } from '@krakenjs/cross-domain-utils/src';
+import { getUserAgent } from "@krakenjs/cross-domain-utils/src";
-export function needsGlobalMessagingForBrowser() : boolean {
+export function needsGlobalMessagingForBrowser(): boolean {
+ if (getUserAgent(window).match(/MSIE|rv:11|trident|edge\/12|edge\/13/i)) {
+ return true;
+ }
- if (getUserAgent(window).match(/MSIE|rv:11|trident|edge\/12|edge\/13/i)) {
- return true;
- }
-
- return false;
+ return false;
}
diff --git a/src/lib/hello.js b/src/lib/hello.js
index ad7ddb1c..9e209e99 100644
--- a/src/lib/hello.js
+++ b/src/lib/hello.js
@@ -1,78 +1,113 @@
/* @flow */
-import { getAncestor, type CrossDomainWindowType } from '@krakenjs/cross-domain-utils/src';
-import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-import { uniqueID } from '@krakenjs/belter/src';
+import {
+ getAncestor,
+ type CrossDomainWindowType,
+} from "@krakenjs/cross-domain-utils/src";
+import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+import { uniqueID } from "@krakenjs/belter/src";
-import { MESSAGE_NAME, WILDCARD } from '../conf';
-import { windowStore, globalStore, getGlobal } from '../global';
-import type { OnType, SendType, CancelableType } from '../types';
+import { MESSAGE_NAME, WILDCARD } from "../conf";
+import { windowStore, globalStore, getGlobal } from "../global";
+import type { OnType, SendType, CancelableType } from "../types";
-function getInstanceID() : string {
- return globalStore('instance').getOrSet('instanceID', uniqueID);
+function getInstanceID(): string {
+ return globalStore("instance").getOrSet("instanceID", uniqueID);
}
-function getHelloPromise(win : CrossDomainWindowType) : ZalgoPromise<{| domain : string |}> {
- const helloPromises = windowStore('helloPromises');
- return helloPromises.getOrSet(win, () => new ZalgoPromise());
+function getHelloPromise(
+ win: CrossDomainWindowType
+): ZalgoPromise<{| domain: string |}> {
+ const helloPromises = windowStore("helloPromises");
+ return helloPromises.getOrSet(win, () => new ZalgoPromise());
}
-function resolveHelloPromise(win : CrossDomainWindowType, { domain }) : ZalgoPromise<{| domain : string |}> {
- const helloPromises = windowStore('helloPromises');
- const existingPromise = helloPromises.get(win);
- if (existingPromise) {
- existingPromise.resolve({ domain });
- }
- const newPromise = ZalgoPromise.resolve({ domain });
- helloPromises.set(win, newPromise);
- return newPromise;
+function resolveHelloPromise(
+ win: CrossDomainWindowType,
+ { domain }
+): ZalgoPromise<{| domain: string |}> {
+ const helloPromises = windowStore("helloPromises");
+ const existingPromise = helloPromises.get(win);
+ if (existingPromise) {
+ existingPromise.resolve({ domain });
+ }
+ const newPromise = ZalgoPromise.resolve({ domain });
+ helloPromises.set(win, newPromise);
+ return newPromise;
}
-function listenForHello({ on } : {| on : OnType |}) : CancelableType {
- return on(MESSAGE_NAME.HELLO, { domain: WILDCARD }, ({ source, origin }) => {
- resolveHelloPromise(source, { domain: origin });
- return { instanceID: getInstanceID() };
- });
+function listenForHello({ on }: {| on: OnType |}): CancelableType {
+ return on(MESSAGE_NAME.HELLO, { domain: WILDCARD }, ({ source, origin }) => {
+ resolveHelloPromise(source, { domain: origin });
+ return { instanceID: getInstanceID() };
+ });
}
-export function sayHello(win : CrossDomainWindowType, { send } : {| send : SendType |}) : ZalgoPromise<{| win : CrossDomainWindowType, domain : string, instanceID : string |}> {
- return send(win, MESSAGE_NAME.HELLO, { instanceID: getInstanceID() }, { domain: WILDCARD, timeout: -1 })
- .then(({ origin, data: { instanceID } }) => {
- resolveHelloPromise(win, { domain: origin });
- return { win, domain: origin, instanceID };
- });
+export function sayHello(
+ win: CrossDomainWindowType,
+ { send }: {| send: SendType |}
+): ZalgoPromise<{|
+ win: CrossDomainWindowType,
+ domain: string,
+ instanceID: string,
+|}> {
+ return send(
+ win,
+ MESSAGE_NAME.HELLO,
+ { instanceID: getInstanceID() },
+ { domain: WILDCARD, timeout: -1 }
+ ).then(({ origin, data: { instanceID } }) => {
+ resolveHelloPromise(win, { domain: origin });
+ return { win, domain: origin, instanceID };
+ });
}
-export function getWindowInstanceID(win : CrossDomainWindowType, { send } : {| send : SendType |}) : ZalgoPromise {
- return windowStore('windowInstanceIDPromises').getOrSet(win, () => {
- return sayHello(win, { send }).then(({ instanceID }) => instanceID);
- });
+export function getWindowInstanceID(
+ win: CrossDomainWindowType,
+ { send }: {| send: SendType |}
+): ZalgoPromise {
+ return windowStore("windowInstanceIDPromises").getOrSet(win, () => {
+ return sayHello(win, { send }).then(({ instanceID }) => instanceID);
+ });
}
-export function initHello({ on, send } : {| on : OnType, send : SendType |}) : CancelableType {
- return globalStore('builtinListeners').getOrSet('helloListener', () => {
- const listener = listenForHello({ on });
+export function initHello({
+ on,
+ send,
+}: {|
+ on: OnType,
+ send: SendType,
+|}): CancelableType {
+ return globalStore("builtinListeners").getOrSet("helloListener", () => {
+ const listener = listenForHello({ on });
- const parent = getAncestor();
- if (parent) {
- sayHello(parent, { send }).catch(err => {
- // $FlowFixMe
- if (__TEST__ && getGlobal(parent)) {
- throw err;
- }
- });
+ const parent = getAncestor();
+ if (parent) {
+ sayHello(parent, { send }).catch((err) => {
+ // $FlowFixMe
+ if (__TEST__ && getGlobal(parent)) {
+ throw err;
}
+ });
+ }
- return listener;
- });
+ return listener;
+ });
}
-export function awaitWindowHello(win : CrossDomainWindowType, timeout : number = 5000, name : string = 'Window') : ZalgoPromise<{| domain : string |}> {
- let promise = getHelloPromise(win);
+export function awaitWindowHello(
+ win: CrossDomainWindowType,
+ timeout: number = 5000,
+ name: string = "Window"
+): ZalgoPromise<{| domain: string |}> {
+ let promise = getHelloPromise(win);
- if (timeout !== -1) {
- promise = promise.timeout(timeout, new Error(`${ name } did not load after ${ timeout }ms`));
- }
+ if (timeout !== -1) {
+ promise = promise.timeout(
+ timeout,
+ new Error(`${name} did not load after ${timeout}ms`)
+ );
+ }
- return promise;
+ return promise;
}
diff --git a/src/lib/index.js b/src/lib/index.js
index a7cc5c99..77f2934f 100644
--- a/src/lib/index.js
+++ b/src/lib/index.js
@@ -1,5 +1,5 @@
/* @flow */
-export * from './hello';
-export * from './compat';
-export * from './windows';
+export * from "./hello";
+export * from "./compat";
+export * from "./windows";
diff --git a/src/lib/windows.js b/src/lib/windows.js
index 962a8b4e..53c7e929 100644
--- a/src/lib/windows.js
+++ b/src/lib/windows.js
@@ -1,15 +1,15 @@
/* @flow */
-import { type CrossDomainWindowType } from '@krakenjs/cross-domain-utils/src';
+import { type CrossDomainWindowType } from "@krakenjs/cross-domain-utils/src";
-import { windowStore } from '../global';
+import { windowStore } from "../global";
-export function markWindowKnown(win : CrossDomainWindowType) {
- const knownWindows = windowStore('knownWindows');
- knownWindows.set(win, true);
+export function markWindowKnown(win: CrossDomainWindowType) {
+ const knownWindows = windowStore("knownWindows");
+ knownWindows.set(win, true);
}
-export function isWindowKnown(win : CrossDomainWindowType) : boolean {
- const knownWindows = windowStore('knownWindows');
- return knownWindows.get(win, false);
+export function isWindowKnown(win: CrossDomainWindowType): boolean {
+ const knownWindows = windowStore("knownWindows");
+ return knownWindows.get(win, false);
}
diff --git a/src/public/index.js b/src/public/index.js
index 27569ea9..6e3560d6 100644
--- a/src/public/index.js
+++ b/src/public/index.js
@@ -1,4 +1,4 @@
/* @flow */
-export * from './on';
-export * from './send';
+export * from "./on";
+export * from "./send";
diff --git a/src/public/on.js b/src/public/on.js
index ca753ffc..0d5b59cb 100644
--- a/src/public/on.js
+++ b/src/public/on.js
@@ -1,83 +1,94 @@
/* @flow */
-import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
+import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
-import { addRequestListener } from '../drivers';
-import { WILDCARD } from '../conf';
-import type { ServerOptionsType, HandlerType, CancelableType } from '../types';
+import { addRequestListener } from "../drivers";
+import { WILDCARD } from "../conf";
+import type { ServerOptionsType, HandlerType, CancelableType } from "../types";
-const getDefaultServerOptions = () : ServerOptionsType => {
- // $FlowFixMe
- return {};
+const getDefaultServerOptions = (): ServerOptionsType => {
+ // $FlowFixMe
+ return {};
};
-export function on(name : string, options : ServerOptionsType | HandlerType, handler : ?HandlerType) : CancelableType {
-
- if (!name) {
- throw new Error('Expected name');
- }
-
- options = options || getDefaultServerOptions();
- if (typeof options === 'function') {
- handler = options;
- options = getDefaultServerOptions();
- }
-
- if (!handler) {
- throw new Error('Expected handler');
- }
-
- const winOrProxyWin = options.window;
- const domain = options.domain || WILDCARD;
-
- const successHandler = handler || options.handler;
- const errorHandler = options.errorHandler || (err => {
- throw err;
+export function on(
+ name: string,
+ options: ServerOptionsType | HandlerType,
+ handler: ?HandlerType
+): CancelableType {
+ if (!name) {
+ throw new Error("Expected name");
+ }
+
+ options = options || getDefaultServerOptions();
+ if (typeof options === "function") {
+ handler = options;
+ options = getDefaultServerOptions();
+ }
+
+ if (!handler) {
+ throw new Error("Expected handler");
+ }
+
+ const winOrProxyWin = options.window;
+ const domain = options.domain || WILDCARD;
+
+ const successHandler = handler || options.handler;
+ const errorHandler =
+ options.errorHandler ||
+ ((err) => {
+ throw err;
});
- const requestListener = addRequestListener({ name, win: winOrProxyWin, domain }, {
- handler: successHandler,
- handleError: errorHandler
- });
+ const requestListener = addRequestListener(
+ { name, win: winOrProxyWin, domain },
+ {
+ handler: successHandler,
+ handleError: errorHandler,
+ }
+ );
- return {
- cancel() {
- requestListener.cancel();
- }
- };
+ return {
+ cancel() {
+ requestListener.cancel();
+ },
+ };
}
type CancelableZalgoPromise = ZalgoPromise & {|
- cancel : () => void
+ cancel: () => void,
|};
-export function once(name : string, options? : ServerOptionsType | HandlerType, handler? : HandlerType) : CancelableZalgoPromise<{| source : mixed, origin : string, data : Object |}> {
-
- options = options || getDefaultServerOptions();
- if (typeof options === 'function') {
- handler = options;
- options = getDefaultServerOptions();
+export function once(
+ name: string,
+ options?: ServerOptionsType | HandlerType,
+ handler?: HandlerType
+): CancelableZalgoPromise<{| source: mixed, origin: string, data: Object |}> {
+ options = options || getDefaultServerOptions();
+ if (typeof options === "function") {
+ handler = options;
+ options = getDefaultServerOptions();
+ }
+
+ const promise = new ZalgoPromise();
+ let listener; // eslint-disable-line prefer-const
+
+ options.errorHandler = (err) => {
+ listener.cancel();
+ promise.reject(err);
+ };
+
+ listener = on(name, options, (event) => {
+ listener.cancel();
+ promise.resolve(event);
+ if (handler) {
+ return handler(event);
}
+ });
- const promise = new ZalgoPromise();
- let listener; // eslint-disable-line prefer-const
-
- options.errorHandler = (err) => {
- listener.cancel();
- promise.reject(err);
- };
-
- listener = on(name, options, event => {
- listener.cancel();
- promise.resolve(event);
- if (handler) {
- return handler(event);
- }
- });
-
- // $FlowFixMe
- promise.cancel = listener.cancel;
+ // $FlowFixMe
+ promise.cancel = listener.cancel;
- // $FlowFixMe
- return promise;
+ // $FlowFixMe
+ return promise;
}
diff --git a/src/public/send.js b/src/public/send.js
index cdb48dc1..bf4bef7f 100644
--- a/src/public/send.js
+++ b/src/public/send.js
@@ -1,145 +1,240 @@
/* @flow */
-import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-import { isAncestor, isWindowClosed, getDomain, matchDomain, type CrossDomainWindowType, type DomainMatcher } from '@krakenjs/cross-domain-utils/src';
-import { uniqueID, isRegex, noop, safeInterval, stringify, stringifyError } from '@krakenjs/belter/src';
-
-
-import { CHILD_WINDOW_TIMEOUT, MESSAGE_TYPE, WILDCARD, MESSAGE_NAME, ACK_TIMEOUT, RES_TIMEOUT, ACK_TIMEOUT_KNOWN, RESPONSE_CYCLE_TIME } from '../conf';
-import { sendMessage, addResponseListener, deleteResponseListener, markResponseListenerErrored, type ResponseListenerType } from '../drivers';
-import { awaitWindowHello, sayHello, isWindowKnown } from '../lib';
-import { windowStore } from '../global';
-import { ProxyWindow } from '../serialize/window';
-import type { SendType } from '../types';
-
-import { on } from './on';
-
-function validateOptions(name : string, win : CrossDomainWindowType, domain : ?DomainMatcher) {
- if (!name) {
- throw new Error('Expected name');
+import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+import {
+ isAncestor,
+ isWindowClosed,
+ getDomain,
+ matchDomain,
+ type CrossDomainWindowType,
+ type DomainMatcher,
+} from "@krakenjs/cross-domain-utils/src";
+import {
+ uniqueID,
+ isRegex,
+ noop,
+ safeInterval,
+ stringify,
+ stringifyError,
+} from "@krakenjs/belter/src";
+
+import {
+ CHILD_WINDOW_TIMEOUT,
+ MESSAGE_TYPE,
+ WILDCARD,
+ MESSAGE_NAME,
+ ACK_TIMEOUT,
+ RES_TIMEOUT,
+ ACK_TIMEOUT_KNOWN,
+ RESPONSE_CYCLE_TIME,
+} from "../conf";
+import {
+ sendMessage,
+ addResponseListener,
+ deleteResponseListener,
+ markResponseListenerErrored,
+ type ResponseListenerType,
+} from "../drivers";
+import { awaitWindowHello, sayHello, isWindowKnown } from "../lib";
+import { windowStore } from "../global";
+import { ProxyWindow } from "../serialize/window";
+import type { SendType } from "../types";
+
+import { on } from "./on";
+
+function validateOptions(
+ name: string,
+ win: CrossDomainWindowType,
+ domain: ?DomainMatcher
+) {
+ if (!name) {
+ throw new Error("Expected name");
+ }
+
+ if (domain) {
+ if (
+ typeof domain !== "string" &&
+ !Array.isArray(domain) &&
+ !isRegex(domain)
+ ) {
+ throw new TypeError(
+ `Can not send ${name}. Expected domain ${JSON.stringify(
+ domain
+ )} to be a string, array, or regex`
+ );
}
+ }
- if (domain) {
- if (typeof domain !== 'string' && !Array.isArray(domain) && !isRegex(domain)) {
- throw new TypeError(`Can not send ${ name }. Expected domain ${ JSON.stringify(domain) } to be a string, array, or regex`);
- }
- }
+ if (isWindowClosed(win)) {
+ throw new Error(`Can not send ${name}. Target window is closed`);
+ }
+}
- if (isWindowClosed(win)) {
- throw new Error(`Can not send ${ name }. Target window is closed`);
+function normalizeDomain(
+ win: CrossDomainWindowType,
+ targetDomain: DomainMatcher,
+ actualDomain: ?string,
+ { send }: {| send: SendType |}
+): ZalgoPromise {
+ return ZalgoPromise.try(() => {
+ if (typeof targetDomain === "string") {
+ return targetDomain;
}
-}
-function normalizeDomain(win : CrossDomainWindowType, targetDomain : DomainMatcher, actualDomain : ?string, { send } : {| send : SendType |}) : ZalgoPromise {
return ZalgoPromise.try(() => {
- if (typeof targetDomain === 'string') {
- return targetDomain;
- }
-
- return ZalgoPromise.try(() => {
- return actualDomain || sayHello(win, { send }).then(({ domain }) => domain);
-
- }).then(normalizedDomain => {
- if (!matchDomain(targetDomain, targetDomain)) {
- throw new Error(`Domain ${ stringify(targetDomain) } does not match ${ stringify(targetDomain) }`);
- }
-
- return normalizedDomain;
- });
+ return (
+ actualDomain || sayHello(win, { send }).then(({ domain }) => domain)
+ );
+ }).then((normalizedDomain) => {
+ if (!matchDomain(targetDomain, targetDomain)) {
+ throw new Error(
+ `Domain ${stringify(targetDomain)} does not match ${stringify(
+ targetDomain
+ )}`
+ );
+ }
+
+ return normalizedDomain;
});
+ });
}
-export const send : SendType = (winOrProxyWin, name, data, options) => {
- options = options || {};
- const domainMatcher = options.domain || WILDCARD;
- const responseTimeout = options.timeout || RES_TIMEOUT;
- const childTimeout = options.timeout || CHILD_WINDOW_TIMEOUT;
- const fireAndForget = options.fireAndForget || false;
-
- return ProxyWindow.toProxyWindow(winOrProxyWin, { send }).awaitWindow().then(win => {
-
- // $FlowFixMe
- return ZalgoPromise.try(() => {
- validateOptions(name, win, domainMatcher);
-
- if (isAncestor(window, win)) {
- return awaitWindowHello(win, childTimeout);
- }
-
- }).then(({ domain: actualDomain } = {}) => {
-
- return normalizeDomain(win, domainMatcher, actualDomain, { send });
- }).then(targetDomain => {
- const domain = targetDomain;
-
- const logName = (name === MESSAGE_NAME.METHOD && data && typeof data.name === 'string') ? `${ data.name }()` : name;
-
- if (__DEBUG__) {
- console.info('send::req', logName, domain, '\n\n', data); // eslint-disable-line no-console
- }
+export const send: SendType = (winOrProxyWin, name, data, options) => {
+ options = options || {};
+ const domainMatcher = options.domain || WILDCARD;
+ const responseTimeout = options.timeout || RES_TIMEOUT;
+ const childTimeout = options.timeout || CHILD_WINDOW_TIMEOUT;
+ const fireAndForget = options.fireAndForget || false;
+
+ return ProxyWindow.toProxyWindow(winOrProxyWin, { send })
+ .awaitWindow()
+ .then((win) => {
+ // $FlowFixMe
+ return ZalgoPromise.try(() => {
+ validateOptions(name, win, domainMatcher);
+
+ if (isAncestor(window, win)) {
+ return awaitWindowHello(win, childTimeout);
+ }
+ })
+ .then(({ domain: actualDomain } = {}) => {
+ return normalizeDomain(win, domainMatcher, actualDomain, { send });
+ })
+ .then((targetDomain) => {
+ const domain = targetDomain;
+
+ const logName =
+ name === MESSAGE_NAME.METHOD &&
+ data &&
+ typeof data.name === "string"
+ ? `${data.name}()`
+ : name;
+
+ if (__DEBUG__) {
+ console.info("send::req", logName, domain, "\n\n", data); // eslint-disable-line no-console
+ }
+
+ const promise = new ZalgoPromise();
+ const hash = `${name}_${uniqueID()}`;
+
+ if (!fireAndForget) {
+ const responseListener: ResponseListenerType = {
+ name,
+ win,
+ domain,
+ promise,
+ };
+ addResponseListener(hash, responseListener);
+
+ const reqPromises = windowStore("requestPromises").getOrSet(
+ win,
+ () => []
+ );
+ reqPromises.push(promise);
+
+ promise.catch(() => {
+ markResponseListenerErrored(hash);
+ deleteResponseListener(hash);
+ });
- const promise = new ZalgoPromise();
- const hash = `${ name }_${ uniqueID() }`;
-
- if (!fireAndForget) {
- const responseListener : ResponseListenerType = { name, win, domain, promise };
- addResponseListener(hash, responseListener);
-
- const reqPromises = windowStore('requestPromises').getOrSet(win, () => []);
- reqPromises.push(promise);
-
- promise.catch(() => {
- markResponseListenerErrored(hash);
- deleteResponseListener(hash);
- });
-
- const totalAckTimeout = isWindowKnown(win) ? ACK_TIMEOUT_KNOWN : ACK_TIMEOUT;
- const totalResTimeout = responseTimeout;
-
- let ackTimeout = totalAckTimeout;
- let resTimeout = totalResTimeout;
-
- const interval = safeInterval(() => {
- if (isWindowClosed(win)) {
- return promise.reject(new Error(`Window closed for ${ name } before ${ responseListener.ack ? 'response' : 'ack' }`));
- }
-
- if (responseListener.cancelled) {
- return promise.reject(new Error(`Response listener was cancelled for ${ name }`));
- }
-
- ackTimeout = Math.max(ackTimeout - RESPONSE_CYCLE_TIME, 0);
- if (resTimeout !== -1) {
- resTimeout = Math.max(resTimeout - RESPONSE_CYCLE_TIME, 0);
- }
-
- if (!responseListener.ack && ackTimeout === 0) {
- return promise.reject(new Error(`No ack for postMessage ${ logName } in ${ getDomain() } in ${ totalAckTimeout }ms`));
-
- } else if (resTimeout === 0) {
- return promise.reject(new Error(`No response for postMessage ${ logName } in ${ getDomain() } in ${ totalResTimeout }ms`));
- }
- }, RESPONSE_CYCLE_TIME);
-
- promise.finally(() => {
- interval.cancel();
- reqPromises.splice(reqPromises.indexOf(promise, 1));
- }).catch(noop);
+ const totalAckTimeout = isWindowKnown(win)
+ ? ACK_TIMEOUT_KNOWN
+ : ACK_TIMEOUT;
+ const totalResTimeout = responseTimeout;
+
+ let ackTimeout = totalAckTimeout;
+ let resTimeout = totalResTimeout;
+
+ const interval = safeInterval(() => {
+ if (isWindowClosed(win)) {
+ return promise.reject(
+ new Error(
+ `Window closed for ${name} before ${
+ responseListener.ack ? "response" : "ack"
+ }`
+ )
+ );
+ }
+
+ if (responseListener.cancelled) {
+ return promise.reject(
+ new Error(`Response listener was cancelled for ${name}`)
+ );
+ }
+
+ ackTimeout = Math.max(ackTimeout - RESPONSE_CYCLE_TIME, 0);
+ if (resTimeout !== -1) {
+ resTimeout = Math.max(resTimeout - RESPONSE_CYCLE_TIME, 0);
+ }
+
+ if (!responseListener.ack && ackTimeout === 0) {
+ return promise.reject(
+ new Error(
+ `No ack for postMessage ${logName} in ${getDomain()} in ${totalAckTimeout}ms`
+ )
+ );
+ } else if (resTimeout === 0) {
+ return promise.reject(
+ new Error(
+ `No response for postMessage ${logName} in ${getDomain()} in ${totalResTimeout}ms`
+ )
+ );
+ }
+ }, RESPONSE_CYCLE_TIME);
+
+ promise
+ .finally(() => {
+ interval.cancel();
+ reqPromises.splice(reqPromises.indexOf(promise, 1));
+ })
+ .catch(noop);
+ }
+
+ return sendMessage(
+ win,
+ domain,
+ {
+ id: uniqueID(),
+ origin: getDomain(window),
+ type: MESSAGE_TYPE.REQUEST,
+ hash,
+ name,
+ data,
+ fireAndForget,
+ },
+ { on, send }
+ ).then(
+ () => {
+ return fireAndForget ? promise.resolve() : promise;
+ },
+ (err) => {
+ throw new Error(
+ `Send request message failed for ${logName} in ${getDomain()}\n\n${stringifyError(
+ err
+ )}`
+ );
}
-
- return sendMessage(win, domain, {
- id: uniqueID(),
- origin: getDomain(window),
- type: MESSAGE_TYPE.REQUEST,
- hash,
- name,
- data,
- fireAndForget
- }, { on, send }).then(() => {
- return fireAndForget ? promise.resolve() : promise;
- }, err => {
- throw new Error(`Send request message failed for ${ logName } in ${ getDomain() }\n\n${ stringifyError(err) }`);
- });
+ );
});
});
};
diff --git a/src/serialize/function.js b/src/serialize/function.js
index 371fbf98..5ded34b5 100644
--- a/src/serialize/function.js
+++ b/src/serialize/function.js
@@ -1,206 +1,302 @@
/* @flow */
-import { matchDomain, getDomain, type CrossDomainWindowType, type DomainMatcher } from '@krakenjs/cross-domain-utils/src';
-import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-import { uniqueID, isRegex, arrayFrom } from '@krakenjs/belter/src';
-import { serializeType, type CustomSerializedType } from '@krakenjs/universal-serialize/src';
+import {
+ matchDomain,
+ getDomain,
+ type CrossDomainWindowType,
+ type DomainMatcher,
+} from "@krakenjs/cross-domain-utils/src";
+import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+import { uniqueID, isRegex, arrayFrom } from "@krakenjs/belter/src";
+import {
+ serializeType,
+ type CustomSerializedType,
+} from "@krakenjs/universal-serialize/src";
-import { MESSAGE_NAME, WILDCARD, SERIALIZATION_TYPE } from '../conf';
-import { windowStore, globalStore } from '../global';
-import type { OnType, SendType, CancelableType } from '../types';
+import { MESSAGE_NAME, WILDCARD, SERIALIZATION_TYPE } from "../conf";
+import { windowStore, globalStore } from "../global";
+import type { OnType, SendType, CancelableType } from "../types";
-import { ProxyWindow } from './window';
+import { ProxyWindow } from "./window";
type StoredMethod = {|
- name : string,
- domain : DomainMatcher,
- val : Function,
- source : CrossDomainWindowType | ProxyWindow
+ name: string,
+ domain: DomainMatcher,
+ val: Function,
+ source: CrossDomainWindowType | ProxyWindow,
|};
-function addMethod(id : string, val : Function, name : string, source : CrossDomainWindowType | ProxyWindow, domain : DomainMatcher) {
- const methodStore = windowStore('methodStore');
- const proxyWindowMethods = globalStore('proxyWindowMethods');
-
- if (ProxyWindow.isProxyWindow(source)) {
- proxyWindowMethods.set(id, { val, name, domain, source });
- } else {
- proxyWindowMethods.del(id);
- // $FlowFixMe
- const methods = methodStore.getOrSet(source, () => ({}));
- methods[id] = { domain, name, val, source };
- }
-}
+function addMethod(
+ id: string,
+ val: Function,
+ name: string,
+ source: CrossDomainWindowType | ProxyWindow,
+ domain: DomainMatcher
+) {
+ const methodStore = windowStore("methodStore");
+ const proxyWindowMethods = globalStore("proxyWindowMethods");
-function lookupMethod(source : CrossDomainWindowType, id : string) : ?StoredMethod {
- const methodStore = windowStore('methodStore');
- const proxyWindowMethods = globalStore('proxyWindowMethods');
+ if (ProxyWindow.isProxyWindow(source)) {
+ proxyWindowMethods.set(id, { val, name, domain, source });
+ } else {
+ proxyWindowMethods.del(id);
+ // $FlowFixMe
const methods = methodStore.getOrSet(source, () => ({}));
- return methods[id] || proxyWindowMethods.get(id);
+ methods[id] = { domain, name, val, source };
+ }
}
-function stringifyArguments(args : $ReadOnlyArray = []) : string {
- return arrayFrom(args).map(arg => {
- if (typeof arg === 'string') {
- return `'${ arg }'`;
- }
- if (arg === undefined) {
- return 'undefined';
- }
- if (arg === null) {
- return 'null';
- }
- if (typeof arg === 'boolean') {
- return arg.toString();
- }
- if (Array.isArray(arg)) {
- return '[ ... ]';
- }
- if (typeof arg === 'object') {
- return '{ ... }';
- }
- if (typeof arg === 'function') {
- return '() => { ... }';
- }
- return `<${ typeof arg }>`;
- }).join(', ');
+function lookupMethod(
+ source: CrossDomainWindowType,
+ id: string
+): ?StoredMethod {
+ const methodStore = windowStore("methodStore");
+ const proxyWindowMethods = globalStore("proxyWindowMethods");
+ const methods = methodStore.getOrSet(source, () => ({}));
+ return methods[id] || proxyWindowMethods.get(id);
}
-function listenForFunctionCalls({ on, send } : {| on : OnType, send : SendType |}) : CancelableType {
- return globalStore('builtinListeners').getOrSet('functionCalls', () => {
- return on(MESSAGE_NAME.METHOD, { domain: WILDCARD }, ({ source, origin, data } : {| source : CrossDomainWindowType, origin : string, data : Object |}) => {
- const { id, name } = data;
+function stringifyArguments(args: $ReadOnlyArray = []): string {
+ return arrayFrom(args)
+ .map((arg) => {
+ if (typeof arg === "string") {
+ return `'${arg}'`;
+ }
+ if (arg === undefined) {
+ return "undefined";
+ }
+ if (arg === null) {
+ return "null";
+ }
+ if (typeof arg === "boolean") {
+ return arg.toString();
+ }
+ if (Array.isArray(arg)) {
+ return "[ ... ]";
+ }
+ if (typeof arg === "object") {
+ return "{ ... }";
+ }
+ if (typeof arg === "function") {
+ return "() => { ... }";
+ }
+ return `<${typeof arg}>`;
+ })
+ .join(", ");
+}
- const meth = lookupMethod(source, id);
-
- if (!meth) {
- throw new Error(`Could not find method '${ name }' with id: ${ data.id } in ${ getDomain(window) }`);
- }
+function listenForFunctionCalls({
+ on,
+ send,
+}: {|
+ on: OnType,
+ send: SendType,
+|}): CancelableType {
+ return globalStore("builtinListeners").getOrSet("functionCalls", () => {
+ return on(
+ MESSAGE_NAME.METHOD,
+ { domain: WILDCARD },
+ ({
+ source,
+ origin,
+ data,
+ }: {|
+ source: CrossDomainWindowType,
+ origin: string,
+ data: Object,
+ |}) => {
+ const { id, name } = data;
- const { source: methodSource, domain, val } = meth;
-
- return ZalgoPromise.try(() => {
- if (!matchDomain(domain, origin)) {
- // $FlowFixMe
- throw new Error(`Method '${ data.name }' domain ${ JSON.stringify(isRegex(meth.domain) ? meth.domain.source : meth.domain) } does not match origin ${ origin } in ${ getDomain(window) }`);
+ const meth = lookupMethod(source, id);
+
+ if (!meth) {
+ throw new Error(
+ `Could not find method '${name}' with id: ${data.id} in ${getDomain(
+ window
+ )}`
+ );
+ }
+
+ const { source: methodSource, domain, val } = meth;
+
+ return ZalgoPromise.try(() => {
+ if (!matchDomain(domain, origin)) {
+ throw new Error(
+ `Method '${data.name}' domain ${JSON.stringify(
+ // $FlowFixMe
+ isRegex(meth.domain) ? meth.domain.source : meth.domain
+ )} does not match origin ${origin} in ${getDomain(window)}`
+ );
+ }
+
+ if (ProxyWindow.isProxyWindow(methodSource)) {
+ // $FlowFixMe
+ return methodSource.matchWindow(source, { send }).then((match) => {
+ if (!match) {
+ throw new Error(
+ `Method call '${
+ data.name
+ }' failed - proxy window does not match source in ${getDomain(
+ window
+ )}`
+ );
+ }
+ });
+ }
+ })
+ .then(
+ () => {
+ return val.apply({ source, origin }, data.args);
+ },
+ (err) => {
+ return ZalgoPromise.try(() => {
+ if (val.onError) {
+ return val.onError(err);
}
-
- if (ProxyWindow.isProxyWindow(methodSource)) {
+ }).then(() => {
+ // $FlowFixMe
+ if (err.stack) {
+ // $FlowFixMe
+ err.stack = `Remote call to ${name}(${stringifyArguments(
+ data.args
// $FlowFixMe
- return methodSource.matchWindow(source, { send }).then(match => {
- if (!match) {
- throw new Error(`Method call '${ data.name }' failed - proxy window does not match source in ${ getDomain(window) }`);
- }
- });
+ )}) failed\n\n${err.stack}`;
}
- }).then(() => {
- return val.apply({ source, origin }, data.args);
- }, err => {
- return ZalgoPromise.try(() => {
- if (val.onError) {
- return val.onError(err);
- }
- }).then(() => {
- // $FlowFixMe
- if (err.stack) {
- // $FlowFixMe
- err.stack = `Remote call to ${ name }(${ stringifyArguments(data.args) }) failed\n\n${ err.stack }`;
- }
-
- throw err;
- });
- }).then(result => {
- return { result, id, name };
- });
- });
- });
+
+ throw err;
+ });
+ }
+ )
+ .then((result) => {
+ return { result, id, name };
+ });
+ }
+ );
+ });
}
-export type SerializedFunction = CustomSerializedType;
+export type SerializedFunction = CustomSerializedType<
+ typeof SERIALIZATION_TYPE.CROSS_DOMAIN_FUNCTION,
+ {|
+ id: string,
+ name: string,
+ |}
+>;
// eslint-disable-next-line flowtype/require-exact-type
type SerializableFunction = {
- () : ZalgoPromise | T,
- __id__? : string,
- __name__? : string
+ (): ZalgoPromise | T,
+ __id__?: string,
+ __name__?: string,
};
-export function serializeFunction(destination : CrossDomainWindowType | ProxyWindow, domain : DomainMatcher, val : SerializableFunction, key : string, { on, send } : {| on : OnType, send : SendType |}) : SerializedFunction {
- listenForFunctionCalls({ on, send });
-
- const id = val.__id__ || uniqueID();
- destination = ProxyWindow.unwrap(destination);
- let name = val.__name__ || val.name || key;
+export function serializeFunction(
+ destination: CrossDomainWindowType | ProxyWindow,
+ domain: DomainMatcher,
+ val: SerializableFunction,
+ key: string,
+ { on, send }: {| on: OnType, send: SendType |}
+): SerializedFunction {
+ listenForFunctionCalls({ on, send });
- if (typeof name === 'string' && typeof name.indexOf === 'function' && name.indexOf('anonymous::') === 0) {
- name = name.replace('anonymous::', `${ key }::`);
- }
+ const id = val.__id__ || uniqueID();
+ destination = ProxyWindow.unwrap(destination);
+ let name = val.__name__ || val.name || key;
- if (ProxyWindow.isProxyWindow(destination)) {
- addMethod(id, val, name, destination, domain);
+ if (
+ typeof name === "string" &&
+ typeof name.indexOf === "function" &&
+ name.indexOf("anonymous::") === 0
+ ) {
+ name = name.replace("anonymous::", `${key}::`);
+ }
- // $FlowFixMe
- destination.awaitWindow().then(win => {
- addMethod(id, val, name, win, domain);
- });
- } else {
- addMethod(id, val, name, destination, domain);
- }
+ if (ProxyWindow.isProxyWindow(destination)) {
+ addMethod(id, val, name, destination, domain);
- return serializeType(SERIALIZATION_TYPE.CROSS_DOMAIN_FUNCTION, { id, name });
+ // $FlowFixMe
+ destination.awaitWindow().then((win) => {
+ addMethod(id, val, name, win, domain);
+ });
+ } else {
+ addMethod(id, val, name, destination, domain);
+ }
+
+ return serializeType(SERIALIZATION_TYPE.CROSS_DOMAIN_FUNCTION, { id, name });
}
-export function deserializeFunction(source : CrossDomainWindowType | ProxyWindow, origin : string, { id, name } : {| id : string, name : string |}, { send } : {| send : SendType |}) : (...args : $ReadOnlyArray) => ZalgoPromise {
- const getDeserializedFunction = (opts? : Object = {}) => {
- function crossDomainFunctionWrapper() : ZalgoPromise {
- let originalStack;
-
- if (__DEBUG__) {
- originalStack = (new Error(`Original call to ${ name }():`)).stack;
- }
-
- return ProxyWindow.toProxyWindow(source, { send }).awaitWindow().then(win => {
- const meth = lookupMethod(win, id);
-
- if (meth && meth.val !== crossDomainFunctionWrapper) {
- return meth.val.apply({ source: window, origin: getDomain() }, arguments);
- } else {
- // $FlowFixMe[method-unbinding]
- const args = Array.prototype.slice.call(arguments);
-
- if (opts.fireAndForget) {
- return send(win, MESSAGE_NAME.METHOD, { id, name, args }, { domain: origin, fireAndForget: true });
- } else {
- return send(win, MESSAGE_NAME.METHOD, { id, name, args }, { domain: origin, fireAndForget: false })
- .then(res => res.data.result);
- }
- }
-
- }).catch(err => {
- // $FlowFixMe
- if (__DEBUG__ && originalStack && err.stack) {
- // $FlowFixMe
- err.stack = `Remote call to ${ name }(${ stringifyArguments(arguments) }) failed\n\n${ err.stack }\n\n${ originalStack }`;
- }
- throw err;
- });
- }
+export function deserializeFunction(
+ source: CrossDomainWindowType | ProxyWindow,
+ origin: string,
+ { id, name }: {| id: string, name: string |},
+ { send }: {| send: SendType |}
+): (...args: $ReadOnlyArray) => ZalgoPromise {
+ const getDeserializedFunction = (opts?: Object = {}) => {
+ function crossDomainFunctionWrapper(): ZalgoPromise {
+ let originalStack;
- crossDomainFunctionWrapper.__name__ = name;
- crossDomainFunctionWrapper.__origin__ = origin;
- crossDomainFunctionWrapper.__source__ = source;
- crossDomainFunctionWrapper.__id__ = id;
+ if (__DEBUG__) {
+ originalStack = new Error(`Original call to ${name}():`).stack;
+ }
- crossDomainFunctionWrapper.origin = origin;
+ return ProxyWindow.toProxyWindow(source, { send })
+ .awaitWindow()
+ .then((win) => {
+ const meth = lookupMethod(win, id);
- return crossDomainFunctionWrapper;
- };
+ if (meth && meth.val !== crossDomainFunctionWrapper) {
+ return meth.val.apply(
+ { source: window, origin: getDomain() },
+ arguments
+ );
+ } else {
+ // $FlowFixMe[method-unbinding]
+ const args = Array.prototype.slice.call(arguments);
- const crossDomainFunctionWrapper = getDeserializedFunction();
- crossDomainFunctionWrapper.fireAndForget = getDeserializedFunction({ fireAndForget: true });
+ if (opts.fireAndForget) {
+ return send(
+ win,
+ MESSAGE_NAME.METHOD,
+ { id, name, args },
+ { domain: origin, fireAndForget: true }
+ );
+ } else {
+ return send(
+ win,
+ MESSAGE_NAME.METHOD,
+ { id, name, args },
+ { domain: origin, fireAndForget: false }
+ ).then((res) => res.data.result);
+ }
+ }
+ })
+ .catch((err) => {
+ // $FlowFixMe
+ if (__DEBUG__ && originalStack && err.stack) {
+ // $FlowFixMe
+ err.stack = `Remote call to ${name}(${stringifyArguments(
+ arguments
+ // $FlowFixMe
+ )}) failed\n\n${err.stack}\n\n${originalStack}`;
+ }
+ throw err;
+ });
+ }
+
+ crossDomainFunctionWrapper.__name__ = name;
+ crossDomainFunctionWrapper.__origin__ = origin;
+ crossDomainFunctionWrapper.__source__ = source;
+ crossDomainFunctionWrapper.__id__ = id;
+
+ crossDomainFunctionWrapper.origin = origin;
return crossDomainFunctionWrapper;
+ };
+
+ const crossDomainFunctionWrapper = getDeserializedFunction();
+ crossDomainFunctionWrapper.fireAndForget = getDeserializedFunction({
+ fireAndForget: true,
+ });
+
+ return crossDomainFunctionWrapper;
}
diff --git a/src/serialize/index.js b/src/serialize/index.js
index 6b612128..ec9dcc64 100644
--- a/src/serialize/index.js
+++ b/src/serialize/index.js
@@ -1,6 +1,6 @@
/* @flow */
-export * from './serialize';
-export * from './function';
-export * from './promise';
-export * from './window';
+export * from "./serialize";
+export * from "./function";
+export * from "./promise";
+export * from "./window";
diff --git a/src/serialize/promise.js b/src/serialize/promise.js
index 5bb4d70c..460bdbe2 100644
--- a/src/serialize/promise.js
+++ b/src/serialize/promise.js
@@ -1,25 +1,51 @@
/* @flow */
-import { type CrossDomainWindowType, type DomainMatcher } from '@krakenjs/cross-domain-utils/src';
-import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-import { serializeType, type CustomSerializedType, type Thenable } from '@krakenjs/universal-serialize/src';
+import {
+ type CrossDomainWindowType,
+ type DomainMatcher,
+} from "@krakenjs/cross-domain-utils/src";
+import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+import {
+ serializeType,
+ type CustomSerializedType,
+ type Thenable,
+} from "@krakenjs/universal-serialize/src";
-import { SERIALIZATION_TYPE } from '../conf';
-import type { OnType, SendType } from '../types';
+import { SERIALIZATION_TYPE } from "../conf";
+import type { OnType, SendType } from "../types";
-import { serializeFunction, type SerializedFunction } from './function';
-import { ProxyWindow } from './window';
+import { serializeFunction, type SerializedFunction } from "./function";
+import { ProxyWindow } from "./window";
-export type SerializedPromise = CustomSerializedType;
+export type SerializedPromise = CustomSerializedType<
+ typeof SERIALIZATION_TYPE.CROSS_DOMAIN_ZALGO_PROMISE,
+ {|
+ then: SerializedFunction,
+ |}
+>;
-export function serializePromise(destination : CrossDomainWindowType | ProxyWindow, domain : DomainMatcher, val : Thenable, key : string, { on, send } : {| on : OnType, send : SendType |}) : SerializedPromise {
- return serializeType(SERIALIZATION_TYPE.CROSS_DOMAIN_ZALGO_PROMISE, {
- then: serializeFunction(destination, domain, (resolve, reject) => val.then(resolve, reject), key, { on, send })
- });
+export function serializePromise(
+ destination: CrossDomainWindowType | ProxyWindow,
+ domain: DomainMatcher,
+ val: Thenable,
+ key: string,
+ { on, send }: {| on: OnType, send: SendType |}
+): SerializedPromise {
+ return serializeType(SERIALIZATION_TYPE.CROSS_DOMAIN_ZALGO_PROMISE, {
+ then: serializeFunction(
+ destination,
+ domain,
+ (resolve, reject) => val.then(resolve, reject),
+ key,
+ { on, send }
+ ),
+ });
}
-export function deserializePromise(source : CrossDomainWindowType | ProxyWindow, origin : string, { then } : {| then : Function |}) : ZalgoPromise {
- return new ZalgoPromise(then);
+export function deserializePromise(
+ source: CrossDomainWindowType | ProxyWindow,
+ origin: string,
+ { then }: {| then: Function |}
+): ZalgoPromise {
+ return new ZalgoPromise(then);
}
diff --git a/src/serialize/serialize.js b/src/serialize/serialize.js
index 81b6adcb..fafba568 100644
--- a/src/serialize/serialize.js
+++ b/src/serialize/serialize.js
@@ -1,29 +1,68 @@
/* @flow */
-import { type CrossDomainWindowType, isWindow, type DomainMatcher } from '@krakenjs/cross-domain-utils/src';
-import { TYPE, serialize, deserialize, type Thenable } from '@krakenjs/universal-serialize/src';
+import {
+ type CrossDomainWindowType,
+ isWindow,
+ type DomainMatcher,
+} from "@krakenjs/cross-domain-utils/src";
+import {
+ TYPE,
+ serialize,
+ deserialize,
+ type Thenable,
+} from "@krakenjs/universal-serialize/src";
-import { SERIALIZATION_TYPE } from '../conf';
-import type { OnType, SendType } from '../types';
+import { SERIALIZATION_TYPE } from "../conf";
+import type { OnType, SendType } from "../types";
-import { serializeFunction, deserializeFunction, type SerializedFunction } from './function';
-import { serializePromise, deserializePromise, type SerializedPromise } from './promise';
-import { serializeWindow, deserializeWindow, type SerializedWindow, ProxyWindow } from './window';
+import {
+ serializeFunction,
+ deserializeFunction,
+ type SerializedFunction,
+} from "./function";
+import {
+ serializePromise,
+ deserializePromise,
+ type SerializedPromise,
+} from "./promise";
+import {
+ serializeWindow,
+ deserializeWindow,
+ type SerializedWindow,
+ ProxyWindow,
+} from "./window";
-export function serializeMessage(destination : CrossDomainWindowType | ProxyWindow, domain : DomainMatcher, obj : T, { on, send } : {| on : OnType, send : SendType |}) : string {
- return serialize(obj, {
- [ TYPE.PROMISE ]: (val : Thenable, key : string) : SerializedPromise => serializePromise(destination, domain, val, key, { on, send }),
- [ TYPE.FUNCTION ]: (val : Function, key : string) : SerializedFunction => serializeFunction(destination, domain, val, key, { on, send }),
- [ TYPE.OBJECT ]: (val : CrossDomainWindowType) : Object | SerializedWindow => {
- return (isWindow(val) || ProxyWindow.isProxyWindow(val)) ? serializeWindow(destination, domain, val, { send }) : val;
- }
- });
+export function serializeMessage(
+ destination: CrossDomainWindowType | ProxyWindow,
+ domain: DomainMatcher,
+ obj: T,
+ { on, send }: {| on: OnType, send: SendType |}
+): string {
+ return serialize(obj, {
+ [TYPE.PROMISE]: (val: Thenable, key: string): SerializedPromise =>
+ serializePromise(destination, domain, val, key, { on, send }),
+ [TYPE.FUNCTION]: (val: Function, key: string): SerializedFunction =>
+ serializeFunction(destination, domain, val, key, { on, send }),
+ [TYPE.OBJECT]: (val: CrossDomainWindowType): Object | SerializedWindow => {
+ return isWindow(val) || ProxyWindow.isProxyWindow(val)
+ ? serializeWindow(destination, domain, val, { send })
+ : val;
+ },
+ });
}
-export function deserializeMessage(source : CrossDomainWindowType | ProxyWindow, origin : string, message : string, { send } : {| on : OnType, send : SendType |}) : T {
- return deserialize(message, {
- [ SERIALIZATION_TYPE.CROSS_DOMAIN_ZALGO_PROMISE ]: (serializedPromise) => deserializePromise(source, origin, serializedPromise),
- [ SERIALIZATION_TYPE.CROSS_DOMAIN_FUNCTION ]: (serializedFunction) => deserializeFunction(source, origin, serializedFunction, { send }),
- [ SERIALIZATION_TYPE.CROSS_DOMAIN_WINDOW ]: (serializedWindow) => deserializeWindow(source, origin, serializedWindow, { send })
- });
+export function deserializeMessage(
+ source: CrossDomainWindowType | ProxyWindow,
+ origin: string,
+ message: string,
+ { send }: {| on: OnType, send: SendType |}
+): T {
+ return deserialize(message, {
+ [SERIALIZATION_TYPE.CROSS_DOMAIN_ZALGO_PROMISE]: (serializedPromise) =>
+ deserializePromise(source, origin, serializedPromise),
+ [SERIALIZATION_TYPE.CROSS_DOMAIN_FUNCTION]: (serializedFunction) =>
+ deserializeFunction(source, origin, serializedFunction, { send }),
+ [SERIALIZATION_TYPE.CROSS_DOMAIN_WINDOW]: (serializedWindow) =>
+ deserializeWindow(source, origin, serializedWindow, { send }),
+ });
}
diff --git a/src/serialize/window.js b/src/serialize/window.js
index 21e66165..fc288a50 100644
--- a/src/serialize/window.js
+++ b/src/serialize/window.js
@@ -1,329 +1,413 @@
/* @flow */
/* eslint no-use-before-define: off */
-import { isSameDomain, isWindowClosed, type CrossDomainWindowType, closeWindow,
- type DomainMatcher, getOpener, WINDOW_TYPE, isWindow, assertSameDomain, getFrameForWindow } from '@krakenjs/cross-domain-utils/src';
-import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-import { uniqueID, memoizePromise, noop, submitForm } from '@krakenjs/belter/src';
-import { serializeType, type CustomSerializedType } from '@krakenjs/universal-serialize/src';
-
-import { SERIALIZATION_TYPE, METHOD } from '../conf';
-import { windowStore, globalStore } from '../global';
-import { getWindowInstanceID } from '../lib';
-import { linkWindow } from '../bridge';
-import type { SendType } from '../types';
+import {
+ isSameDomain,
+ isWindowClosed,
+ type CrossDomainWindowType,
+ closeWindow,
+ type DomainMatcher,
+ getOpener,
+ WINDOW_TYPE,
+ isWindow,
+ assertSameDomain,
+ getFrameForWindow,
+} from "@krakenjs/cross-domain-utils/src";
+import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+import {
+ uniqueID,
+ memoizePromise,
+ noop,
+ submitForm,
+} from "@krakenjs/belter/src";
+import {
+ serializeType,
+ type CustomSerializedType,
+} from "@krakenjs/universal-serialize/src";
+
+import { SERIALIZATION_TYPE, METHOD } from "../conf";
+import { windowStore, globalStore } from "../global";
+import { getWindowInstanceID } from "../lib";
+import { linkWindow } from "../bridge";
+import type { SendType } from "../types";
function cleanupProxyWindows() {
- const idToProxyWindow = globalStore('idToProxyWindow');
- for (const id of idToProxyWindow.keys()) {
- // $FlowFixMe
- if (idToProxyWindow.get(id).shouldClean()) {
- idToProxyWindow.del(id);
- }
+ const idToProxyWindow = globalStore("idToProxyWindow");
+ for (const id of idToProxyWindow.keys()) {
+ // $FlowFixMe
+ if (idToProxyWindow.get(id).shouldClean()) {
+ idToProxyWindow.del(id);
}
+ }
}
type SetLocationOptions = {|
- method? : $Values,
- body? : {|
- [string] : string | boolean
- |}
+ method?: $Values,
+ body?: {|
+ [string]: string | boolean,
+ |},
|};
type SerializedWindowType = {|
- id : string,
- getType : () => ZalgoPromise<$Values>,
- close : () => ZalgoPromise,
- focus : () => ZalgoPromise,
- isClosed : () => ZalgoPromise,
- setLocation : (url : string, opts? : SetLocationOptions) => ZalgoPromise,
- getName : () => ZalgoPromise,
- setName : (string) => ZalgoPromise,
- getInstanceID : () => ZalgoPromise
+ id: string,
+ getType: () => ZalgoPromise<$Values>,
+ close: () => ZalgoPromise,
+ focus: () => ZalgoPromise,
+ isClosed: () => ZalgoPromise,
+ setLocation: (url: string, opts?: SetLocationOptions) => ZalgoPromise,
+ getName: () => ZalgoPromise,
+ setName: (string) => ZalgoPromise,
+ getInstanceID: () => ZalgoPromise,
|};
-function getSerializedWindow(winPromise : ZalgoPromise, { send, id = uniqueID() } : {| send : SendType, id? : string |}) : SerializedWindowType {
+function getSerializedWindow(
+ winPromise: ZalgoPromise,
+ { send, id = uniqueID() }: {| send: SendType, id?: string |}
+): SerializedWindowType {
+ let windowNamePromise = winPromise.then((win) => {
+ if (isSameDomain(win)) {
+ return assertSameDomain(win).name;
+ }
+ });
- let windowNamePromise = winPromise.then(win => {
- if (isSameDomain(win)) {
- return assertSameDomain(win).name;
- }
- });
+ const windowTypePromise = winPromise.then((window) => {
+ if (!isWindowClosed(window)) {
+ return getOpener(window) ? WINDOW_TYPE.POPUP : WINDOW_TYPE.IFRAME;
+ } else {
+ throw new Error(`Window is closed, can not determine type`);
+ }
+ });
- const windowTypePromise = winPromise.then(window => {
- if (!isWindowClosed(window)) {
- return getOpener(window) ? WINDOW_TYPE.POPUP : WINDOW_TYPE.IFRAME;
- } else {
- throw new Error(`Window is closed, can not determine type`);
- }
- });
+ windowNamePromise.catch(noop);
+ windowTypePromise.catch(noop);
- windowNamePromise.catch(noop);
- windowTypePromise.catch(noop);
+ const getName = () =>
+ winPromise.then((win) => {
+ if (isWindowClosed(win)) {
+ return;
+ }
- const getName = () => winPromise.then(win => {
- if (isWindowClosed(win)) {
- return;
- }
+ if (isSameDomain(win)) {
+ return assertSameDomain(win).name;
+ }
+
+ return windowNamePromise;
+ });
+ const getDefaultSetLocationOptions = () => {
+ // $FlowFixMe
+ return {};
+ };
+
+ const setLocation = (
+ href: string,
+ opts?: SetLocationOptions = getDefaultSetLocationOptions()
+ ) =>
+ winPromise.then((win) => {
+ const domain = `${window.location.protocol}//${window.location.host}`;
+ const { method = METHOD.GET, body } = opts;
+
+ if (href.indexOf("/") === 0) {
+ href = `${domain}${href}`;
+ } else if (!href.match(/^https?:\/\//) && href.indexOf(domain) !== 0) {
+ throw new Error(
+ `Expected url to be http or https url, or absolute path, got ${JSON.stringify(
+ href
+ )}`
+ );
+ }
+
+ if (method === METHOD.POST) {
+ return getName().then((name) => {
+ if (!name) {
+ throw new Error(`Can not post to window without target name`);
+ }
+
+ submitForm({
+ url: href,
+ target: name,
+ method,
+ body,
+ });
+ });
+ } else if (method === METHOD.GET) {
if (isSameDomain(win)) {
- return assertSameDomain(win).name;
+ try {
+ if (win.location && typeof win.location.replace === "function") {
+ // $FlowFixMe
+ win.location.replace(href);
+ return;
+ }
+ } catch (err) {
+ // pass
+ }
}
- return windowNamePromise;
+ win.location = href;
+ } else {
+ throw new Error(`Unsupported method: ${method}`);
+ }
});
- const getDefaultSetLocationOptions = () => {
- // $FlowFixMe
- return {};
- };
-
- const setLocation = (href : string, opts? : SetLocationOptions = getDefaultSetLocationOptions()) => winPromise.then(win => {
- const domain = `${ window.location.protocol }//${ window.location.host }`;
- const { method = METHOD.GET, body } = opts;
-
- if (href.indexOf('/') === 0) {
- href = `${ domain }${ href }`;
- } else if (!href.match(/^https?:\/\//) && href.indexOf(domain) !== 0) {
- throw new Error(`Expected url to be http or https url, or absolute path, got ${ JSON.stringify(href) }`);
+ return {
+ id,
+ getType: () => {
+ return windowTypePromise;
+ },
+ getInstanceID: memoizePromise(() =>
+ winPromise.then((win) => getWindowInstanceID(win, { send }))
+ ),
+ close: () => winPromise.then(closeWindow),
+ getName,
+ focus: () =>
+ winPromise.then((win) => {
+ win.focus();
+ }),
+ isClosed: () =>
+ winPromise.then((win) => {
+ return isWindowClosed(win);
+ }),
+ setLocation,
+ setName: (name) =>
+ winPromise.then((win) => {
+ if (__POST_ROBOT__.__IE_POPUP_SUPPORT__) {
+ linkWindow({ win, name });
}
- if (method === METHOD.POST) {
- return getName().then(name => {
- if (!name) {
- throw new Error(`Can not post to window without target name`);
- }
-
- submitForm({
- url: href,
- target: name,
- method,
- body
- });
- });
- } else if (method === METHOD.GET) {
- if (isSameDomain(win)) {
- try {
- if (win.location && typeof win.location.replace === 'function') {
- // $FlowFixMe
- win.location.replace(href);
- return;
- }
- } catch (err) {
- // pass
- }
- }
-
- win.location = href;
+ const sameDomain = isSameDomain(win);
+ const frame = getFrameForWindow(win);
- } else {
- throw new Error(`Unsupported method: ${ method }`);
+ if (!sameDomain) {
+ throw new Error(`Can not set name for cross-domain window: ${name}`);
}
- });
-
- return {
- id,
- getType: () => {
- return windowTypePromise;
- },
- getInstanceID: memoizePromise(() => winPromise.then(win => getWindowInstanceID(win, { send }))),
- close: () => winPromise.then(closeWindow),
- getName,
- focus: () => winPromise.then(win => {
- win.focus();
- }),
- isClosed: () => winPromise.then(win => {
- return isWindowClosed(win);
- }),
- setLocation,
- setName: (name) => winPromise.then(win => {
- if (__POST_ROBOT__.__IE_POPUP_SUPPORT__) {
- linkWindow({ win, name });
- }
- const sameDomain = isSameDomain(win);
- const frame = getFrameForWindow(win);
-
- if (!sameDomain) {
- throw new Error(`Can not set name for cross-domain window: ${ name }`);
- }
-
- assertSameDomain(win).name = name;
- if (frame) {
- frame.setAttribute('name', name);
- }
+ assertSameDomain(win).name = name;
+ if (frame) {
+ frame.setAttribute("name", name);
+ }
- windowNamePromise = ZalgoPromise.resolve(name);
- })
- };
+ windowNamePromise = ZalgoPromise.resolve(name);
+ }),
+ };
}
export class ProxyWindow {
-
- id : string;
- isProxyWindow : true = true;
- serializedWindow : SerializedWindowType;
- actualWindow : ?CrossDomainWindowType;
- actualWindowPromise : ZalgoPromise;
- send : SendType;
- name : string;
-
- constructor({ send, win, serializedWindow } : {| win? : CrossDomainWindowType, serializedWindow? : SerializedWindowType, send : SendType |}) {
- this.actualWindowPromise = new ZalgoPromise();
- this.serializedWindow = serializedWindow || getSerializedWindow(this.actualWindowPromise, { send });
-
- globalStore('idToProxyWindow').set(this.getID(), this);
- if (win) {
- this.setWindow(win, { send });
- }
- }
-
- getID() : string {
- return this.serializedWindow.id;
- }
-
- getType() : ZalgoPromise<$Values> {
- return this.serializedWindow.getType();
- }
-
- isPopup() : ZalgoPromise {
- return this.getType().then(type => {
- return type === WINDOW_TYPE.POPUP;
- });
- }
-
- setLocation(href : string, opts? : SetLocationOptions) : ZalgoPromise {
- return this.serializedWindow.setLocation(href, opts).then(() => this);
- }
-
- getName() : ZalgoPromise {
- return this.serializedWindow.getName();
- }
-
- setName(name : string) : ZalgoPromise {
- return this.serializedWindow.setName(name).then(() => this);
+ id: string;
+ isProxyWindow: true = true;
+ serializedWindow: SerializedWindowType;
+ actualWindow: ?CrossDomainWindowType;
+ actualWindowPromise: ZalgoPromise;
+ send: SendType;
+ name: string;
+
+ constructor({
+ send,
+ win,
+ serializedWindow,
+ }: {|
+ win?: CrossDomainWindowType,
+ serializedWindow?: SerializedWindowType,
+ send: SendType,
+ |}) {
+ this.actualWindowPromise = new ZalgoPromise();
+ this.serializedWindow =
+ serializedWindow ||
+ getSerializedWindow(this.actualWindowPromise, { send });
+
+ globalStore("idToProxyWindow").set(this.getID(), this);
+ if (win) {
+ this.setWindow(win, { send });
}
+ }
- close() : ZalgoPromise {
- return this.serializedWindow.close().then(() => this);
- }
-
- focus() : ZalgoPromise {
- const isPopupPromise = this.isPopup();
- const getNamePromise = this.getName();
-
- const reopenPromise = ZalgoPromise.hash({ isPopup: isPopupPromise, name: getNamePromise }).then(({ isPopup, name }) => {
- if (isPopup && name) {
- window.open('', name, 'noopener');
- }
- });
- const focusPromise = this.serializedWindow.focus();
-
- return ZalgoPromise.all([
- reopenPromise,
- focusPromise
- ]).then(() => this);
- }
-
- isClosed() : ZalgoPromise {
- return this.serializedWindow.isClosed();
- }
-
- getWindow() : ?CrossDomainWindowType {
- return this.actualWindow;
- }
-
- setWindow(win : CrossDomainWindowType, { send } : {| send : SendType |}) {
- this.actualWindow = win;
- this.actualWindowPromise.resolve(this.actualWindow);
- this.serializedWindow = getSerializedWindow(this.actualWindowPromise, { send, id: this.getID() });
- windowStore('winToProxyWindow').set(win, this);
- }
-
- awaitWindow() : ZalgoPromise {
- return this.actualWindowPromise;
- }
-
- matchWindow(win : CrossDomainWindowType, { send } : {| send : SendType |}) : ZalgoPromise {
- return ZalgoPromise.try(() => {
- if (this.actualWindow) {
- return win === this.actualWindow;
- }
-
- return ZalgoPromise.hash({
- proxyInstanceID: this.getInstanceID(),
- knownWindowInstanceID: getWindowInstanceID(win, { send })
- }).then(({ proxyInstanceID, knownWindowInstanceID }) => {
- const match = proxyInstanceID === knownWindowInstanceID;
-
- if (match) {
- this.setWindow(win, { send });
- }
-
- return match;
- });
- });
- }
+ getID(): string {
+ return this.serializedWindow.id;
+ }
- unwrap() : CrossDomainWindowType | ProxyWindow {
- return this.actualWindow || this;
- }
-
- getInstanceID() : ZalgoPromise {
- return this.serializedWindow.getInstanceID();
- }
+ getType(): ZalgoPromise<$Values> {
+ return this.serializedWindow.getType();
+ }
- shouldClean() : boolean {
- return Boolean(this.actualWindow && isWindowClosed(this.actualWindow));
- }
+ isPopup(): ZalgoPromise {
+ return this.getType().then((type) => {
+ return type === WINDOW_TYPE.POPUP;
+ });
+ }
+
+ setLocation(
+ href: string,
+ opts?: SetLocationOptions
+ ): ZalgoPromise {
+ return this.serializedWindow.setLocation(href, opts).then(() => this);
+ }
+
+ getName(): ZalgoPromise {
+ return this.serializedWindow.getName();
+ }
+
+ setName(name: string): ZalgoPromise {
+ return this.serializedWindow.setName(name).then(() => this);
+ }
+
+ close(): ZalgoPromise {
+ return this.serializedWindow.close().then(() => this);
+ }
+
+ focus(): ZalgoPromise {
+ const isPopupPromise = this.isPopup();
+ const getNamePromise = this.getName();
+
+ const reopenPromise = ZalgoPromise.hash({
+ isPopup: isPopupPromise,
+ name: getNamePromise,
+ }).then(({ isPopup, name }) => {
+ if (isPopup && name) {
+ window.open("", name, "noopener");
+ }
+ });
+ const focusPromise = this.serializedWindow.focus();
- serialize() : SerializedWindowType {
- return this.serializedWindow;
- }
+ return ZalgoPromise.all([reopenPromise, focusPromise]).then(() => this);
+ }
- static unwrap(win : CrossDomainWindowType | ProxyWindow) : CrossDomainWindowType | ProxyWindow {
- return ProxyWindow.isProxyWindow(win)
- // $FlowFixMe
- ? win.unwrap()
- : win;
- }
+ isClosed(): ZalgoPromise {
+ return this.serializedWindow.isClosed();
+ }
- static serialize(win : CrossDomainWindowType | ProxyWindow, { send } : {| send : SendType |}) : SerializedWindowType {
- cleanupProxyWindows();
- return ProxyWindow.toProxyWindow(win, { send }).serialize();
- }
+ getWindow(): ?CrossDomainWindowType {
+ return this.actualWindow;
+ }
- static deserialize(serializedWindow : SerializedWindowType, { send } : {| send : SendType |}) : ProxyWindow {
- cleanupProxyWindows();
- return globalStore('idToProxyWindow').get(serializedWindow.id) || new ProxyWindow({ serializedWindow, send });
- }
+ setWindow(win: CrossDomainWindowType, { send }: {| send: SendType |}) {
+ this.actualWindow = win;
+ this.actualWindowPromise.resolve(this.actualWindow);
+ this.serializedWindow = getSerializedWindow(this.actualWindowPromise, {
+ send,
+ id: this.getID(),
+ });
+ windowStore("winToProxyWindow").set(win, this);
+ }
+
+ awaitWindow(): ZalgoPromise {
+ return this.actualWindowPromise;
+ }
+
+ matchWindow(
+ win: CrossDomainWindowType,
+ { send }: {| send: SendType |}
+ ): ZalgoPromise {
+ return ZalgoPromise.try(() => {
+ if (this.actualWindow) {
+ return win === this.actualWindow;
+ }
+
+ return ZalgoPromise.hash({
+ proxyInstanceID: this.getInstanceID(),
+ knownWindowInstanceID: getWindowInstanceID(win, { send }),
+ }).then(({ proxyInstanceID, knownWindowInstanceID }) => {
+ const match = proxyInstanceID === knownWindowInstanceID;
+
+ if (match) {
+ this.setWindow(win, { send });
+ }
- static isProxyWindow(obj : CrossDomainWindowType | ProxyWindow) : boolean {
- // $FlowFixMe
- return Boolean(obj && !isWindow(obj) && obj.isProxyWindow);
+ return match;
+ });
+ });
+ }
+
+ unwrap(): CrossDomainWindowType | ProxyWindow {
+ return this.actualWindow || this;
+ }
+
+ getInstanceID(): ZalgoPromise {
+ return this.serializedWindow.getInstanceID();
+ }
+
+ shouldClean(): boolean {
+ return Boolean(this.actualWindow && isWindowClosed(this.actualWindow));
+ }
+
+ serialize(): SerializedWindowType {
+ return this.serializedWindow;
+ }
+
+ static unwrap(
+ win: CrossDomainWindowType | ProxyWindow
+ ): CrossDomainWindowType | ProxyWindow {
+ return ProxyWindow.isProxyWindow(win)
+ ? // $FlowFixMe
+ win.unwrap()
+ : win;
+ }
+
+ static serialize(
+ win: CrossDomainWindowType | ProxyWindow,
+ { send }: {| send: SendType |}
+ ): SerializedWindowType {
+ cleanupProxyWindows();
+ return ProxyWindow.toProxyWindow(win, { send }).serialize();
+ }
+
+ static deserialize(
+ serializedWindow: SerializedWindowType,
+ { send }: {| send: SendType |}
+ ): ProxyWindow {
+ cleanupProxyWindows();
+ return (
+ globalStore("idToProxyWindow").get(serializedWindow.id) ||
+ new ProxyWindow({ serializedWindow, send })
+ );
+ }
+
+ static isProxyWindow(obj: CrossDomainWindowType | ProxyWindow): boolean {
+ // $FlowFixMe
+ return Boolean(obj && !isWindow(obj) && obj.isProxyWindow);
+ }
+
+ static toProxyWindow(
+ win: CrossDomainWindowType | ProxyWindow,
+ { send }: {| send: SendType |}
+ ): ProxyWindow {
+ cleanupProxyWindows();
+
+ if (ProxyWindow.isProxyWindow(win)) {
+ // $FlowFixMe
+ return win;
}
- static toProxyWindow(win : CrossDomainWindowType | ProxyWindow, { send } : {| send : SendType |}) : ProxyWindow {
- cleanupProxyWindows();
+ // $FlowFixMe
+ const actualWindow: CrossDomainWindowType = win;
- if (ProxyWindow.isProxyWindow(win)) {
- // $FlowFixMe
- return win;
- }
-
- // $FlowFixMe
- const actualWindow : CrossDomainWindowType = win;
-
- return windowStore('winToProxyWindow').get(actualWindow) || new ProxyWindow({ win: actualWindow, send });
- }
+ return (
+ windowStore("winToProxyWindow").get(actualWindow) ||
+ new ProxyWindow({ win: actualWindow, send })
+ );
+ }
}
-export type SerializedWindow = CustomSerializedType;
-
-export function serializeWindow(destination : CrossDomainWindowType | ProxyWindow, domain : DomainMatcher, win : CrossDomainWindowType, { send } : {| send : SendType |}) : SerializedWindow {
- return serializeType(SERIALIZATION_TYPE.CROSS_DOMAIN_WINDOW, ProxyWindow.serialize(win, { send }));
+export type SerializedWindow = CustomSerializedType<
+ typeof SERIALIZATION_TYPE.CROSS_DOMAIN_WINDOW,
+ SerializedWindowType
+>;
+
+export function serializeWindow(
+ destination: CrossDomainWindowType | ProxyWindow,
+ domain: DomainMatcher,
+ win: CrossDomainWindowType,
+ { send }: {| send: SendType |}
+): SerializedWindow {
+ return serializeType(
+ SERIALIZATION_TYPE.CROSS_DOMAIN_WINDOW,
+ ProxyWindow.serialize(win, { send })
+ );
}
-export function deserializeWindow(source : CrossDomainWindowType | ProxyWindow, origin : string, win : SerializedWindowType, { send } : {| send : SendType |}) : ProxyWindow {
- return ProxyWindow.deserialize(win, { send });
+export function deserializeWindow(
+ source: CrossDomainWindowType | ProxyWindow,
+ origin: string,
+ win: SerializedWindowType,
+ { send }: {| send: SendType |}
+): ProxyWindow {
+ return ProxyWindow.deserialize(win, { send });
}
diff --git a/src/setup.js b/src/setup.js
index f07b9f39..1f172cd2 100644
--- a/src/setup.js
+++ b/src/setup.js
@@ -1,47 +1,70 @@
/* @flow */
-import type { CrossDomainWindowType, DomainMatcher } from '@krakenjs/cross-domain-utils/src';
+import type {
+ CrossDomainWindowType,
+ DomainMatcher,
+} from "@krakenjs/cross-domain-utils/src";
-import { initHello } from './lib';
-import { listenForMessages, stopListenForMessages, receiveMessage, setupGlobalReceiveMessage, cancelResponseListeners } from './drivers';
-import { getGlobal, deleteGlobal } from './global';
-import { on, send } from './public';
-import { setupBridge } from './bridge';
-import { serializeMessage as internalSerializeMessage, deserializeMessage as internalDeserializeMessage, ProxyWindow } from './serialize';
+import { initHello } from "./lib";
+import {
+ listenForMessages,
+ stopListenForMessages,
+ receiveMessage,
+ setupGlobalReceiveMessage,
+ cancelResponseListeners,
+} from "./drivers";
+import { getGlobal, deleteGlobal } from "./global";
+import { on, send } from "./public";
+import { setupBridge } from "./bridge";
+import {
+ serializeMessage as internalSerializeMessage,
+ deserializeMessage as internalDeserializeMessage,
+ ProxyWindow,
+} from "./serialize";
-export function serializeMessage(destination : CrossDomainWindowType | ProxyWindow, domain : DomainMatcher, obj : T) : string {
- return internalSerializeMessage(destination, domain, obj, { on, send });
+export function serializeMessage(
+ destination: CrossDomainWindowType | ProxyWindow,
+ domain: DomainMatcher,
+ obj: T
+): string {
+ return internalSerializeMessage(destination, domain, obj, { on, send });
}
-export function deserializeMessage(source : CrossDomainWindowType | ProxyWindow, origin : string, message : string) : T {
- return internalDeserializeMessage(source, origin, message, { on, send });
+export function deserializeMessage(
+ source: CrossDomainWindowType | ProxyWindow,
+ origin: string,
+ message: string
+): T {
+ return internalDeserializeMessage(source, origin, message, { on, send });
}
-export function createProxyWindow(win? : CrossDomainWindowType) : ProxyWindow {
- return new ProxyWindow({ send, win });
+export function createProxyWindow(win?: CrossDomainWindowType): ProxyWindow {
+ return new ProxyWindow({ send, win });
}
-export function toProxyWindow(win : CrossDomainWindowType | ProxyWindow) : ProxyWindow {
- return ProxyWindow.toProxyWindow(win, { send });
+export function toProxyWindow(
+ win: CrossDomainWindowType | ProxyWindow
+): ProxyWindow {
+ return ProxyWindow.toProxyWindow(win, { send });
}
export function setup() {
- if (!getGlobal().initialized) {
- getGlobal().initialized = true;
-
- setupGlobalReceiveMessage({ on, send });
- listenForMessages({ on, send });
-
- if (__POST_ROBOT__.__IE_POPUP_SUPPORT__) {
- setupBridge({ on, send, receiveMessage });
- }
-
- initHello({ on, send });
+ if (!getGlobal().initialized) {
+ getGlobal().initialized = true;
+
+ setupGlobalReceiveMessage({ on, send });
+ listenForMessages({ on, send });
+
+ if (__POST_ROBOT__.__IE_POPUP_SUPPORT__) {
+ setupBridge({ on, send, receiveMessage });
}
+
+ initHello({ on, send });
+ }
}
export function destroy() {
- cancelResponseListeners();
- stopListenForMessages();
- deleteGlobal();
+ cancelResponseListeners();
+ stopListenForMessages();
+ deleteGlobal();
}
diff --git a/src/types.js b/src/types.js
index 41eff84a..91629214 100644
--- a/src/types.js
+++ b/src/types.js
@@ -1,90 +1,98 @@
/* @flow */
-import type { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-import type { CrossDomainWindowType, DomainMatcher } from '@krakenjs/cross-domain-utils/src';
+import type { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+import type {
+ CrossDomainWindowType,
+ DomainMatcher,
+} from "@krakenjs/cross-domain-utils/src";
-import type { ProxyWindow } from './serialize/window';
+import type { ProxyWindow } from "./serialize/window";
// export something to force webpack to see this as an ES module
export const TYPES = true;
// eslint-disable-next-line flowtype/require-exact-type
export type CancelableType = {
- cancel : () => void
+ cancel: () => void,
};
-export type ErrorHandlerType = (err : mixed) => void;
+export type ErrorHandlerType = (err: mixed) => void;
export type HandlerType = ({|
- source : CrossDomainWindowType,
- origin : string,
- data : any // eslint-disable-line flowtype/no-weak-types
-|}) => (void | any | ZalgoPromise); // eslint-disable-line flowtype/no-weak-types
+ source: CrossDomainWindowType,
+ origin: string,
+ data: any, // eslint-disable-line flowtype/no-weak-types
+|}) => void | any | ZalgoPromise; // eslint-disable-line flowtype/no-weak-types
export type ServerOptionsType = {|
- handler? : ?HandlerType,
- errorHandler? : ?ErrorHandlerType,
- window? : CrossDomainWindowType | ProxyWindow,
- name? : ?string,
- domain? : ?DomainMatcher,
- once? : ?boolean,
- errorOnClose? : ?boolean
+ handler?: ?HandlerType,
+ errorHandler?: ?ErrorHandlerType,
+ window?: CrossDomainWindowType | ProxyWindow,
+ name?: ?string,
+ domain?: ?DomainMatcher,
+ once?: ?boolean,
+ errorOnClose?: ?boolean,
|};
export type OnType = (
- name : string,
- options : ServerOptionsType | HandlerType,
- handler : ?HandlerType
+ name: string,
+ options: ServerOptionsType | HandlerType,
+ handler: ?HandlerType
) => CancelableType;
type RegularRequestOptionsType = {|
- domain? : ?DomainMatcher,
- fireAndForget? : false,
- timeout? : ?number
+ domain?: ?DomainMatcher,
+ fireAndForget?: false,
+ timeout?: ?number,
|};
type FireAndForgetRequestOptionsType = {|
- domain? : ?DomainMatcher,
- fireAndForget : true,
- timeout? : ?number
+ domain?: ?DomainMatcher,
+ fireAndForget: true,
+ timeout?: ?number,
|};
-export type RequestOptionsType = RegularRequestOptionsType | FireAndForgetRequestOptionsType;
+export type RequestOptionsType =
+ | RegularRequestOptionsType
+ | FireAndForgetRequestOptionsType;
export type ResponseMessageEvent = {|
- source : CrossDomainWindowType,
- origin : string,
- data : Object
+ source: CrossDomainWindowType,
+ origin: string,
+ data: Object,
|};
type RegularSendType = (
- win : CrossDomainWindowType | ProxyWindow,
- name : string,
- data : ?Object,
- options? : RegularRequestOptionsType
+ win: CrossDomainWindowType | ProxyWindow,
+ name: string,
+ data: ?Object,
+ options?: RegularRequestOptionsType
) => ZalgoPromise;
type FireAndForgetSendType = (
- win : CrossDomainWindowType | ProxyWindow,
- name : string,
- data : ?Object,
- options? : FireAndForgetRequestOptionsType
+ win: CrossDomainWindowType | ProxyWindow,
+ name: string,
+ data: ?Object,
+ options?: FireAndForgetRequestOptionsType
) => ZalgoPromise;
export type SendType = RegularSendType & FireAndForgetSendType;
export type MessageEvent = {|
- source : CrossDomainWindowType,
- origin : string,
- data : string
+ source: CrossDomainWindowType,
+ origin: string,
+ data: string,
|};
// eslint-disable-next-line flowtype/require-exact-type
export type CrossDomainFunctionType = {
- (...args : A) : ZalgoPromise,
- fireAndForget : (...args : A) => ZalgoPromise,
- __id__? : string,
- __name__? : string
+ (...args: A): ZalgoPromise,
+ fireAndForget: (...args: A) => ZalgoPromise,
+ __id__?: string,
+ __name__?: string,
};
-export type ReceiveMessageType = (MessageEvent, {| on : OnType, send : SendType |}) => void;
+export type ReceiveMessageType = (
+ MessageEvent,
+ {| on: OnType, send: SendType |}
+) => void;
diff --git a/test/.eslintrc.js b/test/.eslintrc.js
index 59d1b440..68eb73b5 100644
--- a/test/.eslintrc.js
+++ b/test/.eslintrc.js
@@ -2,5 +2,6 @@
/* eslint import/no-commonjs: off */
module.exports = {
- 'extends': '../node_modules/@krakenjs/grumbler-scripts/config/.eslintrc-browser-test.js'
+ extends:
+ "../node_modules/@krakenjs/grumbler-scripts/config/.eslintrc-browser-test.js",
};
diff --git a/test/bridge.htm b/test/bridge.htm
index 11fda520..36dc6679 100644
--- a/test/bridge.htm
+++ b/test/bridge.htm
@@ -1,6 +1,6 @@
-
\ No newline at end of file
+
diff --git a/test/child.htm b/test/child.htm
index 94acc762..91bf346f 100644
--- a/test/child.htm
+++ b/test/child.htm
@@ -1,9 +1,9 @@
-
\ No newline at end of file
+
diff --git a/test/child.js b/test/child.js
index 4876249a..e44cc9d4 100644
--- a/test/child.js
+++ b/test/child.js
@@ -1,24 +1,25 @@
/* @flow */
-import { send, on, once } from '../src';
+import { send, on, once } from "../src";
-on('sendMessageToParent', ({ data }) => {
- return send(window.opener || window.parent, data.messageName, data.data)
- .then((event) => event.data);
+on("sendMessageToParent", ({ data }) => {
+ return send(window.opener || window.parent, data.messageName, data.data).then(
+ (event) => event.data
+ );
});
-on('setupListener', ({ data }) => {
- once(data.messageName, () => {
- return data.handler ? data.handler() : data.data;
- });
+on("setupListener", ({ data }) => {
+ once(data.messageName, () => {
+ return data.handler ? data.handler() : data.data;
+ });
});
-on('waitForMessage', ({ data }) => {
- return once(data.messageName, () => {
- return data.handler ? data.handler() : data.data;
- }).then((event) => event.data);
+on("waitForMessage", ({ data }) => {
+ return once(data.messageName, () => {
+ return data.handler ? data.handler() : data.data;
+ }).then((event) => event.data);
});
-window.addEventListener('error', () => {
- // pass
+window.addEventListener("error", () => {
+ // pass
});
diff --git a/test/common.js b/test/common.js
index bd7b035e..b86d11f1 100644
--- a/test/common.js
+++ b/test/common.js
@@ -1,50 +1,63 @@
/* @flow */
-import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-import { getBody, noop } from '@krakenjs/belter/src';
-import { type CrossDomainWindowType } from '@krakenjs/cross-domain-utils/src';
+import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+import { getBody, noop } from "@krakenjs/belter/src";
+import { type CrossDomainWindowType } from "@krakenjs/cross-domain-utils/src";
-import { awaitWindowHello } from '../src/lib';
+import { awaitWindowHello } from "../src/lib";
-window.mockDomain = 'mock://test-post-robot.com';
+window.mockDomain = "mock://test-post-robot.com";
window.console.karma = (...args) => {
- const karma = window.karma || (window.top && window.top.karma) || (window.opener && window.opener.karma);
- if (karma) {
- karma.log('debug', args);
- }
- // eslint-disable-next-line no-console
- console.log(...args);
+ const karma =
+ window.karma ||
+ (window.top && window.top.karma) ||
+ (window.opener && window.opener.karma);
+ if (karma) {
+ karma.log("debug", args);
+ }
+ // eslint-disable-next-line no-console
+ console.log(...args);
};
-const IE8_USER_AGENT = 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)';
+const IE8_USER_AGENT =
+ "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)";
-export function enableIE8Mode() : {| cancel : () => void |} {
- window.navigator.mockUserAgent = IE8_USER_AGENT;
+export function enableIE8Mode(): {| cancel: () => void |} {
+ window.navigator.mockUserAgent = IE8_USER_AGENT;
- return {
- cancel() {
- delete window.navigator.mockUserAgent;
- }
- };
+ return {
+ cancel() {
+ delete window.navigator.mockUserAgent;
+ },
+ };
}
-export function createIframe(name : string, callback? : () => void) : CrossDomainWindowType {
- const frame = document.createElement('iframe');
- frame.src = `/base/test/${ name }`;
- frame.id = 'childframe';
- frame.name = `${ Math.random().toString() }_${ name.replace(/[^a-zA-Z0-9]+/g, '_') }`;
- if (callback) {
- frame.addEventListener('load', callback);
- }
- getBody().appendChild(frame);
- return frame.contentWindow;
+export function createIframe(
+ name: string,
+ callback?: () => void
+): CrossDomainWindowType {
+ const frame = document.createElement("iframe");
+ frame.src = `/base/test/${name}`;
+ frame.id = "childframe";
+ frame.name = `${Math.random().toString()}_${name.replace(
+ /[^a-zA-Z0-9]+/g,
+ "_"
+ )}`;
+ if (callback) {
+ frame.addEventListener("load", callback);
+ }
+ getBody().appendChild(frame);
+ return frame.contentWindow;
}
-export function createPopup(name : string) : CrossDomainWindowType {
- const popup = window.open(`mock://test-post-robot-child.com/base/test/${ name }`, `${ Math.random().toString() }_${ name.replace(/[^a-zA-Z0-9]+/g, '_') }`);
- window.focus();
- return popup;
+export function createPopup(name: string): CrossDomainWindowType {
+ const popup = window.open(
+ `mock://test-post-robot-child.com/base/test/${name}`,
+ `${Math.random().toString()}_${name.replace(/[^a-zA-Z0-9]+/g, "_")}`
+ );
+ window.focus();
+ return popup;
}
let childWindow;
@@ -52,49 +65,49 @@ let childFrame;
let otherChildFrame;
type Windows = {|
- childWindow : CrossDomainWindowType,
- childFrame : CrossDomainWindowType,
- otherChildFrame : CrossDomainWindowType
+ childWindow: CrossDomainWindowType,
+ childFrame: CrossDomainWindowType,
+ otherChildFrame: CrossDomainWindowType,
|};
-export function getWindows() : Windows {
- if (!childFrame || !childWindow || !otherChildFrame) {
- throw new Error(`Not all windows available`);
- }
+export function getWindows(): Windows {
+ if (!childFrame || !childWindow || !otherChildFrame) {
+ throw new Error(`Not all windows available`);
+ }
- return {
- childWindow,
- childFrame,
- otherChildFrame
- };
+ return {
+ childWindow,
+ childFrame,
+ otherChildFrame,
+ };
}
-before(() : ZalgoPromise => {
- childWindow = createPopup('child.htm');
- childFrame = createIframe('child.htm');
- otherChildFrame = createIframe('child.htm');
+before((): ZalgoPromise => {
+ childWindow = createPopup("child.htm");
+ childFrame = createIframe("child.htm");
+ otherChildFrame = createIframe("child.htm");
- return ZalgoPromise.all([
- awaitWindowHello(childWindow),
- awaitWindowHello(childFrame),
- awaitWindowHello(otherChildFrame)
- ]).then(noop);
+ return ZalgoPromise.all([
+ awaitWindowHello(childWindow),
+ awaitWindowHello(childFrame),
+ awaitWindowHello(otherChildFrame),
+ ]).then(noop);
});
after(() => {
- if (!document.body) {
- throw new Error(`Expected document.body to be available`);
- }
- const body = document.body;
- // $FlowFixMe
- if (!childFrame.frameElement) {
- throw new Error(`Expected childFrame.frameElement to be available`);
- }
- body.removeChild(childFrame.frameElement);
- // $FlowFixMe
- if (!otherChildFrame.frameElement) {
- throw new Error(`Expected otherChildFrame.frameElement to be available`);
- }
- body.removeChild(otherChildFrame.frameElement);
- childWindow.close();
+ if (!document.body) {
+ throw new Error(`Expected document.body to be available`);
+ }
+ const body = document.body;
+ // $FlowFixMe
+ if (!childFrame.frameElement) {
+ throw new Error(`Expected childFrame.frameElement to be available`);
+ }
+ body.removeChild(childFrame.frameElement);
+ // $FlowFixMe
+ if (!otherChildFrame.frameElement) {
+ throw new Error(`Expected otherChildFrame.frameElement to be available`);
+ }
+ body.removeChild(otherChildFrame.frameElement);
+ childWindow.close();
});
diff --git a/test/index.js b/test/index.js
index afd7a8c0..fe522d7f 100644
--- a/test/index.js
+++ b/test/index.js
@@ -1,3 +1,3 @@
/* @flow */
-import './tests';
+import "./tests";
diff --git a/test/tests/error.js b/test/tests/error.js
index 7071dfb4..2a43d10e 100644
--- a/test/tests/error.js
+++ b/test/tests/error.js
@@ -1,81 +1,94 @@
/* @flow */
/* eslint max-lines: 0 */
-import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-import { wrapPromise } from '@krakenjs/belter/src';
-
-import { on, send } from '../../src';
-import { getWindows } from '../common';
-
-describe('Error cases', () => {
-
- it('should get an error when messaging with an unknown name', () : ZalgoPromise => {
- const { childFrame } = getWindows();
-
- return send(childFrame, 'doesntexist').then(() => {
- throw new Error('Expected success handler to not be called');
- }, (err) => {
- if (!err) {
- throw new Error(`Expected err`);
- }
- });
- });
-
- it('should error out if you try to register the same listener name twice', () => {
-
- on('onceonly', () => {
- // pass
- });
-
- try {
- on('onceonly', () => {
- // pass
- });
- } catch (err) {
- if (!err) {
- throw new Error(`Expected err`);
- }
- return;
+import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+import { wrapPromise } from "@krakenjs/belter/src";
+
+import { on, send } from "../../src";
+import { getWindows } from "../common";
+
+describe("Error cases", () => {
+ it("should get an error when messaging with an unknown name", (): ZalgoPromise => {
+ const { childFrame } = getWindows();
+
+ return send(childFrame, "doesntexist").then(
+ () => {
+ throw new Error("Expected success handler to not be called");
+ },
+ (err) => {
+ if (!err) {
+ throw new Error(`Expected err`);
}
+ }
+ );
+ });
- throw new Error('Expected error handler to be called');
+ it("should error out if you try to register the same listener name twice", () => {
+ on("onceonly", () => {
+ // pass
});
- it('should fail to send a message when the expected domain does not match', () => {
- return wrapPromise(({ expect, avoid }) => {
- const { childFrame } = getWindows();
-
- on('foobuzzzzz', { domain: 'http://www.zombo.com' }, avoid('onFoobuzzzzz'));
-
- send(childFrame, 'sendMessageToParent', {
- messageName: 'foobuzzzzz'
- }).then(avoid('successHandler'), expect('errorHandler', (err) => {
- if (!err) {
- throw new Error(`Expected err`);
- }
- }));
- });
+ try {
+ on("onceonly", () => {
+ // pass
+ });
+ } catch (err) {
+ if (!err) {
+ throw new Error(`Expected err`);
+ }
+ return;
+ }
+
+ throw new Error("Expected error handler to be called");
+ });
+
+ it("should fail to send a message when the expected domain does not match", () => {
+ return wrapPromise(({ expect, avoid }) => {
+ const { childFrame } = getWindows();
+
+ on(
+ "foobuzzzzz",
+ { domain: "http://www.zombo.com" },
+ avoid("onFoobuzzzzz")
+ );
+
+ send(childFrame, "sendMessageToParent", {
+ messageName: "foobuzzzzz",
+ }).then(
+ avoid("successHandler"),
+ expect("errorHandler", (err) => {
+ if (!err) {
+ throw new Error(`Expected err`);
+ }
+ })
+ );
});
-
- it('should fail to send a message when the target domain does not match', () : ZalgoPromise => {
- const { childFrame } = getWindows();
-
- return send(childFrame, 'setupListener', {
-
- messageName: 'foo',
- data: {
- foo: 'bar'
- }
-
- }).then(() => {
-
- return send(childFrame, 'foo', {}, { domain: 'http://www.zombo.com' }).then(() => {
- throw new Error('Expected success handler to not be called');
- }, (err) => {
- if (!err) {
- throw new Error(`Expected err`);
- }
- });
- });
+ });
+
+ it("should fail to send a message when the target domain does not match", (): ZalgoPromise => {
+ const { childFrame } = getWindows();
+
+ return send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ foo: "bar",
+ },
+ }).then(() => {
+ return send(
+ childFrame,
+ "foo",
+ {},
+ { domain: "http://www.zombo.com" }
+ ).then(
+ () => {
+ throw new Error("Expected success handler to not be called");
+ },
+ (err) => {
+ if (!err) {
+ throw new Error(`Expected err`);
+ }
+ }
+ );
});
+ });
});
diff --git a/test/tests/happy.js b/test/tests/happy.js
index af759121..128f418d 100644
--- a/test/tests/happy.js
+++ b/test/tests/happy.js
@@ -1,133 +1,149 @@
/* @flow */
/* eslint max-lines: 0 */
-import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-import { wrapPromise } from '@krakenjs/belter/src';
+import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+import { wrapPromise } from "@krakenjs/belter/src";
-import { on, send } from '../../src';
-import { getWindows } from '../common';
+import { on, send } from "../../src";
+import { getWindows } from "../common";
-describe('Happy cases', () => {
+describe("Happy cases", () => {
+ it("should set up a simple server and listen for a request", () => {
+ return wrapPromise(({ expect }) => {
+ const { childFrame } = getWindows();
- it('should set up a simple server and listen for a request', () => {
- return wrapPromise(({ expect }) => {
- const { childFrame } = getWindows();
+ on("foobu", expect("onFoobu"));
- on('foobu', expect('onFoobu'));
-
- return send(childFrame, 'sendMessageToParent', {
- messageName: 'foobu'
- }).then(expect('sendSuccess'));
- });
+ return send(childFrame, "sendMessageToParent", {
+ messageName: "foobu",
+ }).then(expect("sendSuccess"));
});
+ });
- it('should set up a simple server and listen for multiple requests', () : ZalgoPromise => {
- const { childFrame } = getWindows();
+ it("should set up a simple server and listen for multiple requests", (): ZalgoPromise => {
+ const { childFrame } = getWindows();
- let count = 0;
-
- on('multilistener', () => {
- count += 1;
- });
+ let count = 0;
- return send(childFrame, 'sendMessageToParent', {
- messageName: 'multilistener'
- }).then(() => {
- return send(childFrame, 'sendMessageToParent', {
- messageName: 'multilistener'
- });
- }).then(() => {
- if (count !== 2) {
- throw new Error(`Expected count to be 2, got ${ count }`);
- }
- });
+ on("multilistener", () => {
+ count += 1;
});
- it('should message a child and expect a response', () : ZalgoPromise => {
- const { childFrame } = getWindows();
-
- return send(childFrame, 'setupListener', {
-
- messageName: 'foo',
- data: {
- foo: 'bar'
- }
-
- }).then(() => {
-
- return send(childFrame, 'foo').then(({ data }) => {
- if (data.foo !== 'bar') {
- throw new Error(`Expected data.foo to be 'bar', got ${ data.foo }`);
- }
- });
+ return send(childFrame, "sendMessageToParent", {
+ messageName: "multilistener",
+ })
+ .then(() => {
+ return send(childFrame, "sendMessageToParent", {
+ messageName: "multilistener",
});
+ })
+ .then(() => {
+ if (count !== 2) {
+ throw new Error(`Expected count to be 2, got ${count}`);
+ }
+ });
+ });
+
+ it("should message a child and expect a response", (): ZalgoPromise => {
+ const { childFrame } = getWindows();
+
+ return send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ foo: "bar",
+ },
+ }).then(() => {
+ return send(childFrame, "foo").then(({ data }) => {
+ if (data.foo !== "bar") {
+ throw new Error(`Expected data.foo to be 'bar', got ${data.foo}`);
+ }
+ });
});
+ });
- it('should set up a simple server and listen for a request from a specific domain', () => {
- return wrapPromise(({ expect }) => {
- const { childFrame } = getWindows();
+ it("should set up a simple server and listen for a request from a specific domain", () => {
+ return wrapPromise(({ expect }) => {
+ const { childFrame } = getWindows();
- on('domainspecificmessage', { domain: 'mock://test-post-robot-child.com' }, expect('onDomainspecificmessage'));
+ on(
+ "domainspecificmessage",
+ { domain: "mock://test-post-robot-child.com" },
+ expect("onDomainspecificmessage")
+ );
- return send(childFrame, 'sendMessageToParent', {
- messageName: 'domainspecificmessage'
- }).then(expect('sendSuccess'));
- });
+ return send(childFrame, "sendMessageToParent", {
+ messageName: "domainspecificmessage",
+ }).then(expect("sendSuccess"));
});
-
-
- it('should message a child with a specific domain and expect a response', () : ZalgoPromise => {
- const { childFrame } = getWindows();
-
- return send(childFrame, 'setupListener', {
-
- messageName: 'domainspecificmessage',
- data: {
- foo: 'bar'
- }
-
- }, { domain: 'mock://test-post-robot-child.com' }).then(() => {
-
- return send(childFrame, 'domainspecificmessage').then(({ data }) => {
- if (data.foo !== 'bar') {
- throw new Error(`Expected data.foo to be 'bar', got ${ data.foo }`);
- }
- });
- });
+ });
+
+ it("should message a child with a specific domain and expect a response", (): ZalgoPromise => {
+ const { childFrame } = getWindows();
+
+ return send(
+ childFrame,
+ "setupListener",
+ {
+ messageName: "domainspecificmessage",
+ data: {
+ foo: "bar",
+ },
+ },
+ { domain: "mock://test-post-robot-child.com" }
+ ).then(() => {
+ return send(childFrame, "domainspecificmessage").then(({ data }) => {
+ if (data.foo !== "bar") {
+ throw new Error(`Expected data.foo to be 'bar', got ${data.foo}`);
+ }
+ });
});
-
- it('should set up a simple server and listen for a request from multiple domains', () => {
- return wrapPromise(({ expect }) => {
- const { childFrame } = getWindows();
-
- on('multidomainspecificmessage', { domain: [ 'mock://test-post-robot-child.com', 'mock://non-existant-domain.com' ] }, expect('onMultidomainspecificmessage'));
-
- send(childFrame, 'sendMessageToParent', {
- messageName: 'multidomainspecificmessage'
- }).then(expect('sendSuccess'));
- });
+ });
+
+ it("should set up a simple server and listen for a request from multiple domains", () => {
+ return wrapPromise(({ expect }) => {
+ const { childFrame } = getWindows();
+
+ on(
+ "multidomainspecificmessage",
+ {
+ domain: [
+ "mock://test-post-robot-child.com",
+ "mock://non-existant-domain.com",
+ ],
+ },
+ expect("onMultidomainspecificmessage")
+ );
+
+ send(childFrame, "sendMessageToParent", {
+ messageName: "multidomainspecificmessage",
+ }).then(expect("sendSuccess"));
});
-
-
- it('should message a child with multiple domains and expect a response', () : ZalgoPromise => {
- const { childFrame } = getWindows();
-
- return send(childFrame, 'setupListener', {
-
- messageName: 'multidomainspecificmessage',
- data: {
- foo: 'bar'
- }
-
- }, { domain: [ 'mock://test-post-robot-child.com', 'mock://non-existant-domain.com' ] }).then(() => {
-
- return send(childFrame, 'multidomainspecificmessage').then(({ data }) => {
- if (data.foo !== 'bar') {
- throw new Error(`Expected data.foo to be 'bar', got ${ data.foo }`);
- }
- });
- });
+ });
+
+ it("should message a child with multiple domains and expect a response", (): ZalgoPromise => {
+ const { childFrame } = getWindows();
+
+ return send(
+ childFrame,
+ "setupListener",
+ {
+ messageName: "multidomainspecificmessage",
+ data: {
+ foo: "bar",
+ },
+ },
+ {
+ domain: [
+ "mock://test-post-robot-child.com",
+ "mock://non-existant-domain.com",
+ ],
+ }
+ ).then(() => {
+ return send(childFrame, "multidomainspecificmessage").then(({ data }) => {
+ if (data.foo !== "bar") {
+ throw new Error(`Expected data.foo to be 'bar', got ${data.foo}`);
+ }
+ });
});
+ });
});
-
-
diff --git a/test/tests/index.js b/test/tests/index.js
index 70560037..9fecf8f4 100644
--- a/test/tests/index.js
+++ b/test/tests/index.js
@@ -1,8 +1,8 @@
/* @flow */
-import './happy';
-import './options';
-import './serialization';
-import './popup';
-import './error';
-import './window-proxy';
+import "./happy";
+import "./options";
+import "./serialization";
+import "./popup";
+import "./error";
+import "./window-proxy";
diff --git a/test/tests/options.js b/test/tests/options.js
index 4c02aea1..55e6cc33 100644
--- a/test/tests/options.js
+++ b/test/tests/options.js
@@ -1,107 +1,112 @@
/* @flow */
/* eslint max-lines: 0 */
-import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
+import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
-import { on, send, once } from '../../src';
-import { getWindows } from '../common';
+import { on, send, once } from "../../src";
+import { getWindows } from "../common";
-describe('Options cases', () => {
+describe("Options cases", () => {
+ it("should be able to listen for a message only once", (): ZalgoPromise => {
+ const { childFrame } = getWindows();
- it('should be able to listen for a message only once', () : ZalgoPromise => {
- const { childFrame } = getWindows();
+ let count = 0;
- let count = 0;
-
- once('foobuz', () => {
- count += 1;
- });
-
- return send(childFrame, 'sendMessageToParent', {
- messageName: 'foobuz'
- }).then(() => {
- return send(childFrame, 'sendMessageToParent', {
- messageName: 'foobuz'
- }).then(() => {
- throw new Error('Expected success handler to not be called');
- }, () => {
- if (count !== 1) {
- throw new Error(`Expected count to be 1, got ${ count }`);
- }
- });
- });
+ once("foobuz", () => {
+ count += 1;
});
- it('should be able to re-register the same once handler after the first is called', () : ZalgoPromise => {
- const { childFrame } = getWindows();
+ return send(childFrame, "sendMessageToParent", {
+ messageName: "foobuz",
+ }).then(() => {
+ return send(childFrame, "sendMessageToParent", {
+ messageName: "foobuz",
+ }).then(
+ () => {
+ throw new Error("Expected success handler to not be called");
+ },
+ () => {
+ if (count !== 1) {
+ throw new Error(`Expected count to be 1, got ${count}`);
+ }
+ }
+ );
+ });
+ });
- let count = 0;
+ it("should be able to re-register the same once handler after the first is called", (): ZalgoPromise => {
+ const { childFrame } = getWindows();
- once('foobuzz', ({ data }) => {
- count += data.add;
- });
+ let count = 0;
- return send(childFrame, 'sendMessageToParent', {
- messageName: 'foobuzz',
- data: {
- add: 2
- }
- }).then(() => {
-
- once('foobuzz', ({ data }) => {
- count += data.add;
- });
-
- return send(childFrame, 'sendMessageToParent', {
- messageName: 'foobuzz',
- data: {
- add: 3
- }
- });
-
- }).then(() => {
- if (count !== 5) {
- throw new Error(`Expected count to be 5, got ${ count }`);
- }
- });
+ once("foobuzz", ({ data }) => {
+ count += data.add;
});
- it('should allow you to register the same listener twice providing it is to different windows', () => {
- const { childFrame, otherChildFrame } = getWindows();
-
- on('onceonlywindow', { window: childFrame }, () => {
- // pass
+ return send(childFrame, "sendMessageToParent", {
+ messageName: "foobuzz",
+ data: {
+ add: 2,
+ },
+ })
+ .then(() => {
+ once("foobuzz", ({ data }) => {
+ count += data.add;
});
- on('onceonlywindow', { window: otherChildFrame }, () => {
- // pass
+ return send(childFrame, "sendMessageToParent", {
+ messageName: "foobuzz",
+ data: {
+ add: 3,
+ },
});
+ })
+ .then(() => {
+ if (count !== 5) {
+ throw new Error(`Expected count to be 5, got ${count}`);
+ }
+ });
+ });
+
+ it("should allow you to register the same listener twice providing it is to different windows", () => {
+ const { childFrame, otherChildFrame } = getWindows();
+
+ on("onceonlywindow", { window: childFrame }, () => {
+ // pass
});
- it('should allow you to register a listener for a specific window', () : ZalgoPromise => {
- const { childFrame, otherChildFrame } = getWindows();
+ on("onceonlywindow", { window: otherChildFrame }, () => {
+ // pass
+ });
+ });
- let count = 0;
+ it("should allow you to register a listener for a specific window", (): ZalgoPromise => {
+ const { childFrame, otherChildFrame } = getWindows();
- on('specificchildlistener', { window: otherChildFrame }, () => {
- count += 1;
- });
+ let count = 0;
- return send(otherChildFrame, 'sendMessageToParent', {
- messageName: 'specificchildlistener'
- }).then(() => {
- return send(childFrame, 'sendMessageToParent', {
- messageName: 'specificchildlistener'
- }).then(() => {
- throw new Error('Expected success handler to not be called');
- }, (err) => {
- if (!err) {
- throw new Error(`Expected err`);
- }
- if (count !== 1) {
- throw new Error(`Expected count to be 1, got ${ count }`);
- }
- });
- });
+ on("specificchildlistener", { window: otherChildFrame }, () => {
+ count += 1;
+ });
+
+ return send(otherChildFrame, "sendMessageToParent", {
+ messageName: "specificchildlistener",
+ }).then(() => {
+ return send(childFrame, "sendMessageToParent", {
+ messageName: "specificchildlistener",
+ }).then(
+ () => {
+ throw new Error("Expected success handler to not be called");
+ },
+ (err) => {
+ if (!err) {
+ throw new Error(`Expected err`);
+ }
+ if (count !== 1) {
+ throw new Error(`Expected count to be 1, got ${count}`);
+ }
+ }
+ );
});
+ });
});
diff --git a/test/tests/popup.js b/test/tests/popup.js
index 5f344ac8..1e80d5ec 100644
--- a/test/tests/popup.js
+++ b/test/tests/popup.js
@@ -1,61 +1,58 @@
/* @flow */
/* eslint max-lines: 0 */
-import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-
-import { send, bridge } from '../../src';
-import { awaitWindowHello } from '../../src/lib';
-import { enableIE8Mode, createPopup, getWindows } from '../common';
-
-describe('Popup cases', () => {
-
- it('should work with a popup window', () : ZalgoPromise => {
- const { childWindow } = getWindows();
-
- return send(childWindow, 'setupListener', {
-
- messageName: 'foo',
- data: {
- foo: 'bar'
- }
-
- }).then(() => {
-
- return send(childWindow, 'foo').then(({ data }) => {
- if (data.foo !== 'bar') {
- throw new Error(`Expected data.foo to be 'bar', got ${ data.foo }`);
- }
- });
- });
- });
-
- it('should succeed messaging popup when emulating IE', () : ZalgoPromise => {
- const ie8mode = enableIE8Mode();
-
- if (!bridge) {
- throw new Error(`Bridge not found`);
+import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+
+import { send, bridge } from "../../src";
+import { awaitWindowHello } from "../../src/lib";
+import { enableIE8Mode, createPopup, getWindows } from "../common";
+
+describe("Popup cases", () => {
+ it("should work with a popup window", (): ZalgoPromise => {
+ const { childWindow } = getWindows();
+
+ return send(childWindow, "setupListener", {
+ messageName: "foo",
+ data: {
+ foo: "bar",
+ },
+ }).then(() => {
+ return send(childWindow, "foo").then(({ data }) => {
+ if (data.foo !== "bar") {
+ throw new Error(`Expected data.foo to be 'bar', got ${data.foo}`);
}
-
- return bridge.openBridge('/base/test/bridge.htm', 'mock://test-post-robot-child.com').then(() => {
- const ie8Window = createPopup('child.htm');
-
- return awaitWindowHello(ie8Window).then(() => {
- return send(ie8Window, 'setupListener', {
-
- messageName: 'foo',
- data: {
- foo: 'bar'
- }
-
- });
-
- }).then(() => {
- return send(ie8Window, 'foo');
-
- }).then(() => {
- ie8Window.close();
- ie8mode.cancel();
- });
- });
+ });
});
+ });
+
+ it("should succeed messaging popup when emulating IE", (): ZalgoPromise => {
+ const ie8mode = enableIE8Mode();
+
+ if (!bridge) {
+ throw new Error(`Bridge not found`);
+ }
+
+ return bridge
+ .openBridge("/base/test/bridge.htm", "mock://test-post-robot-child.com")
+ .then(() => {
+ const ie8Window = createPopup("child.htm");
+
+ return awaitWindowHello(ie8Window)
+ .then(() => {
+ return send(ie8Window, "setupListener", {
+ messageName: "foo",
+ data: {
+ foo: "bar",
+ },
+ });
+ })
+ .then(() => {
+ return send(ie8Window, "foo");
+ })
+ .then(() => {
+ ie8Window.close();
+ ie8mode.cancel();
+ });
+ });
+ });
});
diff --git a/test/tests/serialization.js b/test/tests/serialization.js
index 151fc511..6bf62938 100644
--- a/test/tests/serialization.js
+++ b/test/tests/serialization.js
@@ -1,691 +1,693 @@
/* @flow */
/* eslint max-lines: 0 */
-import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
-import { WINDOW_TYPE } from '@krakenjs/cross-domain-utils/src';
-import { uniqueID, getBody } from '@krakenjs/belter/src';
-
-import { send } from '../../src';
-import { awaitWindowHello } from '../../src/lib';
-import { createIframe, getWindows } from '../common';
-
-describe('Serialization cases', () => {
-
- it('should pass a function across windows and be able to call it later', () => {
- const { childFrame } = getWindows();
-
- const expectedArgument = 567;
- let actualArgument;
- const expectedReturn = 'hello world';
-
- const myfunction = (val) => {
- actualArgument = val;
- return expectedReturn;
- };
-
- return send(childFrame, 'setupListener', {
-
- messageName: 'foo',
- data: {
- myfunction
- }
-
- }).then(() => {
- return send(childFrame, 'foo');
-
- }).then(({ data }) => {
- return data.myfunction(expectedArgument);
-
- }).then(result => {
- if (actualArgument !== expectedArgument) {
- throw new Error(`Expected function to accept ${ expectedArgument }, got ${ actualArgument }`);
- }
-
- if (result !== expectedReturn) {
- throw new Error(`Expected function to return ${ expectedReturn }, got ${ result }`);
- }
- });
- });
+import { ZalgoPromise } from "@krakenjs/zalgo-promise/src";
+import { WINDOW_TYPE } from "@krakenjs/cross-domain-utils/src";
+import { uniqueID, getBody } from "@krakenjs/belter/src";
+
+import { send } from "../../src";
+import { awaitWindowHello } from "../../src/lib";
+import { createIframe, getWindows } from "../common";
+
+describe("Serialization cases", () => {
+ it("should pass a function across windows and be able to call it later", () => {
+ const { childFrame } = getWindows();
+
+ const expectedArgument = 567;
+ let actualArgument;
+ const expectedReturn = "hello world";
+
+ const myfunction = (val) => {
+ actualArgument = val;
+ return expectedReturn;
+ };
+
+ return send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ myfunction,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
+ return data.myfunction(expectedArgument);
+ })
+ .then((result) => {
+ if (actualArgument !== expectedArgument) {
+ throw new Error(
+ `Expected function to accept ${expectedArgument}, got ${actualArgument}`
+ );
+ }
- it('should pass a function across windows and be able to call it later and capture the exception', () => {
- const { childFrame } = getWindows();
+ if (result !== expectedReturn) {
+ throw new Error(
+ `Expected function to return ${expectedReturn}, got ${result}`
+ );
+ }
+ });
+ });
+
+ it("should pass a function across windows and be able to call it later and capture the exception", () => {
+ const { childFrame } = getWindows();
+
+ const expectedErrorMessage = "something went wrong";
+ const expectedErrorCode = "ERROR_567";
+ let expectedErrorStack;
+
+ const myfunction = () => {
+ const err = new Error(expectedErrorMessage);
+ // $FlowFixMe
+ err.code = expectedErrorCode;
+ expectedErrorStack = err.stack;
+ throw err;
+ };
+
+ return send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ myfunction,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
+ return data.myfunction();
+ })
+ .catch((err) => {
+ if (!(err instanceof Error)) {
+ throw new TypeError(`Expected err to be an Error instance`);
+ }
- const expectedErrorMessage = 'something went wrong';
- const expectedErrorCode = 'ERROR_567';
- let expectedErrorStack;
+ if (err.message !== expectedErrorMessage) {
+ throw new Error(
+ `Expected function throw error with message ${expectedErrorMessage}, got ${err.message}`
+ );
+ }
- const myfunction = () => {
- const err = new Error(expectedErrorMessage);
+ // $FlowFixMe
+ if (err.code !== expectedErrorCode) {
+ throw new Error(
// $FlowFixMe
- err.code = expectedErrorCode;
- expectedErrorStack = err.stack;
- throw err;
- };
-
- return send(childFrame, 'setupListener', {
+ `Expected function throw error with code ${expectedErrorCode}, got ${err.code}`
+ );
+ }
- messageName: 'foo',
- data: {
- myfunction
- }
+ if (!expectedErrorStack) {
+ throw new Error(`Expected error to have stack`);
+ }
- }).then(() => {
- return send(childFrame, 'foo');
+ if (err.stack.indexOf(expectedErrorStack) === -1) {
+ throw new Error(
+ `Expected function throw error with stack ${expectedErrorStack}, got ${err.stack}`
+ );
+ }
+ });
+ });
+
+ it("should pass a function across windows and be able to call it instantly from its origin window", () => {
+ const { childFrame } = getWindows();
+
+ const expectedArgument = 567;
+ let actualArgument;
+ const expectedReturn = "hello world";
+
+ const myfunction = (val) => {
+ actualArgument = val;
+ return expectedReturn;
+ };
+
+ return send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ myfunction,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
+ const promise = data.myfunction(expectedArgument);
+
+ if (actualArgument !== expectedArgument) {
+ throw new Error(
+ `Expected function to accept ${expectedArgument}, got ${actualArgument}`
+ );
+ }
- }).then(({ data }) => {
- return data.myfunction();
+ return promise;
+ })
+ .then((result) => {
+ if (result !== expectedReturn) {
+ throw new Error(
+ `Expected function to return ${expectedReturn}, got ${result}`
+ );
+ }
+ });
+ });
- }).catch(err => {
- if (!(err instanceof Error)) {
- throw new TypeError(`Expected err to be an Error instance`);
- }
+ it("should pass a promise across windows and be able to call it later", () => {
+ const { childFrame } = getWindows();
- if (err.message !== expectedErrorMessage) {
- throw new Error(`Expected function throw error with message ${ expectedErrorMessage }, got ${ err.message }`);
- }
+ const expectedValue = 123;
+ let resolver;
- // $FlowFixMe
- if (err.code !== expectedErrorCode) {
- // $FlowFixMe
- throw new Error(`Expected function throw error with code ${ expectedErrorCode }, got ${ err.code }`);
- }
-
- if (!expectedErrorStack) {
- throw new Error(`Expected error to have stack`);
- }
-
- if (err.stack.indexOf(expectedErrorStack) === -1) {
- throw new Error(`Expected function throw error with stack ${ expectedErrorStack }, got ${ err.stack }`);
- }
- });
+ // eslint-disable-next-line promise/no-native, no-restricted-globals
+ const promise = new Promise((resolve) => {
+ resolver = resolve;
});
- it('should pass a function across windows and be able to call it instantly from its origin window', () => {
- const { childFrame } = getWindows();
-
- const expectedArgument = 567;
- let actualArgument;
- const expectedReturn = 'hello world';
-
- const myfunction = (val) => {
- actualArgument = val;
- return expectedReturn;
- };
-
- return send(childFrame, 'setupListener', {
-
- messageName: 'foo',
- data: {
- myfunction
- }
+ const sendPromise = send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ promise,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
+ return data.promise;
+ })
+ .then((result) => {
+ if (result !== expectedValue) {
+ throw new Error(
+ `Expected promise to resolve to ${expectedValue}, got ${result}`
+ );
+ }
+ });
- }).then(() => {
- return send(childFrame, 'foo');
+ if (!resolver) {
+ throw new Error(`Expected resolver to be set`);
+ }
- }).then(({ data }) => {
- const promise = data.myfunction(expectedArgument);
+ resolver(expectedValue);
- if (actualArgument !== expectedArgument) {
- throw new Error(`Expected function to accept ${ expectedArgument }, got ${ actualArgument }`);
- }
+ return sendPromise;
+ });
- return promise;
+ it("should pass a promise across windows and be able to reject it later", () => {
+ const { childFrame } = getWindows();
- }).then(result => {
+ const expectedErrorMessage = "Oh no!";
+ const expectedErrorCode = "ABC123";
+ let expectedErrorStack; // eslint-disable-line prefer-const
+ let rejector;
- if (result !== expectedReturn) {
- throw new Error(`Expected function to return ${ expectedReturn }, got ${ result }`);
- }
- });
+ // eslint-disable-next-line promise/no-native, no-restricted-globals
+ const promise = new Promise((resolve, reject) => {
+ rejector = reject;
});
- it('should pass a promise across windows and be able to call it later', () => {
- const { childFrame } = getWindows();
-
- const expectedValue = 123;
- let resolver;
-
- // eslint-disable-next-line promise/no-native, no-restricted-globals
- const promise = new Promise((resolve) => {
- resolver = resolve;
- });
-
- const sendPromise = send(childFrame, 'setupListener', {
-
- messageName: 'foo',
- data: {
- promise
- }
-
- }).then(() => {
- return send(childFrame, 'foo');
-
- }).then(({ data }) => {
- return data.promise;
-
- }).then(result => {
- if (result !== expectedValue) {
- throw new Error(`Expected promise to resolve to ${ expectedValue }, got ${ result }`);
- }
- });
-
- if (!resolver) {
- throw new Error(`Expected resolver to be set`);
+ const sendPromise = send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ promise,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
+ return data.promise;
+ })
+ .catch((err2) => {
+ if (!(err2 instanceof Error)) {
+ throw new TypeError(`Expected err to be an Error instance`);
}
- resolver(expectedValue);
-
- return sendPromise;
- });
-
- it('should pass a promise across windows and be able to reject it later', () => {
- const { childFrame } = getWindows();
-
- const expectedErrorMessage = 'Oh no!';
- const expectedErrorCode = 'ABC123';
- let expectedErrorStack; // eslint-disable-line prefer-const
- let rejector;
-
- // eslint-disable-next-line promise/no-native, no-restricted-globals
- const promise = new Promise((resolve, reject) => {
- rejector = reject;
- });
-
- const sendPromise = send(childFrame, 'setupListener', {
-
- messageName: 'foo',
- data: {
- promise
- }
-
- }).then(() => {
- return send(childFrame, 'foo');
-
- }).then(({ data }) => {
- return data.promise;
-
- }).catch(err2 => {
- if (!(err2 instanceof Error)) {
- throw new TypeError(`Expected err to be an Error instance`);
- }
-
- if (err2.message !== expectedErrorMessage) {
- throw new Error(`Expected function throw error with message ${ expectedErrorMessage }, got ${ err2.message }`);
- }
-
- // $FlowFixMe
- if (err2.code !== expectedErrorCode) {
- // $FlowFixMe
- throw new Error(`Expected function throw error with code ${ expectedErrorCode }, got ${ err2.code }`);
- }
-
- if (!expectedErrorStack) {
- throw new Error(`Expected error to have stack`);
- }
-
- if (err2.stack.indexOf(expectedErrorStack) === -1) {
- throw new Error(`Expected function throw error with stack ${ expectedErrorStack }, got ${ err2.stack }`);
- }
- });
+ if (err2.message !== expectedErrorMessage) {
+ throw new Error(
+ `Expected function throw error with message ${expectedErrorMessage}, got ${err2.message}`
+ );
+ }
- const err = new Error(expectedErrorMessage);
// $FlowFixMe
- err.code = expectedErrorCode;
- expectedErrorStack = err.stack;
-
- if (!rejector) {
- throw new Error(`Expected rejector to be set`);
+ if (err2.code !== expectedErrorCode) {
+ throw new Error(
+ // $FlowFixMe
+ `Expected function throw error with code ${expectedErrorCode}, got ${err2.code}`
+ );
}
- rejector(err);
-
- return sendPromise;
- });
-
- it('should pass a zalgo promise across windows and be able to call it later', () => {
- const { childFrame } = getWindows();
-
- const expectedValue = 123;
- let resolver;
-
- const promise = new ZalgoPromise((resolve) => {
- resolver = resolve;
- });
-
- const sendPromise = send(childFrame, 'setupListener', {
-
- messageName: 'foo',
- data: {
- promise
- }
-
- }).then(() => {
- return send(childFrame, 'foo');
-
- }).then(({ data }) => {
- return data.promise;
-
- }).then(result => {
- if (result !== expectedValue) {
- throw new Error(`Expected promise to resolve to ${ expectedValue }, got ${ result }`);
- }
- });
-
- if (!resolver) {
- throw new Error(`Expected resolver to be set`);
+ if (!expectedErrorStack) {
+ throw new Error(`Expected error to have stack`);
}
- resolver(expectedValue);
-
- return sendPromise;
- });
-
- it('should pass a zalgo promise across windows and be able to reject it later', () => {
- const { childFrame } = getWindows();
-
- const expectedErrorMessage = 'Oh no!';
- const expectedErrorCode = 'ABC123';
- let expectedErrorStack; // eslint-disable-line prefer-const
- let rejector;
-
- const promise = new ZalgoPromise((resolve, reject) => {
- rejector = reject;
- });
-
- const sendPromise = send(childFrame, 'setupListener', {
-
- messageName: 'foo',
- data: {
- promise
- }
-
- }).then(() => {
- return send(childFrame, 'foo');
-
- }).then(({ data }) => {
- return data.promise;
-
- }).catch(err2 => {
-
- if (!(err2 instanceof Error)) {
- throw new TypeError(`Expected err to be an Error instance`);
- }
-
- if (err2.message !== expectedErrorMessage) {
- throw new Error(`Expected function throw error with message ${ expectedErrorMessage }, got ${ err2.message }`);
- }
-
- // $FlowFixMe
- if (err2.code !== expectedErrorCode) {
- // $FlowFixMe
- throw new Error(`Expected function throw error with code ${ expectedErrorCode }, got ${ err2.code }`);
- }
-
- if (!expectedErrorStack) {
- throw new Error(`Expected error to have stack`);
- }
-
- if (err2.stack.indexOf(expectedErrorStack) === -1) {
- throw new Error(`Expected function throw error with stack ${ expectedErrorStack }, got ${ err2.stack }`);
- }
- });
-
- const err = new Error(expectedErrorMessage);
- // $FlowFixMe
- err.code = expectedErrorCode;
- expectedErrorStack = err.stack;
-
- if (!rejector) {
- throw new Error(`Expected rejector to be set`);
+ if (err2.stack.indexOf(expectedErrorStack) === -1) {
+ throw new Error(
+ `Expected function throw error with stack ${expectedErrorStack}, got ${err2.stack}`
+ );
}
+ });
- rejector(err);
-
- return sendPromise;
- });
+ const err = new Error(expectedErrorMessage);
+ // $FlowFixMe
+ err.code = expectedErrorCode;
+ expectedErrorStack = err.stack;
- it('should pass an iframe across the window boundary and focus it', () => {
- const { childFrame } = getWindows();
+ if (!rejector) {
+ throw new Error(`Expected rejector to be set`);
+ }
- const iframe = document.createElement('iframe');
- getBody().appendChild(iframe);
- const mywindow = iframe.contentWindow;
+ rejector(err);
- return send(childFrame, 'setupListener', {
+ return sendPromise;
+ });
- messageName: 'foo',
- data: {
- mywindow
- }
+ it("should pass a zalgo promise across windows and be able to call it later", () => {
+ const { childFrame } = getWindows();
- }).then(() => {
- return send(childFrame, 'foo');
+ const expectedValue = 123;
+ let resolver;
- }).then(({ data }) => {
- return data.mywindow.focus();
- });
- });
-
- it('should pass an iframe across the window boundary and close it', () => {
- const { childFrame } = getWindows();
-
- const iframe = document.createElement('iframe');
- getBody().appendChild(iframe);
- const mywindow = iframe.contentWindow;
-
- return send(childFrame, 'setupListener', {
-
- messageName: 'foo',
- data: {
- mywindow
- }
-
- }).then(() => {
- return send(childFrame, 'foo');
-
- }).then(({ data }) => {
- return data.mywindow.close();
- });
+ const promise = new ZalgoPromise((resolve) => {
+ resolver = resolve;
});
+ const sendPromise = send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ promise,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
+ return data.promise;
+ })
+ .then((result) => {
+ if (result !== expectedValue) {
+ throw new Error(
+ `Expected promise to resolve to ${expectedValue}, got ${result}`
+ );
+ }
+ });
- it('should pass an iframe across the window boundary and change its location', () => {
- const { childFrame } = getWindows();
-
- const iframe = document.createElement('iframe');
- getBody().appendChild(iframe);
- const mywindow = iframe.contentWindow;
-
- return send(childFrame, 'setupListener', {
-
- messageName: 'foo',
- data: {
- mywindow
- }
-
- }).then(() => {
- return send(childFrame, 'foo');
-
- }).then(({ data }) => {
- return data.mywindow.setLocation('/base/test/child.htm');
-
- }).then(() => {
- return awaitWindowHello(mywindow);
-
- }).then(() => {
- return send(mywindow, 'setupListener', {
-
- messageName: 'foo',
- data: {
- hello: 'world'
- }
- });
-
- }).then(() => {
- return send(mywindow, 'foo');
-
- }).then(({ data }) => {
- if (data.hello !== 'world') {
- throw new Error(`Expected hello to equal world, got ${ data.hello }`);
- }
- });
- });
-
- it('should pass an iframe across the window boundary and get its instance id', () => {
- const { childFrame } = getWindows();
-
- const iframe = document.createElement('iframe');
- getBody().appendChild(iframe);
- const mywindow = iframe.contentWindow;
-
- return send(childFrame, 'setupListener', {
-
- messageName: 'foo',
- data: {
- mywindow
- }
-
- }).then(() => {
- return send(childFrame, 'foo');
-
- }).then(({ data }) => {
- return data.mywindow.setLocation('/base/test/child.htm');
-
- }).then((win) => {
- return win.getInstanceID();
-
- }).then(instanceID => {
-
- if (!instanceID || typeof instanceID !== 'string') {
- throw new Error(`Expected instance id to be returned`);
- }
- });
- });
-
- it('should pass a popup across the window boundary and focus it', () => {
- const { childFrame } = getWindows();
-
- const mywindow = window.open('', uniqueID(), 'width=500,height=500');
-
- return send(childFrame, 'setupListener', {
-
- messageName: 'foo',
- data: {
- mywindow
- }
-
- }).then(() => {
- return send(childFrame, 'foo');
-
- }).then(({ data }) => {
- return data.mywindow.focus();
- });
- });
-
- it('should pass a popup across the window boundary and close it', () => {
- const { childFrame } = getWindows();
-
- const mywindow = window.open('', uniqueID(), 'width=500,height=500');
-
- return send(childFrame, 'setupListener', {
-
- messageName: 'foo',
- data: {
- mywindow
- }
-
- }).then(() => {
- return send(childFrame, 'foo');
-
- }).then(({ data }) => {
- return data.mywindow.close();
-
- }).then(() => {
- if (!mywindow.closed) {
- throw new Error(`Expected window to be closed`);
- }
- });
- });
-
- it('should get window type for popup even if window closed after serialization', () => {
- const { childFrame } = getWindows();
-
- const mywindow = window.open('', uniqueID(), 'width=500,height=500');
+ if (!resolver) {
+ throw new Error(`Expected resolver to be set`);
+ }
- return send(childFrame, 'setupListener', {
+ resolver(expectedValue);
- messageName: 'foo',
- data: {
- mywindow
- }
+ return sendPromise;
+ });
- }).then(() => {
- return send(childFrame, 'foo');
+ it("should pass a zalgo promise across windows and be able to reject it later", () => {
+ const { childFrame } = getWindows();
- }).then(({ data }) => {
- mywindow.close();
- return data.mywindow.getType();
+ const expectedErrorMessage = "Oh no!";
+ const expectedErrorCode = "ABC123";
+ let expectedErrorStack; // eslint-disable-line prefer-const
+ let rejector;
- }).then((type) => {
- if (type !== WINDOW_TYPE.POPUP) {
- throw new Error(`Expected window to be a popup`);
- }
- });
+ const promise = new ZalgoPromise((resolve, reject) => {
+ rejector = reject;
});
- it('should get window type for iframe even if window closed after serialization', () => {
- const { childFrame } = getWindows();
-
- const mywindow = createIframe('child.htm');
-
- return send(childFrame, 'setupListener', {
-
- messageName: 'foo',
- data: {
- mywindow
- }
+ const sendPromise = send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ promise,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
+ return data.promise;
+ })
+ .catch((err2) => {
+ if (!(err2 instanceof Error)) {
+ throw new TypeError(`Expected err to be an Error instance`);
+ }
- }).then(() => {
- return send(childFrame, 'foo');
+ if (err2.message !== expectedErrorMessage) {
+ throw new Error(
+ `Expected function throw error with message ${expectedErrorMessage}, got ${err2.message}`
+ );
+ }
- }).then(({ data }) => {
+ // $FlowFixMe
+ if (err2.code !== expectedErrorCode) {
+ throw new Error(
// $FlowFixMe
- mywindow.frameElement.parentNode.removeChild(mywindow.frameElement);
- return data.mywindow.getType();
-
- }).then((type) => {
- if (type !== WINDOW_TYPE.IFRAME) {
- throw new Error(`Expected window to be an iframe`);
- }
- });
- });
-
- it('should error getting window type for popup if window is closed prior to serialization', () => {
- const { childFrame } = getWindows();
-
- const mywindow = window.open('', uniqueID(), 'width=500,height=500');
- mywindow.close();
- let error;
-
- return send(childFrame, 'setupListener', {
-
- messageName: 'foo',
- data: {
- mywindow
- }
-
- }).then(() => {
- return send(childFrame, 'foo');
+ `Expected function throw error with code ${expectedErrorCode}, got ${err2.code}`
+ );
+ }
- }).then(({ data }) => {
- return data.mywindow.getType().catch(err => {
- error = err;
- });
+ if (!expectedErrorStack) {
+ throw new Error(`Expected error to have stack`);
+ }
- }).then(() => {
- if (!error) {
- throw new Error(`Expected error to be thrown`);
- }
+ if (err2.stack.indexOf(expectedErrorStack) === -1) {
+ throw new Error(
+ `Expected function throw error with stack ${expectedErrorStack}, got ${err2.stack}`
+ );
+ }
+ });
+
+ const err = new Error(expectedErrorMessage);
+ // $FlowFixMe
+ err.code = expectedErrorCode;
+ expectedErrorStack = err.stack;
+
+ if (!rejector) {
+ throw new Error(`Expected rejector to be set`);
+ }
+
+ rejector(err);
+
+ return sendPromise;
+ });
+
+ it("should pass an iframe across the window boundary and focus it", () => {
+ const { childFrame } = getWindows();
+
+ const iframe = document.createElement("iframe");
+ getBody().appendChild(iframe);
+ const mywindow = iframe.contentWindow;
+
+ return send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ mywindow,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
+ return data.mywindow.focus();
+ });
+ });
+
+ it("should pass an iframe across the window boundary and close it", () => {
+ const { childFrame } = getWindows();
+
+ const iframe = document.createElement("iframe");
+ getBody().appendChild(iframe);
+ const mywindow = iframe.contentWindow;
+
+ return send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ mywindow,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
+ return data.mywindow.close();
+ });
+ });
+
+ it("should pass an iframe across the window boundary and change its location", () => {
+ const { childFrame } = getWindows();
+
+ const iframe = document.createElement("iframe");
+ getBody().appendChild(iframe);
+ const mywindow = iframe.contentWindow;
+
+ return send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ mywindow,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
+ return data.mywindow.setLocation("/base/test/child.htm");
+ })
+ .then(() => {
+ return awaitWindowHello(mywindow);
+ })
+ .then(() => {
+ return send(mywindow, "setupListener", {
+ messageName: "foo",
+ data: {
+ hello: "world",
+ },
});
- });
-
- it('should error getting window type for iframe if window is closed prior to serialization', () => {
- const { childFrame } = getWindows();
-
- const mywindow = createIframe('child.htm');
+ })
+ .then(() => {
+ return send(mywindow, "foo");
+ })
+ .then(({ data }) => {
+ if (data.hello !== "world") {
+ throw new Error(`Expected hello to equal world, got ${data.hello}`);
+ }
+ });
+ });
+
+ it("should pass an iframe across the window boundary and get its instance id", () => {
+ const { childFrame } = getWindows();
+
+ const iframe = document.createElement("iframe");
+ getBody().appendChild(iframe);
+ const mywindow = iframe.contentWindow;
+
+ return send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ mywindow,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
+ return data.mywindow.setLocation("/base/test/child.htm");
+ })
+ .then((win) => {
+ return win.getInstanceID();
+ })
+ .then((instanceID) => {
+ if (!instanceID || typeof instanceID !== "string") {
+ throw new Error(`Expected instance id to be returned`);
+ }
+ });
+ });
+
+ it("should pass a popup across the window boundary and focus it", () => {
+ const { childFrame } = getWindows();
+
+ const mywindow = window.open("", uniqueID(), "width=500,height=500");
+
+ return send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ mywindow,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
+ return data.mywindow.focus();
+ });
+ });
+
+ it("should pass a popup across the window boundary and close it", () => {
+ const { childFrame } = getWindows();
+
+ const mywindow = window.open("", uniqueID(), "width=500,height=500");
+
+ return send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ mywindow,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
+ return data.mywindow.close();
+ })
+ .then(() => {
+ if (!mywindow.closed) {
+ throw new Error(`Expected window to be closed`);
+ }
+ });
+ });
+
+ it("should get window type for popup even if window closed after serialization", () => {
+ const { childFrame } = getWindows();
+
+ const mywindow = window.open("", uniqueID(), "width=500,height=500");
+
+ return send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ mywindow,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
+ mywindow.close();
+ return data.mywindow.getType();
+ })
+ .then((type) => {
+ if (type !== WINDOW_TYPE.POPUP) {
+ throw new Error(`Expected window to be a popup`);
+ }
+ });
+ });
+
+ it("should get window type for iframe even if window closed after serialization", () => {
+ const { childFrame } = getWindows();
+
+ const mywindow = createIframe("child.htm");
+
+ return send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ mywindow,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
// $FlowFixMe
mywindow.frameElement.parentNode.removeChild(mywindow.frameElement);
- let error;
-
- return send(childFrame, 'setupListener', {
-
- messageName: 'foo',
- data: {
- mywindow
- }
-
- }).then(() => {
- return send(childFrame, 'foo');
-
- }).then(({ data }) => {
- return data.mywindow.getType().catch(err => {
- error = err;
- });
-
- }).then(() => {
- if (!error) {
- throw new Error(`Expected error to be thrown`);
- }
+ return data.mywindow.getType();
+ })
+ .then((type) => {
+ if (type !== WINDOW_TYPE.IFRAME) {
+ throw new Error(`Expected window to be an iframe`);
+ }
+ });
+ });
+
+ it("should error getting window type for popup if window is closed prior to serialization", () => {
+ const { childFrame } = getWindows();
+
+ const mywindow = window.open("", uniqueID(), "width=500,height=500");
+ mywindow.close();
+ let error;
+
+ return send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ mywindow,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
+ return data.mywindow.getType().catch((err) => {
+ error = err;
});
- });
-
-
- it('should pass a popup across the window boundary and change its location', () => {
- const { childFrame } = getWindows();
-
- const mywindow = window.open('', uniqueID(), 'width=500,height=500');
-
- return send(childFrame, 'setupListener', {
-
- messageName: 'foo',
- data: {
- mywindow
- }
-
- }).then(() => {
- return send(childFrame, 'foo');
-
- }).then(({ data }) => {
- return data.mywindow.setLocation('/base/test/child.htm');
-
- }).then(() => {
- return awaitWindowHello(mywindow);
-
- }).then(() => {
- return send(mywindow, 'setupListener', {
-
- messageName: 'foo',
- data: {
- hello: 'world'
- }
- });
-
- }).then(() => {
- return send(mywindow, 'foo');
-
- }).then(({ data }) => {
- if (data.hello !== 'world') {
- throw new Error(`Expected hello to equal world, got ${ data.hello }`);
- }
+ })
+ .then(() => {
+ if (!error) {
+ throw new Error(`Expected error to be thrown`);
+ }
+ });
+ });
+
+ it("should error getting window type for iframe if window is closed prior to serialization", () => {
+ const { childFrame } = getWindows();
+
+ const mywindow = createIframe("child.htm");
+ // $FlowFixMe
+ mywindow.frameElement.parentNode.removeChild(mywindow.frameElement);
+ let error;
+
+ return send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ mywindow,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
+ return data.mywindow.getType().catch((err) => {
+ error = err;
});
- });
-
- it('should pass a popup across the window boundary and get its instance id', () => {
- const { childFrame } = getWindows();
-
- const mywindow = window.open('', uniqueID(), 'width=500,height=500');
-
- return send(childFrame, 'setupListener', {
-
- messageName: 'foo',
- data: {
- mywindow
- }
-
- }).then(() => {
- return send(childFrame, 'foo');
-
- }).then(({ data }) => {
- return data.mywindow.setLocation('/base/test/child.htm');
-
- }).then((win) => {
- return win.getInstanceID();
-
- }).then(instanceID => {
-
- if (!instanceID || typeof instanceID !== 'string') {
- throw new Error(`Expected instance id to be returned`);
- }
+ })
+ .then(() => {
+ if (!error) {
+ throw new Error(`Expected error to be thrown`);
+ }
+ });
+ });
+
+ it("should pass a popup across the window boundary and change its location", () => {
+ const { childFrame } = getWindows();
+
+ const mywindow = window.open("", uniqueID(), "width=500,height=500");
+
+ return send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ mywindow,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
+ return data.mywindow.setLocation("/base/test/child.htm");
+ })
+ .then(() => {
+ return awaitWindowHello(mywindow);
+ })
+ .then(() => {
+ return send(mywindow, "setupListener", {
+ messageName: "foo",
+ data: {
+ hello: "world",
+ },
});
- });
+ })
+ .then(() => {
+ return send(mywindow, "foo");
+ })
+ .then(({ data }) => {
+ if (data.hello !== "world") {
+ throw new Error(`Expected hello to equal world, got ${data.hello}`);
+ }
+ });
+ });
+
+ it("should pass a popup across the window boundary and get its instance id", () => {
+ const { childFrame } = getWindows();
+
+ const mywindow = window.open("", uniqueID(), "width=500,height=500");
+
+ return send(childFrame, "setupListener", {
+ messageName: "foo",
+ data: {
+ mywindow,
+ },
+ })
+ .then(() => {
+ return send(childFrame, "foo");
+ })
+ .then(({ data }) => {
+ return data.mywindow.setLocation("/base/test/child.htm");
+ })
+ .then((win) => {
+ return win.getInstanceID();
+ })
+ .then((instanceID) => {
+ if (!instanceID || typeof instanceID !== "string") {
+ throw new Error(`Expected instance id to be returned`);
+ }
+ });
+ });
});
diff --git a/test/tests/window-proxy.js b/test/tests/window-proxy.js
index 49efd5c5..98198c58 100644
--- a/test/tests/window-proxy.js
+++ b/test/tests/window-proxy.js
@@ -1,113 +1,131 @@
/* @flow */
/* eslint max-lines: 0, max-nested-callbacks: off */
-import { wrapPromise } from '@krakenjs/belter/src';
-
-import { on, send } from '../../src';
-import { getWindows } from '../common';
-
-describe('Window Proxy cases', () => {
-
- it('Should send the a window in a message', () => {
- return wrapPromise(({ expect }) => {
- const { childFrame, otherChildFrame } = getWindows();
-
- const listener = on('passProxyWindow', expect('passProxyWindow', ({ data }) => {
- if (data.otherFrame.getWindow() !== otherChildFrame) {
- throw new Error(`Expected window to be correctly passed`);
- }
-
- listener.cancel();
- }));
-
- return send(childFrame, 'sendMessageToParent', {
- messageName: 'passProxyWindow',
- data: {
- otherFrame: otherChildFrame
- }
- }).then(expect('sendSuccess'));
- });
+import { wrapPromise } from "@krakenjs/belter/src";
+
+import { on, send } from "../../src";
+import { getWindows } from "../common";
+
+describe("Window Proxy cases", () => {
+ it("Should send the a window in a message", () => {
+ return wrapPromise(({ expect }) => {
+ const { childFrame, otherChildFrame } = getWindows();
+
+ const listener = on(
+ "passProxyWindow",
+ expect("passProxyWindow", ({ data }) => {
+ if (data.otherFrame.getWindow() !== otherChildFrame) {
+ throw new Error(`Expected window to be correctly passed`);
+ }
+
+ listener.cancel();
+ })
+ );
+
+ return send(childFrame, "sendMessageToParent", {
+ messageName: "passProxyWindow",
+ data: {
+ otherFrame: otherChildFrame,
+ },
+ }).then(expect("sendSuccess"));
});
-
- it('Should send the a window in a message, then call isPopup', () => {
- return wrapPromise(({ expect }) => {
- const { childFrame, otherChildFrame } = getWindows();
-
- const listener = on('passProxyWindow', expect('passProxyWindow', ({ data }) => {
- return data.otherFrame.isPopup().then(isPopup => {
- listener.cancel();
- if (isPopup !== false) {
- throw new Error(`Expected isPopup to be false but got ${ isPopup }`);
- }
- });
- }));
-
- return send(childFrame, 'sendMessageToParent', {
- messageName: 'passProxyWindow',
- data: {
- otherFrame: otherChildFrame
- }
- }).then(expect('sendSuccess'));
- });
+ });
+
+ it("Should send the a window in a message, then call isPopup", () => {
+ return wrapPromise(({ expect }) => {
+ const { childFrame, otherChildFrame } = getWindows();
+
+ const listener = on(
+ "passProxyWindow",
+ expect("passProxyWindow", ({ data }) => {
+ return data.otherFrame.isPopup().then((isPopup) => {
+ listener.cancel();
+ if (isPopup !== false) {
+ throw new Error(
+ `Expected isPopup to be false but got ${isPopup}`
+ );
+ }
+ });
+ })
+ );
+
+ return send(childFrame, "sendMessageToParent", {
+ messageName: "passProxyWindow",
+ data: {
+ otherFrame: otherChildFrame,
+ },
+ }).then(expect("sendSuccess"));
});
-
- it('Should send a message to a proxy window', () => {
- return wrapPromise(({ expect }) => {
- const { childFrame, otherChildFrame } = getWindows();
-
- const passListener = on('passProxyWindow', expect('passProxyWindow', ({ data }) => {
- if (data.otherFrame.getWindow() !== otherChildFrame) {
- throw new Error(`Expected window to be correctly passed`);
- }
-
- passListener.cancel();
-
- return send(data.otherFrame, 'sendMessageToParent', {
- messageName: 'callProxyWindow'
- }).then(expect('sendSuccess'));
- }));
-
- const callListener = on('callProxyWindow', expect('onCallProxyWindow', () => {
- callListener.cancel();
- }));
-
- return send(childFrame, 'sendMessageToParent', {
- messageName: 'passProxyWindow',
- data: {
- otherFrame: otherChildFrame
- }
- }).then(expect('sendSuccess'));
- });
+ });
+
+ it("Should send a message to a proxy window", () => {
+ return wrapPromise(({ expect }) => {
+ const { childFrame, otherChildFrame } = getWindows();
+
+ const passListener = on(
+ "passProxyWindow",
+ expect("passProxyWindow", ({ data }) => {
+ if (data.otherFrame.getWindow() !== otherChildFrame) {
+ throw new Error(`Expected window to be correctly passed`);
+ }
+
+ passListener.cancel();
+
+ return send(data.otherFrame, "sendMessageToParent", {
+ messageName: "callProxyWindow",
+ }).then(expect("sendSuccess"));
+ })
+ );
+
+ const callListener = on(
+ "callProxyWindow",
+ expect("onCallProxyWindow", () => {
+ callListener.cancel();
+ })
+ );
+
+ return send(childFrame, "sendMessageToParent", {
+ messageName: "passProxyWindow",
+ data: {
+ otherFrame: otherChildFrame,
+ },
+ }).then(expect("sendSuccess"));
});
-
- it('Should receive a message from a proxy window', () => {
- return wrapPromise(({ expect }) => {
- const { childFrame, otherChildFrame } = getWindows();
-
- const passListener = on('passProxyWindow', expect('passProxyWindow', ({ data }) => {
- if (data.otherFrame.getWindow() !== otherChildFrame) {
- throw new Error(`Expected window to be correctly passed`);
- }
-
- passListener.cancel();
-
- const callListener = on('callProxyWindow', { window: data.otherFrame }, expect('onCallProxyWindow', () => {
- callListener.cancel();
- }));
-
- return send(data.otherFrame, 'sendMessageToParent', {
- messageName: 'callProxyWindow'
- }).then(expect('sendSuccess'));
- }));
-
- return send(childFrame, 'sendMessageToParent', {
- messageName: 'passProxyWindow',
- data: {
- otherFrame: otherChildFrame
- }
- }).then(expect('sendSuccess'));
- });
+ });
+
+ it("Should receive a message from a proxy window", () => {
+ return wrapPromise(({ expect }) => {
+ const { childFrame, otherChildFrame } = getWindows();
+
+ const passListener = on(
+ "passProxyWindow",
+ expect("passProxyWindow", ({ data }) => {
+ if (data.otherFrame.getWindow() !== otherChildFrame) {
+ throw new Error(`Expected window to be correctly passed`);
+ }
+
+ passListener.cancel();
+
+ const callListener = on(
+ "callProxyWindow",
+ { window: data.otherFrame },
+ expect("onCallProxyWindow", () => {
+ callListener.cancel();
+ })
+ );
+
+ return send(data.otherFrame, "sendMessageToParent", {
+ messageName: "callProxyWindow",
+ }).then(expect("sendSuccess"));
+ })
+ );
+
+ return send(childFrame, "sendMessageToParent", {
+ messageName: "passProxyWindow",
+ data: {
+ otherFrame: otherChildFrame,
+ },
+ }).then(expect("sendSuccess"));
});
+ });
});
-
-
diff --git a/webpack.config.js b/webpack.config.js
index ddd605b5..8f550921 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,79 +1,87 @@
/* @flow */
/* eslint import/no-nodejs-modules: off, import/no-default-export: off, import/default: off */
-import type { WebpackConfig } from '@krakenjs/grumbler-scripts/config/types';
-import { getWebpackConfig, getNextVersion } from '@krakenjs/grumbler-scripts/config/webpack.config';
-import { argv } from 'yargs';
+import type { WebpackConfig } from "@krakenjs/grumbler-scripts/config/types";
+import {
+ getWebpackConfig,
+ getNextVersion,
+} from "@krakenjs/grumbler-scripts/config/webpack.config";
+import { argv } from "yargs";
-import pkg from './package.json';
-import globals from './globals';
+import pkg from "./package.json";
+import globals from "./globals";
-export const FILE_NAME = 'post-robot';
-export const MODULE_NAME = 'postRobot';
+export const FILE_NAME = "post-robot";
+export const MODULE_NAME = "postRobot";
const postRobotGlobals = {
- ...globals.__POST_ROBOT__,
- __GLOBAL_KEY__: `__post_robot_${ getNextVersion(pkg, argv.level) }__`
+ ...globals.__POST_ROBOT__,
+ __GLOBAL_KEY__: `__post_robot_${getNextVersion(pkg, argv.level)}__`,
};
-export const WEBPACK_CONFIG : WebpackConfig = getWebpackConfig({
- filename: `${ FILE_NAME }.js`,
- modulename: MODULE_NAME,
- minify: false,
- vars: {
- ...globals,
+export const WEBPACK_CONFIG: WebpackConfig = getWebpackConfig({
+ filename: `${FILE_NAME}.js`,
+ modulename: MODULE_NAME,
+ minify: false,
+ vars: {
+ ...globals,
- __POST_ROBOT__: {
- ...postRobotGlobals,
- __IE_POPUP_SUPPORT__: false,
- __GLOBAL_MESSAGE_SUPPORT__: false
- }
- }
+ __POST_ROBOT__: {
+ ...postRobotGlobals,
+ __IE_POPUP_SUPPORT__: false,
+ __GLOBAL_MESSAGE_SUPPORT__: false,
+ },
+ },
});
-export const WEBPACK_CONFIG_MIN : WebpackConfig = getWebpackConfig({
- filename: `${ FILE_NAME }.min.js`,
- modulename: MODULE_NAME,
- minify: true,
- vars: {
- ...globals,
+export const WEBPACK_CONFIG_MIN: WebpackConfig = getWebpackConfig({
+ filename: `${FILE_NAME}.min.js`,
+ modulename: MODULE_NAME,
+ minify: true,
+ vars: {
+ ...globals,
- __POST_ROBOT__: {
- ...postRobotGlobals,
- __IE_POPUP_SUPPORT__: false,
- __GLOBAL_MESSAGE_SUPPORT__: false
- }
- }
+ __POST_ROBOT__: {
+ ...postRobotGlobals,
+ __IE_POPUP_SUPPORT__: false,
+ __GLOBAL_MESSAGE_SUPPORT__: false,
+ },
+ },
});
-export const WEBPACK_CONFIG_IE : WebpackConfig = getWebpackConfig({
- filename: `${ FILE_NAME }.ie.js`,
- modulename: MODULE_NAME,
- minify: false,
- vars: {
- ...globals,
- __POST_ROBOT__: postRobotGlobals
- }
+export const WEBPACK_CONFIG_IE: WebpackConfig = getWebpackConfig({
+ filename: `${FILE_NAME}.ie.js`,
+ modulename: MODULE_NAME,
+ minify: false,
+ vars: {
+ ...globals,
+ __POST_ROBOT__: postRobotGlobals,
+ },
});
-export const WEBPACK_CONFIG_IE_MIN : WebpackConfig = getWebpackConfig({
- filename: `${ FILE_NAME }.ie.min.js`,
- modulename: MODULE_NAME,
- minify: true,
- vars: {
- ...globals,
- __POST_ROBOT__: postRobotGlobals
- }
+export const WEBPACK_CONFIG_IE_MIN: WebpackConfig = getWebpackConfig({
+ filename: `${FILE_NAME}.ie.min.js`,
+ modulename: MODULE_NAME,
+ minify: true,
+ vars: {
+ ...globals,
+ __POST_ROBOT__: postRobotGlobals,
+ },
});
-export const WEBPACK_CONFIG_TEST : WebpackConfig = getWebpackConfig({
- modulename: MODULE_NAME,
- minify: false,
- test: true,
- vars: {
- ...globals,
- __POST_ROBOT__: postRobotGlobals
- }
+export const WEBPACK_CONFIG_TEST: WebpackConfig = getWebpackConfig({
+ modulename: MODULE_NAME,
+ minify: false,
+ test: true,
+ vars: {
+ ...globals,
+ __POST_ROBOT__: postRobotGlobals,
+ },
});
-export default [ WEBPACK_CONFIG, WEBPACK_CONFIG_MIN, WEBPACK_CONFIG_IE, WEBPACK_CONFIG_IE_MIN ];
+export default [
+ WEBPACK_CONFIG,
+ WEBPACK_CONFIG_MIN,
+ WEBPACK_CONFIG_IE,
+ WEBPACK_CONFIG_IE_MIN,
+];