終端機 runtime

Environment server 擁有 PTY、session 的生命週期,以及保留下來的輸出。每個 client,包括桌面版的 renderer,都是透過 environment 連線來附掛(attach)。這讓 client 可以重新連線,或共用一個執行中的 session。Renderer 的選擇是各個 client 本機的事,不會改變終端機的合約。

輸出與保留#

終端機歷史是遞增式的。PTY 的 callback 把新的 chunk 附加上去;即時 event 只帶這些 chunk。如果每次 callback 都把完整的 scrollback 具體化或複製一份,輸出的成本就會隨著保留的歷史一起成長,所以只有 snapshot 和合併後的持久化,才是把內容具體化的時機。持久化是把可變的歷史 buffer 排進佇列,等到寫入真正執行時才讀取它最新的值。Clear、restart 和 close 都必須先把寫入 drain 完,才能完成它們各自的生命週期界線。

Server 的歷史上限是每個終端機 5,000 行,以及 8 MiB 的 UTF-8 文字,所以一條很長、沒有換行的輸出也沒辦法繞過保留上限。淘汰時會移除最舊的輸出,而且不會把 Unicode code point 切開;即時輸出不會被截斷。被丟棄的 chunk 參照要立刻釋放,即使陣列的壓實(compaction)是之後才做。Client 的 buffer 另有 512 KiB 的上限。修改這條路徑時,要在 scrollback 全滿的情況下量測吞吐量。

還原時,只能讀取目前或舊版歷史檔案有上限的尾端,跳過任何不完整的 UTF-8 開頭,並套用行數上限。在重寫這個已截短的檔案之前,要先關閉讀取用的 handle。把整個舊 log 讀進來的話,啟動期間的記憶體上限就形同虛設。

Renderer 的歸屬#

Android 和網頁版使用同一套 libghostty-vt C ABI 來實現終端機行為。繪製和輸入的整合由各平台的 adapter 負責,React 不介入終端機的畫面更新(frame)。網頁版的 adapter 在每個瀏覽器分頁裡共用一個 WebAssembly instance,而每個終端機各自擁有並釋放自己的 handle。正式的 upstream 版本釘選(pin)在 native/libghostty-vt/VERSION;它一變動,原生和網頁的產出物都必須重新建置。網頁版會把 revision 嵌進它的建置資訊,這樣 ABI 檢查不需要第二個 pin 就能偵測到版本落差。

還原 scrollback 時,不可以把終端機的回覆送給目前的 shell。否則歷史裡的裝置查詢可能引發新的回覆,在提示字元處顯示成一堆亂碼。Server 會從保留的歷史裡去掉查詢/回應的流量,而網頁版 renderer 在 replay 期間會把它的 PTY writer 卸離。修改保留機制或 renderer 的程式碼時,這兩道保護都要保留。

本頁譯自 docs/internals/terminal-runtime.md(英文原文,版本 ca5f0d4)。標示「本站補充」的區塊不在原文裡。

非官方翻譯,與 T3 Code 的維護者無關。內容由 AI 翻譯並補充,未經逐頁人工校對,可能有錯誤或已經過時,請以英文原文為準。

原文 © T3 Tools Inc.,以 MIT 授權釋出;本站為其官方 repository 中 docs/ 的翻譯。本站原始碼與問題回報