聊聊网页断点调试及其扩展

字节前端 ByteFE 发表于 1年以前  | 总阅读数:607 次

抖音小程序开发者工具(https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/developer-instrument/overview)是面向字节系小程序开发者推出的桌面端集成开发环境,支持小程序开发、调试、预览、上传等基本功能,旨在帮助开发者更高效地开发小程序,我也是负责本地开发能力的建设。

因为工作原因最近对断点调试进行一些研究,百度了一下,遗憾的是发现网络上大部分内容都是在教学如何使用调试工具,并没有扩展到具体的细节,譬如通信逻辑,基本原理等。因此,为了尝试去弄懂一些断点调试的底层逻辑,特意去找了一些英文文档并实践。

前言

作为一个前端开发,前端调试的方式一般有如下几种:

  1. 代码中直接打印,比如很多时候直接在代码中使用 console 来打印一些变量,或者在 vscode 中使用 Turbo Console Log 等插件生成特色的日志内容。
  2. debugger,在代码中输入 debugger 关键字,然后在浏览器中进行断点调试,或者在浏览器中找到源码,然后进行断点调试。
  3. vscode 自带的 web 调试能力。

相比于 console,debugger 可以看到代码实际的执行路线以及每个变量的变化,代码可以跳着看,也可以针对某个函数步步执行。

但是 console 与 debugger 方式对代码都有侵入,在开发阶段可能要不断增加和移除来调试,如果不小心忘了,那 mr 又得打回并重新提交了…

相信很多人在提 mr 都有类似经验…

相对来说,浏览器中找到 source 源码打断点是一个更好的方式,但是还是需要打开 Devtools ,并在 sources 面板找到文件注入断点,操作上也是有点小麻烦。

因此第 3 种方式,可能是不错的方式,在 vscode 中直接在源码中调试,并能看到具体的变量信息和网页效果。

实际上,浏览器打断点与在 vscode 打断点本质原理都类似。下面就聊一聊浏览器断点调试和 vscode 断点调试的原理。

基本知识

Chrome Devtools Protocol

在了解具体场景之前,首先有一个比较重要的概念,那就是 CDP。

基本概念

CDP(Chrome DevTools Protocol)是一种通过网络协议与 Google Chrome 或其他兼容的浏览器进行通信的协议。通过 CDP,开发者可以远程控制浏览器,获取浏览器状态信息,以及执行各种浏览器操作,从而实现自动化测试、性能分析、调试等应用场景。

CDP 最早于 2011 年在 Chrome 15 版本中引入,作为 Chrome DevTools 的核心组件之一而出现。在此之前,开发者通常需要通过浏览器插件或者第三方工具来进行调试和测试,这些工具通常不够标准化和通用,也难以实现远程控制。

就跟 Emoji 的历史差不多了,都是乱的,然后规范化,最后大力发展。

CDP 的出现解决了这些问题,使得开发者可以通过标准化的协议来远程控制浏览器,获取浏览器状态信息,以及执行各种浏览器操作。CDP 的出现和发展推动了 Web 开发和测试的发展,为开发者带来了更加高效和便捷的开发和测试方式。

CDP 通过 JSON-RPC 协议来进行通信,提供了一套完整的 API,包括 DOM、CSS、网络、调试、安全等方面的接口。实际上,可以使用各种编程语言来编写 CDP 客户端,从而实现与浏览器的交互。

