ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

使用 hcdp 调试 Hermes:CDP 调试工具的架构解析与实战指南

使用 hcdp 调试 Hermes:CDP 调试工具的架构解析与实战指南 语言运行时编译器移动开发【免费下载链接】hermesA JavaScript engine optimized for running React Native.项目地址https://gitcode.com/gh_mirrors/hermes/hermes点击查看免费下载导读hcdpHermes CDP是 Hermes 仓库中一个独立的命令行调试工具它把 Hermes 引擎的 CDPChrome DevTools Protocol调试能力包装成一个可直接运行的进程用户既可以用它调试本地的 JavaScript 脚本也可以借助 Chrome / Edge DevTools 界面进行可视化调试。本文以 tools/hcdp/README.md 为核心结合 tools/hcdp/hcdp.cpp、tools/hcdp/hcdp.js 等源码完整讲解 hcdp 的构建、运行方式、双组件架构与 IPC 消息协议帮助你快速上手并理解 Hermes CDP 调试链路的工作原理。一、hcdp 是什么Hermes 是一个针对 React Native 场景优化的 JavaScript 引擎其调试能力基于 CDPChrome DevTools Protocol实现。hcdp正是围绕这一能力打造的命令行工具它的核心目标是把“Hermes 运行时 CDP 调试 API 调试客户端”串成一条可独立运行的调试链路它承载一个真实的 Hermes Runtime并执行你指定的 JS 脚本它对外暴露一个 WebSocket 服务接收调试客户端如 Chrome DevTools发来的 CDP 消息它把 CDP 消息转化为内部 IPC 消息交给 C 组件中的 CDP Agent 处理再将 Agent 产生的响应与通知转发回客户端。从源码结构看整个工具由两大部分组成hcdp.cppC 组件负责运行时与调试内核和hcdp.jsJavaScript 组件负责网络与交互二者通过标准输入输出上的行式 IPC 协议通信详见 tools/hcdp/ 目录。二、快速上手构建与运行1. 构建 hcdp 二进制进入tools/hcdp目录后使用 BUCK 或 CMake 构建hcdp可执行文件。CMake 构建入口为 tools/hcdp/CMakeLists.txt它依赖仓库根目录的 CMakeLists.txt 中定义的add_hermes_tool与hermesvm_a目标。值得注意的是构建行为与HERMES_ENABLE_DEBUGGER编译选项强相关若该选项未开启构建出的hcdp只是一个打印提示后以失败退出的占位程序stub源码见 tools/hcdp/hcdp.cpphcdp compiled without Hermes debugger enabled.若该选项开启才会编译完整的调试实现并链接hermesvm_a静态库。同时 CMake 会强制为hcdp打开 RTTI 与异常支持set(HERMES_ENABLE_RTTI ON)、set(HERMES_ENABLE_EH ON)并为JSONHelpers.cpp单独附加-fno-exceptions -fno-rttiMSVC 下对应/EHs-c- /GR-编译选项以隔离差异见 tools/hcdp/CMakeLists.txt。构建产物默认通过install(TARGETS hcdp RUNTIME DESTINATION bin)安装到bin目录。2. 安装 npm 依赖JavaScript 组件依赖ws、chrome-launcher、chromium-edge-launcher三个包声明见 tools/hcdp/package.json在tools/hcdp目录下执行npm install3. 运行运行hcdp.js依次传入两个参数hcdp二进制的路径以及待调试脚本的路径。例如node ./hcdp.js ~/hcdp ~/loop.js其中~/hcdp指向构建好的hcdp二进制~/loop.js是你要调试的脚本。hcdp.js在启动时会做参数与文件存在性校验缺少参数会打印Usage: node path to hcdp binary path to script to debug并退出路径非法会分别报Binary not found at .../Script not found at ...见 tools/hcdp/hcdp.js。校验通过后它会以子进程方式拉起 C 二进制并把脚本内容读入内存备用。启动成功后终端会打印提示按下o键会用本机 Chrome或 Edge打开 DevTools 界面按下x键退出。也可以直接访问提示中给出的 URL其形式为https://chrome-devtools-frontend.appspot.com/serve_file/devtools版本/js_app.html?ws127.0.0.1%3A9999可见调试端口固定为9999DevTools 前端版本号定义在 tools/hcdp/hcdp.js浏览器启动依赖chrome-launcher/chromium-edge-launcher若两者都不可用则抛出“Supported browsers: Google Chrome, Microsoft Edge”的错误。三、整体架构双组件协作原文档明确给出了工具的两个组成部分这里结合源码进一步展开其职责边界组件文件职责C 组件tools/hcdp/hcdp.cpp、tools/hcdp/IPC.cpp、tools/hcdp/JSONHelpers.cpp通过 Hermes API 承载调试会话所需对象Hermes Runtime、CDP Debug API、CDP Agent从 stdin 接收 IPC 消息按需创建/销毁 CDP Agent 或处理消息把 Agent 产生的响应与通知通过 stdout 以 IPC 消息发出JavaScript 组件tools/hcdp/hcdp.js启动 WebSocket 服务与调试客户端通信原样打印流经的 CDP 消息处理用户键盘输入在客户端与 C 组件之间做消息格式转换消息流转方向是双向的客户端 → JS → C调试客户端通过 WebSocket 发送 CDP 消息hcdp.js将其封装成 IPC 消息写入子进程 stdinC 组件解析后交给对应 CDP Agent 处理C → JS → 客户端CDP Agent 产生的响应与通知由 C 组件写到 stdouthcdp.js逐行解析、转发回 WebSocket 客户端并同步打印到终端。四、C 组件运行时与 CDP Agent 管理1. RuntimeInstance承载可调试的 Hermes 运行时hcdp/hcdp.cpp 中的RuntimeInstance类负责在一个独立线程上运行待调试脚本其构造过程清晰地展示了 Hermes 调试 API 的标准用法用fbhermes::makeHermesRuntime(...)创建运行时配置中显式开启了采样性能分析withEnableSampleProfiling(true)调用cdp::CDPDebugAPI::create(*runtime_)为运行时挂接 CDP 调试接口这是之后创建 CDP Agent 的前提注入console.log通过 JSI 的Object/Function::createFromHostFunction构造宿主函数把参数收集后以cdpDebugAPI-addConsoleMessage(...)上报为 CDP 控制台消息类型为ConsoleAPIType::kLog并附带当前调用栈hermesRt.getDebugger().captureStackTrace()这样 DevTools 的 Console 面板才能看到脚本输出通过SerialExecutor将runtime_-debugJavaScript(source, url, flags)排入运行时线程执行保证脚本执行与调试任务串行化。析构顺序同样讲究先销毁 executor 等待任务结束再依次销毁 CDP Debug API 与运行时。2. debugScriptIPC 事件循环与 Agent 生命周期hcdp/hcdp.cpp 的debugScript是 C 侧的主循环结构为while (std::optionalIPCCommand ipc receiveIPC())对三类 IPC 消息分别处理CConnect为clientID创建新 Agent调用cdp::CDPAgent::create(...)并传入两个关键回调运行时任务回调把 CDP 内部产生的、需要独占运行时执行的任务通过RuntimeInstance::addTask排到运行时线程确保“在两次 JS 执行间隙”执行出站消息回调把 Agent 产生的响应/通知封装为M类型 IPC 消息发回 stdout。MMessage从agents表按clientID查找 Agent把客户端消息解析为message::Request后交给agent-second-handleCommand(...)处理若找不到对应 Agent 则抛出No such agent。DDisconnect从agents表移除并销毁该客户端对应的 Agent。3. 两个值得注意的实现细节executionContextCreated通知的拦截注入。为了让 DevTools 的 Console 面板正常工作运行时必须发出Runtime.executionContextCreated通知。hcdp 的实现方式是当收到客户端的Runtime.enable命令时记录其消息id见 tools/hcdp/hcdp.cpp随后在出站消息回调里若发现某条响应的id恰好等于该记录值就紧接着补发一条Runtime.executionContextCreated通知desc.name main执行上下文 id 由全局计数器nextExecutionContextId分配再转发原响应见 tools/hcdp/hcdp.cpp。响应id的提取由 tools/hcdp/JSONHelpers.cpp 的getResponseId完成它借助 Hermes 自身的JSONParser与valueFromJsonlong long解析。stdout 缓冲处理。main入口调用setbuf(stdout, nullptr)关闭输出缓冲避免大体积输出例如性能分析结果被积压在缓冲区见 tools/hcdp/hcdp.cpp。五、IPC 消息协议C 与 JavaScript 组件之间的通信采用行式文本协议定义于 tools/hcdp/IPC.h 与 tools/hcdp/IPC.cpp。每条消息由三部分组成字段说明取值type消息类型单个字符C/M/DagentId源码中为clientID目标 Agent 的唯一数字 ID类型为uint32_t非负整数message可选的 CDP 消息体JSON 字符串C与D时留空三种消息类型的语义如下沿用原文档定义C— Connect连接。agentId表示要创建的新 Agent 的唯一 IDmessage不使用。对应源码常量kConnectIPCType C。M— Message消息。agentId表示此前已创建、应处理message的那个 Agent。对应kMessageIPCType M。D— Disconnect断开。agentId表示要销毁的 Agent 的 IDmessage不使用。对应kDisconnectIPCType D。线格式示例C 侧发送见 tools/hcdp/IPC.cppM3{id:5,method:Debugger.enable}即type紧随agentId随后是消息体若无消息体则省略最后以换行符\n结束整条 IPC 消息。解析侧tools/hcdp/IPC.cpp先std::getline读一行再用istringstream依次提取type与agentId行尾剩余部分作为message。JavaScript 侧的发送函数与之一一对应sendConnectIPC/sendMessageIPC/sendDisconnectIPC最终都调用sendIPC(type, clientId, message)拼出typeclientIdmessage\n写入子进程 stdin见 tools/hcdp/hcdp.js。六、JavaScript 组件WebSocket 服务与消息桥1. WebSocket 服务与客户端管理hcdp.js使用ws库在9999端口启动 WebSocket 服务tools/hcdp/hcdp.js。每个客户端连接会获得一个自增的数字 IDclientIdCounter并立即向 C 组件发送C连接 IPC收到客户端消息则发送M消息 IPC连接关闭则发送D断开 IPC同时清理本地clients表tools/hcdp/hcdp.js。因此该服务天然支持多个调试客户端同时连接每个客户端对应一个独立的 CDP Agent。2. stdout 行解析与消息转发C 组件通过 stdout 输出两类内容IPC 消息与脚本自身的输出。hcdp.js按行累积缓冲lineBuffer对每一行定位首个{若无则视为脚本输出直接打印到终端首字符必须是M即messageIPCType否则也视为普通输出打印解析M与{之间的数字作为clientID做合法性校验非数字、越界、客户端已断开等情况都有对应处理——例如客户端在 CDP 消息到达前就已断开时会直接跳过该消息对剩余 JSON 做JSON.parse校验非法消息抛出Malformed message转发给对应 WebSocket 客户端并记录日志tools/hcdp/hcdp.js。3. 本地拦截Debugger.getScriptSource一个典型的“JS 侧智能”是当客户端请求Debugger.getScriptSource获取脚本源码时hcdp.js并不把它转发给 C而是直接在本地生成响应——因为脚本源码本来就是由hcdp.js自己读入内存的。实现方式为监听Debugger.scriptParsed通知记录当前脚本的scriptIdinspectScriptParsed收到getScriptSource请求时若请求的scriptId匹配则返回result.scriptSource否则返回-32602Invalid params错误tools/hcdp/hcdp.js。这既减少了 IPC 往返也避免把整个脚本源码通过子进程管道传回。4. 终端交互与事件日志hcdp.js将进程 stdin 设为 raw 模式实现两键快捷键o打开 DevTools、x退出并杀掉子进程tools/hcdp/hcdp.js。终端日志以“图标 客户端 ID 消息”的格式打印所有流经事件图标含义如下图标含义⚡客户端连接connect→客户端发来的命令command from client←发往客户端的响应/通知response/notification to client✕客户端断开disconnect七、CDP Agent 与调试 API 的源码依据hcdp 依赖的调试内核位于 API/hermes/cdp/CDPDebugAPI管理运行时级调试状态CDPDebugAPI::create以 Hermes 运行时为参数创建hcdp 在RuntimeInstance构造时调用见 API/hermes/cdp/CDPDebugAPI.hCDPAgent处理 Debugger、Runtime、Profiler、HeapProfiler 域的 CDP 消息。其公开接口CDPAgent::create(executionContextID, cdpDebugAPI, enqueueRuntimeTaskFunc, messageCallback, state)与 hcdp 的调用方式完全对应API/hermes/cdp/CDPAgent.h注释明确要求集成方维护一个“独占访问运行时”的任务队列即 hcdp 中SerialExecutoraddTask的职责来源。handleCommand(std::string json)可被任意线程调用这与 hcdp 在 IPC 主循环中直接调用它相印证。此外hcdp 使用的消息类型如message::Request::fromJson、Runtime.executionContextCreated由 API/hermes/cdp/MessageTypes.h 等头文件定义JSON 解析则复用 Hermes 自身的 lib/Parser/JSONParser.cpp。八、小结与适用场景通过本文可以梳理出 hcdp 的完整工作链条调试客户端(Chrome/Edge DevTools) │ WebSocket (127.0.0.1:9999) ▼ hcdp.jsWebSocket 服务、日志、键盘交互、脚本源码本地应答 │ IPC 行协议stdin/stdoutC/M/D agentId message ▼ hcdp.cppHermes Runtime CDPDebugAPI 每客户端一个 CDPAgent │ debugJavaScript 执行脚本 ▼ 待调试的 JS 脚本hcdp 的适用场景包括快速验证 Hermes 的 CDP 调试行为、在没有完整 React Native 宿主环境的情况下调试单个 JS 脚本、以及作为研究 Hermes 调试 APICDPDebugAPI/CDPAgent/debugJavaScript如何集成的参考实现。需要特别说明的是hcdp是仓库tools目录下的独立开发调试工具若需在应用内集成 CDP 调试官方路径仍是直接使用 API/hermes/cdp/ 中的公开 API可参考 API/hermes/DebuggerAPI.h 与 API/hermes/cdp/CDPAgent.h 的接口注释。赞分享语言运行时编译器移动开发【免费下载链接】hermesA JavaScript engine optimized for running React Native.项目地址https://gitcode.com/gh_mirrors/hermes/hermes点击查看免费下载相关推荐NumPy 高级调试工具实战指南Python 调试构建、Valgrind、C 调试器与编译器 SanitizerNumPy 高级调试工具实战指南Python 调试构建、Valgrind、C 调试器与编译器 Sanitizer 导读 本文是 NumPy 开发者文档中 de科学计算数据分析Chokidar 如何做到事件不重复触发文件监听 5 层节流去重机制完整指南Chokidar 如何做到事件不重复触发文件监听 5 层节流去重机制完整指南 Chokidar 是 Node.js 生态中最流行的跨平台文件监听file w开发工具Koop核心功能解析从数据转换到FeatureServer查询的完整流程Koop核心功能解析从数据转换到FeatureServer查询的完整流程 Koop是一个强大的JavaScript工具包专为在Web上转换、查询和下载地理空创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表