Repository navigation
Code Analysis Validation
这轮用两个问题检验分析结果。内部函数加入公共入口后,能否指到正确的实现?回调通过事件名注册后,能否找到执行它的代码?先用上游的源码、差异和测试写下答案,再运行同一版本的分析器读变更前后两份源码。另取 EventEmitter3 5.0.1 复核同名回调的实际分派。Code Analysis One Page · 公开 Labs 基线 bf0a29e7
#4621(85d7f27a → c9e06506)只改了 src/index.ts。变更后,第 8 行导入原有的 isPlainObject,第 48 行把它列为公共导出。原有三个内部调用方是 combineReducers、createStore 和 isAction 所在的文件。它们和函数实现的源码在两版中相同。入口导入 · 公共导出 · 函数实现
-
Labs 找对了文件依赖。 仅扫描
src/的 17 个文件。变更前的 38 条导入和变更后的 39 条都解析到文件。指向该函数实现文件的导入方从 3 个变为 4 个,新增的正是公共入口。 -
公共名称需要核对导出语句。 导入记录里的
default只说明入口怎样取得这个函数。用 TypeScript 5.9.3 将两份源码分别转为 CommonJS 后,直接读取入口,确认只有后版导出了isPlainObject,而且与原函数是同一对象。本次验证读取源码入口,范围不含已发布的 npm 包和外部使用方。 - 本地双版本实验
c3dddd5c选中了唯一变化的index.ts。公开 Labs 的文件依赖加上上面两处源码,已足够回答本例。实验输出对读者用时或准确度的增益,需另做对照。
#1763(3ae30a29 → 2c7f687e)新增 preSubcommand。注册时,父命令把监听函数存入事件表。分派时,先调用监听函数,再把参数交给直接子命令。用 Node 跑同一个根命令、子命令和孙命令,旧版拒绝注册,新版只触发一次根钩子,传入直接子命令,随后才执行孙命令动作。注册 · 分派 · 回调调用处 · 上游顺序测试
-
Labs 漏掉了进入库的依赖。 两版各扫描 149 个 JS/TS 文件,各记录 174 条导入。125 个文件中的 125 处相对目录
require都由 Node 解析到根index.js,包括 96 个测试文件和 29 个示例文件。默认配置下,Labs 对这 125 处都报告未解析。放开.d.ts排除后,这些运行时引用又全指向了类型声明。包分别声明了 JS 入口和类型入口。包入口声明 · 测试的实际导入 -
定位方法和认出回调对象是两个结果。 本地实验
c3dddd5c选中了 7 个 Git 变更文件中的 4 个。两份 README 和公开声明typings/index.d.ts在默认扫描范围外。实验找到了新增方法的第 1202–1212 行。对第 1207 行究竟执行哪一个监听函数,它明确报告未绑定。该方法的直接引用计数为 0,但第 1058 行确有调用。调查影响时应沿注册表回查,并保留对运行时顺序的独立验证。
| 固定样本 | 公开 Labs 的结果 | Draft #1214 的本地验证 |
|---|---|---|
| Commander #1763,变更前后分别检查 | 每版 125 处目录引用均未解析。显式纳入声明时都指向类型文件 | 两版各 125 处均与 Node 的运行时入口一致。纳入声明后也指向 JS |
| dotenv v16.4.7,追加检查相邻的类型文件 | 7 处省略扩展名的引用均未解析 | 7 处均指向 lib/main.js,逐处与 Node 一致 |
| minimist v1.2.8,追加检查已能解析的目录入口 | 16 处均指向 index.js
|
同样 16 处逐一吻合 |
上层 d2754f100 继承下层条件导入修复 5df422692。它利用本轮已捕获的文件区分相对 CommonJS 引用和类型入口。Commander 单版的已解析导入由 16/174 增至 141/174,剩余 30 条外部依赖和 3 条未知项。该变化集中于测试和示例。233 项模块测试通过。解压后用 CLI 重跑 Commander 和 dotenv,原始分析结果均与源码版相同。修复已提交审查,详见条件导入 Draft #1213和运行时入口 Draft #1214。表中的 Labs 列可以直接按下方命令复现。dotenv 配置入口 · dotenv 测试使用处 · minimist 示例
- 已有分工继续按原讨论推进。稳定 finding ID 修复已开 Draft PR。配置无效时的错误提示、解析失败与跳过语言的披露,由原协作者按 A1、A2 分别推进。稳定 ID #1212 · A1/A2 范围
- EventEmitter3 的同名回调已复核。本地实验能定位 12 处执行监听器的代码,具体闭包要结合注册时的函数对象和上下文核对。两次分派的预期、实际输出和运行命令见独立案例。下一项选注册与分派跨文件的真实变更,对照源码搜索和分析器给出的位置,并检查错误绑定。
复现公开 Labs 对 Redux 和 Commander 的结果
在临时目录准备 Git 和 Node 22。下面固定三个仓库版本。npm ci 只给临时的分析器副本安装锁定依赖。两个被分析的仓库均不需要安装依赖。这里使用 --fail-on never 收集分析结果,逐条比较导入目标。最后一段使用 Node 的 require.resolve,不执行被解析的模块。Node.js CommonJS 解析规则
set -eu
w=$(mktemp -d)
pin() {
git init -q "$w/$1"
git -C "$w/$1" fetch -q --no-tags --depth=2 "https://github.com/$2.git" "$3"
git -C "$w/$1" checkout -q --detach FETCH_HEAD
}
pin archify tt-a1i/archify bf0a29e7664f52973d06a8e6a608df2db1ecbd39
pin redux reduxjs/redux c9e06506f88926e252daf5275495eba0c04bf8e3
pin commander tj/commander.js 2c7f687eaea6e7b29b917db8d71a06fe6fbfb53e
(cd "$w/archify/archify/modules/code-analysis" && npm ci --ignore-scripts --no-audit --no-fund)
cli="$w/archify/archify/bin/archify.mjs"
for project in redux commander; do
git -C "$w/$project" worktree add -q --detach "$w/$project-base" 'HEAD^1'
for side in base head; do
root="$w/$project"
if [ "$side" = base ]; then root="$w/$project-base"; fi
if [ "$project" = redux ]; then root="$root/src"; fi
node "$cli" code-analysis check "$root" --language ts --fail-on never --json \
--out "$w/$project-$side-out" > "$w/$project-$side-receipt.json"
done
done
node - "$w" <<'JS'
const fs = require('node:fs');
const path = require('node:path');
const { createRequire } = require('node:module');
const w = process.argv[2];
for (const side of ['base', 'head']) {
const facts = name => require(path.join(w, name + '-' + side + '-out', 'raw-facts.json'));
const helper = facts('redux').imports.filter(e => e.to === 'utils/isPlainObject.ts');
const repo = fs.realpathSync(path.join(w, side === 'base' ? 'commander-base' : 'commander'));
const loads = facts('commander').imports.filter(e => e.kind === 'require' && ['../', '../../'].includes(e.specifier));
const agree = loads.filter(e => {
const target = createRequire(path.join(repo, e.from)).resolve(e.specifier);
return e.to === path.relative(repo, target).split(path.sep).join('/');
});
console.log(side, { reduxImporters: helper.map(e => e.from), commanderAgreed: agree.length, commanderChecked: loads.length });
}
JS预期 Redux 的导入方从三个增加到四个,新增 index.ts。Commander 的 commanderChecked 在两版均为 125,公开 Labs 的 commanderAgreed 均为 0。复核上层 Draft 时,把 pin archify 一行的 SHA 换成 d2754f10066980b9ce1e7c13f2f634e6cec67447。从 GitHub 重新取得该提交后,两版均为 125/125,Redux 仍只增加 index.ts。