npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@i-scope/iscope-bridge

v0.3.2

Published

Win32 npm distribution of iScopeBridge.exe (JSON-RPC stdio → Oscilloscope COM). Not a Node.js library: no main entry — use @i-scope/iscope-bridge-client from TypeScript.

Readme

packages/iscope-bridge/ — iScopeBridge.exe, JSON-RPC міст до Oscilloscope.exe COM

npm version npm downloads License: MIT Platform: Win32

Part of the @i-scope/debugger SDK — один із семи leaf-пакетів, що агрегуються мета-umbrella @i-scope/debugger. Цей npm-пакет — це binary-tarball з готовим iScopeBridge.exe (Win32 native). Більшість користувачів НЕ ставлять його напряму — він приходить транзитивно через @i-scope/iscope-bridge-client (а той — через @i-scope/dap-adapter, @i-scope/mcp-server, або через meta @i-scope/debugger). Прямий npm install @i-scope/iscope-bridge має сенс лише коли треба прицільно винести бінарник на диск (CI artefact pinning, redistributable bundle для не-Node хоста, тощо).

Standalone C++ ATL-додаток (~150-200 KB, нуль runtime-залежностей), який виступає мостом між IDE-клієнтами (@i-scope/iscope-bridge-client) і Oscilloscope.exe. Спілкування з клієнтами — через JSON-RPC 2.0 over Content-Length framed stdio.

Архітектура

IDE client                              iScopeBridge.exe                       Oscilloscope.exe
─────────────────────                  ─────────────────────                  ─────────────────────
@i-scope/iscope-bridge-client         Main.cpp                              ScopeAppControl COM
  IScopeBridge (EventEmitter) ──────►  wmain → "serve" subcommand            ScopeAppDbgCtrl COM
                                       ↓                                      ↑
  child_process.spawn ◄─stdin/stdout─► JsonRpc (CL framing + reader thread)  │
  Content-Length frames                ↓                                      │
                                       Server.cpp (8 method handlers)        │
                                       ↓                                      │
                                       ComBridge.cpp ──────CoCreateInstance──┤
                                       ↓                  IDispatch::Invoke  │
                                       DispatchSink ◄──IConnectionPoint──────┘
                                       (events: trace/stop/break/error)

Threading у helper.exe:

  • Main thread = STA COM thread: CoInitializeEx(COINIT_APARTMENTTHREADED), тримає всі IDispatch хендли, виконує Invoke, обробляє sink callbacks через message pump (GetMessage/DispatchMessage).
  • Reader thread: блокується на ReadFile(stdin), парсить framed JSON, посилає WM_JSONRPC_REQUEST через PostThreadMessage у main thread.
  • Stdout writes серіалізуються через CRITICAL_SECTION (sink-нотифікації + responses + diagnostic-помилки можуть конкурувати).

Verifying the bundled binary

