diff --git a/src/attribution/onCLS.ts b/src/attribution/onCLS.ts index 7197a4c0..95b75187 100644 --- a/src/attribution/onCLS.ts +++ b/src/attribution/onCLS.ts @@ -25,7 +25,7 @@ import { } from '../types.js'; const getLargestLayoutShiftEntry = (entries: LayoutShift[]) => { - return entries.reduce((a, b) => (a?.value > b.value ? a : b)); + return entries.reduce((a, b) => (a.value > b.value ? a : b)); }; const getLargestLayoutShiftSource = (sources: LayoutShiftAttribution[]) => { @@ -53,7 +53,12 @@ const attributeCLS = (metric: CLSMetric): CLSMetricWithAttribution => { } } - return {...metric, attribution}; + // Use `Object.assign()` to ensure the original metric object is returned. + const metricWithAttribution: CLSMetricWithAttribution = Object.assign( + metric, + {attribution}, + ); + return metricWithAttribution; }; /** diff --git a/src/attribution/onFCP.ts b/src/attribution/onFCP.ts index aec0524f..5cc1143d 100644 --- a/src/attribution/onFCP.ts +++ b/src/attribution/onFCP.ts @@ -51,7 +51,12 @@ const attributeFCP = (metric: FCPMetric): FCPMetricWithAttribution => { } } - return {...metric, attribution}; + // Use `Object.assign()` to ensure the original metric object is returned. + const metricWithAttribution: FCPMetricWithAttribution = Object.assign( + metric, + {attribution}, + ); + return metricWithAttribution; }; /** diff --git a/src/attribution/onINP.ts b/src/attribution/onINP.ts index cc4876a2..41b1c903 100644 --- a/src/attribution/onINP.ts +++ b/src/attribution/onINP.ts @@ -219,7 +219,7 @@ const getIntersectingLoAFs = ( start: DOMHighResTimeStamp, end: DOMHighResTimeStamp, ) => { - const intersectingLoAFs = []; + const intersectingLoAFs: PerformanceLongAnimationFrameTiming[] = []; for (const loaf of pendingLoAFs) { // If the LoAF ends before the given start time, ignore it. @@ -281,7 +281,12 @@ const attributeINP = (metric: INPMetric): INPMetricWithAttribution => { loadState: getLoadState(firstEntry.startTime), }; - return {...metric, attribution}; + // Use `Object.assign()` to ensure the original metric object is returned. + const metricWithAttribution: INPMetricWithAttribution = Object.assign( + metric, + {attribution}, + ); + return metricWithAttribution; }; /** diff --git a/src/attribution/onLCP.ts b/src/attribution/onLCP.ts index 932099e6..3f91d68e 100644 --- a/src/attribution/onLCP.ts +++ b/src/attribution/onLCP.ts @@ -84,7 +84,12 @@ const attributeLCP = (metric: LCPMetric): LCPMetricWithAttribution => { } } - return {...metric, attribution}; + // Use `Object.assign()` to ensure the original metric object is returned. + const metricWithAttribution: LCPMetricWithAttribution = Object.assign( + metric, + {attribution}, + ); + return metricWithAttribution; }; /** diff --git a/src/attribution/onTTFB.ts b/src/attribution/onTTFB.ts index cb19b5e2..5e96b408 100644 --- a/src/attribution/onTTFB.ts +++ b/src/attribution/onTTFB.ts @@ -73,7 +73,12 @@ const attributeTTFB = (metric: TTFBMetric): TTFBMetricWithAttribution => { }; } - return {...metric, attribution}; + // Use `Object.assign()` to ensure the original metric object is returned. + const metricWithAttribution: TTFBMetricWithAttribution = Object.assign( + metric, + {attribution}, + ); + return metricWithAttribution; }; /** diff --git a/src/lib/getNavigationEntry.ts b/src/lib/getNavigationEntry.ts index 42bdf3f2..5fa79bdd 100644 --- a/src/lib/getNavigationEntry.ts +++ b/src/lib/getNavigationEntry.ts @@ -22,12 +22,15 @@ export const getNavigationEntry = (): PerformanceNavigationTiming | void => { // In some cases no value is reported by the browser (for // privacy/security reasons), and in other cases (bugs) the value is // negative or is larger than the current page time. Ignore these cases: - // https://github.com/GoogleChrome/web-vitals/issues/137 - // https://github.com/GoogleChrome/web-vitals/issues/162 - // https://github.com/GoogleChrome/web-vitals/issues/275 + // - https://github.com/GoogleChrome/web-vitals/issues/137 + // - https://github.com/GoogleChrome/web-vitals/issues/162 + // - https://github.com/GoogleChrome/web-vitals/issues/275 if ( - navigationEntry?.responseStart > 0 && - navigationEntry?.responseStart < globalThis.performance?.now() + navigationEntry && + navigationEntry.responseStart > 0 && + // Note: if `navigationEnrtry` exists, then we don't need to + // feature-detect `performance.now()`. + navigationEntry.responseStart < performance.now() ) { return navigationEntry; } diff --git a/src/lib/observe.ts b/src/lib/observe.ts index 06d4aece..56fca7b4 100644 --- a/src/lib/observe.ts +++ b/src/lib/observe.ts @@ -48,7 +48,7 @@ export const observe = ( callback(list.getEntries() as PerformanceEntryMap[K]); }); }); - po.observe({type, buffered: true, ...opts} as PerformanceObserverInit); + po.observe({type, buffered: true, ...opts}); return po; } } catch { diff --git a/src/onINP.ts b/src/onINP.ts index 0f9312cc..63205d25 100644 --- a/src/onINP.ts +++ b/src/onINP.ts @@ -66,8 +66,12 @@ export const onINP = ( opts: ReportOpts = {}, ) => { // Return if the browser doesn't support all APIs needed to measure INP. - const eventTimingProto = globalThis.PerformanceEventTiming?.prototype; - if (!(eventTimingProto && 'interactionId' in eventTimingProto)) { + if ( + !( + globalThis.PerformanceEventTiming && + 'interactionId' in PerformanceEventTiming.prototype + ) + ) { return; } @@ -92,7 +96,7 @@ export const onINP = ( const inp = estimateP98LongestInteraction(); - if (inp?.latency !== metric.value) { + if (inp && inp.latency !== metric.value) { metric.value = inp.latency; metric.entries = inp.entries; report();