@elliemae/ssf-host 2.24.0 → 2.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/guest.js +15 -16
- package/dist/cjs/host.js +37 -55
- package/dist/cjs/performanceTracker.js +111 -0
- package/dist/esm/guest.js +15 -16
- package/dist/esm/host.js +37 -55
- package/dist/esm/performanceTracker.js +91 -0
- package/dist/public/callchain-host.html +1 -1
- package/dist/public/callchain-intermediate.html +1 -1
- package/dist/public/e2e-host.html +1 -1
- package/dist/public/e2e-index.html +1 -1
- package/dist/public/index.html +1 -1
- package/dist/public/js/emuiSsfHost.5bb7139d7e86c74f0b6d.js +3 -0
- package/dist/public/js/emuiSsfHost.5bb7139d7e86c74f0b6d.js.br +0 -0
- package/dist/public/js/emuiSsfHost.5bb7139d7e86c74f0b6d.js.gz +0 -0
- package/dist/public/js/emuiSsfHost.5bb7139d7e86c74f0b6d.js.map +1 -0
- package/dist/public/popup-focus-host.html +1 -1
- package/dist/public/utils.js +1 -1
- package/dist/public/utils.js.br +0 -0
- package/dist/public/utils.js.gz +0 -0
- package/dist/public/utils.js.map +1 -1
- package/dist/public/v1-guest-v2-host.html +1 -1
- package/dist/public/v2-host-v1-guest.html +1 -1
- package/dist/types/lib/guest.d.ts +4 -3
- package/dist/types/lib/host.d.ts +0 -1
- package/dist/types/lib/ihost.d.ts +18 -1
- package/dist/types/lib/performanceTracker.d.ts +46 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.br +0 -0
- package/dist/umd/index.js.gz +0 -0
- package/dist/umd/index.js.map +1 -1
- package/dist/umd/utils.js +1 -1
- package/dist/umd/utils.js.br +0 -0
- package/dist/umd/utils.js.gz +0 -0
- package/dist/umd/utils.js.map +1 -1
- package/package.json +4 -4
- package/dist/public/js/emuiSsfHost.071827d0d7e775690fbb.js +0 -3
- package/dist/public/js/emuiSsfHost.071827d0d7e775690fbb.js.br +0 -0
- package/dist/public/js/emuiSsfHost.071827d0d7e775690fbb.js.gz +0 -0
- package/dist/public/js/emuiSsfHost.071827d0d7e775690fbb.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"js/emuiSsfHost.5bb7139d7e86c74f0b6d.js","mappings":"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","sources":["webpack://ice.host/webpack/universalModuleDefinition","webpack://ice.host/webpack/bootstrap","webpack://ice.host/webpack/runtime/define property getters","webpack://ice.host/webpack/runtime/hasOwnProperty shorthand","webpack://ice.host/webpack/runtime/make namespace object","webpack://ice.host/../common/dist/esm/event.js","webpack://ice.host/../common/dist/esm/scriptingObject.js","webpack://ice.host/../common/dist/esm/messageType.js","webpack://ice.host/./lib/types.ts","webpack://ice.host/./lib/utils.ts","webpack://ice.host/./lib/guest.ts","webpack://ice.host/../../node_modules/.pnpm/uuid@9.0.1/node_modules/uuid/dist/esm-browser/native.js","webpack://ice.host/../../node_modules/.pnpm/uuid@9.0.1/node_modules/uuid/dist/esm-browser/rng.js","webpack://ice.host/../../node_modules/.pnpm/uuid@9.0.1/node_modules/uuid/dist/esm-browser/stringify.js","webpack://ice.host/../../node_modules/.pnpm/uuid@9.0.1/node_modules/uuid/dist/esm-browser/v4.js","webpack://ice.host/../common/dist/esm/remoting.js","webpack://ice.host/../common/dist/esm/scriptingObjectManager.js","webpack://ice.host/../common/dist/esm/proxy.js","webpack://ice.host/./lib/performanceTracker.ts","webpack://ice.host/./lib/host.ts"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ice\"] = factory();\n\telse\n\t\troot[\"ice\"] = root[\"ice\"] || {}, root[\"ice\"][\"host\"] = factory();\n})(globalThis, () => {\nreturn ","// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","class Event {\n /* eslint-enable indent */\n /**\n * name of the event\n */\n name;\n /**\n * scripting object id that owns this event\n */\n objectId;\n /**\n * unique id of the event\n */\n id;\n /**\n * Create an event object\n * @param {EventParam} param - parameters for creating an event\n */\n constructor(param) {\n const { name, objectId } = param;\n if (!name) throw new Error(\"Event name is required\");\n if (!objectId) throw new Error(\"Scripting object id is required\");\n this.objectId = objectId;\n this.name = name;\n this.id = `${this.objectId}.${this.name}`.toLowerCase();\n }\n}\nclass ProxyEvent {\n /**\n * check if given object is an instance of ProxyEvent\n * @param obj object to be compared\n * @returns true if given object is an instance of ProxyEvent\n */\n static [Symbol.hasInstance](obj) {\n return typeof obj === \"object\" && obj !== null && \"getType\" in obj && typeof obj.getType === \"function\" && obj.getType() === \"ProxyEvent\";\n }\n /* eslint-enable indent */\n /**\n * module that owns this event management. SSF Guest or App Bridge host\n */\n #eventSrc;\n /**\n * unique id of scripting object\n */\n objectId;\n /**\n * name of the event\n */\n name;\n /**\n * unique id of the event\n */\n id;\n /**\n * get type of the object\n * @returns type of the object\n */\n getType() {\n return \"ProxyEvent\";\n }\n /**\n * Create a new instance of the Scripting Object Proxy Event\n * @param {ProxyEventParam} param - parameter for the constructor\n */\n constructor(param) {\n const { name, objectId, eventSrc } = param;\n if (!name) throw new Error(\"Event name is required\");\n if (!objectId) throw new Error(\"Scripting object id is required\");\n if (!eventSrc) throw new Error(\"Event source is required\");\n this.objectId = objectId;\n this.name = name;\n this.#eventSrc = eventSrc;\n this.id = `${this.objectId}.${this.name}`.toLowerCase();\n }\n /**\n * subscribe to an scripting object event\n * @param callback event listener\n * @returns subscription token\n */\n subscribe = (callback) => this.#eventSrc.subscribe({\n eventId: this.id,\n callback\n });\n /**\n * unsubscribe from an scripting object event\n * @param token subscription token\n */\n unsubscribe = (token) => {\n this.#eventSrc.unsubscribe({\n eventId: this.id,\n token\n });\n };\n}\nconst isEvent = (value) => value instanceof Event;\nconst getEventId = (objectId, eventName) => `${objectId.toLowerCase()}.${eventName.toLowerCase()}`;\nexport {\n Event,\n ProxyEvent,\n getEventId,\n isEvent\n};\n","import { isEvent } from \"./event.js\";\nconst FUNCTION = \"function\";\nconst isPublicFunction = (value, fnName) => typeof value === FUNCTION && !!fnName && !fnName.startsWith(\"_\");\nclass ScriptingObject {\n /**\n * unique id of the scripting object\n */\n #id;\n /**\n * type of the scripting object\n */\n #objectType = \"Object\";\n /**\n * Creates an instance of ScriptingObject.\n * @param objectId unique id of the scripting object\n * @param objectType type of the scripting object\n */\n constructor(objectId, objectType) {\n this.#id = objectId;\n this.#objectType = objectType || this.#objectType;\n }\n /**\n * get unique id of the scripting object\n */\n get id() {\n return this.#id;\n }\n /**\n * get type of the scripting object\n */\n get objectType() {\n return this.#objectType;\n }\n /**\n * transform the scripting object to a format suitable for transmitting over window.postMessage\n * @returns marshalled scripting object\n */\n // eslint-disable-next-line no-underscore-dangle\n _toJSON = () => {\n const functions = [];\n const events = [];\n Object.keys(this).forEach((property) => {\n const value = this[property];\n if (isEvent(value)) {\n events.push(property);\n } else if (isPublicFunction(value, property)) {\n functions.push(property);\n }\n });\n return {\n objectId: this.#id,\n objectType: this.#objectType,\n functions,\n events\n };\n };\n /**\n * dispose the scripting object\n */\n // eslint-disable-next-line no-underscore-dangle\n _dispose = () => {\n };\n /**\n * dispose the scripting object\n */\n dispose = () => {\n };\n}\nexport {\n ScriptingObject,\n isPublicFunction\n};\n","var MessageType = /* @__PURE__ */ ((MessageType2) => {\n MessageType2[\"GuestClose\"] = \"guest:close\";\n MessageType2[\"GuestEventSubscribe\"] = \"guest:eventSubscribe\";\n MessageType2[\"GuestEventUnsubscribe\"] = \"guest:eventUnsubscribe\";\n MessageType2[\"GuestFocus\"] = \"guest:focus\";\n MessageType2[\"GuestReady\"] = \"guest:ready\";\n MessageType2[\"GuestReadyComplete\"] = \"guest:readyComplete\";\n MessageType2[\"GuestResize\"] = \"guest:resize\";\n MessageType2[\"HandShake\"] = \"handshake\";\n MessageType2[\"HandShakeAck\"] = \"handshake:ack\";\n MessageType2[\"HostClose\"] = \"host:close\";\n MessageType2[\"HostConfig\"] = \"host:config\";\n MessageType2[\"ListObjects\"] = \"list:objects\";\n MessageType2[\"ObjectEvent\"] = \"object:event\";\n MessageType2[\"ObjectGet\"] = \"object:get\";\n MessageType2[\"ObjectInvoke\"] = \"object:invoke\";\n return MessageType2;\n})(MessageType || {});\nexport {\n MessageType\n};\n","import type {\n IScriptingObject,\n RemotingScriptingObject,\n} from '@elliemae/pui-scripting-object';\n\nexport enum OpenMode {\n /**\n * open as a popup window\n */\n Popup = 'popup',\n /**\n * open as an embedded iframe\n */\n Embed = 'embed',\n}\n\nexport type ValueOf<T> = T[keyof T];\n\n/**\n * allowed sandbox values for the guest application\n */\nexport enum IFrameSandboxValues {\n AllowDownloadsWithoutUserActivation = 'allow-downloads-without-user-activation',\n AllowDownloads = 'allow-downloads',\n AllowForms = 'allow-forms',\n AllowModals = 'allow-modals',\n AllowOrientationLock = 'allow-orientation-lock',\n AllowPointerLock = 'allow-pointer-lock',\n AllowPopups = 'allow-popups',\n AllowPopupsToEscapeSandbox = 'allow-popups-to-escape-sandbox',\n AllowPresentation = 'allow-presentation',\n AllowSameOrigin = 'allow-same-origin',\n AllowScripts = 'allow-scripts',\n AllowStorageAccessByUserActivation = 'allow-storage-access-by-user-activation',\n AllowTopNavigation = 'allow-top-navigation',\n AllowTopNavigationByUserActivation = 'allow-top-navigation-by-user-activation',\n}\n\nexport type GenericFunction = (...args: unknown[]) => unknown;\n\nexport type EventObject = {\n object: RemotingScriptingObject;\n eventName: string;\n eventParams: Record<string, unknown>;\n eventHandler: string | null;\n eventOptions: {\n allowsFeedback: boolean;\n timeout?: number;\n };\n};\n\n/**\n * features for the popup window\n */\nexport type WindowFeatures = {\n /**\n * width of the popup window\n */\n width?: number;\n /**\n * height of the popup window\n */\n height?: number;\n /**\n * top position of the popup window\n */\n top?: number;\n /**\n * left position of the popup window\n */\n left?: number;\n};\n\n/**\n * configuration options for rendering a guest application\n *\n */\nexport type GuestOptions = {\n /**\n * mode of opening the guest application, popup or embed\n * @default OpenMode.Embed\n */\n openMode?: OpenMode;\n /**\n * flag to disable sandboxing for iframe\n * @default false\n */\n disableSandbox?: boolean;\n /**\n * additional sandbox values for the iframe. These values will be added in addition to the default sandbox values.\n * @default [IFrameSandboxValues.AllowScripts, IFrameSandboxValues.AllowPopups, IFrameSandboxValues.AllowModals, IFrameSandboxValues.AllowForms, IFrameSandboxValues.AllowDownloads, IFrameSandboxValues.AllowSameOrigin ]\n */\n sandboxValues?: Array<IFrameSandboxValues>;\n /**\n * custom sandbox values for the iframe. These values will replace the default sandbox values entirely.\n */\n customSandboxValues?: Array<IFrameSandboxValues>;\n /**\n * resize the iframe to fit the content inside\n * @default true\n */\n fitToContent?: boolean;\n /**\n * css style for the iframe\n */\n style?: string;\n /**\n * features for the popup window\n * @default { width: 800, height: 600, top: 100, left: 100 }\n */\n popupWindowFeatures?: WindowFeatures;\n /**\n * permission policy for the guest iframe\n * check https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/iframe#allow for more details\n * @example \"microphone 'self' https://example.com; geolocation 'none'\"\n */\n permissionPolicy?: string;\n};\n\n/**\n * collection of scripting objects\n */\nexport type ScriptingObjects = Record<string, IScriptingObject>;\n\n/**\n * parameters for attaching a guest\n */\nexport type AttachParam = {\n /**\n * unique id of the guest application\n */\n guestId: string;\n /**\n * url of the guest application\n */\n url: string;\n /**\n * page title for the guest application\n */\n title: string;\n /**\n * dom element to attach the guest application to\n */\n domElement?: HTMLIFrameElement;\n /**\n * window object of the guest application\n */\n window: Window;\n /**\n * open mode of the guest application\n */\n openMode: OpenMode;\n /**\n * additional parameters for the guest application\n */\n searchParams?: Record<string, string | number | boolean>;\n};\n","import { GenericFunction } from './types.js';\n\nexport const getOrigin = (url: string) => {\n if (url === 'about:blank') return '*';\n try {\n const { origin } = new URL(url);\n return origin === 'null' || !origin ? url : origin;\n } catch (e) {\n const { origin } = new URL(url, document.baseURI);\n return origin;\n }\n};\n\nexport const flatten = (source: unknown[]): unknown[] =>\n source.flat(Infinity).filter((v) => v !== undefined);\n\nexport function isFunction(value: any): value is GenericFunction {\n return typeof value === 'function';\n}\n\nconst TRUSTED_DOMAIN_SUFFIXES = ['.ice.com', '.elliemae.com', '.ellielabs.com'];\nconst TRUSTED_HOSTNAMES = ['localhost', '127.0.0.1'];\n\nexport const isTrustedDomain = (url: string): boolean => {\n try {\n const { hostname } = new URL(url, document.baseURI);\n return (\n TRUSTED_HOSTNAMES.includes(hostname) ||\n TRUSTED_DOMAIN_SUFFIXES.some(\n (suffix) => hostname === suffix.slice(1) || hostname.endsWith(suffix),\n )\n );\n } catch {\n return false;\n }\n};\n","import { Remoting, MessageType } from '@elliemae/microfe-common';\nimport { EventObject, OpenMode } from './types.js';\nimport { getOrigin } from './utils.js';\nimport type { PerformanceTracker } from './performanceTracker.js';\n\n/**\n * options for creating a guest application\n */\ntype GuestOption = {\n /**\n * unique id of the guest application\n */\n guestId: string;\n /**\n * page title of the guest application\n */\n title: string;\n /**\n * url of the guest application\n */\n url: string;\n /**\n * iframe element of the guest application\n */\n domElement?: HTMLIFrameElement;\n /**\n * window object of the guest application\n */\n window: Window;\n /**\n * open mode of the guest application\n */\n openMode: OpenMode;\n /**\n * individual query parameters of the guest application's url parameter string\n */\n searchParams?: Record<string, unknown>;\n /**\n * remoting object\n */\n remoting: Remoting;\n /**\n * performance tracker for timing measurements\n */\n perfTracker: PerformanceTracker;\n};\n\n/**\n * message to be sent\n */\nexport type MessageParam = {\n /**\n * type of the message\n */\n messageType: string;\n /**\n * body of the message\n */\n messageBody: unknown;\n};\n\n/**\n * Object repesenting guest application\n */\nexport class Guest {\n /**\n * unique id of the guest application\n */\n public readonly id: string;\n\n /**\n * page title of the guest application\n */\n public readonly title: string;\n\n /**\n * url of the guest application\n */\n public readonly url: string;\n\n /**\n * individual query parameters of the guest application's url parameter string\n */\n public readonly searchParams: Record<string, unknown>;\n\n /**\n * iframe element of the guest application\n */\n public readonly domElement: HTMLIFrameElement | null;\n\n /**\n * window object of the guest application\n */\n public readonly window: Window;\n\n /**\n * open mode of the guest application\n */\n public readonly openMode: OpenMode;\n\n /**\n * origin of the guest application\n */\n public readonly origin: string;\n\n /**\n * flag indicating if the guest application is initialized\n */\n public initialized = false;\n\n /**\n * flag indicating if the guest application is ready\n */\n public ready = false;\n\n /**\n * capabilities of the guest application\n */\n public capabilities: Record<string, unknown>;\n\n /**\n * remoting object\n */\n #remoting: Remoting;\n\n /**\n * performance tracker for timing measurements\n */\n #perfTracker: PerformanceTracker;\n\n /**\n * Create object representing guest application\n * @param {GuestOption} option - options for creating a guest application\n */\n constructor(option: GuestOption) {\n const {\n guestId,\n domElement = null,\n title,\n url,\n window,\n searchParams = {},\n openMode = OpenMode.Embed,\n remoting,\n perfTracker,\n } = option;\n this.id = guestId;\n this.title = title;\n this.url = url;\n this.origin = getOrigin(url);\n this.searchParams = searchParams;\n this.domElement = domElement;\n this.window = window;\n this.openMode = openMode;\n this.capabilities = {};\n this.#perfTracker = perfTracker;\n this.#remoting = remoting;\n }\n\n /**\n * clean up resources\n */\n dispose = () => {\n if (this.openMode === OpenMode.Popup && !this.window.closed) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n this.window.document;\n this.window.close();\n } catch (e) {\n this.#remoting.send({\n targetWin: this.window,\n targetOrigin: this.origin,\n messageType: MessageType.HostClose,\n messageBody: {},\n });\n }\n } else {\n this.domElement?.remove?.();\n }\n // remove guest window from allowed list\n this.#remoting.removeSender({ origin: this.origin, window: this.window });\n };\n\n /**\n * Get information about the guest application\n * @returns guest properties\n */\n getInfo = () => ({\n guestId: this.id,\n guestTitle: this.title,\n guestUrl: this.url,\n });\n\n /**\n * Handshake with the guest application in the popup window\n * @returns true if the guest popup window is open & connected\n */\n handShake = () =>\n new Promise<boolean>((resolve) => {\n let handShakeCount = 0;\n const handShakeRetries = 5;\n let handShakeHandle: ReturnType<typeof setInterval>;\n const onAck = () => {\n clearInterval(handShakeHandle);\n this.#remoting.unlisten({\n messageType: MessageType.HandShakeAck,\n callback: onAck,\n });\n resolve(true);\n };\n handShakeHandle = setInterval(() => {\n if (handShakeCount >= handShakeRetries) {\n clearInterval(handShakeHandle);\n this.#remoting.unlisten({\n messageType: MessageType.HandShakeAck,\n callback: onAck,\n });\n resolve(false);\n } else {\n this.#remoting.send({\n targetWin: this.window,\n targetOrigin: this.origin,\n messageType: MessageType.HandShake,\n messageBody: {},\n });\n handShakeCount += 1;\n }\n }, 1000);\n this.#remoting.listen({\n messageType: MessageType.HandShakeAck,\n callback: onAck,\n });\n });\n\n /**\n * initialize guest messaging\n */\n init = () => {\n // add guest window to the allowed list\n this.#remoting.addSender({ origin: this.origin, window: this.window });\n // for popup guests, we need to provide the guest with the host's window\n if (this.openMode === OpenMode.Popup) {\n this.handShake().catch(() => {});\n }\n };\n\n /**\n * invokes event callback on the guest application\n * @param {EventObject} event - event object\n * @param {number} timeout - timeout in milliseconds\n * @returns {Promise} resolves when the guest handles the event\n */\n dispatchEvent = (event: EventObject, timeout: number) => {\n let timingToken: string | undefined;\n if (this.#perfTracker.enabled) {\n const name = `ScriptingObject.Event.${event.object.objectId}.${event.eventName}`;\n timingToken = this.#perfTracker.start(name, {\n appId: this.id,\n appUrl: this.url,\n });\n }\n return this.#remoting\n .invoke({\n targetWin: this.window,\n targetOrigin: this.origin,\n messageType: MessageType.ObjectEvent,\n messageBody: event,\n responseTimeoutMs: timeout,\n })\n .finally(() => {\n if (timingToken) {\n this.#perfTracker.end(timingToken, {\n appId: this.id,\n appUrl: this.url,\n });\n }\n });\n };\n\n /**\n * Send a message without any form of response. fire and forget\n * @param {MessageParam} param - message to be sent\n */\n send = (param: MessageParam) => {\n this.#remoting.send({\n targetWin: this.window,\n targetOrigin: this.origin,\n ...param,\n });\n };\n}\n","const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);\nexport default {\n randomUUID\n};","// Unique ID creation requires a high quality random # generator. In the browser we therefore\n// require the crypto API and do not support built-in fallback to lower quality random number\n// generators (like Math.random()).\nlet getRandomValues;\nconst rnds8 = new Uint8Array(16);\nexport default function rng() {\n // lazy load so that environments that need to polyfill have a chance to do so\n if (!getRandomValues) {\n // getRandomValues needs to be invoked in a context where \"this\" is a Crypto implementation.\n getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);\n\n if (!getRandomValues) {\n throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');\n }\n }\n\n return getRandomValues(rnds8);\n}","import validate from './validate.js';\n/**\n * Convert array of 16 byte values to UUID string format of the form:\n * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n */\n\nconst byteToHex = [];\n\nfor (let i = 0; i < 256; ++i) {\n byteToHex.push((i + 0x100).toString(16).slice(1));\n}\n\nexport function unsafeStringify(arr, offset = 0) {\n // Note: Be careful editing this code! It's been tuned for performance\n // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434\n return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];\n}\n\nfunction stringify(arr, offset = 0) {\n const uuid = unsafeStringify(arr, offset); // Consistency check for valid UUID. If this throws, it's likely due to one\n // of the following:\n // - One or more input array values don't map to a hex octet (leading to\n // \"undefined\" in the uuid)\n // - Invalid input values for the RFC `version` or `variant` fields\n\n if (!validate(uuid)) {\n throw TypeError('Stringified UUID is invalid');\n }\n\n return uuid;\n}\n\nexport default stringify;","import native from './native.js';\nimport rng from './rng.js';\nimport { unsafeStringify } from './stringify.js';\n\nfunction v4(options, buf, offset) {\n if (native.randomUUID && !buf && !options) {\n return native.randomUUID();\n }\n\n options = options || {};\n const rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`\n\n rnds[6] = rnds[6] & 0x0f | 0x40;\n rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided\n\n if (buf) {\n offset = offset || 0;\n\n for (let i = 0; i < 16; ++i) {\n buf[offset + i] = rnds[i];\n }\n\n return buf;\n }\n\n return unsafeStringify(rnds);\n}\n\nexport default v4;","import { v4 as uuidv4 } from \"uuid\";\nconst MESSAGE_SOURCE = \"elli:remoting\";\nconst RESPONSE_MESSAGE_TYPE = \"elli:remoting:response\";\nconst EXCEPTION_MESSAGE_TYPE = \"elli:remoting:exception\";\nconst createMessage = ({\n messageType,\n messageBody,\n requestId,\n onewayMsg = false\n}) => ({\n requestId: requestId ?? (!onewayMsg ? uuidv4() : null),\n source: MESSAGE_SOURCE,\n type: messageType,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n body: messageBody\n});\nconst sendMessage = (param) => {\n const { targetWin, targetOrigin, messageType, messageBody } = param;\n const msg = createMessage({ messageType, messageBody });\n targetWin.postMessage(msg, targetOrigin);\n};\nclass Remoting {\n #correlationId;\n #logger;\n /**\n * set of listeners that are registered\n */\n #listeners = /* @__PURE__ */ new Map();\n /**\n * Represents the set of invocations that are waiting for a response\n */\n #invocations = /* @__PURE__ */ new Map();\n /**\n * The handle to the timeout monitor\n */\n #timeoutMonitorHandle = null;\n /**\n * The window that remoting was initialized on\n */\n #initializedWindow = null;\n /**\n * The set of windows that are allowed to send messages to this window\n */\n #allowedSenders = /* @__PURE__ */ new Map();\n /**\n * Create a new instance of the Remoting class\n * @param logger pui-diagnostic logger\n * @param correlationId unique id for the current session\n */\n constructor(logger, correlationId) {\n if (!logger) throw new Error(\"logger is required\");\n if (!correlationId) throw new Error(\"correlationId is required\");\n this.#correlationId = correlationId;\n this.#logger = logger;\n }\n // Evaluates the timeouts on any waiting invocations and schedules the next check\n #evaluateTimeouts = () => {\n this.#timeoutMonitorHandle = null;\n const ts = Date.now();\n const canceledItems = [];\n let nextCancelTime = null;\n this.#invocations.forEach((eventData, key) => {\n const { requestId, cancelTime } = eventData;\n if (cancelTime && cancelTime <= ts) {\n this.#logger.debug(\n `Detected response timeout for requestId: ${requestId}...`\n );\n canceledItems.push(key);\n eventData.resolve(void 0);\n } else if (cancelTime) {\n nextCancelTime = nextCancelTime === null ? cancelTime : Math.min(nextCancelTime, cancelTime);\n }\n });\n canceledItems.forEach((key) => {\n this.#invocations.delete(key);\n });\n if (nextCancelTime !== null) {\n const delay = Math.max(nextCancelTime - Date.now(), 0);\n this.#scheduleTimeoutCheck(delay);\n }\n };\n // Schedule a timeout check after a delay\n #scheduleTimeoutCheck = (delayMs) => {\n if (this.#timeoutMonitorHandle !== null) return;\n this.#timeoutMonitorHandle = window.setTimeout(\n this.#evaluateTimeouts,\n delayMs\n );\n };\n // Stops the timeout monitor\n #stopResponseMonitor = () => {\n if (this.#timeoutMonitorHandle !== null) {\n window.clearTimeout(this.#timeoutMonitorHandle);\n this.#timeoutMonitorHandle = null;\n }\n };\n // Pops an invocation from the incovation list\n #popInvocation = (requestId) => {\n const e = this.#invocations.get(requestId);\n this.#logger.debug(`serving requestId: ${requestId}`);\n this.#invocations.delete(requestId);\n return e;\n };\n // Handles a response to a prior cross-frame invocation\n #processResponse = (message) => {\n const { requestId } = message;\n this.#logger.debug(\n `Response received for invocation requestId: ${requestId}`\n );\n const eventData = this.#popInvocation(requestId);\n if (!eventData) {\n this.#logger.debug(\n `Received response to stale/invalid request with requestId: ${requestId}`\n );\n return false;\n }\n eventData.resolve(message.body);\n return true;\n };\n // Handles a response to a prior cross-frame invocation\n #processException = (message) => {\n this.#logger.debug(\n `Exception received for invocation (requestId = ${message.requestId})`\n );\n const eventData = this.#popInvocation(message.requestId);\n if (!eventData) {\n this.#logger.warn(\n `Received exception for stale/invalid request (requestId = ${message.requestId})`\n );\n return false;\n }\n eventData.reject(new Error(message.body));\n return true;\n };\n // Receives a message from another window and invokes any event handlers\n #receive = ({\n sourceWin,\n sourceOrigin,\n message\n }) => {\n this.#logger.debug(`Received message of type \"${message.type}\"`);\n const callbacks = this.#listeners.get(message.type);\n if (!callbacks) return false;\n callbacks.forEach((callback) => {\n this.#logger.debug(`Invoking message handler ${callback.name}`);\n callback({\n sourceWin,\n sourceOrigin,\n requestId: message.requestId,\n type: message.type,\n body: message.body\n });\n });\n return true;\n };\n // Processes a message received thru the window's message event\n #processMessage = (message) => {\n if (this.#allowedSenders.size === 0) return false;\n if (!message.source) return false;\n const senderOrigin = this.#allowedSenders.get(message.source);\n if (!senderOrigin) return false;\n if (message?.data?.source !== MESSAGE_SOURCE) return false;\n this.#logger.debug(\n `Remoting: Received message of type \"${message.data.type}\"`\n );\n if (message.data.type === RESPONSE_MESSAGE_TYPE)\n this.#processResponse(message.data);\n else if (message.data.type === EXCEPTION_MESSAGE_TYPE)\n this.#processException(message.data);\n else\n this.#receive({\n sourceWin: message.source,\n sourceOrigin: senderOrigin,\n message: message.data\n });\n return true;\n };\n /**\n * Adds window and its origin list of allowed senders\n * @param {AddSenderParam} param - The sender to add\n */\n addSender = (param) => {\n const { origin, window: window2 } = param;\n if (!origin) throw new Error(\"origin is required\");\n if (!window2) throw new Error(\"window is required\");\n this.#allowedSenders.set(window2, origin);\n };\n /**\n * Initializes the remoting service for a window\n * @param win The window to initialize remoting for\n */\n initialize = (win) => {\n if (this.#initializedWindow) {\n this.#initializedWindow.removeEventListener(\n \"message\",\n this.#processMessage\n );\n }\n win.addEventListener(\"message\", this.#processMessage);\n this.#initializedWindow = win;\n this.#logger.debug(`initialized remoting id: ${this.#correlationId}`);\n };\n /**\n * Closes the remoting service for a window\n */\n close = () => {\n if (this.#initializedWindow) {\n this.#initializedWindow.removeEventListener(\n \"message\",\n this.#processMessage\n );\n this.#initializedWindow = null;\n }\n this.#stopResponseMonitor();\n this.#logger.debug(`closed remoting id: ${this.#correlationId}`);\n };\n /**\n * Sends an invocation which generates a Promise to be used to get a response\n * @param {InvokeParam} param The parameters for the invocation\n * @returns promisifyed response\n */\n invoke = (param) => {\n const {\n targetWin,\n targetOrigin,\n messageType,\n messageBody,\n responseTimeoutMs\n } = param;\n return new Promise((resolve, reject) => {\n const msg = createMessage({ messageType, messageBody });\n this.#invocations.set(msg.requestId, {\n requestId: msg.requestId,\n resolve,\n reject,\n cancelTime: responseTimeoutMs ? Date.now() + responseTimeoutMs : null\n });\n targetWin.postMessage(msg, targetOrigin);\n const { requestId } = msg;\n this.#logger.debug(\n `Posted invocation message of type ${messageType} requestId: ${requestId || \"\"}`\n );\n if (responseTimeoutMs) {\n this.#logger.debug(\n `scheduling timeout check for requestId: ${requestId || \"\"} in ${responseTimeoutMs} ms`\n );\n this.#scheduleTimeoutCheck(responseTimeoutMs);\n }\n });\n };\n /**\n * Setup callback for a specific message type\n * @param {ListenParam<T>} param The parameters for the listener\n */\n listen = (param) => {\n const { messageType, callback } = param;\n const items = this.#listeners.get(messageType) || [];\n items.push(callback);\n this.#listeners.set(messageType, items);\n };\n /**\n * Remove a previously registered callback for a specific message type\n * @param {ListenParam<T>} param The parameters identifying the listener to remove\n */\n unlisten = (param) => {\n const { messageType, callback } = param;\n const items = this.#listeners.get(messageType);\n if (!items) return;\n const index = items.indexOf(callback);\n if (index !== -1) {\n items.splice(index, 1);\n }\n };\n /**\n * Send a message without any form of response. Fire and forget\n * @param {SendParam} param The parameters for the send\n */\n send = (param) => {\n const { targetWin, targetOrigin, messageType, messageBody } = param;\n const msg = createMessage({\n messageType,\n messageBody,\n onewayMsg: true\n });\n targetWin.postMessage(msg, targetOrigin);\n this.#logger.debug(`Posted one-way message of type \"${messageType}\"`);\n };\n /**\n * Removes a window from the list of allowed senders\n * @param {AddSenderParam} param - The sender to remove\n */\n removeSender = (param) => {\n const { window: window2 } = param;\n if (window2) this.#allowedSenders.delete(window2);\n };\n /**\n * Send a response message to a window\n * @param {RespondParam} param The parameters for the response\n */\n respond = (param) => {\n const { targetWin, targetOrigin, requestId, response } = param;\n const msg = createMessage({\n messageType: RESPONSE_MESSAGE_TYPE,\n messageBody: response,\n requestId\n });\n targetWin.postMessage(msg, targetOrigin);\n this.#logger.debug(\n `Response sent to caller for invocation requestId: ${requestId}`\n );\n };\n /**\n * Send an exception message to a window\n * @param {RaiseExceptionParam} param The parameters for the exception\n */\n raiseException = (param) => {\n const { targetWin, targetOrigin, requestId, ex } = param;\n const messageBody = ex instanceof Error ? ex.message : ex;\n const msg = createMessage({\n messageType: EXCEPTION_MESSAGE_TYPE,\n messageBody,\n requestId\n });\n targetWin.postMessage(msg, targetOrigin);\n this.#logger.debug(\n `Exception sent to caller for invocation. requestId: ${requestId}`\n );\n };\n}\nexport {\n Remoting,\n sendMessage\n};\n","const MODULE_OBJECT = \"module\";\nvar SecurityContext = /* @__PURE__ */ ((SecurityContext2) => {\n SecurityContext2[\"USER\"] = \"USER\";\n SecurityContext2[\"PARTNER\"] = \"PARTNER\";\n return SecurityContext2;\n})(SecurityContext || {});\nclass ScriptingObjectManager {\n #normalizeId = (id) => id.trim().toLowerCase();\n /**\n * collection of registered scripting objects\n */\n #scriptingObjects = /* @__PURE__ */ new Map();\n /**\n * collection of proxied scripting objects for each guest\n */\n #guestScriptingObjects = /* @__PURE__ */ new Map();\n #addGuestScriptingObject = (params) => {\n const { so, guestId } = params;\n const objectId = this.#normalizeId(so.id);\n const guestSOs = this.#guestScriptingObjects.get(guestId);\n if (!guestSOs) {\n this.#guestScriptingObjects.set(guestId, /* @__PURE__ */ new Map([[objectId, params]]));\n } else {\n if (guestSOs.has(objectId))\n throw new Error(\n `Scripting Object ${so.id} already exists for guest ${guestId}`\n );\n guestSOs.set(objectId, params);\n }\n };\n #disposeSO = ({ so }) => {\n if (so._dispose && typeof so._dispose === \"function\") {\n try {\n so._dispose();\n } catch {\n }\n }\n };\n /**\n * get scripting object for the given object id and guest id\n * this method is backward compatible with the V1 guest, where the guest id is not provided. It will return the scripting object for the first guest\n * @param root0\n * @param root0.objectId\n * @param root0.guestId\n * @returns scripting object for the given object id and guest id. null if not found\n */\n #getGuestScriptingObject = ({\n objectId,\n guestId\n }) => {\n if (objectId === MODULE_OBJECT && !guestId) {\n for (const [, mSOs] of this.#guestScriptingObjects) {\n const mSO = mSOs.get(objectId);\n if (mSO) return mSO;\n }\n }\n const SOs = guestId ? this.#guestScriptingObjects.get(guestId) : null;\n if (SOs) {\n return SOs.get(objectId) ?? null;\n }\n return null;\n };\n #removeGuestScriptingObject = ({\n objectId,\n guestId\n } = {}) => {\n if (guestId) {\n if (!objectId) {\n const sosInfo = this.#guestScriptingObjects.get(guestId);\n if (sosInfo) {\n sosInfo.forEach(this.#disposeSO);\n }\n this.#guestScriptingObjects.delete(guestId);\n return;\n }\n const moduleSOs = this.#guestScriptingObjects.get(guestId);\n if (moduleSOs) {\n const soInfo = moduleSOs.get(objectId);\n if (soInfo) this.#disposeSO(soInfo);\n moduleSOs.delete(objectId);\n }\n } else if (objectId) {\n this.#guestScriptingObjects.forEach((moduleSOs) => {\n const soInfo = moduleSOs.get(objectId);\n if (soInfo) this.#disposeSO(soInfo);\n moduleSOs.delete(objectId);\n });\n }\n };\n /**\n * registers scripting object to the host\n * @param so scripting object to register\n * @param {AddScriptingObjectParams<ValueOf<AppObjects>>}\n * @param params\n */\n addScriptingObject = (so, params) => {\n const { guestId } = params || {};\n if (!so?.id || !so?._toJSON) {\n throw new Error(\"Object is not derived from ScriptingObject\");\n }\n const objectId = this.#normalizeId(so.id);\n if (objectId === MODULE_OBJECT && !guestId) {\n throw new Error(`Guest id is required to add Module scripting object`);\n }\n if (guestId) {\n this.#addGuestScriptingObject({ so, ...params, guestId });\n return;\n }\n if (this.#scriptingObjects.has(objectId))\n throw new Error(`Scripting Object ${so.id} already exists`);\n this.#scriptingObjects.set(objectId, { so, ...params });\n };\n /**\n * Get reference to the scripting object proxy for a guest\n * @param {string} objectId scripting object id\n * @param {GuestContext} guest that is requesting the scripting object\n * @returns proxied scripting object reference\n */\n getObject = (objectId, guest) => {\n const id = this.#normalizeId(objectId);\n let soInfo = this.#getGuestScriptingObject({\n objectId: id,\n guestId: guest?.id\n });\n soInfo = soInfo ?? this.#scriptingObjects.get(id) ?? null;\n const { so } = soInfo || {};\n if (!so) return null;\n return so;\n };\n /**\n * Check if a scripting object exists\n * @param objectId unique id of the scripting object\n * @param guest\n * @returns true if the scripting object exists, false otherwise\n */\n has = (objectId, guest) => this.getObject(objectId, guest) !== null;\n /**\n * list name of scripting objects for the given guest\n * @param guestId unique id of the guest\n * @returns name of scripting objects for the given guest\n */\n listScriptingObjects = (guestId) => {\n const objects = new Set(this.#scriptingObjects.keys());\n const guestSOs = this.#guestScriptingObjects.get(guestId);\n if (guestSOs) {\n for (const key of guestSOs.keys()) objects.add(key);\n }\n return Array.from(objects);\n };\n /**\n * removes scripting object\n * @param objectId unique id of the scripting object\n * @param guestId unique id of the guest\n */\n removeScriptingObject = (objectId, guestId) => {\n const id = this.#normalizeId(objectId);\n if (guestId) {\n this.#removeGuestScriptingObject({ objectId: id, guestId });\n } else {\n this.#removeGuestScriptingObject({ objectId: id });\n const soInfo = this.#scriptingObjects.get(id);\n if (soInfo) this.#disposeSO(soInfo);\n this.#scriptingObjects.delete(id);\n }\n };\n /**\n * removes all scripting objects\n * @param guestId unique id of the guest\n */\n removeAllScriptingObjects = (guestId) => {\n if (!guestId) {\n this.#scriptingObjects.forEach(this.#disposeSO);\n this.#scriptingObjects.clear();\n } else {\n this.#removeGuestScriptingObject({ guestId });\n }\n };\n}\nexport {\n MODULE_OBJECT,\n ScriptingObjectManager,\n SecurityContext\n};\n","class ScriptingObjectProxy {\n /**\n * proxy type\n */\n __TYPE__ = \"Proxy\";\n /**\n * unique id of scripting object\n */\n id;\n /**\n * type of scripting object\n */\n objectType;\n /**\n * Creates a new instance of the Scripting Object Proxy\n * @param objectId unique id of scripting object\n * @param objectType type of scripting object\n */\n constructor(objectId, objectType) {\n this.id = objectId;\n this.objectType = objectType;\n }\n}\nconst isScriptingObjectProxy = (value) => (\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n value?.constructor?.name === \"Proxy\" || // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n value?.constructor?.name === \"ScriptingObjectProxy\" || // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, no-underscore-dangle\n value?.__TYPE__ === \"Proxy\"\n);\nexport {\n ScriptingObjectProxy,\n isScriptingObjectProxy\n};\n","import type { IAnalytics, TimingOptions } from '@elliemae/pui-scripting-object';\n\nexport type PerformanceTrackerOptions = {\n analyticsObj: IAnalytics;\n enabled?: boolean;\n samplingRatio?: number;\n dedupWindowMs?: number;\n onError?: (message: string) => void;\n};\n\n/**\n * Encapsulates SSF performance timing — enabled guard, per-name sampling\n * ratio configuration, deduplication window, and start/end lifecycle.\n *\n * Low-frequency timing names (e.g. `SSF.Guest.Load`) bypass both the\n * dedup window and the custom sampling ratio, using the analytics-so default.\n */\nexport class PerformanceTracker {\n #analyticsObj: IAnalytics;\n\n #enabled: boolean;\n\n #samplingRatio: number;\n\n #samplingConfigured = new Set<string>();\n\n #dedupWindowMs: number;\n\n #lastRecorded = new Map<string, number>();\n\n #onError: ((message: string) => void) | undefined;\n\n static readonly DEFAULT_SAMPLING_RATIO = 0.05;\n\n static readonly DEFAULT_DEDUP_WINDOW_MS = 10_000;\n\n static readonly #LOW_FREQUENCY = new Set(['SSF.Guest.Load']);\n\n constructor(options: PerformanceTrackerOptions) {\n this.#analyticsObj = options.analyticsObj;\n this.#enabled = options.enabled ?? false;\n this.#samplingRatio =\n options.samplingRatio ?? PerformanceTracker.DEFAULT_SAMPLING_RATIO;\n this.#dedupWindowMs =\n options.dedupWindowMs ?? PerformanceTracker.DEFAULT_DEDUP_WINDOW_MS;\n this.#onError = options.onError;\n }\n\n /**\n * Whether performance tracking is active. Callers can use this to\n * skip expensive work (e.g. building timing name strings) when\n * tracking is disabled.\n * @returns {boolean} true when performance tracking is enabled\n */\n get enabled(): boolean {\n return this.#enabled;\n }\n\n /**\n * Begin a timing measurement. Returns the timing name as a token when\n * timing was started, or `undefined` when timing is disabled, deduped,\n * or skipped. Pass the returned token to {@link end}.\n * Never throws — failures are reported via the `onError` callback.\n * @param {string} name - timing event name\n * @param {TimingOptions} options - context passed to the analytics object\n * @returns {string | undefined} the timing token, or undefined if skipped\n */\n start(name: string, options: TimingOptions): string | undefined {\n if (!this.#enabled) return undefined;\n try {\n const lowFreq = PerformanceTracker.#LOW_FREQUENCY.has(name);\n if (!lowFreq && !this.#shouldTrack(name)) return undefined;\n if (!lowFreq && !this.#samplingConfigured.has(name)) {\n this.#analyticsObj.setTimingEventSamplingRatio({\n [name]: this.#samplingRatio,\n });\n this.#samplingConfigured.add(name);\n }\n this.#analyticsObj.startTiming(name, options).catch((e) => {\n this.#reportError(`startTiming failed: ${(e as Error).message}`);\n });\n return name;\n } catch (e) {\n this.#reportError(`startTiming failed: ${(e as Error).message}`);\n return undefined;\n }\n }\n\n /**\n * End a timing measurement previously started via {@link start}.\n * No-op when token is `undefined` (timing was not started).\n * Never throws — failures are reported via the `onError` callback.\n * @param {string | undefined} token - token returned by {@link start}\n * @param {TimingOptions} options - context passed to the analytics object\n */\n end(token: string | undefined, options: TimingOptions): void {\n if (!token) return;\n try {\n this.#analyticsObj.endTiming(token, options).catch((e) => {\n this.#reportError(`endTiming failed: ${(e as Error).message}`);\n });\n } catch (e) {\n this.#reportError(`endTiming failed: ${(e as Error).message}`);\n }\n }\n\n #reportError(message: string): void {\n try {\n this.#onError?.(message);\n } catch {\n // prevent onError callback from crashing the host/guest\n }\n }\n\n #shouldTrack(name: string): boolean {\n if (this.#dedupWindowMs <= 0) return true;\n const now = performance.now();\n const last = this.#lastRecorded.get(name);\n if (last !== undefined && now - last < this.#dedupWindowMs) return false;\n this.#lastRecorded.set(name, now);\n return true;\n }\n}\n","/* eslint-disable max-lines */\nimport { v4 as uuidv4 } from 'uuid';\nimport type {\n IScriptingObject,\n IScriptingObjectProxy,\n ScriptingObjectTypes,\n Events,\n IAnalytics,\n} from '@elliemae/pui-scripting-object';\nimport {\n Remoting,\n ScriptingObject,\n MessageType,\n Event,\n ScriptingObjectManager,\n ProxyEvent,\n isScriptingObjectProxy,\n GuestContext,\n} from '@elliemae/microfe-common';\nimport type {\n CallerInfo,\n ListenerCallbackParams,\n EventListeners,\n IScriptingObjectProxyEvent,\n AddScriptingObjectParams,\n GetObjectParams,\n DispatchEventParam,\n EventOptions,\n FilterCriteria,\n} from '@elliemae/microfe-common';\nimport { Logger, LogLevels } from '@elliemae/pui-diagnostics';\nimport {\n EventObject,\n GenericFunction,\n IFrameSandboxValues,\n GuestOptions,\n ValueOf,\n ScriptingObjects,\n AttachParam,\n OpenMode,\n WindowFeatures,\n} from './types.js';\nimport {\n ISSFHost,\n HostOption,\n LoadGuestParam,\n LoadGuestsParam,\n GuestCloseParam,\n GuestEventSubscribeCallback,\n GuestEventUnsubscribeCallback,\n} from './ihost.js';\nimport { Guest } from './guest.js';\nimport { flatten, isFunction, isTrustedDomain } from './utils.js';\nimport { PerformanceTracker } from './performanceTracker.js';\n\nexport const SANDBOX_DEFAULT = [\n IFrameSandboxValues.AllowScripts,\n IFrameSandboxValues.AllowPopups,\n IFrameSandboxValues.AllowModals,\n IFrameSandboxValues.AllowForms,\n IFrameSandboxValues.AllowDownloads,\n IFrameSandboxValues.AllowSameOrigin,\n];\n\ntype GuestWindowSize = {\n width: number;\n height: number;\n};\n\n/**\n * Host class for embedding guest application and enabling bi-directional communication using scripting objects methods and events\n * @typeParam AppObjects - scripting objects that are published by the host application\n * @typeParam AppEvents - events that are published by the host application\n */\n/* eslint-disable indent */\nexport class SSFHost<\n AppObjects extends ScriptingObjects = ScriptingObjectTypes,\n AppEvents extends EventListeners = Events,\n> implements ISSFHost<AppObjects, AppEvents>\n{\n /* eslint-enable indent */\n /**\n * unique identifier for the host\n */\n public hostId: string;\n\n /**\n * reference to the remoting object\n */\n #remoting: Remoting;\n\n /**\n * unique identifier for the host\n */\n #correlationId: string;\n\n /**\n * reference to the logger\n */\n #logger: Logger;\n\n /**\n * reference to the analytics object\n */\n #analyticsObj: IAnalytics;\n\n /**\n * list of guests\n */\n #guests = new Map<string, Guest>();\n\n /**\n * reverse lookup: window -> guest for O(1) message routing\n */\n #guestsByWindow = new Map<Window, Guest>();\n\n /**\n * reverse lookup: url -> guest for O(1) popup dedup\n */\n #guestsByUrl = new Map<string, Guest>();\n\n /**\n * list of callbacks for guest close.\n */\n #guestCloseCallbackList = new Map<\n string,\n (({ id }: { id: string }) => void | Promise<void>)[]\n >();\n\n /**\n * scripting object manager\n */\n #soManager: ScriptingObjectManager<AppObjects>;\n\n /**\n * callback for ready state\n */\n #readyStateCallback: null | ((guest: Guest) => void) = null;\n\n /**\n *\n */\n #popupGuestMonitor: ReturnType<typeof setInterval> | null = null;\n\n /**\n * callback for guest event subscription\n */\n #onGuestEventSubscribe: GuestEventSubscribeCallback | null = null;\n\n /**\n * callback for guest event unsubscription\n */\n #onGuestEventUnsubscribe: GuestEventUnsubscribeCallback | null = null;\n\n /**\n * host-supplied metadata keyed by guest id, forwarded in callChain\n */\n #guestMetadata = new Map<string, Record<string, unknown>>();\n\n /**\n * Performance tracker for host-side timing (with dedup).\n */\n #perfTracker: PerformanceTracker;\n\n /**\n * Performance tracker shared by all guests (no dedup).\n */\n #guestPerfTracker: PerformanceTracker;\n\n /**\n * Create a new host\n * @param hostId unique identifier for the host\n * @param {HostOption} option - options for the host\n */\n constructor(hostId: string, option: HostOption) {\n // Set the local variables\n this.hostId = hostId;\n if (!option?.logger) throw new Error('Logger is required');\n if (!option?.analyticsObj) throw new Error('Analytics object is required');\n this.#logger = option.logger;\n this.#analyticsObj = option.analyticsObj;\n const perfOpts = {\n analyticsObj: option.analyticsObj,\n enabled: option?.measurePerformance,\n samplingRatio: option?.performanceSamplingRatio,\n onError: (msg: string) => this.#logger.debug(msg),\n };\n this.#perfTracker = new PerformanceTracker({\n ...perfOpts,\n dedupWindowMs: option?.performanceDedupWindowMs,\n });\n this.#guestPerfTracker = new PerformanceTracker({\n ...perfOpts,\n dedupWindowMs: 0,\n });\n this.#correlationId = uuidv4();\n this.#remoting = new Remoting(this.#logger, this.#correlationId);\n if (\n option?.readyStateCallback &&\n typeof option?.readyStateCallback !== 'function'\n )\n throw new Error('readyStateCallback must be a function');\n this.#readyStateCallback = option?.readyStateCallback || null;\n this.#onGuestEventSubscribe = option?.onGuestEventSubscribe || null;\n this.#onGuestEventUnsubscribe = option?.onGuestEventUnsubscribe || null;\n this.#soManager = new ScriptingObjectManager<AppObjects>();\n // Initialize the messenger\n this.#remoting.initialize(window);\n this.#connect();\n // close all popup guest when host window gets reloaded\n window.addEventListener('beforeunload', this.#closeAllPopupGuests);\n this.#logger.debug(\n `host is initialized. hostId: ${this.hostId}, correlationId: ${\n this.#correlationId\n }`,\n );\n }\n\n #sendBAEvent = (event: string, data: Record<string, unknown>) => {\n const baEvent = { event, ...data };\n this.#analyticsObj.sendBAEvent(baEvent).catch((e) => {\n this.#logger.debug(\n `Analytics sendBAEvent failed: ${(e as Error).message}`,\n );\n });\n };\n\n #closeAllPopupGuests = () => {\n const popupIds = Array.from(this.#guests.values())\n .filter((guest) => guest.openMode === OpenMode.Popup)\n .map((guest) => guest.id);\n popupIds.forEach((id) => this.unloadGuest(id));\n };\n\n /**\n * get the reference to the guest application by its window\n * @param guestWindow reference to the guest window\n * @returns reference to the guest\n */\n #getGuestForWindow = (guestWindow: Window) =>\n this.#guestsByWindow.get(guestWindow);\n\n /**\n * get the reference to the guest application by its window\n * @param url url of the guest application\n * @returns reference to the guest\n */\n #getGuestForUrl = (url: string) => this.#guestsByUrl.get(url) ?? null;\n\n /**\n * check if a object is a scripting object\n * @param value javascript object\n * @returns true if the object is a scripting object\n */\n #isScriptingObject = (value: any): value is ValueOf<AppObjects> =>\n // eslint-disable-next-line no-underscore-dangle, @typescript-eslint/no-unsafe-member-access\n typeof value?._toJSON === 'function';\n\n #encodeResponse = (val: unknown, guest?: GuestContext) => {\n if (this.#isScriptingObject(val)) {\n // add scripting objects returned from scripting object methods\n if (\n !this.#soManager.has(\n val?.id as Extract<keyof AppObjects, string>,\n guest,\n )\n )\n this.#soManager.addScriptingObject(\n val,\n guest ? { guestId: guest?.id } : {},\n );\n // eslint-disable-next-line no-underscore-dangle\n return { type: 'object', object: val._toJSON() };\n }\n return { type: 'value', value: val };\n };\n\n #encodeException = (ex: string | Error) => {\n if (typeof ex === 'string') {\n return ex;\n }\n if (ex instanceof Error) {\n return ex.message;\n }\n return 'An unexpected error occurred in the host application';\n };\n\n #dispatchConfigEvent = (guest: Guest) => {\n if (guest.ready) {\n this.#remoting.send({\n targetWin: guest.window,\n targetOrigin: guest.origin,\n messageType: MessageType.HostConfig,\n messageBody: {\n logLevel: this.#logger.getLogLevel(),\n ...guest.getInfo(),\n },\n });\n }\n };\n\n #invoke = <T extends IScriptingObject>({\n guest,\n obj,\n functionName,\n functionParams,\n callerChain,\n }: {\n guest: Guest;\n obj: T;\n functionName: keyof IScriptingObject;\n functionParams: unknown[];\n callerChain?: CallerInfo[];\n }) => {\n const func = obj[functionName];\n // Ensure the function exists\n if (!isFunction(func)) {\n this.#logger.warn(\n `Attempt to call invalid function on object type ${\n obj.objectType\n }: ${String(functionName)}`,\n );\n return Promise.reject(\n new Error(\n `Method '${functionName}' not found in Scripting Object '${obj.id}'`,\n ),\n );\n }\n\n // Invoke the object's function\n this.#logger.debug(\n `Invoking host implementation of ${obj.id}.${String(functionName)}()`,\n );\n return new Promise((resolve) => {\n Object.defineProperty(func, 'callContext', {\n value: {\n guest,\n ...(callerChain?.length ? { callChain: callerChain } : {}),\n },\n configurable: true,\n enumerable: true,\n writable: true,\n });\n\n resolve((func as GenericFunction)(...functionParams));\n });\n };\n\n #handleGuestReadyComplete = ({\n sourceWin,\n sourceOrigin,\n requestId,\n }: ListenerCallbackParams<any>) => {\n // Verify the guest belongs to this host\n const guest = this.#getGuestForWindow(sourceWin);\n if (!guest) {\n this.#logger.warn(\n `Received ready event for unknown guest. requestId: ${requestId}`,\n );\n return;\n }\n\n // Ensure this guest is initialized\n if (!guest.initialized) {\n this.#logger.warn(\n 'Guest must be initialized before it is marked as ready',\n );\n this.#remoting.raiseException({\n targetWin: sourceWin,\n targetOrigin: sourceOrigin,\n requestId,\n ex: 'Guest must be initialized before it is marked as ready',\n });\n return;\n }\n\n if (!guest.ready) {\n // Set the ready state\n guest.ready = true;\n const guestInfo = guest.getInfo();\n this.#perfTracker.end('SSF.Guest.Load', {\n appId: guestInfo.guestId,\n appUrl: guestInfo.guestUrl,\n });\n // Invoke the control function on the guest\n this.#dispatchConfigEvent(guest);\n // Invoke the registered callback, if any\n this.#readyStateCallback?.(guest);\n this.#logger.audit({\n message: `Guest is ready`,\n ...guestInfo,\n });\n }\n };\n\n // Initializes a guest when the guest is full loaded\n #handleGuestReady = ({\n sourceWin,\n sourceOrigin,\n requestId,\n body,\n }: ListenerCallbackParams<Record<string, any>>) => {\n // Verify the guest belongs to this host\n const guest = this.#getGuestForWindow(sourceWin);\n if (!guest) {\n this.#logger.warn(\n `Received ready event for unknown guest. requestid = ${requestId}`,\n );\n return;\n }\n if (!guest.initialized) {\n // Initialize the capabilities object\n guest.initialized = true;\n guest.capabilities = body || {};\n this.#logger.audit({\n message: `Guest is initialized`,\n ...guest.getInfo(),\n });\n }\n // If the guest has not indicated that it will provide explicit notification\n // when it's ready, we'll fire the ready event now\n if (!body || !body.onReady) {\n this.#handleGuestReadyComplete({\n sourceWin,\n sourceOrigin,\n requestId,\n type: '',\n body: null,\n });\n }\n };\n\n /**\n * cleanup the guest reference when it is closed\n * @param param0\n * @param param0.sourceWin\n */\n #handleGuestClose = async ({ sourceWin }: ListenerCallbackParams<any>) => {\n if (sourceWin?.window) {\n const guest = this.#findGuest(sourceWin);\n if (guest && !(await guest.handShake())) {\n this.unloadGuest(sourceWin);\n }\n }\n };\n\n // Handles list objects requests from the remote automation framework\n #handleListObjects = ({\n sourceWin,\n sourceOrigin,\n requestId,\n }: ListenerCallbackParams<{\n objects: keyof AppObjects;\n }>) => {\n this.#logger.debug(\n `Processing listObjects request. requestId = ${requestId}`,\n );\n\n // Get the guest from which the request came\n const guest = this.#getGuestForWindow(sourceWin);\n if (!guest) {\n this.#logger.warn('Rejected object request from unknown guest window');\n return false;\n }\n\n // Get the list of objects available for the guest\n const objects = this.#soManager.listScriptingObjects(guest.id);\n\n this.#remoting.respond({\n targetWin: sourceWin,\n targetOrigin: sourceOrigin,\n requestId,\n response: objects,\n });\n\n this.#logger.debug({\n message: `name of scripting objects returned`,\n requestId,\n objects,\n ...guest.getInfo(),\n });\n return true;\n };\n\n // Handles object get requests from the remote automation framework\n #handleObjectGet = ({\n sourceWin,\n sourceOrigin,\n requestId,\n body,\n }: ListenerCallbackParams<{\n objectId: Extract<keyof AppObjects, string>;\n }>) => {\n const { objectId } = body;\n this.#logger.debug(\n `Processing getObject request for object ${objectId}. requestId = ${requestId}`,\n );\n\n // Get the guest from which the request came\n const guest = this.#getGuestForWindow(sourceWin);\n if (!guest) {\n this.#logger.warn('Rejected object request from unknown guest window');\n return false;\n }\n\n // Get the object from the guest's host\n const obj = this.getScriptingObject(objectId, { guest });\n if (!obj) {\n this.#logger.warn(\n `unknown or unauthorized object ${objectId} from guest ${guest.id}`,\n );\n this.#remoting.raiseException({\n targetWin: sourceWin,\n targetOrigin: sourceOrigin,\n requestId,\n ex: `The requested object (${objectId}) is not available`,\n });\n return false;\n }\n\n this.#remoting.respond({\n targetWin: sourceWin,\n targetOrigin: sourceOrigin,\n requestId,\n response: this.#encodeResponse(obj, guest),\n });\n\n this.#logger.debug({\n message: `Scripting Object returned`,\n requestId,\n scriptingObject: objectId,\n ...guest.getInfo(),\n });\n return true;\n };\n\n /**\n * Handles a guest event subscription request.\n *\n * This method processes a request from a guest window to subscribe to a specific event.\n * It verifies the guest window, logs the request, and invokes the subscription callback asynchronously.\n * If the guest window is unknown, the request is rejected and a warning is logged.\n * @param params - The parameters for the event subscription request.\n * @param params.sourceWin - The window object from which the request originated.\n * @param params.requestId - The unique identifier for the request.\n * @param params.body - The body of the request containing event subscription details.\n * @param params.body.eventId - The identifier of the event to subscribe to.\n * @param params.body.criteria - Optional filter criteria for the event subscription.\n * @param params.body.token - The authentication token for the request.\n * @returns Returns `false` if the guest window is unknown; otherwise, no explicit return value.\n */\n #handleGuestEventSubscribe = ({\n sourceWin,\n requestId,\n body,\n }: ListenerCallbackParams<{\n eventId: string;\n criteria?: FilterCriteria;\n token: string;\n }>) => {\n const { eventId, criteria, token } = body;\n this.#logger.debug(\n `Processing guest event subscribe request for event ${eventId}. requestId = ${requestId}`,\n );\n // Get the guest from which the request came\n const guest = this.#getGuestForWindow(sourceWin);\n if (!guest) {\n this.#logger.warn(\n 'Rejected event subscribe request from unknown guest window',\n );\n return;\n }\n // invoke the callback\n setTimeout(() => {\n try {\n this.#onGuestEventSubscribe?.({\n guestId: guest.id,\n eventId,\n criteria,\n token,\n });\n } catch (error) {\n this.#logger.warn(\n `Error in onGuestEventSubscribe callback for event ${eventId}: ${\n (error as Error).message\n }`,\n );\n }\n }, 0);\n };\n\n /**\n * Handles a guest event unsubscribe request.\n *\n * This method processes an unsubscribe request from a guest window for a specific event.\n * It verifies the source window, retrieves the corresponding guest, and invokes the\n * `#onGuestEventUnsubscribe` callback asynchronously. If the source window is not recognized,\n * the request is rejected and a warning is logged.\n * @param params - The parameters for the unsubscribe request, including:\n * - `sourceWin`: The window from which the request originated.\n * - `requestId`: The unique identifier for the request.\n * - `body`: An object containing the `eventId` and `token` for the event to unsubscribe.\n * @param params.sourceWin\n * @param params.requestId\n * @param params.body\n * @returns `false` if the guest window is unknown; otherwise, no explicit return value.\n */\n #handleGuestEventUnsubscribe = ({\n sourceWin,\n requestId,\n body,\n }: ListenerCallbackParams<{ eventId: string; token: string }>) => {\n const { eventId, token } = body;\n this.#logger.debug(\n `Processing guest event unsubscribe request for event ${eventId}. requestId = ${requestId}`,\n );\n // Get the guest from which the request came\n const guest = this.#getGuestForWindow(sourceWin);\n if (!guest) {\n this.#logger.warn(\n 'Rejected event unsubscribe request from unknown guest window',\n );\n return;\n }\n // invoke the callback\n setTimeout(() => {\n try {\n this.#onGuestEventUnsubscribe?.({\n guestId: guest.id,\n eventId,\n token,\n });\n } catch (error) {\n this.#logger.warn(\n `Error in onGuestEventUnsubscribe callback for event ${eventId}: ${\n (error as Error).message\n }`,\n );\n }\n }, 0);\n };\n\n // handles guest resize event\n #handleGuestResize = ({\n sourceWin,\n requestId,\n body,\n }: ListenerCallbackParams<GuestWindowSize>) => {\n const guest = this.#getGuestForWindow(sourceWin);\n if (!guest) {\n this.#logger.warn(\n `Received resize event from unknown guest. requestid = ${requestId}`,\n );\n return;\n }\n if (guest.domElement) {\n guest.domElement.style.height = `${body.height}px`;\n }\n this.#logger.debug(\n `Guest ${guest.id} resized to ${body.width}x${body.height}`,\n );\n };\n\n // Handles object invoke requests from the remote automation framework\n #handleObjectInvoke = ({\n sourceWin,\n sourceOrigin,\n requestId,\n body,\n }: ListenerCallbackParams<{\n objectId: Extract<keyof AppObjects, string>;\n functionName: keyof IScriptingObject;\n functionParams: unknown[];\n callerChain?: CallerInfo[];\n }>) => {\n const { objectId, callerChain } = body;\n\n // Get the guest from which the request came\n const guest = this.#getGuestForWindow(sourceWin);\n if (!guest) {\n this.#logger.warn(\n 'Rejected method invocation request from unknown guest window',\n );\n // this.#remoting.raiseException({\n // targetWin: sourceWin,\n // targetOrigin: sourceOrigin,\n // requestId,\n // ex: 'Specified window is not a known guest',\n // });\n return false;\n }\n\n this.#logger.debug(\n `Function ${objectId}.${String(body.functionName)}() called from guest \"${\n guest.id\n }\" (requestId = ${requestId})`,\n );\n\n // Get the object from the guest's host\n const obj = this.getScriptingObject(objectId, { guest });\n if (!obj) {\n this.#logger.warn(\n `Invocation of unknown or unauthorized object ${objectId} from guest ${guest.id}`,\n );\n this.#remoting.raiseException({\n targetWin: sourceWin,\n targetOrigin: sourceOrigin,\n requestId,\n ex: `The requested object (${objectId}) is not available`,\n });\n return false;\n }\n\n const guestInfo = guest.getInfo();\n let timingToken: string | undefined;\n if (this.#perfTracker.enabled) {\n const name = `ScriptingObject.API.${objectId}.${body.functionName}`;\n timingToken = this.#perfTracker.start(name, {\n appId: guestInfo.guestId,\n appUrl: guestInfo.guestUrl,\n });\n }\n // Invoke the function, which will always return a Promise\n this.#invoke({\n guest,\n obj,\n functionName: body.functionName,\n functionParams: body.functionParams,\n callerChain,\n })\n .then((val) => {\n this.#remoting.respond({\n targetWin: sourceWin,\n targetOrigin: sourceOrigin,\n requestId,\n response: this.#encodeResponse(val, guest),\n });\n this.#logger.debug({\n message: `Value returned for Scripting Object method call`,\n requestId,\n scriptingObject: objectId,\n scriptingMethod: body.functionName,\n ...guestInfo,\n });\n })\n .catch((ex) => {\n this.#remoting.raiseException({\n targetWin: sourceWin,\n targetOrigin: guest.origin,\n requestId,\n ex: ex as Error,\n });\n this.#logger.error({\n message: `Exception thrown for Scripting Object method call`,\n requestId,\n scriptingObject: objectId,\n scriptingMethod: body.functionName,\n ...guestInfo,\n });\n })\n .finally(() => {\n if (timingToken) {\n this.#perfTracker.end(timingToken, {\n appId: guestInfo.guestId,\n appUrl: guestInfo.guestUrl,\n });\n }\n });\n return true;\n };\n\n /**\n * subscribe to guest resize event\n */\n #subscribeToGuestResizeEvent = () => {\n this.#remoting.listen({\n messageType: MessageType.GuestResize,\n callback: this.#handleGuestResize,\n });\n };\n\n /**\n * start listening to the remoting messages\n */\n #connect = () => {\n this.#remoting.listen({\n messageType: MessageType.GuestReady,\n callback: this.#handleGuestReady,\n });\n this.#remoting.listen({\n messageType: MessageType.GuestReadyComplete,\n callback: this.#handleGuestReadyComplete,\n });\n this.#remoting.listen({\n messageType: MessageType.GuestClose,\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n callback: this.#handleGuestClose,\n });\n this.#remoting.listen({\n messageType: MessageType.ListObjects,\n callback: this.#handleListObjects,\n });\n this.#remoting.listen({\n messageType: MessageType.ObjectGet,\n callback: this.#handleObjectGet,\n });\n this.#remoting.listen({\n messageType: MessageType.ObjectInvoke,\n callback: this.#handleObjectInvoke,\n });\n this.#remoting.listen({\n messageType: MessageType.GuestEventSubscribe,\n callback: this.#handleGuestEventSubscribe,\n });\n this.#remoting.listen({\n messageType: MessageType.GuestEventUnsubscribe,\n callback: this.#handleGuestEventUnsubscribe,\n });\n };\n\n /**\n * check if the value is a proxy event\n * @param value\n * @returns\n */\n #isProxyEvent = (\n value: any,\n ): value is IScriptingObjectProxyEvent<AppEvents> =>\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n value instanceof ProxyEvent ||\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n typeof value?.subscribe === 'function'; // support v1 scripting objects\n\n /**\n * Register pre-rendered guest application to host\n * @param {AttachParam} param - parameters for attaching the guest\n * @returns reference to the guest object\n */\n #attachGuest = (param: AttachParam): Guest => {\n const guest = new Guest({\n ...param,\n remoting: this.#remoting,\n perfTracker: this.#guestPerfTracker,\n });\n // Register the guest with host\n guest.init();\n // Add the guest to all lookup maps\n this.#guests.set(param.guestId, guest);\n this.#guestsByWindow.set(guest.window, guest);\n this.#guestsByUrl.set(guest.url, guest);\n return guest;\n };\n\n /**\n * find the guest object by its id, window or dom element\n * @param guestIdOrWindowOrEle id, window or dom element of the guest\n * @returns guest object\n */\n #findGuest = (guestIdOrWindowOrEle: string | Window | HTMLIFrameElement) => {\n if (typeof guestIdOrWindowOrEle === 'string') {\n return this.#guests.get(guestIdOrWindowOrEle);\n }\n // O(1) lookup by window reference\n const byWindow = this.#guestsByWindow.get(guestIdOrWindowOrEle as Window);\n if (byWindow) return byWindow;\n // fallback: scan for domElement match\n return Array.from(this.#guests.values()).find(\n (value) => value.domElement === guestIdOrWindowOrEle,\n );\n };\n\n #monitorPopupGuests = () => {\n // already monitoring\n if (this.#popupGuestMonitor) return;\n this.#popupGuestMonitor = setInterval(() => {\n const guestsToRemove: Guest[] = [];\n this.#guests.forEach((guest) => {\n if (guest.openMode === OpenMode.Popup && guest.window.closed) {\n guestsToRemove.push(guest);\n }\n });\n guestsToRemove.forEach((guest) => {\n const { id } = guest;\n this.unloadGuest(id);\n const callbacks = this.#guestCloseCallbackList.get(id);\n callbacks?.forEach((callback) => {\n // eslint-disable-next-line max-nested-callbacks\n Promise.resolve(callback({ id })).catch(() => {});\n });\n });\n }, 1000);\n };\n\n #stopMonitoringPopupGuests = () => {\n if (!this.#popupGuestMonitor) return;\n const hasPopups = Array.from(this.#guests.values()).some(\n (guest) => guest.openMode === OpenMode.Popup,\n );\n if (!hasPopups) {\n clearInterval(this.#popupGuestMonitor);\n this.#popupGuestMonitor = null;\n }\n };\n\n #openPopupGuest = <\n SearchParams extends Record<string, string | number | boolean>,\n >(param: {\n guestId: string;\n url: string;\n title: string;\n searchParams: SearchParams;\n popupWindowFeatures?: WindowFeatures;\n onLoad?: (guestId: string) => void;\n onError?: (guestId: string) => void;\n }) => {\n const {\n url,\n title,\n popupWindowFeatures = {},\n searchParams,\n guestId,\n onLoad,\n onError,\n } = param;\n const {\n width = 800,\n height = 600,\n top = 100,\n left = 100,\n } = popupWindowFeatures;\n let guest = this.#getGuestForUrl(url);\n if (guest) {\n if (!guest.window.closed) {\n if (isTrustedDomain(url)) {\n // Trusted guests keep opener intact, so the browser can resolve\n // the named window and bring it to the foreground without reload.\n window.open('', title);\n } else {\n // Untrusted guests had opener nulled — window.open('', name)\n // can't resolve the name, so fall back to the stored WindowProxy.\n guest.window.focus();\n }\n }\n } else {\n // construct window features as comma separated string\n const windowFeatures = Object.entries({ width, height, top, left })\n .filter(([, v]) => v)\n .map(([k, v]) => `${k}=${v}`)\n .join(',');\n // open new guest popup window\n const guestWindow = window.open(url, title, `popup, ${windowFeatures}`);\n if (!guestWindow) {\n // notify load failure to the caller\n setTimeout(() => {\n try {\n onError?.(guestId);\n } catch (error) {\n this.#logger.debug(\n `Error occurred in onError for guest with id '${guestId}': ${\n (error as Error).message\n }`,\n );\n }\n }, 0);\n throw new Error('Failed to open guest application in popup window');\n } else {\n // notify load complete to the caller\n setTimeout(() => {\n try {\n onLoad?.(guestId);\n } catch (error) {\n this.#logger.debug(\n `Error occurred in onLoad for guest with id '${guestId}': ${\n (error as Error).message\n }`,\n );\n }\n }, 0);\n }\n // Null opener for untrusted (non-ICE) guests to prevent access to\n // the host window. Trusted ICE domain guests keep opener so the\n // host can refocus the popup later via window.open.\n if (!isTrustedDomain(url)) {\n guestWindow.opener = null;\n }\n guest = this.#attachGuest({\n guestId,\n window: guestWindow,\n title,\n url,\n searchParams,\n openMode: OpenMode.Popup,\n });\n // start polling for popup close only when popups exist\n this.#monitorPopupGuests();\n }\n return guest;\n };\n\n #openEmbedGuest = <\n SearchParams extends Record<string, string | number | boolean>,\n >(param: {\n guestId: string;\n url: string;\n title: string;\n searchParams: SearchParams;\n targetElement: HTMLElement;\n onLoad?: (guestId: string) => void;\n onError?: (guestId: string) => void;\n options?: GuestOptions;\n }) => {\n const {\n url,\n title,\n targetElement,\n searchParams,\n guestId,\n onLoad,\n onError,\n options = {} as GuestOptions,\n } = param;\n // create the iframe\n const targetElementDocument = targetElement.ownerDocument ?? document;\n const {\n fitToContent = false,\n disableSandbox = false,\n sandboxValues = [],\n customSandboxValues = [],\n style = '',\n permissionPolicy = '',\n } = options;\n if (!title) throw new Error('title is required');\n if (fitToContent) this.#subscribeToGuestResizeEvent();\n // create guest frame\n const frame = targetElementDocument.createElement('iframe');\n frame.setAttribute('id', guestId);\n // handle frame load and error events\n const onFrameLoad = () => {\n // notify load complete to the caller\n setTimeout(() => {\n try {\n onLoad?.(guestId);\n } catch (error) {\n this.#logger.debug(\n `Error occurred in onLoad for guest with id '${guestId}': ${\n (error as Error).message\n }`,\n );\n }\n }, 0);\n this.#logger.debug(`frame loaded for guest with id '${guestId}'`);\n frame.removeEventListener('load', onFrameLoad);\n };\n const onFrameLoadFailure = () => {\n // notify load failure to the caller\n setTimeout(() => {\n try {\n onError?.(guestId);\n } catch (error) {\n this.#logger.debug(\n `Error occurred in onError for guest with id '${guestId}': ${\n (error as Error).message\n }`,\n );\n }\n }, 0);\n this.#logger.error(`frame load failed for guest with id '${guestId}'`);\n frame.removeEventListener('error', onFrameLoadFailure);\n };\n frame.addEventListener('load', onFrameLoad);\n frame.addEventListener('error', onFrameLoadFailure);\n frame.setAttribute(\n 'style',\n `min-width: 100%; height: 100%; border: 0px; ${style}`,\n );\n if (!disableSandbox) {\n frame.setAttribute(\n 'sandbox',\n customSandboxValues.length > 0\n ? customSandboxValues.join(' ')\n : [...SANDBOX_DEFAULT, ...sandboxValues].join(' '),\n );\n }\n frame.setAttribute('title', title);\n frame.setAttribute('src', url);\n if (permissionPolicy) frame.setAttribute('allow', permissionPolicy);\n targetElement.appendChild(frame);\n // Find the window object and create the guest\n const guestFrameEle = targetElementDocument.getElementById(\n guestId,\n ) as HTMLIFrameElement;\n return this.#attachGuest({\n guestId,\n domElement: guestFrameEle,\n window: guestFrameEle.contentWindow as Window,\n title,\n url,\n searchParams,\n openMode: OpenMode.Embed,\n });\n };\n\n #getGuestUrl = <Params extends Record<string, string | number | boolean>>(\n url: string,\n params: Params,\n ) => {\n let querystring = '';\n Object.keys(params).forEach((queryParam) => {\n querystring += `${\n (querystring.length ? '&' : '') + encodeURIComponent(queryParam)\n }=${encodeURIComponent(params[queryParam])}`;\n });\n\n return (\n url +\n (!querystring ? '' : (url.indexOf('?') >= 0 ? '&' : '?') + querystring)\n );\n };\n\n /**\n * registers scripting object to the host\n * @param {ValueOf<AppObjects>} so scripting object to be registered\n * @param {AddScriptingObjectParams} params params to add scripting object\n */\n addScriptingObject = <SO extends ValueOf<AppObjects>>(\n so: SO,\n params?: AddScriptingObjectParams,\n ) => {\n // if scripting object is proxy then clone it\n if (isScriptingObjectProxy(so)) {\n const clonedSo = this.cloneScriptingObject(so);\n this.#soManager.addScriptingObject(clonedSo, params);\n } else {\n // if scripting object is not a proxy object, add it directly\n this.#soManager.addScriptingObject(so, params);\n }\n };\n\n /**\n * Clone parent host's scripting object for exposing to grand children\n * @param proxy - reference to the scripting object obtained through getObject method\n * @param guest - reference to the ssf guest\n * @returns cloned version of the scripting object\n */\n cloneScriptingObject = <ObjectId extends Extract<keyof AppObjects, string>>(\n proxy: IScriptingObjectProxy,\n ): AppObjects[ObjectId] => {\n if (!proxy) throw new Error('proxy is required');\n // Create a new, base ScriptingObject with V2 properties\n const so = new ScriptingObject(proxy.id, proxy.objectType);\n type UnsubscribeFn = () => void;\n // Store the tokens for unsubscription\n let unsubscribers: Array<UnsubscribeFn> = [];\n\n // Copy the functions and events over\n // let propName: keyof typeof proxy;\n Object.keys(proxy).forEach((propName) => {\n const propValue = proxy[propName as keyof IScriptingObjectProxy];\n if (this.#isProxyEvent(propValue)) {\n // v1 or v2 object event\n const event = new Event<AppEvents>({\n name: propValue.name || propName,\n objectId: so.id,\n });\n // Create the event on the object\n Object.defineProperty(so, propName, {\n value: event,\n enumerable: true,\n });\n\n // Subscribe to the event and pass the callback down\n if ((propValue as any) instanceof ProxyEvent) {\n // proxy was obtained from v2 guest\n const listener = ({\n eventParams,\n eventOptions,\n }: {\n eventParams: any;\n eventOptions?: any;\n }) =>\n this.dispatchEvent({\n event,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n eventParams,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n eventOptions,\n });\n\n const token = (propValue as unknown as ProxyEvent).subscribe(\n listener,\n );\n unsubscribers.push(() => {\n (propValue as unknown as ProxyEvent).unsubscribe(token);\n });\n } else {\n // proxy was obtained from v1 guest\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment\n const token = (propValue as any).subscribe?.(\n (obj: ScriptingObject, params: any, options: any) =>\n this.dispatchEvent({\n event,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n eventParams: params,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n eventOptions: options,\n }),\n );\n unsubscribers.push(() => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n (propValue as any).unsubscribe?.(token);\n });\n }\n } else if (isFunction(propValue)) {\n // Create a function that proxies the call to the proxy\n Object.defineProperty(so, propName, {\n value: async (...args: unknown[]) => {\n // Forward caller chain: read callContext set by #invoke on this\n // cloned function, then propagate it to the parent proxy so the\n // guest's #invoke includes it in the ObjectInvoke message.\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment\n const callerCtx = (so as any)[propName]?.callContext;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n if (callerCtx?.guest) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const existingChain = (callerCtx.callChain ?? []) as CallerInfo[];\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const guestId = (callerCtx.guest as GuestContext).id;\n const meta = this.#guestMetadata.get(guestId);\n const callerEntry: Record<string, unknown> = { id: guestId };\n if (meta) callerEntry.metadata = meta;\n Object.defineProperty(propValue, 'callContext', {\n value: {\n callChain: [...existingChain, callerEntry],\n },\n configurable: true,\n enumerable: true,\n writable: true,\n });\n }\n const retVal = await propValue(...args);\n return isScriptingObjectProxy(retVal)\n ? this.cloneScriptingObject(retVal)\n : retVal;\n },\n enumerable: true,\n });\n\n // Override the dispose function\n if (propName === 'dispose') {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n const defaultImpl = so.dispose;\n Object.defineProperty(so, propName, {\n value: () => {\n // Dispose of the object in the proxy tier\n // eslint-disable-next-line no-underscore-dangle\n so._dispose();\n return defaultImpl.apply(so);\n },\n enumerable: true,\n });\n }\n }\n });\n\n // Override the dispose function// Add a destroy method to clean up the proxy by unsubscribing to the\n // proxied object's events and unpublishing the object\n // eslint-disable-next-line no-underscore-dangle\n so._dispose = () => {\n unsubscribers.forEach((unsub) => {\n unsub?.();\n });\n unsubscribers = [];\n };\n\n return so as unknown as AppObjects[ObjectId];\n };\n\n /**\n * dispose the resources used by the host application\n */\n close = () => {\n if (this.#popupGuestMonitor) {\n clearInterval(this.#popupGuestMonitor);\n this.#popupGuestMonitor = null;\n }\n this.#closeAllPopupGuests();\n this.#guestMetadata.clear();\n this.#remoting.close();\n window.removeEventListener('beforeunload', this.#closeAllPopupGuests);\n this.#logger.debug(\n `host is closed. hostId: ${this.hostId}, correlationId: ${\n this.#correlationId\n }`,\n );\n };\n\n /**\n * dispatch event to guest application(s)\n * @param {EventDetail} params details of the event to be dispatched\n * @returns promise that resolves to an array with result from each guest application\n */\n dispatchEvent = async <\n EventId extends Extract<keyof AppEvents, string>,\n Params extends Parameters<AppEvents[EventId]>[0]['eventParams'],\n Options extends EventOptions,\n >(\n params: DispatchEventParam<EventId, Params, Options>,\n ) => {\n const {\n event: { id, name },\n eventParams,\n eventOptions = {} as Options,\n } = params;\n const {\n eventHandler = null,\n timeout = null,\n window: targetWindow = null,\n guestId,\n } = eventOptions;\n // Get the scripting object\n const objectId = id.split('.')[0] as Extract<keyof AppObjects, string>;\n // get the guest object to which the event should be dispatched to\n const guestIdorWnd = guestId || targetWindow;\n const targetGuest = guestIdorWnd ? this.#findGuest(guestIdorWnd) : null;\n // get scripting object\n const scriptingObject = targetGuest\n ? this.getScriptingObject(objectId, { guest: targetGuest })\n : this.getScriptingObject(objectId);\n if (!scriptingObject) {\n this.#logger.warn(\n `Attempt to dispatch event ${name} on unknown object ${objectId}`,\n );\n return Promise.resolve([]);\n }\n\n const eventObj: EventObject = {\n // eslint-disable-next-line no-underscore-dangle\n object: scriptingObject._toJSON(),\n eventName: name,\n eventParams,\n eventHandler,\n eventOptions: {\n allowsFeedback: false,\n },\n };\n\n if (timeout && !Number.isNaN(timeout)) {\n eventObj.eventOptions = {\n allowsFeedback: true,\n timeout: Number(timeout),\n };\n }\n\n // Invoke the event handler in target or all guests\n const guestPromises: Array<Promise<unknown>> = [];\n let eventTimingToken: string | undefined;\n\n const dispatchToGuest = (guest: Guest) => {\n const guestInfo = guest.getInfo();\n if (timeout && guest?.capabilities?.eventFeedback) {\n guestPromises.push(guest.dispatchEvent(eventObj, timeout));\n if (!eventTimingToken && this.#perfTracker.enabled) {\n eventTimingToken = this.#perfTracker.start(\n `ScriptingObject.Event.${scriptingObject.id}.${name}`,\n { appId: this.hostId, appUrl: window.location.href },\n );\n }\n this.#logger.debug({\n message: 'Event dispatched and awaiting feedback',\n scriptingEventId: id,\n ...guestInfo,\n });\n } else {\n guest.send({\n messageType: MessageType.ObjectEvent,\n messageBody: eventObj,\n });\n this.#logger.debug({\n message: 'Event dispatched',\n scriptingEventId: id,\n ...guestInfo,\n });\n }\n };\n\n if (targetGuest) {\n // targeted dispatch — skip iterating all guests\n dispatchToGuest(targetGuest);\n } else {\n this.#guests.forEach(dispatchToGuest);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return Promise.all(guestPromises)\n .then((values) => {\n this.#logger.debug({\n message: 'Event feedback received',\n scriptingEventId: id,\n });\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return flatten(values);\n })\n .catch((ex: Error) => {\n this.#logger.error({\n message: 'Error processing event',\n eventId: id,\n exception: ex,\n });\n throw ex;\n })\n .finally(() => {\n if (eventTimingToken) {\n this.#perfTracker.end(eventTimingToken, {\n appId: this.hostId,\n appUrl: window.location.href,\n });\n }\n });\n };\n\n /**\n * get reference to all guest applications\n * @returns list of guest application references\n */\n getGuests = (): Array<Guest> => Array.from(this.#guests.values());\n\n /**\n * get the scripting object by id\n * @param objectId - id of the scripting object\n * @param params\n * @returns scripting object\n */\n getScriptingObject = <Id extends Extract<keyof AppObjects, string>>(\n objectId: Id,\n params?: GetObjectParams,\n ): AppObjects[Id] | null =>\n this.#soManager.getObject(objectId, params?.guest);\n\n /**\n * loads guest application inside sandboxed iframe\n * @param {LoadGuestParam} param - parameters for loading the guest application\n * @returns reference to the guest object\n */\n loadGuest = <SearchParams extends Record<string, string | number | boolean>>(\n param: LoadGuestParam<SearchParams>,\n ): Guest => {\n const {\n id: guestId,\n url,\n targetElement,\n title,\n searchParams = {} as SearchParams,\n onLoad,\n onError,\n options = {} as GuestOptions,\n metadata,\n } = param;\n if (!guestId) throw new Error('id for guest application is required');\n // Generate a unique instance ID when multiple instances of the same app are loaded\n let instanceId = guestId;\n if (this.#guests.has(instanceId)) {\n let counter = 1;\n while (this.#guests.has(`${guestId}-${counter}`)) {\n counter += 1;\n }\n instanceId = `${guestId}-${counter}`;\n }\n const { openMode = OpenMode.Embed, popupWindowFeatures = {} } = options;\n\n const srcUrl = this.#getGuestUrl(url, searchParams);\n let guest: Guest | null = null;\n\n this.#perfTracker.start('SSF.Guest.Load', {\n appId: instanceId,\n appUrl: srcUrl,\n });\n if (openMode === OpenMode.Popup) {\n guest = this.#openPopupGuest({\n guestId: instanceId,\n url: srcUrl,\n title,\n searchParams,\n popupWindowFeatures,\n onLoad,\n onError,\n });\n } else if (openMode === OpenMode.Embed) {\n guest = this.#openEmbedGuest({\n guestId: instanceId,\n url: srcUrl,\n title,\n targetElement,\n searchParams,\n onLoad,\n onError,\n options,\n });\n } else {\n throw new Error(`Invalid openMode: ${openMode as string}`);\n }\n\n if (metadata) this.#guestMetadata.set(instanceId, metadata);\n\n this.#logger.audit({\n message: 'Guest loaded',\n ...guest.getInfo(),\n });\n return guest;\n };\n\n /**\n * loads guest application inside sandboxed iframe with different params\n * @param {LoadGuestsParam} param - parameters for loading the guest application\n */\n loadGuests = <SearchParams extends Record<string, string | number | boolean>>(\n param: LoadGuestsParam<SearchParams>,\n ) => {\n const {\n id,\n url,\n targetElement,\n title,\n searchParamsList = [] as SearchParams[],\n options = {} as GuestOptions,\n } = param;\n // Render the plugins into sandboxed iframe elements\n searchParamsList.forEach((searchParams, index) => {\n this.loadGuest({\n id: `${id}-${index}`,\n url,\n title,\n targetElement,\n searchParams,\n options,\n });\n }, this);\n };\n\n /**\n * removes all scripting objects from host\n * @param guestId unique id of the guest application\n */\n removeAllScriptingObjects = (guestId?: string) => {\n this.#soManager.removeAllScriptingObjects(guestId);\n };\n\n /**\n * removes scripting object from the host\n * @param objectId unique id of the scripting object\n * @param guestId unique id of the guest application\n */\n removeScriptingObject = (\n objectId: Extract<keyof AppObjects, string>,\n guestId?: string,\n ) => {\n this.#soManager.removeScriptingObject(objectId, guestId);\n };\n\n /**\n * set the log level for the host application\n * @param level - log level\n */\n setLogLevel = (level: LogLevels) => {\n // Set the logging level at the host\n this.#logger.setLogLevel(level);\n // Notify all guests of the change\n this.#guests.forEach(this.#dispatchConfigEvent);\n this.#logger.debug('Dispatched config events to all guests');\n };\n\n /**\n * unloads guest application from host\n * @param guestIdOrWindowOrEle unique id of the guest application or window object or dom element of the guest application\n * @throws Error if guestId or Window reference is invalid\n */\n unloadGuest = (guestIdOrWindowOrEle: string | Window | HTMLIFrameElement) => {\n // Find the guest object\n const guest = this.#findGuest(guestIdOrWindowOrEle);\n if (guest) {\n // dispose the guest\n guest.dispose();\n // Remove from all lookup maps\n this.#guestsByWindow.delete(guest.window);\n this.#guestsByUrl.delete(guest.url);\n this.#guestMetadata.delete(guest.id);\n this.#guests.delete(guest.id);\n this.#logger.audit({\n message: `Guest is removed from host`,\n ...guest.getInfo(),\n });\n // stop polling if no popup guests remain\n this.#stopMonitoringPopupGuests();\n }\n };\n\n /**\n * monitors guest window close action and executes the callback from host.\n * @param callback host callback method\n * @param id unique id of the guest application\n * @param param\n */\n onGuestClose = (param: GuestCloseParam) => {\n const { id, guestCloseCallback } = param;\n const callbacks = this.#guestCloseCallbackList.get(id) || [];\n callbacks.push(guestCloseCallback);\n this.#guestCloseCallbackList.set(id, callbacks);\n };\n}\n"],"names":["root","factory","__webpack_require__","exports","definition","key","obj","prop","Event","param","name","objectId","ProxyEvent","#eventSrc","eventSrc","callback","token","isEvent","value","getEventId","eventName","FUNCTION","isPublicFunction","fnName","ScriptingObject","#id","#objectType","objectType","functions","events","property","MessageType","MessageType2","OpenMode","IFrameSandboxValues","getOrigin","url","origin","flatten","source","v","isFunction","TRUSTED_DOMAIN_SUFFIXES","TRUSTED_HOSTNAMES","isTrustedDomain","hostname","suffix","Guest","#remoting","#perfTracker","option","guestId","domElement","title","window","searchParams","openMode","remoting","perfTracker","resolve","handShakeCount","handShakeRetries","handShakeHandle","onAck","event","timeout","timingToken","getRandomValues","rnds8","rng","byteToHex","i","unsafeStringify","arr","offset","stringify","uuid","validate","v4","options","buf","rnds","MESSAGE_SOURCE","RESPONSE_MESSAGE_TYPE","EXCEPTION_MESSAGE_TYPE","createMessage","messageType","messageBody","requestId","onewayMsg","sendMessage","targetWin","targetOrigin","msg","Remoting","#correlationId","#logger","#listeners","#invocations","#timeoutMonitorHandle","#initializedWindow","#allowedSenders","logger","correlationId","#evaluateTimeouts","ts","canceledItems","nextCancelTime","eventData","cancelTime","delay","#scheduleTimeoutCheck","delayMs","#stopResponseMonitor","#popInvocation","e","#processResponse","message","#processException","#receive","sourceWin","sourceOrigin","callbacks","#processMessage","senderOrigin","window2","win","responseTimeoutMs","reject","items","index","response","ex","MODULE_OBJECT","SecurityContext","SecurityContext2","ScriptingObjectManager","#normalizeId","id","#scriptingObjects","#guestScriptingObjects","#addGuestScriptingObject","params","so","guestSOs","#disposeSO","#getGuestScriptingObject","mSOs","mSO","SOs","#removeGuestScriptingObject","sosInfo","moduleSOs","soInfo","guest","objects","ScriptingObjectProxy","isScriptingObjectProxy","PerformanceTracker","#analyticsObj","#enabled","#samplingRatio","#samplingConfigured","#dedupWindowMs","#lastRecorded","#onError","#LOW_FREQUENCY","lowFreq","#shouldTrack","#reportError","now","last","SANDBOX_DEFAULT","SSFHost","#guests","#guestsByWindow","#guestsByUrl","#guestCloseCallbackList","#soManager","#readyStateCallback","#popupGuestMonitor","#onGuestEventSubscribe","#onGuestEventUnsubscribe","#guestMetadata","#guestPerfTracker","hostId","perfOpts","#connect","#closeAllPopupGuests","#sendBAEvent","data","baEvent","#getGuestForWindow","guestWindow","#getGuestForUrl","#isScriptingObject","#encodeResponse","val","#encodeException","#dispatchConfigEvent","#invoke","functionName","functionParams","callerChain","func","#handleGuestReadyComplete","guestInfo","#handleGuestReady","body","#handleGuestClose","#findGuest","#handleListObjects","#handleObjectGet","#handleGuestEventSubscribe","eventId","criteria","error","#handleGuestEventUnsubscribe","#handleGuestResize","#handleObjectInvoke","#subscribeToGuestResizeEvent","#isProxyEvent","#attachGuest","guestIdOrWindowOrEle","byWindow","#monitorPopupGuests","guestsToRemove","#stopMonitoringPopupGuests","#openPopupGuest","popupWindowFeatures","onLoad","onError","width","height","top","left","windowFeatures","k","#openEmbedGuest","targetElement","targetElementDocument","fitToContent","disableSandbox","sandboxValues","customSandboxValues","style","permissionPolicy","frame","onFrameLoad","onFrameLoadFailure","guestFrameEle","#getGuestUrl","querystring","queryParam","clonedSo","proxy","unsubscribers","propName","propValue","listener","eventParams","eventOptions","args","callerCtx","existingChain","meta","callerEntry","retVal","defaultImpl","unsub","eventHandler","targetWindow","guestIdorWnd","targetGuest","scriptingObject","eventObj","guestPromises","eventTimingToken","dispatchToGuest","values","metadata","instanceId","counter","srcUrl","searchParamsList","level","guestCloseCallback"],"sourceRoot":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!doctype html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Popup Focus E2E Test</title><script src="https://cdn.tailwindcss.com?plugins=forms"></script><script src="https://cdn.mortgagetech.q1.ice.com/pui-diagnostics@3"></script><script defer="defer" src="js/emuiSsfHost.
|
|
1
|
+
<!doctype html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Popup Focus E2E Test</title><script src="https://cdn.tailwindcss.com?plugins=forms"></script><script src="https://cdn.mortgagetech.q1.ice.com/pui-diagnostics@3"></script><script defer="defer" src="js/emuiSsfHost.5bb7139d7e86c74f0b6d.js"></script></head><body class="bg-gray-50"><header class="bg-purple-600 text-white px-4 py-3 flex items-center justify-between"><h1 class="text-lg font-semibold">Popup Focus E2E Test</h1><a href="./index.html" class="text-purple-200 hover:text-white text-sm">← Back to main</a></header><main class="mx-auto max-w-5xl px-4 py-4"><div class="grid grid-cols-2 gap-4 mb-4"><div class="bg-purple-50 border border-purple-200 rounded-md p-3"><h2 class="text-sm font-bold text-purple-900 mb-2">Behavior Under Test</h2><ul class="text-xs text-purple-800 space-y-1 list-disc list-inside"><li><strong>Trusted domains</strong> (.ice.com, .elliemae.com, .ellielabs.com, localhost): <code>window.opener</code> is kept intact. Re-opening uses <code>window.open('', name)</code> to bring the popup to front.</li><li><strong>Untrusted domains</strong> (everything else): <code>window.opener = null</code> is set for security. Re-opening falls back to <code>guest.window.focus()</code>.</li><li>The host tracks popup windows and detects closure via a periodic monitor.</li></ul></div><div class="bg-green-50 border border-green-200 rounded-md p-3"><h2 class="text-sm font-bold text-green-900 mb-2">Test Steps</h2><ol class="text-xs text-green-800 space-y-1.5 list-decimal list-inside"><li>Wait for <code>"Popup Focus Host ready"</code> in the Event Log.</li><li><strong>Trusted popup test:</strong> Click "Open Title Service" → popup opens. Click "Re-open Title Service" → the <em>existing</em> popup should come to the foreground (no new window).</li><li><strong>Second trusted popup:</strong> Click "Open Credit Service" → second popup opens. Click "Re-open Credit" → same foreground behavior.</li><li><strong>Untrusted popup test:</strong> Click "Open Third-Party" → popup opens to <code>example.com</code>. Click "Re-open Third-Party" → focus may or may not work (opener was nulled). Observe the behavior.</li><li>Verify the Guest Status panel shows the open/closed state of each popup.</li><li>Manually close a popup window, then check Guest Status updates to "closed".</li></ol></div></div><div class="bg-amber-50 border border-amber-200 rounded-md p-3 mb-4"><h2 class="text-sm font-bold text-amber-900 mb-2">Expected Behavior</h2><div class="grid grid-cols-3 gap-3 text-xs"><div><h3 class="font-semibold text-amber-800 mb-1">Title / Credit Service (Trusted)</h3><ul class="text-amber-900 list-disc list-inside space-y-0.5"><li>"Open" → new popup window appears</li><li>"Re-open" → existing popup comes to front, <strong>no new window</strong></li><li>Guest Status shows <span class="text-green-600 font-semibold">open</span></li><li>Embedded Pricing Service renders normally</li></ul></div><div><h3 class="font-semibold text-amber-800 mb-1">Third-Party (Untrusted)</h3><ul class="text-amber-900 list-disc list-inside space-y-0.5"><li>"Open" → popup opens to <code>example.com</code></li><li>"Re-open" → <code>focus()</code> is called on stored reference (browser may or may not honor it)</li><li><code>opener</code> is <code>null</code> inside the popup</li></ul></div><div><h3 class="font-semibold text-amber-800 mb-1">Popup Closure</h3><ul class="text-amber-900 list-disc list-inside space-y-0.5"><li>Close a popup manually (X button)</li><li>Guest Status updates to <span class="text-red-500 font-semibold">closed</span> within 2 seconds</li><li>Re-opening a closed popup should open a new window</li></ul></div></div></div><div class="grid grid-cols-2 gap-4 mb-4"><div class="bg-white rounded-lg shadow p-4"><h2 class="text-sm font-semibold text-gray-700 mb-3">Popup Actions</h2><div class="flex flex-col gap-2"><p class="text-xs text-gray-400 font-medium">Trusted (localhost — opener preserved)</p><button data-testid="btn-open-title-popup" id="btnOpenTitle" class="rounded bg-purple-600 px-4 py-2 text-sm text-white hover:bg-purple-700">Open Title Service (Popup)</button> <button data-testid="btn-reopen-title-popup" id="btnReopenTitle" class="rounded bg-purple-500 px-4 py-2 text-sm text-white hover:bg-purple-600">Re-open Title Service (should focus existing)</button> <button data-testid="btn-open-credit-popup" id="btnOpenCredit" class="rounded bg-indigo-600 px-4 py-2 text-sm text-white hover:bg-indigo-700">Open Credit Service (Popup)</button> <button data-testid="btn-reopen-credit-popup" id="btnReopenCredit" class="rounded bg-indigo-500 px-4 py-2 text-sm text-white hover:bg-indigo-600">Re-open Credit Service (should focus existing)</button><hr class="my-2 border-gray-300"/><p class="text-xs text-gray-400 font-medium">Untrusted (opener nulled)</p><button data-testid="btn-open-thirdparty-popup" id="btnOpenThirdParty" class="rounded bg-red-600 px-4 py-2 text-sm text-white hover:bg-red-700">Open Third-Party (Popup) — untrusted</button> <button data-testid="btn-reopen-thirdparty-popup" id="btnReopenThirdParty" class="rounded bg-red-500 px-4 py-2 text-sm text-white hover:bg-red-600">Re-open Third-Party (focus test — opener nulled)</button></div></div><div class="bg-white rounded-lg shadow p-4"><h2 class="text-sm font-semibold text-gray-700 mb-3">Guest Status</h2><div data-testid="popup-guest-list" id="guestList" class="text-xs space-y-1 min-h-[100px]"><p class="text-gray-400">No popup guests loaded yet</p></div></div></div><div class="bg-white rounded-lg shadow p-4 mb-4"><h2 class="text-sm font-semibold text-gray-700 mb-2">Event Log</h2><div data-testid="popup-event-log" id="eventLog" class="text-xs bg-gray-100 rounded p-2 min-h-[100px] max-h-[250px] overflow-y-auto"></div></div><div class="mb-4"><h2 class="text-sm font-semibold text-gray-700 mb-2">Embedded Guest (for comparison)</h2><div data-testid="embedded-container" id="embedded-container" class="border-2 border-dashed border-purple-300 rounded-lg min-h-[150px]"></div></div><div class="bg-gray-100 border border-gray-300 rounded-md p-3"><h2 class="text-sm font-bold text-gray-800 mb-2">Verification Checklist</h2><div class="grid grid-cols-2 gap-2 text-xs"><label class="flex items-start gap-2"><input type="checkbox" class="mt-0.5"/> <span><strong>TC-POP-01:</strong> Host initializes, embedded Pricing Service guest loads without error</span></label> <label class="flex items-start gap-2"><input type="checkbox" class="mt-0.5"/> <span><strong>TC-POP-02:</strong> "Open Title Service" opens a new popup window</span></label> <label class="flex items-start gap-2"><input type="checkbox" class="mt-0.5"/> <span><strong>TC-POP-03:</strong> "Re-open Title Service" brings the existing popup to front — <strong>no new window or about:blank tab</strong></span></label> <label class="flex items-start gap-2"><input type="checkbox" class="mt-0.5"/> <span><strong>TC-POP-04:</strong> "Open Credit Service" opens a second popup (both coexist)</span></label> <label class="flex items-start gap-2"><input type="checkbox" class="mt-0.5"/> <span><strong>TC-POP-05:</strong> "Re-open Credit Service" brings credit popup to front</span></label> <label class="flex items-start gap-2"><input type="checkbox" class="mt-0.5"/> <span><strong>TC-POP-06:</strong> Guest Status shows each popup as <span class="text-green-600 font-semibold">open</span></span></label> <label class="flex items-start gap-2"><input type="checkbox" class="mt-0.5"/> <span><strong>TC-POP-07:</strong> Manually close a popup → Guest Status updates to <span class="text-red-500 font-semibold">closed</span> within ~2s</span></label> <label class="flex items-start gap-2"><input type="checkbox" class="mt-0.5"/> <span><strong>TC-POP-08:</strong> Re-opening a closed popup opens a new window (not just focus)</span></label> <label class="flex items-start gap-2"><input type="checkbox" class="mt-0.5"/> <span><strong>TC-POP-09:</strong> "Open Third-Party" opens <code>example.com</code> popup</span></label> <label class="flex items-start gap-2"><input type="checkbox" class="mt-0.5"/> <span><strong>TC-POP-10:</strong> "Re-open Third-Party" attempts <code>focus()</code> (may open about:blank — expected for untrusted, opener was nulled)</span></label> <label class="flex items-start gap-2"><input type="checkbox" class="mt-0.5"/> <span><strong>TC-POP-11:</strong> No console errors during trusted popup operations</span></label></div></div></main><script src="./popup-focus-host.js" type="module"></script></body></html>
|
package/dist/public/utils.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
let n=null,s=null;const a=()=>{try{new PerformanceObserver(o=>{for(const e of o.getEntries())switch(e.entryType){case"measure":{const r=e.detail??{},i={name:e.name,duration:e.duration,startTime:new Date(performance.timeOrigin+e.startTime).toISOString(),...r};break}default:break}}).observe({type:"measure",buffered:!0})}catch{}},c=()=>{const{logger:t,http:o,webvitals:e,logUnhandledErrors:r,Console:i}=window.emuiDiagnostics||{};t&&(window.logger=t({transport:o("https://int.api.ellielabs.com/diagnostics/v2/logging"),index:"ssfhost",team:"ui platform",appName:"SSF Host Demo"}),e(window.logger),r(window.logger),window.logger.info("SSF Host launched"))};export const getHost=t=>{if(s)return s;c(),a();const o={logger:window.logger,readyStateCallback:e=>{},analyticsObj:t,onGuestEventSubscribe:e=>{},onGuestEventUnSubscribe:e=>{}};return s=ice?.host?.SSFHost?new ice.host.SSFHost("IMTProduct",o):null,s},getGuestBaseUrl=async()=>(n||(n=await(await fetch("./app.config.json")).json()),{...n?.options,...n[n.activeEnv]?.options}?.guestUrl);
|
|
1
|
+
let n=null,s=null;const a=()=>{try{new PerformanceObserver(o=>{for(const e of o.getEntries())switch(e.entryType){case"measure":{const r=e.detail??{},i={name:e.name,duration:e.duration,startTime:new Date(performance.timeOrigin+e.startTime).toISOString(),...r};break}default:break}}).observe({type:"measure",buffered:!0})}catch{}},c=()=>{const{logger:t,http:o,webvitals:e,logUnhandledErrors:r,Console:i}=window.emuiDiagnostics||{};t&&(window.logger=t({transport:o("https://int.api.ellielabs.com/diagnostics/v2/logging"),index:"ssfhost",team:"ui platform",appName:"SSF Host Demo"}),e(window.logger),r(window.logger),window.logger.info("SSF Host launched"))};export const getHost=t=>{if(s)return s;c(),a();const o={logger:window.logger,readyStateCallback:e=>{},analyticsObj:t,measurePerformance:!0,onGuestEventSubscribe:e=>{},onGuestEventUnSubscribe:e=>{}};return s=ice?.host?.SSFHost?new ice.host.SSFHost("IMTProduct",o):null,s},getGuestBaseUrl=async()=>(n||(n=await(await fetch("./app.config.json")).json()),{...n?.options,...n[n.activeEnv]?.options}?.guestUrl);
|
|
2
2
|
|
|
3
3
|
//# sourceMappingURL=utils.js.map
|
package/dist/public/utils.js.br
CHANGED
|
Binary file
|
package/dist/public/utils.js.gz
CHANGED
|
Binary file
|
package/dist/public/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["webpack://ice.host/utils.js"],"sourcesContent":["let appConfig = null;\nlet host = null;\n\nconst monitorPerformance = () => {\n try {\n const po = new PerformanceObserver((list) => {\n // eslint-disable-next-line no-restricted-syntax\n for (const entry of list.getEntries()) {\n switch (entry.entryType) {\n case 'measure': {\n const detail = entry.detail ?? {};\n const data = {\n name: entry.name,\n duration: entry.duration,\n startTime: new Date(\n performance.timeOrigin + entry.startTime,\n ).toISOString(),\n ...detail,\n };\n console.log('timing', data);\n break;\n }\n default:\n break;\n }\n }\n });\n po.observe({ type: 'measure', buffered: true });\n } catch (e) {}\n};\n\nconst createLogger = () => {\n const { logger, http, webvitals, logUnhandledErrors, Console } =\n window.emuiDiagnostics || {};\n if (logger) {\n window.logger = logger({\n transport: http('https://int.api.ellielabs.com/diagnostics/v2/logging'),\n // transport: Console(),\n index: 'ssfhost',\n team: 'ui platform',\n appName: 'SSF Host Demo',\n });\n\n webvitals(window.logger);\n logUnhandledErrors(window.logger);\n window.logger.info('SSF Host launched');\n } else console.warn('ui logger missing'); // eslint-disable-line no-console\n};\n\nexport const getHost = (analyticsObj) => {\n if (host) return host;\n createLogger();\n monitorPerformance();\n const hostOptions = {\n logger: window.logger,\n readyStateCallback: (guest) => {},\n analyticsObj,\n onGuestEventSubscribe: (options) => {\n console.log('Guest Event Subscribe:', options);\n },\n onGuestEventUnSubscribe: (options) => {\n console.log('Guest Event UnSubscribe:', options);\n },\n };\n host = ice?.host?.SSFHost\n ? new ice.host.SSFHost('IMTProduct', hostOptions)\n : null;\n // debug loglevel\n // host.setLogLevel(10);\n return host;\n};\n\nexport const getGuestBaseUrl = async () => {\n if (!appConfig) {\n const response = await fetch('./app.config.json');\n appConfig = await response.json();\n }\n const activeEnvConfig = {\n ...appConfig?.options,\n ...appConfig[appConfig.activeEnv]?.options,\n };\n return activeEnvConfig?.guestUrl;\n};\n"],"mappings":"AAAA,IAAIA,EAAY,KACZC,EAAO,KAEX,MAAMC,EAAqB,IAAM,CAC/B,GAAI,CACS,IAAI,oBAAqBC,GAAS,CAE3C,UAAWC,KAASD,EAAK,WAAW,EAClC,OAAQC,EAAM,UAAW,CACvB,IAAK,UAAW,CACd,MAAMC,EAASD,EAAM,QAAU,CAAC,EAC1BE,EAAO,CACX,KAAMF,EAAM,KACZ,SAAUA,EAAM,SAChB,UAAW,IAAI,KACb,YAAY,WAAaA,EAAM,SACjC,EAAE,YAAY,EACd,GAAGC,CACL,EAEA,KACF,CACA,QACE,KACJ,CAEJ,CAAC,EACE,QAAQ,CAAE,KAAM,UAAW,SAAU,EAAK,CAAC,CAChD,MAAY,CAAC,CACf,EAEME,EAAe,IAAM,CACzB,KAAM,CAAE,OAAAC,EAAQ,KAAAC,EAAM,UAAAC,EAAW,mBAAAC,EAAoB,QAAAC,CAAQ,EAC3D,OAAO,iBAAmB,CAAC,EACzBJ,IACF,OAAO,OAASA,EAAO,CACrB,UAAWC,EAAK,sDAAsD,EAEtE,MAAO,UACP,KAAM,cACN,QAAS,eACX,CAAC,EAEDC,EAAU,OAAO,MAAM,EACvBC,EAAmB,OAAO,MAAM,EAChC,OAAO,OAAO,KAAK,mBAAmB,EAE1C,EAEO,aAAM,QAAWE,GAAiB,CACvC,GAAIZ,EAAM,OAAOA,EACjBM,EAAa,EACbL,EAAmB,EACnB,MAAMY,EAAc,CAClB,OAAQ,OAAO,OACf,mBAAqBC,GAAU,CAAC,EAChC,aAAAF,EACA,sBAAwBG,GAAY,CAEpC,EACA,wBAA0BA,GAAY,CAEtC,CACF,EACA,OAAAf,EAAO,KAAK,MAAM,QACd,IAAI,IAAI,KAAK,QAAQ,aAAca,CAAW,EAC9C,KAGGb,CACT,EAEa,gBAAkB,UACxBD,IAEHA,EAAY,MADK,MAAM,MAAM,mBAAmB,GACrB,KAAK,GAEV,CACtB,GAAGA,GAAW,QACd,GAAGA,EAAUA,EAAU,SAAS,GAAG,OACrC,GACwB","names":["appConfig","host","monitorPerformance","list","entry","detail","data","createLogger","logger","http","webvitals","logUnhandledErrors","Console","analyticsObj","hostOptions","guest","options"],"sourceRoot":"","file":"utils.js"}
|
|
1
|
+
{"version":3,"sources":["webpack://ice.host/utils.js"],"sourcesContent":["let appConfig = null;\nlet host = null;\n\nconst monitorPerformance = () => {\n try {\n const po = new PerformanceObserver((list) => {\n // eslint-disable-next-line no-restricted-syntax\n for (const entry of list.getEntries()) {\n switch (entry.entryType) {\n case 'measure': {\n const detail = entry.detail ?? {};\n const data = {\n name: entry.name,\n duration: entry.duration,\n startTime: new Date(\n performance.timeOrigin + entry.startTime,\n ).toISOString(),\n ...detail,\n };\n console.log('timing', data);\n break;\n }\n default:\n break;\n }\n }\n });\n po.observe({ type: 'measure', buffered: true });\n } catch (e) {}\n};\n\nconst createLogger = () => {\n const { logger, http, webvitals, logUnhandledErrors, Console } =\n window.emuiDiagnostics || {};\n if (logger) {\n window.logger = logger({\n transport: http('https://int.api.ellielabs.com/diagnostics/v2/logging'),\n // transport: Console(),\n index: 'ssfhost',\n team: 'ui platform',\n appName: 'SSF Host Demo',\n });\n\n webvitals(window.logger);\n logUnhandledErrors(window.logger);\n window.logger.info('SSF Host launched');\n } else console.warn('ui logger missing'); // eslint-disable-line no-console\n};\n\nexport const getHost = (analyticsObj) => {\n if (host) return host;\n createLogger();\n monitorPerformance();\n const hostOptions = {\n logger: window.logger,\n readyStateCallback: (guest) => {},\n analyticsObj,\n measurePerformance: true,\n onGuestEventSubscribe: (options) => {\n console.log('Guest Event Subscribe:', options);\n },\n onGuestEventUnSubscribe: (options) => {\n console.log('Guest Event UnSubscribe:', options);\n },\n };\n host = ice?.host?.SSFHost\n ? new ice.host.SSFHost('IMTProduct', hostOptions)\n : null;\n // debug loglevel\n // host.setLogLevel(10);\n return host;\n};\n\nexport const getGuestBaseUrl = async () => {\n if (!appConfig) {\n const response = await fetch('./app.config.json');\n appConfig = await response.json();\n }\n const activeEnvConfig = {\n ...appConfig?.options,\n ...appConfig[appConfig.activeEnv]?.options,\n };\n return activeEnvConfig?.guestUrl;\n};\n"],"mappings":"AAAA,IAAIA,EAAY,KACZC,EAAO,KAEX,MAAMC,EAAqB,IAAM,CAC/B,GAAI,CACS,IAAI,oBAAqBC,GAAS,CAE3C,UAAWC,KAASD,EAAK,WAAW,EAClC,OAAQC,EAAM,UAAW,CACvB,IAAK,UAAW,CACd,MAAMC,EAASD,EAAM,QAAU,CAAC,EAC1BE,EAAO,CACX,KAAMF,EAAM,KACZ,SAAUA,EAAM,SAChB,UAAW,IAAI,KACb,YAAY,WAAaA,EAAM,SACjC,EAAE,YAAY,EACd,GAAGC,CACL,EAEA,KACF,CACA,QACE,KACJ,CAEJ,CAAC,EACE,QAAQ,CAAE,KAAM,UAAW,SAAU,EAAK,CAAC,CAChD,MAAY,CAAC,CACf,EAEME,EAAe,IAAM,CACzB,KAAM,CAAE,OAAAC,EAAQ,KAAAC,EAAM,UAAAC,EAAW,mBAAAC,EAAoB,QAAAC,CAAQ,EAC3D,OAAO,iBAAmB,CAAC,EACzBJ,IACF,OAAO,OAASA,EAAO,CACrB,UAAWC,EAAK,sDAAsD,EAEtE,MAAO,UACP,KAAM,cACN,QAAS,eACX,CAAC,EAEDC,EAAU,OAAO,MAAM,EACvBC,EAAmB,OAAO,MAAM,EAChC,OAAO,OAAO,KAAK,mBAAmB,EAE1C,EAEO,aAAM,QAAWE,GAAiB,CACvC,GAAIZ,EAAM,OAAOA,EACjBM,EAAa,EACbL,EAAmB,EACnB,MAAMY,EAAc,CAClB,OAAQ,OAAO,OACf,mBAAqBC,GAAU,CAAC,EAChC,aAAAF,EACA,mBAAoB,GACpB,sBAAwBG,GAAY,CAEpC,EACA,wBAA0BA,GAAY,CAEtC,CACF,EACA,OAAAf,EAAO,KAAK,MAAM,QACd,IAAI,IAAI,KAAK,QAAQ,aAAca,CAAW,EAC9C,KAGGb,CACT,EAEa,gBAAkB,UACxBD,IAEHA,EAAY,MADK,MAAM,MAAM,mBAAmB,GACrB,KAAK,GAEV,CACtB,GAAGA,GAAW,QACd,GAAGA,EAAUA,EAAU,SAAS,GAAG,OACrC,GACwB","names":["appConfig","host","monitorPerformance","list","entry","detail","data","createLogger","logger","http","webvitals","logUnhandledErrors","Console","analyticsObj","hostOptions","guest","options"],"sourceRoot":"","file":"utils.js"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!doctype html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Guest V1 -> V2 Host</title><style>body,html,main{height:100%;margin:2px;padding:0}iframe{width:100%;height:100%;border:none}#guest-container{height:100%}</style><script src="https://cdn.mortgagetech.q1.ice.com/pui-diagnostics@3"></script><script src="https://cdn.elliemae.io/elliemae/core/ssf/1.0/elli.ssf.guest.js"></script><script defer="defer" src="js/emuiSsfHost.
|
|
1
|
+
<!doctype html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Guest V1 -> V2 Host</title><style>body,html,main{height:100%;margin:2px;padding:0}iframe{width:100%;height:100%;border:none}#guest-container{height:100%}</style><script src="https://cdn.mortgagetech.q1.ice.com/pui-diagnostics@3"></script><script src="https://cdn.elliemae.io/elliemae/core/ssf/1.0/elli.ssf.guest.js"></script><script defer="defer" src="js/emuiSsfHost.5bb7139d7e86c74f0b6d.js"></script></head><body><h2>Guest V1 nesting Host V2</h2><div id="result"><p id="loan-details"></p><p id="loan-pre-save-event-details"></p></div><div id="guest-container"></div><script type="module">import{getGuestBaseUrl,getHost}from"./utils.js";import{Analytics}from"./analytics-object-v2.js";const analyticsObj=new Analytics,hostV2=getHost(analyticsObj),loadV2Guest=async()=>{const t=await getGuestBaseUrl(),{id:e}=hostV2.loadGuest({id:"guestV2",url:new URL("./v2-guest.html",t).href,title:"Guest V2",targetElement:document.getElementById("guest-container")})};window.addEventListener("load",async()=>{await elli.script.connect();const t=await elli.script.getObject("Application"),e=await elli.script.getObject("Loan"),a=await e.getLoanDetails();document.getElementById("loan-details").innerText=`Loan Data: ${JSON.stringify(a)}`,elli.script.subscribe("loan","onPreSave",(t,e)=>(document.getElementById("loan-pre-save-event-details").innerText=`Presave event data: ${JSON.stringify(e)}`,!1)),hostV2.addScriptingObject(hostV2.cloneScriptingObject(t,{})),hostV2.addScriptingObject(hostV2.cloneScriptingObject(e,{})),await loadV2Guest()})</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!doctype html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Host V2 -> V1 Guest</title><style>body,html,main{height:100%;margin:4px;padding:0}iframe{width:100%;height:100%;border:none}#guest-container{height:100%}</style><script src="https://cdn.mortgagetech.q1.ice.com/pui-diagnostics@3"></script><script defer="defer" src="js/emuiSsfHost.
|
|
1
|
+
<!doctype html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Host V2 -> V1 Guest</title><style>body,html,main{height:100%;margin:4px;padding:0}iframe{width:100%;height:100%;border:none}#guest-container{height:100%}</style><script src="https://cdn.mortgagetech.q1.ice.com/pui-diagnostics@3"></script><script defer="defer" src="js/emuiSsfHost.5bb7139d7e86c74f0b6d.js"></script></head><body><main><h1>Host V2 nesting V1 Guest</h1><button id="save-btn" type="button" onclick="saveLoan()">Save Loan</button><div id="results"><p id="pre-save-feedback-result"></p></div><div id="guest-container"></div></main><script type="module">import{Loan}from"./loan-object.js";import{Application}from"./application-object-v2.js";import{getGuestBaseUrl,getHost}from"./utils.js";import{Analytics}from"./analytics-object-v2.js";const analyticsObj=new Analytics,hostV2=getHost(analyticsObj),loanObj=new Loan,appObj=new Application;hostV2.addScriptingObject(loanObj),hostV2.addScriptingObject(appObj);const params=new URLSearchParams(document.location.search),{id:id}=hostV2.loadGuest({id:"guestV1",url:new URL("true"!==params.get("nestV1GuestV2Host")?"./v1-guest.html":"./v1-guest-v2-host.html",window.location.href).href,searchParams:{nestHostV1:!0},title:"Guest V1",targetElement:document.getElementById("guest-container")});window.saveLoan=async()=>{const e=loanObj.getLoanDetails();(await hostV2.dispatchEvent({event:loanObj.onPreSave,eventParams:e,eventOptions:{timeout:1e3}})).some(e=>!1===e)?document.getElementById("pre-save-feedback-result").innerText="Pre save failed":document.getElementById("pre-save-feedback-result").innerText="Pre save succeeded"}</script></body></html>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { IAnalytics } from '@elliemae/pui-scripting-object';
|
|
2
1
|
import { Remoting } from '@elliemae/microfe-common';
|
|
3
2
|
import { EventObject, OpenMode } from './types.js';
|
|
3
|
+
import type { PerformanceTracker } from './performanceTracker.js';
|
|
4
4
|
/**
|
|
5
5
|
* options for creating a guest application
|
|
6
6
|
*/
|
|
@@ -38,9 +38,9 @@ type GuestOption = {
|
|
|
38
38
|
*/
|
|
39
39
|
remoting: Remoting;
|
|
40
40
|
/**
|
|
41
|
-
*
|
|
41
|
+
* performance tracker for timing measurements
|
|
42
42
|
*/
|
|
43
|
-
|
|
43
|
+
perfTracker: PerformanceTracker;
|
|
44
44
|
};
|
|
45
45
|
/**
|
|
46
46
|
* message to be sent
|
|
@@ -135,6 +135,7 @@ export declare class Guest {
|
|
|
135
135
|
* invokes event callback on the guest application
|
|
136
136
|
* @param {EventObject} event - event object
|
|
137
137
|
* @param {number} timeout - timeout in milliseconds
|
|
138
|
+
* @returns {Promise} resolves when the guest handles the event
|
|
138
139
|
*/
|
|
139
140
|
dispatchEvent: (event: EventObject, timeout: number) => Promise<unknown>;
|
|
140
141
|
/**
|
package/dist/types/lib/host.d.ts
CHANGED
|
@@ -16,7 +16,6 @@ export declare class SSFHost<AppObjects extends ScriptingObjects = ScriptingObje
|
|
|
16
16
|
* unique identifier for the host
|
|
17
17
|
*/
|
|
18
18
|
hostId: string;
|
|
19
|
-
static readonly DEFAULT_TIMING_DEDUP_WINDOW_MS = 10000;
|
|
20
19
|
/**
|
|
21
20
|
* Create a new host
|
|
22
21
|
* @param hostId unique identifier for the host
|
|
@@ -61,15 +61,32 @@ export type HostOption = {
|
|
|
61
61
|
* callback to process guest event unsubscription
|
|
62
62
|
*/
|
|
63
63
|
onGuestEventUnsubscribe?: GuestEventUnsubscribeCallback;
|
|
64
|
+
/**
|
|
65
|
+
* Enable performance timing for SSF operations (guest load, scripting
|
|
66
|
+
* object method calls, and event dispatches). Disabled by default to
|
|
67
|
+
* avoid excessive analytics volume.
|
|
68
|
+
* @default false
|
|
69
|
+
*/
|
|
70
|
+
measurePerformance?: boolean;
|
|
64
71
|
/**
|
|
65
72
|
* Minimum interval (ms) between timing measurements for the same metric name.
|
|
66
73
|
* When a timing for a given name is recorded, subsequent timings for the same
|
|
67
74
|
* name are skipped until this window elapses. Avoids redundant cross-window
|
|
68
75
|
* analytics calls for high-frequency APIs and events.
|
|
69
76
|
* Set to 0 to disable deduplication (time every call).
|
|
77
|
+
* Only effective when {@link measurePerformance} is true.
|
|
70
78
|
* @default 10000
|
|
71
79
|
*/
|
|
72
|
-
|
|
80
|
+
performanceDedupWindowMs?: number;
|
|
81
|
+
/**
|
|
82
|
+
* Sampling ratio (0–1) for high-frequency timing events such as
|
|
83
|
+
* scripting object method calls (`ScriptingObject.API.*`) and event
|
|
84
|
+
* dispatches (`ScriptingObject.Event.*`).
|
|
85
|
+
* `SSF.Guest.Load` is low-frequency and uses the analytics-so default.
|
|
86
|
+
* Only effective when {@link measurePerformance} is true.
|
|
87
|
+
* @default 0.05
|
|
88
|
+
*/
|
|
89
|
+
performanceSamplingRatio?: number;
|
|
73
90
|
};
|
|
74
91
|
/**
|
|
75
92
|
* parameters for rendering a guest
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { IAnalytics, TimingOptions } from '@elliemae/pui-scripting-object';
|
|
2
|
+
export type PerformanceTrackerOptions = {
|
|
3
|
+
analyticsObj: IAnalytics;
|
|
4
|
+
enabled?: boolean;
|
|
5
|
+
samplingRatio?: number;
|
|
6
|
+
dedupWindowMs?: number;
|
|
7
|
+
onError?: (message: string) => void;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Encapsulates SSF performance timing — enabled guard, per-name sampling
|
|
11
|
+
* ratio configuration, deduplication window, and start/end lifecycle.
|
|
12
|
+
*
|
|
13
|
+
* Low-frequency timing names (e.g. `SSF.Guest.Load`) bypass both the
|
|
14
|
+
* dedup window and the custom sampling ratio, using the analytics-so default.
|
|
15
|
+
*/
|
|
16
|
+
export declare class PerformanceTracker {
|
|
17
|
+
#private;
|
|
18
|
+
static readonly DEFAULT_SAMPLING_RATIO = 0.05;
|
|
19
|
+
static readonly DEFAULT_DEDUP_WINDOW_MS = 10000;
|
|
20
|
+
constructor(options: PerformanceTrackerOptions);
|
|
21
|
+
/**
|
|
22
|
+
* Whether performance tracking is active. Callers can use this to
|
|
23
|
+
* skip expensive work (e.g. building timing name strings) when
|
|
24
|
+
* tracking is disabled.
|
|
25
|
+
* @returns {boolean} true when performance tracking is enabled
|
|
26
|
+
*/
|
|
27
|
+
get enabled(): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Begin a timing measurement. Returns the timing name as a token when
|
|
30
|
+
* timing was started, or `undefined` when timing is disabled, deduped,
|
|
31
|
+
* or skipped. Pass the returned token to {@link end}.
|
|
32
|
+
* Never throws — failures are reported via the `onError` callback.
|
|
33
|
+
* @param {string} name - timing event name
|
|
34
|
+
* @param {TimingOptions} options - context passed to the analytics object
|
|
35
|
+
* @returns {string | undefined} the timing token, or undefined if skipped
|
|
36
|
+
*/
|
|
37
|
+
start(name: string, options: TimingOptions): string | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* End a timing measurement previously started via {@link start}.
|
|
40
|
+
* No-op when token is `undefined` (timing was not started).
|
|
41
|
+
* Never throws — failures are reported via the `onError` callback.
|
|
42
|
+
* @param {string | undefined} token - token returned by {@link start}
|
|
43
|
+
* @param {TimingOptions} options - context passed to the analytics object
|
|
44
|
+
*/
|
|
45
|
+
end(token: string | undefined, options: TimingOptions): void;
|
|
46
|
+
}
|