asar是一种简单的扩展归档格式,它的工作方式类似于tar,它将所有文件连接在一起而不进行压缩,同时具有随机访问支持。
$ asar -V
v2.0.0
近期使用asar工具解压asar文件时发现如下报错:
C:\Users\zhujiaming\AppData\Roaming\npm\node_modules\asar\lib\filesystem.js:22
json = json.files[dir]
^
TypeError: Cannot read property 'files' of undefined
at Filesystem.searchNodeFromDirectory (C:\Users\zhujiaming\AppData\Roaming\npm\node_modules\asar\lib\filesystem.js:22:21)
...
根据报错信息发现是asar库内部的filesystem.js类报错,根据TypeError: Cannot read property 'files' of undefined
可以初步分析解析到某个文件时,某个文件不存在,导致了undefined。
在网上搜罗一圈,包括在asar仓库的issue中,也基本没有解决此类的问题,于是决定自己分析源码解决。
1.先查找仓库在本地安装的地址
根据报错信息可以看到地址为:C:\Users\zhujiaming\AppData\Roaming\npm\node_modules\asar\lib\
2.查看分析filesystem.js:22
searchNodeFromDirectory (p) {
let json = this.header
const dirs = p.split(path.sep)
for (const dir of dirs) {
if (dir !== '.') {
json = json.files[dir]
}
}
return json
}
其中22行为json = json.files[dir]
,说明json没有files属性。进而推断循环app.asar提供的文件列表中,存在本地不存在的列表。
3.分析app.asar解压后得到的文件列表
通过源码追踪,定位到了解压获取文件列表的位置,位于disk.js
下
module.exports.readFilesystemSync = function (archive) {
if (!filesystemCache[archive]) {
let header = this.readArchiveHeaderSync(archive)
const filesystem = new Filesystem(archive)
filesystem.header = header.header
filesystem.headerSize = header.headerSize
filesystemCache[archive] = filesystem
}
return filesystemCache[archive]
}
此处header即文件列表,此处打印header值即可发现本地不存在的文件,在此处过滤即可解决。
disk.js
module.exports.readFilesystemSync = function (archive) {
if (!filesystemCache[archive]) {
let header = this.readArchiveHeaderSync(archive)
console.log("readFilesystemSync before | ",header)
delete header.header.files["nvm-nodejs"] //进过调试发现执行遍历nvm-nodejs的时候报错,这里将该文件删除即正常
//delete header.header.files["node_modules"] //这个注释了就不会解压node_modules,能加快解压速度
console.log("readFilesystemSync after| ",header)
const filesystem = new Filesystem(archive)
filesystem.header = header.header
filesystem.headerSize = header.headerSize
filesystemCache[archive] = filesystem
}
return filesystemCache[archive]
}
所以这是asar工具的bug,可以利用这个bug,来给asar文件做反解压操作。
其他:
npm asar
github asar
网友评论