Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ label our Commit messages and Pull Request titles:
- 🚨 **Linting** - Add/fix linter rules
- 🧹 **Cleanup** - Minor cleanup, housekeeping
- πŸ”Š **Logging** - Add/modify debug logs, telemetry
- πŸ”‡ **Remove logs** - Remove debug logs or telemetry

## Dependency Management

Expand Down
80 changes: 0 additions & 80 deletions packages/core/src/browser/lifecycleTracker.spec.ts

This file was deleted.

94 changes: 0 additions & 94 deletions packages/core/src/browser/lifecycleTracker.ts

This file was deleted.

2 changes: 0 additions & 2 deletions packages/core/src/domain/session/sessionManager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
} from '../../../test'
import type { Clock } from '../../../test'
import { DOM_EVENT } from '../../browser/addEventListener'
import { resetLifecycleTracker } from '../../browser/lifecycleTracker'
import { display } from '../../tools/display'
import { ONE_SECOND } from '../../tools/utils/timeUtils'
import type { Configuration } from '../configuration'
Expand Down Expand Up @@ -76,7 +75,6 @@ describe('startSessionManager', () => {

registerCleanupTask(() => {
stopSessionManager()
resetLifecycleTracker()
clock.tick(SESSION_TIME_OUT_DELAY)
})
})
Expand Down
4 changes: 0 additions & 4 deletions packages/core/src/domain/session/sessionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
timeStampNow,
} from '../../tools/utils/timeUtils'
import { addEventListener, addEventListeners, DOM_EVENT } from '../../browser/addEventListener'
import { resetLifecycleTracker, startLifecycleTracker } from '../../browser/lifecycleTracker'
import { clearInterval, clearTimeout, setInterval, setTimeout } from '../../tools/timer'
import { mockable } from '../../tools/mockable'
import { noop, throttle } from '../../tools/utils/functionUtils'
Expand Down Expand Up @@ -100,8 +99,6 @@ export async function startSessionManager(
return
}

startLifecycleTracker(configuration)

const strategy = mockable(getSessionStoreStrategy)(sessionStoreStrategyType, configuration)

