mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-26 03:03:04 +00:00
Speed up cold diffs and wrapped text measurement (#4676)
* perf(app): optimize wrapped measurements and checkpoint native layout experiment Compute full grapheme geometry only for final wrap fragments. Preserve shaped-text search behavior while bounding additive wrap probes. Keep the Android background layout experiment isolated from the normal diff renderer; native renderer integration and iOS bindings remain unfinished. * perf(server): reduce cold diff generation work Keep active diff reads owned across invalidation and wait for the initial watcher inventory before cold generation. Batch patch and blob reads while preserving per-file size isolation, bounded output, and daemon responsiveness. Avoid constructing fallback tokens when full-file highlighting already covers both sides. * test(server): exercise oversized highlighted diff rejection The single-line fixture now bypasses highlighting under the long-line guard, so it no longer reaches the structured payload limit. Use short dense lines to keep testing oversized rejection and continued socket usability. * fix(server): queue fresh diffs for forced reads A forced request following a repository mutation must not reuse an older active build. Invalidate that result and coalesce waiting callers onto one subsequent build. Give the cache a named object input and completed-value type. * test(server): share deferred diff loader setup * test(server): name completed diff cache setup * refactor(server): use aliases for new diff imports * fix(server): keep shipped diff imports resolvable by Node The TypeScript build preserves path aliases without a runtime resolver. Restore relative imports for shipped code and declarations, and correct the server import guideline that prompted the regression.
This commit is contained in:
@@ -71,6 +71,78 @@ function input(overrides: Partial<BuildDiffDocumentModelInput> = {}): BuildDiffD
|
||||
}
|
||||
|
||||
describe("diff document model", () => {
|
||||
it("preserves shaped wrap breaks when joining makes a longer prefix narrower", () => {
|
||||
const measure = (text: string) => {
|
||||
if (text === "لا") return 30;
|
||||
if (text === "لام") return 15;
|
||||
return text.length * 10;
|
||||
};
|
||||
const fragments = measureFragments({
|
||||
text: "لام",
|
||||
availableWidth: 20,
|
||||
wrapLines: true,
|
||||
lineHeight: 18,
|
||||
measureText: { measure, measureWidth: (graphemes) => measure(graphemes.join("")) },
|
||||
});
|
||||
expect(fragments.map((fragment) => fragment.text)).toEqual(["ل", "ام"]);
|
||||
expect(fragments.map((fragment) => fragment.width)).toEqual([10, 20]);
|
||||
});
|
||||
|
||||
it("does not search wrap boundaries when the remaining text already fits", () => {
|
||||
let widthQueries = 0;
|
||||
const fragments = measureFragments({
|
||||
text: "const answer = value + 1;",
|
||||
availableWidth: 300,
|
||||
wrapLines: true,
|
||||
lineHeight: 18,
|
||||
measureText: {
|
||||
measure: measurer.measure,
|
||||
measureWidth(graphemes) {
|
||||
widthQueries++;
|
||||
return graphemes.length * 10;
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(fragments).toHaveLength(1);
|
||||
expect(fragments[0]?.width).toBe(250);
|
||||
expect(widthQueries).toBe(1);
|
||||
});
|
||||
|
||||
it("builds character geometry only for displayed wrapped fragments", () => {
|
||||
let advancedGraphemes = 0;
|
||||
const measureWidth = (graphemes: readonly string[]) => graphemes.length * 10;
|
||||
const measureText = {
|
||||
// Whole-string widths need not match the chunked advance contract.
|
||||
measure: () => 999,
|
||||
measureWidth,
|
||||
measureAdvances(graphemes: readonly string[]) {
|
||||
advancedGraphemes += graphemes.length;
|
||||
return graphemes.map((_, index) => (index + 1) * 10);
|
||||
},
|
||||
};
|
||||
const text = "const next = (value) => value + 1;".repeat(4);
|
||||
const fragments = measureFragments({
|
||||
text,
|
||||
availableWidth: 80,
|
||||
wrapLines: true,
|
||||
lineHeight: 18,
|
||||
measureText,
|
||||
});
|
||||
|
||||
expect(fragments.map((fragment) => fragment.text).join("")).toBe(text);
|
||||
expect(fragments.every((fragment) => fragment.width <= 80)).toBe(true);
|
||||
expect(fragments).toEqual(
|
||||
measureFragments({
|
||||
text,
|
||||
availableWidth: 80,
|
||||
wrapLines: true,
|
||||
lineHeight: 18,
|
||||
measureText: { measure: measurer.measure },
|
||||
}),
|
||||
);
|
||||
expect(advancedGraphemes).toBe(text.length);
|
||||
});
|
||||
|
||||
it("materializes only visible rows of a large file while preserving full horizontal extent", () => {
|
||||
const source = file("large.ts");
|
||||
source.hunks[0]!.lines = Array.from({ length: 1000 }, (_, index) => ({
|
||||
|
||||
Reference in New Issue
Block a user