ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Electron Node.js 依赖升级实战指南:从 e sync --3 补丁冲突修复到上游测试套件运行

Electron Node.js 依赖升级实战指南:从 e sync --3 补丁冲突修复到上游测试套件运行 Electron Node.js 依赖升级实战指南从 e sync --3 补丁冲突修复到上游测试套件运行【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electron本文基于 Electron 仓库内的升级作业手册 .claude/skills/electron-node-upgrade/SKILL.md 及其引用文件展开完整覆盖 Node.js 依赖升级的三个标准阶段用e sync --3循环修复补丁冲突、用e build修复编译破坏、用script/node-spec-runner.js跑通 Node.js 上游测试套件。读完后你将掌握补丁patch系统的完整心智模型、git am/ fixup-rebase 的冲突修复流程、BoringSSL 与 Chromium V8 差异的应对模式以及各阶段强制要求的提交信息规范。背景roller/node/main 分支与两类版本更新roller/node/main分支由自动化流程创建其唯一作用是更新 Electron 对 Node.js 的依赖版本——即 DEPS 中的node_version变量并据此克隆third_party/electron_node代码库# DEPS vars { chromium_version: 154.0.8029.0, node_version: v24.20.0, ... } src/third_party/electron_node: { url: (Var(nodejs_git)) /node.git (Var(node_version)), ... }该分支上并未做任何处理新旧版本之间破坏性变更的工作这正是升级作业要补上的部分。仓库当前跟踪的版本是 Node.js v24.xtypes/node为^24.9.0见 package.json 第 20 行。Node.js 版本更新分为两类Bumpspatch/minor 小版本由electron-roller[bot]自动化提交标题为chore: bump node to v{version}其中琐碎的补丁索引更新由patchup[bot]自动处理。这类更新通常能干净落地但也可能需要人工修补丁。主版本升级如 v22 → v24人工发起的大型 PR标题为chore: upgrade Node.js to v{X}.{Y}.{Z}。通常涉及删除过时补丁、适配大量补丁并同步更新 package.json 中的types/node主版本。关键目录约定后续所有操作基于此路径说明Electron 仓库当前目录所有e命令都在这里执行../third_party/electron_nodeNode.js 代码库补丁实际应用的落点patches/node/Node.js 补丁文件存放处docs/development/patches.md补丁系统官方文档补丁系统心智模型与核心命令补丁系统与代码库之间是双向同步关系patches/node/*.patch → [e sync --3] → ../third_party/electron_node 中的提交 ← [e patches] ←核心命令一览命令用途e sync --3克隆依赖并以三方合并3-way merge方式应用补丁git am --continue在 Node.js 仓库中解决冲突后继续git ame patches node将 Node.js 仓库中的提交导出为补丁文件e patches all导出所有目标的全部补丁e patches node --commit-updates导出补丁并自动提交琐碎变更e patches --list-targets列出补丁目标及配置文件路径何时直接编辑补丁、何时走工作目录场景操作处于git am冲突过程中在 Node.js 仓库工作区修复然后git am --continue冲突之外要修改补丁直接编辑.patch文件创建新补丁罕见尽量避免在 Node.js 仓库提交再e patches node99% 的情况应当是修复已有补丁而不是新建补丁。阶段一e sync --3 与补丁冲突解决循环阶段一的目标反复运行e sync --3解决沿途出现的每一个补丁冲突直到它以退出码 0 结束随后导出补丁并按提交规范原子化提交。满足成功标准之前不要停e sync --3退出码为 0无补丁失败所有变更已按提交指南提交。两条红线原文标记为 CRITICAL不要删除或跳过补丁除非 100% 确认补丁不再需要。主版本升级中垫片shim已废弃 V8 API 或回移上游变更的补丁往往可以删除——因为新版 Node.js 已原生包含这些变更——但删除前必须逐一验证。复杂冲突在穷尽其他手段后应交由用户决策绝不因解决不了而删除补丁。永远不要git am --skip后手工重建补丁提交——这会摧毁原补丁的作者信息、提交信息与在序列中的位置。若git am --continue报 No changes说明该补丁的变更已被先前某个冲突的三方合并吸收应向用户呈现该情况而不是跳过重建。会话前检查每次升级会话开始时执行一次清理 rerere 缓存若启用在 electron 与../third_party/electron_node两个仓库中分别执行git rerere clear。上一轮尝试留下的陈旧合并记录可能悄悄应用错误的合并结果。确认 pre-commit 钩子已安装检查.git/hooks/pre-commit是否存在不存在则运行yarn husky安装。该钩子通过lint-staged对 C 文件执行 clang-format。主循环工作流运行e sync --3--3开启三方合并必须始终携带成功则跳到第 5 步补丁失败时从错误输出中定位目标仓库与具体补丁按 patch-analysis.md 的方法分析失败原因在../third_party/electron_node工作区中修复冲突在该仓库中运行git am --continue循环直到该仓库所有补丁应用完毕git am --continue成功后必须运行e patches node导出修复回到第 1 步。e sync --3成功后运行e patches all阅读 phase-one-commit-guidelines.md 并严格按其提交变更。补丁修复的四条硬性规则保留作者信息TODO 注释中保留补丁From:字段的原作者永远不改 TODO 责任人TODO(name)必须保持原姓名更新描述若上游改动了 API 或宏同步更新补丁提交信息以反映当前状态绝不 skip 后重建报 No changes — did you forget to use git add? 时说明更早的某次冲突解决拉入了过多变更正确做法可能要求重做那次更早的解决让每个补丁的变更保持分离——应向用户呈现此情况。补丁冲突分析方法patch-analysis 参考定位失败根因的标准步骤阅读patches/node/{patch_name}.patch补丁文件本身在 Node.js 仓库中查看补丁提到的行号处的当前代码状态检查上游近期变更git log --oneline -10 -- {file}从提交信息中找到对应 Node.js PR——提交信息中的PR-URL:行指向 Node.js 上游 PR 编号。核心原则是按意图解决而非机械合并。不要盲目保留补丁旧代码而是理解上游提交的完整范围不只是冲突 hunkgit show commit --stat并通读所有受影响文件的 diff上游可能删除了补丁在其他 hunk 中引用的结构体、成员或方法重读补丁提交信息弄清其意图——它需要保留或新增什么行为将意图在新上游代码上重新实现。若补丁目的是增加 BoringSSL 兼容就只加兼容层不要顺带恢复上游另外删除的旧代码。沉淀下来的三条经验教训上游删除会打断补丁引用补丁旧代码若引用了被删除的类型/成员解决时必须改用新上游机制把补丁目的与补丁实现分离若补丁只是把代码包进条件分支就只补条件分支不要恢复条件内已被上游清理的旧代码在冲突时刻完成适配补丁涉及上游 API 移除/替换时必须在同一个提交中完整适配到新 API不要留下阶段二再修的陈旧引用——每个补丁修复提交都应是一个完整解决方案。常见失败模式对照表模式原因解法上下文行不匹配周边代码变更更新补丁上下文文件未找到文件被重命名/移动更新补丁目标路径函数未找到上游重构找到新函数名OpenSSL → BoringSSL 不匹配加密 API 变更更新为 BoringSSL 兼容 APIGYP/GN 构建变更构建系统重构适配构建补丁到新结构代码被删除功能被移除验证补丁是否仍需要V8 API 桥接补丁冲突Node.js 追上了 Chromium 的 V8补丁可能可删除——先确认该 API 已在新版 Node.js 的 V8 中原生可用用git blame定位变更来源git blame -L {start},{end} -- {file}再对定位到的提交git log -1 {commit_sha}查看PR-URL:行。验证补丁必要性删除前三查补丁功能是否已被上游有意移除Electron 是否因其他原因仍需要它是否有其他代码依赖被补丁改变的行为。特别是 V8 桥接补丁——Electron 使用 Chromium 的 V8通常领先于 Node.js 捆绑的 V8这类补丁用于弥合版本差Node.js 主版本升级后其 V8 追上 Chromium 时这些补丁往往可以删除。拿不准时保留并适配。阶段二的伏笔有些补丁在阶段一干净应用却在阶段二引发编译错误例如补丁禁用了某个头文件 include 而新上游代码用到了该类型或补丁改了类而上游新增了引用原类的代码。用grep -l filename.cc patches/node/*.patch找出影响某文件的补丁修复时匹配既有补丁风格——看它用#if 0/#endif、#if BUILDFLAG(...)还是#ifndef/#ifdef区分 BoringSSL 与 OpenSSL保持一致。阶段一提交规范仅当阶段一成功后存在未提交的patches/变更时适用。要点每个提交必须完整在同一个提交中把补丁完整适配到新上游代码不遗留以后再修的陈旧引用标题遵循 60/80 字符惯例简单变更 ≤60否则 ≤80并附Co-Authored-By:协作者信息原子提交每个补丁冲突修复独立一个提交各带各的 RefRef 的寻找要尽力而为对 Node.js 源文件用git log/git blame找PR-URL:或Refs:引用多数 Electron 补丁是 Electron 原创、没有上游引用此时在 Node.js 仓库git log中找引发冲突的上游提交实在找不到则写Ref: Unable to locate reference。三种提交类型与示例补丁冲突修复使用fix(patch):前缀标题命名上游变更本身而非你的应对fix(patch): stop using v8::PropertyCallbackInfoT::This() Ref: Node.js issue #60616 Co-Authored-By: AI 模型署名已上游化补丁的删除全部删除合并进单个提交chore: remove upstreamed patch多个时为chore: remove upstreamed patches若补丁源自上游 Node.js PR 则无需额外Ref:。琐碎补丁更新所有 fix 提交之后将只剩索引哈希、行号、上下文行变化的剩余改动git am冲突也可能仅由上下文漂移引起单独提交git add patches git commit -m chore: update patches (trivial only)阶段二e build 与两类构建修复阶段一完成后立即进入。目标反复运行e build -k 999 -- --quiet-k 999遇错继续--quiet只输出错误与最终结果直到成功然后e start --version验证 Electron 能启动最后按规范提交。成功标准构建退出码 0、已运行e start --version、变更已提交。禁止删除代码或功能、禁止注释掉代码走捷径——必须让既有代码、逻辑与意图全部工作起来。核心原则编译错误的修复方向永远是改 Electron 的侧去适配 Node.js 的变更强烈避免改 Node.js 侧代码来迁就 Electron 的构建。../third_party/electron_node在该阶段只读不改仅用于获取上下文。主循环工作流运行e build -k 999 -- --quiet成功则跳到第 6 步失败时从编译错误信息中定位 electron 侧的底层文件分析失败通过适配 Electron 代码修复随后用e build -t {target_that_failed}.o只构建刚修的目标快速验证——目标名取自构建日志的 FAILED 行例如FAILED: ... ./obj/electron/shell/browser/api/electron_api_utility_process.o CXX obj/electron/shell/browser/api/electron_api_utility_process.o中的obj/electron/shell/browser/api/electron_api_utility_process.o阅读 phase-two-commit-guidelines.md 后提交回到第 1 步关键步骤任何提交尤其补丁提交之后立即在 electron 仓库运行git status检查是否有仅含索引/hunk 头变化的其他.patch文件——这些是受本次修复影响的依赖补丁须立即git commit -am chore: update patches (trivial only)回到第 1 步构建成功后运行e start --version在../third_party/electron_node中运行git status检查是否有未提交的 Node.js 侧改动若有则按下方A. 补丁修复流程提交进对应补丁文件。A. 补丁修复报错文件属于被 Electron 打补丁的 Node.js 文件先用grep -l filename patches/node/*.patch确认文件被哪个补丁影响然后走 fixup 工作流在 Node.js 源码树../third_party/electron_node/...中编辑文件针对原补丁提交创建 fixup 提交并自动压缩cd ../third_party/electron_node git add modified-file git commit --fixuporiginal-patch-commit-hash GIT_SEQUENCE_EDITOR: git rebase --autosquash --autostash -i commit^导出更新后的补丁e patches node按 phase-one-commit-guidelines.md 提交更新后的补丁文件。定位 fixup 目标git log --oneline | grep -i 补丁名关键词。rebase 的基线提交是补丁应用前的 Node.js 上游提交可通过refs/patches/upstream-head引用找到。B. Electron 代码修复报错文件在 shell/、electron/ 等 Electron 自有代码中直接在 electron 仓库中编辑并直接提交无需导出补丁。阶段二提交规范两种提交类型。Electron 源码变更当上游 Node.js 提交带PR-URL:时使用上游 PR 原始标题逐字照用不改写长度超 80 也照用node#61898: src: stop using v8::PropertyCallbackInfoT::This() Ref: Node.js 上游 PR #61898 Co-Authored-By: AI 模型署名无 PR 仅有 issue 引用时fix: adapt to v8::PropertyCallbackInfoT::This() removal Updated NodeBindings to use HolderV2() after upstream Node.js stopped using the deprecated This() API. Ref: Node.js issue #60616 Co-Authored-By: AI 模型署名每个变更独立提交、独立 Ref可含多个 Ref逻辑相关的变更合理分组而不是合并成一个大提交。补丁文件更新则复用阶段一的fix(patch):规范。依赖补丁的头部更新仅索引/行号/上下文变化同样提交为chore: update patches (trivial only)。阶段三运行 Node.js 上游测试套件阶段二完成后立即进入。Electron 通过自定义 runner script/node-spec-runner.js 运行 Node.js 上游测试套件的一个子集测试以构建出的 Electron 二进制为解释器执行环境变量ELECTRON_RUN_AS_NODEtrue。大量测试需要适配因为 Electron 用的是 BoringSSL而非 Node.js 捆绑的 OpenSSL和 Chromium 的 V8可能与 Node.js 捆绑 V8 不同。成功标准node script/node-spec-runner.js --default零失败且变更已提交。关键文件script/node-spec-runner.js —— 测试 runnerscript/node-disabled-tests.json —— 永久禁用测试清单不要试图修复这些测试../third_party/electron_node/test/—— Node.js 测试文件patches/node/fix_crypto_tests_to_run_with_bssl.patch —— BoringSSL 加密测试适配patches/node/test_formally_mark_some_tests_as_flaky.patch —— 不稳定测试标记清单。runner 实现细节源码级佐证阅读 script/node-spec-runner.js 可验证手册中的两条操作纪律为何存在--default模式拼装的是tools/test.py -p tap --logfile test.tap --modedebug default --skip-tests禁用清单逗号拼接 --flaky-testsdontcare --measure-flakiness9 --shell electron可执行路径 -Jnode-spec-runner.js#L27-L41。因此跑单个测试时绝不能加--default——自定义模式只透传你的参数并追加--shellgetCustomOptions路径形如test/parallel/test-crypto-key-objects-raw.js相对 Nodetest/目录。不要直接用ELECTRON_RUN_AS_NODE裸跑测试runner 会临时把仓库根与输出目录的package.json移开备份到.spec-runner-backup并在退出/中断时恢复见 node-spec-runner.js#L56-L78。原因是上游测试套件假设测试文件上方没有package.json而 Electron 的 ESM 型 package.json 会改变模块类型解析、触发 MODULE_TYPELESS_PACKAGE_JSON 告警破坏一批断言 stderr 干净的测试同时 runner 负责设置ELECTRON_RUN_AS_NODEtrue与ELECTRON_EAGER_ASAR_HOOK_FOR_TESTINGtrue等环境node-spec-runner.js#L128-L136。附加能力--jUnitDir会把 TAP 日志经 tap-xunit 转换为nodejs.xml--validateDisabled会校验禁用清单里的测试文件确实存在。当前 node-disabled-tests.json 共收录 119 条禁用项。主循环工作流在 electron 仓库运行node script/node-spec-runner.js --default全过则阶段三完成有失败时从输出定位失败测试文件按下述常见失败模式分析在../third_party/electron_node/test/...修复用node script/node-spec-runner.js {test-path}单测验证按 fixup 工作流与提交规范提交回到第 1 步。命令速查命令用途node script/node-spec-runner.js --default运行完整 Node.js 测试套件node script/node-spec-runner.js test/parallel/test-foo.js运行单个测试NODE_REGENERATE_SNAPSHOTS1 node script/node-spec-runner.js test/test-runner/test-foo.mjs为快照型测试重新生成快照常见失败模式BoringSSL 不兼容。Electron 让 Node.js 构建在 Chromium 的 BoringSSL 上而非 Node.js 捆绑的 OpenSSL。截至 v24.18.0 的 roll这件事已从一个大型源码补丁收敛为一个 GN 参数build/args/all.gn#L8# build/args/all.gn # Build Node.js against Chromiums BoringSSL instead of nodes bundled OpenSSL. node_openssl_path //third_party/boringssl由于上游 Node.js 已原生支持 BoringSSL 构建Electron 历史上的 BoringSSL 绕路大部分已被消除v24.18.0 roll 期间fix_crypto_tests_to_run_with_bssl.patch从约 1100 行缩减到只跳过两个测试文件fix_handle_boringssl_and_openssl_incompatibilities.patch删减约 176 行剩余的是deps/ncrypto/ncrypto.cc、src/crypto/crypto_{common,context,hash}.cc、src/env.h、src/node_metadata.h、src/node_options.h中 C 层的垫片。总体趋势是期待删除这些绕路而非增长它们上游测试越来越多地在process.features.openssl_is_boringssl为真时自行跳过此时无需 Electron 侧任何改动。仍受支持缺口影响的测试的推荐写法——在文件顶部整体跳过并纳入fix_crypto_tests_to_run_with_bssl.patch当前 补丁文件 中即可看到test-crypto-keygen-deprecation.js、test-crypto-pqc-key-objects-ml-dsa.js等处正是这一模式if (process.features.openssl_is_boringssl) { common.skip(Skipping unsupported ML-DSA key tests); }无法内联干净守卫的测试则把整个文件加入 script/node-disabled-tests.json。Chromium BoringSSL 截至 v24.18.0 仍不支持的能力与现行处理特性当前处理RSA-PSS 密钥生成废弃路径test-crypto-keygen-deprecation文件级common.skipML-DSA 密钥test-crypto-pqc-key-objects-ml-dsa文件级common.skipML-KEM 密钥禁用node-disabled-tests.json中的test-crypto-pqc-key-objects-ml-kemFIPS 模式禁用test-crypto-fipsSecure heap禁用test-crypto-secure-heapStateless DH禁用test-crypto-dh-stateless杂项 keygen / WebCrypto keygen禁用test-crypto-keygen、test-webcrypto-keygen、wpt/test-webcrypto还有一类行为差异需更新断言而非跳过例如从不支持的 OKPEd448JWK 创建私钥现在抛Invalid JWK OKP key旧为Invalid JWK data。需要守卫时能直接探测能力就优先精确能力检查如ciphers.includes(aes-128-ccm)而非一律用process.features.openssl_is_boringssl粗粒度判断。快照测试不匹配。部分测试用assert.strictEqual与已提交的.snapshot文件比对——这是精确比较而非通配比较。Chromium V8 输出不同如 V8 增强导致堆栈格式变化时必须重新生成NODE_REGENERATE_SNAPSHOTS1 node script/node-spec-runner.js test/test-runner/test-foo.mjs检查 diff 确认变化符合预期再把更新后的快照提交进对应补丁。V8 行为差异。Chromium 的 V8 可能领先于 Node.js 捆绑 V8会导致堆栈格式不同如 thenable 异步栈帧、错误消息不同、一方有而另一方无的特性。测试修复的两类归属A. 补丁修复测试失败最常见的归属绝大多数测试修复进入patches/node/既有补丁走 fixup 工作流——在 Node.js 仓库编辑测试文件用git log --oneline | grep -i keyword找到目标补丁提交加密/BoringSSL 测试对应fix crypto tests to run with bssl快照测试对应具体快照补丁如test: accomodate V8 thenable不稳定测试对应test: formally mark some tests as flaky然后cd ../third_party/electron_node git add test/path/to/test.js git commit --fixuppatch-commit-hash GIT_SEQUENCE_EDITOR: git rebase --autosquash --autostash -i commit^再e patches node导出按 phase-three-commit-guidelines.md 提交更新后的补丁文件。B. 新补丁罕见仅当修复无法归入任何既有补丁时才新建新补丁提交必须带说明为何存在、何时可移除——lint 检查会强制这一要求。加入禁用清单是最后手段只有当测试与 Electron 架构从根本上不兼容而非一个可以用守卫解决的 BoringSSL 差异时才加入 script/node-disabled-tests.json——被禁用的测试完全跳过、永不运行。阶段三提交规范测试修复走fix(patch):前缀例如fix(patch): guard DH key test for BoringSSL、fix(patch): adapt new crypto tests for BoringSSL、fix(patch): correct thenable snapshot for Chromium V8、fix(patch): skip AES-KW tests with BoringSSL。同一根因的相关修复合并为一个提交不要每个测试文件一个提交。BoringSSL 类修复的 Ref 通常是引入该新测试的上游 Node.js PR对测试文件git log取提交再grep PR-URLV8 行为差异则引用对应 Chromium CL。高频冲突补丁清单以下补丁在 Node.js 升级中一贯需要最多的工作量fix_handle_boringssl_and_openssl_incompatibilities.patch—— Electron 用 BoringSSL经 Chromium而 Node.js 预期 OpenSSL。历史上庞大复杂Node.js 获得原生 BoringSSL 支持经 build/args/all.gn 中node_openssl_path //third_party/boringssl启用后已大幅缩减剩余 C 层垫片仍可能因上游 OpenSSL/ncrypto API 变更而破坏。fix_crypto_tests_to_run_with_bssl.patch—— 上一项的配套为 BoringSSL 适配 Node.js 加密测试上游测试在 BoringSSL 下自跳过后同样大幅缩减如今主要只是跳过少数仍不支持的测试文件。support_v8_sandboxed_pointers.patch—— V8 沙箱指针支持V8 API 变更时需要精细适配。build_add_gn_build_files.patch—— GN 构建文件补丁体量大、触及众多构建目标上游构建系统变更频繁引发冲突。主版本升级的特别注意事项主版本迁移如 v22 → v24远比 patch bump 复杂预期会删除补丁。Electron 用 Chromium 的 V8通常领先于 Node.js 捆绑 V8很多补丁正是为了桥接这一差距而存在——垫片 Node.js 旧 V8 尚不具备、而 Chromium V8 已具备的新 API。Node.js 主版本升级后其 V8 追上 Chromium这些桥接补丁即可删除。v22 → v24 升级中就因该原因删除了 17 个补丁。更新types/nodepackage.json 中同步到新的主版本当前为^24.9.0。升级后的回归是常态即便升级落地后续修复边界情况ESM 路径处理、证书加载、平台相关问题的跟进 PR 属正常现象。附录技能目录与延伸阅读本指南的完整作业手册位于 .claude/skills/electron-node-upgrade/包含本文引用的全部参考文件SKILL.md —— 三阶段工作流主文档即本文骨架references/patch-analysis.md —— 补丁失败分析方法references/phase-one-commit-guidelines.md —— 阶段一提交格式references/phase-two-commit-guidelines.md —— 阶段二提交格式references/phase-three-commit-guidelines.md —— 阶段三提交格式。补丁系统本身的机制目录布局、e patches子命令、补丁命名等的权威文档见 docs/development/patches.mdpatches/node/目录下当前共有一百余份补丁文件可结合 patches/README.md 与 patches/config.json 浏览全貌。执行升级前请确认环境满足e工具链electron 仓库的 devDependencies 脚本与 gclient 依赖布局要求且../third_party/electron_node位于与 electron 仓库平级的位置。【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electron创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表