@amplitude/session-replay-browser 1.40.0 → 1.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -0
- package/lib/cjs/config/local-config.d.ts +2 -1
- package/lib/cjs/config/local-config.d.ts.map +1 -1
- package/lib/cjs/config/local-config.js +3 -0
- package/lib/cjs/config/local-config.js.map +1 -1
- package/lib/cjs/config/types.d.ts +26 -0
- package/lib/cjs/config/types.d.ts.map +1 -1
- package/lib/cjs/config/types.js.map +1 -1
- package/lib/cjs/constants.d.ts +2 -0
- package/lib/cjs/constants.d.ts.map +1 -1
- package/lib/cjs/constants.js +3 -1
- package/lib/cjs/constants.js.map +1 -1
- package/lib/cjs/cross-origin-iframes.d.ts +28 -0
- package/lib/cjs/cross-origin-iframes.d.ts.map +1 -0
- package/lib/cjs/cross-origin-iframes.js +175 -0
- package/lib/cjs/cross-origin-iframes.js.map +1 -0
- package/lib/cjs/events/events-idb-store.d.ts +25 -4
- package/lib/cjs/events/events-idb-store.d.ts.map +1 -1
- package/lib/cjs/events/events-idb-store.js +257 -61
- package/lib/cjs/events/events-idb-store.js.map +1 -1
- package/lib/cjs/session-replay.d.ts +4 -0
- package/lib/cjs/session-replay.d.ts.map +1 -1
- package/lib/cjs/session-replay.js +118 -51
- package/lib/cjs/session-replay.js.map +1 -1
- package/lib/cjs/track-destination.d.ts.map +1 -1
- package/lib/cjs/track-destination.js +5 -1
- package/lib/cjs/track-destination.js.map +1 -1
- package/lib/cjs/utils/rrweb.d.ts +1 -0
- package/lib/cjs/utils/rrweb.d.ts.map +1 -1
- package/lib/cjs/utils/rrweb.js.map +1 -1
- package/lib/cjs/version.d.ts +1 -1
- package/lib/cjs/version.js +1 -1
- package/lib/cjs/version.js.map +1 -1
- package/lib/cjs/worker/index.js +1 -1
- package/lib/esm/config/local-config.d.ts +2 -1
- package/lib/esm/config/local-config.d.ts.map +1 -1
- package/lib/esm/config/local-config.js +3 -0
- package/lib/esm/config/local-config.js.map +1 -1
- package/lib/esm/config/types.d.ts +26 -0
- package/lib/esm/config/types.d.ts.map +1 -1
- package/lib/esm/config/types.js.map +1 -1
- package/lib/esm/constants.d.ts +2 -0
- package/lib/esm/constants.d.ts.map +1 -1
- package/lib/esm/constants.js +2 -0
- package/lib/esm/constants.js.map +1 -1
- package/lib/esm/cross-origin-iframes.d.ts +28 -0
- package/lib/esm/cross-origin-iframes.d.ts.map +1 -0
- package/lib/esm/cross-origin-iframes.js +170 -0
- package/lib/esm/cross-origin-iframes.js.map +1 -0
- package/lib/esm/events/events-idb-store.d.ts +25 -4
- package/lib/esm/events/events-idb-store.d.ts.map +1 -1
- package/lib/esm/events/events-idb-store.js +255 -61
- package/lib/esm/events/events-idb-store.js.map +1 -1
- package/lib/esm/session-replay.d.ts +4 -0
- package/lib/esm/session-replay.d.ts.map +1 -1
- package/lib/esm/session-replay.js +118 -51
- package/lib/esm/session-replay.js.map +1 -1
- package/lib/esm/track-destination.d.ts.map +1 -1
- package/lib/esm/track-destination.js +6 -2
- package/lib/esm/track-destination.js.map +1 -1
- package/lib/esm/utils/rrweb.d.ts +1 -0
- package/lib/esm/utils/rrweb.d.ts.map +1 -1
- package/lib/esm/utils/rrweb.js.map +1 -1
- package/lib/esm/version.d.ts +1 -1
- package/lib/esm/version.js +1 -1
- package/lib/esm/version.js.map +1 -1
- package/lib/esm/worker/index.js +1 -1
- package/lib/scripts/index-min.js +1 -1
- package/lib/scripts/index-min.js.gz +0 -0
- package/lib/scripts/index-min.js.map +1 -1
- package/lib/scripts/session-replay-browser-min.js +1 -1
- package/lib/scripts/session-replay-browser-min.js.gz +0 -0
- package/lib/scripts/session-replay-browser-min.js.map +1 -1
- package/lib/scripts/targeting-min.js +1 -1
- package/lib/scripts/targeting-min.js.gz +0 -0
- package/lib/scripts/targeting-min.js.map +1 -1
- package/lib/scripts/worker-min.js +1 -1
- package/lib/scripts/worker-min.js.gz +0 -0
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events-idb-store.js","sourceRoot":"","sources":["../../../src/events/events-idb-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { DBSchema, IDBPDatabase, openDB } from 'idb';\nimport { STORAGE_FAILURE } from '../messages';\nimport { EventType, Events, SendingSequencesReturn } from '../typings/session-replay';\nimport { BaseEventsStore, InstanceArgs as BaseInstanceArgs } from './base-events-store';\nimport { logIdbError } from '../utils/is-abort-error';\n\nexport const currentSequenceKey = 'sessionCurrentSequence';\nexport const sequencesToSendKey = 'sequencesToSend';\nexport const remoteConfigKey = 'remoteConfig';\n\nexport interface SessionReplayDB extends DBSchema {\n sessionCurrentSequence: {\n key: number;\n value: Omit<SendingSequencesReturn<number>, 'sequenceId'>;\n };\n sequencesToSend: {\n key: number;\n value: Omit<SendingSequencesReturn<number>, 'sequenceId'>;\n indexes: { sessionId: string | number };\n };\n}\n\nexport const defineObjectStores = (db: IDBPDatabase<SessionReplayDB>) => {\n let sequencesStore;\n let currentSequenceStore;\n if (!db.objectStoreNames.contains(currentSequenceKey)) {\n currentSequenceStore = db.createObjectStore(currentSequenceKey, {\n keyPath: 'sessionId',\n });\n }\n if (!db.objectStoreNames.contains(sequencesToSendKey)) {\n sequencesStore = db.createObjectStore(sequencesToSendKey, {\n keyPath: 'sequenceId',\n autoIncrement: true,\n });\n sequencesStore.createIndex('sessionId', 'sessionId');\n }\n return {\n sequencesStore,\n currentSequenceStore,\n };\n};\n\nexport const createStore = async (dbName: string) => {\n return await openDB<SessionReplayDB>(dbName, 1, {\n upgrade: defineObjectStores,\n });\n};\n\ntype InstanceArgs = {\n apiKey: string;\n db: IDBPDatabase<SessionReplayDB>;\n onPersistentFailure?: () => void;\n consecutiveFailureThreshold?: number;\n} & BaseInstanceArgs;\n\nexport class SessionReplayEventsIDBStore extends BaseEventsStore<number> {\n private readonly db: IDBPDatabase<SessionReplayDB>;\n private readonly onPersistentFailure?: () => void;\n private readonly consecutiveFailureThreshold: number;\n private consecutiveFailures = 0;\n private hasTriggeredFallback = false;\n\n constructor(args: InstanceArgs) {\n super(args);\n this.db = args.db;\n this.onPersistentFailure = args.onPersistentFailure;\n this.consecutiveFailureThreshold = args.consecutiveFailureThreshold ?? 3;\n }\n\n private recordFailure() {\n this.consecutiveFailures++;\n if (!this.hasTriggeredFallback && this.consecutiveFailures >= this.consecutiveFailureThreshold) {\n this.hasTriggeredFallback = true;\n this.onPersistentFailure?.();\n }\n }\n\n private recordSuccess() {\n this.consecutiveFailures = 0;\n }\n\n static async new(type: EventType, args: Omit<InstanceArgs, 'db'>): Promise<SessionReplayEventsIDBStore | undefined> {\n try {\n const dbSuffix = type === 'replay' ? '' : `_${type}`;\n const dbName = `${args.apiKey.substring(0, 10)}_amp_session_replay_events${dbSuffix}`;\n const db = await createStore(dbName);\n return new SessionReplayEventsIDBStore({\n ...args,\n db,\n });\n } catch (e) {\n logIdbError(args.loggerProvider, `${STORAGE_FAILURE}: ${e as string}`, e);\n }\n return;\n }\n\n async getCurrentSequenceEvents(sessionId?: number) {\n if (sessionId) {\n const events = await this.db.get('sessionCurrentSequence', sessionId);\n if (!events) {\n return undefined;\n }\n return [events];\n }\n\n const allEvents = [];\n for (const events of await this.db.getAll('sessionCurrentSequence')) {\n allEvents.push(events);\n }\n\n return allEvents;\n }\n\n getSequencesToSend = async (): Promise<SendingSequencesReturn<number>[] | undefined> => {\n let errorLogged = false;\n try {\n const sequences: SendingSequencesReturn<number>[] = [];\n const tx = this.db.transaction('sequencesToSend');\n // Attach a catch handler immediately so tx.done rejections (e.g. AbortError after\n // cursor traversal completes) are always handled without blocking the return path.\n // The errorLogged flag prevents double-logging when the outer catch already fired\n // for the same abort (e.g. cursor.continue() threw mid-traversal).\n tx.done.catch((e: unknown) => {\n if (!errorLogged) {\n logIdbError(this.loggerProvider, `${STORAGE_FAILURE}: ${e as string}`, e);\n }\n });\n let cursor = await tx.store.openCursor();\n while (cursor) {\n const { sessionId, events } = cursor.value;\n sequences.push({\n events,\n sequenceId: cursor.key,\n sessionId,\n });\n cursor = await cursor.continue();\n }\n\n this.recordSuccess();\n return sequences;\n } catch (e) {\n errorLogged = true;\n logIdbError(this.loggerProvider, `${STORAGE_FAILURE}: ${e as string}`, e);\n this.recordFailure();\n }\n return undefined;\n };\n\n storeCurrentSequence = async (sessionId: number) => {\n try {\n const currentSequenceData = await this.db.get<'sessionCurrentSequence'>(currentSequenceKey, sessionId);\n if (!currentSequenceData) {\n this.recordSuccess();\n return undefined;\n }\n\n const sequenceId = await this.db.put<'sequencesToSend'>(sequencesToSendKey, {\n sessionId: sessionId,\n events: currentSequenceData.events,\n });\n\n await this.db.put<'sessionCurrentSequence'>(currentSequenceKey, {\n sessionId,\n events: [],\n });\n\n this.recordSuccess();\n return {\n ...currentSequenceData,\n sessionId,\n sequenceId,\n };\n } catch (e) {\n logIdbError(this.loggerProvider, `${STORAGE_FAILURE}: ${e as string}`, e);\n this.recordFailure();\n }\n return undefined;\n };\n\n addEventToCurrentSequence = async (sessionId: number, event: string) => {\n let errorLogged = false;\n try {\n // Always open a readwrite transaction over both stores so that the read and\n // any subsequent write are atomic. IDB serializes readwrite transactions on\n // overlapping stores, so concurrent fire-and-forget callers (events-manager\n // does not await this method) are queued by the engine rather than interleaving\n // — eliminating the TOCTOU race that a narrow-read + separate-write approach\n // would introduce on the split path.\n const tx = this.db.transaction([currentSequenceKey, sequencesToSendKey], 'readwrite');\n // Attach a catch handler immediately so tx.done rejections (e.g. AbortError after\n // put succeeds but before auto-commit) are always handled without blocking.\n // The errorLogged flag prevents double-logging when the outer catch already fired\n // for the same abort (e.g. a put() threw).\n tx.done.catch((e: unknown) => {\n if (!errorLogged) {\n logIdbError(this.loggerProvider, `${STORAGE_FAILURE}: ${e as string}`, e);\n }\n });\n const sequenceEvents = await tx.objectStore(currentSequenceKey).get(sessionId);\n\n if (!sequenceEvents) {\n await tx.objectStore(currentSequenceKey).put({ sessionId, events: [event] });\n this.recordSuccess();\n return undefined;\n }\n\n if (!this.shouldSplitEventsList(sequenceEvents.events, event)) {\n await tx.objectStore(currentSequenceKey).put({ sessionId, events: sequenceEvents.events.concat(event) });\n this.recordSuccess();\n return undefined;\n }\n\n // Split path: reset sessionCurrentSequence and write the old events to\n // sequencesToSend atomically within the same transaction.\n const eventsToSend = sequenceEvents.events;\n await tx.objectStore(currentSequenceKey).put({ sessionId, events: [event] });\n const sequenceId = await tx.objectStore(sequencesToSendKey).put({\n sessionId,\n events: eventsToSend,\n });\n\n this.recordSuccess();\n return {\n events: eventsToSend,\n sessionId,\n sequenceId,\n };\n } catch (e) {\n errorLogged = true;\n logIdbError(this.loggerProvider, `${STORAGE_FAILURE}: ${e as string}`, e);\n this.recordFailure();\n }\n return undefined;\n };\n\n storeSendingEvents = async (sessionId: number, events: Events) => {\n try {\n const sequenceId = await this.db.put<'sequencesToSend'>(sequencesToSendKey, {\n sessionId: sessionId,\n events: events,\n });\n this.recordSuccess();\n return sequenceId;\n } catch (e) {\n logIdbError(this.loggerProvider, `${STORAGE_FAILURE}: ${e as string}`, e);\n this.recordFailure();\n }\n return undefined;\n };\n\n cleanUpSessionEventsStore = async (_sessionId: number, sequenceId?: number) => {\n if (!sequenceId) {\n return;\n }\n try {\n await this.db.delete<'sequencesToSend'>(sequencesToSendKey, sequenceId);\n this.recordSuccess();\n } catch (e) {\n logIdbError(this.loggerProvider, `${STORAGE_FAILURE}: ${e as string}`, e);\n this.recordFailure();\n }\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"events-idb-store.js","sourceRoot":"","sources":["../../../src/events/events-idb-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { DBSchema, IDBPDatabase, openDB } from 'idb';\nimport { STORAGE_FAILURE } from '../messages';\nimport { EventType, Events, SendingSequencesReturn } from '../typings/session-replay';\nimport { BaseEventsStore, InstanceArgs as BaseInstanceArgs } from './base-events-store';\nimport { logIdbError } from '../utils/is-abort-error';\n\n// crypto.randomUUID() requires a secure context (https). Fall back to a\n// Math.random-based UUID for http origins or older browsers — tab IDs don't\n// need to be cryptographically secure, just unique within a session.\nexport function generateUUID(): string {\n try {\n return crypto.randomUUID();\n } catch {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);\n });\n }\n}\n\nexport const currentSequenceKey = 'sessionCurrentSequence';\nexport const sequencesToSendKey = 'sequencesToSend';\nexport const remoteConfigKey = 'remoteConfig';\n\n// Timeout for openDB at init. IDB openDB can hang forever when another tab\n// holds an open connection during a version upgrade, or when the DB is in a\n// \"closing\" state (documented Chrome behaviour). When that happens we want\n// SessionReplayEventsIDBStore.new() to bail out so the caller can fall back\n// to the in-memory store.\nexport const OPEN_DB_TIMEOUT_MS = 2000;\n\n// Timeout for per-operation tx.done settlement. Mid-recording a readwrite\n// transaction can stall (storage pressure in some browsers stalls instead of\n// throwing); without a timeout, recordFailure() is never called and the\n// memory fallback never triggers. The transaction may still settle later;\n// the timedOut flag prevents double-counting alongside errorLogged.\nexport const TX_DONE_TIMEOUT_MS = 5000;\n\n/**\n * Race a promise against a timeout. Resolves/rejects with the original\n * promise's value when it settles first; rejects with a timeout error if\n * `ms` elapses first. Either way the timer is cleared so we don't leak\n * pending setTimeouts.\n */\nexport function withTimeout<T>(promise: Promise<T>, ms: number, message = 'IDB operation timed out'): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error(`${message} after ${ms}ms`)), ms);\n promise.then(\n (v) => {\n clearTimeout(timer);\n resolve(v);\n },\n (e) => {\n clearTimeout(timer);\n reject(e);\n },\n );\n });\n}\n\n/**\n * Arms a watchdog that fires `onTimeout` only if `tx.done` hasn't settled\n * within `ms`. A \"soft cancel\" returned to the caller suppresses the timeout\n * if the synchronous operation body completes without exception — important\n * because in test environments fake timers can fire ahead of tx.done's commit\n * microtask. Production behaviour is preserved: a genuinely stalled\n * transaction (no commit, no error, individual op promises never resolved)\n * cannot reach the soft-cancel call and the timeout fires as designed.\n *\n * Soft-cancel is only invoked once the awaits inside the operation's outer\n * try block have all returned — i.e. the IDB driver acknowledged each\n * individual put/get. If the driver accepts a put but the underlying\n * transaction silently fails to commit (the production stall scenario),\n * tx.done still hasn't settled, and recordFailure must NOT have been\n * suppressed. The fix for that scenario in production is the tx.done.catch\n * handler attached separately by callers, which catches the eventual abort.\n *\n * The soft-cancel pattern only suppresses the timeout for the \"all puts\n * resolved successfully\" case — a case where tx.done is overwhelmingly\n * likely to settle imminently in production. If it doesn't, callers can\n * still detect the failure on the NEXT operation (which will fail to open\n * a transaction or hit the same pressure), because all three methods use\n * readwrite transactions on the same two stores, which IDB serializes:\n * if T1's tx.done never settles, T2 is blocked waiting for T1 to commit or\n * abort — T2's put/get requests never resolve, T2 never reaches its\n * soft-cancel, and T2's watchdog fires, calling recordFailure().\n */\nfunction armTxDoneTimeout(txDone: Promise<unknown>, ms: number, onTimeout: () => void): () => void {\n const timer = setTimeout(onTimeout, ms);\n // Belt-and-braces: clear the timer when tx.done settles, even though the\n // primary cancel path is the caller's success-path cancel(). This covers\n // the case where tx.done settles with no caller cancellation (shouldn't\n // happen in current code paths, but cheap insurance).\n txDone.then(\n () => clearTimeout(timer),\n () => clearTimeout(timer),\n );\n return () => clearTimeout(timer);\n}\n\nexport interface SessionReplayDB extends DBSchema {\n sessionCurrentSequence: {\n key: number;\n value: Omit<SendingSequencesReturn<number>, 'sequenceId'> & { tabId?: string };\n };\n sequencesToSend: {\n key: number;\n value: Omit<SendingSequencesReturn<number>, 'sequenceId'> & { tabId?: string };\n indexes: { sessionId: string | number };\n };\n}\n\nexport const defineObjectStores = (db: IDBPDatabase<SessionReplayDB>) => {\n let sequencesStore;\n let currentSequenceStore;\n if (!db.objectStoreNames.contains(currentSequenceKey)) {\n currentSequenceStore = db.createObjectStore(currentSequenceKey, {\n keyPath: 'sessionId',\n });\n }\n if (!db.objectStoreNames.contains(sequencesToSendKey)) {\n sequencesStore = db.createObjectStore(sequencesToSendKey, {\n keyPath: 'sequenceId',\n autoIncrement: true,\n });\n sequencesStore.createIndex('sessionId', 'sessionId');\n }\n return {\n sequencesStore,\n currentSequenceStore,\n };\n};\n\nexport const createStore = async (dbName: string) => {\n // Wrap openDB with a timeout so a hung connection (foreign tab holding an\n // open handle during version upgrade, or \"closing\" DB) doesn't block the\n // SDK from initialising. On timeout this rejects, which propagates up to\n // SessionReplayEventsIDBStore.new()'s catch block, returning undefined and\n // triggering the memory fallback.\n return await withTimeout(\n openDB<SessionReplayDB>(dbName, 1, {\n upgrade: defineObjectStores,\n }),\n OPEN_DB_TIMEOUT_MS,\n 'IDB openDB timed out',\n );\n};\n\ntype InstanceArgs = {\n apiKey: string;\n db: IDBPDatabase<SessionReplayDB>;\n tabId: string;\n onPersistentFailure?: () => void;\n consecutiveFailureThreshold?: number;\n} & BaseInstanceArgs;\n\nexport class SessionReplayEventsIDBStore extends BaseEventsStore<number> {\n private readonly db: IDBPDatabase<SessionReplayDB>;\n private readonly tabId: string;\n private readonly onPersistentFailure?: () => void;\n private readonly consecutiveFailureThreshold: number;\n private consecutiveFailures = 0;\n private hasTriggeredFallback = false;\n\n constructor(args: InstanceArgs) {\n super(args);\n this.db = args.db;\n this.tabId = args.tabId;\n this.onPersistentFailure = args.onPersistentFailure;\n // Default threshold of 1: fall back to memory immediately on the first IDB failure.\n // Session replay correctness is far more important than persistence, and IDB errors\n // are typically the symptom of a deeper problem (storage pressure, locked DB, broken\n // browser implementation) that won't recover within a single session. Memory store\n // is always safe — fall back early.\n this.consecutiveFailureThreshold = args.consecutiveFailureThreshold ?? 1;\n }\n\n private recordFailure() {\n this.consecutiveFailures++;\n if (!this.hasTriggeredFallback && this.consecutiveFailures >= this.consecutiveFailureThreshold) {\n this.hasTriggeredFallback = true;\n this.onPersistentFailure?.();\n }\n }\n\n private recordSuccess() {\n this.consecutiveFailures = 0;\n }\n\n static async new(\n type: EventType,\n args: Omit<InstanceArgs, 'db' | 'tabId'> & { tabId?: string },\n ): Promise<SessionReplayEventsIDBStore | undefined> {\n try {\n const dbSuffix = type === 'replay' ? '' : `_${type}`;\n const dbName = `${args.apiKey.substring(0, 10)}_amp_session_replay_events${dbSuffix}`;\n const db = await createStore(dbName);\n // Generate a fresh in-memory UUID per store instance. sessionStorage is\n // intentionally avoided: standalone session-replay customers (without the\n // analytics-browser SDK) would be exposed to a new storage surface they\n // did not consent to, and persistence across page reloads is not needed —\n // completed sequences in sequencesToSend are flushed by any tab/instance.\n const tabId = args.tabId ?? generateUUID();\n return new SessionReplayEventsIDBStore({\n ...args,\n db,\n tabId,\n });\n } catch (e) {\n logIdbError(args.loggerProvider, `${STORAGE_FAILURE}: ${e as string}`, e);\n }\n return;\n }\n\n async getCurrentSequenceEvents(sessionId?: number) {\n if (sessionId) {\n const record = await this.db.get('sessionCurrentSequence', sessionId);\n if (!record) {\n return undefined;\n }\n // Only return our own tab's record (or legacy untagged records).\n if (record.tabId && record.tabId !== this.tabId) {\n return undefined;\n }\n const { tabId: _tabId, ...rest } = record;\n return [rest];\n }\n\n const allEvents = [];\n for (const record of await this.db.getAll('sessionCurrentSequence')) {\n if (record.tabId && record.tabId !== this.tabId) {\n continue;\n }\n const { tabId: _tabId, ...rest } = record;\n allEvents.push(rest);\n }\n\n return allEvents;\n }\n\n getSequencesToSend = async (): Promise<SendingSequencesReturn<number>[] | undefined> => {\n let errorLogged = false;\n let timedOut = false;\n try {\n const sequences: SendingSequencesReturn<number>[] = [];\n const tx = this.db.transaction('sequencesToSend');\n // Attach a catch handler immediately so tx.done rejections (e.g. AbortError after\n // cursor traversal completes) are always handled without blocking the return path.\n // The errorLogged / timedOut flags prevent double-logging and double-recording\n // when the outer catch (or the timeout race) already fired for the same abort.\n tx.done.catch((e: unknown) => {\n if (!errorLogged && !timedOut) {\n logIdbError(this.loggerProvider, `${STORAGE_FAILURE}: ${e as string}`, e);\n this.recordFailure();\n }\n });\n // Arm a watchdog so a stalled transaction (no error, no commit, e.g.\n // storage pressure on some browsers) still trips the failure counter.\n // The watchdog fires only when tx.done genuinely never settles AND the\n // operation's success path didn't run; if tx.done rejects (abort), the\n // tx.done.catch handler above is the sole recorder of failure.\n const cancelTimeout = armTxDoneTimeout(tx.done, TX_DONE_TIMEOUT_MS, () => {\n if (!errorLogged && !timedOut) {\n timedOut = true;\n logIdbError(this.loggerProvider, `${STORAGE_FAILURE}: transaction timed out`);\n this.recordFailure();\n }\n });\n let cursor = await tx.store.openCursor();\n while (cursor) {\n const { sessionId, events } = cursor.value;\n // Return all completed sequences regardless of tabId. Filtering by tab\n // would cause event loss on page reload: a new store instance gets a\n // fresh in-memory UUID and would never see sequences written by the\n // previous instance. Completed sequences are safe to flush by any\n // tab/instance; the server deduplicates, and cleanUpSessionEventsStore\n // on an already-deleted key is a no-op.\n sequences.push({\n events,\n sequenceId: cursor.key,\n sessionId,\n });\n cursor = await cursor.continue();\n }\n\n this.recordSuccess();\n cancelTimeout();\n return sequences;\n } catch (e) {\n if (!timedOut) {\n errorLogged = true;\n logIdbError(this.loggerProvider, `${STORAGE_FAILURE}: ${e as string}`, e);\n this.recordFailure();\n }\n }\n return undefined;\n };\n\n storeCurrentSequence = async (sessionId: number) => {\n let errorLogged = false;\n let timedOut = false;\n try {\n // Wrap the read of sessionCurrentSequence and the writes to sequencesToSend +\n // sessionCurrentSequence in a single readwrite transaction so the three operations\n // commit or roll back atomically. Without this, a concurrent addEventToCurrentSequence\n // call could interleave and either lose the events being promoted or duplicate them\n // (storeCurrentSequence reads N events, addEvent appends an N+1th, storeCurrentSequence\n // writes only the first N back to sequencesToSend, then resets the slot — losing N+1).\n const tx = this.db.transaction([currentSequenceKey, sequencesToSendKey], 'readwrite');\n tx.done.catch((e: unknown) => {\n if (!errorLogged && !timedOut) {\n logIdbError(this.loggerProvider, `${STORAGE_FAILURE}: ${e as string}`, e);\n this.recordFailure();\n }\n });\n // Stalled-transaction protection: see armTxDoneTimeout in getSequencesToSend.\n const cancelTimeout = armTxDoneTimeout(tx.done, TX_DONE_TIMEOUT_MS, () => {\n if (!errorLogged && !timedOut) {\n timedOut = true;\n logIdbError(this.loggerProvider, `${STORAGE_FAILURE}: transaction timed out`);\n this.recordFailure();\n }\n });\n\n const currentSequenceData = await tx.objectStore(currentSequenceKey).get(sessionId);\n // Skip promotion if the slot is empty or owned by another tab — let the owning\n // tab promote its own events on its next addEventToCurrentSequence/storeCurrentSequence\n // call (via Bug 1's foreign-tab promotion path).\n // Don't call recordSuccess() here: no write was performed, so this is not\n // evidence the storage layer is healthy — leave the failure counter unchanged.\n if (!currentSequenceData || (currentSequenceData.tabId && currentSequenceData.tabId !== this.tabId)) {\n cancelTimeout();\n return undefined;\n }\n\n // Skip empty sequences — no point writing a zero-event row to sequencesToSend.\n if (currentSequenceData.events.length === 0) {\n cancelTimeout();\n return undefined;\n }\n\n const sequenceId = await tx.objectStore(sequencesToSendKey).put({\n sessionId,\n events: currentSequenceData.events,\n tabId: this.tabId,\n });\n\n await tx.objectStore(currentSequenceKey).put({\n sessionId,\n events: [],\n tabId: this.tabId,\n });\n\n this.recordSuccess();\n cancelTimeout();\n const { tabId: _tabId, ...rest } = currentSequenceData;\n return {\n ...rest,\n sessionId,\n sequenceId,\n };\n } catch (e) {\n if (!timedOut) {\n errorLogged = true;\n logIdbError(this.loggerProvider, `${STORAGE_FAILURE}: ${e as string}`, e);\n this.recordFailure();\n }\n }\n return undefined;\n };\n\n addEventToCurrentSequence = async (sessionId: number, event: string) => {\n let errorLogged = false;\n let timedOut = false;\n try {\n // Always open a readwrite transaction over both stores so that the read and\n // any subsequent write are atomic. IDB serializes readwrite transactions on\n // overlapping stores, so concurrent fire-and-forget callers (events-manager\n // does not await this method) are queued by the engine rather than interleaving\n // — eliminating the TOCTOU race that a narrow-read + separate-write approach\n // would introduce on the split path.\n const tx = this.db.transaction([currentSequenceKey, sequencesToSendKey], 'readwrite');\n // Attach a catch handler immediately so tx.done rejections (e.g. AbortError after\n // put succeeds but before auto-commit) are always handled without blocking.\n // The errorLogged / timedOut flags prevent double-logging when the outer catch\n // (or the timeout) already fired for the same transaction.\n tx.done.catch((e: unknown) => {\n if (!errorLogged && !timedOut) {\n logIdbError(this.loggerProvider, `${STORAGE_FAILURE}: ${e as string}`, e);\n this.recordFailure();\n }\n });\n // Stalled-transaction protection: see armTxDoneTimeout in getSequencesToSend.\n const cancelTimeout = armTxDoneTimeout(tx.done, TX_DONE_TIMEOUT_MS, () => {\n if (!errorLogged && !timedOut) {\n timedOut = true;\n logIdbError(this.loggerProvider, `${STORAGE_FAILURE}: transaction timed out`);\n this.recordFailure();\n }\n });\n const sequenceEvents = await tx.objectStore(currentSequenceKey).get(sessionId);\n\n // Foreign-tab record path: another tab owns the current-sequence slot for this\n // sessionId. Don't silently overwrite — that would drop the foreign tab's\n // in-progress events. Promote them to sequencesToSend (tabId kept for forensics)\n // before claiming the slot for ourselves. getSequencesToSend no longer filters\n // by tabId, so either tab may flush the promoted sequence; server deduplicates.\n if (sequenceEvents?.tabId && sequenceEvents.tabId !== this.tabId) {\n if (sequenceEvents.events.length > 0) {\n await tx.objectStore(sequencesToSendKey).put({\n sessionId,\n events: sequenceEvents.events,\n tabId: sequenceEvents.tabId,\n });\n }\n await tx.objectStore(currentSequenceKey).put({ sessionId, events: [event], tabId: this.tabId });\n this.recordSuccess();\n cancelTimeout();\n return undefined;\n }\n\n // ownedSequence is either undefined (no record yet) or this tab's record.\n const ownedSequence = sequenceEvents;\n\n if (!ownedSequence) {\n await tx.objectStore(currentSequenceKey).put({ sessionId, events: [event], tabId: this.tabId });\n this.recordSuccess();\n cancelTimeout();\n return undefined;\n }\n\n if (!this.shouldSplitEventsList(ownedSequence.events, event)) {\n await tx\n .objectStore(currentSequenceKey)\n .put({ sessionId, events: ownedSequence.events.concat(event), tabId: this.tabId });\n this.recordSuccess();\n cancelTimeout();\n return undefined;\n }\n\n // Split path: reset sessionCurrentSequence and write the old events to\n // sequencesToSend atomically within the same transaction.\n const eventsToSend = ownedSequence.events;\n await tx.objectStore(currentSequenceKey).put({ sessionId, events: [event], tabId: this.tabId });\n const sequenceId = await tx.objectStore(sequencesToSendKey).put({\n sessionId,\n events: eventsToSend,\n tabId: this.tabId,\n });\n\n this.recordSuccess();\n cancelTimeout();\n return {\n events: eventsToSend,\n sessionId,\n sequenceId,\n };\n } catch (e) {\n if (!timedOut) {\n errorLogged = true;\n logIdbError(this.loggerProvider, `${STORAGE_FAILURE}: ${e as string}`, e);\n this.recordFailure();\n }\n }\n return undefined;\n };\n\n storeSendingEvents = async (sessionId: number, events: Events) => {\n try {\n const sequenceId = await this.db.put<'sequencesToSend'>(sequencesToSendKey, {\n sessionId: sessionId,\n events: events,\n tabId: this.tabId,\n });\n this.recordSuccess();\n return sequenceId;\n } catch (e) {\n logIdbError(this.loggerProvider, `${STORAGE_FAILURE}: ${e as string}`, e);\n this.recordFailure();\n }\n return undefined;\n };\n\n cleanUpSessionEventsStore = async (_sessionId: number, sequenceId?: number) => {\n if (!sequenceId) {\n return;\n }\n try {\n await this.db.delete<'sequencesToSend'>(sequencesToSendKey, sequenceId);\n this.recordSuccess();\n } catch (e) {\n logIdbError(this.loggerProvider, `${STORAGE_FAILURE}: ${e as string}`, e);\n this.recordFailure();\n }\n };\n}\n"]}
|
|
@@ -30,6 +30,8 @@ export declare class SessionReplay implements AmplitudeSessionReplay {
|
|
|
30
30
|
private recordEventsPendingShouldLogMetadata;
|
|
31
31
|
/** Cleanup for URL change listener used to re-evaluate targeting on SPA route changes */
|
|
32
32
|
private urlChangeCleanup;
|
|
33
|
+
private crossOriginIframeCoordinator;
|
|
34
|
+
private crossOriginParentSignalCleanup;
|
|
33
35
|
/** Monotonic counter to ignore stale URL-change targeting results */
|
|
34
36
|
private latestUrlChangeTargetingEvaluationId;
|
|
35
37
|
constructor();
|
|
@@ -71,6 +73,8 @@ export declare class SessionReplay implements AmplitudeSessionReplay {
|
|
|
71
73
|
private getRecordFunction;
|
|
72
74
|
recordEvents(shouldLogMetadata?: boolean): Promise<void>;
|
|
73
75
|
private _recordEvents;
|
|
76
|
+
private buildRRWebRecordOptions;
|
|
77
|
+
private _recordEventsInChildMode;
|
|
74
78
|
addCustomRRWebEvent: (eventName: CustomRRwebEvent, eventData?: {
|
|
75
79
|
[key: string]: any;
|
|
76
80
|
}, addStorageInfo?: boolean) => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,OAAO,EASR,MAAM,2BAA2B,CAAC;AAKnC,OAAO,EACL,aAAa,EACb,yBAAyB,EACzB,kCAAkC,EAInC,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAEL,gBAAgB,EASjB,MAAM,aAAa,CAAC;AAWrB,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAQ5D,OAAO,EACL,sBAAsB,EACtB,0BAA0B,IAAI,mCAAmC,EAIjE,kBAAkB,IAAI,mBAAmB,EACzC,oBAAoB,EACpB,2BAA2B,EAC5B,MAAM,0BAA0B,CAAC;AAOlC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,OAAO,EASR,MAAM,2BAA2B,CAAC;AAKnC,OAAO,EACL,aAAa,EACb,yBAAyB,EACzB,kCAAkC,EAInC,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAEL,gBAAgB,EASjB,MAAM,aAAa,CAAC;AAWrB,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAQ5D,OAAO,EACL,sBAAsB,EACtB,0BAA0B,IAAI,mCAAmC,EAIjE,kBAAkB,IAAI,mBAAmB,EACzC,oBAAoB,EACpB,2BAA2B,EAC5B,MAAM,0BAA0B,CAAC;AAOlC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,KAAK,WAAW,GAAG,CAAC,CAAC,EAAE,mBAAmB,GAAG,KAAK,KAAK,IAAI,CAAC;AAE5D,qBAAa,aAAc,YAAW,sBAAsB;IAC1D,IAAI,SAAuC;IAC3C,MAAM,EAAE,yBAAyB,GAAG,SAAS,CAAC;IAC9C,qBAAqB,EAAE,kCAAkC,GAAG,SAAS,CAAC;IACtE,WAAW,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAC7C,aAAa,CAAC,EAAE,mCAAmC,CAAC,QAAQ,GAAG,aAAa,EAAE,MAAM,CAAC,CAAC;IACtF,cAAc,EAAE,OAAO,CAAC;IACxB,oBAAoB,EAAE,UAAU,CAAC,cAAc,CAAC,GAAG,IAAI,CAAQ;IAC/D,UAAU,SAAK;IACf,eAAe,EAAE,eAAe,GAAG,SAAS,CAAC;IAC7C,qBAAqB,UAAS;IAC9B,OAAO,CAAC,mBAAmB,CAAC,CAA8B;IAC1D,OAAO,CAAC,wBAAwB,CAAC,CAAU;IAG3C,YAAY,EAAE,WAAW,EAAE,CAAM;IACjC,OAAO,CAAC,UAAU,CAAC,CAAiB;IACpC,OAAO,CAAC,YAAY,CAAC,CAAe;IACpC,OAAO,CAAC,gBAAgB,CAAC,CAAmB;IAC5C,OAAO,CAAC,QAAQ,CAAoC;IAGpD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,oBAAoB,CAAS;IAErC,gFAAgF;IAChF,OAAO,CAAC,cAAc,CAAM;IAE5B,OAAO,CAAC,oCAAoC,CAAwB;IAEpE,yFAAyF;IACzF,OAAO,CAAC,gBAAgB,CAA6B;IACrD,OAAO,CAAC,4BAA4B,CAA6C;IACjF,OAAO,CAAC,8BAA8B,CAA6B;IACnE,qEAAqE;IACrE,OAAO,CAAC,oCAAoC,CAAK;;IAMjD,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;IAIlD,OAAO,CAAC,sBAAsB,CAmB5B;IAEF;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;IAuC9B,OAAO,CAAC,0BAA0B;cAKlB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;IAuJnE,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAIpD,iBAAiB,CACrB,SAAS,EAAE,MAAM,GAAG,MAAM,EAC1B,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE;YAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;SAAE,CAAA;KAAE;IAoCvD,0BAA0B;;;IAsC1B,YAAY,aAEV;IAEF,aAAa,aAUX;IAEF;;;;OAIG;IACH,OAAO,CAAC,iBAAiB,CAIvB;IAEF,2BAA2B,oBACR,2BAA2B,mGA6F5C;IAEF,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM;IAShC,UAAU,CAAC,sBAAsB,UAAQ;IAgB/C,YAAY;IAUZ,eAAe;IA+Df,iBAAiB,IAAI,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IAWlD,oBAAoB,IAAI,MAAM,GAAG,SAAS;IAgCpC,mBAAmB,CAAC,aAAa,EAAE,aAAa,GAAG,SAAS;YAyCpD,iBAAiB;IAezB,YAAY,CAAC,iBAAiB,UAAO;YAmB7B,aAAa;IAuH3B,OAAO,CAAC,uBAAuB;IA4C/B,OAAO,CAAC,wBAAwB;IAkChC,mBAAmB,cACN,gBAAgB;;kDAmC3B;IAEF,mBAAmB,aAgBjB;IAEF,WAAW;IAIX,YAAY;IAIN,KAAK,CAAC,QAAQ,UAAQ;IAI5B,QAAQ;IASR,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,WAAW;YAyBL,0BAA0B;CAUzC"}
|
|
@@ -19,6 +19,7 @@ var targeting_manager_1 = require("./targeting/targeting-manager");
|
|
|
19
19
|
var sampling_1 = require("./sampling");
|
|
20
20
|
var version_1 = require("./version");
|
|
21
21
|
var url_tracking_plugin_1 = require("./plugins/url-tracking-plugin");
|
|
22
|
+
var cross_origin_iframes_1 = require("./cross-origin-iframes");
|
|
22
23
|
var SessionReplay = /** @class */ (function () {
|
|
23
24
|
function SessionReplay() {
|
|
24
25
|
var _this = this;
|
|
@@ -36,6 +37,8 @@ var SessionReplay = /** @class */ (function () {
|
|
|
36
37
|
this.recordEventsPendingShouldLogMetadata = null;
|
|
37
38
|
/** Cleanup for URL change listener used to re-evaluate targeting on SPA route changes */
|
|
38
39
|
this.urlChangeCleanup = null;
|
|
40
|
+
this.crossOriginIframeCoordinator = null;
|
|
41
|
+
this.crossOriginParentSignalCleanup = null;
|
|
39
42
|
/** Monotonic counter to ignore stale URL-change targeting results */
|
|
40
43
|
this.latestUrlChangeTargetingEvaluationId = 0;
|
|
41
44
|
this.teardownEventListeners = function (teardown) {
|
|
@@ -215,12 +218,18 @@ var SessionReplay = /** @class */ (function () {
|
|
|
215
218
|
});
|
|
216
219
|
};
|
|
217
220
|
this.stopRecordingEvents = function () {
|
|
218
|
-
var _a;
|
|
221
|
+
var _a, _b, _c;
|
|
219
222
|
try {
|
|
220
223
|
_this.loggerProvider.log('Session Replay capture stopping.');
|
|
221
224
|
_this.recordCancelCallback && _this.recordCancelCallback();
|
|
222
225
|
_this.recordCancelCallback = null;
|
|
223
226
|
(_a = _this.networkObservers) === null || _a === void 0 ? void 0 : _a.stop();
|
|
227
|
+
(_b = _this.crossOriginIframeCoordinator) === null || _b === void 0 ? void 0 : _b.stop();
|
|
228
|
+
_this.crossOriginIframeCoordinator = null;
|
|
229
|
+
// Remove the child-mode parent signal listener so a later mode change
|
|
230
|
+
// (e.g. crossOriginIframes disabled) does not leave a stale listener.
|
|
231
|
+
(_c = _this.crossOriginParentSignalCleanup) === null || _c === void 0 ? void 0 : _c.call(_this);
|
|
232
|
+
_this.crossOriginParentSignalCleanup = null;
|
|
224
233
|
}
|
|
225
234
|
catch (error) {
|
|
226
235
|
var typedError = error;
|
|
@@ -729,11 +738,11 @@ var SessionReplay = /** @class */ (function () {
|
|
|
729
738
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
730
739
|
if (shouldLogMetadata === void 0) { shouldLogMetadata = true; }
|
|
731
740
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
732
|
-
var config, shouldRecord, sessionId, recordFunction, networkLoggingConfig, trackUrl, ignoredUrls,
|
|
733
|
-
var
|
|
741
|
+
var config, shouldRecord, sessionId, recordFunction, networkLoggingConfig, trackUrl, ignoredUrls, interactionConfig, loggingConfig, hooks, ugcFilterRules, crossOriginIframesEnabled, coordinateChildren, childMode, _j, _k, _l, error_5;
|
|
742
|
+
var _m;
|
|
734
743
|
var _this = this;
|
|
735
|
-
return tslib_1.__generator(this, function (
|
|
736
|
-
switch (
|
|
744
|
+
return tslib_1.__generator(this, function (_o) {
|
|
745
|
+
switch (_o.label) {
|
|
737
746
|
case 0:
|
|
738
747
|
config = this.config;
|
|
739
748
|
shouldRecord = this.getShouldRecord();
|
|
@@ -744,14 +753,14 @@ var SessionReplay = /** @class */ (function () {
|
|
|
744
753
|
this.stopRecordingEvents();
|
|
745
754
|
return [4 /*yield*/, this.getRecordFunction()];
|
|
746
755
|
case 1:
|
|
747
|
-
recordFunction =
|
|
756
|
+
recordFunction = _o.sent();
|
|
748
757
|
// May be undefined if cannot import rrweb-record
|
|
749
758
|
if (!recordFunction) {
|
|
750
759
|
return [2 /*return*/];
|
|
751
760
|
}
|
|
752
761
|
return [4 /*yield*/, this.initializeNetworkObservers()];
|
|
753
762
|
case 2:
|
|
754
|
-
|
|
763
|
+
_o.sent();
|
|
755
764
|
networkLoggingConfig = (_b = config.loggingConfig) === null || _b === void 0 ? void 0 : _b.network;
|
|
756
765
|
trackUrl = (0, helpers_1.getServerUrl)(config.serverZone, config.trackServerUrl);
|
|
757
766
|
ignoredUrls = [constants_1.SESSION_REPLAY_SERVER_URL, constants_1.SESSION_REPLAY_EU_URL, constants_1.SESSION_REPLAY_STAGING_URL, trackUrl];
|
|
@@ -760,7 +769,7 @@ var SessionReplay = /** @class */ (function () {
|
|
|
760
769
|
return;
|
|
761
770
|
void _this.addCustomRRWebEvent(constants_1.CustomRRwebEvent.FETCH_REQUEST, event);
|
|
762
771
|
}, networkLoggingConfig);
|
|
763
|
-
|
|
772
|
+
interactionConfig = config.interactionConfig, loggingConfig = config.loggingConfig;
|
|
764
773
|
hooks = (interactionConfig === null || interactionConfig === void 0 ? void 0 : interactionConfig.enabled)
|
|
765
774
|
? {
|
|
766
775
|
mouseInteraction: this.eventsManager &&
|
|
@@ -777,13 +786,36 @@ var SessionReplay = /** @class */ (function () {
|
|
|
777
786
|
: {};
|
|
778
787
|
ugcFilterRules = (interactionConfig === null || interactionConfig === void 0 ? void 0 : interactionConfig.enabled) && interactionConfig.ugcFilterRules ? interactionConfig.ugcFilterRules : [];
|
|
779
788
|
this.loggerProvider.log("Session Replay capture beginning for ".concat(sessionId, "."));
|
|
780
|
-
|
|
789
|
+
_o.label = 3;
|
|
781
790
|
case 3:
|
|
782
|
-
|
|
791
|
+
_o.trys.push([3, 5, , 6]);
|
|
792
|
+
crossOriginIframesEnabled = !!((_g = config.crossOriginIframes) === null || _g === void 0 ? void 0 : _g.enabled);
|
|
793
|
+
coordinateChildren = ((_h = config.crossOriginIframes) === null || _h === void 0 ? void 0 : _h.coordinateChildren) !== false;
|
|
794
|
+
childMode = crossOriginIframesEnabled && (0, cross_origin_iframes_1.isInIframe)();
|
|
795
|
+
if (childMode && coordinateChildren) {
|
|
796
|
+
// Child mode: don't self-start; wait for a start signal from the parent.
|
|
797
|
+
// (The previous listener, if any, was already removed by stopRecordingEvents above.)
|
|
798
|
+
this.crossOriginParentSignalCleanup = (0, cross_origin_iframes_1.listenForParentSignals)({
|
|
799
|
+
onStart: function () { return _this._recordEventsInChildMode(recordFunction, sessionId, config, hooks); },
|
|
800
|
+
onStop: function () {
|
|
801
|
+
try {
|
|
802
|
+
// Only cancel the rrweb recording — do NOT call stopRecordingEvents() here,
|
|
803
|
+
// which would clear crossOriginParentSignalCleanup and make the child deaf
|
|
804
|
+
// to subsequent start/stop cycles from the parent.
|
|
805
|
+
_this.recordCancelCallback && _this.recordCancelCallback();
|
|
806
|
+
_this.recordCancelCallback = null;
|
|
807
|
+
}
|
|
808
|
+
catch (error) {
|
|
809
|
+
var typedError = error;
|
|
810
|
+
_this.loggerProvider.warn("Error occurred while stopping child iframe replay capture: ".concat(typedError.toString()));
|
|
811
|
+
}
|
|
812
|
+
},
|
|
813
|
+
});
|
|
814
|
+
return [2 /*return*/];
|
|
815
|
+
}
|
|
783
816
|
_j = this;
|
|
784
817
|
_k = recordFunction;
|
|
785
|
-
_l = {
|
|
786
|
-
emit: function (event) {
|
|
818
|
+
_l = [tslib_1.__assign({}, this.buildRRWebRecordOptions(config, hooks, function (event) {
|
|
787
819
|
if (_this.shouldOptOut()) {
|
|
788
820
|
_this.loggerProvider.log("Opting session ".concat(sessionId, " out of recording due to optOut config."));
|
|
789
821
|
_this.stopRecordingEvents();
|
|
@@ -797,52 +829,24 @@ var SessionReplay = /** @class */ (function () {
|
|
|
797
829
|
// Schedule processing during idle time if the browser supports requestIdleCallback
|
|
798
830
|
_this.eventCompressor.enqueueEvent(event, sessionId);
|
|
799
831
|
}
|
|
800
|
-
},
|
|
801
|
-
|
|
802
|
-
hooks: hooks,
|
|
803
|
-
maskAllInputs: true,
|
|
804
|
-
maskTextClass: constants_1.MASK_TEXT_CLASS,
|
|
805
|
-
blockClass: constants_1.BLOCK_CLASS,
|
|
806
|
-
blockSelector: this.getBlockSelectors(),
|
|
807
|
-
applyBackgroundColorToBlockedElements: config.applyBackgroundColorToBlockedElements,
|
|
808
|
-
maskInputFn: (0, helpers_1.maskFn)('input', privacyConfig, function () { return _this.currentPageUrl; }),
|
|
809
|
-
maskTextFn: (0, helpers_1.maskFn)('text', privacyConfig, function () { return _this.currentPageUrl; }),
|
|
810
|
-
maskAttributeFn: (0, helpers_1.maskAttributeFn)(privacyConfig, function () { return _this.currentPageUrl; }),
|
|
811
|
-
maskTextSelector: this.getMaskTextSelectors(),
|
|
812
|
-
recordCanvas: false,
|
|
813
|
-
captureAdoptedStyleSheets: config.captureAdoptedStyleSheets,
|
|
814
|
-
slimDOMOptions: {
|
|
815
|
-
script: (_g = config.omitElementTags) === null || _g === void 0 ? void 0 : _g.script,
|
|
816
|
-
comment: (_h = config.omitElementTags) === null || _h === void 0 ? void 0 : _h.comment,
|
|
817
|
-
},
|
|
818
|
-
errorHandler: function (error) {
|
|
819
|
-
var typedError = error;
|
|
820
|
-
// styled-components relies on this error being thrown and bubbled up, rrweb is otherwise suppressing it
|
|
821
|
-
if (typedError.message.includes('insertRule') && typedError.message.includes('CSSStyleSheet')) {
|
|
822
|
-
throw typedError;
|
|
823
|
-
}
|
|
824
|
-
// rrweb does monkey patching on certain window functions such as CSSStyleSheet.proptype.insertRule,
|
|
825
|
-
// and errors from external clients calling these functions can get suppressed. Styled components depend
|
|
826
|
-
// on these errors being re-thrown.
|
|
827
|
-
if (typedError._external_) {
|
|
828
|
-
throw typedError;
|
|
829
|
-
}
|
|
830
|
-
_this.loggerProvider.warn('Error while capturing replay: ', typedError.toString());
|
|
831
|
-
// Return true so that we don't clutter user's consoles with internal rrweb errors
|
|
832
|
-
return true;
|
|
833
|
-
}
|
|
834
|
-
};
|
|
832
|
+
}, 'Error while capturing replay: '))];
|
|
833
|
+
_m = {};
|
|
835
834
|
return [4 /*yield*/, this.getRecordingPlugins(loggingConfig)];
|
|
836
835
|
case 4:
|
|
837
|
-
_j.recordCancelCallback = _k.apply(void 0, [(_l.plugins =
|
|
838
|
-
|
|
836
|
+
_j.recordCancelCallback = _k.apply(void 0, [tslib_1.__assign.apply(void 0, _l.concat([(_m.plugins = _o.sent(), _m.recordCrossOriginIframes = crossOriginIframesEnabled, _m)]))]);
|
|
837
|
+
if (crossOriginIframesEnabled && !childMode && coordinateChildren) {
|
|
838
|
+
if (!this.crossOriginIframeCoordinator) {
|
|
839
|
+
this.crossOriginIframeCoordinator = new cross_origin_iframes_1.CrossOriginIframeCoordinator();
|
|
840
|
+
}
|
|
841
|
+
this.crossOriginIframeCoordinator.start();
|
|
842
|
+
}
|
|
839
843
|
void this.addCustomRRWebEvent(constants_1.CustomRRwebEvent.DEBUG_INFO);
|
|
840
844
|
if (shouldLogMetadata) {
|
|
841
845
|
void this.addCustomRRWebEvent(constants_1.CustomRRwebEvent.METADATA, this.metadata);
|
|
842
846
|
}
|
|
843
847
|
return [3 /*break*/, 6];
|
|
844
848
|
case 5:
|
|
845
|
-
error_5 =
|
|
849
|
+
error_5 = _o.sent();
|
|
846
850
|
this.loggerProvider.warn('Failed to initialize session replay:', error_5);
|
|
847
851
|
return [3 /*break*/, 6];
|
|
848
852
|
case 6: return [2 /*return*/];
|
|
@@ -850,6 +854,67 @@ var SessionReplay = /** @class */ (function () {
|
|
|
850
854
|
});
|
|
851
855
|
});
|
|
852
856
|
};
|
|
857
|
+
SessionReplay.prototype.buildRRWebRecordOptions = function (config, hooks, emit, errorLogPrefix) {
|
|
858
|
+
var _this = this;
|
|
859
|
+
var _a, _b;
|
|
860
|
+
var privacyConfig = config.privacyConfig;
|
|
861
|
+
return {
|
|
862
|
+
emit: emit,
|
|
863
|
+
inlineStylesheet: config.shouldInlineStylesheet,
|
|
864
|
+
hooks: hooks,
|
|
865
|
+
maskAllInputs: true,
|
|
866
|
+
maskTextClass: constants_1.MASK_TEXT_CLASS,
|
|
867
|
+
blockClass: constants_1.BLOCK_CLASS,
|
|
868
|
+
blockSelector: this.getBlockSelectors(),
|
|
869
|
+
applyBackgroundColorToBlockedElements: config.applyBackgroundColorToBlockedElements,
|
|
870
|
+
maskInputFn: (0, helpers_1.maskFn)('input', privacyConfig, function () { return _this.currentPageUrl; }),
|
|
871
|
+
maskTextFn: (0, helpers_1.maskFn)('text', privacyConfig, function () { return _this.currentPageUrl; }),
|
|
872
|
+
maskAttributeFn: (0, helpers_1.maskAttributeFn)(privacyConfig, function () { return _this.currentPageUrl; }),
|
|
873
|
+
maskTextSelector: this.getMaskTextSelectors(),
|
|
874
|
+
recordCanvas: false,
|
|
875
|
+
captureAdoptedStyleSheets: config.captureAdoptedStyleSheets,
|
|
876
|
+
slimDOMOptions: {
|
|
877
|
+
script: (_a = config.omitElementTags) === null || _a === void 0 ? void 0 : _a.script,
|
|
878
|
+
comment: (_b = config.omitElementTags) === null || _b === void 0 ? void 0 : _b.comment,
|
|
879
|
+
},
|
|
880
|
+
errorHandler: function (error) {
|
|
881
|
+
var typedError = error;
|
|
882
|
+
// styled-components relies on this error being thrown and bubbled up, rrweb is otherwise suppressing it
|
|
883
|
+
if (typedError.message.includes('insertRule') && typedError.message.includes('CSSStyleSheet')) {
|
|
884
|
+
throw typedError;
|
|
885
|
+
}
|
|
886
|
+
// rrweb monkey-patches window functions like CSSStyleSheet.insertRule; errors from external callers
|
|
887
|
+
// (e.g. styled-components) must be re-thrown so they aren't silently swallowed.
|
|
888
|
+
if (typedError._external_) {
|
|
889
|
+
throw typedError;
|
|
890
|
+
}
|
|
891
|
+
_this.loggerProvider.warn(errorLogPrefix, typedError.toString());
|
|
892
|
+
// Return true so that we don't clutter user's consoles with internal rrweb errors
|
|
893
|
+
return true;
|
|
894
|
+
},
|
|
895
|
+
};
|
|
896
|
+
};
|
|
897
|
+
SessionReplay.prototype._recordEventsInChildMode = function (recordFunction, sessionId, config, hooks) {
|
|
898
|
+
// In child mode, rrweb detects window.parent !== window and routes events via
|
|
899
|
+
// postMessage to the parent instead of calling emit. The emit callback is unused.
|
|
900
|
+
// Note: recording plugins (URL tracking, console capture) are intentionally omitted
|
|
901
|
+
// here — the child's events are merged into the parent stream, so URL changes inside
|
|
902
|
+
// the iframe should not be recorded as parent page-view events.
|
|
903
|
+
try {
|
|
904
|
+
// Stop only the previous rrweb recording. Do NOT call stopRecordingEvents() here:
|
|
905
|
+
// that would clear crossOriginParentSignalCleanup — the very listener that invoked
|
|
906
|
+
// this method — making the child permanently deaf to subsequent stop/start cycles.
|
|
907
|
+
this.recordCancelCallback && this.recordCancelCallback();
|
|
908
|
+
this.recordCancelCallback = null;
|
|
909
|
+
this.recordCancelCallback = recordFunction(tslib_1.__assign(tslib_1.__assign({}, this.buildRRWebRecordOptions(config, hooks, function () {
|
|
910
|
+
// no-op: child events are forwarded to parent via postMessage by rrweb
|
|
911
|
+
}, 'Error while capturing replay (child iframe): ')), { recordCrossOriginIframes: true }));
|
|
912
|
+
this.loggerProvider.log("Session Replay child iframe capture beginning for session ".concat(sessionId, "."));
|
|
913
|
+
}
|
|
914
|
+
catch (error) {
|
|
915
|
+
this.loggerProvider.warn('Failed to initialize session replay in child iframe mode:', error);
|
|
916
|
+
}
|
|
917
|
+
};
|
|
853
918
|
SessionReplay.prototype.getDeviceId = function () {
|
|
854
919
|
var _a;
|
|
855
920
|
return (_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.deviceId;
|
|
@@ -868,8 +933,10 @@ var SessionReplay = /** @class */ (function () {
|
|
|
868
933
|
});
|
|
869
934
|
};
|
|
870
935
|
SessionReplay.prototype.shutdown = function () {
|
|
871
|
-
var _a;
|
|
936
|
+
var _a, _b;
|
|
872
937
|
(_a = this.urlChangeCleanup) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
938
|
+
(_b = this.crossOriginParentSignalCleanup) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
939
|
+
this.crossOriginParentSignalCleanup = null;
|
|
873
940
|
this.teardownEventListeners(true);
|
|
874
941
|
this.stopRecordingEvents();
|
|
875
942
|
this.sendEvents();
|