mirror of
https://github.com/binaricat/Netcatty.git
synced 2026-11-08 09:01:40 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28793ed798 |
No files matched your search
@@ -212,6 +212,7 @@ import {
|
||||
import {
|
||||
releaseTerminalFlowBeforeHibernate,
|
||||
} from "./terminal/runtime/terminalSessionAttachment";
|
||||
import { resetTerminalLineTimestamps } from "./terminal/runtime/terminalLineTimestamps";
|
||||
import {
|
||||
flushPendingTerminalWritesBeforeHibernate,
|
||||
hasPendingTerminalWrites,
|
||||
@@ -1631,6 +1632,9 @@ const TerminalComponent: React.FC<TerminalProps> = ({
|
||||
}
|
||||
if (term) {
|
||||
term.reset();
|
||||
// The buffer was just wiped; drop ledger stamps anchored to the old
|
||||
// rows so the reconnect gutter cannot paint stale timestamps.
|
||||
resetTerminalLineTimestamps(term);
|
||||
if (payload.snapshot) {
|
||||
await new Promise<void>((resolve) => term.write(payload.snapshot, resolve));
|
||||
}
|
||||
|
||||
@@ -3708,7 +3708,7 @@ test("ssh session restores cwd before startup command after attaching", async ()
|
||||
assert.deepEqual(progressLogs, ["Restoring working directory: /srv/app dir"]);
|
||||
});
|
||||
|
||||
test("local session resets terminal timestamp state when reusing a terminal", async () => {
|
||||
test("local session keeps timestamp anchors for preserved scrollback when reusing a terminal", async () => {
|
||||
const writes: string[] = [];
|
||||
const markerLines: number[] = [];
|
||||
const disposedMarkerLines: number[] = [];
|
||||
@@ -3814,8 +3814,10 @@ test("local session resets terminal timestamp state when reusing a terminal", as
|
||||
assert.equal(writes.length, 2);
|
||||
assert.equal(writes[0], "unfinished");
|
||||
assert.equal(writes[1], "fresh");
|
||||
// Reconnect preserves the buffer, so the pre-restart stamp stays anchored
|
||||
// (not disposed) and the fresh output records its own stamp.
|
||||
assert.deepEqual(markerLines, [0, 0]);
|
||||
assert.deepEqual(disposedMarkerLines, [0]);
|
||||
assert.deepEqual(disposedMarkerLines, []);
|
||||
});
|
||||
|
||||
test("session data waits for prior terminal writes before evaluating prompt line breaks", async () => {
|
||||
|
||||
@@ -1501,6 +1501,23 @@ export const resetTerminalLineTimestamps = (term: XTerm) => {
|
||||
resetTimestampStore(getTimestampStore(term));
|
||||
};
|
||||
|
||||
/**
|
||||
* Reconnect-style reattach on a reused terminal: the xterm buffer (including
|
||||
* scrollback preserved by the reconnect flow) survives the previous session,
|
||||
* so keep ledger stamps anchored to that history and only reset per-session
|
||||
* recording state (segmenter line tracking, same-second gate, pending prefix).
|
||||
* A full reset here would leave preserved scrollback rows without timestamps.
|
||||
*/
|
||||
export const resetTerminalLineTimestampRecordingState = (term: XTerm): void => {
|
||||
const store = getTimestampStore(term);
|
||||
store.segmenter.reset();
|
||||
store.timestampOnlyPrefix = "";
|
||||
store.lastStampSecondKey = null;
|
||||
store.recordsSincePrune = 0;
|
||||
store.disposedPendingCompact = 0;
|
||||
notifyTimestampStore(store);
|
||||
};
|
||||
|
||||
export const onTerminalLineTimestampsChange = (
|
||||
term: XTerm,
|
||||
listener: () => void,
|
||||
|
||||
@@ -2051,6 +2051,49 @@ test("attachSessionToTerminal resets timestamp state for a reused terminal", ()
|
||||
assert.equal(writes[1], "fresh");
|
||||
});
|
||||
|
||||
test("attachSessionToTerminal keeps timestamps for scrollback preserved by reconnect", () => {
|
||||
const { term } = createFakeTerm();
|
||||
const ctx = {
|
||||
...createContext(false, { showLineTimestamps: true }),
|
||||
sessionId: "session-1",
|
||||
sessionRef: { current: null },
|
||||
hasConnectedRef: { current: true },
|
||||
hasRunStartupCommandRef: { current: false },
|
||||
disposeDataRef: { current: null },
|
||||
disposeExitRef: { current: null },
|
||||
fitAddonRef: { current: null },
|
||||
serializeAddonRef: { current: null },
|
||||
pendingAuthRef: { current: null },
|
||||
terminalBackend: {
|
||||
onSessionData: () => () => {},
|
||||
onSessionExit: () => () => {},
|
||||
},
|
||||
updateStatus: () => {},
|
||||
setError: () => {},
|
||||
onSessionExit: () => {},
|
||||
};
|
||||
const originalDateNow = Date.now;
|
||||
|
||||
try {
|
||||
Date.now = () => new Date(2026, 0, 1, 12, 0, 59, 800).getTime();
|
||||
writeSessionData(ctx as never, term, "before reconnect\r\n");
|
||||
|
||||
// Reconnect reuses the same xterm (scrollback preserved by the caller).
|
||||
attachSessionToTerminal(ctx as never, term, "session-2");
|
||||
|
||||
Date.now = () => new Date(2026, 0, 1, 12, 1, 30, 0).getTime();
|
||||
writeSessionData(ctx as never, term, "after reconnect\r\n");
|
||||
|
||||
assert.deepEqual(getVisibleTerminalLineTimestampRows(term), [
|
||||
{ row: 0, label: "12:00:59" },
|
||||
{ row: 1, label: "12:01:30" },
|
||||
]);
|
||||
} finally {
|
||||
Date.now = originalDateNow;
|
||||
resetTerminalWriteCoalescer(term);
|
||||
}
|
||||
});
|
||||
|
||||
test("attachSessionToTerminal clears the backend id before reporting exit", () => {
|
||||
const { term } = createFakeTerm();
|
||||
let onExit: ((evt: { reason?: string }) => void) | null = null;
|
||||
|
||||
@@ -23,7 +23,7 @@ import type {
|
||||
} from "./createTerminalSessionStarters.types";
|
||||
import { clearConnectionToken } from "./terminalDistroDetection";
|
||||
import {
|
||||
resetTerminalLineTimestamps,
|
||||
resetTerminalLineTimestampRecordingState,
|
||||
type TerminalLineTimestampPerfStep,
|
||||
writeTerminalDataWithLineTimestamps,
|
||||
} from "./terminalLineTimestamps";
|
||||
@@ -409,7 +409,7 @@ export const getFlowController = (
|
||||
return controller;
|
||||
};
|
||||
|
||||
export const resetTerminalLineTimestampState = resetTerminalLineTimestamps;
|
||||
export const resetTerminalLineTimestampState = resetTerminalLineTimestampRecordingState;
|
||||
|
||||
export const acknowledgeDroppedTerminalDisplayBytes = (
|
||||
ctx: TerminalSessionStartersContext,
|
||||
@@ -856,7 +856,10 @@ export const attachSessionToTerminal = (
|
||||
teardownTerminalOutputPipeline(ctx, term, id, flow);
|
||||
flushTerminalWriteCoalescer(term);
|
||||
resetTerminalSyncBlockFilter(term);
|
||||
resetTerminalLineTimestamps(term);
|
||||
// Reattach keeps the xterm buffer (reconnect preserves scrollback), so only
|
||||
// reset per-session recording state — a full reset would strip timestamps
|
||||
// from preserved history.
|
||||
resetTerminalLineTimestampRecordingState(term);
|
||||
resetTerminalOutputPressure(term);
|
||||
ctx.onSessionAttached?.(id);
|
||||
const assistMode =
|
||||
|
||||
Reference in new issue
Block a user