mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-06 16:08:05 +00:00
fix(debugger): cap and virtualise the Debug console, batch output events (#385)
Each DAP output event copied the whole console array and re-rendered every buffered line, so a debuggee writing continuously to stdout froze the window after tens of thousands of lines. Output is now queued and applied once per animation frame (merged per session and category), the buffer is capped (50,000 entries, plus the console buffer-size setting), and the Debug console renders only the visible rows. Refs #377 Co-authored-by: a-rookie-of-C-language <186315048+a-rookie-of-C-language@users.noreply.github.com>
This commit is contained in:
co-authored by
a-rookie-of-C-language
parent
379a52d6e7
commit
ea53e4f6fa
@@ -1,7 +1,8 @@
|
||||
/** Debug tool window: toolbar, Threads & Variables (frames + variables), Console. */
|
||||
import { copySelectionOnKeyDown } from "@/ui/selectableText";
|
||||
import { useEffect, useMemo, useRef, useState, type KeyboardEvent } from "react";
|
||||
import { useEffect, useLayoutEffect, useMemo, useRef, useState, type KeyboardEvent } from "react";
|
||||
import clsx from "clsx";
|
||||
import { useVirtualizer } from "@tanstack/react-virtual";
|
||||
import { executeAction, getAction } from "@/platform/actions";
|
||||
import { evaluateWhen, useContextKeys } from "@/platform/context";
|
||||
import { basename, useProject } from "@/platform/project";
|
||||
@@ -550,15 +551,28 @@ function ConsoleView({ session }: { session: DebugSession }) {
|
||||
const lines = useDebug((s) => s.console[session.id]);
|
||||
const scroller = useRef<HTMLDivElement>(null);
|
||||
const stick = useRef(true);
|
||||
const programmatic = useRef(false);
|
||||
const [input, setInput] = useState("");
|
||||
const history = useRef<string[]>(readHistory("console"));
|
||||
const historyPos = useRef(-1);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const virtualizer = useVirtualizer({
|
||||
count: lines?.length ?? 0,
|
||||
getScrollElement: () => scroller.current,
|
||||
estimateSize: () => 18,
|
||||
overscan: 30,
|
||||
getItemKey: (i) => lines?.[i]?.id ?? i,
|
||||
});
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const el = scroller.current;
|
||||
if (el && stick.current) el.scrollTop = el.scrollHeight;
|
||||
}, [lines]);
|
||||
if (!el || !stick.current || !lines?.length) return;
|
||||
programmatic.current = true;
|
||||
virtualizer.scrollToIndex(lines.length - 1, { align: "end" });
|
||||
el.scrollTop = el.scrollHeight;
|
||||
requestAnimationFrame(() => (programmatic.current = false));
|
||||
}, [lines, virtualizer]);
|
||||
|
||||
const submit = async () => {
|
||||
const e = input.trim();
|
||||
@@ -614,6 +628,7 @@ function ConsoleView({ session }: { session: DebugSession }) {
|
||||
ref={scroller}
|
||||
className={clsx(styles.consoleOutput, ansi.palette)}
|
||||
onScroll={(e) => {
|
||||
if (programmatic.current) return;
|
||||
const el = e.currentTarget;
|
||||
stick.current = el.scrollHeight - el.scrollTop - el.clientHeight < 24;
|
||||
}}
|
||||
@@ -626,15 +641,27 @@ function ConsoleView({ session }: { session: DebugSession }) {
|
||||
aria-label={tx("Debug console")}
|
||||
tabIndex={0}
|
||||
>
|
||||
{(lines ?? []).map((l) => (
|
||||
<span key={l.id} className={clsx(styles.out, styles[`cat-${l.category}`])}>
|
||||
{l.spans.map((sp, i) => (
|
||||
<span key={i} style={spanStyle(sp)}>
|
||||
{sp.text}
|
||||
<div className={styles.consoleInner} style={{ height: virtualizer.getTotalSize() }}>
|
||||
{virtualizer.getVirtualItems().map((item) => {
|
||||
const l = lines?.[item.index];
|
||||
if (!l) return null;
|
||||
return (
|
||||
<span
|
||||
key={item.key}
|
||||
data-index={item.index}
|
||||
ref={virtualizer.measureElement}
|
||||
className={clsx(styles.out, styles[`cat-${l.category}`])}
|
||||
style={{ transform: `translateY(${item.start}px)` }}
|
||||
>
|
||||
{l.spans.map((sp, i) => (
|
||||
<span key={i} style={spanStyle(sp)}>
|
||||
{sp.text}
|
||||
</span>
|
||||
))}
|
||||
</span>
|
||||
))}
|
||||
</span>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<label className={styles.repl}>
|
||||
<span className={styles.prompt} aria-hidden>
|
||||
|
||||
Reference in New Issue
Block a user