Skip to content
| Marketplace
Sign in
Visual Studio Code>Visualization>LoopLensNew to Visual Studio Code? Get it now.
LoopLens

LoopLens

debabrata100

|
2 installs
| (0) | Free
Live, replayable event loop visualization for JavaScript — call stack, microtask queues, and Node.js phases.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

LoopLens

See the JavaScript event loop, live, inside VS Code.

VS Code Marketplace Installs Open VSX

Install from the VS Code Marketplace →  ·  also on Open VSX for VSCodium & Gitpod  ·  or run ext install debabrata100.looplens from Quick Open (⌘P / Ctrl+P)

LoopLens executes the JavaScript in your active editor and shows an animated, replayable visualization of what the event loop actually did: the call stack, the process.nextTick and Promise microtask queues, and the Node.js phases (Timers, Pending Callbacks, Poll, Check, Close Callbacks). Edit your code and the visualization re-runs automatically.

LoopLens visualizing timers, microtasks and nextTick in an untitled file

Features

Live visualization as you type

Open any JavaScript file and run LoopLens: Show Visualizer, or start from scratch with LoopLens: New JavaScript File (works on unsaved, untitled documents — no file on disk required). Every edit triggers a debounced re-run.

Editing code live: pending → running → replay

Trace, then replay

Your program runs to completion in an isolated Node.js child process; LoopLens captures an ordered trace and replays it: play/pause, step forward/back, ×0.5–×4 speed, and a timeline scrubber. Cards animate from enqueued → queue → call stack → done, and the line currently executing is highlighted in your editor — the same way a debugger highlights a paused frame.

Scrubbing the replay timeline; the editor line highlight follows

Honesty note: the replay shows logical ordering, not real-time proportions. It's "step 14 of 62", never a milliseconds axis — a 5-second timer and a 0ms timer are one step apart if they ran back to back.

Two view modes

  • Node.js mode (default): the full phase model, plus the process.nextTick queue and the Promise microtask queue — you can watch both drain after every callback.
  • Plain JS mode: the simplified model most tutorials teach — Call Stack, one Macrotask Queue, one Microtask Queue.

Toggling between Node.js and Plain JS view modes

Errors where you expect them

Syntax and runtime errors map back to the exact line: squiggles in the editor, an entry in the Problems panel, and a clickable banner in the visualizer. Uncaught async errors are traced too.

Live/Debug mode (experimental, off by default)

Set looplens.experimental.debugMode to true (and reload the window) to visualize the event loop live during node/pwa-node debug sessions: instrumentation is injected via --require, events stream over a private IPC pipe (your program's stdout is untouched), breakpoint pauses freeze the view with a banner, and timers whose delay elapsed during the pause are marked "expired — runs on resume". This feature depends on js-debug internals and may not work with every configuration — if it misbehaves, check the "LoopLens Debug" output channel and please file an issue with its contents. attach configs degrade to pause/resume-only visualization.

Note: LoopLens activates on its commands, so run any LoopLens command once per window before starting the debug session you want visualized.

Console drawer

console.log output (captured from the traced run) lives in a drawer at the bottom, in step with the replay — scrub backwards and the log rewinds with you.

Commands

Command Description
LoopLens: Show Visualizer Attach a visualizer panel to the active JavaScript file
LoopLens: New JavaScript File Open an untitled JS document with the visualizer already attached

Settings

Setting Default Description
looplens.runOn change Re-run on edit (debounced) or only on save
looplens.autoRun true Automatic re-runs on/off (Rerun button always works)
looplens.debounceMs 800 Debounce between last edit and re-run
looplens.watchdogMs 5000 Watchdog that force-kills stuck runs (e.g. while(true))
looplens.defaultMode node Default view mode: node or plain

Security

LoopLens executes the code in your editor in a local Node.js child process — the same as running node yourfile.js yourself. A one-time warning asks for consent before the first run. Only visualize code you trust. Runs are guarded by a watchdog timeout and a trace-size cap.

Limitations (v1)

  • Node.js semantics only: no DOM events, browser APIs, or rendering pipeline (no jsdom).
  • The Pending Callbacks and Close Callbacks phases render but aren't populated (that needs socket/handle instrumentation). Network/socket I/O is likewise invisible: e.g. a fetch() shows its (very real) microtask storm but an empty Poll lane while data moves through the socket.
  • Streams (createReadStream / .pipe()) bypass the patched fs callback APIs, so their fd-level I/O isn't traced — you'll see the process.nextTick setup work streams schedule, not the per-chunk poll traffic. Use fs.readFile/fs.writeFile to watch the threadpool → poll story.
  • Timer/nextTick/fs tracing is filtered to calls originating from your file, but promise reactions are traced process-wide (async_hooks): library internals (e.g. undici inside fetch) appear as unlabeled (async continuation) cards. Those microtasks really run — they just aren't your code. Your own callbacks carry L<n> source badges.
  • await resumptions appear with a generic label at execution time; .then/.catch/.finally callbacks get exact labels and enqueue timing.
  • Debug-mode tests simulate DAP sequences and exercise the --require hook against real processes; a full VS Code breakpoint E2E (via @vscode/test-electron) is future work.

Planned for v2

  • Threadpool panel: a modeled libuv pool lane (N slots from UV_THREADPOOL_SIZE, default 4) showing fs/dns/crypto/zlib tasks occupying threads and overflowing into a wait queue — inferred honestly from submission/completion order, since thread timings aren't observable from JS.
  • "Hide library internals" toggle: dim or collapse promise reactions with no user-code ancestry, keeping the teaching view readable while full fidelity stays a click away.
  • Socket/handle instrumentation to populate the Pending Callbacks and Close Callbacks phases, and stream-level tracing for .pipe().

How it works

Your code is sent (as a string — that's why untitled files work) to a forked Node child process running with the file's directory as its working directory (workspace root for untitled files), so relative fs paths and require('./…') behave exactly like node file.js. It is compiled via vm.Script under a synthetic filename so stack frames map 1:1 to your editor lines, and executed against instrumented globals. Timers, immediates, nextTick, queueMicrotask, and fs callbacks are wrapped directly; Promise reactions (including await) are observed via async_hooks. The ordered event trace streams back over IPC and replays in the webview.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft