-
Notifications
You must be signed in to change notification settings - Fork 93
/
bridge.js
88 lines (67 loc) · 2.67 KB
/
bridge.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/* @flow */
import { type ZalgoPromise } from 'zalgo-promise/src';
import { getParent, isWindowClosed, type CrossDomainWindowType } from 'cross-domain-utils/src';
import { noop, uniqueID } from 'belter/src';
import { MESSAGE_NAME, WILDCARD } from '../conf';
import { getGlobal, globalStore } from '../global';
import type { SendType, ResponseMessageEvent } from '../types';
function cleanTunnelWindows() {
const tunnelWindows = globalStore('tunnelWindows');
for (const key of tunnelWindows.keys()) {
const tunnelWindow = tunnelWindows[key];
try {
noop(tunnelWindow.source);
} catch (err) {
tunnelWindows.del(key);
continue;
}
if (isWindowClosed(tunnelWindow.source)) {
tunnelWindows.del(key);
}
}
}
type TunnelWindowDataType = {|
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;
}
export function setupOpenTunnelToParent({ send } : { send : SendType }) {
getGlobal(window).openTunnelToParent = function openTunnelToParent({ name, source, canary, sendMessage } : TunnelWindowDataType) : ZalgoPromise<ResponseMessageEvent> {
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;
}
tunnelWindow.sendMessage.apply(this, arguments);
}
}, { domain: WILDCARD });
};
}