UNPKG

penpal

Version:

A promise-based library for communicating with iframes via postMessage.

107 lines (81 loc) 3.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _enums = require("../enums"); var _createDestructor = _interopRequireDefault(require("../createDestructor")); var _createLogger = _interopRequireDefault(require("../createLogger")); var _getOriginFromSrc = _interopRequireDefault(require("./getOriginFromSrc")); var _handleAckMessageFactory = _interopRequireDefault(require("./handleAckMessageFactory")); var _handleSynMessageFactory = _interopRequireDefault(require("./handleSynMessageFactory")); var _methodSerialization = require("../methodSerialization"); var _monitorIframeRemoval = _interopRequireDefault(require("./monitorIframeRemoval")); var _startConnectionTimeout = _interopRequireDefault(require("../startConnectionTimeout")); var _validateIframeHasSrcOrSrcDoc = _interopRequireDefault(require("./validateIframeHasSrcOrSrcDoc")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Attempts to establish communication with an iframe. */ var _default = options => { let { iframe, methods = {}, childOrigin, timeout, debug = false } = options; const log = (0, _createLogger.default)(debug); const destructor = (0, _createDestructor.default)('Parent', log); const { onDestroy, destroy } = destructor; if (!childOrigin) { (0, _validateIframeHasSrcOrSrcDoc.default)(iframe); childOrigin = (0, _getOriginFromSrc.default)(iframe.src); } // If event.origin is "null", the remote protocol is file: or data: and we // must post messages with "*" as targetOrigin when sending messages. // https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#Using_window.postMessage_in_extensions const originForSending = childOrigin === 'null' ? '*' : childOrigin; const serializedMethods = (0, _methodSerialization.serializeMethods)(methods); const handleSynMessage = (0, _handleSynMessageFactory.default)(log, serializedMethods, childOrigin, originForSending); const handleAckMessage = (0, _handleAckMessageFactory.default)(serializedMethods, childOrigin, originForSending, destructor, log); const promise = new Promise((resolve, reject) => { const stopConnectionTimeout = (0, _startConnectionTimeout.default)(timeout, destroy); const handleMessage = event => { if (event.source !== iframe.contentWindow || !event.data) { return; } if (event.data.penpal === _enums.MessageType.Syn) { handleSynMessage(event); return; } if (event.data.penpal === _enums.MessageType.Ack) { const callSender = handleAckMessage(event); if (callSender) { stopConnectionTimeout(); resolve(callSender); } return; } }; window.addEventListener(_enums.NativeEventType.Message, handleMessage); log('Parent: Awaiting handshake'); (0, _monitorIframeRemoval.default)(iframe, destructor); onDestroy(error => { window.removeEventListener(_enums.NativeEventType.Message, handleMessage); if (error) { reject(error); } }); }); return { promise, destroy() { // Don't allow consumer to pass an error into destroy. destroy(); } }; }; exports.default = _default;