javascript - 为什么 JS 源映射通常以令牌粒度?
问题描述
JavaScript 的源映射似乎通常不比令牌粒度更精细。例如,identity-map 使用令牌粒度。
我知道我看过其他例子,但不记得在哪里。
为什么我们不使用基于 AST 节点的粒度呢?也就是说,如果我们的源地图有所有 AST 节点的位置,并且只有 AST 节点的起点,那么不利的一面是什么?
在我的理解中,源映射用于崩溃堆栈解码和调试:永远不会有错误位置或有用的断点不在某个 AST 节点的开头,对吧?
更新 1
一些进一步的澄清:
该问题与 AST 已知的情况有关。因此,“生成 AST 比生成令牌数组更昂贵”不会回答这个问题。
这个问题的实际影响是,如果我们可以降低源映射的粒度,同时保留调试器和崩溃堆栈解码器的行为,那么源映射可能会小得多。主要优点是调试器的性能:开发工具可能需要很长时间来处理大型源文件,这让调试很痛苦。
以下是使用source-map库在令牌级别添加源地图位置的示例:
for (const token of tokens) {
generator.addMapping({
source: "source.js",
original: token.location(),
generated: generated.get(token).location(),
});
}
这是在 AST 节点级别添加位置的示例:
for (const node of nodes) {
generator.addMapping({
source: "source.js",
original: node.location(),
generated: generated.get(node).location(),
});
}
更新 2
Q1:为什么期望 AST 节点的启动次数少于代币的启动次数?
A1:因为如果 AST 节点的开始数多于令牌的开始数,那么就会有一个以非令牌开始的 AST 节点。对于解析器的作者来说,这将是一个相当大的成就!为了具体说明,假设您有以下 JavaScript 语句:
const a = function *() { return a + ++ b }
以下是令牌开头的位置:
const a = function *() { return a + ++ b } /*
^ ^ ^ ^^^ ^ ^ ^ ^ ^ ^ ^
*/
这大概是大多数解析器所说的 AST 节点的开始位置。
const a = function *() { return a + ++ b } /*
^ ^ ^ ^ ^ ^ ^
*/
源地图位置的数量减少了46% !
Q2:为什么期望 AST-Node-granularity source maps 更小?
A2:见上面的 A1
Q3:你会使用什么格式来引用 AST 节点?
A3:没有格式。请参阅上面更新 1中的示例代码。我说的是为 AST 节点的开始添加源地图位置。该过程几乎与为标记开头添加源地图位置的过程完全相同,只是您要添加的位置更少。
Q4:您如何断言所有处理源映射的工具都使用相同的 AST 表示?
A4:假设我们控制整个管道并且在所有地方都使用相同的解析器。
解决方案
编译器TypeScript
实际上只在 AST 节点边界上发出 sourcemap 位置,但有一些例外是为了提高与某些工具的兼容性,这些工具需要对某些位置进行映射,因此基于令牌的映射实际上并不是很通用。在您给出的示例中,TS 的源图适用于如下位置:
const a = function *() { return a + ++ b } /*
^ ^^ ^ ^ ^^ ^ ^^^
*/
它们通常是每个标识符 AST 节点的开始和结束(否则加上开始)。
映射标识符 AST 节点的开始和结束位置的基本原理非常简单 - 当您重命名标识符时,您希望重命名标识符上的选择范围能够映射回原始标识符,而不必依赖启发式。
推荐阅读
- amazon-web-services - 在 AWS Lambda 中处理事件之前,是否有一种惯用的方法来聚合事件?
- mysql - 正在初始化 c3p0 池...超时
- c++ - 如何获取客户端上 GameplayAbility 属性的增量值(属性值更改后)?
- azure - 使用 Powershell 访问对象值
- kubernetes - Docker for Mac Kubernetes 负载均衡器 NoHttpResponseException
- c# - Microsoft BotFramework v4 任务计划和状态
- c# - 在更新数据库,实体框架 6 上未调用种子方法
- c# - 从非 xaml.cs 超类调用 InitializeComponent()
- python - 如何在不降级 mkl 和 python 的情况下安装 cvxopt
- python - keras.preprocessing.image imagedatagenerator flow from dataframe read error