V8 如何使用 requestAnimationFrame 重构异步堆栈跟踪?

How does V8 reconstruct async stacktraces with requestAnimationFrame?

根据Zero-cost async stack traces,V8 在微任务中使用 Promise 引用来重建“异步堆栈跟踪”。我假设调试器中也使用了类似的技术,它也显示了一个“异步堆栈”。但是,在调试“伪递归函数”时,例如这个使用 requestAnimationFrame:

(function tick() { requestAnimationFrame(tick); })();

然后 Chrome 也显示了一些“异步堆栈”,如 this question 所示,尽管没有 Promise 存在。 V8 是如何回收这个堆栈的?它是否收集有关微任务如何安排的信息?如果是这样,是什么阻止了它泄漏内存?

基本上是作弊。当打开 devtools 时,调试器使用 chrome devtools 协议连接到 v8.

它依次调用 setAsyncCallStackDepth,只要异步调用完成,它就会“缝合”堆栈(您可以在 chromium 存储库的 v8/src/inspector/v8-debugger.cc 中看到如何操作)。

它很贵,这就是为什么你只能在 devtools 中得到它。

你可以把它想象成:

  • 每当调用异步函数时,通过获取堆栈跟踪来跟踪它。
  • 抛出错误时,获取其堆栈跟踪并将两者“缝合”在一起。

请注意,这是之前在用户空间库中完成的(如 bluebird),它非常有用,但在生产应用程序中依赖性不是很好,因为它仅适用于连接的调试器。