Skip to content

Conversation

@amadeus
Copy link
Member

@amadeus amadeus commented Dec 19, 2025

This branch started off with me building out a few virtualization test cases, and as I've learned more about the requirements, I realized there are various foundational pieces that needed to be addressed before I can ship a virtualization feature.

This PR technically includes a few Virtualization components, however are not ready for prime time and should not be used at this time.

The goal with this PR however is to get it merged into main in a state where I can potentially do a release with these foundational changes to make sure they are thoroughly tested by people as I continue working on virtualization.

The Changes, in no particular order

Revamped FileDiffMetadata

The original data structure was mostly built as a convenience wrapper for early diff rendering, however it was not very efficient or useful and required a lot of additional data to be derived as well as doubled up a lot of existing data (i.e. we would include multiple copies of the contents, both as a top level array of strings and in the hunk structure itself).

The new type looks something like this:

export interface FileDiffMetadata {
  name: string;
  prevName?: string;
  languageOverride?: SupportedLanguages;
  mode?: string;
  prevMode?: string;
  type: ChangeTypes;

  hunks: Hunk[];
  splitLineCount: number;
  unifiedLineCount: number;

  isPartial: boolean;
  deletionLines: string[];
  additionLines: string[];
  cacheKey?: string;
}

export interface Hunk {
  collapsedBefore: number;

  additionStart: number;
  additionCount: number;
  additionLines: number;
  additionLineIndex: number;

  deletionStart: number;
  deletionCount: number;
  deletionLines: number;
  deletionLineIndex: number;

  hunkContent: (ContextContent | ChangeContent)[];
  hunkContext: string | undefined;
  hunkSpecs: string | undefined;

  splitLineStart: number;
  splitLineCount: number;

  unifiedLineStart: number;
  unifiedLineCount: number;

  noEOFCRDeletions: boolean;
  noEOFCRAdditions: boolean;
}

export interface ContextContent {
  type: 'context';
  lines: number;
  additionLineIndex: number;
  deletionLineIndex: number;
}

export interface ChangeContent {
  type: 'change';
  deletions: number;
  deletionLineIndex: number;
  additions: number;
  additionLineIndex: number;
}

Content diff content now lives at the top level of the data structure and the nested Hunk/Change/Content structures are simply derived data to work with these top level arrays of strings. This is to enable more efficient calculations, not needlessly duplicate data and require significantly fewer variables when iterating through the data structure.

New Shared iterateOverDiff Helper

Whether it's highlighiting, rendering or eventually computing virtualization data, there are many similar but different use cases that require us to iterate through our FileDiffMetadata data structure. As i was building out various virtualization prototypes, it was quite common for me to deal with subtle bugs in how these different usecases would calculate things. Not to mention it would continue to be a maintenance nightmare as we move forward with adding new features, etc.

Essentially iterateOverDiff takes a callback, an instance of FileDiffMetadata, and potentially some other helper props and will iterate over each line (or within windowed situations). It's built to keep overall iterations to a minimum, allowing to skip lines that shouldn't be rendered/computed/highlighted. In this PR it's been fully implemented into DiffHunksRenderer and our renderDiffWithHighlighter method.

Misc Virtualization/DOM Performance Optimizations

Originally these components were built to have a very simple snapshot style rendering. if we needed to update or re-render the diff, we'd just full scale re-render everything. This is something that won't work well with virtualization as we'll be doing many DOM operations while scrolling. This PR does not include all the performance optimizations I need to make, but it does include a decent handful:

  • Annotations are now smarter about re-rendering
  • position: sticky can have a real performance impact and so I've taken a pass only apply sticky in cases where we have overflow: scroll
  • I've made a few CSS tweaks related to virtualization, to ensure things stay a bit more stable under various windowed scenarios
  • Various managers should be and interactivity classes should be smarter about only doing work when they need to
  • WorkerPoolManager should be a bit smarter about handling a larger task queue and if components get mounted and then unmounted while in a highlight queue

Virtualization Pieces

Given the size of this PR, it was going to be too difficult to properly remove these unfinished virtualization components. So I am including them in this merge. They are not fully usable in their current state, but I will be continuing to work on them after merge.

When I do a release with these changes, I will probably make a specialized beta branch that removes the exports for them and does the release to ensure that people don't try using them. There's also a whole bunch of docs code that I had built out for testing monster diffs that I've removed, but will re-vert back in a follow up branch as I continue development.

Misc

  • Removed the fast-deep-equal dependency
    • It didn't provide a whole lot, plus I found it more helpful to just create special object comparators for things.
  • The lang prop on FileDiffMetadata and FileContents was confusing people as they often assumed it was required. I've renamed it to languageOverride to be explicit about it's intent. I've also tweaked the docs that mention it

