debugger & sourcemap

277 阅读2分钟

1、调试原理

类型原理
编译型cpu 里面有 4 个寄存器可以做硬中断,操作系统提供了系统调用来做软中断。通过机器码替换成 0xcc (INT 3)是把程序断住了,需要释放断点的时候再换原来的机器码
解释型插入一段代码来断住,支持环境数据的查看和代码的执行

比如 js 中支持 debugger 语句,当解释器执行到这一条语句的时候就会断住

2、devtools

image.png

组成作用
frontend连接debugger server(websocket),绘制ui展示
cdpsocket传递的信息格式
backend起debugger server,环境信息和脚本执行能力通过socket传递出去
  • frontend
npm install chrome-devtools-frontend@1.0.672485

可通过live server插件打开devtools_app.html,后面加上 ws=localhost:8080 的参数

const ws = require('ws'); 
const wss = new ws.Server({ port: 8080 }); 
wss.on('connection', function connection(ws) { 
  ws.on('message', function message(data) { 
    console.log('received: %s', data); 
  }); 
});

自己实现 CDP 的交互还是挺麻烦的,chrome 给提供了一个工具包 chrome-remote-interface

3、vue devtools

Vue DevTools 和 React DevTools 就是自己定制的一套协议

image.png

4、sourcemap

sourcemap 是关联编译后的代码和源码的,通过一个个行列号的映射。

{
    version : 3,
    file: "out.js",
    sourceRoot : "",
    sources: ["foo.js", "bar.js"],
    names: ["a", "b"],
    mappings: "AAgBC,SAAQ,CAAEA;AAAEA",
      sourcesContent: ['const a = 1; console.log(a)', 'const b = 2; console.log(b)']
}

file 是文件名,sourceRoot 是源码根目录,names 是转换前的变量名,sources 是源码文件,sourcesContent 是每个 sources 对应的源码的内容,mappings 就是一个个位置映射

  • 一个 bundle.js 就对应了 n 个 sources 源文件
  • mappings 部分是通过分号; 和逗号 , 分隔的:一个分号就代表一行,然后每一行可能有多个位置的映射,用 , 分隔
  • 比如 AAAAA 一共五位,分别有不同的含义:

转换后代码的第几列(行数通过分号 ; 来确定)
转换前的哪个源码文件,保存在 sources 里的,这里通过下标索引
转换前的源码的第几行
转换前的源码的第几列
转换前的源码的哪个变量名,保存在 names 里的,这里通过下标索引

  • 各种调试工具一般都支持 sourcemap 的解析,只要在文件末尾加上这样一行
//@ sourceMappingURL=/path/to/source.js.map

参考地址
JavaScript Debugger 原理揭秘》、 《 玩转 Chrome DevTools》、
Webpack 的 sourcemap 配置原理

欢迎关注我的前端自检清单,我和你一起成长