Files
cherry-studio/scripts/fix-electron-builder.js
T
2025-04-26 06:27:33 +08:00

110 lines
4.1 KiB
JavaScript

/**
* 修复 electron-builder 堆栈溢出问题的补丁脚本
*
* 这个脚本修复了 electron-builder 在处理循环依赖时导致的堆栈溢出问题。
* 主要修改了以下文件:
* 1. node_modules/app-builder-lib/out/node-module-collector/nodeModulesCollector.js
*/
const fs = require('fs');
const path = require('path');
// 获取 nodeModulesCollector.js 文件的路径
const nodeModulesCollectorPath = path.join(
process.cwd(),
'node_modules',
'app-builder-lib',
'out',
'node-module-collector',
'nodeModulesCollector.js'
);
// 检查文件是否存在
if (!fs.existsSync(nodeModulesCollectorPath)) {
console.error('找不到 nodeModulesCollector.js 文件,请确保已安装 electron-builder');
process.exit(1);
}
// 读取文件内容
let content = fs.readFileSync(nodeModulesCollectorPath, 'utf8');
// 修复 1: 修改 _getNodeModules 方法,添加环路检测
const oldGetNodeModulesMethod = /(_getNodeModules\(dependencies, result\) \{[\s\S]*?result\.sort\(\(a, b\) => a\.name\.localeCompare\(b\.name\)\);\s*\})/;
const newGetNodeModulesMethod = `_getNodeModules(dependencies, result, depth = 0, visited = new Set()) {
// 添加递归深度限制
if (depth > 10) {
console.log("递归深度超过10,停止递归");
return;
}
if (dependencies.size === 0) {
return;
}
for (const d of dependencies.values()) {
const reference = [...d.references][0];
const moduleId = \`\${d.name}@\${reference}\`;
// 环路检测:如果已经访问过这个模块,则跳过
if (visited.has(moduleId)) {
console.log(\`检测到循环依赖: \${moduleId}\`);
continue;
}
// 标记为已访问
visited.add(moduleId);
const p = this.dependencyPathMap.get(moduleId);
if (p === undefined) {
builder_util_1.log.debug({ name: d.name, reference }, "cannot find path for dependency");
continue;
}
const node = {
name: d.name,
version: reference,
dir: p,
};
result.push(node);
if (d.dependencies.size > 0) {
node.dependencies = [];
this._getNodeModules(d.dependencies, node.dependencies, depth + 1, visited);
}
// 处理完成后,从已访问集合中移除,允许在其他路径中再次访问
visited.delete(moduleId);
}
result.sort((a, b) => a.name.localeCompare(b.name));
}`;
content = content.replace(oldGetNodeModulesMethod, newGetNodeModulesMethod);
// 修复 2: 修改 getNodeModules 方法,传递 visited 集合
const oldGetNodeModulesCall = /(this\._getNodeModules\(hoisterResult\.dependencies, this\.nodeModules\);)/;
const newGetNodeModulesCall = `// 创建一个新的 visited 集合用于环路检测
const visited = new Set();
this._getNodeModules(hoisterResult.dependencies, this.nodeModules, 0, visited);`;
content = content.replace(oldGetNodeModulesCall, newGetNodeModulesCall);
// 修复 3: 修改 convertToDependencyGraph 方法,跳过路径未定义的依赖
const oldPathCheck = /(if \(!dependencies\.path\) \{[\s\S]*?throw new Error\("unable to parse `path` during `tree\.dependencies` reduce"\);[\s\S]*?\})/;
const newPathCheck = `if (!dependencies.path) {
builder_util_1.log.error({
packageName,
data: dependencies,
parentModule: tree.name,
parentVersion: tree.version,
}, "dependency path is undefined");
// 跳过这个依赖而不是抛出错误
console.log(\`跳过路径未定义的依赖: \${packageName}\`);
return acc;
}`;
content = content.replace(oldPathCheck, newPathCheck);
// 写入修改后的内容
fs.writeFileSync(nodeModulesCollectorPath, content, 'utf8');
console.log('成功应用 electron-builder 堆栈溢出修复补丁!');