Add terminal readiness checks to prevent FitAddon errors during initialization
- Added isTerminalReady() method to check if terminal components are initialized - Enhanced fit() method to check terminal readiness before attempting fit operations - Improved initial fit logic with better error handling for viewport initialization - Prevents 'undefined is not an object' errors when viewport.scrollBarWidth is accessed too early - Maintains all existing functionality and backward compatibility Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
@@ -14543,6 +14543,10 @@ class WebTerminal {
|
|||||||
if (this.resizeState.isResizing) {
|
if (this.resizeState.isResizing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!this.isTerminalReady()) {
|
||||||
|
console.debug("Terminal not ready for fit operation, skipping");
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
this.resizeState.isResizing = true;
|
this.resizeState.isResizing = true;
|
||||||
this.resizeState.resizeAttempts++;
|
this.resizeState.resizeAttempts++;
|
||||||
@@ -14570,6 +14574,29 @@ class WebTerminal {
|
|||||||
this.resizeState.resizeAttempts = 0;
|
this.resizeState.resizeAttempts = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
isTerminalReady() {
|
||||||
|
try {
|
||||||
|
if (!this.terminal || !this.terminal._core) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const core = this.terminal._core;
|
||||||
|
if (!core.viewport || !core.viewport.scrollBarWidth) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const renderService = core._renderService;
|
||||||
|
if (!renderService || !renderService.dimensions) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const dims = renderService.dimensions;
|
||||||
|
if (dims.css.cell.width === 0 || dims.css.cell.height === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("Terminal readiness check failed:", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
isValidSize(cols, rows) {
|
isValidSize(cols, rows) {
|
||||||
return cols >= 10 && cols <= 500 && rows >= 5 && rows <= 200;
|
return cols >= 10 && cols <= 500 && rows >= 5 && rows <= 200;
|
||||||
}
|
}
|
||||||
@@ -14615,12 +14642,13 @@ class WebTerminal {
|
|||||||
this.send(["resize", { width: fallback.cols, height: fallback.rows }]);
|
this.send(["resize", { width: fallback.cols, height: fallback.rows }]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.isValidSize(dims.cols, dims.rows)) {
|
if (dims && this.isValidSize(dims.cols, dims.rows) && this.isTerminalReady()) {
|
||||||
this.terminal.resize(dims.cols, dims.rows);
|
this.terminal.resize(dims.cols, dims.rows);
|
||||||
this.resizeState.lastValidSize = dims;
|
this.resizeState.lastValidSize = dims;
|
||||||
this.send(["resize", { width: dims.cols, height: dims.rows }]);
|
this.send(["resize", { width: dims.cols, height: dims.rows }]);
|
||||||
} else {
|
} else {
|
||||||
console.warn(`Initial fit produced invalid dimensions: ${dims.cols}x${dims.rows}, using fallback`);
|
const reason = !dims ? "proposeDimensions failed" : !this.isValidSize(dims.cols, dims.rows) ? `invalid dimensions: ${dims.cols}x${dims.rows}` : "terminal not ready";
|
||||||
|
console.warn(`Initial fit ${reason}, using fallback`);
|
||||||
this.terminal.resize(fallback.cols, fallback.rows);
|
this.terminal.resize(fallback.cols, fallback.rows);
|
||||||
this.resizeState.lastValidSize = fallback;
|
this.resizeState.lastValidSize = fallback;
|
||||||
this.send(["resize", { width: fallback.cols, height: fallback.rows }]);
|
this.send(["resize", { width: fallback.cols, height: fallback.rows }]);
|
||||||
|
|||||||
@@ -198,6 +198,12 @@ class WebTerminal {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if terminal is ready before attempting fit
|
||||||
|
if (!this.isTerminalReady()) {
|
||||||
|
console.debug("Terminal not ready for fit operation, skipping");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.resizeState.isResizing = true;
|
this.resizeState.isResizing = true;
|
||||||
this.resizeState.resizeAttempts++;
|
this.resizeState.resizeAttempts++;
|
||||||
@@ -235,6 +241,38 @@ class WebTerminal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Check if terminal is ready for resize operations */
|
||||||
|
private isTerminalReady(): boolean {
|
||||||
|
try {
|
||||||
|
// Check if terminal and its core components are initialized
|
||||||
|
if (!this.terminal || !this.terminal._core) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if viewport is available (FitAddon requirement)
|
||||||
|
const core = this.terminal._core;
|
||||||
|
if (!core.viewport || !core.viewport.scrollBarWidth) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if render service has valid dimensions
|
||||||
|
const renderService = core._renderService;
|
||||||
|
if (!renderService || !renderService.dimensions) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dims = renderService.dimensions;
|
||||||
|
if (dims.css.cell.width === 0 || dims.css.cell.height === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("Terminal readiness check failed:", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Validate terminal dimensions */
|
/** Validate terminal dimensions */
|
||||||
private isValidSize(cols: number, rows: number): boolean {
|
private isValidSize(cols: number, rows: number): boolean {
|
||||||
return cols >= 10 && cols <= 500 && rows >= 5 && rows <= 200;
|
return cols >= 10 && cols <= 500 && rows >= 5 && rows <= 200;
|
||||||
@@ -298,13 +336,16 @@ class WebTerminal {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate dimensions before applying
|
// Validate dimensions and terminal readiness before applying
|
||||||
if (this.isValidSize(dims.cols, dims.rows)) {
|
if (dims && this.isValidSize(dims.cols, dims.rows) && this.isTerminalReady()) {
|
||||||
this.terminal.resize(dims.cols, dims.rows);
|
this.terminal.resize(dims.cols, dims.rows);
|
||||||
this.resizeState.lastValidSize = dims;
|
this.resizeState.lastValidSize = dims;
|
||||||
this.send(["resize", { width: dims.cols, height: dims.rows }]);
|
this.send(["resize", { width: dims.cols, height: dims.rows }]);
|
||||||
} else {
|
} else {
|
||||||
console.warn(`Initial fit produced invalid dimensions: ${dims.cols}x${dims.rows}, using fallback`);
|
const reason = !dims ? "proposeDimensions failed" :
|
||||||
|
!this.isValidSize(dims.cols, dims.rows) ? `invalid dimensions: ${dims.cols}x${dims.rows}` :
|
||||||
|
"terminal not ready";
|
||||||
|
console.warn(`Initial fit ${reason}, using fallback`);
|
||||||
this.terminal.resize(fallback.cols, fallback.rows);
|
this.terminal.resize(fallback.cols, fallback.rows);
|
||||||
this.resizeState.lastValidSize = fallback;
|
this.resizeState.lastValidSize = fallback;
|
||||||
this.send(["resize", { width: fallback.cols, height: fallback.rows }]);
|
this.send(["resize", { width: fallback.cols, height: fallback.rows }]);
|
||||||
|
|||||||
Reference in New Issue
Block a user