
Rolldown 与 Rollup 行为对齐测试全景从 status.md 读懂 1214 个用例的通过矩阵【免费下载链接】rolldownFast Rust bundler for JavaScript/TypeScript with Rollup-compatible API.项目地址: https://gitcode.com/GitHub_Trending/ro/rolldownRolldown 作为以 Rollup 兼容 API 为目标的 Rust 打包器其核心工程目标之一就是与 Rollup 保持行为对齐。本文以 packages/rollup-tests/src/status.md 这份测试状态清单为主线拆解直接复用 Rollup 官方测试套件来验证 Rolldown的完整机制你会看到 1214 个通过用例、296 个暂缓用例、数百个按原因分门别类的忽略用例是如何被统计出来的以及如何用just test-node-rollup一键复现这套回归测试。一、status.md 是什么一张可机器读取的对齐进度表status.md 是一份由测试运行器自动生成的 Markdown 状态表全文只有一张两列的表numberfailed0skipFailed296ignored106ignored(unsupported features)321ignored(treeshaking)327ignored(behavior passed, snapshot different)163passed1214这张表的每一行都对应 status.json 中同一份数据的落地Rolldown 在跑 Rollup 官方测试这件事上的当前达成度被压缩成了七个数字。读懂它就等于读懂了这个仓库对兼容 Rollup这件事的可量化定义。各状态字段含义failed0本轮测试中真正失败的用例数。CI 中该数字必须为 0否则check.js会以非零退出码终止进程。skipFailed296已经被记录在 failed-tests.json 中的已知失败用例。它们不会在每轮测试中重复跑而是直接跳过从而把 CI 的关注点集中在有没有新增失败上。这一点在 check.js 中可以印证alreadyFailedTests.has(id)时直接this.currentTest.skip()。ignored106因有意为之的行为差异而忽略的用例清单集中在 ignored-tests.js。从源码注释可以归纳出六大类原因已被迁移到其他测试位置的用例、测试基础设施相关的忽略如skipIfWindows、以及预期的行为差异——例如 Rolldown 在bundle.generate/bundle.write时才启动构建、import.meta.urlpolyfill 行为不同、ASSIGN_TO_IMPORT与 Rollup 的ILLEGAL_REASSIGNMENT错误码差异、对 const 重赋值报错而非告警等。ignored(unsupported features)321因 Rolldown 尚未支持某些特性而忽略的用例逐条记录在 ignored-by-unsupported-features.md 中并按特性分组共 427 行。从该文件可以清晰看到当前的能力边界load钩子返回ast暂不支持、resolveDynamicImport钩子的specifier: AstNode暂不支持、插件sequential排序暂不支持、renderDynamicImport/resolveImportMeta/shouldTransformCachedModule钩子暂不支持、PluginContext.cache暂不支持、PluginContext.parse不支持allowReturnOutsideFunction选项等。这份清单本质上就是 Rolldown 插件 API 的待办路线图。ignored(treeshaking)327与 tree-shaking 行为相关的忽略用例清单见 ignored-treeshaking-tests.js同名 JSON 见 ignored-treeshaking-tests.json。ignored(behavior passed, snapshot different)163行为已经通过、但输出快照snapshot与 Rollup 不一致的用例见 ignored-passed-snapshot-different-tests.js。这一类别最有价值——它说明功能逻辑是正确的只是输出细节如代码生成格式与 Rollup 存在差异属于对齐度已经很高、只差快照收敛的部分。passed1214完整通过且快照一致的用例是对齐度的硬指标。从 update-test-status.js 的writeTestStatusToMarkdown函数可以看到status.md的表格格式完全由代码生成Object.keys(status)遍历状态对象逐行输出| key | value |。因此不要手工编辑 status.md任何数字变化都应该通过重新运行测试来更新。二、这套测试为什么可行从 submodule 到测试代理status.md里的数字不是凭空统计出来的它们来自 Rollup 官方测试套件。核心思路在 README.md 中讲得很清楚We aim for behavior alignment with Rollup by running Rollups own tests against Rolldown.具体实现方式submodule 提供测试源仓库根目录下的rollup目录是一个 git submodule包含 Rollup 官方测试用例。代理测试文件packages/rollup-tests/test 下的每个测试文件都代理到 submodule 中对应的测试。例如test/form/index.js代理 Rollup 的 form 测试test/function/index.js代理 function 测试还有 chunking-form、cli、file-hashes、hooks、incremental、leak、load-config-file、misc、sourcemaps、typescript、watch、browser 等目录覆盖了 Rollup 测试的几乎全部类别。替换底层打包实现这些测试原本调用的是 Rollup 的 API而在本仓库中它们被打包进了rolldown/binding等 Rolldown 实现之上从而实现用 Rollup 的测试用例考验 Rolldown 的实现。前置条件submodule 初始化运行测试前需要先初始化 submodule项目 setup 阶段执行just setup会完成初始化之后每次同步上游执行just update-submodule在 justfile 中它是setup-submodule的别名更新 submodule 内容。三、一键运行just test-node-rollup 的完整调用链justfile 中定义了运行 Rollup 测试的入口。关键命令如下# 运行 Rollup 测试套件会先构建 Rolldown just test-node-rollup # 运行并更新测试状态文件failed-tests.json / status.json / status.md just test-node-rollup --update两条命令在 justfile 中的定义分别是test-node-rollup *args: build-rolldown just t-node-rollup {{ args }} t-node-rollup *args: vp run --filter rollup-tests test {{ args }}即just test-node-rollup会先执行build-rolldown构建原生绑定再通过 pnpm workspace 的vp run --filter rollup-tests test运行 packages/rollup-tests/package.json 中的测试脚本test: ROLLUP_TEST1 mocha --file ./src/intercept/main.js test/test.js这条命令由三部分组成ROLLUP_TEST1环境变量告诉测试基础设施当前运行的是 Rollup 对齐测试而非 Rolldown 自身测试mocha测试运行器--file ./src/intercept/main.jsmocha 的--file参数在任何测试用例之前加载 intercept/main.js从而把状态统计逻辑注入到测试生命周期中。此外还可以附加 mocha 参数# 只运行匹配 grep 的用例不会做全量状态校验 just test-node-rollup --grep tree-shaking # 同时跑 Rolldown 自身测试与 Rollup 对齐测试 just test-node--grep与--update不能同时使用main.js 中对此有显式校验Cannot use --update with --grep。依赖环境的自动化处理测试脚本前还会执行 setup-node-modules.js它会把rollup-tests/node_modules符号链接到rollupsubmodule 的node_modules位置以统一控制依赖版本、保证minimumRelease等版本门槛被满足。这意味着你不需要手动为 submodule 安装依赖运行测试时链路会自动处理。四、状态机如何工作intercept 层的生命周期钩子status.md的数字是 mocha 钩子一点点算出来的核心逻辑分布在 intercept 目录的四个文件中。整个流程分两种模式更新模式--update入口 update-test-status.jsbeforeEach计算当前测试 IDcalcTestId用test.titlePath().join()生成形如rollupformjsxpreserves-jsx-text: ...若命中 ignore 清单则跳过若命中已知失败清单则计入skipFailed并跳过。同时设置 500ms 超时保护超时用例会以Test timed out: [id]报错。afterEach根据测试状态累加failed或passed计数失败用例的 ID 会被加入alreadyFailedTests集合。after把失败集合写回 failed-tests.json把状态对象序列化写入 status.json并通过writeTestStatusToMarkdown生成 status.md。最后process.exit(0)强制退出避免 Rust 进程残留导致 mocha 挂起。校验模式默认入口 check.js同样在beforeEach/afterEach中统计但after阶段会与 status.json 中的期望值比对若failed 0输出所有失败详情并以退出码 1 结束若expectedStatus.skipFailed ! status.skipFailed或passed数与期望不一致除非设置了SKIP_PASS_DIFF环境变量则抛出错误提示The rollup test status file is not updated. Please run just test-node-rollup --update to update it.使用--grep时跳过通过数校验因为筛选后数字必然不完整。这套更新—提交—校验的闭环保证了 status 文件包括 status.md永远与实际运行结果一致——任何改动代码导致的通过数变化都必须以--update重新生成状态文件后随 PR 提交。忽略判定逻辑utils.js 中的shouldIgnoredTest决定一个用例是否被忽略它聚合了四份清单ignored-tests.js导出的ignoreTests106 项ignored-by-unsupported-features.md 中以-前缀解析出的用例321 项ignored-treeshaking-tests.js327 项ignored-passed-snapshot-different-tests.js163 项。需要特别注意的是status.md 中的ignored一行对应的是ignoredTests.size——即只有有意忽略那 106 项而ignored(unsupported features)一行才是loadUnsupportedFeaturesIgnoredTests().length。四类忽略之和为 106 321 327 163 917加上 passed 1214、skipFailed 296、failed 0合计 2427 个用例这就是 Rollup 测试套件在本仓库中被度量的总规模。五、从清单反推兼容性路线图status.md是结果而它背后的清单是原因。通过对比不同 ignore 清单可以反推出 Rolldown 的兼容策略刻意行为差异106 项这是主动选择不同的部分。例如 Rolldown 默认output.dir为dist、构建时机在bundle.generate/bundle.write而非rollup.rollup、错误码体系不同ASSIGN_TO_IMPORTvsILLEGAL_REASSIGNMENT、PARSE_ERRORvsMISSING_EXPORT、对 const 重赋值直接报错而非告警等。这些差异多数有对应的 GitHub issue 跟踪清单注释中保留了 issue 链接的编号说明是经过讨论后确定的取舍而不是遗漏。未支持特性321 项这是想做还没做的部分。ignored-by-unsupported-features.md 按Plugin related等章节组织每个章节标题就是一项能力缺口。随着这些特性在 Rust 端落地对应条目会从这份清单中移除、转入正式测试。快照差异163 项这是行为已通过、输出未对齐的部分对齐成本最低、收益也最直接——逻辑正确只是格式化细节不同。tree-shaking 差异327 项单独归类说明 tree-shaking 是 Rollup 对齐中占比最大的独立领域Rolldown 为此维护了独立的忽略清单与更新脚本package.json 中的update-treeshaking-failures脚本专门用于更新 ignored-treeshaking-tests.json配套的专项用例见 test/form/found-tree-shaking-not-align.js。六、总结如何读这份状态表status.md是 Rolldown 项目里最有信息密度的一张表。作为使用者你只需要记住三点看 passed1214这是 Rollup 官方用例中行为与快照双重对齐的硬指标占被测总量的约 50%且仍在增长。看 failed0与 skipFailed296failed必须保持为 0skipFailed是已登记在案的已知失败只读不重跑。任何将skipFailed转化为failed的改动都意味着回归。看三份大清单ignored(unsupported features)321与ignored(treeshaking)327标注了能力边界与待办路线ignored(behavior passed, snapshot different)163则是最容易通过快照收敛转为passed的增量来源。想复现这套数据在完成just setup含 submodule 初始化后执行just test-node-rollup即可改动代码导致数字变化时用just test-node-rollup --update重新生成 status.md 与 status.json让这张表始终如实反映 Rolldown 与 Rollup 的行为对齐进度。【免费下载链接】rolldownFast Rust bundler for JavaScript/TypeScript with Rollup-compatible API.项目地址: https://gitcode.com/GitHub_Trending/ro/rolldown创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考