UNPKG

chrome-devtools-frontend

Version:
170 lines (143 loc) 4.79 kB
// Copyright 2016 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import type * as Protocol from '../../generated/protocol.js'; import {DOMModel, type DOMNode} from './DOMModel.js'; import type {SnapshotWithRect} from './PaintProfiler.js'; import type {Target} from './Target.js'; export interface Layer { id(): string; parentId(): string|null; parent(): Layer|null; isRoot(): boolean; children(): Layer[]; addChild(child: Layer): void; node(): DOMNode|null; nodeForSelfOrAncestor(): DOMNode|null; offsetX(): number; offsetY(): number; width(): number; height(): number; transform(): number[]|null; quad(): number[]; anchorPoint(): number[]; invisible(): boolean; paintCount(): number; lastPaintRect(): Protocol.DOM.Rect|null; scrollRects(): Protocol.LayerTree.ScrollRect[]; stickyPositionConstraint(): StickyPositionConstraint|null; gpuMemoryUsage(): number; requestCompositingReasons(): Promise<string[]>; requestCompositingReasonIds(): Promise<string[]>; drawsContent(): boolean; snapshots(): Array<Promise<SnapshotWithRect|null>>; } export namespace Layer { export const enum ScrollRectType { NON_FAST_SCROLLABLE = 'NonFastScrollable', TOUCH_EVENT_HANDLER = 'TouchEventHandler', WHEEL_EVENT_HANDLER = 'WheelEventHandler', REPAINTS_ON_SCROLL = 'RepaintsOnScroll', MAIN_THREAD_SCROLL_REASON = 'MainThreadScrollingReason', } } export class StickyPositionConstraint { readonly #stickyBoxRect: Protocol.DOM.Rect; readonly #containingBlockRect: Protocol.DOM.Rect; readonly #nearestLayerShiftingStickyBox: Layer|null; readonly #nearestLayerShiftingContainingBlock: Layer|null; constructor(layerTree: LayerTreeBase|null, constraint: Protocol.LayerTree.StickyPositionConstraint) { this.#stickyBoxRect = constraint.stickyBoxRect; this.#containingBlockRect = constraint.containingBlockRect; this.#nearestLayerShiftingStickyBox = null; if (layerTree && constraint.nearestLayerShiftingStickyBox) { this.#nearestLayerShiftingStickyBox = layerTree.layerById(constraint.nearestLayerShiftingStickyBox); } this.#nearestLayerShiftingContainingBlock = null; if (layerTree && constraint.nearestLayerShiftingContainingBlock) { this.#nearestLayerShiftingContainingBlock = layerTree.layerById(constraint.nearestLayerShiftingContainingBlock); } } stickyBoxRect(): Protocol.DOM.Rect { return this.#stickyBoxRect; } containingBlockRect(): Protocol.DOM.Rect { return this.#containingBlockRect; } nearestLayerShiftingStickyBox(): Layer|null { return this.#nearestLayerShiftingStickyBox; } nearestLayerShiftingContainingBlock(): Layer|null { return this.#nearestLayerShiftingContainingBlock; } } export class LayerTreeBase { readonly #target: Target|null; #domModel: DOMModel|null; layersById = new Map<string|number, Layer>(); #root: Layer|null = null; #contentRoot: Layer|null = null; readonly #backendNodeIdToNode = new Map<Protocol.DOM.BackendNodeId, DOMNode|null>(); #viewportSize?: { width: number, height: number, }; constructor(target: Target|null) { this.#target = target; this.#domModel = target ? target.model(DOMModel) : null; } target(): Target|null { return this.#target; } root(): Layer|null { return this.#root; } setRoot(root: Layer|null): void { this.#root = root; } contentRoot(): Layer|null { return this.#contentRoot; } setContentRoot(contentRoot: Layer|null): void { this.#contentRoot = contentRoot; } forEachLayer<T>(callback: (arg0: Layer) => T, root?: Layer|null): T|boolean { if (!root) { root = this.root(); if (!root) { return false; } } return callback(root) || root.children().some(this.forEachLayer.bind(this, callback)); } layerById(id: string): Layer|null { return this.layersById.get(id) || null; } async resolveBackendNodeIds(requestedNodeIds: Set<Protocol.DOM.BackendNodeId>): Promise<void> { if (!requestedNodeIds.size || !this.#domModel) { return; } const nodesMap = await this.#domModel.pushNodesByBackendIdsToFrontend(requestedNodeIds); if (!nodesMap) { return; } for (const nodeId of nodesMap.keys()) { this.#backendNodeIdToNode.set(nodeId, nodesMap.get(nodeId) || null); } } backendNodeIdToNode(): Map<Protocol.DOM.BackendNodeId, DOMNode|null> { return this.#backendNodeIdToNode; } setViewportSize(viewportSize: { width: number, height: number, }): void { this.#viewportSize = viewportSize; } viewportSize(): { width: number, height: number, }|undefined { return this.#viewportSize; } }