cherry-studio/scripts/fix-electron-builder.js
2025-04-28 06:55:18 +08:00

156 lines
5.1 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 修复 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 文件的路径
let nodeModulesCollectorPath = path.join(
process.cwd(),
'node_modules',
'app-builder-lib',
'out',
'node-module-collector',
'nodeModulesCollector.js'
)
// 检查文件是否存在
console.log(`正在检查文件: ${nodeModulesCollectorPath}`)
if (!fs.existsSync(nodeModulesCollectorPath)) {
console.error('找不到 nodeModulesCollector.js 文件,请确保已安装 electron-builder')
// 尝试查找其他可能的路径
const possiblePaths = [
path.join(
process.cwd(),
'node_modules',
'electron-builder',
'node_modules',
'app-builder-lib',
'out',
'node-module-collector',
'nodeModulesCollector.js'
),
path.join(
process.cwd(),
'node_modules',
'app-builder-lib',
'lib',
'node-module-collector',
'nodeModulesCollector.js'
),
path.join(
process.cwd(),
'node_modules',
'app-builder-lib',
'dist',
'node-module-collector',
'nodeModulesCollector.js'
)
]
for (const possiblePath of possiblePaths) {
console.log(`尝试查找: ${possiblePath}`)
if (fs.existsSync(possiblePath)) {
console.log(`找到文件: ${possiblePath}`)
nodeModulesCollectorPath = possiblePath
break
}
}
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 堆栈溢出修复补丁!')