fix(natives): reject ill-formed UTF-16 in native diff and fall back to jsdiff

This commit is contained in:
Wolfgang Schoenberger
2026-07-22 04:32:46 -07:00
parent 55bba890ab
commit 8f17a0300d
4 changed files with 100 additions and 18 deletions
+16 -1
View File
@@ -4,13 +4,28 @@
* Provides diff string generation and the replace-mode edit logic
* used when not in patch mode.
*/
import { diffLines, structuredPatchHunks } from "@oh-my-pi/pi-natives";
import { diffLines as nativeDiffLines, structuredPatchHunks as nativeStructuredPatchHunks } from "@oh-my-pi/pi-natives";
import { diffLines as jsDiffLines, structuredPatch as jsStructuredPatch } from "diff";
import { resolveToCwd } from "../tools/path-utils";
import { type BlockContextSource, findBlockContextLines } from "../utils/block-context";
import { DEFAULT_FUZZY_THRESHOLD, EditMatchError, findMatch } from "./modes/replace";
import { adjustIndentation, normalizeToLF, stripBom } from "./normalize";
import { readEditFileText } from "./read-file";
/** Native line diff when both inputs are well-formed UTF-16; the native binding rejects unpaired surrogates, so ill-formed inputs fall back to jsdiff. */
function diffLines(oldContent: string, newContent: string) {
return oldContent.isWellFormed() && newContent.isWellFormed()
? nativeDiffLines(oldContent, newContent)
: jsDiffLines(oldContent, newContent);
}
/** Native structured-patch hunks with the same ill-formed-UTF-16 fallback as {@link diffLines}. */
function structuredPatchHunks(oldContent: string, newContent: string, context: number) {
return oldContent.isWellFormed() && newContent.isWellFormed()
? nativeStructuredPatchHunks(oldContent, newContent, context)
: jsStructuredPatch("", "", oldContent, newContent, "", "", { context }).hunks;
}
export interface DiffResult {
diff: string;
firstChangedLine: number | undefined;