解码(javascript)源映射

问题描述 投票:0回答:2

我一直对以下图片感到困惑这里

Decoding the source map

以下描述了它应该如何工作:

上图 AAgBC 一旦进一步处理将返回 0, 0, 32, 16, 1 - 32 是帮助构建以下值 16 的延续位。B 纯粹以 Base64 解码为 1。因此使用的重要值是 0, 0, 16, 1。这让我们知道生成的文件的第 1 行(行以分号进行计数)的第 0 列映射到文件 0(文件 0 的数组是 foo.js),第 16 行在第 1 栏。

我隐约明白为什么

B
会转成
16
,但是
C
是什么?它是如何转换为
1
的?

javascript source-maps
2个回答
3
投票

该页面上的解释非常混乱。它忘记提及的一个关键事情是,base64 和 VLQ 系统基于 6 位字母表,而不是通常的 8 位字母表;例如,base64 数据与“普通”base64 解码器不兼容,例如 JavaScript 自己的

atob
函数(
atob("AAgBC")
会产生错误)。我认为此页面提供了更好的解释。

假设我们有一个函数

decodeLine()
来解码单行的数字
"IACH,mBAA0B,CAAS,EAAE,SAAgB"
。这只是成功的一半,因为每个 4 数组(或 5 数组)都是相对于前一个 4 数组的。

在此示例中,第一个 base64 字符串“IACH”表示数组

[4,0,1,-3]
,但此信息本身是无用的,因为它是相对于之前的 4 数组(第一个数字除外,该数字在每行的开头)。因此,如果前面的 4 个数组的总和为
[11,1,10,3]
,我们可以计算出“IACH”的真正含义是
[4, 1+0, 10+1,3+-3] = [4,1,11,0]
- 这意味着“输出列 4 对应于源文件 1、源代码行 11、源代码第 0 列”。类似地,“mBAA0B”解码为[19,0,0,26],与[4,1,11,0]相加得到[23,1,11,26],这意味着“输出列23对应于源文件1、源行11、源列26"。

所以我在这里编写了代码来解码整个

"mappings"
字符串。它有两部分,
decodeLine
用于解码单行,
scanMappings
用于解码所有行并为每个解码的 6 个值集(行、列、源文件、源行、源列和可选名称)调用一个函数索引):

function decodeLine(line) { 
  function digit(c) { return atob("AAA"+c).charCodeAt(2); }
  if (line==="") return [];
  return line.split(",").map(token => {
    var output = [], num;
    for (var i = 0; i < token.length;) {
      var v = 0, shift = 0;
      do {
        var d = digit(token[i++]);  // d = next 6-bit value decoded from base64
        v |= (d & 31) << shift;     // put lowest 5 bits of d into v
      } while (shift += 5, d & 32); // repeat if high bit of d is set
      output.push(v & 1 ? -(v >> 1) : v >> 1); // low bit is sign
    }
    return output;
  });
}
function scanMappings(data, callback) {
  var lines = data.split(";"), output = [];
  var sum = [0,0,0,0,0];
  for (var line = 0; line < lines.length; line++) {
    sum[0] = 0;
    decodeLine(lines[line]).forEach(p => {
      for (var i = 0; i < p.length; i++) sum[i] += p[i];
      callback(line, ...sum);
    })
  }
}

// Example taken from one of my TypeScript files
console.log(JSON.stringify(decodeLine("IACH,mBAA0B,CAAS,EAAE,SAAgB")));
scanMappings(
 ";;;;;;;;;;;ICAA;;;;;;;;;;OAUG;IACH,mBAA0B,CAAS,EAAE,SAAgB;QACnD,uEAAuE",
  (line,col,srcFile,srcLine,srcCol) => 
    console.log(`(${line},${col}) is from src file ${srcFile} at (${srcLine},${srcCol})`));

行和列都是从零开始的。规格是这里


-1
投票

mlfjeffsmelfksmldkfmselkmdlkfmleksmdlkfselkmdkfs

© www.soinside.com 2019 - 2024. All rights reserved.