refactor(react): toPredicateInput 改为 re-export @object-ui/core,不再保留渲染器侧副本 - #3511
Conversation
…ead of duplicating it The renderer-side copy in packages/react/src/hooks/useExpression.ts had item-for-item identical semantics to the canonical implementation in packages/core/src/evaluator/predicateInput.ts (#3314), held in step only by a 14-shape normalization parity table. A guardrail against drift is not a single source of truth, so the twin is replaced by a re-export. The normalization parity table degenerated once both of its columns called the same function -- every row passed by construction. It is replaced by one identity assertion (react's export IS core's function object), which is strictly stronger. The engine-path vs renderer-path VERDICT parity suite is untouched: sharing a normalizer does not by itself prove the two call paths reach the same verdict. Fixes #3367
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
Type Check 红是 main 上的既存故障,不是本 PR本 PR 基于
待 #3505 落地后 rebase 本分支重跑即可。 其余门禁当前状态:Lint ✅ / Build Docs ✅ / Build & E2E ✅ / Control Byte Scan ✅ / Changeset Bump Policy ✅ / Changeset Fixed Group Check ✅ / Internal Docs Link Check ✅。 🤖 Generated with Claude Code https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt Generated by Claude Code |
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
…ired twin The paragraph still described "renderer-side code (@object-ui/react's toPredicateInput, which has identical semantics and is pinned to this one by a parity test)" -- both halves of which this branch removed: there is no twin, and the 14-shape normalization table it referred to is gone. Comment-only, lines 73-77 of the docblock. It now names the re-export and the identity assertion that pins it, and keeps the verdict parity suite explicitly distinct -- sharing a normalizer does not by itself prove the engine and renderer paths agree.
追加 rider:core 侧 docblock 已同步(PM 批准扩围)上文「遗留」一节已处理 —— PM 批准把 fence 精确扩到 原文两个断言在本分支上都已不成立: —— 既没有「语义相同的渲染器侧副本」,它所指的那张 14 形态表也已不存在。改写后点名 re-export 与钉住它的同一性断言,并显式区分判决 parity 套件仍是另一条独立主张(共用归一化并不证明两条路径判决一致)。
验证(预测:注释改动,全绿;实测一致)
按 PM 指示, 🤖 Generated with Claude Code https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt Generated by Claude Code |
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
Fixes #3367
做了什么
packages/react/src/hooks/useExpression.ts里的toPredicateInput实现体换成一行 re-export:它与 canonical 的
packages/core/src/evaluator/predicateInput.ts逐项语义相同(布尔短路;裸字符串与非celdialect 包成${…};{ dialect: 'cel', source }信封保留,好让useCondition路由到 canonical 的@objectstack/formula引擎;空/缺省归一到undefined),此前只靠一张 14 形态 parity 表钉在一起。护栏不是单一事实源 —— #3314 正是两处归一化放任不管的后果:同一条visible:谓词,取决于是ActionEngine.getActionsForLocation浮出的还是独立渲染的,会得到不同判决。re-export 不会漂移。依赖方向合法:
@object-ui/core本就是@object-ui/react的dependencies,且本文件早已从同一个 barrel importExpressionEvaluator/evalRowPredicate—— 「hook 代码不该被迫走引擎 barrel」这条旧理由在今天的代码里已不成立。反方向才是被禁止的(core 声明 "Zero React dependencies")。测试形态变更(刻意,非静默删除)
packages/react/src/hooks/__tests__/actionPredicate.parity.test.tsx里两个 describe 的处理不同,issue 也是这么区分的:expect(toPredicateInput).toBe(coreToPredicateInput):同一个函数对象 ⇒ 输入形态不可能分歧,这比枚举形态更强。逐形态行为仍有真实断言覆盖:useExpression.test.ts(经 react 导出)与下面的判决套件(经两条调用路径)。同 describe 里那条 "preserves the cel dialect" 也保留:它直接读 core 的输出,从来不依赖「两份实现」这个前提,退化的不是它。
反向验证(方向先预测,再执行)
预测:把旧的两份实现状态放回去(
git checkout origin/main -- packages/react/src/hooks/useExpression.ts,测试文件保持新版),同一性断言应当红,判决 parity 9 例与 cel 保留应当绿 —— 即 1 failed / 10 passed。实测完全一致:
断言信息里那句 "Compared values have no visual difference" 恰好就是本 issue 要消除的漂移面本身:两份看不出差别的实现,靠人眼和一张表守着。恢复后 11 passed。
行为与公开面
行为逐字节不变;
import { toPredicateInput } from '@object-ui/react'的所有既有引用路径照常可用,签名未削弱(core 的返回类型EvaluatorPredicateInput与原先内联的联合类型结构相同,没有any泄漏)。没有新增导出名 —— 类型EvaluatorPredicateInput不从 react 侧转出,公开面与改动前完全一致。tsc产物是干净的 re-export:顺带:旧实现里的 3 处
(value as any)断言随之消失(该文件as any计数 3 → 0)。star-export 隐患已按 issue 备注复核:仓内没有任何文件 star-re-export
@object-ui/core或@object-ui/react(实际上没有任何export * from '@object-ui/...'),packages/react/src/index.ts也不做 —— 不会产生 ambiguous star-export。core 侧 docblock 同步(经 PM 批准的定向扩围,纯注释)
packages/core/src/evaluator/predicateInput.ts的 73-77 行原本写着「渲染器侧代码(@object-ui/react的toPredicateInput,语义相同,由 parity 测试钉住)」—— 本分支之后两个断言都不成立:没有副本,它所指的那张 14 形态表也没了。留着它就是在 ship 一段自相矛盾的注释,正是 #3367 要消除的那一类漂移。改写后点名 re-export 与钉住它的同一性断言,并显式区分判决 parity 套件仍是另一条独立主张。
1 file changed, 13 insertions(+), 5 deletions(-),机械核验为纯注释改动(git diff -U0去掉*开头行后无剩余)。验证
pnpm exec vitest run packages/react— 32 files / 398 passed@object-ui/react取toPredicateInput的包):packages/components/src/renderers/action、packages/plugin-detail、packages/app-shell/.../DeclaredActionsBar.test.tsx— 54 files / 476 passedpnpm exec vitest run packages/core/src/actions/__tests__/ActionEngine.visibility.test.ts packages/core/src/evaluator— 10 files / 293 passedpnpm --filter @object-ui/react type-check(tsc --noEmit+ typetests 工程)/build— 均 exit 0pnpm --filter @object-ui/core type-check— exit 0eslint改动文件 — 0 errorsnode scripts/check-control-bytes.mjs— OK;check-changeset-no-major.mjs— OK远端 CI(
c2470b274):18 项检查全部 success/skipped,含Type Check✅。 早先264a5f16e上的Type Check红是 #3504 的既存故障(scripts/__tests__/check-doc-links.test.tsTS2578,本 PR 未触碰该文件);hotfix #3505 已于 02:11Z 合入 main,本 PR 的 merge-ref 随即带上修复,无需 rebase。Changeset
@object-ui/react: patch。#3314 的既有 changeset 保持不动(它描述的是那个 PR 当时的状态,历史上准确)。🤖 Generated with Claude Code
https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt