{"version":3,"file":"sf-1.50.k4vbi2hr.js","names":[],"sources":["../../../../src/js/components/perf.ts","../../../../../../../node_modules/@amzn/apejs-instrumentation/src/metrics/browseNode.ts","../../../../../../../node_modules/@amzn/apejs-instrumentation/src/metrics/csm/util.ts","../../../../../../../node_modules/@amzn/apejs-instrumentation/src/metrics/csm/counter.ts","../../../../../../../node_modules/@amzn/apejs-instrumentation/src/metrics/logging.ts","../../../../../../../node_modules/@amzn/apejs-instrumentation/src/metrics/csa/events.ts","../../../../../../../node_modules/@amzn/apejs-instrumentation/src/metrics/counters.ts","../../../../src/js/client/apiPage/cache/geomCache.ts","../../../../src/js/client/apiPage/cache/numberCache.ts","../../../../src/js/client/apiPage/sfApi.ts","../../../../src/js/components/metrics/latency-metric-type.ts","../../../../src/js/client/commonSf.ts","../../../../src/js/client/CommonApiImplementation.ts","../../../../src/js/client/clientMessageReceiver.ts","../../../../src/js/client/clientMessageSender.ts","../../../../../../../node_modules/@amzn/creative-rendering-monitor/src/btr.ts","../../../../../../../node_modules/@amzn/creative-rendering-monitor/src/creativeBTREvaluatorSync.ts","../../../../src/js/components/weblabs.ts","../../../../src/js/components/metrics/awsMetricLoggerApiKey.ts","../../../../src/js/components/metrics/awsMetricBatcher.ts","../../../../src/js/components/metrics/logMetricOnce.ts","../../../../src/js/components/metrics/awsMetricLogger.ts","../../../../src/js/components/pixels/pixel.ts","../../../../src/js/components/pixels/pixelIdentifiers.ts","../../../../src/js/components/pixels/services/pixelLogger.ts","../../../../src/js/client/MEASUREMENT_METHODS.ts","../../../../src/js/components/urlQueryParams/addJSONQueryParamToURL.ts","../../../../src/js/components/util.ts","../../../../src/js/components/pixels/urlGenerators/impressionPixelUrlGenerator.ts","../../../../src/js/components/pixels/pixelMapper.ts","../../../../src/js/components/viewRateExperimentUtil.ts","../../../../src/js/host/api-client/CommonSupportedCommands.ts","../../../../src/js/client/checkAndResizeImageOnlyCreative.ts","../../../../src/js/client/clientReporter.ts","../../../../src/js/client/render.util.ts","../../../../src/js/client/validateCreativeRendering.ts","../../../../src/js/client/render.ts","../../../../src/js/client/service/documentWrite.ts","../../../../src/js/components/clickTracking/replace.ts","../../../../src/js/components/counters/AD_LOAD_CSM_COUNTERS.ts","../../../../src/js/client/percolateClickTracker.ts","../../../../src/js/client/service/get-creative.ts","../../../../src/js/client/CommonSFSetup.ts","../../../../src/js/client/DesktopSFClientAPIImplementation.ts","../../../../src/js/client/application/safeframeClientFactory.ts","../../../../src/js/client/components/adDetails.ts","../../../../src/js/components/messaging/bootstrap.ts","../../../../src/js/client/components/notifyParent.ts","../../../../src/js/client/errorHandling/handleErrors.ts","../../../../src/js/components/messageChannel/bridge/clientBridge.ts","../../../../src/js/components/messageChannel/csm/csmChannelClient.ts","../../../../src/js/client/disable/disableCookieAccess.ts","../../../../src/js/client/disable/disableGeolocationApi.ts","../../../../src/js/client/disable/disableUserAgent.ts","../../../../src/js/client/disable/workAroundIOBugtt0156195085.ts","../../../../src/js/client/disable/disableAll.ts","../../../../src/js/client/security/referrers.ts","../../../../src/js/client/service/dcm.ts","../../../../src/js/client/service/setupReportingObserver.ts","../../../../src/js/client/initSafeframeClient.ts","../../../../src/js/client/entrypoints/sf.ts"],"sourcesContent":["import type { AdDetails } from '@amzn/safeframe-model';\n\nexport const getMarkName = (scope: string, message: string, adDetails?: AdDetails): string =>\n    `${scope}${adDetails ? `:${adDetails.placementName}` : ''} - ${message}`;\n\nexport const mark = (scope: string, message: string, adDetails?: AdDetails): string => {\n    const markString = getMarkName(scope, message, adDetails);\n\n    performance?.mark?.(markString);\n\n    return markString;\n};\n","/*\n    The regex pattern used in Javelin for getting browseNode in the URL\n    https://code.amazon.com/packages/JavelinPrimingServiceCDK/blobs/mainline/--/configuration/appconfig/pageContextConfig-prod.json#L97\n*/\nconst regex = /(\\/b|\\/s|\\/l).*(node=)(\\d{1,12})/;\nconst cache = new Map();\n\nexport const getBrowseNode = (): string | null => {\n    if (!cache.has(window.location.href)) {\n        const match = regex.exec(window.location.href);\n        const browseNode = match && match[3] ? match[3] : null;\n        cache.set(window.location.href, browseNode);\n    }\n    return cache.get(window.location.href);\n};\n\nexport const getSlotWithBrowseNode = (slot: string): string | null => {\n    const browseNode = getBrowseNode();\n    if (!slot || !browseNode) {\n        return null;\n    }\n    const slotItems = slot.split(':');\n    slotItems.splice(slotItems.length - 1, 0, browseNode);\n    return slotItems.join(':');\n};\n\nexport const getPlacementWithBrowseNode = (placementId: string): string | null => {\n    const browseNode = getBrowseNode();\n    if (!browseNode) {\n        return null;\n    }\n\n    return `${placementId}:${browseNode}`;\n};\n","export const csmName = (name: string) => name.replace(/_/g, ':');\n","// https://w.amazon.com/index.php/ClientSideMetrics/UserDocs/Instrumentation/ClientSideCounters\nimport { getPlacementWithBrowseNode, getSlotWithBrowseNode } from '../browseNode.js';\nimport { csmName } from './util.js';\nimport type { Placement } from '../placement.js';\n\n/**\n * @description CSM - Increment placement level counter for a CSM metric.\n * @param metric The actual metrics name, without Placement information\n * @param placement The Placement you want to log metrics for\n * @param count The number to increment the count by (default 1)\n * @example incrementPlacementCounter('adfeedback:request', {id: '597b923a-8c7e-4665-9541-de88160dd0ba', name: 'Gateway_right-2_desktop'})\n * @example incrementPlacementCounter('adfeedback:request', {id: '597b923a-8c7e-4665-9541-de88160dd0ba', name: 'Gateway_right-2_desktop'}, 2)\n */\nexport const incrementCsmPlacementCounter = (metric: string, placement: Placement, count = 1) => {\n    if (!isUeCountAvailable()) return;\n\n    const countMetric = (metric: string, metricType: string | null, count: number) => {\n        if (!metricType) return;\n        ueCount(`${adPlacementMetric(metric)}:${metricType}`, count);\n    };\n\n    countMetric(metric, placement.id, count);\n    countMetric(metric, getPlacementWithBrowseNode(placement.id), count);\n\n    countMetric(metric, csmName(placement.name), count);\n    countMetric(metric, getSlotWithBrowseNode(csmName(placement.name)), count);\n};\n\n/**\n * @description CSM - Increment market level counter for a CSM metric.\n * @param metric The actual metrics name\n * @param count The number to increment the count by (default 1)\n * @example incrementCounter('adfeedback:request')\n * @example incrementCounter('adfeedback:request', 2)\n */\nexport const incrementCsmCounter = (metric: string, count = 1) => {\n    if (!isUeCountAvailable()) return;\n\n    ueCount(adPlacementMetric(metric), count);\n};\n\nexport const isUeCountAvailable = () => typeof window?.ue?.count === 'function';\nexport const ueCount = (metric: string, count: number) => window?.ue?.count(metric, count);\n\nconst adPlacementPrefix = 'adplacements';\nconst adPlacementMetric = (metric: string): string =>\n    metric.startsWith(adPlacementPrefix) ? metric : `${adPlacementPrefix}:${metric}`;\n","import { LogLevel } from './csmGlobal.js';\n\n/*\n * All Error logging should go through these 2 functions.\n * Issues which degrade customer experience should call {@link logFatal}\n * Log level descriptions: https://w.amazon.com/bin/view/ClientSideMetrics/UserDocs/JavascriptErrors/#Error_levels\n * This will send messages/errors to RTLA, which can be analyzed to provide more information.\n */\n\n/**\n * Logs a message to the console, with console.debug(message)\n * @param message text send to console\n */\nexport const logDebug = (message: string): void => {\n    console.debug(message);\n};\n\n/**\n * Sends a warn message to RTLA.\n * @param message the text string of the warn\n * @param err the error object to log, if omitted, an error object will be created using message\n */\nexport const logWarn = (message: string, err?: Error | any): void => {\n    console.warn(message, JSON.stringify(err));\n    emitToRTLA('WARN', message, toError(message, err));\n};\n\n/**\n * Send an error message to RTLA. Use {@link logFatal} instead for issues which degrade customer experience.\n * @param message the text string of the error\n * @param err the error object to log, if omitted, an error object will be created using message\n */\nexport const logError = (message: string, err?: Error | any): void => {\n    console.error(message, JSON.stringify(err));\n    emitToRTLA('ERROR', message, toError(message, err));\n};\n\n/**\n * Send a fatal error message to RTLA. Use {@link logError} instead for non-critical errors.\n * @param message the text string of the error\n * @param err the error object to log, if omitted, an error object will be created using message\n */\nexport const logFatal = (message: string, err?: Error | any): void => {\n    console.error(message, JSON.stringify(err));\n    emitToRTLA('FATAL', message, toError(message, err));\n};\n\nconst emitToRTLA = (level: LogLevel, message: string, err: Error): void => {\n    window.ueLogError?.(err, {\n        logLevel: level,\n        attribution: 'APE-safeframe',\n        message: message + ' | '\n    });\n};\n\nconst toError = (message: string, err: any): Error =>\n    err instanceof Error ? err : err ? new Error(err) : new Error(message);\n","import { logError } from '../logging.js';\nimport type { Placement } from '../placement.js';\nimport type {} from './csa-global.js';\n\n/**\n * Attaches metadata from an `entity` to subsequent events. For example:\n * ```\n *   csa.addCsaEntity({ ABPStatus: ABP_STATUS[data.abpStatus as keyof typeof ABP_STATUS] });\n *   events('log', {schemaId: 'ApeSafeframe.csaEvent.1'}, {ent: 'all'})\n * ```\n *\n * will produce the following CSA log:\n * ```\n * \"data\": {\n *      \"schemaId\": \"ApeSafeframe.csaEvent.1\",\n *      \"metricName\": \"abpstatus_notenabled:Gateway_right-2_desktop:4293fb4d-96ae-46e9-81f1-7503c09f76f3\",\n *      \"metricValue\": 1,\n *      ...\n *      \"entities\": {\n *          \"adCreativeMetaData\": {\n *              \"id\": \"3v21xq-3ejsvn-ut5yxw-3kbtb4\",\n *              \"ABPStatus\": \"NotEnabled\"\n *          },\n *          ...\n *      }\n * ```\n * @param entity {Object} - metadata that can be attached to multiple events\n */\n\nexport const setCsaEntity = (entity: object): void => {\n    if (!window.csa) return;\n\n    try {\n        window.csa('Events', {\n            producerId: 'adplacements'\n        })('setEntity', { adCreativeMetaData: entity });\n    } catch (ex) {\n        logError(\"Error with 'setEntity' CSA\", ex);\n    }\n};\n\n/**\n * Increment counter for a CSA metric. For example:\n * ```\n * logCsaEvent(\"adload:htmlreached\", \"Gateway_desktop-ad-center-1_desktop\", \"73950e1c-6f66-4784-b2d9-e5d5693a4353\");\n * ```\n *\n * will produce the following CSA log:\n * ```\n * \"data\": {\n *      \"schemaId\": \"ApeSafeframe.csaEvent.1\",\n *      \"metricName\": \"adload:htmlreached:Gateway_desktop-ad-center-1_desktop:73950e1c-6f66-4784-b2d9-e5d5693a4353\",\n *      \"metricValue\": 1,\n *      ...\n * }\n * ```\n *\n * CSA events reference: https://info.analytics.a2z.com/#/docs/data_collection/csa/events\n */\nexport const incrementCsaPlacementCounter = (metric: string, placement: Placement, count = 1) => {\n    if (!window.csa) return;\n\n    try {\n        window.csa('Events', {\n            producerId: 'adplacements'\n        })(\n            'log',\n            {\n                schemaId: 'ApeSafeframe.csaEvent.1',\n                metricName: metric + ':' + placement.name + ':' + placement.id,\n                metricValue: count\n            },\n            { ent: 'all' }\n        );\n    } catch (ex) {\n        logError(\"Error with 'logCsaEvent' CSA\", ex);\n    }\n};\n\nexport const incrementCsaCounter = (metric: string, count = 1) => {\n    if (!window.csa) return;\n\n    try {\n        window.csa('Events', {\n            producerId: 'adplacements'\n        })(\n            'log',\n            {\n                schemaId: 'ApeSafeframe.csaEvent.1',\n                metricName: metric,\n                metricValue: count\n            },\n            { ent: 'all' }\n        );\n    } catch (ex) {\n        logError(\"Error with 'incrementCounter' CSA\", ex);\n    }\n};\n","import { incrementCsmPlacementCounter, incrementCsmCounter } from './csm/counter.js';\nimport { incrementCsaPlacementCounter, incrementCsaCounter } from './csa/events.js';\nimport type { Placement } from './placement.js';\n\nexport const AD_LOAD_COUNTERS = {\n    HTML_REACHED: 'adload:htmlreached'\n};\n\nexport const incrementPlacementCounter = (metric: string, placement: Placement, count = 1) => {\n    incrementCsmPlacementCounter(metric, placement, count);\n    incrementCsaPlacementCounter(metric, placement, count);\n};\n\nexport const incrementMarketCounter = (metric: string, count = 1) => {\n    incrementCsmCounter(metric, count);\n    incrementCsaCounter(metric, count);\n};\n","import type { GeometricInformation } from '@amzn/safe-frame-client';\n\nimport type { Cache } from '@/client/apiPage/cache/cache.js';\n\nexport const defaultGeom: GeometricInformation = {\n    win: {\n        t: 0,\n        b: 0,\n        l: 0,\n        r: 0,\n        w: 0,\n        h: 0,\n    },\n    self: {\n        t: 0,\n        l: 0,\n        r: 0,\n        b: 0,\n        xiv: 0,\n        yiv: 0,\n        iv: 0,\n        z: 0,\n        w: 0,\n        h: 0,\n    },\n    exp: {\n        t: 0,\n        l: 0,\n        r: 0,\n        b: 0,\n        xs: 0,\n        yx: 0,\n    },\n};\n\nexport const createGeomCache = (initial: GeometricInformation = defaultGeom): Cache<GeometricInformation> => {\n    const cachedGeom: GeometricInformation = initial;\n\n    return {\n        set(newGeom: GeometricInformation): void {\n            cachedGeom.self = {\n                ...cachedGeom.self,\n                ...newGeom.self,\n            };\n        },\n        get(): GeometricInformation {\n            return cachedGeom;\n        },\n    };\n};\n","import type { Cache } from '@/client/apiPage/cache/cache.js';\n\nexport const createNumberCache = (defaultNumber: number = -1): Cache<number> => {\n    let cachedNumber = defaultNumber;\n\n    return {\n        set(value: number): void {\n            cachedNumber = value;\n        },\n        get(): number {\n            return cachedNumber;\n        },\n    };\n};\n","/**\n * @desc IAB safeframe API for some limited functionality\n * {@link http://www.iab.net/media/file/SafeFrames_v1.1_final.pdf}\n */\nimport type { ExternalParty, GeometricInformation } from '@amzn/safe-frame-client';\n\nimport { createGeomCache } from '@/client/apiPage/cache/geomCache.js';\nimport { createNumberCache } from '@/client/apiPage/cache/numberCache.js';\n\ndeclare global {\n    interface Window {\n        $sf?: SafeFrame;\n    }\n}\n\nexport interface SafeFrame {\n    ext: ExternalParty;\n}\n\nexport const inViewPercentageCache = createNumberCache();\nexport const geomCache = createGeomCache();\n\nexport const create$sf = (): SafeFrame => {\n    return {\n        ext: {\n            /**\n             * @desc Gives the inViewPercentage of the SafeFrame container as a whole number in [0, 100]\n             * @returns {Number} returns the inView percentage of the SafeFrame container\n             */\n            inViewPercentage: (): number => inViewPercentageCache.get(),\n\n            /**\n             * @desc Gives the geometric dimension and location of SafeFrame container\n             */\n            geom: (): GeometricInformation => geomCache.get(),\n        },\n    };\n};\n","type CsaKey =\n    | 'bodyBegin'\n    | 'bodyEnd'\n    | 'clickToATF'\n    | 'criticalFeature'\n    | 'loaded'\n    | 'viewablelatency:bodyBegin'\n    | 'viewablelatency:loaded';\n\ntype CsmKey = 'af' | 'bb' | 'be' | 'cf' | 'ld';\n\nconst HOST_SCOPE = 'sfImpression' as const;\nconst LIGHTAD_SCOPE = 'LightAdImpression' as const;\nconst VIEWABLE_LATENCY = 'viewablelatency' as const;\n\ntype CsmMessage = typeof HOST_SCOPE | typeof LIGHTAD_SCOPE | typeof VIEWABLE_LATENCY;\n\nexport interface LatencyMetricType {\n    readonly csaKey: CsaKey;\n    readonly csmKey: CsmKey;\n    readonly csmMessage?: CsmMessage;\n}\n\nconst create = (csaKey: CsaKey, csmKey: CsmKey, csmMessage?: CsmMessage): LatencyMetricType => {\n    return { csaKey, csmKey, csmMessage };\n};\n\nexport const BODY_BEGIN = create('bodyBegin', 'bb');\nexport const BODY_BEGIN_HOST_SCOPE = create('bodyBegin', 'bb', HOST_SCOPE);\nexport const BODY_BEGIN_LIGHTAD_SCOPE = create('bodyBegin', 'bb', LIGHTAD_SCOPE);\n\nexport const BODY_END = create('bodyEnd', 'be');\n\nexport const CLICK_TO_ATF = create('clickToATF', 'af');\n\nexport const CRITICAL_FEATURE = create('criticalFeature', 'cf');\nexport const CRITICAL_FEATURE_HOST_SCOPE = create('criticalFeature', 'cf', HOST_SCOPE);\nexport const CRITICAL_FEATURE_LIGHTAD_SCOPE = create('criticalFeature', 'cf', LIGHTAD_SCOPE);\n\nexport const LOADED = create('loaded', 'ld');\nexport const LOADED_HOST_SCOPE = create('loaded', 'ld', HOST_SCOPE);\nexport const LOADED_LIGHTAD_SCOPE = create('loaded', 'ld', LIGHTAD_SCOPE);\n\nexport const VIEWABLE_LATENCY_BODY_BEGIN = create('viewablelatency:bodyBegin', 'bb', VIEWABLE_LATENCY);\nexport const VIEWABLE_LATENCY_LOADED = create('viewablelatency:loaded', 'ld', VIEWABLE_LATENCY);\n","import { CRITICAL_FEATURE, LOADED } from '../components/metrics/latency-metric-type.js';\nimport type { CommonApiImplementation } from './CommonApiImplementation.js';\n\nexport const sendCriticalFeatureAndLoaded = (c: CommonApiImplementation) => {\n    c.sendLatencyMetric(LOADED);\n    c.sendLatencyMetric(CRITICAL_FEATURE);\n};\n","import { incrementMarketCounter } from '@amzn/apejs-instrumentation/src/metrics/counters.js';\nimport type { SFClientAPI, SFClientVideoAPI } from '@amzn/safe-frame-client-amzn';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport { geomCache, inViewPercentageCache } from '@/client/apiPage/sfApi.js';\nimport type { GeomMessage, SafeFrameExtMessage } from '@/host/api-client/handlers/sendSafeFrameExt.js';\n\nimport type { ComputedAdDetailsData, ViewPixelOptionsData } from '../components/commands.js';\nimport type { LatencyMetricType } from '../components/metrics/latency-metric-type.js';\nimport type { CommonSupportedCommands } from '../host/api-client/CommonSupportedCommands.js';\nimport type { ClientMessageListeners } from './clientMessageReceiver.js';\nimport type { ClientMessageSender } from './clientMessageSender.js';\nimport { sendCriticalFeatureAndLoaded } from './commonSf.js';\nimport type { InternalSFClientAPI } from './InternalSFClientAPI.js';\n\ndeclare global {\n    interface Window {\n        aPageStart?: number | undefined;\n        adStartTime?: number | undefined;\n    }\n}\n\n/**\n * @desc Contains safeframe client APIs that are common to desktop and mobile safeframe.\n */\nexport class CommonApiImplementation implements SFClientVideoAPI, SFClientAPI, InternalSFClientAPI {\n    constructor(\n        private readonly cms: ClientMessageSender,\n        private readonly o: AdDetails,\n        private readonly mL: ClientMessageListeners,\n    ) {}\n\n    changeSize = (width: string, height: string) => {\n        this.cms.sendMessage<CommonSupportedCommands['changeSize']>('changeSize', { width: width, height: height });\n    };\n\n    registerCustomMessageListener = (msgKey: string, callback: any) => {\n        this.mL[msgKey] = callback;\n        incrementMarketCounter('sf:commonmain:registerCustomMessageListener');\n    };\n\n    sendLatencyMetric = (latencyMetricType: LatencyMetricType) => {\n        this.cms.sendMessage<CommonSupportedCommands['sendLatencyMetric']>('sendLatencyMetric', {\n            latencyMetricType: latencyMetricType,\n            timestamp: new Date(),\n        });\n    };\n\n    /**\n     * @desc Used by Creative template owners to trigger metric for 'Sponsored Label' rendered.\n     */\n    feedbackLabelRendered = () => {\n        this.cms.sendMessage<CommonSupportedCommands['feedbackLabelRendered']>('feedbackLabelRendered');\n    };\n    /**\n     * @desc Used by Creative template owners to open feedback Modal.\n     */\n    feedbackOpenModal = () => {\n        this.cms.sendMessage<CommonSupportedCommands['feedbackOpenModal']>('feedbackOpenModal');\n    };\n\n    /**\n     * Viewability pixels for video are fired from a combination of time spent in the view port and time spent playing.\n     * For ad templates which implement their own video player (ie Sponsored Display's PERC), they need to tell SF how much\n     * time has been spent playing. SF will combine this with its knowledge of in view time to determine when to fire a\n     * viewability pixel.\n     *\n     * @param continuousPlaybackSeconds - This is the maximum amount of continuous playback time the videoplayer has observed (in seconds)\n     */\n    updatePlayingTimeForVideo = (continuousPlaybackSeconds: number) => {\n        // Send message from iframe to host on the updated continuousPlaybackSeconds\n        this.cms.sendMessage<CommonSupportedCommands['sendSfVideoContinuousPlaytimeSeconds']>(\n            'sendSfVideoContinuousPlaytimeSeconds',\n            {\n                sfVideoContinuousPlaytimeSeconds: continuousPlaybackSeconds,\n            },\n        );\n    };\n    requestVideoAutoplay = () => {\n        this.cms.sendMessage<CommonSupportedCommands['requestVideoAutoplay']>('requestVideoAutoplay');\n    };\n    releaseVideoAutoplay = () => {\n        this.cms.sendMessage<CommonSupportedCommands['releaseVideoAutoplay']>('releaseVideoAutoplay');\n    };\n    haveVideoAutoplayPermission = () => {\n        this.cms.sendMessage<CommonSupportedCommands['haveVideoAutoplayPermission']>('haveVideoAutoplayPermission');\n    };\n\n    isOnAmazon = (): boolean => {\n        return true;\n    };\n\n    collapseSlot = () => {\n        this.cms.sendMessage<CommonSupportedCommands['collapseSlot']>('collapseSlot', 'CREATIVE');\n    };\n\n    resizeCreativeWrapper = (data: { height: string; width: string }) => {\n        const creativeWrapper = window.document.getElementById(`ape_${this.o.scope}_creativeWrapper`);\n        if (creativeWrapper === null) {\n            return;\n        }\n\n        creativeWrapper.style.height = data.height;\n        creativeWrapper.style.width = data.width;\n    };\n\n    /**\n     * Used to emit a custom event to the ad notifying that an event occurred outside the safeframe.\n     * @param data object containing the name of the event which is being propagated to the ad\n     */\n    triggerEventInIframe = (data: { eventType: string }) => {\n        window.dispatchEvent(new Event('outerpage' + data.eventType));\n    };\n\n    setupComputedAdDetails = (data: ComputedAdDetailsData) => {\n        window.aPageStart = data.aPageStart;\n        window.adStartTime = data.adStartTime;\n    };\n\n    signalAdLoadedAndInteractive = () => {\n        sendCriticalFeatureAndLoaded(this);\n    };\n\n    /**\n     *\n     * Client sends domain event to host to fire the\n     * COD impression pixel using the Light Ads logic\n     */\n    sendEventAddedCreative = () => {\n        this.cms.sendMessage<CommonSupportedCommands['sendEventAddedCreative']>('sendEventAddedCreative');\n    };\n\n    sendEventCreativeBeginToRender = () => {\n        this.cms.sendMessage<CommonSupportedCommands['sendEventCreativeBeginToRender']>(\n            'sendEventCreativeBeginToRender',\n        );\n    };\n\n    sendEventCreativeLoaded = (data: ViewPixelOptionsData) => {\n        this.cms.sendMessage<CommonSupportedCommands['sendEventCreativeLoaded']>('sendEventCreativeLoaded', data);\n    };\n\n    resizeForImageOnlyTemplate = () => {\n        this.cms.sendMessage<CommonSupportedCommands['resizeForImageOnlyTemplate']>('resizeForImageOnlyTemplate');\n    };\n\n    populateGeom = (message: GeomMessage): void => geomCache.set(message.geom);\n\n    populateSafeFrameExt = (message: SafeFrameExtMessage): void => {\n        inViewPercentageCache.set(message.inViewPercentage);\n        geomCache.set(message.geom);\n    };\n}\n","import { logError } from '@amzn/apejs-instrumentation/src/metrics/logging.js';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport type { HostMessageToClient } from '../components/messaging/types.js';\nimport type { ClientApis } from './types/types.js';\n\nexport type ClientMessageListeners = { [key: string]: (data: any) => void };\n\nexport class ClientMessageReceiver {\n    constructor(\n        readonly c: ClientApis,\n        readonly o: AdDetails,\n        private readonly mL: ClientMessageListeners,\n    ) {}\n    private readonly pendingMessages = new Map<string, () => void>();\n    // TODO Convert this to a more generalized mechanism\n    // For now it just waits for the next message of the key to be processed\n    // Main usecase is for dynamic compuated details to get the non-Promised APIS to work as in\n    // https://code.amazon.com/packages/SafeFrameClient/blobs/e6d7afa4b0c567ab7ba245a07efd974cd8f3a6b6/--/packages/safe-frame-client-mobilesfclient/src/MobileSFClientAPI.ts#L187\n    /**\n     * This does not support more than one wait per message time and promise will only be resolved once\n     * @deprecated\n     * @param key The commadn to for wait for\n     * @returns A promise that will be fired.\n     */\n    waitForMessageProcessed = async (key: string): Promise<void> => {\n        return new Promise((resolve) => this.pendingMessages.set(key, resolve));\n    };\n\n    receiveMessage = (event: MessageEvent) => {\n        try {\n            const msg: HostMessageToClient = event.data;\n            // msgObj is expected to have a command\n            const cmdPath = msg.command ? msg.command.split('.') : [];\n            type ActionPath = { [key: string]: ActionPath } | ((...args: any) => void);\n            let action: ActionPath = this.c[cmdPath[0] as keyof ClientApis];\n            for (let i = 1; i < cmdPath.length; i++) {\n                if (action) {\n                    action = (action as unknown as { [key: string]: ActionPath })[cmdPath[i]];\n                } else {\n                    break;\n                }\n            }\n            if (msg.command === 'customMessage') {\n                // treat custom message specially\n                const msgKey = msg.data.key;\n                const body = msg.data.data;\n                if (typeof this.mL[msgKey] === 'function') {\n                    try {\n                        this.mL[msgKey](body);\n                    } catch (ex) {\n                        logError('Custom Message Listener Error', ex as Error);\n                    }\n                }\n            } else if (action) {\n                (action as (...args: any) => void)(msg.data);\n                resolveMessagePromise(msg.command, this.pendingMessages);\n            }\n        } catch (ex) {\n            //Log the error metrics for debugging purposes.\n            logError('Error with ' + event.data.command, ex as Error);\n            return;\n        }\n    };\n}\n\nconst resolveMessagePromise = (command: string, pendingMessages: Map<string, () => void>) => {\n    const resolve = pendingMessages?.get(command);\n    resolve?.();\n    pendingMessages?.delete(command);\n};\n","import { logError } from '@amzn/apejs-instrumentation/src/metrics/logging.js';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport type { ClientMessageToHost } from '@/components/messenger.js';\nimport type { CommonSupportedCommands } from '@/host/api-client/CommonSupportedCommands.js';\nimport type { MobileSupportedCommands } from '@/host/api-client/MobileSupportedCommands.js';\n\nexport type ToHostCommandType = keyof CommonSupportedCommands | keyof MobileSupportedCommands;\n\nexport class ClientMessageSender {\n    constructor(\n        private o: AdDetails,\n        private messagePort: MessagePort,\n    ) {}\n\n    sendMessage = <T extends (...args: any) => any>(command: ToHostCommandType, data?: Parameters<T>[1]) => {\n        const msg: ClientMessageToHost = {\n            command: command,\n            adDetails: this.o,\n            payload: data || {},\n        };\n\n        try {\n            this.messagePort.postMessage(msg);\n        } catch (ex) {\n            logError('Post Message error', ex as Error);\n        }\n    };\n}\n","export const btr = {\n    set: (element: HTMLElement, value: boolean): void => {\n        element.dataset.isBtr = String(value);\n    },\n    get: (element: HTMLElement): boolean => {\n        return element.dataset.isBtr === String(true);\n    },\n};\n","/**\n * Possible status codes indicating the evaluation result of a creative's rendering.\n */\nimport { btr } from './btr.js';\n\nexport type Code = 'BEGIN_TO_RENDER' | 'ERROR' | 'NO_CREATIVE';\n\n/**\n * Represents the response structure for evaluating whether a creative has begun to render.\n */\nexport interface CreativeBeginToRenderResponse {\n    /** Indicates whether the creative has begun to render successfully. */\n    success: boolean;\n\n    /** The status code indicating the result of the evaluation. */\n    code: Code;\n}\n\n/**\n * Evaluates whether a creative inside the provided container has begun to render.\n * This is determined by checking the BTR dataset flag or if any visible images within the container have loaded.\n *\n * @param creativeContainer - The HTML element containing the creative.\n * @returns A response indicating whether rendering has begun.\n */\nexport const evaluateCreativeBeginToRender = (creativeContainer: HTMLElement): CreativeBeginToRenderResponse => {\n    if (btr.get(creativeContainer)) {\n        return { success: true, code: 'BEGIN_TO_RENDER' };\n    }\n\n    const images = Array.from(creativeContainer.querySelectorAll('img')).filter(\n        (x) => getComputedStyle(x).display !== 'none',\n    );\n    return evaluateAnyImageLoaded(images);\n};\n\n/**\n * Evaluates whether any image in the provided list has successfully loaded.\n *\n * The function checks if at least one image is fully loaded (i.e., it is marked as complete\n * and has non-zero dimensions). If no images are present, it returns `NO_CREATIVE`.\n * If at least one image loads successfully, it returns `BEGIN_TO_RENDER`.\n * If all images fail to load, it returns `ERROR`.\n *\n * @param images - An array of HTML image elements to evaluate.\n * @returns A response indicating whether rendering has begun, no creative was found, or an error occurred.\n */\nconst evaluateAnyImageLoaded = (images: HTMLImageElement[]): CreativeBeginToRenderResponse => {\n    if (images.length === 0) {\n        return { success: false, code: 'NO_CREATIVE' };\n    }\n\n    return images.some((img) => img.complete && img.naturalWidth > 0 && img.naturalHeight > 0)\n        ? { success: true, code: 'BEGIN_TO_RENDER' }\n        : { success: false, code: 'ERROR' };\n};\n","declare global {\n    // oxlint-disable-next-line\n    interface Window extends WeblabsWindow {}\n}\n\nexport type WeblabTreatment = `t${number}`;\n\nexport type AllWeblabTreatment = WeblabTreatment | 'c';\n\nexport interface WeblabsWindow {\n    renderingWeblabs?: { [key: string]: string };\n}\n\nexport interface Weblab {\n    is(treatment: WeblabTreatment): boolean;\n    isInTreatment(): boolean;\n    getTreatment(): AllWeblabTreatment;\n}\n\nexport const createWeblab = (weblabsWindow: WeblabsWindow, prefix: string): Weblab => {\n    const weblabTreatment = (): AllWeblabTreatment =>\n        weblabsWindow?.renderingWeblabs?.[prefix]?.toLowerCase() as AllWeblabTreatment;\n\n    return {\n        is(treatment: WeblabTreatment): boolean {\n            return weblabTreatment() === treatment;\n        },\n        isInTreatment(): boolean {\n            return !!weblabTreatment() && weblabTreatment() !== 'c';\n        },\n        getTreatment(): AllWeblabTreatment {\n            return weblabTreatment() ?? 'c';\n        },\n    };\n};\n\n/*\n * Used for gating IN art event styling\n * @link https://weblab.amazon.com/wl/ADPT_SF_HOMEPAGE_ART_THEMING_1298909\n */\nexport const ADPT_SF_HOMEPAGE_ART_THEMING = () => createWeblab(window, 'ADPT_SF_HOMEPAGE_ART_THEMING_1298909');\n\n/*\n * Used for sampling metrics logging at a low rate\n * @link https://weblab.amazon.com/wl/ADPT_SF_LOW_RATE_METRIC_LOGGING_1256362\n */\nexport const ADPT_SF_LOW_RATE_METRIC_LOGGING = () => createWeblab(window, 'ADPT_SF_LOW_RATE_METRIC_LOGGING_1256362');\n\n/**\n * Used to enable new retail tracking with the JRS test painter.\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_CLICK_TRACKING_PAINTER_TEST_1259727\n */\nexport const CLICK_TRACKING_PAINTER_TEST = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_CLICK_TRACKING_PAINTER_TEST_1259727');\n\n/**\n * Used to enable viewability-based impression pixel firing for CA, JP, and UK marketplaces.\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_VIEW_RATE_EXPERIMENT_1289633\n */\nexport const VIEW_RATE_EXPERIMENT = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_VIEW_RATE_EXPERIMENT_1289633');\n\n/**\n * Used to control timeout for placement viewability of Stores View Rate experiment in ES and FR marketplaces.\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_VIEW_RATE_EXPERIMENT_TIMEOUT_1373183\n */\nexport const VIEW_RATE_EXPERIMENT_TIMEOUT = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_VIEW_RATE_EXPERIMENT_TIMEOUT_1373183');\n\n/**\n * Used to disable user agent access for creatives\n * @link https://shepherd.a2z.com/issues/e4e8cd86-419a-4e1a-96ff-b20a6615b8b5\n */\nexport const DISABLE_USER_AGENT_WEBLAB = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_DISABLE_USER_AGENT_1326744');\n\n/**\n * Used to enable new viewability tracker implementation\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_NEW_VIEWABILITY_TRACKER_1354300\n */\nexport const NEW_VIEWABILITY_TRACKER_WEBLAB = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_NEW_VIEWABILITY_TRACKER_1354300');\n\n/**\n * Used to enable LightFrames on all eligible placement\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_LIGHT_ADS_EVERYWHERE_1362485\n */\nexport const LIGHT_ADS_EVERYWHERE_WEBLAB = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_LIGHT_ADS_EVERYWHERE_1362485');\n\n/**\n * Used to enable iframe ready retry mechanism for host message receiver\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_IFRAME_READY_RETRY_1374491\n */\nexport const IFRAME_READY_RETRY_WEBLAB = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_IFRAME_READY_RETRY_1374491');\n\n/**\n * Used to disable window.top\n * @link https://weblab.amazon.com/wl/APM_STORES_JPS_JRS_SAFEFRAME_DISABLE_POSTMESSAGE_1327371\n */\nexport const DISABLE_POSTMESSAGE_WEBLAB = () =>\n    createWeblab(window, 'APM_STORES_JPS_JRS_SAFEFRAME_DISABLE_POSTMESSAGE_1327371');\n","export const API_KEY: string = 'aUAZqFtiIp6VxqpW3coqZ2JdZnV3RN9S8yKMRIdJ';\n","import { API_KEY } from '@/components/metrics/awsMetricLoggerApiKey.js';\n\nexport const METRICS_ENDPOINT = 'https://qdbx3pbnx6veby23pzgaowu3q40tmmrr.lambda-url.us-east-1.on.aws';\nexport const STORAGE_KEY = 'APE_CW_METRICS';\nexport const BATCH_SIZE = 10;\n\nexport type PostMetricDTO = {\n    metrics: Metric[];\n    xApiKey: string;\n};\n\nexport type Metric = {\n    metricName: string;\n    timestamp: number;\n    value: number;\n    dimensions: Record<string, string>;\n};\n\nlet unloadHookRegistered = false;\n\n// Used for testing\nexport const resetUnloadHook = (): void => {\n    unloadHookRegistered = false;\n};\n\nexport const logMetric = (metric: Metric): void => {\n    if (!unloadHookRegistered) {\n        window.addEventListener('beforeunload', () => flushAndClear());\n        unloadHookRegistered = true;\n    }\n\n    const cache = getCache();\n    cache.push(metric);\n\n    if (cache.length >= BATCH_SIZE) {\n        flushCache(cache);\n    } else {\n        updateCache(cache);\n    }\n};\n\nconst getCache = (): Metric[] => {\n    const data = localStorage.getItem(STORAGE_KEY);\n    if (!data) return [];\n    try {\n        return JSON.parse(data) as Metric[];\n    } catch {\n        return [];\n    }\n};\n\nconst flushCache = (metrics: Metric[]): void => {\n    navigator.sendBeacon(METRICS_ENDPOINT, JSON.stringify(toPostMetricDTO(metrics)));\n    localStorage.removeItem(STORAGE_KEY);\n};\n\nconst toPostMetricDTO = (metrics: Metric[]): PostMetricDTO => ({\n    metrics: metrics,\n    xApiKey: API_KEY,\n});\n\nconst updateCache = (metrics: Metric[]): void => {\n    localStorage.setItem(STORAGE_KEY, JSON.stringify(metrics));\n};\n\nconst flushAndClear = (): void => {\n    const cache = getCache();\n    if (cache.length > 0) {\n        flushCache(cache);\n    }\n};\n","import type { Metric } from '@/components/metrics/awsMetricBatcher.js';\nimport { logMetric } from '@/components/metrics/awsMetricBatcher.js';\n\n/**\n * logMetric(), but ensure that the same metricName is only logged once per page load.\n */\nexport const logMetricOnce = (metric: Metric): void => {\n    if (!window.APE_SF) {\n        return;\n    }\n\n    // Initlialize the store if it doesn't exist\n    const store = (window.APE_SF.loggedMetricNames ??= new Set<string>());\n\n    if (store.has(metric.metricName)) {\n        return;\n    }\n\n    store.add(metric.metricName);\n\n    logMetric(metric);\n};\n","import type { AdDetails } from '@amzn/safeframe-model';\nimport type { LightAdDetails } from '@amzn/safeframe-model';\n\nimport type { Metric } from '@/components/metrics/awsMetricBatcher.js';\nimport { logMetric } from '@/components/metrics/awsMetricBatcher.js';\nimport { ADPT_SF_LOW_RATE_METRIC_LOGGING } from '@/components/weblabs.js';\n\nimport { logMetricOnce } from './logMetricOnce.js';\n\ntype MetricInputBase = {\n    /**\n     * The name of the metric to log. Use colon (:) to separate metric components. E.g., \"asset:load:timing\"\n     */\n    metricName: string;\n    /**\n     * Number of occurrences to log. Defaults to 1.\n     */\n    count?: number;\n    /**\n     * Additional dimensions to add to the metric. These will be merged with the default dimensions.\n     */\n    additionalDimensions?: Record<string, string>;\n    /**\n     * Whether the metric should only be logged once per page load\n     */\n    once?: boolean;\n};\n\ntype MetricInputSF = MetricInputBase & {\n    adDetails: AdDetails;\n};\n\ntype MetricInputLA = MetricInputBase & {\n    lightAdDetails: LightAdDetails;\n};\n\n/**\n * @deprecated This is not live yet. Don't use.\n * SIM: https://sim.amazon.com/issues/CPP-39529\n */\nexport const logLowRateMetricSF = ({\n    metricName,\n    adDetails,\n    count = 1,\n    additionalDimensions = {},\n    once = false,\n}: MetricInputSF): void => {\n    if (ADPT_SF_LOW_RATE_METRIC_LOGGING().is('t1')) {\n        const logFn = once ? logMetricOnce : logMetric;\n        logFn(toMetric(metricName, count, toSFDimensions(adDetails, additionalDimensions)));\n    }\n};\n\n/**\n * @deprecated This is not live yet. Don't use.\n * SIM: https://sim.amazon.com/issues/CPP-39529\n */\nexport const logLowRateMetricLA = ({\n    metricName,\n    lightAdDetails,\n    count = 1,\n    additionalDimensions = {},\n}: MetricInputLA): void => {\n    if (ADPT_SF_LOW_RATE_METRIC_LOGGING().is('t1')) {\n        logMetric(toMetric(metricName, count, toLADimensions(lightAdDetails, additionalDimensions)));\n    }\n};\n\nconst toMetric = (metricName: string, count: number, dimensions: Record<string, string>): Metric => ({\n    metricName: metricName,\n    timestamp: new Date().getTime(),\n    value: count,\n    dimensions: dimensions,\n});\n\nconst toSFDimensions = (adDetails: AdDetails, additionalDimensions: Record<string, string>): Record<string, string> => {\n    return {\n        app: 'SF',\n        siteName: adDetails.siteName,\n        slotName: adDetails.slotName,\n        pageType: adDetails.pageType,\n        placementId: adDetails.placementId,\n        mediaType: adDetails.mediaType,\n        programId: adDetails.adCreativeMetaData?.adProgramId,\n        creativeTemplateName: adDetails.adCreativeMetaData?.adCreativeTemplateName,\n        deviceType: adDetails.deviceType,\n        ...additionalDimensions,\n    };\n};\n\nconst toLADimensions = (\n    adDetails: LightAdDetails,\n    additionalDimensions: Record<string, string> | undefined,\n): Record<string, string> => {\n    return {\n        app: 'LA',\n        siteName: adDetails.siteName,\n        slotName: adDetails.slotName,\n        pageType: adDetails.pageType,\n        placementId: adDetails.placementId,\n        mediaType: adDetails.videoCreative ? 'V' : 'D',\n        programId: adDetails.adCreativeMetaData?.adProgramId,\n        creativeTemplateName: adDetails.adCreativeMetaData?.adCreativeTemplateName,\n        deviceType: adDetails.deviceType,\n        ...additionalDimensions,\n    };\n};\n","import type { Creative } from '@/light-ad/domain/model/creative.js';\n\nimport type { FirePixel } from './firePixel.js';\nimport type { PixelIdentifier } from './pixelIdentifiers.js';\nimport type { PixelUrlGenerator } from './pixelUrlGenerator.js';\nimport type { PixelLogger } from './services/pixelLogger.js';\n\nconst requestOptions: RequestInit = { keepalive: true, mode: 'no-cors' } as const;\n\n/**\n * TODO: Update/Clean up the Placement type\n * SIM: https://sim.amazon.com/issues/CPP-40575\n */\nexport type Placement = {\n    readonly id: string;\n    readonly name: string;\n    readonly div: HTMLElement;\n    readonly deviceType: string;\n    readonly creative?: Creative;\n};\n\nexport type LoggingContext = {\n    aaxProgramId: number;\n};\n\nexport class Pixel implements FirePixel {\n    protected isFired: boolean = false;\n\n    constructor(\n        private readonly url: string,\n        private readonly loggingContext: LoggingContext,\n        private readonly generatePixelUrl: PixelUrlGenerator,\n        private readonly pixelIdentifier: PixelIdentifier,\n        private readonly pixelLogger: PixelLogger,\n        private readonly urls3p: string[] = [],\n    ) {}\n\n    public async fire(placement: Placement): Promise<void> {\n        if (this.isFired) return;\n        await fetch(this.generatePixelUrl(this.url, placement), requestOptions);\n        placement.div.appendChild(this.pixel(placement));\n        this.isFired = true;\n        this.pixelLogger(this.pixelIdentifier, this.loggingContext, placement);\n\n        // Do not await for 3P URLs as rendering the ad doesn't depend on successful firing\n        this.urls3p.forEach((url3p) => fetch(url3p, requestOptions));\n    }\n\n    /**\n     * This pixel is used by the UI Tests\n     * No src is set, as the pixel is fired by a fetch\n     */\n    private pixel = (placement: Placement): HTMLImageElement => {\n        const pixel = document.createElement('img');\n        pixel.id = `${this.pixelIdentifier.testId}_${placement.name}`;\n        pixel.style.display = 'none';\n        pixel.setAttribute('pixel-url', this.generatePixelUrl(this.url, placement));\n        return pixel;\n    };\n}\n","export type PixelIdentifier = {\n    readonly testId: string;\n    readonly csmLogId: string;\n};\n\nexport const BTR_IDENTIFIER: PixelIdentifier = { testId: 'ape_btr_impression', csmLogId: 'imp:btr' } as const;\nexport const IMPRESSION_IDENTIFIER: PixelIdentifier = { testId: 'ape_impression', csmLogId: 'imp:cod' } as const;\nexport const MEASURABILITY_IDENTIFIER: PixelIdentifier = { testId: 'ape_measurability', csmLogId: 'imp:atf' } as const;\nexport const SKAN_IMPRESSION_IDENTIFIER: PixelIdentifier = { testId: 'ape_impression', csmLogId: 'imp:skan' } as const;\nexport const SKAN_VIEW_IDENTIFIER: PixelIdentifier = { testId: 'skan_view_pixel', csmLogId: 'view:skan' } as const;\nexport const IAB_VIEWABILITY_IDENTIFIER: PixelIdentifier = {\n    testId: 'ape_viewability_iab',\n    csmLogId: 'view:iab',\n} as const;\n","import {\n    incrementCsmCounter,\n    incrementCsmPlacementCounter,\n} from '@amzn/apejs-instrumentation/src/metrics/csm/counter.js';\n\nimport type { LoggingContext, Placement } from '../pixel.js';\nimport type { PixelIdentifier } from '../pixelIdentifiers.js';\n\nexport interface PixelLogger {\n    (pixelIdentifier: PixelIdentifier, loggingContext: LoggingContext, placement: Placement): void;\n}\n\nexport const logPixelFired =\n    (\n        csmCounter: typeof incrementCsmCounter = incrementCsmCounter,\n        csmPlacementCounter: typeof incrementCsmPlacementCounter = incrementCsmPlacementCounter,\n    ): PixelLogger =>\n    (pixelIdentifier, loggingContext, placement) => {\n        csmCounter(`pixel:${pixelIdentifier.csmLogId}`);\n        csmPlacementCounter(`pixel:${pixelIdentifier.csmLogId}`, placement);\n        csmCounter(`pixel:${pixelIdentifier.csmLogId}:${loggingContext.aaxProgramId}`);\n        csmCounter(`pixel:${pixelIdentifier.csmLogId}:device:${placement.deviceType?.toLowerCase()}`);\n    };\n","/**\n * measurementMethod will be an enum used for reporting purposes with following possible values\n *  * btr_client\n *  * btr_server\n *  * cod_client\n *  * cod_server\n *  * coi_client\n *  * coi_server\n *  * unknown (default option)\n * cod = Count on download: Creative html/script/tag/assets are requested by the client device.\n * coi = Count on Insertion: Represents counting at time of won bid / ad serve prior to download request by client.\n * btr = Begin to render: Creative assets are loaded and begin to render\n *\n */\nexport const BEGIN_TO_RENDER_CLIENT = 'btr_client' as const;\nexport const COUNT_ON_DOWNLOAD_CLIENT = 'cod_client' as const;\n\nexport type MEASUREMENT_METHODS = typeof BEGIN_TO_RENDER_CLIENT | typeof COUNT_ON_DOWNLOAD_CLIENT;\n","const EMPTY_OBJECT_STRINGIFIED = '{}' as const;\nconst EMPTY_STRING = '' as const;\n\n/**\n * This function adds a query parameter to the given URL where the value is a JSON.\n * The most common use-case is addition of `publisherJSON` to AAX URLs. eg: https://evergreen.corp.amazon.com/aax-hub/apis/bid-api/xsp/#impression\n * If the existing URL already contains this parameter key, the two JSONs are merged based on the top-level keys.\n * In case of a conflict, priority is given to the new JSON.\n *\n * eg:\n * 1. If url contains json {\"key1\": \"value1\"}, and queryParamValueObject contains {\"key1\":\"value2\"}, priority is given to queryParamValueObject.\n *    Final json is {\"key1\":\"value2\"}\n * 2. If url contains json {\"key1\": \"value1\"}, and queryParamValueObject contains {\"key2\":\"value2\"}, JSONs are merged.\n *    Final json is {\"key1\":\"value1\", \"key2\":\"value2\"}\n *\n * @param {string} url - URL where query param needs to be added.\n * @param {string} queryParamKey - key of query param that needs to be added.\n * @param {Object} queryParamValueObject - value of query param that needs to be added.\n * @returns {string} URL with query param added.\n * @throws Error if invalid inputs are provided.\n **/\nexport const addJSONQueryParamToURL = (\n    url: string,\n    queryParamKey: string,\n    queryParamValueObject: { [key: string]: any },\n): string => {\n    if (queryParamKey === EMPTY_STRING) {\n        throw new Error(\n            'Invalid queryParamKey input to addJSONQueryParamToURL: ' +\n                JSON.stringify({ queryParamKey: queryParamKey }),\n        );\n    }\n    const urlObject = new URL(url);\n    const pk = urlObject.searchParams.get(queryParamKey);\n    const existingJSONString = pk ? pk : EMPTY_OBJECT_STRINGIFIED;\n    const existingJSONObject = JSON.parse(existingJSONString);\n    const mergedJSONObject = Object.assign(existingJSONObject, queryParamValueObject);\n    urlObject.searchParams.set(queryParamKey, JSON.stringify(mergedJSONObject));\n    return urlObject.toString();\n};\n","// Utility Functions used by both Client and Server\nimport type {} from '@amzn/amazon-ui-page-ts';\n\nexport const safeFunctionWrapper = (\n    handler: (...safeArgs: any[]) => void,\n    errorHandler?: (msg: string, ex?: any) => void,\n    errorMessage?: string,\n): any => {\n    return (...args: any[]) => {\n        try {\n            handler(...args);\n        } catch (ex) {\n            errorHandler?.(errorMessage ? errorMessage : 'Error in handler', ex);\n        }\n    };\n};\n\n/**\n * Check if the given mediaType is video\n * @param {String} mediaType - mediaType value from AAX\n * @returns {Boolean} isVideo - True if mediaType is V\n */\nexport const isVideo = (mediaType: string): boolean => mediaType === 'V';\n\n// Below code is for utf_8 compliant versions of atob/btoa\n//M DN https://developer.mozilla.org/en-US/docs/Glossary/Base64#solution_2_%E2%80%93_rewriting_atob_and_btoa_using_typedarrays_and_utf-8\n\nexport const utf_8_atob = (base64: string): string => b64_to_utf8(base64);\nexport const utf_8_btoa = (js_text: string): string => utf8_to_b64(js_text);\n\nconst base64TestRegexp = /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$/;\n/**\n * @deprecated Remove once GPAT changes that only send text have been rolled out\n */\nconst isBase64 = (stringToTest: string) => base64TestRegexp.test(stringToTest);\n/**\n * @deprecated Remove once GPAT changes that only send text have been rolled out\n */\nexport const convertToStringIfBase64 = (stringToTest: string) =>\n    isBase64(stringToTest) ? utf_8_atob(stringToTest) : stringToTest;\n\nexport const convertToBase64IfString = (stringToTest: string) =>\n    isBase64(stringToTest) ? stringToTest : utf8_to_b64(stringToTest);\n\n// We use unescape even though not recommended due to performance and code size\nconst utf8_to_b64 = (utf8: string): string => {\n    return btoa(unescape(encodeURIComponent(utf8)));\n};\n\nconst b64_to_utf8 = (base64: string): string => {\n    return decodeURIComponent(escape(atob(base64)));\n};\n\nexport const isEmptyObject = (obj?: object) => {\n    return obj && Object.keys(obj).length === 0 && obj.constructor === Object;\n};\n\n// Remove when https://issues.amazon.com/issues/V1533734779 is resolved.\nexport const removeAAXPayloadFromUrl = (url: string): string => {\n    if (!url) {\n        return url;\n    }\n    // oxlint-disable-next-line no-template-curly-in-string\n    return url.split('&c=${AAX_PAYLOAD}').join('');\n};\n","import { COUNT_ON_DOWNLOAD_CLIENT } from '@/client/MEASUREMENT_METHODS.js';\n\nimport { PUBLISHER_JSON_KEY } from '../../aax/aax.js';\nimport { addJSONQueryParamToURL } from '../../urlQueryParams/addJSONQueryParamToURL.js';\nimport type { PixelUrlGenerator } from '../pixelUrlGenerator.js';\n\nexport const generateImpressionPixelUrl: PixelUrlGenerator = (url: string): string => {\n    const isPaets = url.includes('.paets.');\n    return addJSONQueryParamToURL(\n        url,\n        PUBLISHER_JSON_KEY,\n        isPaets ? {} : { measurementMethod: COUNT_ON_DOWNLOAD_CLIENT },\n    );\n};\n","import { createObstructionDetectionService } from '@amzn/creative-obstruction-detection/src/obstructionDetectionServiceImpl.js';\nimport type { AdDetails, DeviceType, LightAdDetails, MediaType, SKAdNetwork } from '@amzn/safeframe-model';\n\nimport type { FirePixelValidator } from '@/components/pixels/services/firePixelValidator.ts';\nimport type { ViewPixel } from '@/components/pixels/viewPixel.js';\n\nimport { NEW_VIEWABILITY_TRACKER_WEBLAB } from '../weblabs.js';\nimport { MRCObstructionViewPixel } from './mrcObstructionViewPixel.js';\nimport type { LoggingContext } from './pixel.js';\nimport { Pixel } from './pixel.js';\nimport {\n    BTR_IDENTIFIER,\n    IAB_VIEWABILITY_IDENTIFIER,\n    IMPRESSION_IDENTIFIER,\n    MEASURABILITY_IDENTIFIER,\n} from './pixelIdentifiers.js';\nimport { logPixelFired } from './services/pixelLogger.js';\nimport { createViewabilityService } from './services/viewabilityServiceImpl.js';\nimport { createVisibiltyChangeService } from './services/visibilityChangeService.js';\nimport { SkanImpressionPixel } from './skanImpressionPixel.js';\nimport { SkanViewPixel } from './skanViewPixel.js';\nimport { generateBtrPixelUrl } from './urlGenerators/btrPixelUrlGenerator.js';\nimport { generateImpressionPixelUrl } from './urlGenerators/impressionPixelUrlGenerator.js';\nimport { generateMeasurabilityPixelUrl } from './urlGenerators/measurabilityPixelUrlGenerator.js';\nimport { generateMrcObstructionViewPixelUrl } from './urlGenerators/mrcObstructionViewPixelUrlGenerator.js';\nimport type { ViewabilityStandard } from './viewabilityStandards.js';\nimport { VIEWABILITY_STANDARDS } from './viewabilityStandards.js';\nimport { createViewabilityTracker } from './viewabilityTrackerImpl.js';\n\nexport type PixelInfo = {\n    aaxImpPixelUrl: string;\n    imp3pUrls?: string[];\n    aaxInstrPixelUrl: string;\n    abpAcceptable: string;\n    abpStatus: string;\n    btrPixelUrl?: string;\n    skAdNetwork?: SKAdNetwork;\n    loggingContext: LoggingContext;\n};\n\nexport const mapToBtrPixel = ({ btrPixelUrl, loggingContext }: PixelInfo): Pixel | undefined => {\n    return btrPixelUrl\n        ? new Pixel(btrPixelUrl, loggingContext, generateBtrPixelUrl, BTR_IDENTIFIER, logPixelFired())\n        : undefined;\n};\n\nexport const mapToImpressionPixel = ({ aaxImpPixelUrl, imp3pUrls, loggingContext }: PixelInfo): Pixel =>\n    new Pixel(\n        aaxImpPixelUrl,\n        loggingContext,\n        generateImpressionPixelUrl,\n        IMPRESSION_IDENTIFIER,\n        logPixelFired(),\n        imp3pUrls,\n    );\n\nexport const mapToMeasurabilityPixel = ({ aaxInstrPixelUrl, loggingContext }: PixelInfo): Pixel =>\n    new Pixel(\n        aaxInstrPixelUrl,\n        loggingContext,\n        generateMeasurabilityPixelUrl,\n        MEASURABILITY_IDENTIFIER,\n        logPixelFired(),\n    );\n\nexport const createIabViewPixel = (\n    mediaType: MediaType,\n    htmlElement: HTMLElement,\n    pixelInfo: PixelInfo,\n    deviceType: DeviceType,\n    firePixelValidator: () => FirePixelValidator,\n    adDetails?: AdDetails,\n    lightAdDetails?: LightAdDetails,\n): ViewPixel => {\n    if (mediaType === 'V') {\n        return createMrcViewPixel(\n            pixelInfo,\n            VIEWABILITY_STANDARDS.IAB_VIDEO,\n            firePixelValidator(),\n            adDetails,\n            lightAdDetails,\n        );\n    } else if (isDesktop(deviceType) && isLargeAd(htmlElement)) {\n        return createMrcViewPixel(\n            pixelInfo,\n            VIEWABILITY_STANDARDS.IAB_LARGE_DISPLAY,\n            undefined,\n            adDetails,\n            lightAdDetails,\n        );\n    } else {\n        return createMrcViewPixel(pixelInfo, VIEWABILITY_STANDARDS.IAB_DISPLAY, undefined, adDetails, lightAdDetails);\n    }\n};\n\nconst isDesktop = (deviceType: DeviceType): boolean => deviceType === 'DESKTOP';\n\n/**\n * Large IAB view pixel is used to measure the time the ad is visible on the screen.\n * An ad can be considered a large ad if it is of 242,500 pixels are larger\n * @link https://www.iab.com/wp-content/uploads/2015/06/MRC-Viewable-Ad-Impression-Measurement-Guideline.pdf\n */\nconst isLargeAd = (htmlElement: HTMLElement): boolean => getSizeOfElementInTotalPixels(htmlElement) >= 242500;\n\nconst getSizeOfElementInTotalPixels = (htmlElement: HTMLElement): number =>\n    htmlElement.getBoundingClientRect().height * htmlElement.getBoundingClientRect().width;\n\nconst createMrcViewPixel = (\n    pixelInfo: PixelInfo,\n    standard: ViewabilityStandard,\n    validator?: FirePixelValidator,\n    adDetails?: AdDetails,\n    lightAdDetails?: LightAdDetails,\n): ViewPixel => {\n    const pixel = new Pixel(\n        pixelInfo.aaxInstrPixelUrl,\n        pixelInfo.loggingContext,\n        generateMrcObstructionViewPixelUrl(standard),\n        IAB_VIEWABILITY_IDENTIFIER,\n        logPixelFired(),\n    );\n\n    if (NEW_VIEWABILITY_TRACKER_WEBLAB().is('t1')) {\n        return createViewabilityTracker(\n            [pixel],\n            standard,\n            createViewabilityService(createObstructionDetectionService()),\n            validator ? [validator] : [],\n            adDetails,\n            lightAdDetails,\n        );\n    } else {\n        return new MRCObstructionViewPixel(\n            pixel,\n            standard,\n            createVisibiltyChangeService(),\n            createViewabilityService(createObstructionDetectionService()),\n            validator,\n            adDetails,\n            lightAdDetails,\n        );\n    }\n};\n\nexport const mapToSkanImpressionPixel = (pixelInfo: PixelInfo): SkanImpressionPixel | undefined => {\n    if (pixelInfo.skAdNetwork) {\n        return new SkanImpressionPixel(pixelInfo.loggingContext, pixelInfo.skAdNetwork, logPixelFired());\n    }\n    return undefined;\n};\n\nexport const mapToSkanViewPixel = (pixelInfo: PixelInfo): ViewPixel | undefined => {\n    if (pixelInfo.skAdNetwork) {\n        const skanPixel = new SkanViewPixel(pixelInfo.loggingContext, logPixelFired(), pixelInfo.skAdNetwork);\n        return new MRCObstructionViewPixel(\n            skanPixel,\n            VIEWABILITY_STANDARDS.SKAN,\n            createVisibiltyChangeService(),\n            createViewabilityService(createObstructionDetectionService()),\n            undefined,\n        );\n    }\n    return undefined;\n};\n","import type { Pixel } from '@/components/pixels/pixel.js';\nimport type { Placement } from '@/components/pixels/pixel.js';\nimport { btr } from '@/components/pixels/placementData.js';\nimport type { FirePixelValidator } from '@/components/pixels/services/firePixelValidator.js';\nimport type { ViewabilityService } from '@/components/pixels/services/viewabilityService.js';\nimport { createViewabilityTracker } from '@/components/pixels/viewabilityTrackerImpl.js';\nimport { VIEW_RATE_EXPERIMENT, VIEW_RATE_EXPERIMENT_TIMEOUT } from '@/components/weblabs.js';\n\n/**\n * TODO: Clean up View Rate Experiment\n * https://sim.amazon.com/issues/ASPEN-9994\n */\nexport interface ViewRateExperimentPixels {\n    impressionPixel: Pixel;\n    btrPixel?: Pixel;\n    measurabilityPixel: Pixel;\n}\n\nconst weblabTreatmentToThreshold: Record<string, number> = {\n    c: 0,\n    t1: 0.1,\n    t2: 0.2,\n    t3: 0.3,\n    t4: 0.4,\n    t5: 0.5,\n};\n\nconst weblabTreatmentToTimeout: Record<string, number> = {\n    c: 0,\n    t1: 100,\n    t2: 200,\n    t3: 300,\n    t4: 400,\n    t5: 500,\n    t6: 600,\n    t7: 700,\n    t8: 800,\n    t9: 900,\n};\n\nexport const isViewRateExperimentEnabled = (aaxProgramId: number): boolean => {\n    return aaxProgramId !== 1004 && VIEW_RATE_EXPERIMENT().isInTreatment();\n};\n\nconst btrFirePixelValidator = (placement: Placement): FirePixelValidator => {\n    return {\n        shouldFirePixel(): boolean {\n            return btr.get(placement);\n        },\n    };\n};\n\nexport const trackViewRateExperiment = (\n    placement: Placement,\n    pixels: ViewRateExperimentPixels,\n    viewabilityService: ViewabilityService,\n): void => {\n    const viewabilityStandard = {\n        definition: '',\n        thresholdPercentage: weblabTreatmentToThreshold[VIEW_RATE_EXPERIMENT().getTreatment()],\n        thresholdTimeVisibleMs: weblabTreatmentToTimeout[VIEW_RATE_EXPERIMENT_TIMEOUT().getTreatment()],\n    };\n    // ViewabilityTracker for impression and measurability pixels\n    const impViewabilityTracker = createViewabilityTracker(\n        [pixels.impressionPixel, pixels.measurabilityPixel],\n        viewabilityStandard,\n        viewabilityService,\n        [],\n    );\n    impViewabilityTracker.track(placement);\n\n    // ViewabilityTracker for btrPixel\n    if (pixels.btrPixel) {\n        const btrViewabilityTracker = createViewabilityTracker(\n            [pixels.btrPixel],\n            viewabilityStandard,\n            viewabilityService,\n            [btrFirePixelValidator(placement)],\n        );\n        btrViewabilityTracker.track(placement);\n    }\n};\n","import { incrementCsmCounter } from '@amzn/apejs-instrumentation/src/metrics/csm/counter.js';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport { labelRendered, openModal } from '@/components/feedback.js';\nimport type { SfVideoContinuousPlaytimeEventDetail } from '@/components/pixels/services/videoFirePixelValidator.js';\nimport { SF_VIDEO_CONTINUOUS_PLAYTIME_SECONDS_EVENT } from '@/components/pixels/services/videoFirePixelValidator.js';\n\nimport type {} from '../../client/CommonSFSetup.js';\nimport { type LatencyMetricTypeData, type ViewPixelOptionsData } from '../../components/commands.js';\nimport type { GwVideoOrchestratorOptions } from '../../components/homepage/homepageVideoOrchestrator.js';\nimport { LOADED_HOST_SCOPE } from '../../components/metrics/latency-metric-type.js';\nimport { metricService } from '../../components/metrics/metric-service.js';\nimport type { PixelInfo } from '../../components/pixels/pixelMapper.js';\nimport { mapToImpressionPixel } from '../../components/pixels/pixelMapper.js';\nimport { getPlacement } from '../components/placement.js';\nimport { waitUntilReadyForTracking } from '../components/waitUntilReadyForTracking.js';\nimport type { HostContext } from '../context/HostContext.js';\nimport { changeSizeHandler } from './handlers/changeSizeHandler.js';\nimport { collapseSlotHandler } from './handlers/collapseSlotHandler.js';\nimport { sendEventCreativeBeginToRenderHandler } from './handlers/sendEventCreativeBeginToRenderHandler.js';\nimport { sendEventCreativeLoadedHandler } from './handlers/sendEventCreativeLoadedHandler.js';\nimport {\n    haveVideoAutoplayPermissionHandler,\n    releaseVideoAutoplayHandler,\n    requestVideoAutoplayHandler,\n} from './handlers/videoHandlers.js';\nimport type { HostMessageSender } from './hostMessageSender.js';\n\n// These are the commands that are supported by all the ad-serving platforms.\n// Do not add anything that you do not want to be run directly by the SF client javascript simply by receiving a message!\n// These are validated staticaly for literals on the client side but at runtime it is fair game\nexport class CommonSupportedCommands {\n    constructor(\n        protected readonly hms: HostMessageSender,\n        public hc: HostContext,\n    ) {}\n\n    changeSize = changeSizeHandler;\n\n    sendLatencyMetric = (adDetails: AdDetails, latencyMetric: LatencyMetricTypeData): void =>\n        sendLatencyMetricHandler(adDetails, latencyMetric);\n\n    /**\n     * Verified in use May 29 2025\n     * https://csm.amazon.com/#/rulelist/metric/474984\n     */\n    requestVideoAutoplay = (adDetails: AdDetails, data: GwVideoOrchestratorOptions) => {\n        incrementCsmCounter('common:supported:command:requestVideoAutoplay');\n        requestVideoAutoplayHandler(adDetails, data, this.hms);\n    };\n\n    /**\n     * Verified in use May 29 2025\n     * https://csm.amazon.com/#/rulelist/metric/474985\n     */\n    releaseVideoAutoplay = () => {\n        incrementCsmCounter('common:supported:command:releaseVideoAutoplay');\n        releaseVideoAutoplayHandler();\n    };\n\n    /**\n     * Verified in use May 29 2025\n     * https://csm.amazon.com/#/rulelist/metric/474986\n     */\n    haveVideoAutoplayPermission = (adDetails: AdDetails) => {\n        incrementCsmCounter('common:supported:command:haveVideoAutoplayPermission');\n        haveVideoAutoplayPermissionHandler(adDetails);\n    };\n\n    feedbackLabelRendered = (adDetails: AdDetails) =>\n        labelRendered({\n            id: adDetails.placementId,\n            name: adDetails.placementName,\n        });\n    feedbackOpenModal = (adDetails: AdDetails) => openModal(adDetails.adUnitWrapperId ?? adDetails.adUnitPlacementId);\n\n    collapseSlot = collapseSlotHandler;\n\n    /**\n     * Fires the COD impression pixel on the host side using the Light Ads logic\n     *\n     * @param {AdInfo} adInfo - Ad information object\n     */\n    sendEventAddedCreative = async (adDetails: AdDetails) => {\n        sendLatencyMetricHandler(adDetails, { latencyMetricType: LOADED_HOST_SCOPE, timestamp: new Date() });\n        await waitUntilReadyForTracking(adDetails);\n        await mapToImpressionPixel(getPixelInfo(adDetails)).fire({\n            id: adDetails.placementId,\n            name: adDetails.placementName,\n            div: getPlacement(adDetails),\n            deviceType: adDetails.deviceType,\n        });\n    };\n\n    /**\n     * Called when client sends domain event to signal\n     * creative has begun to render to fire BTR pixel\n     */\n    sendEventCreativeBeginToRender = sendEventCreativeBeginToRenderHandler;\n\n    /**\n     * Called when client sends domain event to start measureability & viewability\n     */\n    sendEventCreativeLoaded = async (adDetails: AdDetails, data: ViewPixelOptionsData) => {\n        await sendEventCreativeLoadedHandler(adDetails, data);\n    };\n\n    /**\n     * Called when client detects that the creative consists primarily of an image\n     * This helps avoid adding minHeight which can distort images when font size changes\n     */\n    resizeForImageOnlyTemplate = (adDetails: AdDetails) => getPlacement(adDetails).classList.add('is-image-oo');\n\n    /**\n     * Called when client send continuous playtime for video creatives.\n     */\n    sendSfVideoContinuousPlaytimeSeconds = (adDetails: AdDetails, data: SfVideoContinuousPlaytimeEventDetail) => {\n        const placement = getPlacement(adDetails);\n        const sfVideoContinuousPlaytimeSecondsEvent = new CustomEvent<SfVideoContinuousPlaytimeEventDetail>(\n            SF_VIDEO_CONTINUOUS_PLAYTIME_SECONDS_EVENT,\n            {\n                detail: data,\n            },\n        );\n        placement.dispatchEvent(sfVideoContinuousPlaytimeSecondsEvent);\n    };\n}\n\nconst sendLatencyMetricHandler = (adDetails: AdDetails, { latencyMetricType, timestamp }: LatencyMetricTypeData) => {\n    metricService().sendLatencyMetric({\n        latencyMetricType,\n        placementName: adDetails.placementName,\n        placementId: adDetails.placementId,\n        placementDivId: adDetails.adUnitPlacementId,\n        timestamp,\n    });\n};\n\nexport const getPixelInfo = (adDetails: AdDetails): PixelInfo => ({\n    aaxImpPixelUrl: adDetails.aaxImpPixelUrl,\n    aaxInstrPixelUrl: adDetails.aaxInstrPixelUrl,\n    abpAcceptable: adDetails.abpAcceptable,\n    abpStatus: adDetails.abpStatus ?? '-1',\n    btrPixelUrl: adDetails.btrPixelUrl,\n    skAdNetwork: adDetails.skAdNetwork,\n    loggingContext: {\n        aaxProgramId: Number(adDetails.adCreativeMetaData.adProgramId),\n    },\n});\n","import type { InternalSFClientAPI } from '@/client/InternalSFClientAPI.js';\n\n// Threshold for considering an image to be spanning the viewport (95%)\nconst VIEWPORT_COVERAGE_THRESHOLD = 0.95;\n\n// Threshold for considering text to be significant (num chars)\nconst SIGNIFICANT_TEXT_THRESHOLD = 75;\n\n// 1P image template ads generally have this class name\nconst AD_BACKGROUND_IMAGE_CLASS = 'ad-background-image';\n\n/**\n * Checks if an image has the 'ad-background-image' class\n */\nexport const hasBackgroundImageClass = (imgElement: HTMLImageElement): boolean =>\n    imgElement.classList.contains(AD_BACKGROUND_IMAGE_CLASS);\n\n/**\n * Checks if an image covers a significant portion of the viewport width\n */\nexport const isImageCoveringViewportWidth = (imgWidth: number): boolean =>\n    imgWidth / window.innerWidth >= VIEWPORT_COVERAGE_THRESHOLD;\n\n/**\n * Checks if the document has significant text content\n */\nexport const hasSignificantText = (): boolean => {\n    // get innerText and strip whitespace\n    const text = (document.documentElement.innerText ?? '').replace(/\\s/g, '');\n    return text.length > SIGNIFICANT_TEXT_THRESHOLD;\n};\n\n/**\n * Checks an array of images for one with the target className\n * @param images\n * @returns\n */\nexport const hasAnyImageWithAdBackgroundClass = (images: HTMLImageElement[]) =>\n    images.some((image) => image.classList.contains(AD_BACKGROUND_IMAGE_CLASS));\n\n/**\n * Returns the largest image based on area.\n */\nexport const hasLargeImage = (images: HTMLImageElement[]): boolean => {\n    for (const image of images) {\n        const rect = image.getBoundingClientRect();\n\n        // check to see if this image covers all/most of the viewport width\n        if (isImageCoveringViewportWidth(rect.width)) {\n            return true;\n        }\n    }\n\n    return false;\n};\n\n/**\n * Determines if the ad is an image template ad and sends appropriate message if needed\n */\nexport const isImageTemplateAd = (): boolean => {\n    // Find all images in the creative\n    const images = Array.from(document.querySelectorAll('img'));\n\n    // no images in the ad means it is not an image template\n    if (!images.length) return false;\n\n    // if any image has .ad-background-class, it is an image template\n    if (hasAnyImageWithAdBackgroundClass(images)) return true;\n\n    // if no large images (spans viewport width), it is not an image template\n    if (!hasLargeImage(images)) return false;\n\n    // if the ad has a full width image, but has a lot of text, likely not an image template\n    if (hasSignificantText()) return false;\n\n    // all conditions met, this is likely an image-only ad\n    return true;\n};\n\n/**\n * Checks to see if the creative consists primarily of an image that spans (or nearly spans)\n * the entire viewport. If so, sends a message to the host to indicate this is an image-only creative.\n */\nexport const checkAndResizeImageOnlyCreative = (internalAPI: InternalSFClientAPI): void => {\n    // Check if the creative is an image-only creative\n    if (isImageTemplateAd()) {\n        // If we found a large image and no significant text\n        internalAPI.resizeForImageOnlyTemplate();\n    }\n};\n","import { evaluateCreativeBeginToRender } from '@amzn/creative-rendering-monitor/src/creativeBTREvaluatorSync.js';\n\nimport type { MEASUREMENT_METHODS } from './MEASUREMENT_METHODS.js';\nimport { BEGIN_TO_RENDER_CLIENT, COUNT_ON_DOWNLOAD_CLIENT } from './MEASUREMENT_METHODS.js';\n\nexport const tryWaitForBTR = async (element: HTMLElement = document.body): Promise<MEASUREMENT_METHODS> => {\n    const btrEvaluationWaitTime = 75;\n    let elapsedTime = 0;\n    const intervalMs = 5;\n\n    return new Promise<MEASUREMENT_METHODS>((resolve) => {\n        const intervalId = setInterval(() => {\n            elapsedTime += intervalMs;\n\n            const response = evaluateCreativeBeginToRender(element);\n            if (response.success) {\n                clearInterval(intervalId);\n                resolve(BEGIN_TO_RENDER_CLIENT);\n            } else if (elapsedTime >= btrEvaluationWaitTime) {\n                clearInterval(intervalId);\n                resolve(COUNT_ON_DOWNLOAD_CLIENT);\n            }\n        }, intervalMs);\n    });\n};\n","import { creativeReplayId } from './render.js';\n\ntype FiredAttributes = 'iscomplete' | 'creativeLoad' | 'creativedomcontentloaded';\n\n// This is so we can tell from the DOM if the creative has triggered\n//  This is useful for UI testing and also interactive debugging\nexport const markScriptAsFired = (attr: FiredAttributes) =>\n    document.getElementById(creativeReplayId)?.setAttribute(attr, 'true');\n","import { incrementMarketCounter } from '@amzn/apejs-instrumentation/src/metrics/counters.js';\nimport type { CreativeRenderingValidators } from '@amzn/creative-rendering-validation/src/api/blankAdDetection.js';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport { logLowRateMetricSF } from '@/components/metrics/awsMetricLogger.js';\n\ndeclare global {\n    interface Window {\n        crv: CreativeRenderingValidators;\n    }\n}\n\nexport const validateCreativeRendering = (adDetails: AdDetails): void => {\n    const callBlankAdValidation = async () => {\n        if (typeof window?.crv?.detectAndReportBlankAd === 'function') {\n            clearInterval(intervalId);\n            try {\n                const result = await window.crv.detectAndReportBlankAd(document.body);\n                if (result) {\n                    incrementMarketCounter('blankadvalidation:failure');\n                    logLowRateMetricSF({\n                        metricName: 'blank:ad',\n                        adDetails: adDetails,\n                        additionalDimensions: {\n                            creativeId: adDetails.adCreativeMetaData.adCreativeId,\n                        },\n                    });\n                } else {\n                    incrementMarketCounter('blankadvalidation:success');\n                }\n            } catch (_err) {\n                incrementMarketCounter('blankadvalidation:error');\n            }\n        }\n    };\n\n    const intervalId = setInterval(callBlankAdValidation, 1000);\n};\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport type { InternalSFClientAPI } from '@/client/InternalSFClientAPI.js';\nimport type { EventsChannel } from '@/components/messageChannel/eventsChannel.js';\nimport { mapToImpressionPixel } from '@/components/pixels/pixelMapper.js';\nimport { isViewRateExperimentEnabled } from '@/components/viewRateExperimentUtil.js';\n\nimport { getPixelInfo } from '../host/api-client/CommonSupportedCommands.js';\nimport { checkAndResizeImageOnlyCreative } from './checkAndResizeImageOnlyCreative.js';\nimport { tryWaitForBTR } from './clientReporter.js';\nimport { generateSyntheticLoadEvent } from './CommonSFSetup.js';\nimport type { MEASUREMENT_METHODS } from './MEASUREMENT_METHODS.js';\nimport { BEGIN_TO_RENDER_CLIENT, COUNT_ON_DOWNLOAD_CLIENT } from './MEASUREMENT_METHODS.js';\nimport { markScriptAsFired } from './render.util.js';\nimport { validateCreativeRendering } from './validateCreativeRendering.js';\n\nexport const creativeReplayId = 'creativeReplayStatus';\nexport const creativeReplayCompleteEventName = 'creativeReplayComplete';\nconst fireEvent = `document.dispatchEvent(new CustomEvent(\"${creativeReplayCompleteEventName}\"));`;\n\nexport const getFinishProcessingEvent = (): string => `<script id=\"${creativeReplayId}\">${fireEvent}</script>`;\n\nexport const replayScriptTag = (adScript: HTMLScriptElement): void => {\n    const range = document.createRange();\n    range.selectNode(adScript);\n    const adScriptCopyDoc = range.createContextualFragment(adScript.outerHTML);\n    const adScriptCopy = adScriptCopyDoc.firstElementChild as HTMLScriptElement;\n    if (adScriptCopy.getAttribute('src')) {\n        // https://html.spec.whatwg.org/multipage/scripting.html#attr-script-async\n        // Need to explicity force async to false to skip https://html.spec.whatwg.org/multipage/scripting.html#script-processing-model\n        // https://hsivonen.fi/script-execution/\n        adScriptCopy.async = false;\n    } else {\n        const scriptText = adScript.innerHTML;\n        adScriptCopy.async = false;\n        adScriptCopy.setAttribute('src', `data:text/javascript;charset=UTF-8,${encodeURIComponent(scriptText)}`);\n    }\n    adScript.parentNode?.insertBefore(adScriptCopy, adScript.nextSibling);\n    adScript.parentNode?.removeChild(adScript);\n};\n\n/**\n * Replaces the contents of the document with the passed HTML string\n * @param htmlContent string of HTML to add\n */\nexport const writeHtmlToDocumentRoot = (htmlContent: string): void => {\n    // setting innerHtml drops the host element's attributes, ie <html lang=\"en\">\n    // setting the outerHtml solves this, but setting outerHtml on document.documentElement is forbidden by the spec\n    // supporting a target of document.documentElement is a must\n\n    // Funciton fails with strict equality\n    // oxlint-disable-next-line eqeqeq\n    if (document.documentElement == undefined) {\n        const html = document.createElement('html');\n        document.appendChild(html);\n    }\n    document.documentElement.innerHTML = htmlContent;\n\n    // options for getting attributes from the html string include DOMParser or regex, but performance is a concern\n    // https://developer.mozilla.org/en-US/docs/Web/API/Element/attributes#enumerating_elements_attributes\n};\n\n/**\n * Executes all of the descendant inline scripts of the passed element in the order in which they appear\n * via depth first, pre-order DOM tree traversal\n */\nexport const replayAllDescendantScriptsSerially = (containerElement: HTMLElement): void => {\n    // https://html.spec.whatwg.org/multipage/scripting.html#list-of-scripts-that-will-execute-in-order-as-soon-as-possible\n    // We cannot use createFragment because it is required to import in the body so we lose the HEAD/BODY/etc. tags\n    // So we use InnerHTML which will not execute the scripts but then dynamically recreate the script tags\n    // so that they will be executed (as they are not with innerHTML imported tags)\n    const adScripts = containerElement.querySelectorAll('script');\n    for (const adScript of adScripts) {\n        replayScriptTag(adScript);\n    }\n};\n\nexport const preCreativeWrite = (\n    internalAPI: InternalSFClientAPI,\n    o: AdDetails,\n    eventsChannel: EventsChannel,\n): void => {\n    eventsChannel.onPreCreativeWrite();\n\n    if (isViewRateExperimentEnabled(Number(o.adCreativeMetaData.adProgramId))) {\n        // Do nothing: delay firing of the COD Impression Pixel for Stores view rate experiment\n        return;\n    }\n\n    if (isFireImpInHostOverride(o) || o.firePixelsAfter) {\n        internalAPI.sendEventAddedCreative();\n    } else {\n        mapToImpressionPixel(getPixelInfo(o)).fire({\n            id: o.placementId,\n            name: o.placementName,\n            div: document.documentElement,\n            deviceType: o.deviceType,\n        });\n    }\n};\n\nexport const postCreativeWrite = async (\n    o: AdDetails,\n    internalAPI: InternalSFClientAPI,\n    eventsChannel: EventsChannel,\n) => {\n    // Since the initial loading event was fired when loading the messageport we need to simulate them\n    // for the creative\n    // TODO(https://sim.amazon.com/issues/CPP-38246) Wait for creative image resource loads in corner case\n    fireDOMContentLoadedEventForCreative();\n    // TODO(https://sim.amazon.com/issues/CPP-38245) Check if this can be moved earlier\n    fireLoadEventForCreativeSinceItWasAlreadyFiredUpon();\n\n    // isNoInventory is always false at this point\n    const measurementMethod: MEASUREMENT_METHODS = o.btrPixelUrl ? await tryWaitForBTR() : COUNT_ON_DOWNLOAD_CLIENT;\n    eventsChannel.onCreativeBeginToRender();\n\n    const isBtr = measurementMethod === BEGIN_TO_RENDER_CLIENT;\n    if (isBtr) {\n        internalAPI.sendEventCreativeBeginToRender();\n    }\n\n    internalAPI.sendEventCreativeLoaded({\n        isBtr,\n    });\n    validateCreativeRendering(o);\n\n    if (isMobile(o)) {\n        checkAndResizeImageOnlyCreative(internalAPI);\n    }\n};\n\nconst fireLoadEventForCreativeSinceItWasAlreadyFiredUpon = () => {\n    markScriptAsFired('creativeLoad');\n    generateSyntheticLoadEvent();\n};\nconst fireDOMContentLoadedEventForCreative = () => {\n    markScriptAsFired('creativedomcontentloaded');\n    document.dispatchEvent(new Event('DOMContentLoaded'));\n};\n\nconst isMobile = (adDetails: AdDetails): boolean => ['mweb', 'mshop'].includes(adDetails.deviceType?.toLowerCase());\n\n/**\n * Determines whether impression firing should be overridden to occur in the host rather than the client.\n * Hard-coded for skyscraper-2 slots to avoid firing impressions when the slot is `display:none`.\n *\n * @param o - The ad details for the current creative.\n * @returns `true` if the impression should be fired in the host.\n *\n * @remarks\n * Remove this when true bill on view is launched.\n * Cleanup SIM: {@link https://taskei.amazon.dev/tasks/CPP-46601}\n */\nconst isFireImpInHostOverride = ({ slotName }: AdDetails): boolean =>\n    slotName === 'auto-left-advertising-2' || slotName.endsWith('-ad-left-2');\n","import {\n    creativeReplayCompleteEventName,\n    getFinishProcessingEvent,\n    replayAllDescendantScriptsSerially,\n    replayScriptTag,\n    writeHtmlToDocumentRoot,\n} from '@/client/render.js';\n\nexport const writeCreativeToDOM = async (htmlContent: string): Promise<void> => {\n    const eventFired = waitForCreativeReplayComplete();\n    documentWriteImpl(htmlContent, getFinishProcessingEvent());\n    await eventFired;\n};\n\nconst waitForCreativeReplayComplete = (): Promise<void> =>\n    new Promise((resolve) => {\n        document.addEventListener(creativeReplayCompleteEventName, () => resolve(), { once: true });\n    });\n\n/**\n * Called by\n * 1. The SF render script to add the creative to the DOM\n * 2. The creative for further mutations to the DOM\n */\nexport const documentWriteImpl = (...text: string[]): void => {\n    const htmlContent = text\n        .filter((x) => !!x)\n        .map(String)\n        .join('');\n\n    // The below conditional checks if an inline script is running AND that document has not\n    // finished painting. In this case, document.write should append to the document immediately\n    // below that script, as described here: https://www.oreilly.com/library/view/javascript-the-definitive/0596000480/re204.html\n    // In all other cases we will replace the contents of the document with the string passed to document.write.\n    if (document.currentScript !== null) {\n        let currentElement: Element | null = document.currentScript;\n        currentElement.insertAdjacentHTML('afterend', htmlContent);\n\n        // Scripts do not execute when added via html string. Need to replay each script after the\n        // insertion point (via next sibling). If we used replayAll on the body, it would infinitely\n        // loop by replaying the script which called renderHTML in the first place.\n        currentElement = currentElement.nextElementSibling;\n        while (currentElement !== null) {\n            if (currentElement.tagName === 'SCRIPT') {\n                replayScriptTag(currentElement as HTMLScriptElement);\n            } else {\n                replayAllDescendantScriptsSerially(currentElement as HTMLElement);\n            }\n            currentElement = currentElement.nextElementSibling;\n        }\n    } else {\n        writeHtmlToDocumentRoot(htmlContent);\n        replayAllDescendantScriptsSerially(document.documentElement);\n    }\n};\n","const PLACEHOLDER_DEFAULT = '&pd_rd_plhdr=t';\n\n/**\n *  HTML entity examples:\n *      Symbols\n *          shortest: &lt;\n *          longest: &Omicron;\n *\n *      Numbers\n *          (0-31 are control characters)\n *          shortest: &#32;\n *          longest: &#8721;\n *\n *  Regular Expressions\n *      Entity Numbers: (&#(0-){2};)|(&#(a-z){3};)|(&#(a-z){4};)\n *      Entity Symbols: (&(a-z){2};)|(&(a-z){3};)|(&(a-z){4};)|(&(a-z){5};)|(&(a-z){6};)|(&(a-z){7};)\n */\nconst REGEX_MATCH = new RegExp(\n    /((&#\\d{2,4};)|(&[a-z]{2};)|(&[a-z]{3,7};)|(%[a-fA-F0-9]{2})|(\\W))pd_rd_plhdr(=|%3D)t((&#\\d{2,4};)|(&[a-z]{2,7};)|(%[a-fA-F0-9]{2})|(\\W))/,\n);\n\n/**\n * Indices must be updated if RegEx groups are modified.\n * Each left and right group has 10 subgroups.\n * String.prototype.match() call will return the results of 22 groups.\n * Main result of the left matching group will be at index 1, while\n * the primary result of the right group is stored at index 12.\n */\nconst LEFT_GROUP_INDEX = 1;\nconst MIDDLE_GROUP_INDEX = 7;\nconst RIGHT_GROUP_INDEX = 8;\nconst LEFT_GROUP_VALUE = '$' + LEFT_GROUP_INDEX;\nconst RIGHT_GROUP_VALUE = '$' + RIGHT_GROUP_INDEX;\n\n/**\n * Replaces placeholders in HTML content with a specified click tracker value.\n *\n * This function substitutes the placeholder `PLACEHOLDER_DEFAULT` (`&pd_rd_plhdr=t`) in the provided\n * HTML content with the given click tracker value. It handles cases where the placeholder is surrounded\n * by HTML entities or URL encoding, ensuring that the replacement respects the format of the surrounding content.\n *\n * @param {string} clickTracker - The replacement value for the placeholder.\n *   - If the value matches the default placeholder or is empty/whitespace, no replacement is performed.\n *   - HTML entities in the value are escaped (e.g., `&` becomes `&amp;`) when appropriate.\n * @param {string} htmlContent - The HTML content where the placeholder should be replaced.\n * @returns {string} The updated HTML content with placeholders replaced.\n */\nexport const replaceForHtml = (clickTracker: string, htmlContent: string): string => {\n    let content = htmlContent,\n        replacement = clickTracker;\n\n    if (clickTracker === PLACEHOLDER_DEFAULT || clickTracker.trim() === '') {\n        return content;\n    }\n\n    replacement = replacement.replace(/&amp;/g, '&');\n    if (replacement.startsWith('&')) {\n        replacement = replacement.replace(/^&+/, '');\n    }\n    if (replacement.endsWith('&')) {\n        replacement = replacement.replace(/&+$/, '');\n    }\n\n    try {\n        let match;\n        let executions = 0;\n        do {\n            executions++;\n            match = content.match(REGEX_MATCH);\n\n            if (!match) {\n                break;\n            }\n\n            const left = match[LEFT_GROUP_INDEX]; // Match of main left group - not subgroups\n            const right = match[RIGHT_GROUP_INDEX]; // Match of main right group - not subgroups\n            const middle = match[MIDDLE_GROUP_INDEX]; // Match middle group (equals sign)\n\n            const hasHtmlEntity =\n                (left.startsWith('&') && left.endsWith(';')) || (right.startsWith('&') && right.endsWith(';'));\n            const hasUrlEncoding = left.startsWith('%') && right.startsWith('%') && middle === '%3D';\n\n            if (hasHtmlEntity) {\n                content = content.replace(\n                    REGEX_MATCH,\n                    LEFT_GROUP_VALUE + replacement.replace(/&/g, '&amp;') + RIGHT_GROUP_VALUE,\n                );\n            } else if (hasUrlEncoding) {\n                content = content.replace(\n                    REGEX_MATCH,\n                    LEFT_GROUP_VALUE + encodeURIComponent(replacement) + RIGHT_GROUP_VALUE,\n                );\n            } else {\n                content = content.replace(REGEX_MATCH, LEFT_GROUP_VALUE + replacement + RIGHT_GROUP_VALUE);\n            }\n        } while (match && executions < 10);\n    } catch (_ex) {\n        return htmlContent;\n    }\n\n    return content;\n};\n\n/**\n * Replaces placeholders in a URL with a specified click tracker value.\n *\n * This function searches for occurrences of the placeholder `pd_rd_plhdr=t` in the given URL\n * and replaces them with the specified click tracker value. It also trims leading or trailing\n * ampersands (`&` or `&amp;`) from the replacement value to avoid introducing malformed URLs.\n *\n * @param {string} clickTracker - The replacement value for the placeholder.\n *   - If the value matches the default placeholder or is empty/whitespace, no replacement is performed.\n * @param {string} url - The URL where the placeholder should be replaced.\n * @returns {string} The updated URL with placeholders replaced.\n */\nexport const replaceForUrl = (clickTracker: string, url: string): string => {\n    if (clickTracker === PLACEHOLDER_DEFAULT || clickTracker.trim() === '') {\n        return url;\n    }\n\n    const URL_PLACEHOLDER_REGEX = /pd_rd_plhdr=t/g;\n    const trimAmpersands = (clickTracker: string): string => {\n        return clickTracker.trim().replace(/^(&amp;|&)+|(&amp;|&)+$/g, '');\n    };\n\n    return url.replace(URL_PLACEHOLDER_REGEX, trimAmpersands(clickTracker));\n};\n","// List of Pre-Defined CSM Counters to be used inside the safeframe.\nexport const IFRAME_INIT = 'adload:iframeinitialized';\nexport const RENDER_START = 'adload:renderstart';\nexport const RENDER_END = 'adload:renderend';\nexport const CREATIVE_WRITTEN = 'adload:creativewritten';\n\n// These ones are used inside the host\nexport const START = 'adload:start';\nexport const CALLBACK = 'adload:delayloadcallback';\n","import { logDebug } from '@amzn/apejs-instrumentation/src/metrics/logging.js';\n\nimport type { HostMessageToClient } from '../components/messaging/types.js';\n\nexport const DEFAULT_PERCOLATE_TIMEOUT = 500;\n\n/**\n *\n * @deprecated Migrate the logic to the GPAT side so we don't need to ask the wrapper.ts\n */\nexport const waitForPercolateClickTrackingFromHost = async (\n    mp: MessagePort,\n    timeout = DEFAULT_PERCOLATE_TIMEOUT,\n): Promise<string> => {\n    // Can't use race here because we need to remove the event listener\n    return new Promise<string>((resolve) => {\n        let timeoutId = -1;\n        const listener = (e: MessageEvent) => {\n            const command = e.data as HostMessageToClient;\n            const expectedCommand = 'percolateClickTracking';\n            if (command.command !== expectedCommand)\n                throw new Error(`Unexpected command ${command}, Expected ${expectedCommand}`);\n            window.clearTimeout(timeoutId); // We don't want to fire the trigger now\n            resolve(command.data);\n        };\n        // TODO Remove this after we have made sure it works\n        timeoutId = window.setTimeout(() => {\n            mp.removeEventListener('message', listener); // Don't want to process the next message as it won't be what we expect!\n            resolve('');\n            logDebug(`Did not receive percolateClickTracking within ${timeout}ms`);\n        }, timeout);\n        mp.addEventListener('message', listener, { once: true });\n        mp.start();\n    });\n};\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport { utf_8_atob } from '../../components/util.js';\n\nexport const getCreative = (adDetails: AdDetails): string => {\n    if (!adDetails.htmlContentEncoded || adDetails.htmlContentEncoded.trim().length === 0)\n        throw new Error('No html content found on a server side fetch');\n    const htmlContent = adDetails.htmlContentEncodedLength\n        ? adDetails.htmlContentEncoded\n        : utf_8_atob(adDetails.htmlContentEncoded);\n    logIfError(htmlContent, adDetails.htmlContentEncodedLength);\n    return htmlContent;\n};\n\nconst logIfError = (htmlContent: string, htmlContentEncodedLength: number | undefined): void => {\n    if (htmlContentEncodedLength && htmlContent.length !== htmlContentEncodedLength) {\n        console.debug(\n            `Mismatched expected htmlContentEncoded size. Expected ${htmlContentEncodedLength} but got ${htmlContent.length}`,\n        );\n    }\n};\n","import { incrementPlacementCounter } from '@amzn/apejs-instrumentation/src/metrics/counters.js';\nimport { evaluateCreativeBeginToRender } from '@amzn/creative-rendering-monitor/src/creativeBTREvaluatorSync.js';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport { writeCreativeToDOM } from '@/client/service/documentWrite.js';\nimport type { EventsChannel } from '@/components/messageChannel/eventsChannel.js';\nimport { CLICK_TRACKING_PAINTER_TEST } from '@/components/weblabs.js';\n\nimport { replaceForHtml } from '../components/clickTracking/replace.js';\nimport { IFRAME_INIT } from '../components/counters/AD_LOAD_CSM_COUNTERS.js';\nimport { BODY_END } from '../components/metrics/latency-metric-type.js';\nimport type { ClientMessageReceiver } from './clientMessageReceiver.js';\nimport type { CommonApiImplementation } from './CommonApiImplementation.js';\nimport { sendCriticalFeatureAndLoaded } from './commonSf.js';\nimport { waitForPercolateClickTrackingFromHost } from './percolateClickTracker.js';\nimport { postCreativeWrite, preCreativeWrite } from './render.js';\nimport { getCreative } from './service/get-creative.js';\n\nexport interface SafeFrameClient {\n    initSFClient: () => void;\n}\n\nexport class SafeframeClientImpl implements SafeFrameClient {\n    private clickTrackingParam = ''; // Containers the clickTrackingParam passed from the host\n    constructor(\n        private readonly o: AdDetails,\n        private readonly mp: MessagePort,\n        private readonly cmr: ClientMessageReceiver,\n        private readonly c: CommonApiImplementation,\n        private readonly eventsChannel: EventsChannel,\n    ) {}\n\n    initSFClient = async () => {\n        // Send clientBodyEnd after setting up the safeframe APIs\n        this.c.sendLatencyMetric(BODY_END);\n        this.eventsChannel.onSafeFrameReady();\n        // Wait for the Percolate Click Tracking To Come Back\n        if (!CLICK_TRACKING_PAINTER_TEST().is('t1')) {\n            this.clickTrackingParam = await waitForPercolateClickTrackingFromHost(this.mp);\n        }\n        // We don't want to start processing messages in the host message receiver until we have gotten the\n        // percolate click tracking param\n        this.mp.onmessage = this.cmr.receiveMessage;\n\n        incrementPlacementCounter(IFRAME_INIT, {\n            id: this.o.placementId,\n            name: this.o.placementName,\n        });\n\n        await this.writeCreativeToDocument();\n    };\n\n    /**\n     * This should only be called once per iframe. Inserts the creative html into the iframe document's DOM.\n     * Currently, we assume all video ad creatives which use the safeframe have a built-in video player.\n     * VAST ads should be rendered through LightAds.\n     * We expect the synthetic load event to be fired during this code path\n     */\n    private readonly writeCreativeToDocument = async (): Promise<void> => {\n        addSyntheticOnLoadListeners(this.c, this.o);\n\n        try {\n            const htmlContent = replaceForHtml(this.clickTrackingParam, getCreative(this.o));\n            preCreativeWrite(this.c, this.o, this.eventsChannel);\n\n            await writeCreativeToDOM(htmlContent);\n\n            this.eventsChannel.onPostCreativeWrite();\n            await postCreativeWrite(this.o, this.c, this.eventsChannel);\n            this.eventsChannel.onCreativeLoad();\n            if (CLICK_TRACKING_PAINTER_TEST().is('t1')) {\n                const onClick = () => this.eventsChannel.onClick();\n                document.body.addEventListener('click', onClick, { once: true });\n                window.addEventListener('pageshow', (e) => {\n                    if (e.persisted) {\n                        document.body.removeEventListener('click', onClick);\n                        document.body.addEventListener('click', onClick, { once: true });\n                    }\n                });\n            }\n        } catch (err) {\n            this.eventsChannel.onError({\n                code: 'CLIENT_SETUP',\n                isBTR: evaluateCreativeBeginToRender(document.body).success,\n                error: err instanceof Error ? err : new Error(String(err)),\n            });\n        }\n    };\n}\n\n// We generate our own synthetic load event for the creative to hook (since the initial sf script and html already fired it)\n// we expect a matching call to generateSyntheticLoadEvent to be generated\nconst addSyntheticOnLoadListeners = (commonApiImplementation: CommonApiImplementation, adDetails: AdDetails) => {\n    if (adDetails.creativeSupportsTTIMeasurement) return;\n    window.addEventListener('load', () => sendCriticalFeatureAndLoaded(commonApiImplementation), { once: true });\n};\nexport const generateSyntheticLoadEvent = () => {\n    window.dispatchEvent(new Event('load'));\n};\n","import type { DesktopSFClientAPI, PlacementInfo } from '@amzn/safe-frame-client-desktopsfclient';\nimport type { AdDetails } from '@amzn/safeframe-model';\nimport type { AdCreativeMetaData } from '@amzn/safeframe-model';\n\nexport class DesktopSFClientAPIImplementation implements DesktopSFClientAPI {\n    constructor(private readonly o: AdDetails) {}\n\n    isSupported = () => {\n        // TODO Remove in the public API\n        return true;\n    };\n    getARID = () => {\n        return this.o.arid;\n    };\n    sendAdInfo = (adInfo: AdCreativeMetaData) => {\n        if (adInfo && this.o.adCreativeMetaData) {\n            this.o.adCreativeMetaData = adInfo;\n        }\n    };\n\n    getPlacementInfo = (): PlacementInfo => {\n        return {\n            slot: this.o.placementName,\n            slotName: this.o.slotName,\n            pageType: this.o.pageType,\n        };\n    };\n}\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport { CommonApiImplementation } from '@/client/CommonApiImplementation.js';\nimport type { EventsChannel } from '@/components/messageChannel/eventsChannel.js';\n\nimport { ClientMessageReceiver } from '../clientMessageReceiver.js';\nimport { ClientMessageSender } from '../clientMessageSender.js';\nimport { SafeframeClientImpl } from '../CommonSFSetup.js';\nimport { DesktopSFClientAPIImplementation } from '../DesktopSFClientAPIImplementation.js';\nimport { MobileSFClientAPIImplementation } from '../MobileSFClientAPIImplementation.js';\n\nexport const createMobileSafeframeClient = (\n    messagePort: MessagePort,\n    adDetails: AdDetails,\n    eventsChannel: EventsChannel,\n): SafeframeClientImpl => {\n    const cms = new ClientMessageSender(adDetails, messagePort);\n    const mL = {};\n    const commonApiImplementation = new CommonApiImplementation(cms, adDetails, mL);\n    const mobileSFClientAPIImplementation = new MobileSFClientAPIImplementation(cms, adDetails);\n\n    window.MSFClient = {\n        ...commonApiImplementation,\n        ...mobileSFClientAPIImplementation,\n    };\n\n    const cmr = new ClientMessageReceiver(window.MSFClient, adDetails, mL);\n\n    return new SafeframeClientImpl(adDetails, messagePort, cmr, commonApiImplementation, eventsChannel);\n};\n\nexport const createDesktopSafeframeClient = (\n    messagePort: MessagePort,\n    adDetails: AdDetails,\n    eventsChannel: EventsChannel,\n): SafeframeClientImpl => {\n    const cms = new ClientMessageSender(adDetails, messagePort);\n    const mL = {};\n    const commonApiImplementation = new CommonApiImplementation(cms, adDetails, mL);\n    const desktopSFClientAPIImplementation = new DesktopSFClientAPIImplementation(adDetails);\n\n    window.SFClient = {\n        ...commonApiImplementation,\n        ...desktopSFClientAPIImplementation,\n    };\n\n    const cmr = new ClientMessageReceiver(window.SFClient, adDetails, mL);\n\n    return new SafeframeClientImpl(adDetails, messagePort, cmr, commonApiImplementation, eventsChannel);\n};\n","import type { AdDetails } from '@amzn/safeframe-model';\n\n/**\n * Retrieves and parses {@link AdDetails} from the iframe's `window.name`.\n * @throws {Error} If `window.name` is empty or contains invalid JSON.\n */\nexport const getAdDetails = (): AdDetails => {\n    if (!window.name) {\n        throw new Error('Ad Details not found in name!');\n    }\n\n    try {\n        return JSON.parse(window.name);\n    } catch {\n        throw new Error(`Failed to parse Ad Details from name: ${window.name}`);\n    }\n};\n","export const readyMessage = 'sf iframe ready';\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport { readyMessage } from '@/components/messaging/bootstrap.js';\nimport { mark } from '@/components/perf.js';\n\n/**\n * Sends a {@link MessagePort} to the SafeFrame host page to establish a communication channel.\n * Uses `postMessage` instead of `onload` as the latter is unreliable for hidden iframes.\n * @see https://stackoverflow.com/questions/12410606/hidden-iframe-onload-event\n * @param mp - The {@link MessagePort} to transfer to the parent.\n * @param adDetails - The {@link AdDetails} used for performance marking.\n */\nexport const sendMessagePortToParent = (mp: MessagePort, adDetails: AdDetails): void => {\n    mark('sf:perf:client', `Start Send Ready ${mp}`, adDetails);\n    window.parent.postMessage(readyMessage, '*', [mp]);\n};\n","import { evaluateCreativeBeginToRender } from '@amzn/creative-rendering-monitor/src/creativeBTREvaluatorSync.js';\n\nimport type { EventsChannel } from '@/components/messageChannel/eventsChannel.js';\n\nconst isExtensionError = (source?: string): boolean =>\n    (source?.startsWith('chrome-extension://') || source?.startsWith('moz-extension://')) ?? false;\n\n/**\n * Creates a handler for window.onerror to catch any unexpected errors\n * coming from the creative code. We will log the error and attempt to\n * show a different ad or collapse the slot.\n */\nexport const createHandleErrors =\n    (eventsChannel: EventsChannel): OnErrorEventHandler =>\n    (message: Event | string, source?: string, _line?: number, _col?: number, error?: Error): boolean => {\n        eventsChannel.onError({\n            code: isExtensionError(source) ? 'BROWSER_EXTENSION' : 'CLIENT_ERROR',\n            isBTR: evaluateCreativeBeginToRender(document.body).success,\n            error: error ?? new Error(typeof message === 'string' ? message : 'Unknown error'),\n        });\n\n        // Returning true suppresses the default browser behavior\n        return true;\n    };\n","import { logError } from '@amzn/apejs-instrumentation/src/metrics/logging.js';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport type { ChannelRegistry, Context } from '@/components/messageChannel/bridge/bridge.js';\nimport type { ArgsForPath } from '@/components/utils/argsForPath.js';\nimport type { NestedKeyOf } from '@/components/utils/nestedKeyOf.js';\n\n/**\n * Internal sender type that enforces compile-time checking on method\n * names and arguments before they cross the iframe→host boundary.\n */\ntype SendFn<T> = <M extends NestedKeyOf<T>>(method: M, ...args: ArgsForPath<T, M>) => void;\n\n/**\n * Creates a sender bound to a channel on the given {@link MessagePort}.\n *\n * Each call captures a fresh {@link Context} (ad identity + timestamps\n * for latency tracking) and posts it to the host page. Errors are\n * logged rather than thrown so a failed metric or event never crashes\n * the ad creative.\n */\nconst sendMessage = <Namespace extends keyof ChannelRegistry>(\n    port: MessagePort,\n    namespace: Namespace,\n    adDetails: AdDetails,\n): SendFn<ChannelRegistry[Namespace]> => {\n    const getContext = (): Context => ({ adDetails, timestamp: new Date(), hrtime: performance.now() });\n    return ((method: string, ...args: unknown[]): void => {\n        try {\n            port.postMessage({ namespace, method, args, context: getContext() });\n        } catch (e) {\n            logError(`Bridge send error in ${namespace}.${method}`, e);\n        }\n    }) as SendFn<ChannelRegistry[Namespace]>;\n};\n\n/**\n * Creates a client-side proxy for a registered channel that the SafeFrame\n * iframe uses to communicate with the host page.\n *\n * The proxy automatically builds dot-notation method paths (e.g.\n * `csm.ue.count(...)` becomes method `'ue.count'`), so adding methods\n * to a channel interface requires zero client-side boilerplate.\n *\n * @typeParam Namespace - A key of {@link ChannelRegistry} identifying the channel.\n * @param port      - The {@link MessagePort} connected to the host page.\n * @param namespace - Channel namespace key (e.g. `'CsmChannel'`).\n * @param adDetails - Ad slot identity embedded in every outgoing message.\n * @returns An object matching the channel interface whose methods post\n *          messages over the port.\n *\n * @example\n * ```ts\n * const csm = createClientChannel(port, 'CsmChannel', adDetails);\n * csm.ueLogError(error, info);   // type-checked\n * csm.ue.count('myMetric', 1);   // nested path handled automatically\n * ```\n */\nexport const createClientChannel = <Namespace extends keyof ChannelRegistry>(\n    port: MessagePort,\n    namespace: Namespace,\n    adDetails: AdDetails,\n): ChannelRegistry[Namespace] => {\n    const send = sendMessage(port, namespace, adDetails);\n    return buildProxy(send as (...args: any[]) => void, '') as ChannelRegistry[Namespace];\n};\n\n/**\n * Recursively builds a {@link Proxy} that accumulates a dot-notation path.\n *\n * This enables nested channel interfaces like `ue.count` — accessing\n * `proxy.ue` returns a deeper proxy, and calling `proxy.ue.count(...)`\n * sends method `'ue.count'` with the provided arguments.\n */\nconst buildProxy = (send: (...args: any[]) => void, prefix: string): unknown =>\n    new Proxy(() => {}, {\n        apply(_target, _thisArg, args: unknown[]) {\n            send(prefix, ...args);\n        },\n        get(_target, prop: string | symbol) {\n            if (typeof prop === 'symbol' || prop === 'then') return undefined;\n            const path = prefix ? `${prefix}.${prop}` : prop;\n            return buildProxy(send, path);\n        },\n    });\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport { createClientChannel } from '@/components/messageChannel/bridge/clientBridge.js';\nimport type { AdditionalInfo, CsmChannel } from '@/components/messageChannel/csm/csmChannel.js';\n\nexport const createClientCsmChannel = (mp: MessagePort, adDetails: AdDetails): CsmChannel => {\n    const proxy = createClientChannel(mp, 'CsmChannel', adDetails);\n    return {\n        ueLogError: (error: Error, info: AdditionalInfo) => proxy.ueLogError(error, info),\n        ue: { count: (metric: string, count?: number) => proxy.ue.count(metric, count) },\n    };\n};\n","/**\n * Disables creative access to set and get cookies.\n * @see https://issues.amazon.com/issues/APEX-4377\n */\nexport const disableCookieAccess = () => {\n    Object.defineProperty(Document.prototype, 'cookie', {\n        get: () => '',\n        set: () => {\n            // Empty\n        },\n    });\n};\n","/**\n * Disables geolocation API access for creatives.\n * @see https://issues.amazon.com/issues/CPP-24902\n */\nconst permissionDeniedError: GeolocationPositionError = {\n    code: 1, // PERMISSION_DENIED\n    message: 'Geolocation access disabled',\n    PERMISSION_DENIED: 1,\n    POSITION_UNAVAILABLE: 2,\n    TIMEOUT: 3,\n};\n\nexport const disableGeolocationApi = () => {\n    if (window?.navigator?.geolocation) {\n        window.navigator.geolocation.watchPosition = (\n            _successCallback: PositionCallback,\n            _errorCallback?: PositionErrorCallback | null,\n            _options?: PositionOptions,\n        ): number => {\n            _errorCallback?.(permissionDeniedError);\n            return 0;\n        };\n\n        window.navigator.geolocation.getCurrentPosition = (\n            _successCallback: PositionCallback,\n            _errorCallback?: PositionErrorCallback | null,\n            _options?: PositionOptions,\n        ) => {\n            _errorCallback?.(permissionDeniedError);\n        };\n    }\n};\n","/**\n * Disables user agent access for creatives.\n * @see https://shepherd.a2z.com/issues/e4e8cd86-419a-4e1a-96ff-b20a6615b8b5\n */\nexport const disableUserAgent = () => {\n    Object.defineProperty(Navigator.prototype, 'userAgent', {\n        get: () => '',\n        set: () => {\n            // Empty\n        },\n    });\n};\n","/**\n * Workaround for iOS bug: allows clicks to propagate in iframe.\n * @see https://tt.amazon.com/0156195085\n * TODO Verify this is still needed.\n */\nexport const workAroundIOBugtt0156195085 = () => {\n    document.addEventListener(\n        'touchstart',\n        {\n            handleEvent: () => {\n                //do nothing\n            },\n        },\n        false,\n    );\n};\n","import { DISABLE_USER_AGENT_WEBLAB } from '@/components/weblabs.js';\n\nimport { disableCookieAccess } from './disableCookieAccess.js';\nimport { disableGeolocationApi } from './disableGeolocationApi.js';\nimport { disableUserAgent } from './disableUserAgent.js';\nimport { workAroundIOBugtt0156195085 } from './workAroundIOBugtt0156195085.js';\n\nexport { disableCookieAccess, disableGeolocationApi, disableUserAgent, workAroundIOBugtt0156195085 };\n\nexport const disableAll = () => {\n    disableCookieAccess();\n    disableGeolocationApi();\n    workAroundIOBugtt0156195085();\n    if (DISABLE_USER_AGENT_WEBLAB().is('t1')) {\n        disableUserAgent();\n    }\n};\n","// Must be kept in sync with https://tiny.amazon.com/2xu3ne6j/SafeframeCSP\nexport const allowedReferrers: string[] = [\n    'amazon.com',\n    'amazon.in',\n    'amazon.de',\n    'amazon.co.jp',\n    'amazon.co.uk',\n    'amazon.ca',\n    'amazon.com.au',\n    'amazon.com.be',\n    'amazon.com.br',\n    'amazon.com.mx',\n    'amazon.com.tr',\n    'amazon.eg',\n    'amazon.es',\n    'amazon.fr',\n    'amazon.it',\n    'amazon.nl',\n    'amazon.pl',\n    'amazon.sa',\n    'amazon.se',\n    'amazon.sg',\n    'amazon.ae',\n    'amazon.co.za',\n    'amazon.cn',\n    'amazon.dev',\n    'boxofficemojo.com',\n    'a2z.com',\n    'console.harmony.a2z.com',\n    'depot.advertising.amazon.dev',\n    'harmony.a2z.com',\n    'd116tmsy8qpy37.cloudfront.net',\n    'd1u3onhraow3iz.cloudfront.net',\n    'd1ubtmbgqm1jlf.cloudfront.net',\n    'd2dk40qqpfbxei.cloudfront.net',\n    'd2jbcalcdp0p85.cloudfront.net',\n    'd2y0vsnh7zmbrq.cloudfront.net',\n    'd345aeerog89iv.cloudfront.net',\n    'imdb.com',\n];\n\nif (process.env.NODE_ENV !== 'production') {\n    // This is stripped from production builds. It is required for local browser testing since SF runs a check for\n    // document.referrer\n    allowedReferrers.push('localhost');\n}\n\nconst isMatched = (referrerHostName: string, allowedList: string[]): boolean => {\n    return allowedList.some((domain) => {\n        return referrerHostName === domain || referrerHostName.endsWith('.' + domain);\n    });\n};\n\nconst isReferrerAllowed = (): boolean => {\n    const referrer = document.referrer;\n\n    if (!referrer) {\n        return false; // No referrer means it's not allowed\n    }\n\n    try {\n        const url = new URL(referrer);\n        return isMatched(url.hostname, allowedReferrers);\n    } catch {\n        return false;\n    }\n};\n\n/**\n * Validates that the current document referrer is in the list of allowed referrers.\n * Skips the check when `window.origin` is `'null'` (e.g. sandboxed iframes).\n * @throws {Error} If the referrer is present but not in the allowed list.\n * @todo Clean up referrer check once https://sim.amazon.com/issues/CPP-41009 is solved.\n */\nexport const validateReferrerAllowed = (): void => {\n    if (window.origin !== 'null' && !isReferrerAllowed()) {\n        throw new Error(`Referrer not allowed: ${document.referrer}`);\n    }\n};\n","const DCM_EIDS = '4|40004007';\n\ntype Dcmads = { eids?: string };\n\ndeclare global {\n    interface Window {\n        dcmads: Dcmads | undefined;\n    }\n}\n\n/**\n * Sets a flag on `window.dcmads.eids` that dcmads.js reads to decide whether to append\n * creative content using document.write or HTMLElement.appendChild.\n * @see https://t.corp.amazon.com/HEDWIGTT-300\n */\nexport const setDcmAdsEids = () => {\n    window.dcmads = window.dcmads || {};\n    window.dcmads.eids = DCM_EIDS;\n};\n","import type { AdDetails } from '@amzn/safeframe-model';\n\nimport { logLowRateMetricSF } from '@/components/metrics/awsMetricLogger.js';\n\n/**\n * Sets up a {@link ReportingObserver} to detect and log heavy ad interventions.\n * Observes intervention reports and flushes pending reports on page hide.\n * No-op if {@link ReportingObserver} is unavailable.\n * @see https://developer.chrome.com/blog/heavy-ad-interventions\n */\nexport const setupReportingObserver = (adDetails: AdDetails) => {\n    if (typeof window.ReportingObserver === 'undefined') return;\n\n    const reportingObserver = new ReportingObserver((reports) => checkReports(reports, adDetails), { buffered: true });\n\n    reportingObserver.observe();\n\n    document.addEventListener('pagehide', () => checkReports(reportingObserver.takeRecords(), adDetails));\n};\n\nconst checkReports = (reports: Report[] = [], adDetails: AdDetails): void =>\n    reports\n        .filter((report) => report.type === 'intervention')\n        .forEach(() => {\n            logLowRateMetricSF({\n                metricName: 'reporting-observer:heavy-ad-intervention',\n                adDetails,\n                additionalDimensions: {\n                    creativeId: adDetails.adCreativeMetaData.adCreativeId,\n                },\n            });\n        });\n","import { logError } from '@amzn/apejs-instrumentation/src/metrics/logging.js';\nimport type { AdDetails } from '@amzn/safeframe-model';\n\nimport { create$sf } from '@/client/apiPage/sfApi.js';\nimport type { SafeFrameClient } from '@/client/CommonSFSetup.js';\nimport { getAdDetails } from '@/client/components/adDetails.js';\nimport { sendMessagePortToParent } from '@/client/components/notifyParent.js';\nimport { createHandleErrors } from '@/client/errorHandling/handleErrors.js';\nimport { documentWriteImpl } from '@/client/service/documentWrite.js';\nimport { createClientChannel } from '@/components/messageChannel/bridge/clientBridge.js';\nimport { createClientCsmChannel } from '@/components/messageChannel/csm/csmChannelClient.js';\nimport type { EventsChannel } from '@/components/messageChannel/eventsChannel.js';\nimport { mark } from '@/components/perf.js';\n\nimport { disableAll } from './disable/disableAll.js';\nimport { validateReferrerAllowed } from './security/referrers.js';\nimport { setDcmAdsEids } from './service/dcm.js';\nimport { setupReportingObserver } from './service/setupReportingObserver.js';\n\n/**\n * Bootstraps the SafeFrame client by creating a {@link MessageChannel} and sending a {@link MessagePort} to the SafeFrame host page.\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API\n */\nexport const bootstrapSafeFrameClient = (safeFrameClientFactory: SafeFrameClientFactory): void => {\n    validateReferrerAllowed();\n    const adDetails = getAdDetails();\n    const { port1: clientPort, port2: hostPort } = new MessageChannel();\n    setupSafeFrameClient(safeFrameClientFactory, clientPort, adDetails);\n    sendMessagePortToParent(hostPort, adDetails);\n};\n\nconst setupSafeFrameClient = async (\n    safeFrameClientFactory: SafeFrameClientFactory,\n    messagePort: MessagePort,\n    adDetails: AdDetails,\n): Promise<void> => {\n    try {\n        setDcmAdsEids();\n        disableAll();\n        setupReportingObserver(adDetails);\n        // FIX ME: we should not have a stringified obj inside the stringified AdDetails. Fix this upstream\n        window.renderingWeblabs = JSON.parse(adDetails.weblabTreatments ?? '');\n        mark('sf:perf:client', 'SF received ad details', adDetails);\n\n        const eventsChannel = createClientChannel(messagePort, 'EventsChannel', adDetails);\n\n        window.$sf = create$sf();\n        document.write = documentWriteImpl;\n        window.onerror = createHandleErrors(eventsChannel);\n        Object.assign(window, createClientCsmChannel(messagePort, adDetails));\n\n        safeFrameClientFactory(messagePort, adDetails, eventsChannel).initSFClient();\n    } catch (ex) {\n        logError('Could not init SafeFrame Client', ex);\n    }\n};\n\nexport type SafeFrameClientFactory = (\n    messagePort: MessagePort,\n    adDetails: AdDetails,\n    eventsChannel: EventsChannel,\n) => SafeFrameClient;\n","import { mark } from '@/components/perf.js';\n\nimport { createDesktopSafeframeClient } from '../application/safeframeClientFactory.js';\nimport { bootstrapSafeFrameClient } from '../initSafeframeClient.js';\nimport type {} from '../InternalClientWindow.js';\n\nmark('perf:sf:client', 'Enter sf.ts');\n\nif (!window.SFClient) {\n    bootstrapSafeFrameClient(createDesktopSafeframeClient);\n}\n"],"x_google_ignoreList":[1,2,3,4,5,6,15,16],"mappings":"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"}