-
Notifications
You must be signed in to change notification settings - Fork 93
/
hello.js
73 lines (59 loc) · 2.78 KB
/
hello.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
/* @flow */
import { getAncestor, type CrossDomainWindowType } from 'cross-domain-utils/src';
import { ZalgoPromise } from 'zalgo-promise/src';
import { noop, uniqueID } from 'belter/src';
import { MESSAGE_NAME, WILDCARD } from '../conf';
import { windowStore, globalStore } from '../global';
import type { OnType, SendType, CancelableType } from '../types';
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 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() };
});
}
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<string> {
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 });
const parent = getAncestor();
if (parent) {
sayHello(parent, { send }).catch(noop);
}
return listener;
});
}
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`));
}
return promise;
}