Enhance terminal readiness checks with comprehensive FitAddon validation
- Added more robust terminal readiness checking - Explicitly check for viewport.scrollBarWidth being defined - Added FitAddon function type checking before calling fit() - Improved error handling for FitAddon initialization issues - Prevents 'undefined is not an object' errors during terminal setup - Maintains all existing functionality and test compatibility Bump version to 0.3.29 Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "textual-webterm"
|
name = "textual-webterm"
|
||||||
version = "0.3.28"
|
version = "0.3.29"
|
||||||
description = "Serve terminal sessions over the web"
|
description = "Serve terminal sessions over the web"
|
||||||
authors = ["Will McGugan <will@textualize.io>"]
|
authors = ["Will McGugan <will@textualize.io>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|||||||
@@ -14551,8 +14551,12 @@ class WebTerminal {
|
|||||||
this.resizeState.isResizing = true;
|
this.resizeState.isResizing = true;
|
||||||
this.resizeState.resizeAttempts++;
|
this.resizeState.resizeAttempts++;
|
||||||
this.lastResizeTime = now;
|
this.lastResizeTime = now;
|
||||||
|
if (this.fitAddon && typeof this.fitAddon.fit === "function") {
|
||||||
this.fitAddon.fit();
|
this.fitAddon.fit();
|
||||||
this.resizeState.resizeAttempts = 0;
|
this.resizeState.resizeAttempts = 0;
|
||||||
|
} else {
|
||||||
|
throw new Error("FitAddon not properly initialized");
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("Fit failed:", e);
|
console.warn("Fit failed:", e);
|
||||||
this.handleResizeFailure();
|
this.handleResizeFailure();
|
||||||
@@ -14576,21 +14580,40 @@ class WebTerminal {
|
|||||||
}
|
}
|
||||||
isTerminalReady() {
|
isTerminalReady() {
|
||||||
try {
|
try {
|
||||||
if (!this.terminal || !this.terminal._core) {
|
if (!this.terminal) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!this.terminal._core) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const core = this.terminal._core;
|
const core = this.terminal._core;
|
||||||
if (!core.viewport || !core.viewport.scrollBarWidth) {
|
if (!core.viewport) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (core.viewport.scrollBarWidth === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!core._renderService) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const renderService = core._renderService;
|
const renderService = core._renderService;
|
||||||
if (!renderService || !renderService.dimensions) {
|
if (!renderService.dimensions) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const dims = renderService.dimensions;
|
const dims = renderService.dimensions;
|
||||||
if (dims.css.cell.width === 0 || dims.css.cell.height === 0) {
|
if (dims.css.cell.width === 0 || dims.css.cell.height === 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (this.fitAddon) {
|
||||||
|
try {
|
||||||
|
const fitTerminal = this.fitAddon._terminal;
|
||||||
|
if (!fitTerminal || fitTerminal !== this.terminal) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("Terminal readiness check failed:", e);
|
console.warn("Terminal readiness check failed:", e);
|
||||||
|
|||||||
@@ -209,8 +209,13 @@ class WebTerminal {
|
|||||||
this.resizeState.resizeAttempts++;
|
this.resizeState.resizeAttempts++;
|
||||||
this.lastResizeTime = now;
|
this.lastResizeTime = now;
|
||||||
|
|
||||||
|
// Wrap FitAddon operation in additional safety check
|
||||||
|
if (this.fitAddon && typeof this.fitAddon.fit === 'function') {
|
||||||
this.fitAddon.fit();
|
this.fitAddon.fit();
|
||||||
this.resizeState.resizeAttempts = 0; // Reset on success
|
this.resizeState.resizeAttempts = 0; // Reset on success
|
||||||
|
} else {
|
||||||
|
throw new Error("FitAddon not properly initialized");
|
||||||
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("Fit failed:", e);
|
console.warn("Fit failed:", e);
|
||||||
@@ -244,28 +249,59 @@ class WebTerminal {
|
|||||||
/** Check if terminal is ready for resize operations */
|
/** Check if terminal is ready for resize operations */
|
||||||
private isTerminalReady(): boolean {
|
private isTerminalReady(): boolean {
|
||||||
try {
|
try {
|
||||||
// Check if terminal and its core components are initialized
|
// Check if terminal exists
|
||||||
if (!this.terminal || !this.terminal._core) {
|
if (!this.terminal) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if terminal core is initialized
|
||||||
|
if (!this.terminal._core) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const core = this.terminal._core;
|
||||||
|
|
||||||
// Check if viewport is available (FitAddon requirement)
|
// Check if viewport is available (FitAddon requirement)
|
||||||
const core = this.terminal._core;
|
if (!core.viewport) {
|
||||||
if (!core.viewport || !core.viewport.scrollBarWidth) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if render service has valid dimensions
|
// Check if viewport has scrollBarWidth (this is what was failing)
|
||||||
|
if (core.viewport.scrollBarWidth === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if render service exists
|
||||||
|
if (!core._renderService) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if render service has dimensions
|
||||||
const renderService = core._renderService;
|
const renderService = core._renderService;
|
||||||
if (!renderService || !renderService.dimensions) {
|
if (!renderService.dimensions) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if cell dimensions are valid
|
||||||
const dims = renderService.dimensions;
|
const dims = renderService.dimensions;
|
||||||
if (dims.css.cell.width === 0 || dims.css.cell.height === 0) {
|
if (dims.css.cell.width === 0 || dims.css.cell.height === 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Additional safety check for FitAddon internal state
|
||||||
|
if (this.fitAddon) {
|
||||||
|
try {
|
||||||
|
// Try to access FitAddon's terminal reference
|
||||||
|
const fitTerminal = (this.fitAddon as any)._terminal;
|
||||||
|
if (!fitTerminal || fitTerminal !== this.terminal) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// FitAddon might not have the expected structure
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("Terminal readiness check failed:", e);
|
console.warn("Terminal readiness check failed:", e);
|
||||||
|
|||||||
Reference in New Issue
Block a user