The npm tarball ships both the pre-built iScopeBridge.exe (bin/Win32/Release/) and its full C++ source (src/*.cpp, src/*.h, iScopeBridge.vcxproj, iScopeBridge.sln, scripts/run-msbuild.cjs). This lets any consumer audit the binary end-to-end without leaving npm:

  1. Inspect what is in the tarball. On npmjs.com click "Code" tab on the package page, or run locally:

    npm pack @i-scope/iscope-bridge --dry-run
  2. Check the binary's PE architecture & published hash. The bundled binary is 32-bit Windows x86 (PE machine 0x014C = IMAGE_FILE_MACHINE_I386). Architecture match with the 32-bit Oscilloscope.exe is not strictly required — the bridge talks to Oscilloscope as a CLSCTX_LOCAL_SERVER (out-of-process) COM client, and Windows transparently cross-arch-marshalls IDispatch calls through the DCOM proxy/stub infrastructure (the OLEAUT32.DLL universal IDispatch_RemoteInvoke marshaller handles it for free). Existence proof: the upstream Oscilloscope.exe debugger plugin ships as a x64 Notepad++ plugin and drives the same ia32 COM surface without issue. We stay on ia32 for two pragmatic reasons:

    • Diagnostic simplicity — ProcMon / Spy++ / OleView see helper and Oscilloscope identically (same bitness in all tools), no "open the other OleView" dance.
    • Smaller resident set — ia32 helper is ~50% lighter on pointer-heavy data structures than the x64 equivalent (saves ~5–10 MB RSS for a long-lived debug helper).

    Verify locally:

    $bin = "node_modules\@i-scope\iscope-bridge\bin\Win32\Release\iScopeBridge.exe"
    Get-FileHash $bin -Algorithm SHA256
    # SHA256 of the published binary is recorded in CHANGELOG.md
    # under the matching version heading.
    
    $pe = [System.IO.File]::ReadAllBytes($bin)
    $off = [System.BitConverter]::ToInt32($pe, 0x3C)
    $mach = [System.BitConverter]::ToUInt16($pe, $off + 4)
    "MachineType: 0x{0:X4}" -f $mach  # expect 0x014C (ia32)
  3. Rebuild from source and compare. With Visual Studio 2017+ Build Tools (v141 toolset + Win10 SDK 19041 + Static ATL), the in-tarball source can be rebuilt one-command and SHA-compared:

    cd node_modules\@i-scope\iscope-bridge
    node scripts\run-msbuild.cjs            # invokes MSBuild via vswhere
    Get-FileHash bin\Win32\Release\iScopeBridge.exe -Algorithm SHA256

    Note: MSBuild Release builds with /GL (whole-program optimisation) and /LTCG:incremental are not byte-stable across machines (PE timestamp, build-id, link-pass ordering all vary). Hash equality after a local rebuild is therefore not the assertion to make. The assertion is: "the published binary is a faithful build of the in-tarball source" — established by inspecting source + building it + running the resulting binary against the JSON-RPC methods listed below.

  4. Authenticode signature. The bundled binary is Authenticode-signed. Verify locally:

    $bin = "node_modules\@i-scope\iscope-bridge\bin\Win32\Release\iScopeBridge.exe"
    Get-AuthenticodeSignature $bin
    # Expect: Status = Valid

Subcommands

| Команда | Призначення | | --- | --- | | iScopeBridge.exe | smoke test (default): GetStatus, OpenFile, Stop + registration probe | | iScopeBridge.exe open <path.mwf> | завантажити .mwf один раз і вийти (для clean experiments) | | iScopeBridge.exe run <path.mwf> <path.ajs> | повний цикл: open + advise sink + ExecuteFile + pump до STOP | | iScopeBridge.exe serve | JSON-RPC server mode — основний режим для розширення |

JSON-RPC методи (server-handled)

Усі параметри — UTF-8 JSON. ID-цілочисельні. Wire-формат — Content-Length-framed.

| Метод | Params | Result | Помилки | | --- | --- | --- | --- | | initialize | {autoLaunch?: bool, oscPath?: string} | {server, version, connected: bool, weLaunched: bool, pid: int} | -32000 ComError | | shutdown | {closePolicy?: 'never'\|'ifWeLaunched'} | {closed: bool} (потім helper закривається) | — | | getStatus | {} | {status: int, name: "Idle"\|...} | -32001 NotConnected | | openFile | {path: string} | {ok: bool} | -32002 FileNotFound, -32602 InvalidParams | | executeFile | {file: string, breakpoints?: string} | {ok: bool} (потім дивись notif dbg/*) | -32002 FileNotFound, -32000 ComError | | setBreakpoint | {line: int, set: bool} | null | -32602 InvalidParams | | resumeExec | {action: int} (STEPACT_*) | null | -32602 InvalidParams | | getStackContent | {req: int, list: string} | {content: string} (VLST raw BSTR) | -32000 ComError | | ping | будь-що | echoes params back | — |

JSON-RPC notifications (server-pushed)

| Метод | Params | Тригер | | --- | --- | --- | | dbg/breakpointErrors | {positions: string} | DBGEID_BRKPNT_ERR_LST (1) | | dbg/breakHit | {line: int, col: int, reason: int} | DBGEID_BRKEXECUTION (2) | | dbg/error | {line: int, col: int, info: string} | DBGEID_ERROR (3) | | dbg/stop | {} | DBGEID_STOP (4) | | dbg/trace | {level: int, text: string} | DBGEID_TRACE (5) |

line/col уже 1-based (server віддає 0-based, helper нормалізує).

Приклади

Клієнтський API — @i-scope/iscope-bridge-client:

import { IScopeBridge, resolveHelperPath } from '@i-scope/iscope-bridge-client';

const br = new IScopeBridge({ helperPath: resolveHelperPath() });
await br.start();
await br.initialize();

br.on('trace', e => console.log(`[${e.level}] ${e.text}`));
br.on('stop',  () => console.log('script done'));
br.on('error', e => console.log(`error at ${e.line}:${e.col}: ${e.info}`));

await br.openFile({ path: 'C:\\Oscillograms\\test.mwf' });
await br.executeFile({ file: 'C:\\scripts\\analyzer.ajs' });

Edge-cases та фіксації

  1. Boolean-результат OpenFile/ExecuteFile ненадійний. false повертається і на успіх теж. Перевіряти стан через getStatus або побічні ефекти (отримання dbg/trace).
  2. Невалідний шлях файлу блокує COM-thread на модальному діалозі. Helper.exe валідує шлях через GetFileAttributesW перед Invoke і повертає JsonRpc::FileNotFound (-32002).
  3. ExecuteFile 2-й BSTR-параметр — L"", не nullptr. NULL-BSTR через DEC marshaler давав RPC_E_SERVERFAULT.
  4. IDispatch::Invoke для multi-arg методів — rgvarg[] у зворотному порядку оголошення параметрів. Загорнуто в ComBridge::InvokeMethod(disp, dispid, BSTR a, BSTR b, ...).
  5. DBGEID_ERROR не спрацьовує для звичайних runtime-помилок та throw у скрипті. Лише DBGEID_STOP. Для виявлення помилок робити polling getStatus після dbg/stop — якщо GSTID_Error (4), помилка була.
  6. Sink тримається advised увесь час між executeFile викликами — для зменшення ризику втратити marshaling proxies. Розривається лише при shutdown.
  7. Реєстрація COM-об'єктів — REGCLS_MULTIPLEUSE. Реконнект після Stop працює без перезапуску Oscilloscope.exe.
  8. Початкові breakpoints задає executeFile.breakpoints — comma-separated list of line numbers. setBreakpoint перед executeFile не реєструє breakpoint. setBreakpoint працює під час паузи (динамічне додавання і зняття).

Oscilloscope lifecycle

Helper також керує процесом Oscilloscope.exe за принципом ownership-based lifecycle: закриває лише те, що сам запустив. Зовнішньо запущений Oscilloscope (через Start menu, інший плагін, попередній сеанс helper-а) у безпеці.

Стейт у Server:

| Поле | Значення | | --- | --- | | oscProc_ | HANDLE запущеного процесу (nullptr якщо ми не запускали або вже закрили) | | oscPid_ | PID Oscilloscope.exe (заповнюється завжди при connected=true, навіть для зовнішнього процесу) | | weLaunched_ | true лише якщо саме цей сеанс helper-а запустив Oscilloscope (через autoLaunch=true коли FindRunningOscilloscope() повернув 0) |

Параметри initialize:

{ "autoLaunch": true, "oscPath": "C:\\Program Files (x86)\\USB Oscilloscope v5\\Oscilloscope.exe" }
  • autoLaunch: false (default) — helper тільки приєднується до існуючого процесу. Якщо Oscilloscope не запущений — ComError.
  • autoLaunch: true — helper викликає FindRunningOscilloscope(). Якщо повернуло 0, запускає вказаний oscPath через CreateProcess і чекає до 15 с поки COM-class objects зареєструються (CoCreateInstance поллінгом кожні 250 мс). При успіху weLaunched_ = true. Якщо Oscilloscope вже існує — weLaunched_ = false.
  • oscPath — опційно, default = стандартний v5-шлях.

Result envelope initialize:

{ "server": "iScopeBridge", "version": "0.1.0", "connected": true, "weLaunched": true, "pid": 12345 }

Параметри shutdown:

{ "closePolicy": "ifWeLaunched" }

| Політика | Поведінка | | --- | --- | | "never" | Не торкається Oscilloscope взагалі. Навіть наш власний процес залишиться живим — корисно для діагностичних сеансів, де користувач хоче подивитися на стан Oscilloscope після виходу з helper. | | "ifWeLaunched" (default) | Якщо weLaunched_ === true — PostMessage(WM_CLOSE) всім top-level вікнам процесу + WaitForSingleObject(5s) + fallback TerminateProcess. Інакше нічого не робить. | | "always" | Не підтримується. |

Result envelope shutdown:

{ "closed": true }

closed: true означає, що Oscilloscope був реально закритий цим викликом. false — або ми не власник, або політика заборонила, або процес уже не існує.

Тестові сценарії:

  • A: auto-launch + auto-close — pre: Oscilloscope killed; init({autoLaunch:true}) ⇒ weLaunched=true; shutdown({ifWeLaunched}) ⇒ closed=true; pid disappears within 8 s.
  • B: attach + protect — pre: Oscilloscope started externally; init({autoLaunch:true}) ⇒ weLaunched=false; shutdown({ifWeLaunched}) ⇒ closed=false; pid still alive after 3 s.

Структура файлів

iScopeBridge.vcxproj    Win32, v141, Win10 SDK 19041, /MT, static ATL, console subsystem
iScopeBridge.sln
src/
  Constants.h           CLSIDs, IIDs, DISPIDs, enums
  ComBridge.{h,cpp}     CoCreateInstance + InvokeMethod overloads (0/1/2 BSTR + raw N-arg)
  DispatchSink.{h,cpp}  IDispatch sink, manual switch DISPID 1..5, refcount, IID_IScopeAppDbgEvents
  Json.{h,cpp}          мінімальний JSON parse/build (ne vendor lib)
  JsonRpc.{h,cpp}       Content-Length framing + reader thread + serialized stdout
  Server.{h,cpp}        8 method handlers + 5 sink-to-notification adapters + process lifecycle
  ProcLifecycle.{h,cpp} FindRunningOscilloscope + LaunchAndAwaitCom (retry) + GracefulClose
  Main.cpp              wmain з 4 subcommands
bin/Win32/{Release,Debug}/iScopeBridge.exe

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 (you are here) | Win32 native helper binary (iScopeBridge.exe) | | @i-scope/source-map-bridge | TS ↔ AJS source-map manager | | @i-scope/vlst-parser | Parser for VLST locals/Watch blobs | | @i-scope/com-protocol-types | TS-mirror of COM DISPID / event constants |

License

MIT — see LICENSE.