上图为 CDP 的官网(https://chromedevtools.github.io/devtools-protocol),可以看到,CDP 包括很多 Domains,常见的 CDP 信息包括:

  • DOM:提供了对文档对象模型的访问和操作接口,如节点遍历、样式计算、事件处理等。
  • CSS:提供了对样式表的访问和操作接口,如样式计算、应用、修改等。
  • Network:提供了对网络请求和响应的访问和操作接口,如请求拦截、修改、模拟等。
  • Console:提供了对浏览器控制台的访问和操作接口,如日志记录、错误捕获、命令执行等。
  • Debugger:提供了对浏览器调试器的访问和操作接口,如断点设置、单步执行、变量查看等。
  • Performance:提供了对浏览器性能分析的访问和操作接口,如性能指标获取、性能分析报告生成等。

这几个也是平常开发中最常用到的几个 Domains 了。

常见 CDP

  • Page:Page.navigate:页面跳转
  • Network:Network.enable:开启网络,可以用来模拟网络开闭能力
  • DOM:DOM.getDocument:获取页面树,比如调试器 Elements 面板的展示
  • CSS:CSS.getComputedStyleForNode:返回给定 nodeId 的所有样式,比如点击 dom 节点,展示 css
  • Runtime:Runtime.evaluate:在当前页面中执行 JavaScript 代码
  • Debugger:下面会提到很多,譬如 Debugger.pause/Debugger.setXXX

应用场景

chrome 的 Devtools (Front-End Devtools)与 Web Page 之间的调试也是通过 CDP 通信的,如下图所示:

除了调试,CDP 额外应用场景也很多,比如刚才提到的自动化测试,通过 CDP 模拟用户行为,操作页面元素等,或者 CDP 获取浏览器的性能指标生成性能报告,还可以通过 CDP 模拟浏览器行为,获取页面数据,实现爬虫等等。

浏览器断点调试原理

带着问题出发,可能需要搞懂以下 3 点:

  1. 页面与 Devtools 是如何通信的?
  2. 断点操作逻辑通信过程是什么?
  3. 如何实现命中断点并停止代码执行的?

操作流程

增加断点

在浏览器中,网页的调试能力是由 Devtools 提供的。Devtools 与网页之间的通信利用的是 Websocket,而通信协议则是 CDP。

除了开发中常用到的元素高亮,日志打印和网络审查,上面也提到了还可以在 sources 面板中使用 debugger。

如下图所示,找到一行 js 代码,在代码中点击断点调试,可以看到 Protocol Monitor 中有一些 CDP 消息,下面就来具体分析一下相关 CDP 信息。

为什么会发送多次,我也不理解,内容基本上是一致的。

点击断点以后,主要有以下一些 CDP 消息在页面与 Devtools 之间通信:

  • Debugger.setBreakpointsActive:Activates / deactivates all breakpoints on the page.
  • Debugger.setBreakpointByUrl:Sets JavaScript breakpoint at given location specified either by URL or URL regex.
  • Debugger.getPossibleBreakpoints:Returns possible locations for breakpoint.

setBreakpointsActive 表示告诉页面要设置一个调试断点了;setBreakpointByUrl 则是告诉页面设置的具体信息;getPossibleBreakpoints 表示设置以后获取正确的断点位置,并展示蓝色小块。

有时候可能会发现设置了某一行为断点,但是断点的位置并不是指向的位置,而是另外的位置。比如上面截图,如果在 15 行设置断点,则最后展示断点位置为 18 行。

整体流程如下图:

移除断点

除了在 sources 面板增加断点,还可以取消断点。取消断点的 CDP 非常简单, Devtools 会给 Web Page 发送一个 Debugger.removeBreakpoint 来移除断点。

实时断点调试

当点击完断点以后,页面会走到断点所在的代码位置,同时 Devtools 会接收到一些 CDP 消息,通知它当前断点的状态和上下文信息。

我写了一个实例,是关于数字的增减逻辑,并在数字增加的时候,走到断点位置(不需要刷新页面)。

可以看到,当点击 + 号以后,页面就进入断点调试逻辑,此时 Devtools 会收到 Debugger.paused消息:

  • Debugger.paused:Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria.

此时表示页面已经暂停了代码执行,Devtools 可以通过 Debugger.paused事件中的参数,获取当前断点的上下文信息,如断点所在的函数、变量值、堆栈信息等。

具体信息没有对应看

点击“Step Over next function call”(按钮 1),Devtools 会收到 Debugger.resumed rɪˈzuːm d 消息,通知继续执行代码。

  • Debugger.resumed:Fired when the virtual machine resumed execution.

随后代码跳到下一行,此时又会收到 Debugger.paused消息。

点击“Resume Script Execution” (按钮 2)按钮,Devtools 会收到 Debugger.resumed消息,如果还存在断点,则此时也会收到 Debugger.paused消息。

此外这里还有一个 Overlay.setPausedInDebuggerMessage 消息,为 Devtools 发送给页面,其信息主要是让页面展示代码停止状态下应该展示的消息,默认为 {"message":"Paused in debugger"},也就是如下图展示的内容:

除了上面两个按钮,还有几个调试按钮,如下图绿色区域内:

分别是:Step into next function call、Step out of current function、Step、Deactivate breakpoints。

  • Step into next function call:这个按钮用于进入当前行代码所在的函数内部,即单步进入函数中执行。
  • Step out of current function:这个按钮用于跳出当前函数,即单步跳出当前函数执行。
  • Step:这个按钮用于单步执行代码,即逐行执行代码。
  • Deactivate breakpoints:这个按钮用于禁用所有的断点,即暂停调试器的所有断点。

点击“Step into next function call”,Devtools 会发送 Debugger.stepInto 消息,并收到 Debugger.resumedDebugger.paused消息,进入到函数内部。

  • Debugger.stepInto:Steps into the function call.

点击“Step out of current function”,Devtools 会发送 Debugger.stepOut消息,并收到 Debugger.resumedDebugger.paused消息,跳出该函数。

点击 “Step” 按钮,Devtools 则发送 Debugger.stepInto,代码执行到下一行,每次点击,都会发送 Debugger.stepInto消息。

点击 “Deactivate (/ˌdiˈæk.tɪ.veɪt/) breakpoints”,Devtools 则发送 Debugger.setBreakpointsActive 消息。如果当前断点状态为执行状态,则参数为 active: false,同时设置蓝色小块颜色为透明色。

重新执行代码,断点调试能力失效。

再点击一次,则参数为 active: true,断点调试能力生效。

基本通信源码

了解完相关断点操作流程以后,再分析一下相关逻辑的源码。

首先,Devtools 的源码就是 Front-End Devtools,UI 上的逻辑这里就不多分析。关于页面的调试通信逻辑在 DebuggerModel 中:https://source.chromium.org/chromium/chromium/src/+/main:out/Debug/gen/third_party/devtools-frontend/src/front_end/core/sdk/DebuggerModel.js;l=280;drc=f09c12c84b39d13189a7039a05253ca3766d4751;bpv=0;bpt=0

async stepInto() {
    const skipList = await this.computeAutoStepSkipList("StepInto" /* StepInto  /);  void this.agent.invoke_stepInto({ breakOnAsyncCall: false, skipList });  }  async stepOver() {   this.#autoSteppingContext = this.#debuggerPausedDetailsInternal?.callFrames[0]?.functionLocation() ?? null;  const skipList = await this.computeAutoStepSkipList("StepOver" /  StepOver  /);  void this.agent.invoke_stepOver({ skipList });  }  async stepOut() {   const skipList = await this.computeAutoStepSkipList("StepOut" /  StepOut */);
    if (skipList.length !== 0) {
      void this.agent.invoke_stepOver({ skipList });
    } else {
      void this.agent.invoke_stepOut();
    }
  }
  pause() {
    this.#isPausingInternal = true;
    this.skipAllPauses(false);
    void this.agent.invoke_pause();
  }

很清晰的看到,上面提到的各种操作逻辑的函数,譬如 pausestepXXX等 API。

这里列举几个操作按钮通信较多的 API。

pause() 的主要逻辑为 2 点:

  1. 设置使页面断点暂停状态为 ture。
  2. 发送 Debugger.paused消息到页面。

stepInto() 的主要逻辑为:

  1. 拿到跳转的 skipList,它是一个字符串数组,用于指定要跳过的函数名称列。在操作调试按钮时,一般都是空数组。
  2. 发送 Debugger.stepInto消息到页面。

其他 API 逻辑类似。

再分析一下 chromium /ˈkroʊ.mi.əm/ 中的断点调试代码逻辑。chromium 中发送 CDP 消息到 Devtools 的逻辑在 devtools_agent_host_impl中,而断点调试逻辑在devtools_session文件中,通过 agent 的 DispatchProtocolMessage最后调用到 session 的 shoulSendOnIO函数。

具体来说,这个函数接收一个包含 CDP 方法的 span 参数,然后检查该方法是否属于一组特定的方法,如果是,则返回 true,表示该 CDP 消息需要转发。

DevToolsSession 是 Chromium 源码中的一个类,代表一个 DevTools 会话。DevToolsSession 负责管理与 DevTools 和页面之间的通信,包括上面提到的调试。

bool ShouldSendOnIO(crdtp::span<uint8_t> method) {
  static auto* kEntries = new std::vector<crdtp::span<uint8_t>>{
      crdtp::SpanFrom("Debugger.getPossibleBreakpoints"),
      crdtp::SpanFrom("Debugger.getScriptSource"),
      crdtp::SpanFrom("Debugger.getStackTrace"),
      crdtp::SpanFrom("Debugger.pause"),
      crdtp::SpanFrom("Debugger.removeBreakpoint"),
      crdtp::SpanFrom("Debugger.resume"),
      crdtp::SpanFrom("Debugger.setBreakpoint"),
      crdtp::SpanFrom("Debugger.setBreakpointByUrl"),
      crdtp::SpanFrom("Debugger.setBreakpointsActive"),
      crdtp::SpanFrom("Emulation.setScriptExecutionDisabled"),
      crdtp::SpanFrom("Page.crash"),
      crdtp::SpanFrom("Performance.getMetrics"),
      crdtp::SpanFrom("Runtime.terminateExecution"),
  };
  ...
}

可以看到,这里定义了所有发送到 Devtools 的 API。在 chromium 的各种断点调试方法,最后都会调用 DispatchToAgent方法,并走到 ShouldSendOnIO逻辑。

命中断点

通过上面的分析,了解到了调试器和页面之间的 CDP 通信内容和 API 的基本实现。那 chromium 又是如何停止代码到断点的呢?为何可以停止代码执行呢?

在 DevTools 中,停止代码执行到断点的核心实现是通过使用 V8 JS 引擎中的断点机制来实现的。当 chromium 执行到一个断点时,V8 会暂停 JS 代码的执行,并将控制权转交给 Devtools。这时候,Devtools 可以执行上述提到的断点调试的各种操作。

这块逻辑的代码在 chromium auction_v8_devtools_agentauction_v8_devtools_session 中,看起来比较复杂,涉及到 AuctionV8DevToolsSession 和 AuctionV8DevToolsAgent 两个类,我的理解是 DevtoolsAgent 提供了一些 Devtools debugger 的服务,并找到对应的 DevtoolsSession 进行通信。V8 将 ws 格式信息转交给了 DevtoolsSession,最后通过 DevtoolsAgent 发送到了 Devtools。

大概逻辑如下:

通过 Devtools Agent,负责接收 Devtools 通信信息,并将断点信息移交给 V8,然后由 V8 来对代码进行停止操作。

V8 里面的逻辑我只能看一个大概,整体逻辑如下:

V8Debugger 是一个抽象,V8DebuggerAgentImpl 类实现了这个类,它是 Debug 类和 V8 调试协议之间的中介,负责将调试消息转换为 V8 调试协议中定义的格式。

关于 V8 断点 Debugger 更底层的逻辑是与 os、cpu 相关,os 提供了系统调用来实现可执行代码的中断。

中断则是 cpu 执行下一条指令之前,关注一下中断标记,从而判断是否需要中断执行。整体逻辑上对照着 Vue 的渲染原理即可,每次事件循环结束后最后去走一次渲染 DOM。

V8 本身也是将 JS 转为可执行语言,这也就是为何 JS 可以在浏览器中拥有断点能力了。

这里涉及到一些指令操作,没有深究。

同时,V8 中断代码执行,也会提供一些环境数据到 Devtools,譬如当前变量数值等,这时候 V8 就会将这些调试信息通过 V8 Debug Protocol 协议的格式丢给 Debug,最后丢给 Devtools,从而鼠标悬浮在 sources panel 即可看到对应的数据内容。

Debugger.evaluateOnCallFrameRuntime.getProperties 可以拿到一些环境信息,前者比如一些 number 数字就可以得到。

Vscode Web 代码断点调试原理

在 Vscode 中调试代码,能让开发者专注于代码本身,一边开发运行一边断点调试查看变量信息,并减少一些脏代码的开发。如下图所示,可以看到,似乎是将浏览器的 Debugger 的逻辑照搬到了 Vscode 中。

在介绍完浏览器断点调试的逻辑以后,我们大概了解了页面与 Devtools 的通信过程和相关 CDP 信息。有了这些基础,我们再分析分析 Vscode 中是如何实现断点调试 Web 代码的。

launch.json

在 Vscode 中配置调试后,会生成一个 .vscode/launch.json 文件,其主要是配置需要调试的 url 和远程调试的端口号 port。

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "chrome",
      "request": "launch",
      "name": "针对 localhost 启动 Chrome",
      "url": "http://localhost:8080",
      "webRoot": "${workspaceFolder}"
    }
  ]
}

Debugging Architecture of VS Code

[ˈɑrkɪˌtektʃər]

Vscode 并不只是前端开发者调试 JS 使用,还可以调试其他语言,Python 一些教程就建议使用 Vscode 调试。因此 Vscode 的调试架构高度灵活,可以支持多种编程语言和调试场景,并且可以基于该架构实现各种调试扩展。

如上图,Vscode 的调试架构中,有 3 个 Core Module:

  • Debug Adapter:调试适配器是 Vscode 和具体调试目标之间的桥梁。适配器主要就是负责将调试请求转换为调试目标,并将调试目标转为调试器需要的结果,其通过 Vscode Debug Protocol 协议通信。Debug Adapter 提供了一组标准的调试接口,包括设置断点、单步执行、查看变量值等。
  • Debug Extension:调试扩展是 Vscode 内置的插件,提供特定语言或者场景的实现。比如可以调试 JS TS Python 等,同时社区也可以提供相关扩展,譬如 Java:
  • Debug UI:即 Vscode 的操作界面,它提供了调试器的各种操作和功能,例如设置断点、单步调试、查看变量值等。

:别忘了另外一个 Debugger,即为 launch.json 中的 type,指底层的调试目标,例如 Node.js 运行时、Chrome 浏览器等等。比如断点后的信息需要传递给 chrome,需要去暂定代码执行,并断点逐步执行等。

原理

在了解原理之前,先看一些现象:

  1. 当 Vscode 启动调试并走到指定断点时,Chrome 自身调试器也会走到对应的调试逻辑(Devtools 本身也是一个 ws client,任何 client 都会收到 chrome 的 cdp 消息)。
  2. 当在 Vscode 调试面板操作 StepInto 按钮时,Vscode 代码会走到下一步,同时 chrome 调试也会走到下一步。
  3. 当在 Chrome Devtools 中操作 StepInto 按钮时,Chrome Devtools 代码也会走到下一步,同时 Vscode 中代码也会跳转到下一步。

通过上面 3 种现象可以看出,Vscode Webpage Devtools 关系如下:

细品一下,这时候就可以知道为何需要 Debug Adapter 了。实际上,就是将 CDP 消息转为 DAP。

Workflow

Vscode Chrome Debug 的工作流程如下:

  1. Vscode 启动 JavaScript 调试器,并配置调试器相关的参数,例如调试类型、调试目标等等。
  2. JavaScript Debug Extension 会根据配置启动一个 Debug Adapter 进程,并向该进程发送调试请求,请求 Debug Adapter 与 Debugger 之间建立连接。
  3. Debug Adapter 进程会根据用户的配置,启动相应的 Chrome,并与对应网页(Debugger)建立连接。
  4. Debug Adapter 进程会将调试结果转换为 Vscode 支持的调试消息格式,即上面提到的 DAP,并将调试消息发送给 Vscode。

这里的核心就是 Extension,其作用就是调度与控制,比如启动 Adapter 进程,发送与接收调试信息等等,属于大 BOSS,而 Adapter 只是下属。

JS Debug Extension

上面提到,chromium 内部是使用 CDP 协议通信,因此 Extension 想要正确调试 Chrome WebPage,首先就得遵守 Chrome 的玩法。比如,在 Vscode 中点击 StepInto 按钮,这时候会将对应操作信息转化为 CDP 信息,然后再发送给 WebPage。

Extension 启动 Chrome 的逻辑在 companionBrowserLaunch 中:https://github.com/microsoft/vscode-js-debug/blob/main/src/ui/companionBrowserLaunch.ts#L50

await vscode.commands.executeCommand('js-debug-companion.launchAndAttach', {
  proxyUri: tunnel ? 127.0.0.1:${tunnel.localAddress.port} : 127.0.0.1:${args.serverPort},
  wslInfo: process.env.WSL_DISTRO_NAME && {
    execPath: process.execPath,
    distro: process.env.WSL_DISTRO_NAME,
    user: process.env.USER,
  },
  ...args,
});

另外,Devtools 与 WebPage 是通过 ws 通信的,这里 JavaScript Extension 内部实现与开发者工具调试器和模拟器的通信相似, Extension 与 WebPage 通信也是拿到了页面的 debug ws url,在 Extension 内部创建一个 ws client,通过该 client 监听来自于 WebPage CDP 信息,并转发到会话的 Adapter,最后再交给 Vscode。

看最新的代码,JS Debug Extension 也会负责部分调试 UI 相关逻辑。

Command 实例

StepInto举例,在 Vscode 中点击该按钮以后,会发送一个 DAP 消息:

{
    "command": "stepInTo",
    "seq": number,
    "type": "request",
    "arguments": {
        "threadId": number
    }
}

然后,Exetension 将该消息转为 CDP 消息,并发送给 WebPage:

{
    "id": 1,
    "method": "Debugger.stepInto",
    "params": {
        "callFrameId": number/string
    }
}

WebPage 收到该消息后,返回执行结果到 Extension:

{
    "id": 1,
    "result": {}
}

Extension 再将该 response 通过 Debug Adapter 转给 Vscode,Vscode 调整 UI:

{
  "body": {
      "reason": "OK",
      "threadId": number
  },
  "type": "response"
}

相关 DAP 格式可以在 debug-adapter-protocol 查阅:https://microsoft.github.io/debug-adapter-protocol/overview

如果要在 Vscode 中查看实时的 DAP 和 CDP 消息,可以通过如下操作:

源码调试

上面给到的例子非常简单,js 代码也没有经过构建生成编译后的代码。但是实际场景中开发的项目会引入各种开源库,然后经过诸如 Webpack 等打包构建工具做编译打包,才能在浏览器中运行。编译压缩后的代码一般不具备可读性,因此在编译后代码进行调试成本比较高。

We all know,SourceMap 存储着源码和生产代码之间的映射关系。譬如我这里启动了一个 Vite 项目:

当我在源码的 main.ts 中设置断点时,可以看到 Request 中的 url 为 host:port/src/main.ts,即实际传给 WebPage 的断点文件为编译后的文件。

JS Debug Extension 亦是如此。

当在 Vscode 的源码中增加了一个断点,JS Debug Extension 会根据 sourceMap 将源代码路径映射到编译后的代码路径中,并将这个信息发送给浏览器。

所以呀,解析是前端行为。

扩展:SourceMap 加载

SourceMap 虽然也是静态资源,但是其加载在 Network 面板并不能看到,而是在 Developer Resources 中。

为了启动快,我用的 Vite 来生成项目。Vite 利用了浏览器原生的 ES modules 功能,根据文件依赖关系,生成依赖树,然后各模块文件模块单独加载。Vite 文件都有单独的 SourceMap,不需要配 SourceMap 依赖。

可以看到,这里 Vite 默认是直接内嵌的 SourceMap,无需单独请求, 可以在代码文件加载完成后,就直接解析了,红框里面展示的链接就是 Base64 的形式了。

⚠️SourceMap 的解析是交给 Devtools 本身的,Debugger 只负责运行和暂停。因此,如果断点在 SourceMap 解析完成之前触发,则没法告诉 Debugger 正确的地址,可能会出现断点无效情况。

IDE 小程序断点调试

Devtools Debug

根据上面的介绍,小程序断点调试的最简单办法就是在代码中写上 debugger,然后交给 v8 处理即可。另外还有一种方式就是打开小程序调试器,在 sources panel 中打断点,如下图:

打断点,刷新小程序,即可跳转到断点位置。此时可以看到对应的 CDP 消息中的 Request。

可以看到,这里点击的是 56 行,但实际上 Request 中却不是,Devtools 通过 sourceMap 进行了处理,定位到了 64 行。根据上面提到的源码调试逻辑,这里的位置为编译后的代码位置,找到编译产物代码 app.js 即可看到 real position。

IDE Editor Debug???

考虑到上面提到的 Vscode 有 web 断点调试能力,那 IDE Editor 或许也是可以支持断点调试能力的。

Vscode 可以直接在编辑器运行项目,然后启动自定义的调试目标(Debugger)。

IDE 为小程序运行时的载体,与 Vscode 启动 web 项目不一样,其逻辑为编译完成后生成一个编译产物目录,通过静态服务,Simulator 直接加载对应编译产物。因此,IDE 的 Editor 实际上跟 Simulator 没什么联系的。

假设借用 Devtools Debug 的逻辑,当在 Editor 打断点时,捕获所有的断点 DAP 消息,当开启调试时,刷新模拟器,将所有的断点信息转为 CDP 信息发送给模拟器,或许就可以简单实现该能力。

当然,考虑到是在源码中打断点,这里的难点应该是在于要实现 sourceMap 解析,而 Debug UI 则可以利用 Vscode JS Extension,或者通过自定义实现一个 Debug UI。

总结

本文从抖音开发者工具支持断点调试能力需求引入,概述了浏览器断点调试的基本原理,也介绍了 Vscode Web 代码断点调试能力,详细介绍了各模块中各 CDP 消息通信逻辑。阅读本文可以掌握前端各种调试方法的基本原理。

参考文档

  • [1] V8 本地调试: https://zhuanlan.zhihu.com/p/568432229
  • [2] Debugging over the V8 Inspector Protocol: https://v8.dev/docs/inspector
  • [3] Adapter Debug Protocol: https://microsoft.github.io/debug-adapter-protocol/
  • [4] SourceMap: https://zhuanlan.zhihu.com/p/615279891
 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237228次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8063次阅读
 目录