Socket
Socket
Sign inDemoInstall

@datadog/browser-rum-core

Package Overview
Dependencies
Maintainers
1
Versions
177
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@datadog/browser-rum-core - npm Package Compare versions

Comparing version 5.18.0 to 5.19.0

cjs/domain/discardNegativeDuration.d.ts

7

cjs/browser/polyfills.d.ts

@@ -19,1 +19,8 @@ export declare function cssEscape(str: string): string;

export declare function getClassList(element: Element): DOMTokenList | string[];
export declare class WeakSet<T extends object> {
private map;
constructor(initialValues?: T[]);
add(value: T): this;
delete(value: T): boolean;
has(value: T): boolean;
}

34

cjs/browser/polyfills.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getClassList = exports.getParentElement = exports.elementMatches = exports.cssEscape = void 0;
exports.WeakSet = exports.getClassList = exports.getParentElement = exports.elementMatches = exports.cssEscape = void 0;
// https://github.com/jquery/jquery/blob/a684e6ba836f7c553968d7d026ed7941e1a612d8/src/selector/escapeSelector.js

@@ -53,11 +53,2 @@ function cssEscape(str) {

exports.getParentElement = getParentElement;
// let parentNode = node.parentNode
// while (parentNode !== null && parentNode.nodeType !== Node.ELEMENT_NODE) {
// parentNode = node.parentNode
// }
// let parentNode = document.querySelector('span').parentNode
// while (parentNode !== null && parentNode.nodeType !== Node.ELEMENT_NODE) {
// parentNode = node.parentNode
// }
// console.log(parentNode)
/**

@@ -79,2 +70,25 @@ * Return the classList of an element or an array of classes if classList is not supported

exports.getClassList = getClassList;
// ie11 supports WeakMap but not WeakSet
var PLACEHOLDER = 1;
var WeakSet = /** @class */ (function () {
function WeakSet(initialValues) {
var _this = this;
this.map = new WeakMap();
if (initialValues) {
initialValues.forEach(function (value) { return _this.map.set(value, PLACEHOLDER); });
}
}
WeakSet.prototype.add = function (value) {
this.map.set(value, PLACEHOLDER);
return this;
};
WeakSet.prototype.delete = function (value) {
return this.map.delete(value);
};
WeakSet.prototype.has = function (value) {
return this.map.has(value);
};
return WeakSet;
}());
exports.WeakSet = WeakSet;
//# sourceMappingURL=polyfills.js.map

@@ -5,2 +5,3 @@ "use strict";

var browser_core_1 = require("@datadog/browser-core");
var discardNegativeDuration_1 = require("../discardNegativeDuration");
var trackClickActions_1 = require("./trackClickActions");

@@ -30,3 +31,3 @@ function startActionCollection(lifeCycle, domMutationObservable, configuration, pageStateHistory) {

id: action.id,
loading_time: (0, browser_core_1.toServerDuration)(action.duration),
loading_time: (0, discardNegativeDuration_1.discardNegativeDuration)((0, browser_core_1.toServerDuration)(action.duration)),
frustration: {

@@ -33,0 +34,0 @@ type: action.frustrationTypes,

@@ -18,4 +18,3 @@ import type { Duration, ClocksState, RelativeTime, TimeStamp } from '@datadog/browser-core';

target?: {
selector: string;
selector_with_stable_attributes?: string;
selector: string | undefined;
width: number;

@@ -22,0 +21,0 @@ height: number;

@@ -59,3 +59,3 @@ "use strict";

},
browser_sdk_version: (0, browser_core_1.canUseEventBridge)() ? "5.18.0" : undefined,
browser_sdk_version: (0, browser_core_1.canUseEventBridge)() ? "5.19.0" : undefined,
},

@@ -62,0 +62,0 @@ application: {

@@ -36,3 +36,3 @@ "use strict";

applicationId: initConfiguration.applicationId,
version: initConfiguration.version,
version: initConfiguration.version || undefined,
actionNameAttribute: initConfiguration.actionNameAttribute,

@@ -39,0 +39,0 @@ sessionReplaySampleRate: (_a = initConfiguration.sessionReplaySampleRate) !== null && _a !== void 0 ? _a : 0,

@@ -7,3 +7,3 @@ /**

export declare const STABLE_ATTRIBUTES: string[];
export declare function getSelectorFromElement(targetElement: Element, actionNameAttribute: string | undefined): string;
export declare function getSelectorFromElement(targetElement: Element, actionNameAttribute: string | undefined): string | undefined;
export declare function supportScopeSelector(): boolean;

@@ -39,2 +39,7 @@ "use strict";

function getSelectorFromElement(targetElement, actionNameAttribute) {
if (!isConnected(targetElement)) {
// We cannot compute a selector for a detached element, as we don't have access to all of its
// parents, and we cannot determine if it's unique in the document.
return;
}
var targetElementSelector = '';

@@ -60,6 +65,5 @@ var element = targetElement;

//
// Here, we use the same strategy: if a the value contains a digit, we consider it generated. This
// Here, we use the same strategy: if the value contains a digit, we consider it generated. This
// strategy might be a bit naive and fail in some cases, but there are many fallbacks to generate
// CSS selectors so it should be fine most of the time. We might want to allow customers to
// provide their own `isGeneratedValue` at some point.
// CSS selectors so it should be fine most of the time.
return /[0-9]/.test(value);

@@ -169,2 +173,13 @@ }

exports.supportScopeSelector = supportScopeSelector;
/**
* Polyfill-utility for the `isConnected` property not supported in IE11
*/
function isConnected(element) {
if ('isConnected' in
// cast is to make sure `element` is not inferred as `never` after the check
element) {
return element.isConnected;
}
return element.ownerDocument.documentElement.contains(element);
}
//# sourceMappingURL=getSelectorFromElement.js.map

@@ -12,5 +12,6 @@ import type { RumPerformanceResourceTiming } from '../../browser/performanceCollection';

* - from valid nested entries (with 1 ms error margin)
* - if a single timing match, return the timing
* - filter out timing that were already matched to a request
* - then, if a single timing match, return the timing
* - otherwise we can't decide, return undefined
*/
export declare function matchRequestTiming(request: RequestCompleteEvent): RumPerformanceResourceTiming | undefined;

@@ -5,3 +5,5 @@ "use strict";

var browser_core_1 = require("@datadog/browser-core");
var polyfills_1 = require("../../browser/polyfills");
var resourceUtils_1 = require("./resourceUtils");
var alreadyMatchedEntries = new polyfills_1.WeakSet();
/**

@@ -16,3 +18,4 @@ * Look for corresponding timing in resource timing buffer

* - from valid nested entries (with 1 ms error margin)
* - if a single timing match, return the timing
* - filter out timing that were already matched to a request
* - then, if a single timing match, return the timing
* - otherwise we can't decide, return undefined

@@ -29,4 +32,4 @@ */

var candidates = sameNameEntries
.map(function (entry) { return entry.toJSON(); })
.filter(resourceUtils_1.toValidEntry)
.filter(function (entry) { return !alreadyMatchedEntries.has(entry); })
.filter(function (entry) { return (0, resourceUtils_1.isValidEntry)(entry); })
.filter(function (entry) {

@@ -36,3 +39,4 @@ return isBetween(entry, request.startClocks.relative, endTime({ startTime: request.startClocks.relative, duration: request.duration }));

if (candidates.length === 1) {
return candidates[0];
alreadyMatchedEntries.add(candidates[0]);
return candidates[0].toJSON();
}

@@ -39,0 +43,0 @@ return;

@@ -19,3 +19,3 @@ "use strict";

if (entry.entryType === performanceCollection_1.RumPerformanceEntryType.RESOURCE && !(0, resourceUtils_1.isRequestKind)(entry)) {
var rawEvent = processResourceEntry(entry, configuration, sessionManager, pageStateHistory);
var rawEvent = processResourceEntry(entry, configuration, sessionManager);
if (rawEvent) {

@@ -30,3 +30,2 @@ lifeCycle.notify(12 /* LifeCycleEventType.RAW_RUM_EVENT_COLLECTED */, rawEvent);

function processRequest(request, configuration, sessionManager, pageStateHistory) {
var _a;
var matchingTiming = (0, matchRequestTiming_1.matchRequestTiming)(request);

@@ -42,3 +41,2 @@ var startClocks = matchingTiming ? (0, browser_core_1.relativeToClocks)(matchingTiming.startTime) : request.startClocks;

var duration = computeRequestDuration(pageStateHistory, startClocks, request.duration);
var pageStateInfo = computePageStateInfo(pageStateHistory, startClocks, (_a = matchingTiming === null || matchingTiming === void 0 ? void 0 : matchingTiming.duration) !== null && _a !== void 0 ? _a : request.duration);
var resourceEvent = (0, browser_core_1.combine)({

@@ -58,3 +56,3 @@ date: startClocks.timeStamp,

},
}, tracingInfo, correspondingTimingOverrides, pageStateInfo);
}, tracingInfo, correspondingTimingOverrides);
return {

@@ -74,3 +72,3 @@ startTime: startClocks.relative,

}
function processResourceEntry(entry, configuration, sessionManager, pageStateHistory) {
function processResourceEntry(entry, configuration, sessionManager) {
var startClocks = (0, browser_core_1.relativeToClocks)(entry.startTime);

@@ -84,3 +82,2 @@ var shouldIndex = shouldIndexResource(configuration, sessionManager, startClocks);

var entryMetrics = computePerformanceEntryMetrics(entry);
var pageStateInfo = computePageStateInfo(pageStateHistory, startClocks, entry.duration);
var resourceEvent = (0, browser_core_1.combine)({

@@ -98,3 +95,3 @@ date: startClocks.timeStamp,

},
}, tracingInfo, entryMetrics, pageStateInfo);
}, tracingInfo, entryMetrics);
return {

@@ -151,13 +148,2 @@ startTime: startClocks.relative,

}
function computePageStateInfo(pageStateHistory, startClocks, duration) {
if (!(0, browser_core_1.isExperimentalFeatureEnabled)(browser_core_1.ExperimentalFeature.RESOURCE_PAGE_STATES)) {
return;
}
return {
_dd: {
page_states: pageStateHistory.findAll(startClocks.relative, duration),
page_was_discarded: String(document.wasDiscarded),
},
};
}
function computeRequestDuration(pageStateHistory, startClocks, duration) {

@@ -164,0 +150,0 @@ return !pageStateHistory.wasInPageStateDuringPeriod("frozen" /* PageState.FROZEN */, startClocks.relative, duration)

@@ -19,3 +19,3 @@ import type { ServerDuration } from '@datadog/browser-core';

export declare function computePerformanceResourceDetails(entry: RumPerformanceResourceTiming): PerformanceResourceDetails | undefined;
export declare function toValidEntry(entry: RumPerformanceResourceTiming): RumPerformanceResourceTiming | undefined;
export declare function isValidEntry(entry: RumPerformanceResourceTiming): boolean;
export declare function computeSize(entry: RumPerformanceResourceTiming): {

@@ -22,0 +22,0 @@ size: number;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sanitizeDataUrl = exports.isLongDataUrl = exports.MAX_ATTRIBUTE_VALUE_CHAR_LENGTH = exports.isAllowedRequestUrl = exports.computeSize = exports.toValidEntry = exports.computePerformanceResourceDetails = exports.computePerformanceResourceDuration = exports.isRequestKind = exports.computeResourceKind = exports.FAKE_INITIAL_DOCUMENT = void 0;
exports.sanitizeDataUrl = exports.isLongDataUrl = exports.MAX_ATTRIBUTE_VALUE_CHAR_LENGTH = exports.isAllowedRequestUrl = exports.computeSize = exports.isValidEntry = exports.computePerformanceResourceDetails = exports.computePerformanceResourceDuration = exports.isRequestKind = exports.computeResourceKind = exports.FAKE_INITIAL_DOCUMENT = void 0;
var browser_core_1 = require("@datadog/browser-core");

@@ -69,7 +69,6 @@ exports.FAKE_INITIAL_DOCUMENT = 'initial_document';

function computePerformanceResourceDetails(entry) {
var validEntry = toValidEntry(entry);
if (!validEntry) {
if (!isValidEntry(entry)) {
return undefined;
}
var startTime = validEntry.startTime, fetchStart = validEntry.fetchStart, redirectStart = validEntry.redirectStart, redirectEnd = validEntry.redirectEnd, domainLookupStart = validEntry.domainLookupStart, domainLookupEnd = validEntry.domainLookupEnd, connectStart = validEntry.connectStart, secureConnectionStart = validEntry.secureConnectionStart, connectEnd = validEntry.connectEnd, requestStart = validEntry.requestStart, responseStart = validEntry.responseStart, responseEnd = validEntry.responseEnd;
var startTime = entry.startTime, fetchStart = entry.fetchStart, redirectStart = entry.redirectStart, redirectEnd = entry.redirectEnd, domainLookupStart = entry.domainLookupStart, domainLookupEnd = entry.domainLookupEnd, connectStart = entry.connectStart, secureConnectionStart = entry.secureConnectionStart, connectEnd = entry.connectEnd, requestStart = entry.requestStart, responseStart = entry.responseStart, responseEnd = entry.responseEnd;
var details = {

@@ -98,5 +97,5 @@ download: formatTiming(startTime, responseStart, responseEnd),

exports.computePerformanceResourceDetails = computePerformanceResourceDetails;
function toValidEntry(entry) {
function isValidEntry(entry) {
if ((0, browser_core_1.isExperimentalFeatureEnabled)(browser_core_1.ExperimentalFeature.TOLERANT_RESOURCE_TIMINGS)) {
return entry;
return true;
}

@@ -111,7 +110,5 @@ // Ensure timings are in the right order. On top of filtering out potential invalid

: true;
if (areCommonTimingsInOrder && areRedirectionTimingsInOrder) {
return entry;
}
return areCommonTimingsInOrder && areRedirectionTimingsInOrder;
}
exports.toValidEntry = toValidEntry;
exports.isValidEntry = isValidEntry;
function hasRedirection(entry) {

@@ -118,0 +115,0 @@ return entry.redirectEnd > entry.startTime;

@@ -16,3 +16,3 @@ "use strict";

findTrackedSession: function (startTime) {
var session = sessionManager.findActiveSession(startTime);
var session = sessionManager.findSession(startTime);
if (!session || !isTypeTracked(session.trackingType)) {

@@ -19,0 +19,0 @@ return;

@@ -47,3 +47,3 @@ "use strict";

lifeCycle.subscribe(11 /* LifeCycleEventType.PAGE_EXITED */, function (pageExitEvent) {
if (pageExitEvent.reason === browser_core_1.PageExitReason.UNLOADING || pageExitEvent.reason === browser_core_1.PageExitReason.PAGEHIDE) {
if (pageExitEvent.reason === browser_core_1.PageExitReason.UNLOADING) {
currentView.end();

@@ -50,0 +50,0 @@ }

@@ -5,2 +5,3 @@ "use strict";

var browser_core_1 = require("@datadog/browser-core");
var discardNegativeDuration_1 = require("../discardNegativeDuration");
var trackViews_1 = require("./trackViews");

@@ -57,3 +58,3 @@ function startViewCollection(lifeCycle, configuration, location, domMutationObservable, locationChangeObservable, featureFlagContexts, pageStateHistory, recorderApi, initialViewOptions) {

load_event: (0, browser_core_1.toServerDuration)((_p = view.initialViewMetrics.navigationTimings) === null || _p === void 0 ? void 0 : _p.loadEvent),
loading_time: discardNegativeDuration((0, browser_core_1.toServerDuration)(view.commonViewMetrics.loadingTime)),
loading_time: (0, discardNegativeDuration_1.discardNegativeDuration)((0, browser_core_1.toServerDuration)(view.commonViewMetrics.loadingTime)),
loading_type: view.loadingType,

@@ -98,5 +99,2 @@ long_task: {

}
function discardNegativeDuration(duration) {
return (0, browser_core_1.isNumber)(duration) && duration < 0 ? undefined : duration;
}
//# sourceMappingURL=viewCollection.js.map

@@ -28,2 +28,3 @@ import { noop } from '@datadog/browser-core';

};
export declare const MAX_WINDOW_DURATION: number;
/**

@@ -30,0 +31,0 @@ * Check whether `layout-shift` is supported by the browser.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isLayoutShiftSupported = exports.trackCumulativeLayoutShift = void 0;
exports.isLayoutShiftSupported = exports.MAX_WINDOW_DURATION = exports.trackCumulativeLayoutShift = void 0;
var browser_core_1 = require("@datadog/browser-core");

@@ -32,2 +32,4 @@ var htmlDomUtils_1 = require("../../../browser/htmlDomUtils");

var maxClsValue = 0;
// WeakRef is not supported in IE11 and Safari mobile, but so is the layout shift API, so this code won't be executed in these browsers
var maxClsTarget;
// if no layout shift happen the value should be reported as 0

@@ -42,16 +44,13 @@ callback({

if (entry.entryType === performanceCollection_1.RumPerformanceEntryType.LAYOUT_SHIFT && !entry.hadRecentInput) {
window.update(entry);
if (window.value() > maxClsValue) {
maxClsValue = window.value();
var cls = (0, browser_core_1.round)(maxClsValue, 4);
var clsTarget = window.largestLayoutShiftTarget();
var cslTargetSelector = void 0;
if (clsTarget &&
// Check if the CLS target have been removed from the DOM between the time we collect the target reference and when we compute the selector
clsTarget.isConnected) {
cslTargetSelector = (0, getSelectorFromElement_1.getSelectorFromElement)(clsTarget, configuration.actionNameAttribute);
}
var _a = window.update(entry), cumulatedValue = _a.cumulatedValue, isMaxValue = _a.isMaxValue;
if (isMaxValue) {
var target = getTargetFromSource(entry.sources);
maxClsTarget = target ? new WeakRef(target) : undefined;
}
if (cumulatedValue > maxClsValue) {
maxClsValue = cumulatedValue;
var target = maxClsTarget === null || maxClsTarget === void 0 ? void 0 : maxClsTarget.deref();
callback({
value: cls,
targetSelector: cslTargetSelector,
value: (0, browser_core_1.round)(maxClsValue, 4),
targetSelector: target && (0, getSelectorFromElement_1.getSelectorFromElement)(target, configuration.actionNameAttribute),
});

@@ -67,39 +66,40 @@ }

exports.trackCumulativeLayoutShift = trackCumulativeLayoutShift;
function getTargetFromSource(sources) {
var _a;
if (!sources) {
return;
}
return (_a = (0, browser_core_1.find)(sources, function (source) { return !!source.node && (0, htmlDomUtils_1.isElementNode)(source.node); })) === null || _a === void 0 ? void 0 : _a.node;
}
exports.MAX_WINDOW_DURATION = 5 * browser_core_1.ONE_SECOND;
var MAX_UPDATE_GAP = browser_core_1.ONE_SECOND;
function slidingSessionWindow() {
var value = 0;
var cumulatedValue = 0;
var startTime;
var endTime;
var largestLayoutShift = 0;
var largestLayoutShiftTarget;
var largestLayoutShiftTime;
var maxValue = 0;
return {
update: function (entry) {
var _a, _b;
var shouldCreateNewWindow = startTime === undefined ||
entry.startTime - endTime >= browser_core_1.ONE_SECOND ||
entry.startTime - startTime >= 5 * browser_core_1.ONE_SECOND;
entry.startTime - endTime >= MAX_UPDATE_GAP ||
entry.startTime - startTime >= exports.MAX_WINDOW_DURATION;
var isMaxValue;
if (shouldCreateNewWindow) {
startTime = endTime = entry.startTime;
value = entry.value;
largestLayoutShift = 0;
largestLayoutShiftTarget = undefined;
maxValue = cumulatedValue = entry.value;
isMaxValue = true;
}
else {
value += entry.value;
cumulatedValue += entry.value;
endTime = entry.startTime;
}
if (entry.value > largestLayoutShift) {
largestLayoutShift = entry.value;
largestLayoutShiftTime = entry.startTime;
if ((_a = entry.sources) === null || _a === void 0 ? void 0 : _a.length) {
largestLayoutShiftTarget = (_b = (0, browser_core_1.find)(entry.sources, function (s) { return !!s.node && (0, htmlDomUtils_1.isElementNode)(s.node); })) === null || _b === void 0 ? void 0 : _b.node;
isMaxValue = entry.value > maxValue;
if (isMaxValue) {
maxValue = entry.value;
}
else {
largestLayoutShiftTarget = undefined;
}
}
return {
cumulatedValue: cumulatedValue,
isMaxValue: isMaxValue,
};
},
value: function () { return value; },
largestLayoutShiftTarget: function () { return largestLayoutShiftTarget; },
largestLayoutShiftTime: function () { return largestLayoutShiftTime; },
};

@@ -106,0 +106,0 @@ }

@@ -10,4 +10,2 @@ "use strict";

exports.LCP_MAXIMUM_DELAY = 10 * browser_core_1.ONE_MINUTE;
var wrongLcpReported = false;
var previousLcp;
/**

@@ -43,7 +41,2 @@ * Track the largest contentful paint (LCP) occurring during the initial View. This can yield

}
if ((0, browser_core_1.isExperimentalFeatureEnabled)(browser_core_1.ExperimentalFeature.ZERO_LCP_TELEMETRY)) {
monitorLcpEntries(lcpEntry, entries.filter(function (entry) {
return entry.entryType === performanceCollection_1.RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT;
}));
}
callback({

@@ -64,32 +57,2 @@ value: lcpEntry.startTime,

exports.trackLargestContentfulPaint = trackLargestContentfulPaint;
function monitorLcpEntries(lcpEntry, lcpEntries) {
if (wrongLcpReported) {
return;
}
var wrongLcpDetected = lcpEntry.startTime === 0
? 'LCP with startTime = 0'
: previousLcp !== undefined && lcpEntry.startTime < previousLcp.startTime
? 'LCP with startTime < previous LCP'
: previousLcp !== undefined && lcpEntry.size < previousLcp.size
? 'LCP with size < previous LCP'
: undefined;
if (wrongLcpDetected) {
wrongLcpReported = true;
(0, browser_core_1.addTelemetryDebug)(wrongLcpDetected, {
debug: {
entry: toSerializableLCP(lcpEntry),
previousLcp: previousLcp,
timeOrigin: performance.timeOrigin,
now: (0, browser_core_1.relativeNow)(),
lcpEntries: lcpEntries.map(toSerializableLCP),
},
});
}
previousLcp = toSerializableLCP(lcpEntry);
}
function toSerializableLCP(entry) {
var jsonEntry = entry.toJSON();
delete jsonEntry.element;
return jsonEntry;
}
//# sourceMappingURL=trackLargestContentfulPaint.js.map

@@ -19,1 +19,8 @@ export declare function cssEscape(str: string): string;

export declare function getClassList(element: Element): DOMTokenList | string[];
export declare class WeakSet<T extends object> {
private map;
constructor(initialValues?: T[]);
add(value: T): this;
delete(value: T): boolean;
has(value: T): boolean;
}

@@ -47,11 +47,2 @@ // https://github.com/jquery/jquery/blob/a684e6ba836f7c553968d7d026ed7941e1a612d8/src/selector/escapeSelector.js

}
// let parentNode = node.parentNode
// while (parentNode !== null && parentNode.nodeType !== Node.ELEMENT_NODE) {
// parentNode = node.parentNode
// }
// let parentNode = document.querySelector('span').parentNode
// while (parentNode !== null && parentNode.nodeType !== Node.ELEMENT_NODE) {
// parentNode = node.parentNode
// }
// console.log(parentNode)
/**

@@ -72,2 +63,25 @@ * Return the classList of an element or an array of classes if classList is not supported

}
// ie11 supports WeakMap but not WeakSet
var PLACEHOLDER = 1;
var WeakSet = /** @class */ (function () {
function WeakSet(initialValues) {
var _this = this;
this.map = new WeakMap();
if (initialValues) {
initialValues.forEach(function (value) { return _this.map.set(value, PLACEHOLDER); });
}
}
WeakSet.prototype.add = function (value) {
this.map.set(value, PLACEHOLDER);
return this;
};
WeakSet.prototype.delete = function (value) {
return this.map.delete(value);
};
WeakSet.prototype.has = function (value) {
return this.map.has(value);
};
return WeakSet;
}());
export { WeakSet };
//# sourceMappingURL=polyfills.js.map
import { noop, assign, combine, toServerDuration, generateUUID } from '@datadog/browser-core';
import { discardNegativeDuration } from '../discardNegativeDuration';
import { trackClickActions } from './trackClickActions';

@@ -25,3 +26,3 @@ export function startActionCollection(lifeCycle, domMutationObservable, configuration, pageStateHistory) {

id: action.id,
loading_time: toServerDuration(action.duration),
loading_time: discardNegativeDuration(toServerDuration(action.duration)),
frustration: {

@@ -28,0 +29,0 @@ type: action.frustrationTypes,

@@ -18,4 +18,3 @@ import type { Duration, ClocksState, RelativeTime, TimeStamp } from '@datadog/browser-core';

target?: {
selector: string;
selector_with_stable_attributes?: string;
selector: string | undefined;
width: number;

@@ -22,0 +21,0 @@ height: number;

@@ -56,3 +56,3 @@ import { combine, isEmptyObject, timeStampNow, currentDrift, display, createEventRateLimiter, canUseEventBridge, assign, round, isExperimentalFeatureEnabled, ExperimentalFeature, getConnectivity, } from '@datadog/browser-core';

},
browser_sdk_version: canUseEventBridge() ? "5.18.0" : undefined,
browser_sdk_version: canUseEventBridge() ? "5.19.0" : undefined,
},

@@ -59,0 +59,0 @@ application: {

@@ -33,3 +33,3 @@ import { getType, arrayFrom, isMatchOption, serializeConfiguration, assign, DefaultPrivacyLevel, TraceContextInjection, display, isPercentage, objectHasValue, validateAndBuildConfiguration, } from '@datadog/browser-core';

applicationId: initConfiguration.applicationId,
version: initConfiguration.version,
version: initConfiguration.version || undefined,
actionNameAttribute: initConfiguration.actionNameAttribute,

@@ -36,0 +36,0 @@ sessionReplaySampleRate: (_a = initConfiguration.sessionReplaySampleRate) !== null && _a !== void 0 ? _a : 0,

@@ -7,3 +7,3 @@ /**

export declare const STABLE_ATTRIBUTES: string[];
export declare function getSelectorFromElement(targetElement: Element, actionNameAttribute: string | undefined): string;
export declare function getSelectorFromElement(targetElement: Element, actionNameAttribute: string | undefined): string | undefined;
export declare function supportScopeSelector(): boolean;

@@ -36,2 +36,7 @@ import { cssEscape, getClassList, getParentElement } from '../browser/polyfills';

export function getSelectorFromElement(targetElement, actionNameAttribute) {
if (!isConnected(targetElement)) {
// We cannot compute a selector for a detached element, as we don't have access to all of its
// parents, and we cannot determine if it's unique in the document.
return;
}
var targetElementSelector = '';

@@ -56,6 +61,5 @@ var element = targetElement;

//
// Here, we use the same strategy: if a the value contains a digit, we consider it generated. This
// Here, we use the same strategy: if the value contains a digit, we consider it generated. This
// strategy might be a bit naive and fail in some cases, but there are many fallbacks to generate
// CSS selectors so it should be fine most of the time. We might want to allow customers to
// provide their own `isGeneratedValue` at some point.
// CSS selectors so it should be fine most of the time.
return /[0-9]/.test(value);

@@ -164,2 +168,13 @@ }

}
/**
* Polyfill-utility for the `isConnected` property not supported in IE11
*/
function isConnected(element) {
if ('isConnected' in
// cast is to make sure `element` is not inferred as `never` after the check
element) {
return element.isConnected;
}
return element.ownerDocument.documentElement.contains(element);
}
//# sourceMappingURL=getSelectorFromElement.js.map

@@ -12,5 +12,6 @@ import type { RumPerformanceResourceTiming } from '../../browser/performanceCollection';

* - from valid nested entries (with 1 ms error margin)
* - if a single timing match, return the timing
* - filter out timing that were already matched to a request
* - then, if a single timing match, return the timing
* - otherwise we can't decide, return undefined
*/
export declare function matchRequestTiming(request: RequestCompleteEvent): RumPerformanceResourceTiming | undefined;
import { addDuration } from '@datadog/browser-core';
import { toValidEntry } from './resourceUtils';
import { WeakSet } from '../../browser/polyfills';
import { isValidEntry } from './resourceUtils';
var alreadyMatchedEntries = new WeakSet();
/**

@@ -12,3 +14,4 @@ * Look for corresponding timing in resource timing buffer

* - from valid nested entries (with 1 ms error margin)
* - if a single timing match, return the timing
* - filter out timing that were already matched to a request
* - then, if a single timing match, return the timing
* - otherwise we can't decide, return undefined

@@ -25,4 +28,4 @@ */

var candidates = sameNameEntries
.map(function (entry) { return entry.toJSON(); })
.filter(toValidEntry)
.filter(function (entry) { return !alreadyMatchedEntries.has(entry); })
.filter(function (entry) { return isValidEntry(entry); })
.filter(function (entry) {

@@ -32,3 +35,4 @@ return isBetween(entry, request.startClocks.relative, endTime({ startTime: request.startClocks.relative, duration: request.duration }));

if (candidates.length === 1) {
return candidates[0];
alreadyMatchedEntries.add(candidates[0]);
return candidates[0].toJSON();
}

@@ -35,0 +39,0 @@ return;

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

import { combine, generateUUID, toServerDuration, relativeToClocks, assign, isNumber, isExperimentalFeatureEnabled, ExperimentalFeature, } from '@datadog/browser-core';
import { combine, generateUUID, toServerDuration, relativeToClocks, assign, isNumber, } from '@datadog/browser-core';
import { RumPerformanceEntryType } from '../../browser/performanceCollection';

@@ -16,3 +16,3 @@ import { matchRequestTiming } from './matchRequestTiming';

if (entry.entryType === RumPerformanceEntryType.RESOURCE && !isRequestKind(entry)) {
var rawEvent = processResourceEntry(entry, configuration, sessionManager, pageStateHistory);
var rawEvent = processResourceEntry(entry, configuration, sessionManager);
if (rawEvent) {

@@ -26,3 +26,2 @@ lifeCycle.notify(12 /* LifeCycleEventType.RAW_RUM_EVENT_COLLECTED */, rawEvent);

function processRequest(request, configuration, sessionManager, pageStateHistory) {
var _a;
var matchingTiming = matchRequestTiming(request);

@@ -38,3 +37,2 @@ var startClocks = matchingTiming ? relativeToClocks(matchingTiming.startTime) : request.startClocks;

var duration = computeRequestDuration(pageStateHistory, startClocks, request.duration);
var pageStateInfo = computePageStateInfo(pageStateHistory, startClocks, (_a = matchingTiming === null || matchingTiming === void 0 ? void 0 : matchingTiming.duration) !== null && _a !== void 0 ? _a : request.duration);
var resourceEvent = combine({

@@ -54,3 +52,3 @@ date: startClocks.timeStamp,

},
}, tracingInfo, correspondingTimingOverrides, pageStateInfo);
}, tracingInfo, correspondingTimingOverrides);
return {

@@ -70,3 +68,3 @@ startTime: startClocks.relative,

}
function processResourceEntry(entry, configuration, sessionManager, pageStateHistory) {
function processResourceEntry(entry, configuration, sessionManager) {
var startClocks = relativeToClocks(entry.startTime);

@@ -80,3 +78,2 @@ var shouldIndex = shouldIndexResource(configuration, sessionManager, startClocks);

var entryMetrics = computePerformanceEntryMetrics(entry);
var pageStateInfo = computePageStateInfo(pageStateHistory, startClocks, entry.duration);
var resourceEvent = combine({

@@ -94,3 +91,3 @@ date: startClocks.timeStamp,

},
}, tracingInfo, entryMetrics, pageStateInfo);
}, tracingInfo, entryMetrics);
return {

@@ -147,13 +144,2 @@ startTime: startClocks.relative,

}
function computePageStateInfo(pageStateHistory, startClocks, duration) {
if (!isExperimentalFeatureEnabled(ExperimentalFeature.RESOURCE_PAGE_STATES)) {
return;
}
return {
_dd: {
page_states: pageStateHistory.findAll(startClocks.relative, duration),
page_was_discarded: String(document.wasDiscarded),
},
};
}
function computeRequestDuration(pageStateHistory, startClocks, duration) {

@@ -160,0 +146,0 @@ return !pageStateHistory.wasInPageStateDuringPeriod("frozen" /* PageState.FROZEN */, startClocks.relative, duration)

@@ -19,3 +19,3 @@ import type { ServerDuration } from '@datadog/browser-core';

export declare function computePerformanceResourceDetails(entry: RumPerformanceResourceTiming): PerformanceResourceDetails | undefined;
export declare function toValidEntry(entry: RumPerformanceResourceTiming): RumPerformanceResourceTiming | undefined;
export declare function isValidEntry(entry: RumPerformanceResourceTiming): boolean;
export declare function computeSize(entry: RumPerformanceResourceTiming): {

@@ -22,0 +22,0 @@ size: number;

@@ -63,7 +63,6 @@ import { addTelemetryDebug, elapsed, ExperimentalFeature, getPathName, includes, isExperimentalFeatureEnabled, isValidUrl, toServerDuration, } from '@datadog/browser-core';

export function computePerformanceResourceDetails(entry) {
var validEntry = toValidEntry(entry);
if (!validEntry) {
if (!isValidEntry(entry)) {
return undefined;
}
var startTime = validEntry.startTime, fetchStart = validEntry.fetchStart, redirectStart = validEntry.redirectStart, redirectEnd = validEntry.redirectEnd, domainLookupStart = validEntry.domainLookupStart, domainLookupEnd = validEntry.domainLookupEnd, connectStart = validEntry.connectStart, secureConnectionStart = validEntry.secureConnectionStart, connectEnd = validEntry.connectEnd, requestStart = validEntry.requestStart, responseStart = validEntry.responseStart, responseEnd = validEntry.responseEnd;
var startTime = entry.startTime, fetchStart = entry.fetchStart, redirectStart = entry.redirectStart, redirectEnd = entry.redirectEnd, domainLookupStart = entry.domainLookupStart, domainLookupEnd = entry.domainLookupEnd, connectStart = entry.connectStart, secureConnectionStart = entry.secureConnectionStart, connectEnd = entry.connectEnd, requestStart = entry.requestStart, responseStart = entry.responseStart, responseEnd = entry.responseEnd;
var details = {

@@ -91,5 +90,5 @@ download: formatTiming(startTime, responseStart, responseEnd),

}
export function toValidEntry(entry) {
export function isValidEntry(entry) {
if (isExperimentalFeatureEnabled(ExperimentalFeature.TOLERANT_RESOURCE_TIMINGS)) {
return entry;
return true;
}

@@ -104,5 +103,3 @@ // Ensure timings are in the right order. On top of filtering out potential invalid

: true;
if (areCommonTimingsInOrder && areRedirectionTimingsInOrder) {
return entry;
}
return areCommonTimingsInOrder && areRedirectionTimingsInOrder;
}

@@ -109,0 +106,0 @@ function hasRedirection(entry) {

@@ -13,3 +13,3 @@ import { Observable, bridgeSupports, noop, performDraw, startSessionManager, } from '@datadog/browser-core';

findTrackedSession: function (startTime) {
var session = sessionManager.findActiveSession(startTime);
var session = sessionManager.findSession(startTime);
if (!session || !isTypeTracked(session.trackingType)) {

@@ -16,0 +16,0 @@ return;

@@ -44,3 +44,3 @@ import { noop, PageExitReason, shallowClone, elapsed, generateUUID, ONE_MINUTE, throttle, clocksNow, clocksOrigin, timeStampNow, display, looksLikeRelativeTime, setInterval, clearInterval, setTimeout, Observable, } from '@datadog/browser-core';

lifeCycle.subscribe(11 /* LifeCycleEventType.PAGE_EXITED */, function (pageExitEvent) {
if (pageExitEvent.reason === PageExitReason.UNLOADING || pageExitEvent.reason === PageExitReason.PAGEHIDE) {
if (pageExitEvent.reason === PageExitReason.UNLOADING) {
currentView.end();

@@ -47,0 +47,0 @@ }

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

import { isEmptyObject, mapValues, toServerDuration, isNumber } from '@datadog/browser-core';
import { isEmptyObject, mapValues, toServerDuration } from '@datadog/browser-core';
import { discardNegativeDuration } from '../discardNegativeDuration';
import { trackViews } from './trackViews';

@@ -92,5 +93,2 @@ export function startViewCollection(lifeCycle, configuration, location, domMutationObservable, locationChangeObservable, featureFlagContexts, pageStateHistory, recorderApi, initialViewOptions) {

}
function discardNegativeDuration(duration) {
return isNumber(duration) && duration < 0 ? undefined : duration;
}
//# sourceMappingURL=viewCollection.js.map

@@ -28,2 +28,3 @@ import { noop } from '@datadog/browser-core';

};
export declare const MAX_WINDOW_DURATION: number;
/**

@@ -30,0 +31,0 @@ * Check whether `layout-shift` is supported by the browser.

@@ -29,2 +29,4 @@ import { round, find, ONE_SECOND, noop } from '@datadog/browser-core';

var maxClsValue = 0;
// WeakRef is not supported in IE11 and Safari mobile, but so is the layout shift API, so this code won't be executed in these browsers
var maxClsTarget;
// if no layout shift happen the value should be reported as 0

@@ -39,16 +41,13 @@ callback({

if (entry.entryType === RumPerformanceEntryType.LAYOUT_SHIFT && !entry.hadRecentInput) {
window.update(entry);
if (window.value() > maxClsValue) {
maxClsValue = window.value();
var cls = round(maxClsValue, 4);
var clsTarget = window.largestLayoutShiftTarget();
var cslTargetSelector = void 0;
if (clsTarget &&
// Check if the CLS target have been removed from the DOM between the time we collect the target reference and when we compute the selector
clsTarget.isConnected) {
cslTargetSelector = getSelectorFromElement(clsTarget, configuration.actionNameAttribute);
}
var _a = window.update(entry), cumulatedValue = _a.cumulatedValue, isMaxValue = _a.isMaxValue;
if (isMaxValue) {
var target = getTargetFromSource(entry.sources);
maxClsTarget = target ? new WeakRef(target) : undefined;
}
if (cumulatedValue > maxClsValue) {
maxClsValue = cumulatedValue;
var target = maxClsTarget === null || maxClsTarget === void 0 ? void 0 : maxClsTarget.deref();
callback({
value: cls,
targetSelector: cslTargetSelector,
value: round(maxClsValue, 4),
targetSelector: target && getSelectorFromElement(target, configuration.actionNameAttribute),
});

@@ -63,39 +62,40 @@ }

}
function getTargetFromSource(sources) {
var _a;
if (!sources) {
return;
}
return (_a = find(sources, function (source) { return !!source.node && isElementNode(source.node); })) === null || _a === void 0 ? void 0 : _a.node;
}
export var MAX_WINDOW_DURATION = 5 * ONE_SECOND;
var MAX_UPDATE_GAP = ONE_SECOND;
function slidingSessionWindow() {
var value = 0;
var cumulatedValue = 0;
var startTime;
var endTime;
var largestLayoutShift = 0;
var largestLayoutShiftTarget;
var largestLayoutShiftTime;
var maxValue = 0;
return {
update: function (entry) {
var _a, _b;
var shouldCreateNewWindow = startTime === undefined ||
entry.startTime - endTime >= ONE_SECOND ||
entry.startTime - startTime >= 5 * ONE_SECOND;
entry.startTime - endTime >= MAX_UPDATE_GAP ||
entry.startTime - startTime >= MAX_WINDOW_DURATION;
var isMaxValue;
if (shouldCreateNewWindow) {
startTime = endTime = entry.startTime;
value = entry.value;
largestLayoutShift = 0;
largestLayoutShiftTarget = undefined;
maxValue = cumulatedValue = entry.value;
isMaxValue = true;
}
else {
value += entry.value;
cumulatedValue += entry.value;
endTime = entry.startTime;
}
if (entry.value > largestLayoutShift) {
largestLayoutShift = entry.value;
largestLayoutShiftTime = entry.startTime;
if ((_a = entry.sources) === null || _a === void 0 ? void 0 : _a.length) {
largestLayoutShiftTarget = (_b = find(entry.sources, function (s) { return !!s.node && isElementNode(s.node); })) === null || _b === void 0 ? void 0 : _b.node;
isMaxValue = entry.value > maxValue;
if (isMaxValue) {
maxValue = entry.value;
}
else {
largestLayoutShiftTarget = undefined;
}
}
return {
cumulatedValue: cumulatedValue,
isMaxValue: isMaxValue,
};
},
value: function () { return value; },
largestLayoutShiftTarget: function () { return largestLayoutShiftTarget; },
largestLayoutShiftTime: function () { return largestLayoutShiftTime; },
};

@@ -102,0 +102,0 @@ }

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

import { DOM_EVENT, ExperimentalFeature, ONE_MINUTE, addEventListeners, addTelemetryDebug, findLast, isExperimentalFeatureEnabled, relativeNow, } from '@datadog/browser-core';
import { DOM_EVENT, ONE_MINUTE, addEventListeners, findLast } from '@datadog/browser-core';
import { RumPerformanceEntryType } from '../../../browser/performanceCollection';

@@ -7,4 +7,2 @@ import { getSelectorFromElement } from '../../getSelectorFromElement';

export var LCP_MAXIMUM_DELAY = 10 * ONE_MINUTE;
var wrongLcpReported = false;
var previousLcp;
/**

@@ -40,7 +38,2 @@ * Track the largest contentful paint (LCP) occurring during the initial View. This can yield

}
if (isExperimentalFeatureEnabled(ExperimentalFeature.ZERO_LCP_TELEMETRY)) {
monitorLcpEntries(lcpEntry, entries.filter(function (entry) {
return entry.entryType === RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT;
}));
}
callback({

@@ -60,32 +53,2 @@ value: lcpEntry.startTime,

}
function monitorLcpEntries(lcpEntry, lcpEntries) {
if (wrongLcpReported) {
return;
}
var wrongLcpDetected = lcpEntry.startTime === 0
? 'LCP with startTime = 0'
: previousLcp !== undefined && lcpEntry.startTime < previousLcp.startTime
? 'LCP with startTime < previous LCP'
: previousLcp !== undefined && lcpEntry.size < previousLcp.size
? 'LCP with size < previous LCP'
: undefined;
if (wrongLcpDetected) {
wrongLcpReported = true;
addTelemetryDebug(wrongLcpDetected, {
debug: {
entry: toSerializableLCP(lcpEntry),
previousLcp: previousLcp,
timeOrigin: performance.timeOrigin,
now: relativeNow(),
lcpEntries: lcpEntries.map(toSerializableLCP),
},
});
}
previousLcp = toSerializableLCP(lcpEntry);
}
function toSerializableLCP(entry) {
var jsonEntry = entry.toJSON();
delete jsonEntry.element;
return jsonEntry;
}
//# sourceMappingURL=trackLargestContentfulPaint.js.map
{
"name": "@datadog/browser-rum-core",
"version": "5.18.0",
"version": "5.19.0",
"license": "Apache-2.0",

@@ -15,3 +15,3 @@ "main": "cjs/index.js",

"dependencies": {
"@datadog/browser-core": "5.18.0"
"@datadog/browser-core": "5.19.0"
},

@@ -32,3 +32,3 @@ "devDependencies": {

},
"gitHead": "933517cf9fc2d33f561ac54a07a1f5e8bbab154e"
"gitHead": "ce92533465ebb3c3d0142f0c7d83af471572a818"
}

@@ -53,13 +53,2 @@ // https://github.com/jquery/jquery/blob/a684e6ba836f7c553968d7d026ed7941e1a612d8/src/selector/escapeSelector.js

// let parentNode = node.parentNode
// while (parentNode !== null && parentNode.nodeType !== Node.ELEMENT_NODE) {
// parentNode = node.parentNode
// }
// let parentNode = document.querySelector('span').parentNode
// while (parentNode !== null && parentNode.nodeType !== Node.ELEMENT_NODE) {
// parentNode = node.parentNode
// }
// console.log(parentNode)
/**

@@ -80,1 +69,27 @@ * Return the classList of an element or an array of classes if classList is not supported

}
// ie11 supports WeakMap but not WeakSet
const PLACEHOLDER = 1
export class WeakSet<T extends object> {
private map = new WeakMap<T, typeof PLACEHOLDER>()
constructor(initialValues?: T[]) {
if (initialValues) {
initialValues.forEach((value) => this.map.set(value, PLACEHOLDER))
}
}
add(value: T) {
this.map.set(value, PLACEHOLDER)
return this
}
delete(value: T) {
return this.map.delete(value)
}
has(value: T) {
return this.map.has(value)
}
}
import type { ClocksState, Context, Observable } from '@datadog/browser-core'
import { noop, assign, combine, toServerDuration, generateUUID } from '@datadog/browser-core'
import { discardNegativeDuration } from '../discardNegativeDuration'
import type { RawRumActionEvent } from '../../rawRumEvent.types'

@@ -65,3 +66,3 @@ import { ActionType, RumEventType } from '../../rawRumEvent.types'

id: action.id,
loading_time: toServerDuration(action.duration),
loading_time: discardNegativeDuration(toServerDuration(action.duration)),
frustration: {

@@ -68,0 +69,0 @@ type: action.frustrationTypes,

@@ -41,4 +41,3 @@ import type { Duration, ClocksState, RelativeTime, TimeStamp } from '@datadog/browser-core'

target?: {
selector: string
selector_with_stable_attributes?: string
selector: string | undefined
width: number

@@ -45,0 +44,0 @@ height: number

@@ -115,3 +115,3 @@ import type { Configuration, InitConfiguration, MatchOption, RawTelemetryConfiguration } from '@datadog/browser-core'

applicationId: initConfiguration.applicationId,
version: initConfiguration.version,
version: initConfiguration.version || undefined,
actionNameAttribute: initConfiguration.actionNameAttribute,

@@ -118,0 +118,0 @@ sessionReplaySampleRate: initConfiguration.sessionReplaySampleRate ?? 0,

@@ -41,3 +41,11 @@ import { cssEscape, getClassList, getParentElement } from '../browser/polyfills'

export function getSelectorFromElement(targetElement: Element, actionNameAttribute: string | undefined) {
export function getSelectorFromElement(
targetElement: Element,
actionNameAttribute: string | undefined
): string | undefined {
if (!isConnected(targetElement)) {
// We cannot compute a selector for a detached element, as we don't have access to all of its
// parents, and we cannot determine if it's unique in the document.
return
}
let targetElementSelector = ''

@@ -79,6 +87,5 @@ let element: Element | null = targetElement

//
// Here, we use the same strategy: if a the value contains a digit, we consider it generated. This
// Here, we use the same strategy: if the value contains a digit, we consider it generated. This
// strategy might be a bit naive and fail in some cases, but there are many fallbacks to generate
// CSS selectors so it should be fine most of the time. We might want to allow customers to
// provide their own `isGeneratedValue` at some point.
// CSS selectors so it should be fine most of the time.
return /[0-9]/.test(value)

@@ -207,1 +214,16 @@ }

}
/**
* Polyfill-utility for the `isConnected` property not supported in IE11
*/
function isConnected(element: Element): boolean {
if (
'isConnected' in
// cast is to make sure `element` is not inferred as `never` after the check
(element as { isConnected?: boolean })
) {
return element.isConnected
}
return element.ownerDocument.documentElement.contains(element)
}

@@ -5,3 +5,4 @@ import type { Duration, RelativeTime } from '@datadog/browser-core'

import type { RequestCompleteEvent } from '../requestCollection'
import { toValidEntry } from './resourceUtils'
import { WeakSet } from '../../browser/polyfills'
import { isValidEntry } from './resourceUtils'

@@ -13,2 +14,4 @@ interface Timing {

const alreadyMatchedEntries = new WeakSet<PerformanceEntry>()
/**

@@ -23,3 +26,4 @@ * Look for corresponding timing in resource timing buffer

* - from valid nested entries (with 1 ms error margin)
* - if a single timing match, return the timing
* - filter out timing that were already matched to a request
* - then, if a single timing match, return the timing
* - otherwise we can't decide, return undefined

@@ -31,3 +35,3 @@ */

}
const sameNameEntries = performance.getEntriesByName(request.url, 'resource')
const sameNameEntries = performance.getEntriesByName(request.url, 'resource') as RumPerformanceResourceTiming[]

@@ -39,4 +43,4 @@ if (!sameNameEntries.length || !('toJSON' in sameNameEntries[0])) {

const candidates = sameNameEntries
.map((entry) => entry.toJSON() as RumPerformanceResourceTiming)
.filter(toValidEntry)
.filter((entry) => !alreadyMatchedEntries.has(entry))
.filter((entry) => isValidEntry(entry))
.filter((entry) =>

@@ -51,3 +55,5 @@ isBetween(

if (candidates.length === 1) {
return candidates[0]
alreadyMatchedEntries.add(candidates[0])
return candidates[0].toJSON() as RumPerformanceResourceTiming
}

@@ -54,0 +60,0 @@

@@ -11,4 +11,2 @@ import type { ClocksState, Duration } from '@datadog/browser-core'

isNumber,
isExperimentalFeatureEnabled,
ExperimentalFeature,
} from '@datadog/browser-core'

@@ -54,3 +52,3 @@ import type { RumConfiguration } from '../configuration'

if (entry.entryType === RumPerformanceEntryType.RESOURCE && !isRequestKind(entry)) {
const rawEvent = processResourceEntry(entry, configuration, sessionManager, pageStateHistory)
const rawEvent = processResourceEntry(entry, configuration, sessionManager)
if (rawEvent) {

@@ -83,7 +81,2 @@ lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, rawEvent)

const duration = computeRequestDuration(pageStateHistory, startClocks, request.duration)
const pageStateInfo = computePageStateInfo(
pageStateHistory,
startClocks,
matchingTiming?.duration ?? request.duration
)

@@ -107,4 +100,3 @@ const resourceEvent = combine(

tracingInfo,
correspondingTimingOverrides,
pageStateInfo
correspondingTimingOverrides
)

@@ -129,4 +121,3 @@ return {

configuration: RumConfiguration,
sessionManager: RumSessionManager,
pageStateHistory: PageStateHistory
sessionManager: RumSessionManager
): RawRumEventCollectedData<RawRumResourceEvent> | undefined {

@@ -143,4 +134,2 @@ const startClocks = relativeToClocks(entry.startTime)

const pageStateInfo = computePageStateInfo(pageStateHistory, startClocks, entry.duration)
const resourceEvent = combine(

@@ -161,4 +150,3 @@ {

tracingInfo,
entryMetrics,
pageStateInfo
entryMetrics
)

@@ -230,15 +218,2 @@ return {

function computePageStateInfo(pageStateHistory: PageStateHistory, startClocks: ClocksState, duration: Duration) {
if (!isExperimentalFeatureEnabled(ExperimentalFeature.RESOURCE_PAGE_STATES)) {
return
}
return {
_dd: {
page_states: pageStateHistory.findAll(startClocks.relative, duration),
page_was_discarded: String((document as any).wasDiscarded),
},
}
}
function computeRequestDuration(pageStateHistory: PageStateHistory, startClocks: ClocksState, duration: Duration) {

@@ -245,0 +220,0 @@ return !pageStateHistory.wasInPageStateDuringPeriod(PageState.FROZEN, startClocks.relative, duration)

@@ -92,5 +92,3 @@ import type { RelativeTime, ServerDuration } from '@datadog/browser-core'

): PerformanceResourceDetails | undefined {
const validEntry = toValidEntry(entry)
if (!validEntry) {
if (!isValidEntry(entry)) {
return undefined

@@ -111,3 +109,3 @@ }

responseEnd,
} = validEntry
} = entry

@@ -142,5 +140,5 @@ const details: PerformanceResourceDetails = {

export function toValidEntry(entry: RumPerformanceResourceTiming) {
export function isValidEntry(entry: RumPerformanceResourceTiming) {
if (isExperimentalFeatureEnabled(ExperimentalFeature.TOLERANT_RESOURCE_TIMINGS)) {
return entry
return true
}

@@ -168,5 +166,3 @@

if (areCommonTimingsInOrder && areRedirectionTimingsInOrder) {
return entry
}
return areCommonTimingsInOrder && areRedirectionTimingsInOrder
}

@@ -173,0 +169,0 @@

@@ -55,3 +55,3 @@ import type { RelativeTime, TrackingConsentState } from '@datadog/browser-core'

findTrackedSession: (startTime) => {
const session = sessionManager.findActiveSession(startTime)
const session = sessionManager.findSession(startTime)
if (!session || !isTypeTracked(session.trackingType)) {

@@ -58,0 +58,0 @@ return

@@ -134,3 +134,3 @@ import type { Duration, ClocksState, TimeStamp, Subscription, RelativeTime } from '@datadog/browser-core'

lifeCycle.subscribe(LifeCycleEventType.PAGE_EXITED, (pageExitEvent) => {
if (pageExitEvent.reason === PageExitReason.UNLOADING || pageExitEvent.reason === PageExitReason.PAGEHIDE) {
if (pageExitEvent.reason === PageExitReason.UNLOADING) {
currentView.end()

@@ -137,0 +137,0 @@ }

import type { Duration, ServerDuration, Observable } from '@datadog/browser-core'
import { isEmptyObject, mapValues, toServerDuration, isNumber } from '@datadog/browser-core'
import { isEmptyObject, mapValues, toServerDuration } from '@datadog/browser-core'
import { discardNegativeDuration } from '../discardNegativeDuration'
import type { RecorderApi } from '../../boot/rumPublicApi'

@@ -134,5 +135,1 @@ import type { RawRumViewEvent } from '../../rawRumEvent.types'

}
function discardNegativeDuration(duration: ServerDuration | undefined): ServerDuration | undefined {
return isNumber(duration) && duration < 0 ? undefined : duration
}
import { round, find, ONE_SECOND, noop } from '@datadog/browser-core'
import type { RelativeTime } from '@datadog/browser-core'
import type { RelativeTime, WeakRef, WeakRefConstructor } from '@datadog/browser-core'
import { isElementNode } from '../../../browser/htmlDomUtils'

@@ -16,2 +16,4 @@ import type { LifeCycle } from '../../lifeCycle'

declare const WeakRef: WeakRefConstructor
/**

@@ -46,2 +48,4 @@ * Track the cumulative layout shifts (CLS).

let maxClsValue = 0
// WeakRef is not supported in IE11 and Safari mobile, but so is the layout shift API, so this code won't be executed in these browsers
let maxClsTarget: WeakRef<HTMLElement> | undefined

@@ -57,21 +61,16 @@ // if no layout shift happen the value should be reported as 0

if (entry.entryType === RumPerformanceEntryType.LAYOUT_SHIFT && !entry.hadRecentInput) {
window.update(entry)
const { cumulatedValue, isMaxValue } = window.update(entry)
if (window.value() > maxClsValue) {
maxClsValue = window.value()
const cls = round(maxClsValue, 4)
const clsTarget = window.largestLayoutShiftTarget()
let cslTargetSelector
if (isMaxValue) {
const target = getTargetFromSource(entry.sources)
maxClsTarget = target ? new WeakRef(target) : undefined
}
if (
clsTarget &&
// Check if the CLS target have been removed from the DOM between the time we collect the target reference and when we compute the selector
clsTarget.isConnected
) {
cslTargetSelector = getSelectorFromElement(clsTarget, configuration.actionNameAttribute)
}
if (cumulatedValue > maxClsValue) {
maxClsValue = cumulatedValue
const target = maxClsTarget?.deref()
callback({
value: cls,
targetSelector: cslTargetSelector,
value: round(maxClsValue, 4),
targetSelector: target && getSelectorFromElement(target, configuration.actionNameAttribute),
})

@@ -88,10 +87,19 @@ }

function getTargetFromSource(sources?: Array<{ node?: Node }>) {
if (!sources) {
return
}
return find(sources, (source): source is { node: HTMLElement } => !!source.node && isElementNode(source.node))?.node
}
export const MAX_WINDOW_DURATION = 5 * ONE_SECOND
const MAX_UPDATE_GAP = ONE_SECOND
function slidingSessionWindow() {
let value = 0
let cumulatedValue = 0
let startTime: RelativeTime
let endTime: RelativeTime
let maxValue = 0
let largestLayoutShift = 0
let largestLayoutShiftTarget: HTMLElement | undefined
let largestLayoutShiftTime: RelativeTime
return {

@@ -101,31 +109,26 @@ update: (entry: RumLayoutShiftTiming) => {

startTime === undefined ||
entry.startTime - endTime >= ONE_SECOND ||
entry.startTime - startTime >= 5 * ONE_SECOND
entry.startTime - endTime >= MAX_UPDATE_GAP ||
entry.startTime - startTime >= MAX_WINDOW_DURATION
let isMaxValue: boolean
if (shouldCreateNewWindow) {
startTime = endTime = entry.startTime
value = entry.value
largestLayoutShift = 0
largestLayoutShiftTarget = undefined
maxValue = cumulatedValue = entry.value
isMaxValue = true
} else {
value += entry.value
cumulatedValue += entry.value
endTime = entry.startTime
}
isMaxValue = entry.value > maxValue
if (entry.value > largestLayoutShift) {
largestLayoutShift = entry.value
largestLayoutShiftTime = entry.startTime
if (entry.sources?.length) {
largestLayoutShiftTarget = find(
entry.sources,
(s): s is { node: HTMLElement } => !!s.node && isElementNode(s.node)
)?.node
} else {
largestLayoutShiftTarget = undefined
if (isMaxValue) {
maxValue = entry.value
}
}
return {
cumulatedValue,
isMaxValue,
}
},
value: () => value,
largestLayoutShiftTarget: () => largestLayoutShiftTarget,
largestLayoutShiftTime: () => largestLayoutShiftTime,
}

@@ -132,0 +135,0 @@ }

import type { RelativeTime } from '@datadog/browser-core'
import {
DOM_EVENT,
ExperimentalFeature,
ONE_MINUTE,
addEventListeners,
addTelemetryDebug,
findLast,
isExperimentalFeatureEnabled,
relativeNow,
} from '@datadog/browser-core'
import { DOM_EVENT, ONE_MINUTE, addEventListeners, findLast } from '@datadog/browser-core'
import { LifeCycleEventType } from '../../lifeCycle'

@@ -29,7 +20,2 @@ import type { LifeCycle } from '../../lifeCycle'

type SerializableLCP = Omit<RumLargestContentfulPaintTiming, 'toJSON' | 'element'>
let wrongLcpReported = false
let previousLcp: SerializableLCP
/**

@@ -84,12 +70,2 @@ * Track the largest contentful paint (LCP) occurring during the initial View. This can yield

if (isExperimentalFeatureEnabled(ExperimentalFeature.ZERO_LCP_TELEMETRY)) {
monitorLcpEntries(
lcpEntry,
entries.filter(
(entry): entry is RumLargestContentfulPaintTiming =>
entry.entryType === RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT
)
)
}
callback({

@@ -111,38 +87,1 @@ value: lcpEntry.startTime,

}
function monitorLcpEntries(lcpEntry: RumLargestContentfulPaintTiming, lcpEntries: RumLargestContentfulPaintTiming[]) {
if (wrongLcpReported) {
return
}
const wrongLcpDetected =
lcpEntry.startTime === 0
? 'LCP with startTime = 0'
: previousLcp !== undefined && lcpEntry.startTime < previousLcp.startTime
? 'LCP with startTime < previous LCP'
: previousLcp !== undefined && lcpEntry.size < previousLcp.size
? 'LCP with size < previous LCP'
: undefined
if (wrongLcpDetected) {
wrongLcpReported = true
addTelemetryDebug(wrongLcpDetected, {
debug: {
entry: toSerializableLCP(lcpEntry),
previousLcp,
timeOrigin: performance.timeOrigin,
now: relativeNow(),
lcpEntries: lcpEntries.map(toSerializableLCP),
},
})
}
previousLcp = toSerializableLCP(lcpEntry)
}
function toSerializableLCP(entry: RumLargestContentfulPaintTiming): SerializableLCP {
const jsonEntry = entry.toJSON()
delete jsonEntry.element
return jsonEntry
}

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