Skip to content

Commit 06e7cb4

Browse files
πŸ”‡ Discard expected navigator.locks errors from page teardown (#4691)
1 parent 1117c70 commit 06e7cb4

7 files changed

Lines changed: 14 additions & 262 deletions

File tree

β€Ždocs/DEVELOPMENT.mdβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ label our Commit messages and Pull Request titles:
2626
- 🚨 **Linting** - Add/fix linter rules
2727
- 🧹 **Cleanup** - Minor cleanup, housekeeping
2828
- πŸ”Š **Logging** - Add/modify debug logs, telemetry
29+
- πŸ”‡ **Remove logs** - Remove debug logs or telemetry
2930

3031
## Dependency Management
3132

β€Žpackages/core/src/browser/lifecycleTracker.spec.tsβ€Ž

Lines changed: 0 additions & 80 deletions
This file was deleted.

β€Žpackages/core/src/browser/lifecycleTracker.tsβ€Ž

Lines changed: 0 additions & 94 deletions
This file was deleted.

β€Žpackages/core/src/domain/session/sessionManager.spec.tsβ€Ž

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {
1313
} from '../../../test'
1414
import type { Clock } from '../../../test'
1515
import { DOM_EVENT } from '../../browser/addEventListener'
16-
import { resetLifecycleTracker } from '../../browser/lifecycleTracker'
1716
import { display } from '../../tools/display'
1817
import { ONE_SECOND } from '../../tools/utils/timeUtils'
1918
import type { Configuration } from '../configuration'
@@ -76,7 +75,6 @@ describe('startSessionManager', () => {
7675

7776
registerCleanupTask(() => {
7877
stopSessionManager()
79-
resetLifecycleTracker()
8078
clock.tick(SESSION_TIME_OUT_DELAY)
8179
})
8280
})

β€Žpackages/core/src/domain/session/sessionManager.tsβ€Ž

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
timeStampNow,
1313
} from '../../tools/utils/timeUtils'
1414
import { addEventListener, addEventListeners, DOM_EVENT } from '../../browser/addEventListener'
15-
import { resetLifecycleTracker, startLifecycleTracker } from '../../browser/lifecycleTracker'
1615
import { clearInterval, clearTimeout, setInterval, setTimeout } from '../../tools/timer'
1716
import { mockable } from '../../tools/mockable'
1817
import { noop, throttle } from '../../tools/utils/functionUtils'
@@ -100,8 +99,6 @@ export async function startSessionManager(
10099
return
101100
}
102101

103-
startLifecycleTracker(configuration)
104-
105102
const strategy = mockable(getSessionStoreStrategy)(sessionStoreStrategyType, configuration)
106103

107104
const sessionContextHistory = createValueHistory<SessionContext>({
@@ -383,7 +380,6 @@ export function startSessionManagerStub(): Promise<SessionManager> {
383380
export function stopSessionManager() {
384381
stopCallbacks.forEach((e) => e())
385382
stopCallbacks = []
386-
resetLifecycleTracker()
387383
}
388384

389385
function trackActivity(configuration: Configuration, expandOrRenewSession: () => void) {

β€Žpackages/core/src/domain/session/storeStrategies/sessionInCookie.tsβ€Ž

Lines changed: 12 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,7 @@ import {
1414
createCookieStoreAccess,
1515
createDocumentCookieAccess,
1616
} from '../../../browser/cookieAccess'
17-
import { timeStampNow, dateNow } from '../../../tools/utils/timeUtils'
18-
import { addTelemetryError } from '../../telemetry'
19-
20-
const LOCK_QUERY_TIMEOUT = 1000
2117
import type { CookieStoreWindow } from '../../../browser/browser.types'
22-
import { getLifecycleContext } from '../../../browser/lifecycleTracker'
23-
import { clearTimeout, setTimeout } from '../../../tools/timer'
24-
import type { Context } from '../../../tools/serialisation/context'
2518
import { CookieApi, LEGACY_SESSION_STORE_KEY, SESSION_STORE_KEY } from './sessionStoreStrategy'
2619
import type {
2720
SessionStoreStrategy,
@@ -68,7 +61,6 @@ export function initCookieStrategy(
6861
const opts = encodeCookieOptions(cookieOptions)
6962
const cookieAccess = mockable(createCookieAccess)(cookieApi, configuration, cookieOptions)
7063
let isFirstCall = true
71-
const initTimestamp = timeStampNow()
7264

7365
cookieAccess.observable.subscribe(() => {
7466
cookieAccess
@@ -99,15 +91,15 @@ export function initCookieStrategy(
9991
return {
10092
async setSessionState(
10193
fn: (sessionState: SessionState) => SessionState,
102-
operation: SessionStateOperation
94+
_operation: SessionStateOperation
10395
): Promise<void> {
10496
if (typeof navigator !== 'undefined' && navigator.locks) {
105-
const lockRequestedAt = dateNow()
10697
await navigator.locks
10798
.request(SESSION_STORE_KEY, () => applyAndWrite(fn))
108-
.catch(async (error) => {
109-
const context = await buildLockErrorContext(operation, initTimestamp, lockRequestedAt)
110-
addTelemetryError(error, context)
99+
.catch((error: unknown) => {
100+
if (isContextGoingAwayError(error)) {
101+
return
102+
}
111103
throw error
112104
})
113105
} else {
@@ -119,76 +111,14 @@ export function initCookieStrategy(
119111
}
120112
}
121113

122-
interface LockQuerySnapshot {
123-
heldByOthers: number
124-
pendingCount: number
125-
isPending: boolean
126-
}
127-
128-
async function queryLockSnapshot(): Promise<LockQuerySnapshot | 'timeout' | 'unavailable' | 'error'> {
129-
if (typeof navigator === 'undefined' || !navigator.locks?.query) {
130-
return 'unavailable'
131-
}
132-
let timeoutId: ReturnType<typeof setTimeout> | undefined
133-
const timeout = new Promise<'timeout'>((resolve) => {
134-
timeoutId = setTimeout(() => resolve('timeout'), LOCK_QUERY_TIMEOUT)
135-
})
136-
try {
137-
const snapshot = await Promise.race([navigator.locks.query(), timeout])
138-
if (snapshot === 'timeout') {
139-
return 'timeout'
140-
}
141-
const held = snapshot.held ?? []
142-
const pending = snapshot.pending ?? []
143-
return {
144-
heldByOthers: held.filter((lock) => lock.name === SESSION_STORE_KEY).length,
145-
pendingCount: pending.filter((lock) => lock.name === SESSION_STORE_KEY).length,
146-
isPending: pending.some((lock) => lock.name === SESSION_STORE_KEY),
147-
}
148-
} catch {
149-
return 'error'
150-
} finally {
151-
clearTimeout(timeoutId)
152-
}
153-
}
154-
155-
function getNavigationType(): string | undefined {
156-
if (typeof performance === 'undefined' || typeof performance.getEntriesByType !== 'function') {
157-
return undefined
158-
}
159-
// The document-load entry is what we want here ('back_forward' signals bfcache restore).
160-
// Some Chromium builds expose extra entries for experimental soft navigations β€” index 0 is
161-
// still the original document-load entry per the Performance Timeline ordering.
162-
const entry = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming | undefined
163-
return entry?.type
164-
}
165-
166-
function isInIframe(): boolean | undefined {
167-
try {
168-
return window !== window.top
169-
} catch {
170-
// Cross-origin access β€” definitely in an iframe
171-
return true
172-
}
173-
}
174-
175-
async function buildLockErrorContext(
176-
operation: SessionStateOperation,
177-
initTimestamp: number,
178-
lockRequestedAt: number
179-
): Promise<Context> {
180-
return {
181-
operation,
182-
timeSinceInit: dateNow() - initTimestamp,
183-
lockRequestDuration: dateNow() - lockRequestedAt,
184-
visibilityState: document.visibilityState,
185-
readyState: document.readyState,
186-
inIframe: isInIframe(),
187-
navigationType: getNavigationType(),
188-
sessionCookies: getCookies(SESSION_STORE_KEY),
189-
lockQuery: (await queryLockSnapshot()) as Context[string],
190-
...getLifecycleContext(),
114+
// Thrown when the browsing context tears down mid-lock-request.
115+
// - "AbortError: Promise was rejected because the browsing context is going away" (Webkit)
116+
// - "Error: Failed to execute 'request' on 'LockManager': The provided callback is no longer runnable." (Chromium)
117+
function isContextGoingAwayError(error: unknown): boolean {
118+
if (!(error instanceof Error)) {
119+
return false
191120
}
121+
return error.name === 'AbortError' || error.message.includes('no longer runnable')
192122
}
193123

194124
export function createCookieAccess(

β€Žscripts/lib/gitmoji.tsβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export const GITMOJI: readonly Gitmoji[] = [
2929
{ emoji: '🚨', label: 'Linting', category: 'internal' },
3030
{ emoji: '🧹', label: 'Cleanup', category: 'internal' },
3131
{ emoji: 'πŸ”Š', label: 'Logging', category: 'internal' },
32+
{ emoji: 'πŸ”‡', label: 'Remove logs', category: 'internal' },
3233
]
3334

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

0 commit comments

Comments
Β (0)