Rocky_Mountain_Vending/.pnpm-store/v10/files/c8/6743fdfb1aba25c27a240145faa4d4bd461589f3a5cf41b46b0a483360ebd537ba81c0fd7a559b1720a1b600dcd3b8ea87aa232f0c369219aadbcba524cbb6
DMleadgen 46d973904b
Initial commit: Rocky Mountain Vending website
Next.js website for Rocky Mountain Vending company featuring:
- Product catalog with Stripe integration
- Service areas and parts pages
- Admin dashboard with Clerk authentication
- SEO optimized pages with JSON-LD structured data

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 16:22:15 -07:00

517 lines
No EOL
23 KiB
Text

// Copyright 2024 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// import * as i18n from '../../../core/i18n/i18n.js';
import * as Platform from '../../../core/platform/platform.js';
import * as Handlers from '../handlers/handlers.js';
import * as Helpers from '../helpers/helpers.js';
import * as Types from '../types/types.js';
import { InsightCategory, InsightKeys, } from './types.js';
export const UIStrings = {
/** Title of an insight that provides details about why elements shift/move on the page. The causes for these shifts are referred to as culprits ("reasons"). */
title: 'Layout shift culprits',
/**
* @description Description of a DevTools insight that identifies the reasons that elements shift on the page.
* This is displayed after a user expands the section to see more. No character length limits.
*/
description: 'Layout shifts occur when elements move absent any user interaction. [Investigate the causes of layout shifts](https://web.dev/articles/optimize-cls), such as elements being added, removed, or their fonts changing as the page loads.',
/**
* @description Text indicating the worst layout shift cluster.
*/
worstLayoutShiftCluster: 'Worst layout shift cluster',
/**
* @description Text indicating the worst layout shift cluster.
*/
worstCluster: 'Worst cluster',
/**
* @description Text indicating a layout shift cluster and its start time.
* @example {32 ms} PH1
*/
layoutShiftCluster: 'Layout shift cluster @ {PH1}',
/**
* @description Text indicating the biggest reasons for the layout shifts.
*/
topCulprits: 'Top layout shift culprits',
/**
* @description Text for a culprit type of Injected iframe.
*/
injectedIframe: 'Injected iframe',
/**
* @description Text for a culprit type of web font request.
*/
webFont: 'Web font',
/**
* @description Text for a culprit type of Animation.
*/
animation: 'Animation',
/**
* @description Text for a culprit type of Unsized image.
*/
unsizedImage: 'Unsized image element',
/**
* @description Text status when there were no layout shifts detected.
*/
noLayoutShifts: 'No layout shifts',
/**
* @description Text status when there no layout shifts culprits/root causes were found.
*/
noCulprits: 'Could not detect any layout shift culprits',
};
// const str_ = i18n.i18n.registerUIStrings('models/trace/insights/CLSCulprits.ts', UIStrings);
export const i18nString = (i18nId, values) => ({i18nId, values}); // i18n.i18n.getLocalizedString.bind(undefined, str_);
export var AnimationFailureReasons;
(function (AnimationFailureReasons) {
AnimationFailureReasons["ACCELERATED_ANIMATIONS_DISABLED"] = "ACCELERATED_ANIMATIONS_DISABLED";
AnimationFailureReasons["EFFECT_SUPPRESSED_BY_DEVTOOLS"] = "EFFECT_SUPPRESSED_BY_DEVTOOLS";
AnimationFailureReasons["INVALID_ANIMATION_OR_EFFECT"] = "INVALID_ANIMATION_OR_EFFECT";
AnimationFailureReasons["EFFECT_HAS_UNSUPPORTED_TIMING_PARAMS"] = "EFFECT_HAS_UNSUPPORTED_TIMING_PARAMS";
AnimationFailureReasons["EFFECT_HAS_NON_REPLACE_COMPOSITE_MODE"] = "EFFECT_HAS_NON_REPLACE_COMPOSITE_MODE";
AnimationFailureReasons["TARGET_HAS_INVALID_COMPOSITING_STATE"] = "TARGET_HAS_INVALID_COMPOSITING_STATE";
AnimationFailureReasons["TARGET_HAS_INCOMPATIBLE_ANIMATIONS"] = "TARGET_HAS_INCOMPATIBLE_ANIMATIONS";
AnimationFailureReasons["TARGET_HAS_CSS_OFFSET"] = "TARGET_HAS_CSS_OFFSET";
AnimationFailureReasons["ANIMATION_AFFECTS_NON_CSS_PROPERTIES"] = "ANIMATION_AFFECTS_NON_CSS_PROPERTIES";
AnimationFailureReasons["TRANSFORM_RELATED_PROPERTY_CANNOT_BE_ACCELERATED_ON_TARGET"] = "TRANSFORM_RELATED_PROPERTY_CANNOT_BE_ACCELERATED_ON_TARGET";
AnimationFailureReasons["TRANSFROM_BOX_SIZE_DEPENDENT"] = "TRANSFROM_BOX_SIZE_DEPENDENT";
AnimationFailureReasons["FILTER_RELATED_PROPERTY_MAY_MOVE_PIXELS"] = "FILTER_RELATED_PROPERTY_MAY_MOVE_PIXELS";
AnimationFailureReasons["UNSUPPORTED_CSS_PROPERTY"] = "UNSUPPORTED_CSS_PROPERTY";
AnimationFailureReasons["MIXED_KEYFRAME_VALUE_TYPES"] = "MIXED_KEYFRAME_VALUE_TYPES";
AnimationFailureReasons["TIMELINE_SOURCE_HAS_INVALID_COMPOSITING_STATE"] = "TIMELINE_SOURCE_HAS_INVALID_COMPOSITING_STATE";
AnimationFailureReasons["ANIMATION_HAS_NO_VISIBLE_CHANGE"] = "ANIMATION_HAS_NO_VISIBLE_CHANGE";
AnimationFailureReasons["AFFECTS_IMPORTANT_PROPERTY"] = "AFFECTS_IMPORTANT_PROPERTY";
AnimationFailureReasons["SVG_TARGET_HAS_INDEPENDENT_TRANSFORM_PROPERTY"] = "SVG_TARGET_HAS_INDEPENDENT_TRANSFORM_PROPERTY";
})(AnimationFailureReasons || (AnimationFailureReasons = {}));
export var LayoutShiftType;
(function (LayoutShiftType) {
LayoutShiftType[LayoutShiftType["WEB_FONT"] = 0] = "WEB_FONT";
LayoutShiftType[LayoutShiftType["IFRAMES"] = 1] = "IFRAMES";
LayoutShiftType[LayoutShiftType["ANIMATIONS"] = 2] = "ANIMATIONS";
LayoutShiftType[LayoutShiftType["UNSIZED_IMAGE"] = 3] = "UNSIZED_IMAGE";
})(LayoutShiftType || (LayoutShiftType = {}));
/**
* Each failure reason is represented by a bit flag. The bit shift operator '<<' is used to define
* which bit corresponds to each failure reason.
* https://source.chromium.org/search?q=f:compositor_animations.h%20%22enum%20FailureReason%22
*/
const ACTIONABLE_FAILURE_REASONS = [
{
flag: 1 << 0,
failure: AnimationFailureReasons.ACCELERATED_ANIMATIONS_DISABLED,
},
{
flag: 1 << 1,
failure: AnimationFailureReasons.EFFECT_SUPPRESSED_BY_DEVTOOLS,
},
{
flag: 1 << 2,
failure: AnimationFailureReasons.INVALID_ANIMATION_OR_EFFECT,
},
{
flag: 1 << 3,
failure: AnimationFailureReasons.EFFECT_HAS_UNSUPPORTED_TIMING_PARAMS,
},
{
flag: 1 << 4,
failure: AnimationFailureReasons.EFFECT_HAS_NON_REPLACE_COMPOSITE_MODE,
},
{
flag: 1 << 5,
failure: AnimationFailureReasons.TARGET_HAS_INVALID_COMPOSITING_STATE,
},
{
flag: 1 << 6,
failure: AnimationFailureReasons.TARGET_HAS_INCOMPATIBLE_ANIMATIONS,
},
{
flag: 1 << 7,
failure: AnimationFailureReasons.TARGET_HAS_CSS_OFFSET,
},
// The failure 1 << 8 is marked as obsolete in Blink
{
flag: 1 << 9,
failure: AnimationFailureReasons.ANIMATION_AFFECTS_NON_CSS_PROPERTIES,
},
{
flag: 1 << 10,
failure: AnimationFailureReasons.TRANSFORM_RELATED_PROPERTY_CANNOT_BE_ACCELERATED_ON_TARGET,
},
{
flag: 1 << 11,
failure: AnimationFailureReasons.TRANSFROM_BOX_SIZE_DEPENDENT,
},
{
flag: 1 << 12,
failure: AnimationFailureReasons.FILTER_RELATED_PROPERTY_MAY_MOVE_PIXELS,
},
{
flag: 1 << 13,
failure: AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY,
},
// The failure 1 << 14 is marked as obsolete in Blink
{
flag: 1 << 15,
failure: AnimationFailureReasons.MIXED_KEYFRAME_VALUE_TYPES,
},
{
flag: 1 << 16,
failure: AnimationFailureReasons.TIMELINE_SOURCE_HAS_INVALID_COMPOSITING_STATE,
},
{
flag: 1 << 17,
failure: AnimationFailureReasons.ANIMATION_HAS_NO_VISIBLE_CHANGE,
},
{
flag: 1 << 18,
failure: AnimationFailureReasons.AFFECTS_IMPORTANT_PROPERTY,
},
{
flag: 1 << 19,
failure: AnimationFailureReasons.SVG_TARGET_HAS_INDEPENDENT_TRANSFORM_PROPERTY,
},
];
// 500ms window.
// Use this window to consider events and requests that may have caused a layout shift.
const ROOT_CAUSE_WINDOW = Helpers.Timing.secondsToMicro(Types.Timing.Seconds(0.5));
/**
* Returns if an event happens within the root cause window, before the target event.
* ROOT_CAUSE_WINDOW v target event
* |------------------------|=======================
*/
function isInRootCauseWindow(event, targetEvent) {
const eventEnd = event.dur ? event.ts + event.dur : event.ts;
return eventEnd < targetEvent.ts && eventEnd >= targetEvent.ts - ROOT_CAUSE_WINDOW;
}
export function getNonCompositedFailure(animationEvent) {
const failures = [];
const beginEvent = animationEvent.args.data.beginEvent;
const instantEvents = animationEvent.args.data.instantEvents || [];
/**
* Animation events containing composite information are ASYNC_NESTABLE_INSTANT ('n').
* An animation may also contain multiple 'n' events, so we look through those with useful non-composited data.
*/
for (const event of instantEvents) {
const failureMask = event.args.data.compositeFailed;
const unsupportedProperties = event.args.data.unsupportedProperties;
if (!failureMask) {
continue;
}
const failureReasons = ACTIONABLE_FAILURE_REASONS.filter(reason => failureMask & reason.flag).map(reason => reason.failure);
const failure = {
name: beginEvent.args.data.displayName,
failureReasons,
unsupportedProperties,
animation: animationEvent,
};
failures.push(failure);
}
return failures;
}
function getNonCompositedFailureRootCauses(animationEvents, prePaintEvents, shiftsByPrePaint, rootCausesByShift) {
const allAnimationFailures = [];
for (const animation of animationEvents) {
/**
* Animation events containing composite information are ASYNC_NESTABLE_INSTANT ('n').
* An animation may also contain multiple 'n' events, so we look through those with useful non-composited data.
*/
const failures = getNonCompositedFailure(animation);
if (!failures) {
continue;
}
allAnimationFailures.push(...failures);
const nextPrePaint = getNextEvent(prePaintEvents, animation);
// If no following prePaint, this is not a root cause.
if (!nextPrePaint) {
continue;
}
// If the animation event is outside the ROOT_CAUSE_WINDOW, it could not be a root cause.
if (!isInRootCauseWindow(animation, nextPrePaint)) {
continue;
}
const shifts = shiftsByPrePaint.get(nextPrePaint);
// if no layout shift(s), this is not a root cause.
if (!shifts) {
continue;
}
for (const shift of shifts) {
const rootCausesForShift = rootCausesByShift.get(shift);
if (!rootCausesForShift) {
throw new Error('Unaccounted shift');
}
rootCausesForShift.nonCompositedAnimations.push(...failures);
}
}
return allAnimationFailures;
}
/**
* Given an array of layout shift and PrePaint events, returns a mapping from
* PrePaint events to layout shifts dispatched within it.
*/
function getShiftsByPrePaintEvents(layoutShifts, prePaintEvents) {
// Maps from PrePaint events to LayoutShifts that occurred in each one.
const shiftsByPrePaint = new Map();
// Associate all shifts to their corresponding PrePaint.
for (const prePaintEvent of prePaintEvents) {
const firstShiftIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(layoutShifts, shift => shift.ts >= prePaintEvent.ts);
if (firstShiftIndex === null) {
// No layout shifts registered after this PrePaint start. Continue.
continue;
}
for (let i = firstShiftIndex; i < layoutShifts.length; i++) {
const shift = layoutShifts[i];
if (shift.ts >= prePaintEvent.ts && shift.ts <= prePaintEvent.ts + prePaintEvent.dur) {
const shiftsInPrePaint = Platform.MapUtilities.getWithDefault(shiftsByPrePaint, prePaintEvent, () => []);
shiftsInPrePaint.push(shift);
}
if (shift.ts > prePaintEvent.ts + prePaintEvent.dur) {
// Reached all layoutShifts of this PrePaint. Break out to continue with the next prePaint event.
break;
}
}
}
return shiftsByPrePaint;
}
/**
* Given a source event list, this returns the first event of that list that directly follows the target event.
*/
function getNextEvent(sourceEvents, targetEvent) {
const index = Platform.ArrayUtilities.nearestIndexFromBeginning(sourceEvents, source => source.ts > targetEvent.ts + (targetEvent.dur || 0));
// No PrePaint event registered after this event
if (index === null) {
return undefined;
}
return sourceEvents[index];
}
/**
* An Iframe is considered a root cause if the iframe event occurs before a prePaint event
* and within this prePaint event a layout shift(s) occurs.
*/
function getIframeRootCauses(parsedTrace, iframeCreatedEvents, prePaintEvents, shiftsByPrePaint, rootCausesByShift, domLoadingEvents) {
for (const iframeEvent of iframeCreatedEvents) {
const nextPrePaint = getNextEvent(prePaintEvents, iframeEvent);
// If no following prePaint, this is not a root cause.
if (!nextPrePaint) {
continue;
}
const shifts = shiftsByPrePaint.get(nextPrePaint);
// if no layout shift(s), this is not a root cause.
if (!shifts) {
continue;
}
for (const shift of shifts) {
const rootCausesForShift = rootCausesByShift.get(shift);
if (!rootCausesForShift) {
throw new Error('Unaccounted shift');
}
// Look for the first dom event that occurs within the bounds of the iframe event.
// This contains the frame id.
const domEvent = domLoadingEvents.find(e => {
const maxIframe = Types.Timing.Micro(iframeEvent.ts + (iframeEvent.dur ?? 0));
return e.ts >= iframeEvent.ts && e.ts <= maxIframe;
});
if (domEvent?.args.frame) {
const frame = domEvent.args.frame;
let url;
const processes = parsedTrace.Meta.rendererProcessesByFrame.get(frame);
if (processes && processes.size > 0) {
url = [...processes.values()][0]?.[0].frame.url;
}
rootCausesForShift.iframes.push({ frame, url });
}
}
}
return rootCausesByShift;
}
/**
* An unsized image is considered a root cause if its PaintImage can be correlated to a
* layout shift. We can correlate PaintImages with unsized images by their matching nodeIds.
* X <- layout shift
* |----------------|
* ^ PrePaint event |-----|
* ^ PaintImage
*/
function getUnsizedImageRootCauses(unsizedImageEvents, paintImageEvents, shiftsByPrePaint, rootCausesByShift) {
shiftsByPrePaint.forEach((shifts, prePaint) => {
const paintImage = getNextEvent(paintImageEvents, prePaint);
if (!paintImage) {
return;
}
// The unsized image corresponds to this PaintImage.
const matchingNode = unsizedImageEvents.find(unsizedImage => unsizedImage.args.data.nodeId === paintImage.args.data.nodeId);
if (!matchingNode) {
return;
}
// The unsized image is a potential root cause of all the shifts of this prePaint.
for (const shift of shifts) {
const rootCausesForShift = rootCausesByShift.get(shift);
if (!rootCausesForShift) {
throw new Error('Unaccounted shift');
}
rootCausesForShift.unsizedImages.push({
backendNodeId: matchingNode.args.data.nodeId,
paintImageEvent: paintImage,
});
}
});
return rootCausesByShift;
}
export function isCLSCulprits(insight) {
return insight.insightKey === InsightKeys.CLS_CULPRITS;
}
/**
* A font request is considered a root cause if the request occurs before a prePaint event
* and within this prePaint event a layout shift(s) occurs. Additionally, this font request should
* happen within the ROOT_CAUSE_WINDOW of the prePaint event.
*/
function getFontRootCauses(networkRequests, prePaintEvents, shiftsByPrePaint, rootCausesByShift) {
const fontRequests = networkRequests.filter(req => req.args.data.resourceType === 'Font' && req.args.data.mimeType.startsWith('font'));
for (const req of fontRequests) {
const nextPrePaint = getNextEvent(prePaintEvents, req);
if (!nextPrePaint) {
continue;
}
// If the req is outside the ROOT_CAUSE_WINDOW, it could not be a root cause.
if (!isInRootCauseWindow(req, nextPrePaint)) {
continue;
}
// Get the shifts that belong to this prepaint
const shifts = shiftsByPrePaint.get(nextPrePaint);
// if no layout shift(s) in this prePaint, the request is not a root cause.
if (!shifts) {
continue;
}
// Include the root cause to the shifts in this prePaint.
for (const shift of shifts) {
const rootCausesForShift = rootCausesByShift.get(shift);
if (!rootCausesForShift) {
throw new Error('Unaccounted shift');
}
rootCausesForShift.webFonts.push(req);
}
}
return rootCausesByShift;
}
/**
* Returns the top 3 shift root causes based on the given cluster.
*/
function getTopCulprits(cluster, culpritsByShift) {
const MAX_TOP_CULPRITS = 3;
const causes = [];
const shifts = cluster.events;
for (const shift of shifts) {
const culprits = culpritsByShift.get(shift);
if (!culprits) {
continue;
}
const fontReq = culprits.webFonts;
const iframes = culprits.iframes;
const animations = culprits.nonCompositedAnimations;
const unsizedImages = culprits.unsizedImages;
for (let i = 0; i < fontReq.length && causes.length < MAX_TOP_CULPRITS; i++) {
causes.push({ type: LayoutShiftType.WEB_FONT, description: i18nString(UIStrings.webFont) });
}
for (let i = 0; i < iframes.length && causes.length < MAX_TOP_CULPRITS; i++) {
causes.push({ type: LayoutShiftType.IFRAMES, description: i18nString(UIStrings.injectedIframe) });
}
for (let i = 0; i < animations.length && causes.length < MAX_TOP_CULPRITS; i++) {
causes.push({ type: LayoutShiftType.ANIMATIONS, description: i18nString(UIStrings.animation) });
}
for (let i = 0; i < unsizedImages.length && causes.length < MAX_TOP_CULPRITS; i++) {
causes.push({
type: LayoutShiftType.UNSIZED_IMAGE,
description: i18nString(UIStrings.unsizedImage),
url: unsizedImages[i].paintImageEvent.args.data.url || '',
backendNodeId: unsizedImages[i].backendNodeId,
frame: unsizedImages[i].paintImageEvent.args.data.frame || '',
});
}
if (causes.length >= MAX_TOP_CULPRITS) {
break;
}
}
return causes.slice(0, MAX_TOP_CULPRITS);
}
function finalize(partialModel) {
let state = 'pass';
if (partialModel.worstCluster) {
const classification = Handlers.ModelHandlers.LayoutShifts.scoreClassificationForLayoutShift(partialModel.worstCluster.clusterCumulativeScore);
if (classification === Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD) {
state = 'informative';
}
else {
state = 'fail';
}
}
return {
insightKey: InsightKeys.CLS_CULPRITS,
strings: UIStrings,
title: i18nString(UIStrings.title),
description: i18nString(UIStrings.description),
category: InsightCategory.CLS,
state,
...partialModel,
};
}
export function generateInsight(parsedTrace, context) {
const isWithinContext = (event) => Helpers.Timing.eventIsInBounds(event, context.bounds);
const compositeAnimationEvents = parsedTrace.Animations.animations.filter(isWithinContext);
const iframeEvents = parsedTrace.LayoutShifts.renderFrameImplCreateChildFrameEvents.filter(isWithinContext);
const networkRequests = parsedTrace.NetworkRequests.byTime.filter(isWithinContext);
const domLoadingEvents = parsedTrace.LayoutShifts.domLoadingEvents.filter(isWithinContext);
const unsizedImageEvents = parsedTrace.LayoutShifts.layoutImageUnsizedEvents.filter(isWithinContext);
const clusterKey = context.navigation ? context.navigationId : Types.Events.NO_NAVIGATION;
const clusters = parsedTrace.LayoutShifts.clustersByNavigationId.get(clusterKey) ?? [];
const clustersByScore = [...clusters].sort((a, b) => b.clusterCumulativeScore - a.clusterCumulativeScore);
const worstCluster = clustersByScore.at(0);
const layoutShifts = clusters.flatMap(cluster => cluster.events);
const prePaintEvents = parsedTrace.LayoutShifts.prePaintEvents.filter(isWithinContext);
const paintImageEvents = parsedTrace.LayoutShifts.paintImageEvents.filter(isWithinContext);
// Get root causes.
const rootCausesByShift = new Map();
const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);
for (const shift of layoutShifts) {
rootCausesByShift.set(shift, { iframes: [], webFonts: [], nonCompositedAnimations: [], unsizedImages: [] });
}
// Populate root causes for rootCausesByShift.
getIframeRootCauses(parsedTrace, iframeEvents, prePaintEvents, shiftsByPrePaint, rootCausesByShift, domLoadingEvents);
getFontRootCauses(networkRequests, prePaintEvents, shiftsByPrePaint, rootCausesByShift);
getUnsizedImageRootCauses(unsizedImageEvents, paintImageEvents, shiftsByPrePaint, rootCausesByShift);
const animationFailures = getNonCompositedFailureRootCauses(compositeAnimationEvents, prePaintEvents, shiftsByPrePaint, rootCausesByShift);
const relatedEvents = [...layoutShifts];
if (worstCluster) {
relatedEvents.push(worstCluster);
}
const topCulpritsByCluster = new Map();
for (const cluster of clusters) {
topCulpritsByCluster.set(cluster, getTopCulprits(cluster, rootCausesByShift));
}
return finalize({
relatedEvents,
animationFailures,
shifts: rootCausesByShift,
clusters,
worstCluster,
topCulpritsByCluster,
});
}
export function createOverlays(model) {
const clustersByScore = model.clusters.toSorted((a, b) => b.clusterCumulativeScore - a.clusterCumulativeScore) ?? [];
const worstCluster = clustersByScore[0];
if (!worstCluster) {
return [];
}
const range = Types.Timing.Micro(worstCluster.dur ?? 0);
const max = Types.Timing.Micro(worstCluster.ts + range);
return [{
type: 'TIMESPAN_BREAKDOWN',
sections: [
{
bounds: { min: worstCluster.ts, range, max },
label: i18nString(UIStrings.worstLayoutShiftCluster),
showDuration: false,
},
],
// This allows for the overlay to sit over the layout shift.
entry: worstCluster.events[0],
renderLocation: 'ABOVE_EVENT',
}];
}
//# sourceMappingURL=CLSCulprits.js.map