in ArticleTemplates/assets/js/modules/messenger.js [79:135]
function onMessage(event) {
// We only allow communication with selected hosts
if (allowedHosts.indexOf(event.origin) < 0) {
return;
}
let data = getData(event.data);
if (!isValidPayload(data)) {
return;
}
if (Array.isArray(listeners[data.type]) && listeners[data.type].length) {
// Because any listener can have side-effects (by unregistering itself),
// we run the promise chain on a copy of the `listeners` array.
// Hat tip @piuccio
let promise = listeners[data.type].slice()
// We offer, but don't impose, the possibility that a listener returns
// a value that must be sent back to the calling frame. To do this,
// we pass the cumulated returned value as a second argument to each
// listener. Notice we don't try some clever way to compose the result
// value ourselves, this would only make the solution more complex.
// That means a listener can ignore the cumulated return value and
// return something else entirely—life is unfair.
// We don't know what each callack will be made of, we don't want to.
// And so we wrap each call in a promise chain, in case one drops the
// occasional fastdom bomb in the middle.
.reduce(function (promise, listener) {
return promise.then(function promiseCallback(ret) {
var iframe = getIframe(data);
if (!iframe) {
throw new Error(formatError(error500, 'iframe element not found'));
}
var thisRet = listener(data.value, ret, iframe);
return thisRet === undefined ? ret : thisRet;
});
}, Promise.resolve(true));
return promise.then(function (response) {
respond(null, response);
}).catch(function (ex) {
respond(formatError(error500, ex), null);
});
} else if (typeof listeners[data.type] === 'function') {
// We found a persistent listener, to which we just delegate
// responsibility to write something. Anything. Really.
listeners[data.type](respond, data.value, getIframe(data));
} else {
// If there is no routine attached to this event type, we just answer
// with an error code
respond(formatError(error405, data.type), null);
}
function respond(error, result) {
postMessage({ id: data.id, error: error, result: result }, event.source, event.origin);
}
}