从源码角度分析asar文件解压报错原因,以及如何解决

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

你可能感兴趣的:(从源码角度分析asar文件解压报错原因,以及如何解决)