fix: close ghostty-web .then() callback in terminal.js and fix stale xterm.js references
Critical fix for JavaScript syntax error:
- terminal.js line 282/415: Missing closing }); for .then(function() { callback
caused SyntaxError: missing ) after argument list, breaking all terminal functionality
Important fixes for stale xterm.js references in terminal.js:
- Line 98: Stale comment 'write directly to xterm' → 'write directly to terminal'
- Line 164: Stale docstring 'xterm.js Terminal' → 'ghostty-web Terminal'
- Line 470: Stale CSS selector '.xterm-helper-textarea' → 'textarea' for ghostty-web
Test improvements:
- Added test_terminal_js_valid_javascript_syntax: validates terminal.js via node -c
(catches JavaScript syntax errors like this one in CI/CD)
- Added test_terminal_js_no_stale_xterm_comments: prevents future stale xterm references
- Updated test_app.mjs Node.js tests to validate ghostty-web.js instead of stale xterm
Verification:
- node -c terminal.js passes (exit 0)
- 1307/1307 Python tests pass
- Node.js test_app.mjs tests pass
This commit is contained in:
@@ -95,7 +95,7 @@ function _openMuxtermSocket() {
|
||||
if (ws !== _ws) return; // stale guard
|
||||
if (!_term) return;
|
||||
if (e.data instanceof ArrayBuffer) {
|
||||
// Binary frame: terminal output — write directly to xterm
|
||||
// Binary frame: terminal output — write directly to terminal
|
||||
var payload = new Uint8Array(e.data);
|
||||
_term.write(_decoder ? _decoder.decode(payload) : payload);
|
||||
} else if (typeof e.data === 'string') {
|
||||
@@ -161,7 +161,7 @@ function initVisualViewport() {
|
||||
|
||||
// ——— Terminal creation ————————————————————————————————————————————————
|
||||
/**
|
||||
* Create (or recreate) the xterm.js Terminal with addons.
|
||||
* Create (or recreate) the ghostty-web Terminal with addons.
|
||||
* @param {number} [fontSize=14]
|
||||
*/
|
||||
function createTerminal(fontSize) {
|
||||
@@ -412,6 +412,7 @@ function openTerminal(sessionName, remoteId, fontSize) {
|
||||
} else {
|
||||
connectWebSocket();
|
||||
}
|
||||
}); // close _ghosttyReady.then(function() { ... })
|
||||
}
|
||||
|
||||
// ——— Close terminal ————————————————————————————————————————————————
|
||||
@@ -467,7 +468,8 @@ function _initAndroidIMEFix(container) {
|
||||
if (!/Android/i.test(navigator.userAgent)) return;
|
||||
|
||||
setTimeout(function() {
|
||||
var ta = container.querySelector('.xterm-helper-textarea');
|
||||
// ghostty-web may use a different textarea class than xterm.js (.xterm-helper-textarea)
|
||||
var ta = container.querySelector('textarea');
|
||||
if (!ta) return;
|
||||
|
||||
ta.addEventListener('beforeinput', function(e) {
|
||||
|
||||
@@ -4110,11 +4110,11 @@ test('tile click handler ignores clicks on tile-options-btn button', () => {
|
||||
|
||||
// --- index.html: self-hosted vendor libs (no CDN) ---
|
||||
|
||||
test('index.html loads xterm.css from local /vendor/ path (not CDN)', () => {
|
||||
test('index.html loads ghostty-web.js from local /vendor/ path (not CDN)', () => {
|
||||
const html = fs.readFileSync(new URL('../index.html', import.meta.url), 'utf8');
|
||||
assert.ok(
|
||||
html.includes('href="/vendor/xterm.css"'),
|
||||
'index.html must reference /vendor/xterm.css (not CDN)',
|
||||
html.includes('ghostty-web.js'),
|
||||
'index.html must reference ghostty-web.js (not xterm.js)',
|
||||
);
|
||||
assert.ok(
|
||||
!html.includes('cdn.jsdelivr.net'),
|
||||
@@ -4122,11 +4122,11 @@ test('index.html loads xterm.css from local /vendor/ path (not CDN)', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('index.html loads all 5 xterm JS scripts from local /vendor/ paths (not CDN)', () => {
|
||||
test('index.html loads ghostty-web and remaining addon scripts from local /vendor/ paths (not CDN)', () => {
|
||||
const html = fs.readFileSync(new URL('../index.html', import.meta.url), 'utf8');
|
||||
// ghostty-web replaces xterm.js + xterm-addon-fit.js (fit is built-in)
|
||||
const vendorScripts = [
|
||||
'/vendor/xterm.js',
|
||||
'/vendor/xterm-addon-fit.js',
|
||||
'/vendor/ghostty-web.js',
|
||||
'/vendor/xterm-addon-web-links.js',
|
||||
'/vendor/xterm-addon-search.js',
|
||||
'/vendor/addon-image.js',
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import pathlib
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
JS_PATH = pathlib.Path(__file__).parent.parent / "frontend" / "app.js"
|
||||
TERMINAL_JS_PATH = pathlib.Path(__file__).parent.parent / "frontend" / "terminal.js"
|
||||
@@ -5004,3 +5005,35 @@ def test_terminal_js_connects_to_muxterm_port_directly() -> None:
|
||||
"terminal.js must reference _muxtermPort — "
|
||||
"WebSocket connects directly to the muxterm port"
|
||||
)
|
||||
|
||||
|
||||
# ── terminal.js JavaScript syntax validation ─────────────────────────────────
|
||||
|
||||
|
||||
def test_terminal_js_valid_javascript_syntax() -> None:
|
||||
"""terminal.js must be syntactically valid JavaScript (node -c)."""
|
||||
result = subprocess.run(
|
||||
["node", "-c", str(TERMINAL_JS_PATH)],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
assert result.returncode == 0, (
|
||||
f"terminal.js has a JavaScript syntax error:\n{result.stderr}"
|
||||
)
|
||||
|
||||
|
||||
# ── terminal.js must not have stale xterm.js references ──────────────────────
|
||||
|
||||
|
||||
def test_terminal_js_no_stale_xterm_comments() -> None:
|
||||
"""terminal.js comments must not reference xterm.js — use 'terminal' or 'ghostty-web'."""
|
||||
# Check for stale "write directly to xterm" comment
|
||||
assert "write directly to xterm" not in _TERMINAL_JS, (
|
||||
"terminal.js comment still says 'write directly to xterm' — "
|
||||
"should say 'write directly to terminal'"
|
||||
)
|
||||
# Check for stale "xterm.js Terminal" in createTerminal docstring
|
||||
assert "xterm.js Terminal" not in _TERMINAL_JS, (
|
||||
"terminal.js comment still says 'xterm.js Terminal' — "
|
||||
"should reference ghostty-web"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user