Files
orca/src/shared/ripgrep-filename-decoder.ts
T
Neil 58bd15fa3f Fix ripgrep result completeness, filename handling, and search errors (#25156)
* Preserve ripgrep search results, filename identity, and failure diagnostics

* Fix adversarial Unicode and Explorer filename findings

* Register search failure localization fallback

* Preserve host filename identity through document and watcher consumers
2026-10-04 01:27:30 -07:00

52 lines
1.4 KiB
TypeScript

export class RipgrepFilenameError extends Error {}
export class RipgrepFilenameEncodingError extends RipgrepFilenameError {
constructor() {
super('File listing contains a filename that is not valid UTF-8')
this.name = 'RipgrepFilenameEncodingError'
}
}
/** Replacement decoding would return a different, potentially existing filename. */
export class RipgrepFilenameDecoder {
private readonly decoder = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true })
constructor(
private readonly onError: (error: Error) => void = throwFilenameError,
private readonly rejectBackslash = false
) {}
decode(chunk: Buffer | string): string | null {
try {
const decoded = this.decoder.decode(typeof chunk === 'string' ? Buffer.from(chunk) : chunk, {
stream: true
})
if (this.rejectBackslash && decoded.includes('\\')) {
throw new RipgrepFilenameError(
'WSL filenames containing a backslash cannot be opened through Windows paths'
)
}
return decoded
} catch (error) {
this.onError(
error instanceof RipgrepFilenameError ? error : new RipgrepFilenameEncodingError()
)
return null
}
}
finish(): boolean {
try {
this.decoder.decode()
return true
} catch {
this.onError(new RipgrepFilenameEncodingError())
return false
}
}
}
function throwFilenameError(error: Error): never {
throw error
}