fix: user workflow deadlock (#677)

This commit is contained in:
Carlos Florêncio
2026-04-23 09:54:06 +01:00
committed by GitHub
parent 86b3099631
commit 6ffb157d7e
15 changed files with 607 additions and 115 deletions
@@ -71,6 +71,39 @@ function createKeyEventHandler(options: TerminalKeyHandlerOptions) {
};
}
/**
* Defer WebGL addon loading to the next animation frame so the initial
* synchronous work (Terminal + FitAddon + open) stays within the browser's
* frame budget.
*
* Skips WebGL on Firefox: its canvas fingerprinting protection silently
* poisons readback data, corrupting the glyph texture atlas.
*/
function deferWebGLAddon(refs: Pick<TerminalInitOptions, "xtermRef" | "webglAddonRef">) {
const isFirefox = typeof navigator !== "undefined" && /firefox/i.test(navigator.userAgent);
if (isFirefox) {
log("Skipping WebGL addon on Firefox (canvas fingerprinting protection)");
return;
}
requestAnimationFrame(() => {
const term = refs.xtermRef.current;
if (!term || refs.webglAddonRef.current) return;
try {
const webglAddon = new WebglAddon();
webglAddon.onContextLoss(() => {
log("WebGL context lost");
webglAddon.dispose();
refs.webglAddonRef.current = null;
});
term.loadAddon(webglAddon);
refs.webglAddonRef.current = webglAddon;
log("WebGL addon loaded");
} catch (e) {
log("WebGL failed, using canvas:", e);
}
});
}
function initTerminalInstance(
termContainer: HTMLDivElement,
refs: Pick<
@@ -121,26 +154,7 @@ function initTerminalInstance(
}
refs.xtermRef.current = terminal;
refs.fitAddonRef.current = fitAddon;
// Defer WebGL addon loading to the next animation frame so the initial
// synchronous work (Terminal + FitAddon + open) stays within the browser's
// frame budget and avoids "Violation: 'setTimeout' handler took Xms" warnings.
requestAnimationFrame(() => {
const term = refs.xtermRef.current;
if (!term || refs.webglAddonRef.current) return;
try {
const webglAddon = new WebglAddon();
webglAddon.onContextLoss(() => {
log("WebGL context lost");
webglAddon.dispose();
refs.webglAddonRef.current = null;
});
term.loadAddon(webglAddon);
refs.webglAddonRef.current = webglAddon;
log("WebGL addon loaded");
} catch (e) {
log("WebGL failed, using canvas:", e);
}
});
deferWebGLAddon(refs);
exposeBufferReader(termContainer, terminal);
const handleResize = () => {
const rect = termContainer.getBoundingClientRect();