Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@sentry-internal/browser-utils

Package Overview
Dependencies
Maintainers
9
Versions
75
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sentry-internal/browser-utils - npm Package Compare versions

Comparing version 8.41.0 to 8.42.0

build/cjs/metrics/web-vitals/lib/interactions.js

31

build/cjs/instrument/dom.js

@@ -44,5 +44,7 @@ Object.defineProperty(exports, '__esModule', { value: true });

['EventTarget', 'Node'].forEach((target) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
const proto = (types.WINDOW )[target] && (types.WINDOW )[target].prototype;
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, no-prototype-builtins
const globalObject = types.WINDOW ;
const targetObj = globalObject[target];
const proto = targetObj && targetObj.prototype;
// eslint-disable-next-line no-prototype-builtins
if (!proto || !proto.hasOwnProperty || !proto.hasOwnProperty('addEventListener')) {

@@ -53,12 +55,7 @@ return;

core.fill(proto, 'addEventListener', function (originalAddEventListener) {
return function (
type,
listener,
options,
) {
return function ( type, listener, options) {
if (type === 'click' || type == 'keypress') {
try {
const el = this ;
const handlers = (el.__sentry_instrumentation_handlers__ = el.__sentry_instrumentation_handlers__ || {});
const handlers = (this.__sentry_instrumentation_handlers__ =
this.__sentry_instrumentation_handlers__ || {});
const handlerForType = (handlers[type] = handlers[type] || { refCount: 0 });

@@ -87,12 +84,6 @@

function (originalRemoveEventListener) {
return function (
type,
listener,
options,
) {
return function ( type, listener, options) {
if (type === 'click' || type == 'keypress') {
try {
const el = this ;
const handlers = el.__sentry_instrumentation_handlers__ || {};
const handlers = this.__sentry_instrumentation_handlers__ || {};
const handlerForType = handlers[type];

@@ -111,3 +102,3 @@

if (Object.keys(handlers).length === 0) {
delete el.__sentry_instrumentation_handlers__;
delete this.__sentry_instrumentation_handlers__;
}

@@ -114,0 +105,0 @@ }

@@ -12,4 +12,2 @@ Object.defineProperty(exports, '__esModule', { value: true });

/* eslint-disable max-lines */
const MAX_INT_AS_BYTES = 2147483647;

@@ -357,3 +355,3 @@

) {
const navEntry = getNavigationEntry.getNavigationEntry();
const navEntry = getNavigationEntry.getNavigationEntry(false);
const requestTime = utils.msToSec(navEntry ? navEntry.requestStart : 0);

@@ -600,3 +598,3 @@ // Because performance.measure accepts arbitrary timestamps it can produce

function _addTtfbRequestTimeToMeasurements(_measurements) {
const navEntry = getNavigationEntry.getNavigationEntry();
const navEntry = getNavigationEntry.getNavigationEntry(false);
if (!navEntry) {

@@ -603,0 +601,0 @@ return;

@@ -61,2 +61,3 @@ Object.defineProperty(exports, '__esModule', { value: true });

const po = observe.observe('first-input', handleEntries);
report = bindReporter.bindReporter(onReport, metric, FIDThresholds, opts.reportAllChanges);

@@ -63,0 +64,0 @@

@@ -6,2 +6,3 @@ Object.defineProperty(exports, '__esModule', { value: true });

const initMetric = require('./lib/initMetric.js');
const interactions = require('./lib/interactions.js');
const observe = require('./lib/observe.js');

@@ -11,2 +12,3 @@ const onHidden = require('./lib/onHidden.js');

const whenActivated = require('./lib/whenActivated.js');
const whenIdle = require('./lib/whenIdle.js');

@@ -33,82 +35,3 @@ /*

// Used to store the interaction count after a bfcache restore, since p98
// interaction latencies should only consider the current navigation.
const prevInteractionCount = 0;
/**
* Returns the interaction count since the last bfcache restore (or for the
* full page lifecycle if there were no bfcache restores).
*/
const getInteractionCountForNavigation = () => {
return interactionCountPolyfill.getInteractionCount() - prevInteractionCount;
};
// To prevent unnecessary memory usage on pages with lots of interactions,
// store at most 10 of the longest interactions to consider as INP candidates.
const MAX_INTERACTIONS_TO_CONSIDER = 10;
// A list of longest interactions on the page (by latency) sorted so the
// longest one is first. The list is as most MAX_INTERACTIONS_TO_CONSIDER long.
const longestInteractionList = [];
// A mapping of longest interactions by their interaction ID.
// This is used for faster lookup.
const longestInteractionMap = {};
/**
* Takes a performance entry and adds it to the list of worst interactions
* if its duration is long enough to make it among the worst. If the
* entry is part of an existing interaction, it is merged and the latency
* and entries list is updated as needed.
*/
const processEntry = (entry) => {
// The least-long of the 10 longest interactions.
const minLongestInteraction = longestInteractionList[longestInteractionList.length - 1];
const existingInteraction = longestInteractionMap[entry.interactionId];
// Only process the entry if it's possibly one of the ten longest,
// or if it's part of an existing interaction.
if (
existingInteraction ||
longestInteractionList.length < MAX_INTERACTIONS_TO_CONSIDER ||
(minLongestInteraction && entry.duration > minLongestInteraction.latency)
) {
// If the interaction already exists, update it. Otherwise create one.
if (existingInteraction) {
existingInteraction.entries.push(entry);
existingInteraction.latency = Math.max(existingInteraction.latency, entry.duration);
} else {
const interaction = {
id: entry.interactionId,
latency: entry.duration,
entries: [entry],
};
longestInteractionMap[interaction.id] = interaction;
longestInteractionList.push(interaction);
}
// Sort the entries by latency (descending) and keep only the top ten.
longestInteractionList.sort((a, b) => b.latency - a.latency);
longestInteractionList.splice(MAX_INTERACTIONS_TO_CONSIDER).forEach(i => {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete longestInteractionMap[i.id];
});
}
};
/**
* Returns the estimated p98 longest interaction based on the stored
* interaction candidates and the interaction count for the current page.
*/
const estimateP98LongestInteraction = () => {
const candidateInteractionIndex = Math.min(
longestInteractionList.length - 1,
Math.floor(getInteractionCountForNavigation() / 50),
);
return longestInteractionList[candidateInteractionIndex];
};
/**
* Calculates the [INP](https://web.dev/articles/inp) value for the current

@@ -141,2 +64,7 @@ * page and calls the `callback` function once the value is ready, along with

const onINP = (onReport, opts = {}) => {
// Return if the browser doesn't support all APIs needed to measure INP.
if (!('PerformanceEventTiming' in types.WINDOW && 'interactionId' in PerformanceEventTiming.prototype)) {
return;
}
whenActivated.whenActivated(() => {

@@ -151,33 +79,19 @@ // TODO(philipwalton): remove once the polyfill is no longer needed.

const handleEntries = (entries) => {
entries.forEach(entry => {
if (entry.interactionId) {
processEntry(entry);
}
// Queue the `handleEntries()` callback in the next idle task.
// This is needed to increase the chances that all event entries that
// occurred between the user interaction and the next paint
// have been dispatched. Note: there is currently an experiment
// running in Chrome (EventTimingKeypressAndCompositionInteractionId)
// 123+ that if rolled out fully may make this no longer necessary.
whenIdle.whenIdle(() => {
entries.forEach(interactions.processInteractionEntry);
// Entries of type `first-input` don't currently have an `interactionId`,
// so to consider them in INP we have to first check that an existing
// entry doesn't match the `duration` and `startTime`.
// Note that this logic assumes that `event` entries are dispatched
// before `first-input` entries. This is true in Chrome (the only browser
// that currently supports INP).
// TODO(philipwalton): remove once crbug.com/1325826 is fixed.
if (entry.entryType === 'first-input') {
const noMatchingEntry = !longestInteractionList.some(interaction => {
return interaction.entries.some(prevEntry => {
return entry.duration === prevEntry.duration && entry.startTime === prevEntry.startTime;
});
});
if (noMatchingEntry) {
processEntry(entry);
}
const inp = interactions.estimateP98LongestInteraction();
if (inp && inp.latency !== metric.value) {
metric.value = inp.latency;
metric.entries = inp.entries;
report();
}
});
const inp = estimateP98LongestInteraction();
if (inp && inp.latency !== metric.value) {
metric.value = inp.latency;
metric.entries = inp.entries;
report();
}
};

@@ -192,4 +106,4 @@

// gained.
durationThreshold: opts.durationThreshold != null ? opts.durationThreshold : 40,
} );
durationThreshold: opts.durationThreshold != null ? opts.durationThreshold : interactions.DEFAULT_DURATION_THRESHOLD,
});

@@ -199,19 +113,8 @@ report = bindReporter.bindReporter(onReport, metric, INPThresholds, opts.reportAllChanges);

if (po) {
// If browser supports interactionId (and so supports INP), also
// observe entries of type `first-input`. This is useful in cases
// Also observe entries of type `first-input`. This is useful in cases
// where the first interaction is less than the `durationThreshold`.
if ('PerformanceEventTiming' in types.WINDOW && 'interactionId' in PerformanceEventTiming.prototype) {
po.observe({ type: 'first-input', buffered: true });
}
po.observe({ type: 'first-input', buffered: true });
onHidden.onHidden(() => {
handleEntries(po.takeRecords() );
// If the interaction count shows that there were interactions but
// none were captured by the PerformanceObserver, report a latency of 0.
if (metric.value < 0 && getInteractionCountForNavigation() > 0) {
metric.value = 0;
metric.entries = [];
}
report(true);

@@ -218,0 +121,0 @@ });

@@ -12,2 +12,3 @@ Object.defineProperty(exports, '__esModule', { value: true });

const whenActivated = require('./lib/whenActivated.js');
const whenIdle = require('./lib/whenIdle.js');

@@ -54,17 +55,23 @@ /*

const handleEntries = (entries) => {
const lastEntry = entries[entries.length - 1] ;
if (lastEntry) {
// If reportAllChanges is set then call this function for each entry,
// otherwise only consider the last one.
if (!opts.reportAllChanges) {
// eslint-disable-next-line no-param-reassign
entries = entries.slice(-1);
}
entries.forEach(entry => {
// Only report if the page wasn't hidden prior to LCP.
if (lastEntry.startTime < visibilityWatcher.firstHiddenTime) {
if (entry.startTime < visibilityWatcher.firstHiddenTime) {
// The startTime attribute returns the value of the renderTime if it is
// not 0, and the value of the loadTime otherwise. The activationStart
// reference is used because LCP should be relative to page activation
// rather than navigation start if the page was prerendered. But in cases
// rather than navigation start if the page was pre-rendered. But in cases
// where `activationStart` occurs after the LCP, this time should be
// clamped at 0.
metric.value = Math.max(lastEntry.startTime - getActivationStart.getActivationStart(), 0);
metric.entries = [lastEntry];
metric.value = Math.max(entry.startTime - getActivationStart.getActivationStart(), 0);
metric.entries = [entry];
report();
}
}
});
};

@@ -90,7 +97,10 @@

['keydown', 'click'].forEach(type => {
// Wrap in a setTimeout so the callback is run in a separate task
// to avoid extending the keyboard/click handler to reduce INP impact
// https://github.com/GoogleChrome/web-vitals/issues/383
if (types.WINDOW.document) {
// Wrap in a setTimeout so the callback is run in a separate task
// to avoid extending the keyboard/click handler to reduce INP impact
// https://github.com/GoogleChrome/web-vitals/issues/383
addEventListener(type, () => setTimeout(stopListening, 0), true);
addEventListener(type, () => whenIdle.whenIdle(stopListening ), {
once: true,
capture: true,
});
}

@@ -97,0 +107,0 @@ });

@@ -25,3 +25,3 @@ Object.defineProperty(exports, '__esModule', { value: true });

const generateUniqueID = () => {
return `v3-${Date.now()}-${Math.floor(Math.random() * (9e12 - 1)) + 1e12}`;
return `v4-${Date.now()}-${Math.floor(Math.random() * (9e12 - 1)) + 1e12}`;
};

@@ -28,0 +28,0 @@

@@ -22,4 +22,22 @@ Object.defineProperty(exports, '__esModule', { value: true });

const getNavigationEntry = () => {
return types.WINDOW.performance && performance.getEntriesByType && performance.getEntriesByType('navigation')[0];
// sentry-specific change:
// add optional param to not check for responseStart (see comment below)
const getNavigationEntry = (checkResponseStart = true) => {
const navigationEntry =
types.WINDOW.performance && types.WINDOW.performance.getEntriesByType && types.WINDOW.performance.getEntriesByType('navigation')[0];
// Check to ensure the `responseStart` property is present and valid.
// 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
if (
// sentry-specific change:
// We don't want to check for responseStart for our own use of `getNavigationEntry`
!checkResponseStart ||
(navigationEntry && navigationEntry.responseStart > 0 && navigationEntry.responseStart < performance.now())
) {
return navigationEntry;
}
};

@@ -26,0 +44,0 @@

@@ -30,3 +30,3 @@ Object.defineProperty(exports, '__esModule', { value: true });

// event logic below).
firstHiddenTime = types.WINDOW.document.visibilityState === 'hidden' && !types.WINDOW.document.prerendering ? 0 : Infinity;
return types.WINDOW.document.visibilityState === 'hidden' && !types.WINDOW.document.prerendering ? 0 : Infinity;
};

@@ -48,4 +48,3 @@

// Remove all listeners now that a `firstHiddenTime` value has been set.
removeEventListener('visibilitychange', onVisibilityUpdate, true);
removeEventListener('prerenderingchange', onVisibilityUpdate, true);
removeChangeListeners();
}

@@ -63,2 +62,7 @@ };

const removeChangeListeners = () => {
removeEventListener('visibilitychange', onVisibilityUpdate, true);
removeEventListener('prerenderingchange', onVisibilityUpdate, true);
};
const getVisibilityWatcher = () => {

@@ -70,3 +74,3 @@ if (types.WINDOW.document && firstHiddenTime < 0) {

// visibilityState.
initHiddenTime();
firstHiddenTime = initHiddenTime();
addChangeListeners();

@@ -73,0 +77,0 @@ }

Object.defineProperty(exports, '__esModule', { value: true });
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**

@@ -4,0 +20,0 @@ * Takes a performance entry type and a callback function, and creates a

@@ -22,2 +22,12 @@ Object.defineProperty(exports, '__esModule', { value: true });

// Sentry-specific change:
// This function's logic was NOT updated to web-vitals 4.2.4 but we continue
// to use the web-vitals 3.5.2 due to us having stricter browser support.
// PR with context that made the changes: https://github.com/GoogleChrome/web-vitals/pull/442/files#r1530492402
// The PR removed listening to the `pagehide` event, in favour of only listening to `visibilitychange` event.
// This is "more correct" but some browsers we still support (Safari 12.1-14.0) don't fully support `visibilitychange`
// or have known bugs w.r.t the `visibilitychange` event.
// TODO (v9): If we decide to drop support for Safari 12.1-14.0, we can use the logic from web-vitals 4.2.4
// In this case, we also need to update the integration tests that currently trigger the `pagehide` event to
// simulate the page being hidden.
const onHidden = (cb) => {

@@ -24,0 +34,0 @@ const onHiddenOrPageHide = (event) => {

@@ -5,2 +5,19 @@ Object.defineProperty(exports, '__esModule', { value: true });

/*
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
let interactionCountEstimate = 0;

@@ -11,3 +28,3 @@ let minKnownInteractionId = Infinity;

const updateEstimate = (entries) => {
(entries ).forEach(e => {
entries.forEach(e => {
if (e.interactionId) {

@@ -14,0 +31,0 @@ minKnownInteractionId = Math.min(minKnownInteractionId, e.interactionId);

@@ -21,5 +21,5 @@ Object.defineProperty(exports, '__esModule', { value: true });

let called = false;
return (arg) => {
return () => {
if (!called) {
cb(arg);
cb();
called = true;

@@ -26,0 +26,0 @@ }

@@ -43,3 +43,3 @@ Object.defineProperty(exports, '__esModule', { value: true });

const handleEntries = (entries) => {
(entries ).forEach(entry => {
entries.forEach(entry => {
if (entry.name === 'first-contentful-paint') {

@@ -46,0 +46,0 @@ po.disconnect();

@@ -65,15 +65,5 @@ Object.defineProperty(exports, '__esModule', { value: true });

whenReady(() => {
const navEntry = getNavigationEntry.getNavigationEntry();
const navigationEntry = getNavigationEntry.getNavigationEntry();
if (navEntry) {
const responseStart = navEntry.responseStart;
// 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
if (responseStart <= 0 || responseStart > performance.now()) return;
if (navigationEntry) {
// The activationStart reference is used because TTFB should be

@@ -83,5 +73,5 @@ // relative to page activation rather than navigation start if the

// after the first byte is received, this time should be clamped at 0.
metric.value = Math.max(responseStart - getActivationStart.getActivationStart(), 0);
metric.value = Math.max(navigationEntry.responseStart - getActivationStart.getActivationStart(), 0);
metric.entries = [navEntry];
metric.entries = [navigationEntry];
report(true);

@@ -88,0 +78,0 @@ }

@@ -42,5 +42,7 @@ import { addHandler, maybeInstrument, triggerHandlers, fill, addNonEnumerableProperty, uuid4 } from '@sentry/core';

['EventTarget', 'Node'].forEach((target) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
const proto = (WINDOW )[target] && (WINDOW )[target].prototype;
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, no-prototype-builtins
const globalObject = WINDOW ;
const targetObj = globalObject[target];
const proto = targetObj && targetObj.prototype;
// eslint-disable-next-line no-prototype-builtins
if (!proto || !proto.hasOwnProperty || !proto.hasOwnProperty('addEventListener')) {

@@ -51,12 +53,7 @@ return;

fill(proto, 'addEventListener', function (originalAddEventListener) {
return function (
type,
listener,
options,
) {
return function ( type, listener, options) {
if (type === 'click' || type == 'keypress') {
try {
const el = this ;
const handlers = (el.__sentry_instrumentation_handlers__ = el.__sentry_instrumentation_handlers__ || {});
const handlers = (this.__sentry_instrumentation_handlers__ =
this.__sentry_instrumentation_handlers__ || {});
const handlerForType = (handlers[type] = handlers[type] || { refCount: 0 });

@@ -85,12 +82,6 @@

function (originalRemoveEventListener) {
return function (
type,
listener,
options,
) {
return function ( type, listener, options) {
if (type === 'click' || type == 'keypress') {
try {
const el = this ;
const handlers = el.__sentry_instrumentation_handlers__ || {};
const handlers = this.__sentry_instrumentation_handlers__ || {};
const handlerForType = handlers[type];

@@ -109,3 +100,3 @@

if (Object.keys(handlers).length === 0) {
delete el.__sentry_instrumentation_handlers__;
delete this.__sentry_instrumentation_handlers__;
}

@@ -112,0 +103,0 @@ }

@@ -10,4 +10,2 @@ import { browserPerformanceTimeOrigin, getActiveSpan, spanToJSON, setMeasurement, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, parseUrl, htmlTreeAsString, getComponentName } from '@sentry/core';

/* eslint-disable max-lines */
const MAX_INT_AS_BYTES = 2147483647;

@@ -355,3 +353,3 @@

) {
const navEntry = getNavigationEntry();
const navEntry = getNavigationEntry(false);
const requestTime = msToSec(navEntry ? navEntry.requestStart : 0);

@@ -598,3 +596,3 @@ // Because performance.measure accepts arbitrary timestamps it can produce

function _addTtfbRequestTimeToMeasurements(_measurements) {
const navEntry = getNavigationEntry();
const navEntry = getNavigationEntry(false);
if (!navEntry) {

@@ -601,0 +599,0 @@ return;

@@ -59,2 +59,3 @@ import { bindReporter } from './lib/bindReporter.js';

const po = observe('first-input', handleEntries);
report = bindReporter(onReport, metric, FIDThresholds, opts.reportAllChanges);

@@ -61,0 +62,0 @@

import { WINDOW } from '../../types.js';
import { bindReporter } from './lib/bindReporter.js';
import { initMetric } from './lib/initMetric.js';
import { DEFAULT_DURATION_THRESHOLD, processInteractionEntry, estimateP98LongestInteraction } from './lib/interactions.js';
import { observe } from './lib/observe.js';
import { onHidden } from './lib/onHidden.js';
import { initInteractionCountPolyfill, getInteractionCount } from './lib/polyfills/interactionCountPolyfill.js';
import { initInteractionCountPolyfill } from './lib/polyfills/interactionCountPolyfill.js';
import { whenActivated } from './lib/whenActivated.js';
import { whenIdle } from './lib/whenIdle.js';

@@ -29,82 +31,3 @@ /*

// Used to store the interaction count after a bfcache restore, since p98
// interaction latencies should only consider the current navigation.
const prevInteractionCount = 0;
/**
* Returns the interaction count since the last bfcache restore (or for the
* full page lifecycle if there were no bfcache restores).
*/
const getInteractionCountForNavigation = () => {
return getInteractionCount() - prevInteractionCount;
};
// To prevent unnecessary memory usage on pages with lots of interactions,
// store at most 10 of the longest interactions to consider as INP candidates.
const MAX_INTERACTIONS_TO_CONSIDER = 10;
// A list of longest interactions on the page (by latency) sorted so the
// longest one is first. The list is as most MAX_INTERACTIONS_TO_CONSIDER long.
const longestInteractionList = [];
// A mapping of longest interactions by their interaction ID.
// This is used for faster lookup.
const longestInteractionMap = {};
/**
* Takes a performance entry and adds it to the list of worst interactions
* if its duration is long enough to make it among the worst. If the
* entry is part of an existing interaction, it is merged and the latency
* and entries list is updated as needed.
*/
const processEntry = (entry) => {
// The least-long of the 10 longest interactions.
const minLongestInteraction = longestInteractionList[longestInteractionList.length - 1];
const existingInteraction = longestInteractionMap[entry.interactionId];
// Only process the entry if it's possibly one of the ten longest,
// or if it's part of an existing interaction.
if (
existingInteraction ||
longestInteractionList.length < MAX_INTERACTIONS_TO_CONSIDER ||
(minLongestInteraction && entry.duration > minLongestInteraction.latency)
) {
// If the interaction already exists, update it. Otherwise create one.
if (existingInteraction) {
existingInteraction.entries.push(entry);
existingInteraction.latency = Math.max(existingInteraction.latency, entry.duration);
} else {
const interaction = {
id: entry.interactionId,
latency: entry.duration,
entries: [entry],
};
longestInteractionMap[interaction.id] = interaction;
longestInteractionList.push(interaction);
}
// Sort the entries by latency (descending) and keep only the top ten.
longestInteractionList.sort((a, b) => b.latency - a.latency);
longestInteractionList.splice(MAX_INTERACTIONS_TO_CONSIDER).forEach(i => {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete longestInteractionMap[i.id];
});
}
};
/**
* Returns the estimated p98 longest interaction based on the stored
* interaction candidates and the interaction count for the current page.
*/
const estimateP98LongestInteraction = () => {
const candidateInteractionIndex = Math.min(
longestInteractionList.length - 1,
Math.floor(getInteractionCountForNavigation() / 50),
);
return longestInteractionList[candidateInteractionIndex];
};
/**
* Calculates the [INP](https://web.dev/articles/inp) value for the current

@@ -137,2 +60,7 @@ * page and calls the `callback` function once the value is ready, along with

const onINP = (onReport, opts = {}) => {
// Return if the browser doesn't support all APIs needed to measure INP.
if (!('PerformanceEventTiming' in WINDOW && 'interactionId' in PerformanceEventTiming.prototype)) {
return;
}
whenActivated(() => {

@@ -147,33 +75,19 @@ // TODO(philipwalton): remove once the polyfill is no longer needed.

const handleEntries = (entries) => {
entries.forEach(entry => {
if (entry.interactionId) {
processEntry(entry);
}
// Queue the `handleEntries()` callback in the next idle task.
// This is needed to increase the chances that all event entries that
// occurred between the user interaction and the next paint
// have been dispatched. Note: there is currently an experiment
// running in Chrome (EventTimingKeypressAndCompositionInteractionId)
// 123+ that if rolled out fully may make this no longer necessary.
whenIdle(() => {
entries.forEach(processInteractionEntry);
// Entries of type `first-input` don't currently have an `interactionId`,
// so to consider them in INP we have to first check that an existing
// entry doesn't match the `duration` and `startTime`.
// Note that this logic assumes that `event` entries are dispatched
// before `first-input` entries. This is true in Chrome (the only browser
// that currently supports INP).
// TODO(philipwalton): remove once crbug.com/1325826 is fixed.
if (entry.entryType === 'first-input') {
const noMatchingEntry = !longestInteractionList.some(interaction => {
return interaction.entries.some(prevEntry => {
return entry.duration === prevEntry.duration && entry.startTime === prevEntry.startTime;
});
});
if (noMatchingEntry) {
processEntry(entry);
}
const inp = estimateP98LongestInteraction();
if (inp && inp.latency !== metric.value) {
metric.value = inp.latency;
metric.entries = inp.entries;
report();
}
});
const inp = estimateP98LongestInteraction();
if (inp && inp.latency !== metric.value) {
metric.value = inp.latency;
metric.entries = inp.entries;
report();
}
};

@@ -188,4 +102,4 @@

// gained.
durationThreshold: opts.durationThreshold != null ? opts.durationThreshold : 40,
} );
durationThreshold: opts.durationThreshold != null ? opts.durationThreshold : DEFAULT_DURATION_THRESHOLD,
});

@@ -195,19 +109,8 @@ report = bindReporter(onReport, metric, INPThresholds, opts.reportAllChanges);

if (po) {
// If browser supports interactionId (and so supports INP), also
// observe entries of type `first-input`. This is useful in cases
// Also observe entries of type `first-input`. This is useful in cases
// where the first interaction is less than the `durationThreshold`.
if ('PerformanceEventTiming' in WINDOW && 'interactionId' in PerformanceEventTiming.prototype) {
po.observe({ type: 'first-input', buffered: true });
}
po.observe({ type: 'first-input', buffered: true });
onHidden(() => {
handleEntries(po.takeRecords() );
// If the interaction count shows that there were interactions but
// none were captured by the PerformanceObserver, report a latency of 0.
if (metric.value < 0 && getInteractionCountForNavigation() > 0) {
metric.value = 0;
metric.entries = [];
}
report(true);

@@ -214,0 +117,0 @@ });

@@ -10,2 +10,3 @@ import { WINDOW } from '../../types.js';

import { whenActivated } from './lib/whenActivated.js';
import { whenIdle } from './lib/whenIdle.js';

@@ -52,17 +53,23 @@ /*

const handleEntries = (entries) => {
const lastEntry = entries[entries.length - 1] ;
if (lastEntry) {
// If reportAllChanges is set then call this function for each entry,
// otherwise only consider the last one.
if (!opts.reportAllChanges) {
// eslint-disable-next-line no-param-reassign
entries = entries.slice(-1);
}
entries.forEach(entry => {
// Only report if the page wasn't hidden prior to LCP.
if (lastEntry.startTime < visibilityWatcher.firstHiddenTime) {
if (entry.startTime < visibilityWatcher.firstHiddenTime) {
// The startTime attribute returns the value of the renderTime if it is
// not 0, and the value of the loadTime otherwise. The activationStart
// reference is used because LCP should be relative to page activation
// rather than navigation start if the page was prerendered. But in cases
// rather than navigation start if the page was pre-rendered. But in cases
// where `activationStart` occurs after the LCP, this time should be
// clamped at 0.
metric.value = Math.max(lastEntry.startTime - getActivationStart(), 0);
metric.entries = [lastEntry];
metric.value = Math.max(entry.startTime - getActivationStart(), 0);
metric.entries = [entry];
report();
}
}
});
};

@@ -88,7 +95,10 @@

['keydown', 'click'].forEach(type => {
// Wrap in a setTimeout so the callback is run in a separate task
// to avoid extending the keyboard/click handler to reduce INP impact
// https://github.com/GoogleChrome/web-vitals/issues/383
if (WINDOW.document) {
// Wrap in a setTimeout so the callback is run in a separate task
// to avoid extending the keyboard/click handler to reduce INP impact
// https://github.com/GoogleChrome/web-vitals/issues/383
addEventListener(type, () => setTimeout(stopListening, 0), true);
addEventListener(type, () => whenIdle(stopListening ), {
once: true,
capture: true,
});
}

@@ -95,0 +105,0 @@ });

@@ -23,3 +23,3 @@ /*

const generateUniqueID = () => {
return `v3-${Date.now()}-${Math.floor(Math.random() * (9e12 - 1)) + 1e12}`;
return `v4-${Date.now()}-${Math.floor(Math.random() * (9e12 - 1)) + 1e12}`;
};

@@ -26,0 +26,0 @@

@@ -20,4 +20,22 @@ import { WINDOW } from '../../../types.js';

const getNavigationEntry = () => {
return WINDOW.performance && performance.getEntriesByType && performance.getEntriesByType('navigation')[0];
// sentry-specific change:
// add optional param to not check for responseStart (see comment below)
const getNavigationEntry = (checkResponseStart = true) => {
const navigationEntry =
WINDOW.performance && WINDOW.performance.getEntriesByType && WINDOW.performance.getEntriesByType('navigation')[0];
// Check to ensure the `responseStart` property is present and valid.
// 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
if (
// sentry-specific change:
// We don't want to check for responseStart for our own use of `getNavigationEntry`
!checkResponseStart ||
(navigationEntry && navigationEntry.responseStart > 0 && navigationEntry.responseStart < performance.now())
) {
return navigationEntry;
}
};

@@ -24,0 +42,0 @@

@@ -28,3 +28,3 @@ import { WINDOW } from '../../../types.js';

// event logic below).
firstHiddenTime = WINDOW.document.visibilityState === 'hidden' && !WINDOW.document.prerendering ? 0 : Infinity;
return WINDOW.document.visibilityState === 'hidden' && !WINDOW.document.prerendering ? 0 : Infinity;
};

@@ -46,4 +46,3 @@

// Remove all listeners now that a `firstHiddenTime` value has been set.
removeEventListener('visibilitychange', onVisibilityUpdate, true);
removeEventListener('prerenderingchange', onVisibilityUpdate, true);
removeChangeListeners();
}

@@ -61,2 +60,7 @@ };

const removeChangeListeners = () => {
removeEventListener('visibilitychange', onVisibilityUpdate, true);
removeEventListener('prerenderingchange', onVisibilityUpdate, true);
};
const getVisibilityWatcher = () => {

@@ -68,3 +72,3 @@ if (WINDOW.document && firstHiddenTime < 0) {

// visibilityState.
initHiddenTime();
firstHiddenTime = initHiddenTime();
addChangeListeners();

@@ -71,0 +75,0 @@ }

@@ -0,1 +1,17 @@

/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**

@@ -2,0 +18,0 @@ * Takes a performance entry type and a callback function, and creates a

@@ -20,2 +20,12 @@ import { WINDOW } from '../../../types.js';

// Sentry-specific change:
// This function's logic was NOT updated to web-vitals 4.2.4 but we continue
// to use the web-vitals 3.5.2 due to us having stricter browser support.
// PR with context that made the changes: https://github.com/GoogleChrome/web-vitals/pull/442/files#r1530492402
// The PR removed listening to the `pagehide` event, in favour of only listening to `visibilitychange` event.
// This is "more correct" but some browsers we still support (Safari 12.1-14.0) don't fully support `visibilitychange`
// or have known bugs w.r.t the `visibilitychange` event.
// TODO (v9): If we decide to drop support for Safari 12.1-14.0, we can use the logic from web-vitals 4.2.4
// In this case, we also need to update the integration tests that currently trigger the `pagehide` event to
// simulate the page being hidden.
const onHidden = (cb) => {

@@ -22,0 +32,0 @@ const onHiddenOrPageHide = (event) => {

import { observe } from '../observe.js';
/*
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
let interactionCountEstimate = 0;

@@ -8,3 +25,3 @@ let minKnownInteractionId = Infinity;

const updateEstimate = (entries) => {
(entries ).forEach(e => {
entries.forEach(e => {
if (e.interactionId) {

@@ -11,0 +28,0 @@ minKnownInteractionId = Math.min(minKnownInteractionId, e.interactionId);

@@ -19,5 +19,5 @@ /*

let called = false;
return (arg) => {
return () => {
if (!called) {
cb(arg);
cb();
called = true;

@@ -24,0 +24,0 @@ }

@@ -41,3 +41,3 @@ import { bindReporter } from './lib/bindReporter.js';

const handleEntries = (entries) => {
(entries ).forEach(entry => {
entries.forEach(entry => {
if (entry.name === 'first-contentful-paint') {

@@ -44,0 +44,0 @@ po.disconnect();

@@ -63,15 +63,5 @@ import { WINDOW } from '../../types.js';

whenReady(() => {
const navEntry = getNavigationEntry();
const navigationEntry = getNavigationEntry();
if (navEntry) {
const responseStart = navEntry.responseStart;
// 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
if (responseStart <= 0 || responseStart > performance.now()) return;
if (navigationEntry) {
// The activationStart reference is used because TTFB should be

@@ -81,5 +71,5 @@ // relative to page activation rather than navigation start if the

// after the first byte is received, this time should be clamped at 0.
metric.value = Math.max(responseStart - getActivationStart(), 0);
metric.value = Math.max(navigationEntry.responseStart - getActivationStart(), 0);
metric.entries = [navEntry];
metric.entries = [navigationEntry];
report(true);

@@ -86,0 +76,0 @@ }

@@ -1,1 +0,1 @@

{"type":"module","version":"8.41.0","sideEffects":false}
{"type":"module","version":"8.42.0","sideEffects":false}

@@ -1,2 +0,2 @@

import { HandlerDataDom } from '@sentry/types';
import { HandlerDataDom } from '@sentry/core';
/**

@@ -3,0 +3,0 @@ * Add an instrumentation handler for when a click or a keypress happens.

@@ -1,2 +0,2 @@

import { HandlerDataHistory } from '@sentry/types';
import { HandlerDataHistory } from '@sentry/core';
/**

@@ -3,0 +3,0 @@ * Add an instrumentation handler for when a fetch request happens.

@@ -1,2 +0,2 @@

import { HandlerDataXhr } from '@sentry/types';
import { HandlerDataXhr } from '@sentry/core';
export declare const SENTRY_XHR_DATA_KEY = "__sentry_xhr_v3__";

@@ -3,0 +3,0 @@ /**

@@ -1,2 +0,2 @@

import { Span } from '@sentry/types';
import { Span } from '@sentry/core';
interface StartTrackingWebVitalsOptions {

@@ -24,3 +24,3 @@ recordClsStandaloneSpans: boolean;

export declare function startTrackingInteractions(): void;
export { startTrackingINP, registerInpInteractionListener } from './inp';
export { registerInpInteractionListener, startTrackingINP } from './inp';
interface AddPerformanceEntriesOptions {

@@ -27,0 +27,0 @@ /**

@@ -1,2 +0,2 @@

import { Span, SpanAttributes, SpanTimeInput, StartSpanOptions } from '@sentry/types';
import { Span, SpanAttributes, SpanTimeInput, StartSpanOptions } from '@sentry/core';
/**

@@ -3,0 +3,0 @@ * Checks if a given value is a valid measurement value.

@@ -1,2 +0,2 @@

import { CLSReportCallback, MetricRatingThresholds, ReportOpts } from './types';
import { CLSMetric, MetricRatingThresholds, ReportOpts } from './types';
/** Thresholds for CLS. See https://web.dev/articles/cls#what_is_a_good_cls_score */

@@ -25,3 +25,3 @@ export declare const CLSThresholds: MetricRatingThresholds;

*/
export declare const onCLS: (onReport: CLSReportCallback, opts?: ReportOpts) => void;
export declare const onCLS: (onReport: (metric: CLSMetric) => void, opts?: ReportOpts) => void;
//# sourceMappingURL=getCLS.d.ts.map

@@ -1,2 +0,2 @@

import { FIDReportCallback, MetricRatingThresholds, ReportOpts } from './types';
import { FIDMetric, MetricRatingThresholds, ReportOpts } from './types';
/** Thresholds for FID. See https://web.dev/articles/fid#what_is_a_good_fid_score */

@@ -13,3 +13,3 @@ export declare const FIDThresholds: MetricRatingThresholds;

*/
export declare const onFID: (onReport: FIDReportCallback, opts?: ReportOpts) => void;
export declare const onFID: (onReport: (metric: FIDMetric) => void, opts?: ReportOpts) => void;
//# sourceMappingURL=getFID.d.ts.map

@@ -1,2 +0,2 @@

import { INPReportCallback, MetricRatingThresholds, ReportOpts } from './types';
import { INPMetric, MetricRatingThresholds, ReportOpts } from './types';
/** Thresholds for INP. See https://web.dev/articles/inp#what_is_a_good_inp_score */

@@ -31,3 +31,3 @@ export declare const INPThresholds: MetricRatingThresholds;

*/
export declare const onINP: (onReport: INPReportCallback, opts?: ReportOpts) => void;
export declare const onINP: (onReport: (metric: INPMetric) => void, opts?: ReportOpts) => void;
//# sourceMappingURL=getINP.d.ts.map

@@ -1,2 +0,2 @@

import { LCPReportCallback, MetricRatingThresholds, ReportOpts } from './types';
import { LCPMetric, MetricRatingThresholds, ReportOpts } from './types';
/** Thresholds for LCP. See https://web.dev/articles/lcp#what_is_a_good_lcp_score */

@@ -15,3 +15,3 @@ export declare const LCPThresholds: MetricRatingThresholds;

*/
export declare const onLCP: (onReport: LCPReportCallback, opts?: ReportOpts) => void;
export declare const onLCP: (onReport: (metric: LCPMetric) => void, opts?: ReportOpts) => void;
//# sourceMappingURL=getLCP.d.ts.map

@@ -1,3 +0,2 @@

import { NavigationTimingPolyfillEntry } from '../types';
export declare const getNavigationEntry: () => PerformanceNavigationTiming | NavigationTimingPolyfillEntry | undefined;
export declare const getNavigationEntry: (checkResponseStart?: boolean) => PerformanceNavigationTiming | void;
//# sourceMappingURL=getNavigationEntry.d.ts.map

@@ -20,4 +20,4 @@ export declare const initMetric: <MetricName extends "CLS" | "FCP" | "FID" | "INP" | "LCP" | "TTFB">(name: MetricName, value?: number) => {

id: string;
navigationType: "navigate" | "prerender" | "reload" | "back-forward" | "back-forward-cache" | "restore";
navigationType: "navigate" | "reload" | "back-forward" | "back-forward-cache" | "prerender" | "restore";
};
//# sourceMappingURL=initMetric.d.ts.map

@@ -1,9 +0,9 @@

import { FirstInputPolyfillEntry, NavigationTimingPolyfillEntry } from '../types';
interface PerformanceEntryMap {
event: PerformanceEventTiming[];
paint: PerformancePaintTiming[];
'first-input': PerformanceEventTiming[];
'layout-shift': LayoutShift[];
'largest-contentful-paint': LargestContentfulPaint[];
'first-input': PerformanceEventTiming[] | FirstInputPolyfillEntry[];
navigation: PerformanceNavigationTiming[] | NavigationTimingPolyfillEntry[];
'long-animation-frame': PerformanceLongAnimationFrameTiming[];
paint: PerformancePaintTiming[];
navigation: PerformanceNavigationTiming[];
resource: PerformanceResourceTiming[];

@@ -10,0 +10,0 @@ longtask: PerformanceEntry[];

@@ -1,5 +0,2 @@

export interface RunOnceCallback {
(arg: unknown): void;
}
export declare const runOnce: (cb: RunOnceCallback) => (arg: unknown) => void;
export declare const runOnce: (cb: () => void) => () => void;
//# sourceMappingURL=runOnce.d.ts.map

@@ -1,2 +0,2 @@

import { FCPReportCallback, MetricRatingThresholds, ReportOpts } from './types';
import { FCPMetric, MetricRatingThresholds, ReportOpts } from './types';
/** Thresholds for FCP. See https://web.dev/articles/fcp#what_is_a_good_fcp_score */

@@ -10,3 +10,3 @@ export declare const FCPThresholds: MetricRatingThresholds;

*/
export declare const onFCP: (onReport: FCPReportCallback, opts?: ReportOpts) => void;
export declare const onFCP: (onReport: (metric: FCPMetric) => void, opts?: ReportOpts) => void;
//# sourceMappingURL=onFCP.d.ts.map

@@ -1,2 +0,2 @@

import { MetricRatingThresholds, ReportOpts, TTFBReportCallback } from './types';
import { MetricRatingThresholds, ReportOpts, TTFBMetric } from './types';
/** Thresholds for TTFB. See https://web.dev/articles/ttfb#what_is_a_good_ttfb_score */

@@ -19,3 +19,3 @@ export declare const TTFBThresholds: MetricRatingThresholds;

*/
export declare const onTTFB: (onReport: TTFBReportCallback, opts?: ReportOpts) => void;
export declare const onTTFB: (onReport: (metric: TTFBMetric) => void, opts?: ReportOpts) => void;
//# sourceMappingURL=onTTFB.d.ts.map

@@ -1,2 +0,1 @@

import { FirstInputPolyfillCallback } from './types/polyfills';
export * from './types/base';

@@ -10,12 +9,2 @@ export * from './types/polyfills';

export * from './types/ttfb';
export interface WebVitalsGlobal {
firstInputPolyfill: (onFirstInput: FirstInputPolyfillCallback) => void;
resetFirstInputPolyfill: () => void;
firstHiddenTime: number;
}
declare global {
interface Window {
webVitals: WebVitalsGlobal;
}
}
interface PerformanceEntryMap {

@@ -42,3 +31,3 @@ navigation: PerformanceNavigationTiming;

duration: DOMHighResTimeStamp;
interactionId?: number;
interactionId: number;
}

@@ -56,10 +45,14 @@ interface LayoutShiftAttribution {

interface LargestContentfulPaint extends PerformanceEntry {
renderTime: DOMHighResTimeStamp;
loadTime: DOMHighResTimeStamp;
size: number;
id: string;
url: string;
element?: Element;
readonly renderTime: DOMHighResTimeStamp;
readonly loadTime: DOMHighResTimeStamp;
readonly size: number;
readonly id: string;
readonly url: string;
readonly element: Element | null;
}
interface PerformanceLongAnimationFrameTiming extends PerformanceEntry {
renderStart: DOMHighResTimeStamp;
duration: DOMHighResTimeStamp;
}
}
//# sourceMappingURL=types.d.ts.map

@@ -1,8 +0,7 @@

import { CLSMetric } from './cls';
import { FCPMetric } from './fcp';
import { FIDMetric } from './fid';
import { INPMetric } from './inp';
import { LCPMetric } from './lcp';
import { FirstInputPolyfillEntry, NavigationTimingPolyfillEntry } from './polyfills';
import { TTFBMetric } from './ttfb';
import { CLSMetric, CLSMetricWithAttribution } from './cls';
import { FCPMetric, FCPMetricWithAttribution } from './fcp';
import { FIDMetric, FIDMetricWithAttribution } from './fid';
import { INPMetric, INPMetricWithAttribution } from './inp';
import { LCPMetric, LCPMetricWithAttribution } from './lcp';
import { TTFBMetric, TTFBMetricWithAttribution } from './ttfb';
export interface Metric {

@@ -42,3 +41,3 @@ /**

*/
entries: (PerformanceEntry | LayoutShift | FirstInputPolyfillEntry | NavigationTimingPolyfillEntry)[];
entries: PerformanceEntry[];
/**

@@ -51,2 +50,3 @@ * The type of navigation.

* - 'back-forward-cache': for pages that are restored from the bfcache.
* - 'back_forward' is renamed to 'back-forward' for consistency.
* - 'prerender': for pages that were prerendered.

@@ -60,16 +60,5 @@ * - 'restore': for pages that were discarded by the browser and then

export type MetricType = CLSMetric | FCPMetric | FIDMetric | INPMetric | LCPMetric | TTFBMetric;
/** The union of supported metric attribution types. */
export type MetricWithAttribution = CLSMetricWithAttribution | FCPMetricWithAttribution | FIDMetricWithAttribution | INPMetricWithAttribution | LCPMetricWithAttribution | TTFBMetricWithAttribution;
/**
* A version of the `Metric` that is used with the attribution build.
*/
export interface MetricWithAttribution extends Metric {
/**
* An object containing potentially-helpful debugging information that
* can be sent along with the metric value for the current page visit in
* order to help identify issues happening to real-users in the field.
*/
attribution: {
[key: string]: unknown;
};
}
/**
* The thresholds of metric's "good", "needs improvement", and "poor" ratings.

@@ -91,2 +80,7 @@ *

];
/**
* @deprecated Use metric-specific function types instead, such as:
* `(metric: LCPMetric) => void`. If a single callback type is needed for
* multiple metrics, use `(metric: MetricType) => void`.
*/
export interface ReportCallback {

@@ -93,0 +87,0 @@ (metric: MetricType): void;

@@ -56,14 +56,2 @@ import { LoadState, Metric } from './base';

}
/**
* A CLS-specific version of the ReportCallback function.
*/
export interface CLSReportCallback {
(metric: CLSMetric): void;
}
/**
* A CLS-specific version of the ReportCallback function with attribution.
*/
export interface CLSReportCallbackWithAttribution {
(metric: CLSMetricWithAttribution): void;
}
//# sourceMappingURL=cls.d.ts.map
import { LoadState, Metric } from './base';
import { NavigationTimingPolyfillEntry } from './polyfills';
/**

@@ -40,3 +39,3 @@ * An FCP-specific version of the Metric object.

*/
navigationEntry?: PerformanceNavigationTiming | NavigationTimingPolyfillEntry;
navigationEntry?: PerformanceNavigationTiming;
}

@@ -49,14 +48,2 @@ /**

}
/**
* An FCP-specific version of the ReportCallback function.
*/
export interface FCPReportCallback {
(metric: FCPMetric): void;
}
/**
* An FCP-specific version of the ReportCallback function with attribution.
*/
export interface FCPReportCallbackWithAttribution {
(metric: FCPMetricWithAttribution): void;
}
//# sourceMappingURL=fcp.d.ts.map
import { LoadState, Metric } from './base';
import { FirstInputPolyfillEntry } from './polyfills';
/**

@@ -8,3 +7,3 @@ * An FID-specific version of the Metric object.

name: 'FID';
entries: (PerformanceEventTiming | FirstInputPolyfillEntry)[];
entries: PerformanceEventTiming[];
}

@@ -32,6 +31,5 @@ /**

/**
* The `PerformanceEventTiming` entry corresponding to FID (or the
* polyfill entry in browsers that don't support Event Timing).
* The `PerformanceEventTiming` entry corresponding to FID.
*/
eventEntry: PerformanceEventTiming | FirstInputPolyfillEntry;
eventEntry: PerformanceEventTiming;
/**

@@ -51,14 +49,2 @@ * The loading state of the document at the time when the first interaction

}
/**
* An FID-specific version of the ReportCallback function.
*/
export interface FIDReportCallback {
(metric: FIDMetric): void;
}
/**
* An FID-specific version of the ReportCallback function with attribution.
*/
export interface FIDReportCallbackWithAttribution {
(metric: FIDMetricWithAttribution): void;
}
//# sourceMappingURL=fid.d.ts.map

@@ -16,27 +16,83 @@ import { LoadState, Metric } from './base';

/**
* A selector identifying the element that the user interacted with for
* the event corresponding to INP. This element will be the `target` of the
* `event` dispatched.
* A selector identifying the element that the user first interacted with
* as part of the frame where the INP candidate interaction occurred.
* If this value is an empty string, that generally means the element was
* removed from the DOM after the interaction.
*/
eventTarget?: string;
interactionTarget: string;
/**
* The time when the user interacted for the event corresponding to INP.
* This time will match the `timeStamp` value of the `event` dispatched.
* A reference to the HTML element identified by `interactionTargetSelector`.
* NOTE: for attribution purpose, a selector identifying the element is
* typically more useful than the element itself. However, the element is
* also made available in case additional context is needed.
*/
eventTime?: number;
interactionTargetElement: Node | undefined;
/**
* The `type` of the `event` dispatched corresponding to INP.
* The time when the user first interacted during the frame where the INP
* candidate interaction occurred (if more than one interaction occurred
* within the frame, only the first time is reported).
*/
eventType?: string;
interactionTime: DOMHighResTimeStamp;
/**
* The `PerformanceEventTiming` entry corresponding to INP.
* The best-guess timestamp of the next paint after the interaction.
* In general, this timestamp is the same as the `startTime + duration` of
* the event timing entry. However, since `duration` values are rounded to
* the nearest 8ms, it can sometimes appear that the paint occurred before
* processing ended (which cannot happen). This value clamps the paint time
* so it's always after `processingEnd` from the Event Timing API and
* `renderStart` from the Long Animation Frame API (where available).
* It also averages the duration values for all entries in the same
* animation frame, which should be closer to the "real" value.
*/
eventEntry?: PerformanceEventTiming;
nextPaintTime: DOMHighResTimeStamp;
/**
* The loading state of the document at the time when the event corresponding
* to INP occurred (see `LoadState` for details). If the interaction occurred
* while the document was loading and executing script (e.g. usually in the
* `dom-interactive` phase) it can result in long delays.
* The type of interaction, based on the event type of the `event` entry
* that corresponds to the interaction (i.e. the first `event` entry
* containing an `interactionId` dispatched in a given animation frame).
* For "pointerdown", "pointerup", or "click" events this will be "pointer",
* and for "keydown" or "keyup" events this will be "keyboard".
*/
loadState?: LoadState;
interactionType: 'pointer' | 'keyboard';
/**
* An array of Event Timing entries that were processed within the same
* animation frame as the INP candidate interaction.
*/
processedEventEntries: PerformanceEventTiming[];
/**
* If the browser supports the Long Animation Frame API, this array will
* include any `long-animation-frame` entries that intersect with the INP
* candidate interaction's `startTime` and the `processingEnd` time of the
* last event processed within that animation frame. If the browser does not
* support the Long Animation Frame API or no `long-animation-frame` entries
* are detect, this array will be empty.
*/
longAnimationFrameEntries: PerformanceLongAnimationFrameTiming[];
/**
* The time from when the user interacted with the page until when the
* browser was first able to start processing event listeners for that
* interaction. This time captures the delay before event processing can
* begin due to the main thread being busy with other work.
*/
inputDelay: number;
/**
* The time from when the first event listener started running in response to
* the user interaction until when all event listener processing has finished.
*/
processingDuration: number;
/**
* The time from when the browser finished processing all event listeners for
* the user interaction until the next frame is presented on the screen and
* visible to the user. This time includes work on the main thread (such as
* `requestAnimationFrame()` callbacks, `ResizeObserver` and
* `IntersectionObserver` callbacks, and style/layout calculation) as well
* as off-main-thread work (such as compositor, GPU, and raster work).
*/
presentationDelay: number;
/**
* The loading state of the document at the time when the interaction
* corresponding to INP occurred (see `LoadState` for details). If the
* interaction occurred while the document was loading and executing script
* (e.g. usually in the `dom-interactive` phase) it can result in long delays.
*/
loadState: LoadState;
}

@@ -49,14 +105,2 @@ /**

}
/**
* An INP-specific version of the ReportCallback function.
*/
export interface INPReportCallback {
(metric: INPMetric): void;
}
/**
* An INP-specific version of the ReportCallback function with attribution.
*/
export interface INPReportCallbackWithAttribution {
(metric: INPMetricWithAttribution): void;
}
//# sourceMappingURL=inp.d.ts.map
import { Metric } from './base';
import { NavigationTimingPolyfillEntry } from './polyfills';
/**

@@ -42,3 +41,3 @@ * An LCP-specific version of the Metric object.

*/
resourceLoadTime: number;
resourceLoadDuration: number;
/**

@@ -55,3 +54,3 @@ * The delta between when the LCP resource finishes loading until the LCP

*/
navigationEntry?: PerformanceNavigationTiming | NavigationTimingPolyfillEntry;
navigationEntry?: PerformanceNavigationTiming;
/**

@@ -73,14 +72,2 @@ * The `resource` entry for the LCP resource (if applicable), which is useful

}
/**
* An LCP-specific version of the ReportCallback function.
*/
export interface LCPReportCallback {
(metric: LCPMetric): void;
}
/**
* An LCP-specific version of the ReportCallback function with attribution.
*/
export interface LCPReportCallbackWithAttribution {
(metric: LCPMetricWithAttribution): void;
}
//# sourceMappingURL=lcp.d.ts.map

@@ -5,5 +5,2 @@ export type FirstInputPolyfillEntry = Pick<PerformanceEventTiming, Exclude<keyof PerformanceEventTiming, 'processingEnd'>>;

}
export type NavigationTimingPolyfillEntry = Pick<PerformanceNavigationTiming, Exclude<keyof PerformanceNavigationTiming, 'initiatorType' | 'nextHopProtocol' | 'redirectCount' | 'transferSize' | 'encodedBodySize' | 'decodedBodySize' | 'type'>> & {
type: PerformanceNavigationTiming['type'];
};
//# sourceMappingURL=polyfills.d.ts.map
import { Metric } from './base';
import { NavigationTimingPolyfillEntry } from './polyfills';
/**

@@ -8,3 +7,3 @@ * A TTFB-specific version of the Metric object.

name: 'TTFB';
entries: PerformanceNavigationTiming[] | NavigationTimingPolyfillEntry[];
entries: PerformanceNavigationTiming[];
}

@@ -15,2 +14,6 @@ /**

* to help identify issues happening to real-users in the field.
*
* NOTE: these values are primarily useful for page loads not handled via
* service worker, as browsers differ in what they report when service worker
* is involved, see: https://github.com/w3c/navigation-timing/issues/199
*/

@@ -20,26 +23,34 @@ export interface TTFBAttribution {

* The total time from when the user initiates loading the page to when the
* DNS lookup begins. This includes redirects, service worker startup, and
* HTTP cache lookup times.
* page starts to handle the request. Large values here are typically due
* to HTTP redirects, though other browser processing contributes to this
* duration as well (so even without redirect it's generally not zero).
*/
waitingTime: number;
waitingDuration: number;
/**
* The total time to resolve the DNS for the current request.
* The total time spent checking the HTTP cache for a match. For navigations
* handled via service worker, this duration usually includes service worker
* start-up time as well as time processing `fetch` event listeners, with
* some exceptions, see: https://github.com/w3c/navigation-timing/issues/199
*/
dnsTime: number;
cacheDuration: number;
/**
* The total time to resolve the DNS for the requested domain.
*/
dnsDuration: number;
/**
* The total time to create the connection to the requested domain.
*/
connectionTime: number;
connectionDuration: number;
/**
* The time time from when the request was sent until the first byte of the
* The total time from when the request was sent until the first byte of the
* response was received. This includes network time as well as server
* processing time.
*/
requestTime: number;
requestDuration: number;
/**
* The `navigation` entry of the current page, which is useful for diagnosing
* general page load issues. This can be used to access `serverTiming` for example:
* navigationEntry?.serverTiming
* general page load issues. This can be used to access `serverTiming` for
* example: navigationEntry?.serverTiming
*/
navigationEntry?: PerformanceNavigationTiming | NavigationTimingPolyfillEntry;
navigationEntry?: PerformanceNavigationTiming;
}

@@ -52,14 +63,2 @@ /**

}
/**
* A TTFB-specific version of the ReportCallback function.
*/
export interface TTFBReportCallback {
(metric: TTFBMetric): void;
}
/**
* A TTFB-specific version of the ReportCallback function with attribution.
*/
export interface TTFBReportCallbackWithAttribution {
(metric: TTFBMetricWithAttribution): void;
}
//# sourceMappingURL=ttfb.d.ts.map

@@ -1,2 +0,2 @@

import type { HandlerDataDom } from '@sentry/types';
import type { HandlerDataDom } from '@sentry/core';
/**

@@ -3,0 +3,0 @@ * Add an instrumentation handler for when a click or a keypress happens.

@@ -1,2 +0,2 @@

import type { HandlerDataHistory } from '@sentry/types';
import type { HandlerDataHistory } from '@sentry/core';
/**

@@ -3,0 +3,0 @@ * Add an instrumentation handler for when a fetch request happens.

@@ -1,2 +0,2 @@

import type { HandlerDataXhr } from '@sentry/types';
import type { HandlerDataXhr } from '@sentry/core';
export declare const SENTRY_XHR_DATA_KEY = "__sentry_xhr_v3__";

@@ -3,0 +3,0 @@ /**

@@ -1,2 +0,2 @@

import type { Span } from '@sentry/types';
import type { Span } from '@sentry/core';
interface StartTrackingWebVitalsOptions {

@@ -24,3 +24,3 @@ recordClsStandaloneSpans: boolean;

export declare function startTrackingInteractions(): void;
export { startTrackingINP, registerInpInteractionListener } from './inp';
export { registerInpInteractionListener, startTrackingINP } from './inp';
interface AddPerformanceEntriesOptions {

@@ -27,0 +27,0 @@ /**

@@ -1,2 +0,2 @@

import type { Span, SpanAttributes, SpanTimeInput, StartSpanOptions } from '@sentry/types';
import type { Span, SpanAttributes, SpanTimeInput, StartSpanOptions } from '@sentry/core';
/**

@@ -3,0 +3,0 @@ * Checks if a given value is a valid measurement value.

@@ -1,2 +0,2 @@

import type { CLSReportCallback, MetricRatingThresholds, ReportOpts } from './types';
import type { CLSMetric, MetricRatingThresholds, ReportOpts } from './types';
/** Thresholds for CLS. See https://web.dev/articles/cls#what_is_a_good_cls_score */

@@ -25,3 +25,3 @@ export declare const CLSThresholds: MetricRatingThresholds;

*/
export declare const onCLS: (onReport: CLSReportCallback, opts?: ReportOpts) => void;
export declare const onCLS: (onReport: (metric: CLSMetric) => void, opts?: ReportOpts) => void;
//# sourceMappingURL=getCLS.d.ts.map

@@ -1,2 +0,2 @@

import type { FIDReportCallback, MetricRatingThresholds, ReportOpts } from './types';
import type { FIDMetric, MetricRatingThresholds, ReportOpts } from './types';
/** Thresholds for FID. See https://web.dev/articles/fid#what_is_a_good_fid_score */

@@ -13,3 +13,3 @@ export declare const FIDThresholds: MetricRatingThresholds;

*/
export declare const onFID: (onReport: FIDReportCallback, opts?: ReportOpts) => void;
export declare const onFID: (onReport: (metric: FIDMetric) => void, opts?: ReportOpts) => void;
//# sourceMappingURL=getFID.d.ts.map

@@ -1,2 +0,2 @@

import type { INPReportCallback, MetricRatingThresholds, ReportOpts } from './types';
import type { INPMetric, MetricRatingThresholds, ReportOpts } from './types';
/** Thresholds for INP. See https://web.dev/articles/inp#what_is_a_good_inp_score */

@@ -31,3 +31,3 @@ export declare const INPThresholds: MetricRatingThresholds;

*/
export declare const onINP: (onReport: INPReportCallback, opts?: ReportOpts) => void;
export declare const onINP: (onReport: (metric: INPMetric) => void, opts?: ReportOpts) => void;
//# sourceMappingURL=getINP.d.ts.map

@@ -1,2 +0,2 @@

import type { LCPReportCallback, MetricRatingThresholds, ReportOpts } from './types';
import type { LCPMetric, MetricRatingThresholds, ReportOpts } from './types';
/** Thresholds for LCP. See https://web.dev/articles/lcp#what_is_a_good_lcp_score */

@@ -15,3 +15,3 @@ export declare const LCPThresholds: MetricRatingThresholds;

*/
export declare const onLCP: (onReport: LCPReportCallback, opts?: ReportOpts) => void;
export declare const onLCP: (onReport: (metric: LCPMetric) => void, opts?: ReportOpts) => void;
//# sourceMappingURL=getLCP.d.ts.map

@@ -1,3 +0,2 @@

import type { NavigationTimingPolyfillEntry } from '../types';
export declare const getNavigationEntry: () => PerformanceNavigationTiming | NavigationTimingPolyfillEntry | undefined;
export declare const getNavigationEntry: (checkResponseStart?: boolean) => PerformanceNavigationTiming | void;
//# sourceMappingURL=getNavigationEntry.d.ts.map

@@ -20,4 +20,4 @@ export declare const initMetric: <MetricName extends "CLS" | "FCP" | "FID" | "INP" | "LCP" | "TTFB">(name: MetricName, value?: number) => {

id: string;
navigationType: "navigate" | "prerender" | "reload" | "back-forward" | "back-forward-cache" | "restore";
navigationType: "navigate" | "reload" | "back-forward" | "back-forward-cache" | "prerender" | "restore";
};
//# sourceMappingURL=initMetric.d.ts.map

@@ -1,9 +0,9 @@

import type { FirstInputPolyfillEntry, NavigationTimingPolyfillEntry } from '../types';
interface PerformanceEntryMap {
event: PerformanceEventTiming[];
paint: PerformancePaintTiming[];
'first-input': PerformanceEventTiming[];
'layout-shift': LayoutShift[];
'largest-contentful-paint': LargestContentfulPaint[];
'first-input': PerformanceEventTiming[] | FirstInputPolyfillEntry[];
navigation: PerformanceNavigationTiming[] | NavigationTimingPolyfillEntry[];
'long-animation-frame': PerformanceLongAnimationFrameTiming[];
paint: PerformancePaintTiming[];
navigation: PerformanceNavigationTiming[];
resource: PerformanceResourceTiming[];

@@ -10,0 +10,0 @@ longtask: PerformanceEntry[];

@@ -1,5 +0,2 @@

export interface RunOnceCallback {
(arg: unknown): void;
}
export declare const runOnce: (cb: RunOnceCallback) => (arg: unknown) => void;
export declare const runOnce: (cb: () => void) => () => void;
//# sourceMappingURL=runOnce.d.ts.map

@@ -1,2 +0,2 @@

import type { FCPReportCallback, MetricRatingThresholds, ReportOpts } from './types';
import type { FCPMetric, MetricRatingThresholds, ReportOpts } from './types';
/** Thresholds for FCP. See https://web.dev/articles/fcp#what_is_a_good_fcp_score */

@@ -10,3 +10,3 @@ export declare const FCPThresholds: MetricRatingThresholds;

*/
export declare const onFCP: (onReport: FCPReportCallback, opts?: ReportOpts) => void;
export declare const onFCP: (onReport: (metric: FCPMetric) => void, opts?: ReportOpts) => void;
//# sourceMappingURL=onFCP.d.ts.map

@@ -1,2 +0,2 @@

import type { MetricRatingThresholds, ReportOpts, TTFBReportCallback } from './types';
import type { MetricRatingThresholds, ReportOpts, TTFBMetric } from './types';
/** Thresholds for TTFB. See https://web.dev/articles/ttfb#what_is_a_good_ttfb_score */

@@ -19,3 +19,3 @@ export declare const TTFBThresholds: MetricRatingThresholds;

*/
export declare const onTTFB: (onReport: TTFBReportCallback, opts?: ReportOpts) => void;
export declare const onTTFB: (onReport: (metric: TTFBMetric) => void, opts?: ReportOpts) => void;
//# sourceMappingURL=onTTFB.d.ts.map

@@ -1,2 +0,1 @@

import type { FirstInputPolyfillCallback } from './types/polyfills';
export * from './types/base';

@@ -10,12 +9,2 @@ export * from './types/polyfills';

export * from './types/ttfb';
export interface WebVitalsGlobal {
firstInputPolyfill: (onFirstInput: FirstInputPolyfillCallback) => void;
resetFirstInputPolyfill: () => void;
firstHiddenTime: number;
}
declare global {
interface Window {
webVitals: WebVitalsGlobal;
}
}
interface PerformanceEntryMap {

@@ -42,3 +31,3 @@ navigation: PerformanceNavigationTiming;

duration: DOMHighResTimeStamp;
interactionId?: number;
interactionId: number;
}

@@ -56,10 +45,14 @@ interface LayoutShiftAttribution {

interface LargestContentfulPaint extends PerformanceEntry {
renderTime: DOMHighResTimeStamp;
loadTime: DOMHighResTimeStamp;
size: number;
id: string;
url: string;
element?: Element;
readonly renderTime: DOMHighResTimeStamp;
readonly loadTime: DOMHighResTimeStamp;
readonly size: number;
readonly id: string;
readonly url: string;
readonly element: Element | null;
}
interface PerformanceLongAnimationFrameTiming extends PerformanceEntry {
renderStart: DOMHighResTimeStamp;
duration: DOMHighResTimeStamp;
}
}
//# sourceMappingURL=types.d.ts.map

@@ -1,8 +0,7 @@

import type { CLSMetric } from './cls';
import type { FCPMetric } from './fcp';
import type { FIDMetric } from './fid';
import type { INPMetric } from './inp';
import type { LCPMetric } from './lcp';
import type { FirstInputPolyfillEntry, NavigationTimingPolyfillEntry } from './polyfills';
import type { TTFBMetric } from './ttfb';
import type { CLSMetric, CLSMetricWithAttribution } from './cls';
import type { FCPMetric, FCPMetricWithAttribution } from './fcp';
import type { FIDMetric, FIDMetricWithAttribution } from './fid';
import type { INPMetric, INPMetricWithAttribution } from './inp';
import type { LCPMetric, LCPMetricWithAttribution } from './lcp';
import type { TTFBMetric, TTFBMetricWithAttribution } from './ttfb';
export interface Metric {

@@ -42,3 +41,3 @@ /**

*/
entries: (PerformanceEntry | LayoutShift | FirstInputPolyfillEntry | NavigationTimingPolyfillEntry)[];
entries: PerformanceEntry[];
/**

@@ -51,2 +50,3 @@ * The type of navigation.

* - 'back-forward-cache': for pages that are restored from the bfcache.
* - 'back_forward' is renamed to 'back-forward' for consistency.
* - 'prerender': for pages that were prerendered.

@@ -60,16 +60,5 @@ * - 'restore': for pages that were discarded by the browser and then

export type MetricType = CLSMetric | FCPMetric | FIDMetric | INPMetric | LCPMetric | TTFBMetric;
/** The union of supported metric attribution types. */
export type MetricWithAttribution = CLSMetricWithAttribution | FCPMetricWithAttribution | FIDMetricWithAttribution | INPMetricWithAttribution | LCPMetricWithAttribution | TTFBMetricWithAttribution;
/**
* A version of the `Metric` that is used with the attribution build.
*/
export interface MetricWithAttribution extends Metric {
/**
* An object containing potentially-helpful debugging information that
* can be sent along with the metric value for the current page visit in
* order to help identify issues happening to real-users in the field.
*/
attribution: {
[key: string]: unknown;
};
}
/**
* The thresholds of metric's "good", "needs improvement", and "poor" ratings.

@@ -88,2 +77,7 @@ *

export type MetricRatingThresholds = [number, number];
/**
* @deprecated Use metric-specific function types instead, such as:
* `(metric: LCPMetric) => void`. If a single callback type is needed for
* multiple metrics, use `(metric: MetricType) => void`.
*/
export interface ReportCallback {

@@ -90,0 +84,0 @@ (metric: MetricType): void;

@@ -56,14 +56,2 @@ import type { LoadState, Metric } from './base';

}
/**
* A CLS-specific version of the ReportCallback function.
*/
export interface CLSReportCallback {
(metric: CLSMetric): void;
}
/**
* A CLS-specific version of the ReportCallback function with attribution.
*/
export interface CLSReportCallbackWithAttribution {
(metric: CLSMetricWithAttribution): void;
}
//# sourceMappingURL=cls.d.ts.map
import type { LoadState, Metric } from './base';
import type { NavigationTimingPolyfillEntry } from './polyfills';
/**

@@ -40,3 +39,3 @@ * An FCP-specific version of the Metric object.

*/
navigationEntry?: PerformanceNavigationTiming | NavigationTimingPolyfillEntry;
navigationEntry?: PerformanceNavigationTiming;
}

@@ -49,14 +48,2 @@ /**

}
/**
* An FCP-specific version of the ReportCallback function.
*/
export interface FCPReportCallback {
(metric: FCPMetric): void;
}
/**
* An FCP-specific version of the ReportCallback function with attribution.
*/
export interface FCPReportCallbackWithAttribution {
(metric: FCPMetricWithAttribution): void;
}
//# sourceMappingURL=fcp.d.ts.map
import type { LoadState, Metric } from './base';
import type { FirstInputPolyfillEntry } from './polyfills';
/**

@@ -8,3 +7,3 @@ * An FID-specific version of the Metric object.

name: 'FID';
entries: (PerformanceEventTiming | FirstInputPolyfillEntry)[];
entries: PerformanceEventTiming[];
}

@@ -32,6 +31,5 @@ /**

/**
* The `PerformanceEventTiming` entry corresponding to FID (or the
* polyfill entry in browsers that don't support Event Timing).
* The `PerformanceEventTiming` entry corresponding to FID.
*/
eventEntry: PerformanceEventTiming | FirstInputPolyfillEntry;
eventEntry: PerformanceEventTiming;
/**

@@ -51,14 +49,2 @@ * The loading state of the document at the time when the first interaction

}
/**
* An FID-specific version of the ReportCallback function.
*/
export interface FIDReportCallback {
(metric: FIDMetric): void;
}
/**
* An FID-specific version of the ReportCallback function with attribution.
*/
export interface FIDReportCallbackWithAttribution {
(metric: FIDMetricWithAttribution): void;
}
//# sourceMappingURL=fid.d.ts.map

@@ -16,27 +16,83 @@ import type { LoadState, Metric } from './base';

/**
* A selector identifying the element that the user interacted with for
* the event corresponding to INP. This element will be the `target` of the
* `event` dispatched.
* A selector identifying the element that the user first interacted with
* as part of the frame where the INP candidate interaction occurred.
* If this value is an empty string, that generally means the element was
* removed from the DOM after the interaction.
*/
eventTarget?: string;
interactionTarget: string;
/**
* The time when the user interacted for the event corresponding to INP.
* This time will match the `timeStamp` value of the `event` dispatched.
* A reference to the HTML element identified by `interactionTargetSelector`.
* NOTE: for attribution purpose, a selector identifying the element is
* typically more useful than the element itself. However, the element is
* also made available in case additional context is needed.
*/
eventTime?: number;
interactionTargetElement: Node | undefined;
/**
* The `type` of the `event` dispatched corresponding to INP.
* The time when the user first interacted during the frame where the INP
* candidate interaction occurred (if more than one interaction occurred
* within the frame, only the first time is reported).
*/
eventType?: string;
interactionTime: DOMHighResTimeStamp;
/**
* The `PerformanceEventTiming` entry corresponding to INP.
* The best-guess timestamp of the next paint after the interaction.
* In general, this timestamp is the same as the `startTime + duration` of
* the event timing entry. However, since `duration` values are rounded to
* the nearest 8ms, it can sometimes appear that the paint occurred before
* processing ended (which cannot happen). This value clamps the paint time
* so it's always after `processingEnd` from the Event Timing API and
* `renderStart` from the Long Animation Frame API (where available).
* It also averages the duration values for all entries in the same
* animation frame, which should be closer to the "real" value.
*/
eventEntry?: PerformanceEventTiming;
nextPaintTime: DOMHighResTimeStamp;
/**
* The loading state of the document at the time when the event corresponding
* to INP occurred (see `LoadState` for details). If the interaction occurred
* while the document was loading and executing script (e.g. usually in the
* `dom-interactive` phase) it can result in long delays.
* The type of interaction, based on the event type of the `event` entry
* that corresponds to the interaction (i.e. the first `event` entry
* containing an `interactionId` dispatched in a given animation frame).
* For "pointerdown", "pointerup", or "click" events this will be "pointer",
* and for "keydown" or "keyup" events this will be "keyboard".
*/
loadState?: LoadState;
interactionType: 'pointer' | 'keyboard';
/**
* An array of Event Timing entries that were processed within the same
* animation frame as the INP candidate interaction.
*/
processedEventEntries: PerformanceEventTiming[];
/**
* If the browser supports the Long Animation Frame API, this array will
* include any `long-animation-frame` entries that intersect with the INP
* candidate interaction's `startTime` and the `processingEnd` time of the
* last event processed within that animation frame. If the browser does not
* support the Long Animation Frame API or no `long-animation-frame` entries
* are detect, this array will be empty.
*/
longAnimationFrameEntries: PerformanceLongAnimationFrameTiming[];
/**
* The time from when the user interacted with the page until when the
* browser was first able to start processing event listeners for that
* interaction. This time captures the delay before event processing can
* begin due to the main thread being busy with other work.
*/
inputDelay: number;
/**
* The time from when the first event listener started running in response to
* the user interaction until when all event listener processing has finished.
*/
processingDuration: number;
/**
* The time from when the browser finished processing all event listeners for
* the user interaction until the next frame is presented on the screen and
* visible to the user. This time includes work on the main thread (such as
* `requestAnimationFrame()` callbacks, `ResizeObserver` and
* `IntersectionObserver` callbacks, and style/layout calculation) as well
* as off-main-thread work (such as compositor, GPU, and raster work).
*/
presentationDelay: number;
/**
* The loading state of the document at the time when the interaction
* corresponding to INP occurred (see `LoadState` for details). If the
* interaction occurred while the document was loading and executing script
* (e.g. usually in the `dom-interactive` phase) it can result in long delays.
*/
loadState: LoadState;
}

@@ -49,14 +105,2 @@ /**

}
/**
* An INP-specific version of the ReportCallback function.
*/
export interface INPReportCallback {
(metric: INPMetric): void;
}
/**
* An INP-specific version of the ReportCallback function with attribution.
*/
export interface INPReportCallbackWithAttribution {
(metric: INPMetricWithAttribution): void;
}
//# sourceMappingURL=inp.d.ts.map
import type { Metric } from './base';
import type { NavigationTimingPolyfillEntry } from './polyfills';
/**

@@ -42,3 +41,3 @@ * An LCP-specific version of the Metric object.

*/
resourceLoadTime: number;
resourceLoadDuration: number;
/**

@@ -55,3 +54,3 @@ * The delta between when the LCP resource finishes loading until the LCP

*/
navigationEntry?: PerformanceNavigationTiming | NavigationTimingPolyfillEntry;
navigationEntry?: PerformanceNavigationTiming;
/**

@@ -73,14 +72,2 @@ * The `resource` entry for the LCP resource (if applicable), which is useful

}
/**
* An LCP-specific version of the ReportCallback function.
*/
export interface LCPReportCallback {
(metric: LCPMetric): void;
}
/**
* An LCP-specific version of the ReportCallback function with attribution.
*/
export interface LCPReportCallbackWithAttribution {
(metric: LCPMetricWithAttribution): void;
}
//# sourceMappingURL=lcp.d.ts.map

@@ -5,5 +5,2 @@ export type FirstInputPolyfillEntry = Omit<PerformanceEventTiming, 'processingEnd'>;

}
export type NavigationTimingPolyfillEntry = Omit<PerformanceNavigationTiming, 'initiatorType' | 'nextHopProtocol' | 'redirectCount' | 'transferSize' | 'encodedBodySize' | 'decodedBodySize' | 'type'> & {
type: PerformanceNavigationTiming['type'];
};
//# sourceMappingURL=polyfills.d.ts.map
import type { Metric } from './base';
import type { NavigationTimingPolyfillEntry } from './polyfills';
/**

@@ -8,3 +7,3 @@ * A TTFB-specific version of the Metric object.

name: 'TTFB';
entries: PerformanceNavigationTiming[] | NavigationTimingPolyfillEntry[];
entries: PerformanceNavigationTiming[];
}

@@ -15,2 +14,6 @@ /**

* to help identify issues happening to real-users in the field.
*
* NOTE: these values are primarily useful for page loads not handled via
* service worker, as browsers differ in what they report when service worker
* is involved, see: https://github.com/w3c/navigation-timing/issues/199
*/

@@ -20,26 +23,34 @@ export interface TTFBAttribution {

* The total time from when the user initiates loading the page to when the
* DNS lookup begins. This includes redirects, service worker startup, and
* HTTP cache lookup times.
* page starts to handle the request. Large values here are typically due
* to HTTP redirects, though other browser processing contributes to this
* duration as well (so even without redirect it's generally not zero).
*/
waitingTime: number;
waitingDuration: number;
/**
* The total time to resolve the DNS for the current request.
* The total time spent checking the HTTP cache for a match. For navigations
* handled via service worker, this duration usually includes service worker
* start-up time as well as time processing `fetch` event listeners, with
* some exceptions, see: https://github.com/w3c/navigation-timing/issues/199
*/
dnsTime: number;
cacheDuration: number;
/**
* The total time to resolve the DNS for the requested domain.
*/
dnsDuration: number;
/**
* The total time to create the connection to the requested domain.
*/
connectionTime: number;
connectionDuration: number;
/**
* The time time from when the request was sent until the first byte of the
* The total time from when the request was sent until the first byte of the
* response was received. This includes network time as well as server
* processing time.
*/
requestTime: number;
requestDuration: number;
/**
* The `navigation` entry of the current page, which is useful for diagnosing
* general page load issues. This can be used to access `serverTiming` for example:
* navigationEntry?.serverTiming
* general page load issues. This can be used to access `serverTiming` for
* example: navigationEntry?.serverTiming
*/
navigationEntry?: PerformanceNavigationTiming | NavigationTimingPolyfillEntry;
navigationEntry?: PerformanceNavigationTiming;
}

@@ -52,14 +63,2 @@ /**

}
/**
* A TTFB-specific version of the ReportCallback function.
*/
export interface TTFBReportCallback {
(metric: TTFBMetric): void;
}
/**
* A TTFB-specific version of the ReportCallback function with attribution.
*/
export interface TTFBReportCallbackWithAttribution {
(metric: TTFBMetricWithAttribution): void;
}
//# sourceMappingURL=ttfb.d.ts.map
{
"name": "@sentry-internal/browser-utils",
"version": "8.41.0",
"version": "8.42.0",
"description": "Browser Utilities for all Sentry JavaScript SDKs",

@@ -42,4 +42,3 @@ "repository": "git://github.com/getsentry/sentry-javascript.git",

"dependencies": {
"@sentry/core": "8.41.0",
"@sentry/types": "8.41.0"
"@sentry/core": "8.42.0"
},

@@ -46,0 +45,0 @@ "scripts": {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc