RenJS Debugger
VS Code debug adapter for the RenJS / PrairieScript scripting engine.
Supports breakpoints, step-in / step-out / step-over, stack frames, variable
inspection, and virtual (in-memory) source files served over a custom
virtual:// URI scheme.
Features
| Feature |
Description |
| Breakpoints |
Set, remove, and hit breakpoints in .renjs files |
| Step controls |
Step In, Step Out, Step Over, Continue, Pause |
| Stack frames |
Full call-stack view at every pause |
| Variables |
Locals and globals visible in the Variables panel |
| Virtual sources |
Scripts loaded from a database are served to VS Code automatically |
| Multi-engine |
Debug any one of several simultaneously running engine instances |
File Extensions
.renjs · .renJS
Quick Start — Single Engine
The simplest case: one engine, one port, no picker.
1. Start your engine with debug support
Build and run debugExample (or your own host) without --manager:
debugExample.exe --debug --port 5678
2. Add a launch configuration
In your project's .vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"type": "renjs-debuger",
"request": "attach",
"name": "Attach to RenJS engine",
"address": "localhost",
"port": 5678
}
]
}
3. Set a breakpoint and press F5
Open a .renjs file, click in the gutter, then press F5.
The engine pauses and VS Code shows the stack, local variables, and source.

Multi-Engine Mode — Step by Step
When the server hosts several script engines simultaneously (e.g. one per
customer session or workflow), use EngineManager mode. A single TCP port
is shared; VS Code shows a picker so you choose which engine to debug.
Prerequisites
- The server process was started with
--manager (or equivalent in your code).
- Each engine thread called
prepareDebugServer() + registerEngine() +
startServer(5678) — the first call opens the socket, subsequent calls
are a silent no-op.
Step 1 — Start the server in manager mode
debugExample.exe --manager --port 5678
The console should show:
[EngineManager] Registered engine: engine-1 ("Worker 1 — billing.renjs")
[EngineManager] Registered engine: engine-2 ("Worker 2 — reporting.renjs")
[EngineManager] Listening on port 5678

Step 2 — Add manager-mode launch configurations
{
"version": "0.2.0",
"configurations": [
{
"type": "renjs-debuger",
"request": "attach",
"name": "RenJS — attach (pick engine)",
"address": "localhost",
"port": 5678
// No engineId → picker appears automatically
},
{
"type": "renjs-debuger",
"request": "attach",
"name": "RenJS — attach engine-1 (no picker)",
"address": "localhost",
"port": 5678,
"engineId": "engine-1"
},
{
"type": "renjs-debuger",
"request": "attach",
"name": "RenJS — attach engine-2 (no picker)",
"address": "localhost",
"port": 5678,
"engineId": "engine-2"
}
],
"compounds": [
{
"name": "Debug both engines simultaneously",
"configurations": [
"RenJS — attach engine-1 (no picker)",
"RenJS — attach engine-2 (no picker)"
]
}
]
}
Step 3 — Open the Run and Debug panel
Press Ctrl+Shift+D to open the Run and Debug side-panel.

Step 4 — Select "attach (pick engine)" and press F5
The extension connects to port 5678, calls listEngines, and — because more
than one engine is running — displays the engine picker.

Each entry shows the engine name and its current status (idle, running,
paused, or stopped).
Step 5 — Select the engine you want to debug
Click one of the entries. The extension sends selectEngine over the same
TCP connection, which the server uses to hand the socket to that engine's
DAPServer. All subsequent traffic on that socket is normal DAP.
If only one engine is registered, the picker is skipped and the sole
engine is selected automatically.
If engineId is set in launch.json, the picker is skipped entirely.

Step 6 — Set breakpoints and debug normally
VS Code receives all virtual source files via the sourceInfo event and opens
them automatically. Set breakpoints in the gutter and use the debug toolbar
as usual.

Step 7 — Detach or stop
| Action |
Effect on engine |
| Detach (disconnect icon) |
Engine continues running; breakpoints cleared |
| Stop (red square) |
Engine execution is terminated |
| VS Code crash / network drop |
Engine continues running (implicit detach) |

Step 8 — Debug a second engine simultaneously (optional)
Leave the first session running and press F5 again with a different
configuration (or use the compound). VS Code opens a second debug session
and connects to the same port — EngineManager accepts the new connection in
parallel.

Connection Protocol — Overview
VS Code Server (port 5678)
| |
|-- TCP connect ---------------------->| EngineManager accepts
| |
|-- { command:"listEngines" } ------->| Manager responds with engine list
|<- { engines:[{id,name,status},...] }-|
| |
|-- { command:"selectEngine", | Manager hands socket to DAPServer
| arguments:{engineId:"..."} } -->|
|<- { success:true } ----------------|
| |
|-- { command:"initialize" } -------->| Normal DAP from here on
| ... full DAP session ... |
Building the Extension
# One-time compile
npm run compile
# Clean rebuild (wipes out/ then recompiles)
npm run rebuild
# Watch mode (recompiles on every save)
npm run watch
# Package as .vsix for distribution
npm run package
The .vsix file is written to the project root and can be installed via
Extensions → Install from VSIX… or code --install-extension <file>.vsix.
Version History
1.0.4
- Multi-engine EngineManager support (single shared port, pre-DAP handshake)
- Engine quick-pick before DAP session starts
- Disconnect/detach correctness: engines resume on detach, terminate on stop
InitializedEvent ordering fix (prevents premature setBreakpoints)
- ECONNRESET guard on manager socket
1.0.3
- Virtual source file support (
virtual:// URI scheme)
sourceInfo custom event → automatic source file display
1.0.0
- Initial DAP adapter / client
- Breakpoints, step controls, stack frames
Author
Shpend Gjonbalaj — s.gjonbalaj@epay.de