serialize (w/ actionid) the resize events

This commit is contained in:
sawka 2024-12-19 09:44:29 -08:00
parent aee35f0e01
commit e6315658e1
5 changed files with 88 additions and 47 deletions

View File

@ -46,6 +46,7 @@ type TermWrapOptions = {
export class TermWrap { export class TermWrap {
blockId: string; blockId: string;
ptyOffset: number; ptyOffset: number;
pendingPtyOffset: number;
dataBytesProcessed: number; dataBytesProcessed: number;
terminal: Terminal; terminal: Terminal;
connectElem: HTMLDivElement; connectElem: HTMLDivElement;
@ -56,6 +57,7 @@ export class TermWrap {
heldData: Uint8Array[]; heldData: Uint8Array[];
handleResize_debounced: () => void; handleResize_debounced: () => void;
hasResized: boolean; hasResized: boolean;
isLoadingCache: boolean;
constructor( constructor(
blockId: string, blockId: string,
@ -64,6 +66,7 @@ export class TermWrap {
waveOptions: TermWrapOptions waveOptions: TermWrapOptions
) { ) {
this.loaded = false; this.loaded = false;
this.isLoadingCache = false;
this.blockId = blockId; this.blockId = blockId;
this.ptyOffset = 0; this.ptyOffset = 0;
this.dataBytesProcessed = 0; this.dataBytesProcessed = 0;
@ -165,11 +168,20 @@ export class TermWrap {
} }
handleTermData(data: string) { handleTermData(data: string) {
if (this.isLoadingCache) {
return;
}
if (!this.loaded) { if (!this.loaded) {
return; return;
} }
const b64data = util.stringToBase64(data); const b64data = util.stringToBase64(data);
RpcApi.ControllerInputCommand(TabRpcClient, { blockid: this.blockId, inputdata64: b64data }); const actionId = util.getNextActionId();
RpcApi.ControllerInputCommand(TabRpcClient, {
blockid: this.blockId,
inputdata64: b64data,
feactionid: actionId,
pendingptyoffset: this.pendingPtyOffset,
});
} }
addFocusListener(focusFn: () => void) { addFocusListener(focusFn: () => void) {
@ -198,11 +210,14 @@ export class TermWrap {
let prtn = new Promise<void>((presolve, _) => { let prtn = new Promise<void>((presolve, _) => {
resolve = presolve; resolve = presolve;
}); });
if (setPtyOffset != null) {
this.pendingPtyOffset = setPtyOffset;
} else {
this.pendingPtyOffset = this.ptyOffset + data.length;
}
this.terminal.write(data, () => { this.terminal.write(data, () => {
if (setPtyOffset != null) { this.ptyOffset = this.pendingPtyOffset;
this.ptyOffset = setPtyOffset; if (setPtyOffset == null) {
} else {
this.ptyOffset += data.length;
this.dataBytesProcessed += data.length; this.dataBytesProcessed += data.length;
} }
resolve(); resolve();
@ -217,20 +232,25 @@ export class TermWrap {
if (cacheFile != null) { if (cacheFile != null) {
ptyOffset = cacheFile.meta["ptyoffset"] ?? 0; ptyOffset = cacheFile.meta["ptyoffset"] ?? 0;
if (cacheData.byteLength > 0) { if (cacheData.byteLength > 0) {
const curTermSize: TermSize = { rows: this.terminal.rows, cols: this.terminal.cols }; try {
const fileTermSize: TermSize = cacheFile.meta["termsize"]; this.isLoadingCache = true;
let didResize = false; const curTermSize: TermSize = { rows: this.terminal.rows, cols: this.terminal.cols };
if ( const fileTermSize: TermSize = cacheFile.meta["termsize"];
fileTermSize != null && let didResize = false;
(fileTermSize.rows != curTermSize.rows || fileTermSize.cols != curTermSize.cols) if (
) { fileTermSize != null &&
console.log("terminal restore size mismatch, temp resize", fileTermSize, curTermSize); (fileTermSize.rows != curTermSize.rows || fileTermSize.cols != curTermSize.cols)
this.terminal.resize(fileTermSize.cols, fileTermSize.rows); ) {
didResize = true; console.log("terminal restore size mismatch, temp resize", fileTermSize, curTermSize);
} this.terminal.resize(fileTermSize.cols, fileTermSize.rows);
this.doTerminalWrite(cacheData, ptyOffset); didResize = true;
if (didResize) { }
this.terminal.resize(curTermSize.cols, curTermSize.rows); await this.doTerminalWrite(cacheData, ptyOffset);
if (didResize) {
this.terminal.resize(curTermSize.cols, curTermSize.rows);
}
} finally {
this.isLoadingCache = false;
} }
} }
} }

View File

@ -116,6 +116,8 @@ declare global {
blockid: string; blockid: string;
inputdata64?: string; inputdata64?: string;
signame?: string; signame?: string;
pendingptyoffset?: number;
feactionid?: string;
termsize?: TermSize; termsize?: TermSize;
}; };

View File

@ -62,24 +62,27 @@ var globalLock = &sync.Mutex{}
var blockControllerMap = make(map[string]*BlockController) var blockControllerMap = make(map[string]*BlockController)
type BlockInputUnion struct { type BlockInputUnion struct {
InputData []byte `json:"inputdata,omitempty"` InputData []byte `json:"inputdata,omitempty"`
SigName string `json:"signame,omitempty"` SigName string `json:"signame,omitempty"`
TermSize *waveobj.TermSize `json:"termsize,omitempty"` TermSize *waveobj.TermSize `json:"termsize,omitempty"`
FeActionId string `json:"feactionid,omitempty"`
} }
type BlockController struct { type BlockController struct {
Lock *sync.Mutex Lock *sync.Mutex
ControllerType string ControllerType string
TabId string TabId string
BlockId string BlockId string
BlockDef *waveobj.BlockDef BlockDef *waveobj.BlockDef
CreatedHtmlFile bool CreatedHtmlFile bool
ShellProc *shellexec.ShellProc ShellProc *shellexec.ShellProc
ShellInputCh chan *BlockInputUnion ShellInputCh chan *BlockInputUnion
ShellProcStatus string ShellProcStatus string
ShellProcExitCode int ShellProcExitCode int
RunLock *atomic.Bool RunLock *atomic.Bool
StatusVersion int StatusVersion int
ProcessedToOffset int64
LastResizeActionId string
} }
type BlockControllerRuntimeStatus struct { type BlockControllerRuntimeStatus struct {
@ -117,6 +120,16 @@ func (bc *BlockController) getShellProc() *shellexec.ShellProc {
return bc.ShellProc return bc.ShellProc
} }
func (bc *BlockController) TestAndSetResizeActionId(actionId string) bool {
bc.Lock.Lock()
defer bc.Lock.Unlock()
if actionId <= bc.LastResizeActionId {
return false
}
bc.LastResizeActionId = actionId
return true
}
type RunShellOpts struct { type RunShellOpts struct {
TermSize waveobj.TermSize `json:"termsize,omitempty"` TermSize waveobj.TermSize `json:"termsize,omitempty"`
} }
@ -469,13 +482,16 @@ func (bc *BlockController) DoRunShellCommand(rc *RunShellOpts, blockMeta waveobj
shellProc.Cmd.Write(ic.InputData) shellProc.Cmd.Write(ic.InputData)
} }
if ic.TermSize != nil { if ic.TermSize != nil {
err = setTermSize(ctx, bc.BlockId, *ic.TermSize) ok := bc.TestAndSetResizeActionId(ic.FeActionId)
if err != nil { if ok {
log.Printf("error setting pty size: %v\n", err) err = setTermSize(ctx, bc.BlockId, *ic.TermSize)
} if err != nil {
err = shellProc.Cmd.SetSize(ic.TermSize.Rows, ic.TermSize.Cols) log.Printf("error setting pty size: %v\n", err)
if err != nil { }
log.Printf("error setting pty size: %v\n", err) err = shellProc.Cmd.SetSize(ic.TermSize.Rows, ic.TermSize.Cols)
if err != nil {
log.Printf("error setting pty size: %v\n", err)
}
} }
} }
} }

View File

@ -312,10 +312,12 @@ type CommandControllerResyncData struct {
} }
type CommandBlockInputData struct { type CommandBlockInputData struct {
BlockId string `json:"blockid" wshcontext:"BlockId"` BlockId string `json:"blockid" wshcontext:"BlockId"`
InputData64 string `json:"inputdata64,omitempty"` InputData64 string `json:"inputdata64,omitempty"`
SigName string `json:"signame,omitempty"` SigName string `json:"signame,omitempty"`
TermSize *waveobj.TermSize `json:"termsize,omitempty"` PendingPtyOffset int64 `json:"pendingptyoffset,omitempty"`
FeActionId string `json:"feactionid,omitempty"`
TermSize *waveobj.TermSize `json:"termsize,omitempty"`
} }
type CommandFileDataAt struct { type CommandFileDataAt struct {

View File

@ -242,8 +242,9 @@ func (ws *WshServer) ControllerInputCommand(ctx context.Context, data wshrpc.Com
return fmt.Errorf("block controller not found for block %q", data.BlockId) return fmt.Errorf("block controller not found for block %q", data.BlockId)
} }
inputUnion := &blockcontroller.BlockInputUnion{ inputUnion := &blockcontroller.BlockInputUnion{
SigName: data.SigName, SigName: data.SigName,
TermSize: data.TermSize, TermSize: data.TermSize,
FeActionId: data.FeActionId,
} }
if len(data.InputData64) > 0 { if len(data.InputData64) > 0 {
inputBuf := make([]byte, base64.StdEncoding.DecodedLen(len(data.InputData64))) inputBuf := make([]byte, base64.StdEncoding.DecodedLen(len(data.InputData64)))