@react-native/debugger-frontend
Version:
Debugger frontend for React Native based on Chrome DevTools
421 lines • 61.8 kB
JavaScript
import*as e from"../../../services/trace_bounds/trace_bounds.js";import*as t from"../../../core/i18n/i18n.js";import*as i from"../../../models/trace/trace.js";import*as n from"../../../ui/components/helpers/helpers.js";import*as r from"../../../ui/components/icon_button/icon_button.js";import*as s from"../../../ui/lit-html/lit-html.js";import*as a from"../../../ui/visual_logging/visual_logging.js";import*as o from"../../../core/sdk/sdk.js";import*as l from"../../../ui/components/menus/menus.js";import*as d from"../../mobile_throttling/mobile_throttling.js";import*as c from"../../../core/platform/platform.js";import*as h from"../../../ui/legacy/legacy.js";import*as u from"../../../models/crux-manager/crux-manager.js";import*as g from"../../../ui/components/buttons/buttons.js";import*as p from"../../../ui/components/dialogs/dialogs.js";import*as m from"../../../ui/components/input/input.js";import*as v from"../../../core/common/common.js";import*as b from"../../../models/emulation/emulation.js";import*as w from"../../../models/live-metrics/live-metrics.js";import*as f from"../../../ui/legacy/components/perf_ui/perf_ui.js";import*as k from"../../../ui/legacy/components/utils/utils.js";import*as S from"../utils/utils.js";import*as y from"../../../ui/legacy/theme_support/theme_support.js";import*as $ from"./insights/insights.js";function T(e){const t=[e];let i=e;for(;null!==i.child;){const e=i.child;null!==e&&(t.push(e),i=e)}return t}var x=Object.freeze({__proto__:null,flattenBreadcrumbs:T,Breadcrumbs:class{initialBreadcrumb;lastBreadcrumb;constructor(e){this.initialBreadcrumb={window:e,child:null},this.lastBreadcrumb=this.initialBreadcrumb}add(e){if(!this.isTraceWindowWithinTraceWindow(e,this.lastBreadcrumb.window))throw new Error("Can not add a breadcrumb that is equal to or is outside of the parent breadcrumb TimeWindow");{const t={window:e,child:null};this.lastBreadcrumb.child=t,this.setLastBreadcrumb(t)}}isTraceWindowWithinTraceWindow(e,t){return e.min>=t.min&&e.max<=t.max&&!(e.min===t.min&&e.max===t.max)}setInitialBreadcrumbFromLoadedModifications(e){this.initialBreadcrumb=e;let t=e;for(;null!==t.child;)t=t.child;this.setLastBreadcrumb(t)}setLastBreadcrumb(t){this.lastBreadcrumb=t,this.lastBreadcrumb.child=null,e.TraceBounds.BoundsManager.instance().setMiniMapBounds(t.window),e.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(t.window)}}});const C=new CSSStyleSheet;C.replaceSync(".breadcrumbs{display:none;align-items:center;height:29px;padding:3px;overflow-y:hidden;overflow-x:scroll}.breadcrumbs::-webkit-scrollbar{display:none}.breadcrumb{padding:2px 6px;border-radius:4px}.breadcrumb:hover{background-color:var(--sys-color-state-hover-on-subtle)}.range{font-size:12px;white-space:nowrap}.last-breadcrumb{font-weight:bold;color:var(--app-color-active-breadcrumb)}\n/*# sourceURL=breadcrumbsUI.css */\n");const{render:R,html:M}=s;class P extends Event{breadcrumb;static eventName="breadcrumbremoved";constructor(e){super(P.eventName),this.breadcrumb=e}}class I extends HTMLElement{static litTagName=s.literal`devtools-breadcrumbs-ui`;#e=this.attachShadow({mode:"open"});#t=this.#i.bind(this);#n=null;connectedCallback(){this.#e.adoptedStyleSheets=[C]}set data(e){this.#n=e.breadcrumb,n.ScheduledRender.scheduleRender(this,this.#t)}#r(e){this.dispatchEvent(new P(e))}#s(){const e=this.#e.querySelector(".breadcrumbs");e&&(e.style.display="flex",requestAnimationFrame((()=>{e.scrollWidth-e.clientWidth>0&&requestAnimationFrame((()=>{e.scrollLeft=e.scrollWidth-e.clientWidth}))})))}#a(e,n){const s=i.Helpers.Timing.microSecondsToMilliseconds(e.window.range);return M`
<div class="breadcrumb" @click=${()=>this.#r(e)}
jslog=${a.action("timeline.breadcrumb-select").track({click:!0})}>
<span class="${0!==n&&null===e.child?"last-breadcrumb":""} range">
${0===n?`Full range (${t.TimeUtilities.preciseMillisToString(s,2)})`:`${t.TimeUtilities.preciseMillisToString(s,2)}`}
</span>
</div>
${null!==e.child?M`
<${r.Icon.Icon.litTagName} .data=${{iconName:"chevron-right",color:"var(--icon-default)",width:"16px",height:"16px"}}>`:""}
`}#i(){const e=M`
${null===this.#n?M``:M`<div class="breadcrumbs">
${T(this.#n).map(((e,t)=>this.#a(e,t)))}
</div>`}
`;R(e,this.#e,{host:this}),this.#n?.child&&this.#s()}}customElements.define("devtools-breadcrumbs-ui",I);var L=Object.freeze({__proto__:null,BreadcrumbRemovedEvent:P,BreadcrumbsUI:I});const{html:N}=s,D={noThrottling:"No throttling",dSlowdown:"{PH1}× slowdown"},E=t.i18n.registerUIStrings("panels/timeline/components/CPUThrottlingSelector.ts",D),U=t.i18n.getLocalizedString.bind(void 0,E);class q extends HTMLElement{static litTagName=s.literal`devtools-cpu-throttling-selector`;#e=this.attachShadow({mode:"open"});#o;constructor(){super(),this.#o=o.CPUThrottlingManager.CPUThrottlingManager.instance().cpuThrottlingRate(),this.#i()}connectedCallback(){o.CPUThrottlingManager.CPUThrottlingManager.instance().addEventListener("RateChanged",this.#l,this)}disconnectedCallback(){o.CPUThrottlingManager.CPUThrottlingManager.instance().removeEventListener("RateChanged",this.#l,this)}#l(e){this.#o=e.data,n.ScheduledRender.scheduleRender(this,this.#i)}#d(e){d.ThrottlingManager.throttlingManager().setCPUThrottlingRate(Number(e.itemValue))}#i=()=>{const e=N`
<${l.SelectMenu.SelectMenu.litTagName}
@selectmenuselected=${this.#d}
.showDivider=${!0}
.showArrow=${!0}
.sideButton=${!1}
.showSelectedItem=${!0}
.showConnector=${!1}
.buttonTitle=${1===this.#o?U(D.noThrottling):U(D.dSlowdown,{PH1:this.#o})}
>
${d.ThrottlingPresets.ThrottlingPresets.cpuThrottlingPresets.map((e=>{const t=1===e?U(D.noThrottling):U(D.dSlowdown,{PH1:e});return s.html`
<${l.Menu.MenuItem.litTagName}
.value=${e}
.selected=${this.#o===e}
>
${t}
</${l.Menu.MenuItem.litTagName}>
`}))}
</${l.SelectMenu.SelectMenu.litTagName}>
`;s.render(e,this.#e,{host:this})}}customElements.define("devtools-cpu-throttling-selector",q);var O=Object.freeze({__proto__:null,CPUThrottlingSelector:q});const B={forcedReflow:"Forced reflow",sIsALikelyPerformanceBottleneck:"{PH1} is a likely performance bottleneck.",idleCallbackExecutionExtended:"Idle callback execution extended beyond deadline by {PH1}",sTookS:"{PH1} took {PH2}.",longTask:"Long task",longInteractionINP:"Long interaction",sIsLikelyPoorPageResponsiveness:"{PH1} is indicating poor page responsiveness.",websocketProtocol:"WebSocket Protocol",webSocketBytes:"{PH1} byte(s)",webSocketDataLength:"Data Length"},A=t.i18n.registerUIStrings("panels/timeline/components/DetailsView.ts",B),F=t.i18n.getLocalizedString.bind(void 0,A);var _=Object.freeze({__proto__:null,buildWarningElementsForEvent:function(e,n){const r=n.Warnings.perEvent.get(e),s=[];if(!r)return s;for(const n of r){const r=i.Helpers.Timing.microSecondsToMilliseconds(i.Types.Timing.MicroSeconds(e.dur||0)),a=document.createElement("span");switch(n){case"FORCED_REFLOW":{const e=h.XLink.XLink.create("https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing#avoid-forced-synchronous-layouts",F(B.forcedReflow),void 0,void 0,"forced-reflow");a.appendChild(t.i18n.getFormatLocalizedString(A,B.sIsALikelyPerformanceBottleneck,{PH1:e}));break}case"IDLE_CALLBACK_OVER_TIME":{if(!i.Types.TraceEvents.isTraceEventFireIdleCallback(e))break;const n=t.TimeUtilities.millisToString((r||0)-e.args.data.allottedMilliseconds,!0);a.textContent=F(B.idleCallbackExecutionExtended,{PH1:n});break}case"LONG_TASK":{const e=h.XLink.XLink.create("https://web.dev/optimize-long-tasks/",F(B.longTask),void 0,void 0,"long-tasks");a.appendChild(t.i18n.getFormatLocalizedString(A,B.sTookS,{PH1:e,PH2:t.TimeUtilities.millisToString(r||0,!0)}));break}case"LONG_INTERACTION":{const e=h.XLink.XLink.create("https://web.dev/inp",F(B.longInteractionINP),void 0,void 0,"long-interaction");a.appendChild(t.i18n.getFormatLocalizedString(A,B.sIsLikelyPoorPageResponsiveness,{PH1:e}));break}default:c.assertNever(n,`Unhandled warning type ${n}`)}s.push(a)}return s},buildRowsForWebSocketEvent:function(e,n){const r=[],s=n.Initiators.eventToInitiator.get(e);return s&&i.Types.TraceEvents.isTraceEventWebSocketCreate(s)?(r.push({key:t.i18n.lockedString("URL"),value:s.args.data.url}),s.args.data.websocketProtocol&&r.push({key:F(B.websocketProtocol),value:s.args.data.websocketProtocol})):i.Types.TraceEvents.isTraceEventWebSocketCreate(e)&&(r.push({key:t.i18n.lockedString("URL"),value:e.args.data.url}),e.args.data.websocketProtocol&&r.push({key:F(B.websocketProtocol),value:e.args.data.websocketProtocol})),i.Types.TraceEvents.isTraceEventWebSocketTransfer(e)&&e.args.data.dataLength&&r.push({key:F(B.webSocketDataLength),value:`${F(B.webSocketBytes,{PH1:e.args.data.dataLength})}`}),r},generateInvalidationsList:function(e){const t={},n=new Set;for(const r of e){n.add(r.args.data.nodeId);let e=r.args.data.reason||"unknown";if("unknown"===e&&i.Types.TraceEvents.isTraceEventScheduleStyleInvalidationTracking(r)&&r.args.data.invalidatedSelectorId)switch(r.args.data.invalidatedSelectorId){case"attribute":e="Attribute",r.args.data.changedAttribute&&(e+=` (${r.args.data.changedAttribute})`);break;case"class":e="Class",r.args.data.changedClass&&(e+=` (${r.args.data.changedClass})`);break;case"id":e="Id",r.args.data.changedId&&(e+=` (${r.args.data.changedId})`)}if("PseudoClass"===e&&i.Types.TraceEvents.isTraceEventStyleRecalcInvalidationTracking(r)&&r.args.data.extraData&&(e+=r.args.data.extraData),"Attribute"===e&&i.Types.TraceEvents.isTraceEventStyleRecalcInvalidationTracking(r)&&r.args.data.extraData&&(e+=` (${r.args.data.extraData})`),"StyleInvalidator"===e)continue;const s=t[e]||[];s.push(r),t[e]=s}return{groupedByReason:t,backendNodeIds:n}}});const H=new CSSStyleSheet;H.replaceSync(':host *{box-sizing:border-box}devtools-dialog{--override-transparent:rgb(0 0 0/50%)}.content{max-width:500px;padding:16px}.content > :first-child{margin-top:0}.buttons-section{display:flex;justify-content:flex-end;margin-top:16px;gap:8px}input[type="checkbox"]{height:12px;width:12px;min-height:12px;min-width:12px;margin:6px}input[type="text"][disabled]{color:var(--sys-color-state-disabled)}label{display:inline-flex;align-items:center;overflow:hidden;text-overflow:ellipsis}.warning{color:var(--color-error-text)}\n/*# sourceURL=fieldSettingsDialog.css */\n');const j={setUp:"Set up",configure:"Configure",ok:"Ok",optOut:"Opt out",cancel:"Cancel",onlyFetchFieldData:"Only fetch field data for the below URL",urlOverride:"URL Override",doesNotHaveSufficientData:"The Chrome UX Report does not have sufficient real-world speed data for this page.",configureFieldData:"Configure field data fetching",fetchAggregated:"Fetch aggregated field data from the Chrome UX Report to help you contextualize local measurements with what real users experience on the site.",privacyDisclosure:"Privacy disclosure",whenPerformanceIsShown:"When DevTools is open, the URLs you visit will be sent to Google to query field data. These requests are not tied to your Google account.",advanced:"Advanced"},W=t.i18n.registerUIStrings("panels/timeline/components/FieldSettingsDialog.ts",j),V=t.i18n.getLocalizedString.bind(void 0,W),{html:z,nothing:X}=s;class K extends Event{static eventName="showdialog";constructor(){super(K.eventName)}}class G extends HTMLElement{static litTagName=s.literal`devtools-field-settings-dialog`;#e=this.attachShadow({mode:"open"});#c;#h=u.CrUXManager.instance().getConfigSetting();#u="";#g=!1;#p=!1;constructor(){super();const e=u.CrUXManager.instance();this.#h=e.getConfigSetting(),this.#m(),this.#i()}#m(){this.#u=this.#h.get().override,this.#g=Boolean(this.#u)}#v(e){this.#h.set({enabled:e,override:this.#g?this.#u:""})}#b(){n.ScheduledRender.scheduleRender(this,this.#i)}async#w(e){if(e&&this.#g){const e=u.CrUXManager.instance(),t=await e.getFieldDataForPage(this.#u);if(Object.values(t).every((e=>!e)))return this.#p=!0,void n.ScheduledRender.scheduleRender(this,this.#i)}this.#v(e),this.#f()}#k(){if(!this.#c)throw new Error("Dialog not found");this.#m(),this.#c.setDialogVisible(!0),n.ScheduledRender.scheduleRender(this,this.#i),this.dispatchEvent(new K)}#f(e){if(!this.#c)throw new Error("Dialog not found");this.#c.setDialogVisible(!1),e&&e.stopImmediatePropagation(),n.ScheduledRender.scheduleRender(this,this.#i)}connectedCallback(){this.#e.adoptedStyleSheets=[H,m.textInputStyles,m.checkboxStyles],this.#h.addChangeListener(this.#b,this),n.ScheduledRender.scheduleRender(this,this.#i)}disconnectedCallback(){this.#h.removeChangeListener(this.#b,this)}#S(){return this.#h.get().enabled?z`
<${g.Button.Button.litTagName}
@click=${this.#k}
.data=${{variant:"outlined",title:V(j.configure)}}
jslogContext=${"field-data-configure"}
>${V(j.configure)}</${g.Button.Button.litTagName}>
`:z`
<${g.Button.Button.litTagName}
@click=${this.#k}
.data=${{variant:"primary",title:V(j.setUp)}}
jslogContext=${"field-data-setup"}
>${V(j.setUp)}</${g.Button.Button.litTagName}>
`}#y(){return z`
<${g.Button.Button.litTagName}
@click=${()=>{this.#w(!0)}}
.data=${{variant:"primary",title:V(j.ok)}}
jslogContext=${"field-data-enable"}
>${V(j.ok)}</${g.Button.Button.litTagName}>
`}#$(){const e=this.#h.get().enabled?V(j.optOut):V(j.cancel);return z`
<${g.Button.Button.litTagName}
@click=${()=>{this.#w(!1)}}
.data=${{variant:"outlined",title:e}}
jslogContext=${"field-data-disable"}
>${e}</${g.Button.Button.litTagName}>
`}#T(e){const t=e.target;this.#u=t.value,this.#p=!1,n.ScheduledRender.scheduleRender(this,this.#i)}#x(e){const t=e.target;this.#g=t.checked,this.#p=!1,n.ScheduledRender.scheduleRender(this,this.#i)}#i=()=>{const e=z`
${this.#S()}
<${p.Dialog.Dialog.litTagName}
@clickoutsidedialog=${this.#f}
.showConnector=${!0}
.position=${"auto"}
.horizontalAlignment=${"center"}
.jslogContext=${"field-data-settings"}
on-render=${n.Directives.nodeRenderedCallback((e=>{this.#c=e}))}
>
<div class="content">
<h2>${V(j.configureFieldData)}</h2>
<p>${V(j.fetchAggregated)}</p>
<h3>${V(j.privacyDisclosure)}</h3>
<p>${V(j.whenPerformanceIsShown)}</p>
<details>
<summary>${V(j.advanced)}</summary>
<p>
<label>
<input
type="checkbox"
.checked=${this.#g}
@change=${this.#x}
jslog=${a.toggle().track({click:!0}).context("field-url-override-enabled")}
aria-label=${V(j.onlyFetchFieldData)}
/>
${V(j.onlyFetchFieldData)}
</label>
</p>
<input
type="text"
@change=${this.#T}
@keyup=${this.#T}
class="devtools-text-input"
.disabled=${!this.#g}
.value=${this.#u}
aria-label=${V(j.urlOverride)}
/>
${this.#p?z`
<p class="warning">${V(j.doesNotHaveSufficientData)}</p>
`:X}
</details>
<div class="buttons-section">
${this.#$()}
${this.#y()}
</div>
</div>
</${p.Dialog.Dialog.litTagName}
`;s.render(e,this.#e,{host:this})}}customElements.define("devtools-field-settings-dialog",G);var J=Object.freeze({__proto__:null,ShowDialog:K,FieldSettingsDialog:G});const Q=new CSSStyleSheet;Q.replaceSync(":host{display:block}.breakdown{margin:0;padding:0;list-style:none;color:var(--sys-color-token-subtle)}.value{display:inline-block;padding:0 5px;color:var(--sys-color-on-surface)}\n/*# sourceURL=interactionBreakdown.css */\n");const Y={inputDelay:"Input delay",processingDuration:"Processing duration",presentationDelay:"Presentation delay"},Z=t.i18n.registerUIStrings("panels/timeline/components/InteractionBreakdown.ts",Y),ee=t.i18n.getLocalizedString.bind(void 0,Z);class te extends HTMLElement{static litTagName=s.literal`devtools-interaction-breakdown`;#e=this.attachShadow({mode:"open"});#t=this.#i.bind(this);#C=null;connectedCallback(){this.#e.adoptedStyleSheets=[Q]}set entry(e){e!==this.#C&&(this.#C=e,n.ScheduledRender.scheduleRender(this,this.#t))}#i(){if(!this.#C)return;const e=t.TimeUtilities.formatMicroSecondsTime(this.#C.inputDelay),i=t.TimeUtilities.formatMicroSecondsTime(this.#C.mainThreadHandling),n=t.TimeUtilities.formatMicroSecondsTime(this.#C.presentationDelay);s.render(s.html`<ul class="breakdown">
<li data-entry="input-delay">${ee(Y.inputDelay)}<span class="value">${e}</span></li>
<li data-entry="processing-duration">${ee(Y.processingDuration)}<span class="value">${i}</span></li>
<li data-entry="presentation-delay">${ee(Y.presentationDelay)}<span class="value">${n}</span></li>
</ul>
`,this.#e,{host:this})}}customElements.define("devtools-interaction-breakdown",te);var ie=Object.freeze({__proto__:null,InteractionBreakdown:te});const ne=new CSSStyleSheet;ne.replaceSync(".container{container-type:inline-size;height:100%}.live-metrics-view{--min-main-area-size:60%;background-color:var(--sys-color-cdt-base-container);display:flex;flex-direction:row;width:100%;height:100%}.live-metrics,\n.next-steps{padding:8px 16px;height:100%;overflow-y:auto;box-sizing:border-box;display:flex;flex-direction:column}.live-metrics{flex:1}.next-steps{flex:0 0 300px;box-sizing:border-box;border:none;border-left:1px solid var(--sys-color-divider)}@container (max-width: 600px){.live-metrics-view{flex-direction:column}.next-steps{flex-basis:40%;border:none;border-top:1px solid var(--sys-color-divider)}}.metric-cards{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));width:100%}.section-title{text-wrap:nowrap;font-size:14px;font-weight:bold}.card{border:1px solid var(--sys-color-divider);border-radius:4px;padding:12px 16px;display:flex;flex-direction:column;gap:16px;background-color:var(--sys-color-surface2)}.next-steps .card{margin-bottom:16px}.card-title{text-wrap:nowrap;font-size:12px;font-weight:bold}.card-section-title{text-wrap:nowrap;font-size:12px;font-weight:bold}.card-metric-values{display:grid;grid-template-columns:1fr 1fr;column-gap:8px}.metric-value{text-wrap:nowrap}.local-value,\n.field-value{font-size:30px}.metric-value-label{font-size:12px;font-weight:bold}.good{color:var(--app-color-performance-good)}.needs-improvement{color:var(--app-color-performance-ok)}.poor{color:var(--app-color-performance-bad)}.good-bg{background-color:var(--app-color-performance-good)}.needs-improvement-bg{background-color:var(--app-color-performance-ok)}.poor-bg{background-color:var(--app-color-performance-bad)}.metric-card-element{overflow:hidden}.interactions-list{padding:0;margin:0;overflow:auto;flex-grow:1;min-height:100px}.interaction{display:flex;align-items:center;gap:32px}.interaction-type{font-weight:bold;width:60px;flex-shrink:0}.interaction-node{overflow:hidden;flex-grow:1}.interaction-duration{text-align:end;width:max-content;flex-shrink:0}.divider{grid-column:1/-1;width:100%;border:0;border-bottom:1px solid var(--sys-color-divider);margin:4px 0}.field-data-histogram{display:grid;grid-template-columns:max-content 100px max-content;grid-auto-rows:1fr;column-gap:8px;justify-items:flex-end;align-items:center;flex:1}.histogram-bar{height:6px}.histogram-label{width:100%;font-weight:bold}.histogram-range{font-weight:normal;color:var(--sys-color-token-subtle)}.record-action{display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:8px}.record-action devtools-button{overflow:hidden}.shortcut-label{width:max-content;color:var(--sys-color-token-subtle);flex-shrink:0}.live-metrics-option{display:flex;flex-flow:row nowrap;align-items:center;gap:8px;max-width:100%;text-wrap:nowrap}.live-metrics-option > devtools-select-menu{min-width:0;max-width:100%}.no-data{color:var(--sys-color-token-subtle)}.tooltip-content{margin:0 6px}\n/*# sourceURL=liveMetricsView.css */\n");const{html:re,nothing:se}=s,ae={disabled:"Disabled",presets:"Presets",custom:"Custom",add:"Add…"},oe=t.i18n.registerUIStrings("panels/timeline/components/NetworkThrottlingSelector.ts",ae),le=t.i18n.getLocalizedString.bind(void 0,oe);class de extends HTMLElement{static litTagName=s.literal`devtools-network-throttling-selector`;#e=this.attachShadow({mode:"open"});#R;#M=[];#P;constructor(){super(),this.#R=v.Settings.Settings.instance().moduleSetting("custom-network-conditions"),this.#I(),this.#P=o.NetworkManager.MultitargetNetworkManager.instance().networkConditions(),this.#i()}connectedCallback(){o.NetworkManager.MultitargetNetworkManager.instance().addEventListener("ConditionsChanged",this.#L,this),this.#R.addChangeListener(this.#N,this)}disconnectedCallback(){o.NetworkManager.MultitargetNetworkManager.instance().removeEventListener("ConditionsChanged",this.#L,this),this.#R.removeChangeListener(this.#N,this)}#I(){this.#M=[{name:le(ae.disabled),items:[o.NetworkManager.NoThrottlingConditions]},{name:le(ae.presets),items:d.ThrottlingPresets.ThrottlingPresets.networkPresets},{name:le(ae.custom),items:this.#R.get(),showCustomAddOption:!0}]}#L(){this.#P=o.NetworkManager.MultitargetNetworkManager.instance().networkConditions(),n.ScheduledRender.scheduleRender(this,this.#i)}#d(e){const t=this.#M.flatMap((e=>e.items)).find((t=>t.i18nTitleKey===e.itemValue));t&&o.NetworkManager.MultitargetNetworkManager.instance().setNetworkConditions(t)}#N(){this.#I(),n.ScheduledRender.scheduleRender(this,this.#i)}#D(e){return e.title instanceof Function?e.title():e.title}#E(){v.Revealer.reveal(this.#R)}#i=()=>{const e=re`
<${l.SelectMenu.SelectMenu.litTagName}
@selectmenuselected=${this.#d}
.showDivider=${!0}
.showArrow=${!0}
.sideButton=${!1}
.showSelectedItem=${!0}
.showConnector=${!1}
.jslogContext=${"network-conditions"}
.buttonTitle=${this.#D(this.#P)}
>
${this.#M.map((e=>re`
<${l.Menu.MenuGroup.litTagName} .name=${e.name}>
${e.items.map((e=>re`
<${l.Menu.MenuItem.litTagName}
.value=${e.i18nTitleKey}
.selected=${this.#P.i18nTitleKey===e.i18nTitleKey}
jslog=${a.item(c.StringUtilities.toKebabCase(e.i18nTitleKey||""))}
>
${this.#D(e)}
</${l.Menu.MenuItem.litTagName}>
`))}
${e.showCustomAddOption?re`
<${l.Menu.MenuItem.litTagName}
.value=${1}
jslog=${a.action("add").track({click:!0})}
@click=${this.#E}
>
${le(ae.add)}
</${l.Menu.MenuItem.litTagName}>
`:se}
</${l.Menu.MenuGroup.litTagName}>
`))}
</${l.SelectMenu.SelectMenu.litTagName}>
`;s.render(e,this.#e,{host:this})}}customElements.define("devtools-network-throttling-selector",de);var ce=Object.freeze({__proto__:null,NetworkThrottlingSelector:de});const{html:he,nothing:ue,Directives:ge}=s,{until:pe}=ge,me=[2500,4e3],ve=[.1,.25],be=[200,500],we=["AUTO",...u.DEVICE_SCOPE_LIST],fe={localAndFieldMetrics:"Local and Field Metrics",interactions:"Interactions",nextSteps:"Next steps",fieldData:"Field data",throttling:"Throttling",lcpTitle:"Largest Contentful Paint (LCP)",clsTitle:"Cumulative Layout Shift (CLS)",inpTitle:"Interaction to Next Paint (INP)",localValue:"Local",field75thPercentile:"Field 75th Percentile",deviceType:"Device type:",urlOrOrigin:"URL/Origin:",networkThrottling:"Network throttling:",cpuThrottling:"CPU throttling:",allDevices:"All devices",desktop:"Desktop",mobile:"Mobile",tablet:"Tablet",auto:"Auto ({PH1})",loadingOption:"{PH1} - Loading…",needsDataOption:"{PH1} - No data",urlOption:"URL",originOption:"Origin",urlOptionWithKey:"URL ({PH1})",originOptionWithKey:"Origin ({PH1})",tryDisablingThrottling:"Try disabling network throttling to approximate the network latency measured by real users.",tryUsingThrottling:"Try using {PH1} network throttling to approximate the network latency measured by real users.",relatedNode:"Related node",good:"Good",needsImprovement:"Needs improvement",poor:"Poor",leqRange:"(≤{PH1})",betweenRange:"({PH1}-{PH2})",gtRange:"(>{PH1})",percentage:"{PH1}%"},ke=t.i18n.registerUIStrings("panels/timeline/components/LiveMetricsView.ts",fe),Se=t.i18n.getLocalizedString.bind(void 0,ke);class ye extends HTMLElement{static litTagName=s.literal`devtools-metric-card`;#e=this.attachShadow({mode:"open"});constructor(){super(),this.#i()}#U;#c;connectedCallback(){this.#e.adoptedStyleSheets=[ne],n.ScheduledRender.scheduleRender(this,this.#i)}#k(){this.#c&&(this.#c.setDialogVisible(!0),n.ScheduledRender.scheduleRender(this,this.#i))}#f(e){if(this.#c&&this.#U){if(e){const t=e.composedPath();if(t.includes(this.#U))return;if(t.includes(this.#c))return}this.#c.setDialogVisible(!1),n.ScheduledRender.scheduleRender(this,this.#i)}}#i=()=>{const e=he`
<div class="card metric-card">
<div class="card-title">
<slot name="headline"></slot>
</div>
<div class="card-metric-values"
@mouseenter=${this.#k}
@mouseleave=${this.#f}
on-render=${n.Directives.nodeRenderedCallback((e=>{this.#U=e}))}
>
<span class="local-value">
<slot name="local-value"></slot>
</span>
<span class="field-value">
<slot name="field-value"></slot>
</span>
<span class="metric-value-label">${Se(fe.localValue)}</span>
<span class="metric-value-label">${Se(fe.field75thPercentile)}</span>
</div>
<${p.Dialog.Dialog.litTagName}
@pointerleftdialog=${()=>this.#f()}
.showConnector=${!0}
.centered=${!0}
.closeOnScroll=${!1}
.origin=${()=>{if(!this.#U)throw new Error("No metric values element");return this.#U}}
on-render=${n.Directives.nodeRenderedCallback((e=>{this.#c=e}))}
>
<div class="tooltip-content">
<slot name="tooltip"></slot>
</div>
</${p.Dialog.Dialog.litTagName}>
<hr class="divider">
<div class="metric-card-element">
<slot name="related-element"><slot>
</div>
</div>
`;s.render(e,this.#e,{host:this})}}class $e extends HTMLElement{static litTagName=s.literal`devtools-live-metrics-view`;#e=this.attachShadow({mode:"open"});#q;#O;#B;#A=[];#F;#_="AUTO";#H="url";#j;#W;constructor(){super(),this.#j=h.ActionRegistry.ActionRegistry.instance().getAction("timeline.toggle-recording"),this.#W=h.ActionRegistry.ActionRegistry.instance().getAction("timeline.record-reload"),this.#i()}#V(e){this.#q=e.data.lcp,this.#O=e.data.cls,this.#B=e.data.inp,this.#A=e.data.interactions,n.ScheduledRender.scheduleRender(this,this.#i)}#z(e){this.#F=e.data,n.ScheduledRender.scheduleRender(this,this.#i)}#X(){n.ScheduledRender.scheduleRender(this,this.#i)}async#K(){this.#F=await u.CrUXManager.instance().getFieldDataForCurrentPage(),n.ScheduledRender.scheduleRender(this,this.#i)}#G(e){const t="AUTO"===this.#_?this.#J():this.#_;return this.#F?.[`${this.#H}-${t}`]?.record.metrics[e]}connectedCallback(){this.#e.adoptedStyleSheets=[ne];const e=w.LiveMetrics.instance();e.addEventListener("status",this.#V,this);const t=u.CrUXManager.instance();t.addEventListener("field-data-changed",this.#z,this);b.DeviceModeModel.DeviceModeModel.instance().addEventListener("Updated",this.#X,this),t.getConfigSetting().get().enabled&&this.#K(),this.#q=e.lcpValue,this.#O=e.clsValue,this.#B=e.inpValue,this.#A=e.interactions,n.ScheduledRender.scheduleRender(this,this.#i)}disconnectedCallback(){w.LiveMetrics.instance().removeEventListener("status",this.#V,this);u.CrUXManager.instance().removeEventListener("field-data-changed",this.#z,this);b.DeviceModeModel.DeviceModeModel.instance().removeEventListener("Updated",this.#X,this)}#Q(e,t,i){if(void 0===e)return he`<span class="metric-value waiting">-<span>`;"string"==typeof e&&(e=Number(e));const n=this.#Y(e,t),r=i(e);return he`
<span class=${`metric-value ${n}`}>${r}</span>
`}#Z(){const e=this.#G("largest_contentful_paint");return this.#ee(Se(fe.lcpTitle),this.#q?.value,e?.percentiles?.p75,e?.histogram,me,(e=>t.TimeUtilities.millisToString(e)),this.#q?.node)}#te(){const e=this.#G("cumulative_layout_shift");return this.#ee(Se(fe.clsTitle),this.#O?.value,e?.percentiles?.p75,e?.histogram,ve,(e=>0===e?"0":e.toFixed(2)))}#ie(){const e=this.#G("interaction_to_next_paint");return this.#ee(Se(fe.inpTitle),this.#B?.value,e?.percentiles?.p75,e?.histogram,be,(e=>t.TimeUtilities.millisToString(e)))}#ne(e){void 0===e&&(e=0);return`${Math.round(100*e)}%`}#re(e,t){if(void 0===e)return"-";const i=e[t].density||0,n=Math.round(100*i);return Se(fe.percentage,{PH1:n})}#se(e,t,i){const n=this.#ne(e?.[0].density),r=this.#ne(e?.[1].density),s=this.#ne(e?.[2].density);return he`
<div class="field-data-histogram">
<span class="histogram-label">
${Se(fe.good)}
<span class="histogram-range">${Se(fe.leqRange,{PH1:i(t[0])})}</span>
</span>
<span class="histogram-bar good-bg" style="width: ${n}"></span>
<span class="histogram-percent">${this.#re(e,0)}</span>
<span class="histogram-label">
${Se(fe.needsImprovement)}
<span class="histogram-range">${Se(fe.betweenRange,{PH1:i(t[0]),PH2:i(t[1])})}</span>
</span>
<span class="histogram-bar needs-improvement-bg" style="width: ${r}"></span>
<span class="histogram-percent">${this.#re(e,1)}</span>
<span class="histogram-label">
${Se(fe.poor)}
<span class="histogram-range">${Se(fe.gtRange,{PH1:i(t[1])})}</span>
</span>
<span class="histogram-bar poor-bg" style="width: ${s}"></span>
<span class="histogram-percent">${this.#re(e,2)}</span>
</div>
`}#Y(e,t){return e<=t[0]?"good":e<=t[1]?"needs-improvement":"poor"}#ee(e,t,i,n,r,s,a){return he`
<${ye.litTagName}>
<div slot="headline">${e}</div>
<span slot="local-value">${this.#Q(t,r,s)}</span>
<span slot="field-value">${this.#Q(i,r,s)}</span>
<div slot="tooltip">
${this.#se(n,r,s)}
</div>
<div slot="related-element">
${a?he`
<div class="card-section-title">${Se(fe.relatedNode)}</div>
<div>${pe(v.Linkifier.Linkifier.linkify(a))}</div>`:ue}
</div>
</${ye.litTagName}>
`}#ae(e){return he`
<div class="record-action">
<${g.Button.Button.litTagName} @click=${function(){e.execute()}} .data=${{variant:"text",size:"REGULAR",iconName:e.icon(),title:e.title(),jslogContext:e.id()}}>
${e.title()}
</${g.Button.Button.litTagName}>
<span class="shortcut-label">${h.ShortcutRegistry.ShortcutRegistry.instance().shortcutTitleForAction(e.id())}</span>
</div>
`}#oe(){const e=this.#G("round_trip_time");if(!e?.percentiles)return null;const t=Number(e.percentiles.p75);if(!Number.isFinite(t))return null;if(t<60)return o.NetworkManager.NoThrottlingConditions;let i=null,n=1/0;for(const e of d.ThrottlingPresets.ThrottlingPresets.networkPresets){const{targetLatency:r}=e;if(!r)continue;const s=Math.abs(r-t);s>200||(n<s||(i=e,n=s))}return i}#le(){const e=this.#oe();let t;if(e)if(e===o.NetworkManager.NoThrottlingConditions)t=Se(fe.tryDisablingThrottling);else{const i="function"==typeof e.title?e.title():e.title;t=Se(fe.tryUsingThrottling,{PH1:i})}return he`
<div class="card-title">${Se(fe.throttling)}</div>
${t?he`<div class="throttling-recommendation">${t}</div>`:ue}
<span class="live-metrics-option">
${Se(fe.cpuThrottling)}<${q.litTagName}>
</${q.litTagName}>
</span>
<span class="live-metrics-option">
${Se(fe.networkThrottling)}
<${de.litTagName}></${de.litTagName}>
</span>
`}#de(e){const t=this.#F?.[`${e}-ALL`]?.record.key[e];if(t)return Se("url"===e?fe.urlOptionWithKey:fe.originOptionWithKey,{PH1:t});const i=Se("url"===e?fe.urlOption:fe.originOption);return Se(fe.needsDataOption,{PH1:i})}#ce(e){"url"===e.itemValue?this.#H="url":this.#H="origin",n.ScheduledRender.scheduleRender(this,this.#i)}#he(){if(!u.CrUXManager.instance().getConfigSetting().get().enabled)return s.nothing;const e=this.#de("url"),t=this.#de("origin");return he`
<span id="page-scope-select" class="live-metrics-option">
${Se(fe.urlOrOrigin)}
<${l.SelectMenu.SelectMenu.litTagName}
@selectmenuselected=${this.#ce}
.showDivider=${!0}
.showArrow=${!0}
.sideButton=${!1}
.showSelectedItem=${!0}
.showConnector=${!1}
.buttonTitle=${"url"===this.#H?e:t}
>
<${l.Menu.MenuItem.litTagName}
.value=${"url"}
.selected=${"url"===this.#H}
>
${e}
</${l.Menu.MenuItem.litTagName}>
<${l.Menu.MenuItem.litTagName}
.value=${"origin"}
.selected=${"origin"===this.#H}
>
${t}
</${l.Menu.MenuItem.litTagName}>
</${l.SelectMenu.SelectMenu.litTagName}>
</span>
`}#ue(e){switch(e){case"ALL":return Se(fe.allDevices);case"DESKTOP":return Se(fe.desktop);case"PHONE":return Se(fe.mobile);case"TABLET":return Se(fe.tablet)}}#J(){const e=b.DeviceModeModel.DeviceModeModel.instance();return e.device()?.mobile()?this.#F?.[`${this.#H}-PHONE`]?"PHONE":"ALL":this.#F?.[`${this.#H}-DESKTOP`]?"DESKTOP":"ALL"}#ge(e){const t="AUTO"===e?this.#J():e,i=this.#ue(t),n="AUTO"===e?Se(fe.auto,{PH1:i}):i;if(!this.#F)return Se(fe.loadingOption,{PH1:n});return this.#F[`${this.#H}-${t}`]?n:Se(fe.needsDataOption,{PH1:n})}#pe(e){this.#_=e.itemValue,n.ScheduledRender.scheduleRender(this,this.#i)}#me(){if(!u.CrUXManager.instance().getConfigSetting().get().enabled)return s.nothing;const e=!this.#F?.[`${this.#H}-ALL`];return he`
<span id="device-scope-select" class="live-metrics-option">
${Se(fe.deviceType)}
<${l.SelectMenu.SelectMenu.litTagName}
@selectmenuselected=${this.#pe}
.showDivider=${!0}
.showArrow=${!0}
.sideButton=${!1}
.showSelectedItem=${!0}
.showConnector=${!1}
.buttonTitle=${this.#ge(this.#_)}
.disabled=${e}
>
${we.map((e=>he`
<${l.Menu.MenuItem.litTagName}
.value=${e}
.selected=${this.#_===e}
>
${this.#ge(e)}
</${l.Menu.MenuItem.litTagName}>
`))}
</${l.SelectMenu.SelectMenu.litTagName}>
</span>
`}#i=()=>{const e=he`
<div class="container">
<div class="live-metrics-view">
<div class="live-metrics" slot="main">
<h3>${Se(fe.localAndFieldMetrics)}</h3>
<div class="metric-cards">
<div id="lcp">
${this.#Z()}
</div>
<div id="cls">
${this.#te()}
</div>
<div id="inp">
${this.#ie()}
</div>
</div>
<h3>${Se(fe.interactions)}</h3>
<ol class="interactions-list">
${this.#A.map(((e,i)=>he`
${0===i?he`<hr class="divider">`:ue}
<li class="interaction">
<span class="interaction-type">${e.interactionType}</span>
<span class="interaction-node">${e.node&&pe(v.Linkifier.Linkifier.linkify(e.node))}</span>
<span class="interaction-duration">
${this.#Q(e.duration,be,(e=>t.TimeUtilities.millisToString(e)))}
</span>
</li>
<hr class="divider">
`))}
</ol>
</div>
<div class="next-steps" slot="sidebar">
<h3>${Se(fe.nextSteps)}</h3>
<div id="field-setup" class="card">
<div class="card-title">${Se(fe.fieldData)}</div>
${this.#he()}
${this.#me()}
<${G.litTagName}></${G.litTagName}>
</div>
<div id="throttling" class="card">
${this.#le()}
</div>
<div id="record" class="card">
${this.#ae(this.#j)}
</div>
<div id="record-page-load" class="card">
${this.#ae(this.#W)}
</div>
</div>
</div>
</div>
`;s.render(e,this.#e,{host:this})}}customElements.define("devtools-metric-card",ye),customElements.define("devtools-live-metrics-view",$e);var Te=Object.freeze({__proto__:null,MetricCard:ye,LiveMetricsView:$e});const xe=new CSSStyleSheet;var Ce;function Re(e){let t="--app-color-system";switch(e){case Ce.Doc:t="--app-color-doc";break;case Ce.JS:t="--app-color-scripting";break;case Ce.CSS:t="--app-color-css";break;case Ce.Img:t="--app-color-image";break;case Ce.Media:t="--app-color-media";break;case Ce.Font:t="--app-color-font";break;case Ce.Wasm:t="--app-color-wasm";break;case Ce.Other:default:t="--app-color-system"}return y.ThemeSupport.instance().getComputedValue(t)}function Me(e){const t=function(e){switch(e.args.data.mimeType){case"text/html":return Ce.Doc;case"application/javascript":case"application/x-javascript":case"text/javascript":return Ce.JS;case"text/css":return Ce.CSS;case"image/gif":case"image/jpeg":case"image/png":case"image/svg+xml":case"image/webp":case"image/x-icon":return Ce.Img;case"audio/aac":case"audio/midi":case"audio/x-midi":case"audio/mpeg":case"audio/ogg":case"audio/wav":case"audio/webm":return Ce.Media;case"font/opentype":case"font/woff2":case"font/ttf":case"application/font-woff":return Ce.Font;case"application/wasm":return Ce.Wasm;default:return Ce.Other}}(e);return Re(t)}xe.replaceSync('.network-request-details-title{font-size:13px;padding:8px;display:flex;align-items:center}.network-request-details-title > div{box-sizing:border-box;width:12px;height:12px;border:1px solid var(--sys-color-divider);display:inline-block;margin-right:4px;content:" "}.network-request-details-body{display:flex;padding-bottom:5px;border-bottom:1px solid var(--sys-color-divider)}.network-request-details-col{flex:1}.network-request-details-row{display:flex;padding:0 10px;min-height:20px}.title{color:var(--sys-color-token-subtle);overflow:hidden;padding-right:10px;display:inline-block;vertical-align:top}.value{display:inline-block;user-select:text;text-overflow:ellipsis;overflow:hidden;padding:0 3px}.devtools-link{color:var(--text-link);text-decoration:underline;outline-offset:2px;padding:0;.elements-disclosure &{color:var(--text-link)}devtools-icon{vertical-align:baseline;color:var(--sys-color-primary)}:focus .selected & devtools-icon{color:var(--sys-color-tonal-container)}&:focus-visible{outline-width:unset}&.invalid-link{color:var(--text-disabled);text-decoration:none}&:not(.devtools-link-prevent-click, .invalid-link){cursor:pointer}@media (forced-colors: active){&:not(.devtools-link-prevent-click){forced-color-adjust:none;color:linktext}&:focus-visible{background:Highlight;color:HighlightText}}}.text-button.link-style,\n.text-button.link-style:hover,\n.text-button.link-style:active{background:none;border:none;font:inherit}.timings-row{align-self:start;display:flex;align-items:center;width:100%}.indicator{display:inline-block;width:10px;height:4px;margin-right:5px;border:1px solid var(--sys-color-on-surface-subtle)}.whisker-left{align-self:center;display:inline-flex;width:10px;height:6px;margin-right:5px;border-left:1px solid var(--sys-color-on-surface-subtle)}.whisker-right{align-self:center;display:inline-flex;width:10px;height:6px;margin-right:5px;border-right:1px solid var(--sys-color-on-surface-subtle)}.horizontal{background-color:var(--sys-color-on-surface-subtle);height:1px;width:10px;align-self:center}.time{display:inline-block;padding-left:10px;margin-left:auto}\n/*# sourceURL=networkRequestDetails.css */\n'),function(e){e.Doc="Doc",e.CSS="CSS",e.JS="JS",e.Font="Font",e.Img="Img",e.Media="Media",e.Wasm="Wasm",e.Other="Other"}(Ce||(Ce={}));var Pe=Object.freeze({__proto__:null,get NetworkCategory(){return Ce},colorForNetworkCategory:Re,colorForNetworkRequest:Me});const Ie={initialPriority:"Initial Priority",requestMethod:"Request Method",priority:"Priority",encodedData:"Encoded Data",decodedBody:"Decoded Body",yes:"Yes",no:"No",preview:"Preview",networkRequest:"Network request",duration:"Duration",fromCache:"From cache",mimeType:"Mime Type",FromMemoryCache:" (from memory cache)",FromCache:" (from cache)",FromPush:" (from push)",FromServiceWorker:" (from `service worker`)",initiatedBy:"Initiated by",queuingAndConnecting:"Queuing and connecting",requestSentAndWaiting:"Request sent and waiting",contentDownloading:"Content downloading",waitingOnMainThread:"Waiting on main thread"},Le=t.i18n.registerUIStrings("panels/timeline/components/NetworkRequestDetails.ts",Ie),Ne=t.i18n.getLocalizedString.bind(void 0,Le);class De extends HTMLElement{static litTagName=s.literal`devtools-performance-network-request-details`;#e=this.attachShadow({mode:"open"});#ve=null;#be=null;#we=new WeakMap;#fe;constructor(e){super(),this.#fe=e}connectedCallback(){this.#e.adoptedStyleSheets=[xe]}async setData(e,t){this.#ve!==e&&(this.#ve=e,this.#be=t,await this.#i())}#ke(){if(!this.#ve)return null;const e={backgroundColor:`${Me(this.#ve)}`};return s.html`
<div class="network-request-details-title">
<div style=${s.Directives.styleMap(e)}"></div>
${Ne(Ie.networkRequest)}
</div>
`}#Se(e,t){return t?s.html`
<div class="network-request-details-row"><div class="title">${e}</div><div class="value">${t}</div></div>
`:null}#ye(){if(!this.#ve)return null;const e={tabStop:!0,showColumnNumber:!1,inlineFrameIndex:0,maxLength:80},i=k.Linkifier.Linkifier.linkifyURL(this.#ve.args.data.url,e);return i.addEventListener("contextmenu",(e=>{if(!this.#ve)return;const t=new S.NetworkRequest.TimelineNetworkRequest(this.#ve),i=new h.ContextMenu.ContextMenu(e,{useSoftMenu:!0});i.appendApplicableItems(t),i.show()})),this.#Se(t.i18n.lockedString("URL"),i)}#$e(){if(!this.#ve)return null;const e=this.#ve.args.data.syntheticData.isMemoryCached||this.#ve.args.data.syntheticData.isDiskCached;return this.#Se(Ne(Ie.fromCache),Ne(e?Ie.yes:Ie.no))}#Te(){if(!this.#ve)return null;const e=this.#ve.dur;if(!isFinite(e))return null;const i=t.TimeUtilities.formatMicroSecondsTime(e),n=s.html`
<div>
${i}
${this.#xe()}
</div>
`;return this.#Se(Ne(Ie.duration),n)}#Ce(){if(!this.#ve)return null;let e="";return this.#ve.args.data.syntheticData.isMemoryCached?e+=Ne(Ie.FromMemoryCache):this.#ve.args.data.syntheticData.isDiskCached?e+=Ne(Ie.FromCache):this.#ve.args.data.timing?.pushStart&&(e+=Ne(Ie.FromPush)),this.#ve.args.data.fromServiceWorker&&(e+=Ne(Ie.FromServiceWorker)),!this.#ve.args.data.encodedDataLength&&e||(e=`${c.NumberUtilities.bytesToString(this.#ve.args.data.encodedDataLength)}${e}`),this.#Se(Ne(Ie.encodedData),e)}#Re(){if(!this.#ve)return null;const e=i.Helpers.Trace.getZeroIndexedStackTraceForEvent(this.#ve)?.at(0)??null;if(e){const t=this.#fe.maybeLinkifyConsoleCallFrame(this.#be,e,{tabStop:!0,inlineFrameIndex:0,showColumnNumber:!0});if(t)return this.#Se(Ne(Ie.initiatedBy),t)}return null}async#Me(){if(!this.#ve)return null;if(!this.#we.get(this.#ve)&&this.#ve.args.data.url&&this.#be){const e=await k.ImagePreview.ImagePreview.build(this.#be,this.#ve.args.data.url,!1,{imageAltText:k.ImagePreview.ImagePreview.defaultAltTextForImageURL(this.#ve.args.data.url),precomputedFeatures:void 0});this.#we.set(this.#ve,e)}const e=this.#we.get(this.#ve);return e?this.#Se(Ne(Ie.preview),e):null}#Pe(){return s.html`<span class="whisker-left"> <span class="horizontal"></span> </span>`}#Ie(){return s.html`<span class="whisker-right"> <span class="horizontal"></span> </span>`}#xe(){if(!this.#ve)return null;const e=this.#ve.args.data.syntheticData,i=e.sendStartTime-this.#ve.ts,n=e.downloadStart-e.sendStartTime,r=e.finishTime-e.downloadStart,a=this.#ve.ts+this.#ve.dur-e.finishTime,o=Me(this.#ve),l={backgroundColor:`color-mix(in srgb, ${o}, hsla(0, 100%, 100%, 0.8))`},d={backgroundColor:o};return s.html`
<div class="timings-row">
${this.#Pe()}
${Ne(Ie.queuingAndConnecting)}
<span class="time">${t.TimeUtilities.formatMicroSecondsTime(i)}</span>
</div>
<div class="timings-row">
<span class="indicator" style=${s.Directives.styleMap(l)}></span>
${Ne(Ie.requestSentAndWaiting)}
<span class="time">${t.TimeUtilities.formatMicroSecondsTime(n)}</span>
</div>
<div class="timings-row">
<span class="indicator" style=${s.Directives.styleMap(d)}></span>
${Ne(Ie.contentDownloading)}
<span class="time">${t.TimeUtilities.formatMicroSecondsTime(r)}</span>
</div>
<div class="timings-row">
${this.#Ie()}
${Ne(Ie.waitingOnMainThread)}
<span class="time">${t.TimeUtilities.formatMicroSecondsTime(a)}</span>
</div>
`}async#i(){if(!this.#ve)return;const e=this.#ve.args.data,t=s.html`
${this.#ke()}
<div class="network-request-details-body">
<div class="network-request-details-col">
${this.#ye()}
${this.#Se(Ne(Ie.requestMethod),e.requestMethod)}
${this.#Se(Ne(Ie.initialPriority),f.NetworkPriorities.uiLabelForNetworkPriority(e.initialPriority))}
${this.#Se(Ne(Ie.priority),f.NetworkPriorities.uiLabelForNetworkPriority(e.priority))}
${this.#Se(Ne(Ie.mimeType),e.mimeType)}
${this.#Ce()}
${this.#Se(Ne(Ie.decodedBody),c.NumberUtilities.bytesToString(this.#ve.args.data.decodedBodyLength))}
${this.#Re()}
${await this.#Me()}
</div>
<div class="network-request-details-col">
${this.#$e()}
${this.#Te()}
</div>
</div>
`;s.render(t,this.#e,{host:this})}}customElements.define("devtools-performance-network-request-details",De);var Ee=Object.freeze({__proto__:null,NetworkRequestDetails:De});const Ue=new CSSStyleSheet;Ue.replaceSync(".bold{font-weight:bold}.url{margin-left:15px;margin-right:5px}.priority{margin-left:15px}.priority > devtools-icon{height:13px;width:13px;color:var(--sys-color-on-surface-subtle)}.render-blocking{margin-left:15px;color:var(--sys-color-error)}.divider{border-top:1px solid var(--sys-color-divider);margin:5px 0}ul{list-style:none;padding:0;margin:0}li{display:flex;align-items:center}.indicator{display:inline-block;width:10px;height:4px;margin-right:5px;border:1px solid var(--sys-color-on-surface-subtle)}.whisker-left{display:flex;width:10px;height:6px;margin-right:5px;border-left:1px solid var(--sys-color-on-surface-subtle)}.whisker-right{display:flex;width:10px;height:6px;margin-right:5px;border-right:1px solid var(--sys-color-on-surface-subtle)}.horizontal{background-color:var(--sys-color-on-surface-subtle);height:1px;width:10px;align-self:center}.time{margin-left:auto}\n/*# sourceURL=networkRequestTooltip.css */\n");const qe="Priority",Oe="Queuing and connecting",Be="Request sent and waiting",Ae="Content downloading",Fe="Waiting on main thread",_e="Render blocking";class He extends HTMLElement{static litTagName=s.literal`devtools-performance-network-request-tooltip`;#e=this.attachShadow({mode:"open"});#ve;connectedCallback(){this.#e.adoptedStyleSheets=[Ue],this.#i()}set networkRequest(e){this.#ve!==e&&(this.#ve=e,this.#i())}#Le(){return this.#ve?this.#ve.args.data.priority===this.#ve.args.data.initialPriority?s.html`
<div class="priority">${qe}: ${f.NetworkPriorities.uiLabelForNetworkPriority(this.#ve.args.data.priority)}</div>
`:s.html`
<div class="priority">
${qe}:
${f.NetworkPriorities.uiLabelForNetworkPriority(this.#ve.args.data.initialPriority)}
<${r.Icon.Icon.litTagName} name=${"arrow-forward"}></${r.Icon.Icon.litTagName}>
${f.NetworkPriorities.uiLabelForNetworkPriority(this.#ve.args.data.priority)}
</div>
`:null}#Pe(){return s.html`<span class="whisker-left"> <span class="horizontal"></span> </span>`}#Ie(){return s.html`<span class="whisker-right"> <span class="horizontal"></span> </span>`}#xe(){if(!this.#ve)return null;const e=this.#ve.args.data.syntheticData,i=e.sendStartTime-this.#ve.ts,n=e.downloadStart-e.sendStartTime,r=e.finishTime-e.downloadStart,a=this.#ve.ts+this.#ve.dur-e.finishTime,o=Me(this.#ve),l={backgroundColor:`color-mix(in srgb, ${o}, hsla(0, 100%, 100%, 0.8))`},d={backgroundColor:o};return s.html`
<ul>
<li>
${this.#Pe()}
${Oe}
<span class="time">${t.TimeUtilities.formatMicroSecondsTime(i)}</span>
</li>
<li>
<span class="indicator" style=${s.Directives.styleMap(l)}></span>
${Be}
<span class="time">${t.TimeUtilities.formatMicroSecondsTime(n)}</span>
</li>
<li>
<span class="indicator" style=${s.Directives.styleMap(d)}></span>
${Ae}
<span class="time">${t.TimeUtilities.formatMicroSecondsTime(r)}</span>
</li>
<li>
${this.#Ie()}
${Fe}
<span class="time">${t.TimeUtilities.formatMicroSecondsTime(a)}</span>
</li>
</ul>
`}#i(){if(!this.#ve)return;const e=this.#ve.args.data,n=s.html`
<div class="performance-card">
<span class="url">${c.Stri