Skip to content

Commit 46a95b5

Browse files
committed
feat: add memory and stack variables visualization to event loop simulator
1 parent 19b2580 commit 46a95b5

File tree

5 files changed

+275
-29
lines changed

5 files changed

+275
-29
lines changed

src/App.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { MicrotaskQueue } from '@/components/event-loop/MicrotaskQueue'
66
import { TaskQueue } from '@/components/event-loop/TaskQueue'
77
import { EventLoopStatus } from '@/components/event-loop/EventLoopStatus'
88
import { CodeDisplay } from '@/components/event-loop/CodeDisplay'
9+
import { Memory } from '@/components/event-loop/Memory'
10+
import { StackVariables } from '@/components/event-loop/StackVariables'
911
import { HistoryPanel } from '@/components/panels/HistoryPanel'
1012
import { ExampleButtons } from '@/components/controls/ExampleButtons'
1113
import { StepControls } from '@/components/controls/StepControls'
@@ -109,6 +111,12 @@ function App() {
109111
/>
110112
)}
111113

114+
{/* Memory and Stack Variables */}
115+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
116+
<StackVariables frames={state.stackVariables} />
117+
<Memory items={state.memory} />
118+
</div>
119+
112120
{/* Main Layout */}
113121
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
114122
{/* Event Loop Visualization */}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
2+
import { Badge } from '@/components/ui/badge'
3+
import { Database, Box } from 'lucide-react'
4+
import { MemoryItem } from '@/types/memory'
5+
6+
interface MemoryProps {
7+
items: MemoryItem[]
8+
title?: string
9+
}
10+
11+
export function Memory({ items, title = 'Memory (Heap)' }: MemoryProps) {
12+
const getTypeColor = (type: MemoryItem['type']) => {
13+
switch (type) {
14+
case 'object':
15+
return 'bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300'
16+
case 'function':
17+
return 'bg-purple-100 text-purple-700 dark:bg-purple-900 dark:text-purple-300'
18+
case 'closure':
19+
return 'bg-pink-100 text-pink-700 dark:bg-pink-900 dark:text-pink-300'
20+
default:
21+
return 'bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-300'
22+
}
23+
}
24+
25+
const formatValue = (value: any): string => {
26+
if (typeof value === 'object') {
27+
return JSON.stringify(value, null, 2)
28+
}
29+
return String(value)
30+
}
31+
32+
return (
33+
<Card className="h-full">
34+
<CardHeader className="pb-3">
35+
<CardTitle className="text-lg flex items-center gap-2">
36+
<Database className="w-5 h-5 text-blue-600 dark:text-blue-400" />
37+
{title}
38+
<Badge variant="secondary" className="ml-auto">
39+
{items.length}
40+
</Badge>
41+
</CardTitle>
42+
</CardHeader>
43+
<CardContent className="space-y-2">
44+
{items.length === 0 ? (
45+
<div className="text-center py-8 text-muted-foreground">
46+
<Box className="w-12 h-12 mx-auto mb-2 opacity-50" />
47+
<p className="text-sm">Heap порожній</p>
48+
</div>
49+
) : (
50+
<div className="space-y-2 max-h-[300px] overflow-y-auto">
51+
{items.map((item) => (
52+
<div
53+
key={item.id}
54+
className="p-3 rounded-lg border bg-card hover:bg-accent/50 transition-colors"
55+
>
56+
<div className="flex items-start justify-between mb-2">
57+
<div className="flex items-center gap-2">
58+
<span className="font-mono font-semibold text-sm">
59+
{item.name}
60+
</span>
61+
<Badge className={`text-xs ${getTypeColor(item.type)}`}>
62+
{item.type}
63+
</Badge>
64+
</div>
65+
{item.reference && (
66+
<Badge variant="outline" className="text-xs font-mono">
67+
@{item.reference}
68+
</Badge>
69+
)}
70+
</div>
71+
72+
{item.scope && (
73+
<div className="text-xs text-muted-foreground mb-1">
74+
Scope: {item.scope}
75+
</div>
76+
)}
77+
78+
<div className="font-mono text-xs bg-muted p-2 rounded overflow-x-auto">
79+
<pre className="whitespace-pre-wrap">
80+
{formatValue(item.value)}
81+
</pre>
82+
</div>
83+
</div>
84+
))}
85+
</div>
86+
)}
87+
</CardContent>
88+
</Card>
89+
)
90+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
2+
import { Badge } from '@/components/ui/badge'
3+
import { Layers, Variable } from 'lucide-react'
4+
import { StackFrame } from '@/types/memory'
5+
6+
interface StackVariablesProps {
7+
frames: StackFrame[]
8+
}
9+
10+
export function StackVariables({ frames }: StackVariablesProps) {
11+
return (
12+
<Card className="h-full">
13+
<CardHeader className="pb-3">
14+
<CardTitle className="text-lg flex items-center gap-2">
15+
<Layers className="w-5 h-5 text-green-600 dark:text-green-400" />
16+
Stack Variables
17+
<Badge variant="secondary" className="ml-auto">
18+
{frames.length}
19+
</Badge>
20+
</CardTitle>
21+
</CardHeader>
22+
<CardContent className="space-y-2">
23+
{frames.length === 0 ? (
24+
<div className="text-center py-8 text-muted-foreground">
25+
<Variable className="w-12 h-12 mx-auto mb-2 opacity-50" />
26+
<p className="text-sm">Stack порожній</p>
27+
</div>
28+
) : (
29+
<div className="space-y-3 max-h-[300px] overflow-y-auto">
30+
{frames.map((frame, idx) => (
31+
<div
32+
key={idx}
33+
className="p-3 rounded-lg border bg-card hover:bg-accent/50 transition-colors"
34+
>
35+
<div className="font-semibold text-sm mb-2 flex items-center gap-2">
36+
<span className="text-primary">{frame.name}</span>
37+
<Badge variant="outline" className="text-xs">
38+
Frame {frames.length - idx}
39+
</Badge>
40+
</div>
41+
42+
{frame.variables.length > 0 ? (
43+
<div className="space-y-1">
44+
{frame.variables.map((variable, vIdx) => (
45+
<div
46+
key={vIdx}
47+
className="flex items-center justify-between text-xs font-mono bg-muted p-2 rounded"
48+
>
49+
<span className="text-muted-foreground">{variable.name}:</span>
50+
<div className="flex items-center gap-2">
51+
<span className="font-semibold">
52+
{typeof variable.value === 'string'
53+
? `"${variable.value}"`
54+
: variable.value}
55+
</span>
56+
{variable.heapRef && (
57+
<Badge variant="outline" className="text-xs">
58+
→@{variable.heapRef}
59+
</Badge>
60+
)}
61+
</div>
62+
</div>
63+
))}
64+
</div>
65+
) : (
66+
<p className="text-xs text-muted-foreground italic">
67+
Немає локальних змінних
68+
</p>
69+
)}
70+
</div>
71+
))}
72+
</div>
73+
)}
74+
</CardContent>
75+
</Card>
76+
)
77+
}

0 commit comments

Comments
 (0)