const sessionContextHistory = createValueHistory<SessionContext>({
Expand Down Expand Up @@ -383,7 +380,6 @@ export function startSessionManagerStub(): Promise<SessionManager> {
export function stopSessionManager() {
stopCallbacks.forEach((e) => e())
stopCallbacks = []
resetLifecycleTracker()
}

function trackActivity(configuration: Configuration, expandOrRenewSession: () => void) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,7 @@ import {
createCookieStoreAccess,
createDocumentCookieAccess,
} from '../../../browser/cookieAccess'
import { timeStampNow, dateNow } from '../../../tools/utils/timeUtils'
import { addTelemetryError } from '../../telemetry'

const LOCK_QUERY_TIMEOUT = 1000
import type { CookieStoreWindow } from '../../../browser/browser.types'
import { getLifecycleContext } from '../../../browser/lifecycleTracker'
import { clearTimeout, setTimeout } from '../../../tools/timer'
import type { Context } from '../../../tools/serialisation/context'
import { CookieApi, LEGACY_SESSION_STORE_KEY, SESSION_STORE_KEY } from './sessionStoreStrategy'
import type {
SessionStoreStrategy,
Expand Down Expand Up @@ -68,7 +61,6 @@ export function initCookieStrategy(
const opts = encodeCookieOptions(cookieOptions)
const cookieAccess = mockable(createCookieAccess)(cookieApi, configuration, cookieOptions)
let isFirstCall = true
const initTimestamp = timeStampNow()

cookieAccess.observable.subscribe(() => {
cookieAccess
Expand Down Expand Up @@ -99,15 +91,15 @@ export function initCookieStrategy(
return {
async setSessionState(
fn: (sessionState: SessionState) => SessionState,
operation: SessionStateOperation
_operation: SessionStateOperation
): Promise<void> {
if (typeof navigator !== 'undefined' && navigator.locks) {
const lockRequestedAt = dateNow()
await navigator.locks
.request(SESSION_STORE_KEY, () => applyAndWrite(fn))
.catch(async (error) => {
const context = await buildLockErrorContext(operation, initTimestamp, lockRequestedAt)
addTelemetryError(error, context)
.catch((error: unknown) => {
if (isContextGoingAwayError(error)) {
return
}
throw error
})
} else {
Expand All @@ -119,76 +111,14 @@ export function initCookieStrategy(
}
}

interface LockQuerySnapshot {
heldByOthers: number
pendingCount: number
isPending: boolean
}

async function queryLockSnapshot(): Promise<LockQuerySnapshot | 'timeout' | 'unavailable' | 'error'> {
if (typeof navigator === 'undefined' || !navigator.locks?.query) {
return 'unavailable'
}
let timeoutId: ReturnType<typeof setTimeout> | undefined
const timeout = new Promise<'timeout'>((resolve) => {
timeoutId = setTimeout(() => resolve('timeout'), LOCK_QUERY_TIMEOUT)
})
try {
const snapshot = await Promise.race([navigator.locks.query(), timeout])
if (snapshot === 'timeout') {
return 'timeout'
}
const held = snapshot.held ?? []
const pending = snapshot.pending ?? []
return {
heldByOthers: held.filter((lock) => lock.name === SESSION_STORE_KEY).length,
pendingCount: pending.filter((lock) => lock.name === SESSION_STORE_KEY).length,
isPending: pending.some((lock) => lock.name === SESSION_STORE_KEY),
}
} catch {
return 'error'
} finally {
clearTimeout(timeoutId)
}
}

function getNavigationType(): string | undefined {
if (typeof performance === 'undefined' || typeof performance.getEntriesByType !== 'function') {
return undefined
}
// The document-load entry is what we want here ('back_forward' signals bfcache restore).
// Some Chromium builds expose extra entries for experimental soft navigations β€” index 0 is
// still the original document-load entry per the Performance Timeline ordering.
const entry = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming | undefined
return entry?.type
}

function isInIframe(): boolean | undefined {
try {
return window !== window.top
} catch {
// Cross-origin access β€” definitely in an iframe
return true
}
}

async function buildLockErrorContext(
operation: SessionStateOperation,
initTimestamp: number,
lockRequestedAt: number
): Promise<Context> {
return {
operation,
timeSinceInit: dateNow() - initTimestamp,
lockRequestDuration: dateNow() - lockRequestedAt,
visibilityState: document.visibilityState,
readyState: document.readyState,
inIframe: isInIframe(),
navigationType: getNavigationType(),
sessionCookies: getCookies(SESSION_STORE_KEY),
lockQuery: (await queryLockSnapshot()) as Context[string],
...getLifecycleContext(),
// Thrown when the browsing context tears down mid-lock-request.
// - "AbortError: Promise was rejected because the browsing context is going away" (Webkit)
// - "Error: Failed to execute 'request' on 'LockManager': The provided callback is no longer runnable." (Chromium)
function isContextGoingAwayError(error: unknown): boolean {
if (!(error instanceof Error)) {
return false
}
return error.name === 'AbortError' || error.message.includes('no longer runnable')
}

export function createCookieAccess(
Expand Down
1 change: 1 addition & 0 deletions scripts/lib/gitmoji.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const GITMOJI: readonly Gitmoji[] = [
{ emoji: '🚨', label: 'Linting', category: 'internal' },
{ emoji: '🧹', label: 'Cleanup', category: 'internal' },
{ emoji: 'πŸ”Š', label: 'Logging', category: 'internal' },
{ emoji: 'πŸ”‡', label: 'Remove logs', category: 'internal' },
]

// Strip the Unicode variation selector (U+FE0F) so '⚑' and '⚑️' compare equal.
Expand Down
Loading