fix: add JS fallbacks for wrapTextWithAnsi and visibleWidth when native addon unavailable (#1418) (#1428)

On older Linux distributions (e.g., RHEL 8 with older glibc), the native
Rust addon fails to load. The proxy throws on every function call, but
wrapTextWithAnsi and visibleWidth in pi-tui had no JS fallback — causing
an uncaught crash during TUI rendering.

Fix: Both functions now catch native throws and fall back to JS
implementations (simple word-wrap and ANSI-strip length).

Fixes #1418
This commit is contained in:
Tom Boucher 2026-03-19 12:49:13 -04:00 committed by GitHub
parent 5187841c0b
commit eaf0538150

View file

@ -85,7 +85,12 @@ export function extractAnsiCode(str: string, pos: number): { code: string; lengt
* Delegates to the native Rust implementation.
*/
export function visibleWidth(str: string): number {
return nativeVisibleWidth(str);
try {
return nativeVisibleWidth(str);
} catch {
// JS fallback — strip ANSI codes and return length (#1418)
return str.replace(/\x1b\[[0-9;]*m/g, "").length;
}
}
/**
@ -97,7 +102,28 @@ export function visibleWidth(str: string): number {
* @returns Array of wrapped lines (NOT padded to width)
*/
export function wrapTextWithAnsi(text: string, width: number): string[] {
return nativeWrapTextWithAnsi(text, width);
try {
return nativeWrapTextWithAnsi(text, width);
} catch {
// JS fallback when native addon is unavailable (e.g., glibc mismatch on older Linux) (#1418)
const lines: string[] = [];
for (const line of text.split("\n")) {
if (line.length <= width) {
lines.push(line);
} else {
// Simple word-wrap without ANSI awareness
let remaining = line;
while (remaining.length > width) {
const breakAt = remaining.lastIndexOf(" ", width);
const splitPoint = breakAt > 0 ? breakAt : width;
lines.push(remaining.slice(0, splitPoint));
remaining = remaining.slice(splitPoint).trimStart();
}
if (remaining) lines.push(remaining);
}
}
return lines;
}
}
/**