@i-scope/vlst-parser
v0.1.2
Published
Parser for the VLST (Variable List String Table) binary blob returned by ScopeAppDbgCtrl::GetStackContent. Shared building block for iScope IDE frontends that need to surface JScript locals / watch trees.
Maintainers
Readme
@i-scope/vlst-parser
Part of the
@i-scope/debuggerSDK — one of seven leaf packages aggregated by the@i-scope/debuggermeta-umbrella. Most users should install the meta (npm install @i-scope/debugger), which transitively gives you VLST decoding alongside the DAP / MCP stack. Install@i-scope/vlst-parserdirectly only when you decode VLST blobs outside a live debug session — post-mortem dump inspectors, CLI tools that re-parse captured payloads, format research.
Parser for the VLST (Variable List String Table) binary blob returned by
ScopeAppDbgCtrl::GetStackContent on Oscilloscope.exe. Turns the engine's
UTF-16-LE BSTR into a tree of locals / watch / hover values for IDE tooling.
Originally lived inside the iScope DAP adapter; now a stand-alone package so
@i-scope/dap-adapter, @i-scope/iscope-bridge-client, and
@i-scope/mcp-server share one parser implementation.
Install
npm install @i-scope/vlst-parserRequires Node.js ≥ 20. No runtime dependencies beyond Node built-ins.
Quick start
import {
decodeVlstBase64,
parseVlst,
dumpVlst,
packEvalReqData,
} from '@i-scope/vlst-parser';
// Base64 is how iScopeBridge returns GetStackContent (raw BSTR bytes).
const words = decodeVlstBase64(rawBase64FromBridge);
const { roots, consumed } = parseVlst(words);
for (const node of roots) {
console.log(node.name, node.type, node.value ?? '(compound)');
if (node.children) {
for (const child of node.children) {
console.log(' ', child.name, '=', child.value);
}
}
}
// Debug dump (tests, CLI inspectors)
console.log(dumpVlst(roots));
// Pack the 32-bit `req` argument for GetStackContent (EvalReqData layout)
const req = packEvalReqData({ contextId: 0, typeId: 0, radix: 0 });Typical flow in a debug session:
- Call
getStackContentvia@i-scope/iscope-bridge-client→rawBase64. decodeVlstBase64→Uint16Arrayof UTF-16 code units.parseVlst→{ roots: VlstNode[], consumed }.- Map
VlstNodetrees to DAPVariable/Scoperesponses (adapter layer).
API
| Export | Description |
| --- | --- |
| decodeVlstBase64(b64) | Base64 (raw BSTR bytes) → Uint16Array UTF-16-LE code units. Throws on odd byte length. |
| parseVlst(words) | Parse code units → VlstParseResult (roots, consumed). Throws with vlstPos on malformed input. |
| packEvalReqData({ contextId?, typeId?, radix? }) | Pack EvalReqData into the 32-bit req field for GetStackContent. |
| dumpVlst(nodes, indent?) | Pretty-print a tree for logs and fixtures. |
| VlstNode | { name, type, value?, children? } — one variable or expression result. |
| VlstParseResult | { roots: VlstNode[], consumed: number }. |
typeId: 0 = local scope (RTID_LocalVarScope), 1 = parsed expressions
(RTID_ParceExpressions). Radix bits follow the engine's internal enum when
requesting numeric display strings.
Wire format (summary)
| Topic | Detail |
| --- | --- |
| Transport | BSTR: UTF-16-LE WORDs, even byte length, trailing 0x0000 terminator WORD ignored by the parser. |
| Chunk | 1 WORD header: top 3 bits = flags, low 13 bits = payload length in WCHARs; then length UTF-16 payload WORDs. |
| Item | Triplet on the wire: Name → Type → Value (or nested sub-level). |
| FLG_ITM (0x8000) | Name header starts a new item. |
| FLG_SLEV (0x4000) | Value slot opens a nested child list (recursion). |
| FLG_ULEV (0x2000) | Last item on the current level — parser returns to parent. |
Integration
| Consumer | Role |
| --- | --- |
| @i-scope/iscope-bridge-client | Re-exports VLST helpers; returns rawBase64 from getStackContent. |
| @i-scope/dap-adapter | Locals, watch, evaluate → DAP variables / scopes. |
| @i-scope/mcp-server | debug_variables and related MCP tools over the same tree. |
This package does not talk to COM or spawn iScopeBridge.exe — only parses
bytes you already received.
Tests
From the monorepo root:
npm run test --workspace=@i-scope/vlst-parserFixtures live under packages/vlst-parser/tests/ (compiled to dist/tests/).
Verify the published tarball includes this README:
npm pack --dry-run --workspace=@i-scope/vlst-parserRelated docs
@i-scope/com-protocol-types—RTID_*and COM constants.
Related packages
This package is one of seven leaves of the
@i-scope/debugger SDK
meta-umbrella. The full family:
| Package | Role |
|---------|------|
| @i-scope/debugger | meta — one-install entry point for the whole SDK |
| @i-scope/mcp-server | MCP server for AI agents (22 tools) |
| @i-scope/dap-adapter | DAP server (AjsDebugSession) — embeddable + stdio |
| @i-scope/iscope-bridge-client | Node JSON-RPC client to the native helper |
| @i-scope/iscope-bridge | Win32 native helper binary (iScopeBridge.exe) |
| @i-scope/source-map-bridge | TS ↔ AJS source-map manager |
| @i-scope/vlst-parser (you are here) | Parser for VLST locals/Watch blobs |
| @i-scope/com-protocol-types | TS-mirror of COM DISPID / event constants |
License
MIT — see LICENSE.
Repository
Part of the iScope Debugger monorepo:
https://gitlab.com/i-scope/Debugger (packages/vlst-parser).
