fix(vom): add new texts and fix bugs

This commit is contained in:
Ljy-0827
2026-09-08 15:16:10 +08:00
parent f528f95bd6
commit 7469d3506a
7 changed files with 258 additions and 64 deletions
@@ -0,0 +1,35 @@
import { describe, expect, it } from "vitest";
import {
compareVisualSurfacePriority,
selectHighestPriorityVisualSurfaces,
} from "../visual-surface-priority";
function surface(backendNodeId: number, area: number, label?: string) {
return {
backendNodeId,
frameId: "main",
visibleRect: { x: backendNodeId, y: 0, w: area, h: 1 },
...(label ? { label } : {}),
};
}
describe("visual surface priority selection", () => {
it("matches a full priority sort when selecting a bounded prefix", () => {
const surfaces = Array.from({ length: 600 }, (_, index) => surface(index, index + 1));
surfaces[599] = surface(599, 1, "Important status");
const selected = selectHighestPriorityVisualSurfaces(surfaces, 512);
const expected = [...surfaces].sort(compareVisualSurfacePriority).slice(0, 512);
expect(selected).toEqual(expected);
expect(selected[0]?.backendNodeId).toBe(599);
});
it("normalizes empty, fractional, and unbounded limits", () => {
const surfaces = [surface(1, 1), surface(2, 2), surface(3, 3)];
expect(selectHighestPriorityVisualSurfaces(surfaces, 0)).toEqual([]);
expect(selectHighestPriorityVisualSurfaces(surfaces, 1.9)).toEqual([surface(3, 3)]);
expect(selectHighestPriorityVisualSurfaces(surfaces, Number.POSITIVE_INFINITY)).toHaveLength(3);
});
});
+1
View File
@@ -22,5 +22,6 @@ export type {
} from "./types";
export {
compareVisualSurfacePriority,
selectHighestPriorityVisualSurfaces,
type VisualSurfacePriorityInput,
} from "./visual-surface-priority";
+11 -10
View File
@@ -11,7 +11,7 @@ import type {
VomScene,
VomVisualSurface,
} from "./types";
import { compareVisualSurfacePriority } from "./visual-surface-priority";
import { selectHighestPriorityVisualSurfaces } from "./visual-surface-priority";
const SKIP_ROLES = new Set(["generic", "none", "presentation", "inlinetextbox"]);
@@ -822,17 +822,18 @@ function selectVisualSurfaces(
surfaces: readonly VomVisualSurface[],
nodesById: ReadonlyMap<number, VomNode>,
): { selected: VomVisualSurface[]; eligibleCount: number } {
const selected: VomVisualSurface[] = [];
let eligibleCount = 0;
for (const surface of surfaces) {
if (surface.parentId !== null && !nodesById.has(surface.parentId)) continue;
eligibleCount += 1;
selected.push(surface);
function* eligibleSurfaces(): Generator<VomVisualSurface> {
for (const surface of surfaces) {
if (surface.parentId !== null && !nodesById.has(surface.parentId)) continue;
eligibleCount += 1;
yield surface;
}
}
selected.sort(compareVisualSurfacePriority);
return { selected, eligibleCount };
return {
selected: selectHighestPriorityVisualSurfaces(eligibleSurfaces(), MAX_VISUAL_SURFACE_REFS),
eligibleCount,
};
}
function emitVisualAppendix(state: RenderState): void {
@@ -27,3 +27,54 @@ export function compareVisualSurfacePriority(
a.backendNodeId - b.backendNodeId
);
}
function siftWorstUp<T extends VisualSurfacePriorityInput>(heap: T[], start: number): void {
let index = start;
while (index > 0) {
const parent = Math.floor((index - 1) / 2);
if (compareVisualSurfacePriority(heap[index], heap[parent]) <= 0) break;
[heap[index], heap[parent]] = [heap[parent], heap[index]];
index = parent;
}
}
function siftWorstDown<T extends VisualSurfacePriorityInput>(heap: T[], start: number): void {
let index = start;
while (true) {
const left = index * 2 + 1;
if (left >= heap.length) return;
const right = left + 1;
let worst = left;
if (right < heap.length && compareVisualSurfacePriority(heap[right], heap[left]) > 0) {
worst = right;
}
if (compareVisualSurfacePriority(heap[worst], heap[index]) <= 0) return;
[heap[index], heap[worst]] = [heap[worst], heap[index]];
index = worst;
}
}
/** Selects the best `limit` surfaces and returns them in priority order. */
export function selectHighestPriorityVisualSurfaces<T extends VisualSurfacePriorityInput>(
surfaces: Iterable<T>,
limit: number,
): T[] {
if (!Number.isFinite(limit)) return [...surfaces].sort(compareVisualSurfacePriority);
const normalizedLimit = Math.max(0, Math.floor(limit));
if (normalizedLimit === 0) return [];
if (Array.isArray(surfaces) && surfaces.length <= normalizedLimit) {
return [...surfaces].sort(compareVisualSurfacePriority);
}
const heap: T[] = [];
for (const surface of surfaces) {
if (heap.length < normalizedLimit) {
heap.push(surface);
siftWorstUp(heap, heap.length - 1);
} else if (compareVisualSurfacePriority(surface, heap[0]) < 0) {
heap[0] = surface;
siftWorstDown(heap, 0);
}
}
return heap.sort(compareVisualSurfacePriority);
}