{"version":3,"file":"FontDisplay.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/FontDisplay.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport * as Platform from '../../../core/platform/platform.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {\n InsightCategory,\n InsightKeys,\n type InsightModel,\n type InsightSetContext,\n type PartialInsightModel,\n} from './types.js';\n\nexport const UIStrings = {\n /** Title of an insight that provides details about the fonts used on the page, and the value of their `font-display` properties. */\n title: 'Font display',\n /**\n * @description Text to tell the user about the font-display CSS feature to help improve a the UX of a page.\n */\n description:\n 'Consider setting [`font-display`](https://developer.chrome.com/blog/font-display) to `swap` or `optional` to ensure text is consistently visible. `swap` can be further optimized to mitigate layout shifts with [font metric overrides](https://developer.chrome.com/blog/font-fallbacks).',\n /** Column for a font loaded by the page to render text. */\n fontColumn: 'Font',\n /** Column for the amount of time wasted. */\n wastedTimeColumn: 'Wasted time',\n} as const;\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/FontDisplay.ts', UIStrings);\nexport const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport interface RemoteFont {\n name?: string;\n request: Types.Events.SyntheticNetworkRequest;\n display: string;\n wastedTime: Types.Timing.Milli;\n}\n\nexport type FontDisplayInsightModel = InsightModel;\n\nfunction finalize(partialModel: PartialInsightModel): FontDisplayInsightModel {\n return {\n insightKey: InsightKeys.FONT_DISPLAY,\n strings: UIStrings,\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.INP,\n state: partialModel.fonts.find(font => font.wastedTime > 0) ? 'fail' : 'pass',\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): FontDisplayInsightModel {\n const fonts: RemoteFont[] = [];\n for (const remoteFont of parsedTrace.LayoutShifts.remoteFonts) {\n const event = remoteFont.beginRemoteFontLoadEvent;\n if (!Helpers.Timing.eventIsInBounds(event, context.bounds)) {\n continue;\n }\n\n const requestId = `${event.pid}.${event.args.id}`;\n const request = parsedTrace.NetworkRequests.byId.get(requestId);\n if (!request) {\n continue;\n }\n\n if (!/^(block|fallback|auto)$/.test(remoteFont.display)) {\n continue;\n }\n\n const wastedTimeMicro =\n Types.Timing.Micro(request.args.data.syntheticData.finishTime - request.args.data.syntheticData.sendStartTime);\n // TODO(crbug.com/352244504): should really end at the time of the next Commit trace event.\n let wastedTime =\n Platform.NumberUtilities.floor(Helpers.Timing.microToMilli(wastedTimeMicro), 1 / 5) as Types.Timing.Milli;\n if (wastedTime === 0) {\n continue;\n }\n\n // All browsers wait for no more than 3s.\n wastedTime = Math.min(wastedTime, 3000) as Types.Timing.Milli;\n\n fonts.push({\n name: remoteFont.name,\n request,\n display: remoteFont.display,\n wastedTime,\n });\n }\n\n fonts.sort((a, b) => b.wastedTime - a.wastedTime);\n\n const savings = Math.max(...fonts.map(f => f.wastedTime)) as Types.Timing.Milli;\n\n return finalize({\n relatedEvents: fonts.map(f => f.request),\n fonts,\n metricSavings: {FCP: savings},\n });\n}\n\nexport function createOverlays(model: FontDisplayInsightModel): Types.Overlays.Overlay[] {\n return model.fonts.map(font => ({\n type: 'ENTRY_OUTLINE',\n entry: font.request,\n outlineReason: font.wastedTime ? 'ERROR' : 'INFO',\n }));\n}\n"]}