mirror of
https://github.com/coder/coder.git
synced 2026-09-22 05:05:20 +08:00
fix(site): upgrade @pierre/diffs to 1.1.0-beta.19 (#22895)
Fixes a race condition in `DiffHunksRenderer` where a stale async highlight callback overwrites the render cache with an old diff, causing a hunk count mismatch: ``` DiffHunksRenderer.renderHunks: lineHunk doesn't exist ``` ## Root cause The `DiffHunksRenderer` in `@pierre/diffs@1.0.11` caches highlighted AST results keyed by diff object reference. When the shiki highlighter isn't fully loaded, it fires `asyncHighlight(diff)` which captures the current diff in a closure. If the diff changes before that promise resolves, `onHighlightSuccess` unconditionally overwrites `renderCache` with the stale diff/result pair. The subsequent `rerender()` then iterates the new diff's hunks against the old result's `code.hunks` array, crashing at an out-of-bounds index. ## Fix Upgrades `@pierre/diffs` from `1.0.11` to `1.1.0-beta.19`, which completely refactors the rendering pipeline: - Replaces the per-hunk `code.hunks[hunkIndex]` lookup with flat `additionLines`/`deletionLines` arrays indexed directly by line index - Uses a new `iterateOverDiff` callback pattern instead of the `renderHunks` method - The `lineHunk doesn't exist` error is gone from the codebase entirely The only code change on our side is adapting `extractDiffContent()` in `FilesChangedPanel.tsx` to the new `ChangeContent`/`ContextContent` types where `deletions`, `additions`, and `lines` are now counts with index pointers into top-level `FileDiffMetadata.deletionLines`/`additionLines` arrays.
This commit is contained in:
+1
-1
@@ -53,7 +53,7 @@
|
||||
"@mui/material": "5.18.0",
|
||||
"@mui/system": "5.18.0",
|
||||
"@mui/x-tree-view": "7.29.10",
|
||||
"@pierre/diffs": "1.0.11",
|
||||
"@pierre/diffs": "1.1.0-beta.19",
|
||||
"@radix-ui/react-avatar": "1.1.11",
|
||||
"@radix-ui/react-checkbox": "1.3.3",
|
||||
"@radix-ui/react-collapsible": "1.1.12",
|
||||
|
||||
Generated
+12
-7
@@ -74,8 +74,8 @@ importers:
|
||||
specifier: 7.29.10
|
||||
version: 7.29.10(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2))(@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react-dom@19.2.2(react@19.2.2))(react@19.2.2))(@mui/system@5.18.0(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react@19.2.2))(@types/react@19.2.7)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)
|
||||
'@pierre/diffs':
|
||||
specifier: 1.0.11
|
||||
version: 1.0.11(react-dom@19.2.2(react@19.2.2))(react@19.2.2)
|
||||
specifier: 1.1.0-beta.19
|
||||
version: 1.1.0-beta.19(react-dom@19.2.2(react@19.2.2))(react@19.2.2)
|
||||
'@radix-ui/react-avatar':
|
||||
specifier: 1.1.11
|
||||
version: 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)
|
||||
@@ -1596,12 +1596,16 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@pierre/diffs@1.0.11':
|
||||
resolution: {integrity: sha512-j6zIEoyImQy1HfcJqbrDwP0O5I7V2VNXAaw53FqQ+SykRfaNwABeZHs9uibXO4supaXPmTx6LEH9Lffr03e1Tw==, tarball: https://registry.npmjs.org/@pierre/diffs/-/diffs-1.0.11.tgz}
|
||||
'@pierre/diffs@1.1.0-beta.19':
|
||||
resolution: {integrity: sha512-XxGPKkVW+1t2KJQfgjmSnS+93nI9+ACJl1XjhF3Lo4BdQJOxV3pHeyix31ySn/m/1llq6O/7bXucE0OYCK6Kog==, tarball: https://registry.npmjs.org/@pierre/diffs/-/diffs-1.1.0-beta.19.tgz}
|
||||
peerDependencies:
|
||||
react: ^18.3.1 || ^19.0.0
|
||||
react-dom: ^18.3.1 || ^19.0.0
|
||||
|
||||
'@pierre/theme@0.0.22':
|
||||
resolution: {integrity: sha512-ePUIdQRNGjrveELTU7fY89Xa7YGHHEy5Po5jQy/18lm32eRn96+tnYJEtFooGdffrx55KBUtOXfvVy/7LDFFhA==, tarball: https://registry.npmjs.org/@pierre/theme/-/theme-0.0.22.tgz}
|
||||
engines: {vscode: ^1.0.0}
|
||||
|
||||
'@pkgjs/parseargs@0.11.0':
|
||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==, tarball: https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz}
|
||||
engines: {node: '>=14'}
|
||||
@@ -7941,10 +7945,9 @@ snapshots:
|
||||
'@oxc-resolver/binding-win32-x64-msvc@11.14.0':
|
||||
optional: true
|
||||
|
||||
'@pierre/diffs@1.0.11(react-dom@19.2.2(react@19.2.2))(react@19.2.2)':
|
||||
'@pierre/diffs@1.1.0-beta.19(react-dom@19.2.2(react@19.2.2))(react@19.2.2)':
|
||||
dependencies:
|
||||
'@shikijs/core': 3.22.0
|
||||
'@shikijs/engine-javascript': 3.22.0
|
||||
'@pierre/theme': 0.0.22
|
||||
'@shikijs/transformers': 3.22.0
|
||||
diff: 8.0.3
|
||||
hast-util-to-html: 9.0.5
|
||||
@@ -7953,6 +7956,8 @@ snapshots:
|
||||
react-dom: 19.2.2(react@19.2.2)
|
||||
shiki: 3.22.0
|
||||
|
||||
'@pierre/theme@0.0.22': {}
|
||||
|
||||
'@pkgjs/parseargs@0.11.0':
|
||||
optional: true
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@ function extractDiffContent(
|
||||
const file = parsedFiles.find((f) => f.name === fileName);
|
||||
if (!file) return "";
|
||||
|
||||
const lines = side === "additions" ? file.additionLines : file.deletionLines;
|
||||
const collected: string[] = [];
|
||||
for (const hunk of file.hunks) {
|
||||
let addLine = hunk.additionStart;
|
||||
@@ -96,10 +97,14 @@ function extractDiffContent(
|
||||
|
||||
for (const block of hunk.hunkContent) {
|
||||
if (block.type === "context") {
|
||||
for (const line of block.lines) {
|
||||
for (let i = 0; i < block.lines; i++) {
|
||||
const ln = side === "additions" ? addLine : delLine;
|
||||
if (ln >= startLine && ln <= endLine) {
|
||||
collected.push(line);
|
||||
const idx =
|
||||
side === "additions"
|
||||
? block.additionLineIndex + i
|
||||
: block.deletionLineIndex + i;
|
||||
if (lines[idx] != null) collected.push(lines[idx]);
|
||||
}
|
||||
addLine++;
|
||||
delLine++;
|
||||
@@ -107,23 +112,25 @@ function extractDiffContent(
|
||||
} else {
|
||||
// ChangeContent block.
|
||||
if (side === "deletions") {
|
||||
for (const line of block.deletions) {
|
||||
for (let i = 0; i < block.deletions; i++) {
|
||||
if (delLine >= startLine && delLine <= endLine) {
|
||||
collected.push(line);
|
||||
const line = lines[block.deletionLineIndex + i];
|
||||
if (line != null) collected.push(line);
|
||||
}
|
||||
delLine++;
|
||||
}
|
||||
// Addition lines in a change block still advance
|
||||
// the addition counter.
|
||||
addLine += block.additions.length;
|
||||
addLine += block.additions;
|
||||
} else {
|
||||
// side === "additions"
|
||||
// Deletion lines in a change block still advance
|
||||
// the deletion counter.
|
||||
delLine += block.deletions.length;
|
||||
for (const line of block.additions) {
|
||||
delLine += block.deletions;
|
||||
for (let i = 0; i < block.additions; i++) {
|
||||
if (addLine >= startLine && addLine <= endLine) {
|
||||
collected.push(line);
|
||||
const line = lines[block.additionLineIndex + i];
|
||||
if (line != null) collected.push(line);
|
||||
}
|
||||
addLine++;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user