UNPKG

chrome-devtools-frontend

Version:
99 lines (83 loc) 3.36 kB
// 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. /* eslint-disable rulesdir/no-lit-render-outside-of-view */ // TODO: move to ui/components/node_link? import * as Common from '../../../../core/common/common.js'; import type * as Protocol from '../../../../generated/protocol.js'; import * as Trace from '../../../../models/trace/trace.js'; import * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js'; import * as Lit from '../../../../ui/lit/lit.js'; const {html} = Lit; export interface NodeLinkData { backendNodeId: Protocol.DOM.BackendNodeId; frame: string; options?: Common.Linkifier.Options; /** * Text to display if backendNodeId cannot be resolved (ie for traces loaded from disk). * Displayed as monospace code. Use this or the next field. */ fallbackHtmlSnippet?: string; /** * Text to display if backendNodeId cannot be resolved (ie for traces loaded from disk). * Displayed as plain text. Use this or the previous field. */ fallbackText?: string; } export class NodeLink extends HTMLElement { readonly #shadow = this.attachShadow({mode: 'open'}); #backendNodeId?: Protocol.DOM.BackendNodeId; #frame?: string; #options?: Common.Linkifier.Options; #fallbackHtmlSnippet?: string; #fallbackText?: string; set data(data: NodeLinkData) { this.#backendNodeId = data.backendNodeId; this.#frame = data.frame; this.#options = data.options; this.#fallbackHtmlSnippet = data.fallbackHtmlSnippet; this.#fallbackText = data.fallbackText; void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#render); } async #linkify(): Promise<Node|undefined> { if (this.#backendNodeId === undefined) { return; } // Users of `NodeLink` do not have a parsed trace so this is a workaround. This // is an abuse of this API, but it's currently alright since the first parameter // is only used as a cache key. const domNodesMap = await Trace.Extras.FetchNodes.domNodesForMultipleBackendNodeIds( this as unknown as Trace.Handlers.Types.ParsedTrace, [this.#backendNodeId]); const node = domNodesMap.get(this.#backendNodeId); if (!node) { return; } if (node.frameId() !== this.#frame) { return; } // TODO: it'd be nice if we could specify what attributes to render, // ex for the Viewport insight: <meta content="..."> (instead of just <meta>) return await Common.Linkifier.Linkifier.linkify(node, this.#options); } async #render(): Promise<void> { const relatedNodeEl = await this.#linkify(); let template; if (relatedNodeEl) { template = html`<div class='node-link'>${relatedNodeEl}</div>`; } else if (this.#fallbackHtmlSnippet) { // TODO: Use CodeHighlighter. template = html`<pre style='text-wrap: auto'>${this.#fallbackHtmlSnippet}</pre>`; } else if (this.#fallbackText) { template = html`<span>${this.#fallbackText}</span>`; } else { template = Lit.nothing; } Lit.render(template, this.#shadow, {host: this}); } } declare global { interface HTMLElementTagNameMap { 'devtools-performance-node-link': NodeLink; } } customElements.define('devtools-performance-node-link', NodeLink);