我一直对以下找到的here
图片感到困惑
以下描述它应该如何工作:
上面的图AAgBC一旦进一步处理将返回0,0,32,16,1 - 32是连续位,有助于构建以下16的值.B在Base64中纯粹解码为1.所以重要的值是使用的是0,0,16,1。然后让我们知道第1行(由冒号保持行数)生成的文件的第0列映射到文件0(文件0的数组是foo.js),第1栏第16行。
我含糊地理解为什么B
被转换为16
,但是什么是C
?以及如何将其转换为1
?
答案 0 :(得分:2)
该页面上的解释非常混乱。忘记提及的关键是,base64和VLQ系统基于6位字母,而不是通常的8位字母。例如,base64数据与JavaScript自身的atob
函数之类的“常规” base64解码器不兼容(atob("AAgBC")
会产生错误)。我认为this page提供了更好的解释。
假设我们有一个函数decodeLine()
来解码一行"IACH,mBAA0B,CAAS,EAAE,SAAgB"
的数字。这仅是成功的一半,因为4个数组(或5个数组)中的每个数组都相对于先前的4个数组。
在此示例中,第一个base64字符串“ IACH”表示数组[4,0,1,-3]
,但是此信息本身无用,因为它相对于先前的4数组(第一个数字除外,即在每一行的开头重置为0)。因此,如果先前的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})`));
行和列从零开始。规范为here。