观测项目(2): 精确标记代码运行轨迹

104 阅读1分钟

上一篇中我们能获取到变量访问和修改时所在的栈信息,但是能获取到信息量比较有限,我们希望定位能够更加细化,信息量也更加丰富

问题: 如何更加细化的定位代码位置

image.png

初始化树

  1. 生成一个唯一ID
  2. 标记自己的父节点
  3. 标记自己在父节点里的key 值
  4. 如果是一个作用域(如 函数内部,括号作用域等),则插入作用域队列里,每个作用域搜集所有本地创建的变量
  5. 如果是声明的变量,则向上寻找最近的作用域,并标记

遍历树

  1. 如果是声明变量,则用特殊函数包裹初始值
  2. 如果是一个语句,则搜集并且在前面插入标记代码
window['__tj__current_code'] = 当前块节点 ID
  1. 如果变量是我们用特殊函数包创建的 x,则需要改为 x.value

包裹函数

  1. 所有初始值存在对象的 value 值里
  2. 使用 Proxy 代理 set, get
  3. 触发set,get 的时候,通过全局变量 window['__tj__current_code'] 来获取当前运行到的节点位置
  4. 发送节点位置给历史记录信息
  5. 如果 set 的是对象,则递归对象返回 Proxy 代理的对象

最终的结果

image.png

获取历史记录

image.png

image.png

这里 loc 是在每个语句前面插入的 当前运行语句的 AST 节点 ID

window['__tj__current_code'] = 当前块节点 ID

targetName 表示变量名,type 为 set,get 等,value 为修改的新值

当变量触发 set,get 的时候就会塞入这个 ID。我们通过这个ID 可以找寻对应的代码运行位置。