@amadeus amadeus force-pushed the amadeus/virtualization-v1 branch 3 times, most recently from 6cca062 to 9a479dd Compare December 20, 2025 02:30
@vercel
Copy link

vercel bot commented Dec 20, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
pierrejs-diff-demo Ready Ready Preview Jan 21, 2026 1:17am
pierrejs-docs Ready Ready Preview Jan 21, 2026 1:17am
pierrejs-solid-diff-demo Ready Ready Preview Jan 21, 2026 1:17am

Request Review

@amadeus amadeus force-pushed the amadeus/virtualization-v1 branch from 945184c to c878b0b Compare December 22, 2025 23:56
@amadeus amadeus force-pushed the amadeus/virtualization-v1 branch from c878b0b to e53f541 Compare December 23, 2025 02:44
@amadeus amadeus force-pushed the amadeus/virtualization-v1 branch from 893431f to d125f9a Compare December 23, 2025 03:20
@amadeus amadeus force-pushed the amadeus/virtualization-v1 branch from d125f9a to b786379 Compare December 23, 2025 04:12
@amadeus amadeus force-pushed the amadeus/virtualization-v1 branch from e7ed2c2 to b537069 Compare December 25, 2025 03:31
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR lays the groundational work for virtualization support in the diffs package. The main changes include a revamped FileDiffMetadata structure that stores content as top-level arrays rather than nested within hunks, a new shared iterateOverDiff helper for consistent iteration patterns, and various DOM/performance optimizations. The PR also renames the lang prop to languageOverride for clarity and improves WorkerPoolManager's task management capabilities.

Changes:

  • Revamped FileDiffMetadata structure to store content at the top level with hunks containing only derived metadata
  • Added new iterateOverDiff utility for consistent iteration patterns across rendering, highlighting, and virtualization
  • Renamed lang prop to languageOverride across all interfaces for better clarity
  • Enhanced WorkerPoolManager with improved task cleanup, state broadcasting, and error handling
  • Added various performance optimizations and utility functions for virtualization support

Reviewed changes

Copilot reviewed 62 out of 67 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/diffs/test/testUtils.ts Updated to work with numeric line counts instead of arrays; added virtualization buffer helpers
packages/diffs/test/parsePatchFiles.test.ts Changed to compute line counts from hunks instead of using file-level counts
packages/diffs/test/parseDiffFromFile.test.ts Updated property names from oldLines/newLines to deletionLines/additionLines
packages/diffs/test/iterateOverDiff.test.ts New test file for the shared iteration helper
packages/diffs/test/snapshots/patchFileRender.test.ts.snap Major snapshot update reflecting data structure changes
packages/diffs/test/snapshots/parseDiffFromFile.test.ts.snap Complete restructuring to new metadata format
packages/diffs/test/DiffHunksRender.test.ts Added assertions to verify rendered line counts match metadata
packages/diffs/src/worker/types.ts Added __id to renderer instances and expanded WorkerStats
packages/diffs/src/worker/WorkerPoolManager.ts Enhanced task management, cleanup, and state broadcasting
packages/diffs/src/utils/setWrapperNodeProps.ts Refactored function signature to take pre as first argument
packages/diffs/src/utils/setLanguageOverride.ts Renamed parameter from lang to languageOverride
packages/diffs/src/utils/renderFileWithHighlighter.ts Updated to use languageOverride property
packages/diffs/src/utils/processLine.ts Fixed line indexing to be 0-based
packages/diffs/src/utils/parseDiffFromFile.ts Refactored to use processFile function
packages/diffs/src/utils/isDefaultRenderRange.ts New utility to check for default render range
packages/diffs/src/utils/hast_utils.ts Added createBufferElement for virtualization
packages/diffs/src/utils/getTotalLineCountFromHunks.ts Modernized to use .at(-1)
packages/diffs/src/utils/getOrCreateCodeNode.ts Renamed and enhanced to reuse existing code elements

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

name: 'config',
contents: '{ "key": "value" }',
lang: 'json',
languageOverride: 'json',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would personally not change this

Copy link
Member Author

@amadeus amadeus Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my hot, wont-die-on-the-hill-about-it take:

  • it's an easy thing for people to fix
  • it should hopefully help train people that they don't really need this prop in practice
  • figured i would do it while changing a bunch of types already.

That said, if more of you guys think it's better to stay consistent, i can revert this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SlexAxton ur turn to weigh in 👯

* Make Simple/Advanced virtualizer global window type overrides be a bit
  more consistent
* Remove the silly names for more professional sounding ones
Copy link
Contributor

@fat fat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perfect code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants