docs: root-cause why the compiler rejects Home, and close two dead ends
Diagnosis was unblocked by temporarily installing babel-plugin-react-compiler and reading its logger events, which the Rust port swallows. Every failure in Home comes from the compiler, not from this repository's code: 24 errors under the stable 1.0.0, all prefixed Todo: (the compiler's own marker for unimplemented syntax) -- 13 for try/finally, 9 for throw inside try/catch, 2 for a non-reorderable MemberExpression. All 13 finally blocks do real cleanup (clearing a timeout, releasing in-flight guards, resetting loading flags), so deleting them to please the compiler would trade correctness for speculative memoization. Two paths are now closed by measurement rather than assumption. Newer compiler builds fix the try/finally gap but Home then hits two consecutive internal Invariant panics, which are compiler bugs. And project-wide the version makes no difference at all: across 373 files both versions compile exactly 134 functions, with the same 21 files failing, so switching implementations buys nothing. The diagnostic dependency is therefore removed and the lockfile restored via npm ci. Deliverable is unchanged: config still rolled back, frontend/src untouched. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -197,6 +197,69 @@ React Compiler 在所有六种配置下都拒编 `Home`,包括显式 `"use mem
|
||||
而那 44 个组件的运行时收益没有测量数据支撑首屏 +2.50 % 的代价。
|
||||
若日后要改变这个结论,前置条件应当是先给那 44 个组件测出渲染基准,而不是直接开配置。
|
||||
|
||||
## 追加轮 · 授权新增依赖后的根因诊断(2026-08-17)
|
||||
|
||||
用户授权新增依赖,于是把 `BLOCKED.md` 第一条(拿不到编译器诊断)解掉。做法:临时
|
||||
`npm i -D babel-plugin-react-compiler`,用 `@babel/core` 的 `transformSync` 单独跑 `page.tsx`
|
||||
(`parserOpts.plugins = ["jsx", ["typescript", {isTSX:true}]]`),给插件传 `logger` 钩子逐函数收事件。
|
||||
脚本在 `/tmp/rc_diagnose.mjs`、`/tmp/rc_batch.mjs`,不进仓库。
|
||||
|
||||
### `Home` 到底被什么挡住
|
||||
|
||||
稳定版 `1.0.0` 对 `page.tsx` 报 26 个事件:`CompileSuccess` 2、`CompileError` 24。
|
||||
`Home`(行 1002)的 24 条去重后三类,**全部带 `Todo:` 前缀** —— 这是 React Compiler
|
||||
标记「该语法尚未实现」的前缀,不是用户代码违规:
|
||||
|
||||
| 条数 | 原因 |
|
||||
| --- | --- |
|
||||
| 13 | `Todo: (BuildHIR::lowerStatement) Handle TryStatement with a finalizer ('finally') clause` |
|
||||
| 9 | `Todo: (BuildHIR::lowerStatement) Support ThrowStatement inside of try/catch` |
|
||||
| 2 | `Todo: (BuildHIR::node.lowerReorderableExpression) Expression type MemberExpression cannot be safely reordered` |
|
||||
|
||||
那 13 个 `finally` 做的全是 `finally` 该做的事:`window.clearTimeout(bootstrapTimeout)`、
|
||||
`polling = false`、`rectificationOpenInFlight.current = false`、
|
||||
`cancellationRequests.current.delete(requestId)`,以及 8 处 `setProfileSaving(false)`/
|
||||
`setAvatarSaving(false)`/`setCreatingSession(false)`/`setBirthTimeAssessmentPhase(null)` 这类加载态复位。
|
||||
删掉任何一个,try 块抛错时 UI 就永久卡在加载态 —— 那是拿真 bug 换假优化,所以一行没动。
|
||||
|
||||
顺带交叉验证了之前的产物取证:Babel 版报告编译成功的是 `BirthLocationFields @ 760` 与
|
||||
`ProfileFields @ 815`,和先前从 Rust 版构建产物 source map 反查出的槽 11/24(行 760/815)
|
||||
逐一对上。两条完全独立的证据链互相印证,取证方法没问题。
|
||||
|
||||
### 更新版本能不能救
|
||||
|
||||
`experimental` 版(`0.0.0-experimental-a1856f3-20260507`)里那 22 条 `try/finally` 与 `throw`
|
||||
错误已被上游修好,`CompileError` 从 24 降到 2。但 `Home` 立刻撞上编译器内部断言失败:
|
||||
`Invariant: Expected all references to a variable to be consistently local or context references`
|
||||
(`page.tsx:2666`,`catch (error)` 的绑定既被直接使用、又被 `setRequestError((current) => ...)`
|
||||
的闭包捕获)。在仓库外的副本上把这一处改掉,又冒出下一个
|
||||
`Invariant: [PruneHoistedContexts] Unexpected hoisted function`(`page.tsx:1837` 的 `refreshAccount`,
|
||||
被 1626 行的 `useEffect` 提前引用)。`Invariant:` 在 React Compiler 分类里是**编译器 bug**。
|
||||
`Home` 共 50 个函数声明,其中 6 个被声明前引用,要满足编译器得跨千行重排这 6 个定义。
|
||||
一句话:打地鼠,且每步都由编译器 bug 而非代码质量驱动。
|
||||
|
||||
### 换版本/换实现的全项目收益:零
|
||||
|
||||
对 `frontend/src` 全部 373 个文件跑批量诊断,两版对比:
|
||||
|
||||
| | 稳定版 1.0.0 | experimental 版 |
|
||||
| --- | --- | --- |
|
||||
| 编译成功的函数数 | **134** | **134** |
|
||||
| bailout 事件数 | 74 | 48 |
|
||||
| 有 bailout 的文件数 | 21 | 21 |
|
||||
|
||||
成功数一个没多。原因是被上游修掉的错误类别,所在函数都还有别的拦路错误。
|
||||
所以「升编译器版本」或「改用 Babel 版实现」这两条路由数据关闭,
|
||||
`babel-plugin-react-compiler` 诊断完即卸载,锁文件用 `npm ci` 权威还原(`npm uninstall` 会留下
|
||||
3 条 `dev` → `devOptional` 的元数据漂移,已还原掉),`git diff` 为空,不进交付。
|
||||
|
||||
### 这一轮改变了什么结论
|
||||
|
||||
任务 2 的验收结论不变(`Home` 未被编译),但**原因的性质变了**:
|
||||
从「不明原因的静默失败」变成「上游编译器缺陷,本仓库代码无错」。
|
||||
这直接影响后续该怎么做:不该去改 `page.tsx` 迎合编译器,该做的是按职责拆小 `Home`。
|
||||
交付物本身零变化 —— 配置仍是回滚态,`frontend/src/**` 仍是零改动。
|
||||
|
||||
## 收尾
|
||||
|
||||
`docs/BUG_HISTORY.md` 追加 `BUG-255`。按 BUG-253 的防复发要求先检索最大编号:本地基点
|
||||
|
||||
Reference in New Issue
Block a user