[DevTools] Recursively compute the bounding rect of the roots (#34629)

It's possible for the children to overflow the bounding rect of the root
in general when they overflow in the DOM. However even when it doesn't
overflow in the DOM, the bounding rect of the root can shrink while the
content is suspended. In fact, it's very likely.

Originally I thought we didn't need to consider this recursively because
document scrolling takes absolute positioned content into account but
because we're using nested overflow scrolling, we have to manually
compute this.
This commit is contained in:
Sebastian Markbåge 2025-09-28 10:15:31 -04:00 committed by GitHub
parent e08f53b182
commit f78b2343cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -184,6 +184,42 @@ function getBoundingBox(rects: $ReadOnlyArray<Rect> | null): Rect {
};
}
function computeBoundingRectRecursively(
store: Store,
node: SuspenseNode,
bounds: {
minX: number,
minY: number,
maxX: number,
maxY: number,
},
): void {
const rects = node.rects;
if (rects !== null) {
for (let j = 0; j < rects.length; j++) {
const rect = rects[j];
if (rect.x < bounds.minX) {
bounds.minX = rect.x;
}
if (rect.x + rect.width > bounds.maxX) {
bounds.maxX = rect.x + rect.width;
}
if (rect.y < bounds.minY) {
bounds.minY = rect.y;
}
if (rect.y + rect.height > bounds.maxY) {
bounds.maxY = rect.y + rect.height;
}
}
}
for (let i = 0; i < node.children.length; i++) {
const child = store.getSuspenseByID(node.children[i]);
if (child !== null) {
computeBoundingRectRecursively(store, child, bounds);
}
}
}
function getDocumentBoundingRect(
store: Store,
roots: $ReadOnlyArray<SuspenseNode['id']>,
@ -192,10 +228,12 @@ function getDocumentBoundingRect(
return {x: 0, y: 0, width: 0, height: 0};
}
let minX = Number.POSITIVE_INFINITY;
let minY = Number.POSITIVE_INFINITY;
let maxX = Number.NEGATIVE_INFINITY;
let maxY = Number.NEGATIVE_INFINITY;
const bounds = {
minX: Number.POSITIVE_INFINITY,
minY: Number.POSITIVE_INFINITY,
maxX: Number.NEGATIVE_INFINITY,
maxY: Number.NEGATIVE_INFINITY,
};
for (let i = 0; i < roots.length; i++) {
const rootID = roots[i];
@ -203,30 +241,19 @@ function getDocumentBoundingRect(
if (root === null) {
continue;
}
const rects = root.rects;
if (rects === null) {
continue;
}
for (let j = 0; j < rects.length; j++) {
const rect = rects[j];
minX = Math.min(minX, rect.x);
minY = Math.min(minY, rect.y);
maxX = Math.max(maxX, rect.x + rect.width);
maxY = Math.max(maxY, rect.y + rect.height);
}
computeBoundingRectRecursively(store, root, bounds);
}
if (minX === Number.POSITIVE_INFINITY) {
if (bounds.minX === Number.POSITIVE_INFINITY) {
// No rects found, return empty rect
return {x: 0, y: 0, width: 0, height: 0};
}
return {
x: minX,
y: minY,
width: maxX - minX,
height: maxY - minY,
x: bounds.minX,
y: bounds.minY,
width: bounds.maxX - bounds.minX,
height: bounds.maxY - bounds.minY,
};
}