来源
发现自 #3842 实施时的全仓扫面(grep "disabled != null")。#3842 的正文只点了两处落点,PM 也据此把范围裁成两处;实际同形的还有五处,不在其修法面,故独立成单,未认领。
机理
与 #3842 逐字相同:「是否声明了 disabled / enabled 门」的判定停在 != null,少了 !== ''。于是 disabled: '' 被判成「声明了门」,verdict 交给求值入口,而求值入口把空谓词读成「没有条件 → true」—— 在 disabled 方向上 true 意味着禁用,空谓词从「没有门」变成「永久置灰」。完整机理与探针见 #3842。
enabled 那条 legacy 腿在这五处同样停在 != null,但该腿取反(disabled = !isEnabled),空谓词的 true 落成「不置灰」,与「没有门」同一结果 —— 所以 enabled 腿是行为等价、不是缺陷,改它只为「已声明」在两条腿上只有一种拼法(#3842 的 PR 里有四形状推演表)。
五处落点(origin/main = aca561a77fd0dc793ea76a7b46cd037e1731eb93)
| # |
文件:行 |
组件 |
| 1 |
packages/components/src/renderers/action/action-icon.tsx:97 |
action:icon |
| 2 |
packages/components/src/renderers/action/action-group.tsx:106 |
action:group 内联按钮(InlineActionButton) |
| 3 |
packages/components/src/renderers/action/action-group.tsx:148 |
action:group 下拉项(DropdownActionItem) |
| 4 |
packages/components/src/renderers/action/action-menu.tsx:98 |
action:menu 项 |
| 5 |
packages/plugin-detail/src/renderers/record-quick-actions.tsx:208 |
记录快捷动作(与 DeclaredActionsBar 同拼法,无 enabled 腿) |
这五处的 visible 门都已经在读 hasDeclaredVisibilityGate(#3812 / PR #3825、#3823 / PR #3836),同一文件同一按钮上,visible 问「已声明」而 disabled 问 != null —— 一处组件里两种拼法。
可达性
不需要重新论证:这五处的 visible 门可达性已由 #3812 / #3823 建立并各自钉住(action:bar 绕过 SchemaRenderer 直接把成员铺到子渲染器的 schema 上;action:group / action:menu 自己 map 成员;record-quick-actions 由 plugin-detail 直接挂载)。disabled 与 visible 在同一个渲染函数体内,同一条路。
差别在于 SchemaRenderer 对这两个键不等价:packages/react/src/SchemaRenderer.tsx:323 会读 newSchema.disabled !== undefined(注意是 !== undefined,又是第三种拼法),所以走 SchemaRenderer 的路径上还另有一层;action:bar 成员路径不走它。实施时请按落点逐一确认,不要整批假设。
影响
命中条件同 #3842(元数据里出现 disabled: '')。这五处是通用动作面(工具条、下拉、记录快捷动作),不像 #3842 的审批收件箱那样有单一高价值宿主,但覆盖面更广。严重度请分诊裁。
修法(与 #3842 一致,应无新决定)
五处改读 hasDeclaredVisibilityGate(@object-ui/components barrel 已导出;plugin-detail 从 barrel 取,包内三处从 ./visibility-gate 取),就地注释说明名称系历史、语义为谓词通用(#3842 已裁不重命名、不加别名)。钉子按 #3842 的形态:四形状('' 不置灰 / true 置灰 / false 不置灰 / 未声明不置灰)× 每处落点,enabled 腿按推演写明行为等价。
反向验证方向可以预判:还原 != null 后 '' 一例钉红(disabled 侧 '' 是真的变异探测器,与 visible 侧相反 —— 原因见 #3842)。
Related: #3842(同族,已修两处,PR 分支 claude/issue-3842-disabled-declared-gate)、#3848(执行入口 ActionRunner 的同族半边)、#3492(不变量出处)、#3812 / #3823 / #3835(visible 侧同批落点)。未认领。
来源
发现自 #3842 实施时的全仓扫面(
grep "disabled != null")。#3842 的正文只点了两处落点,PM 也据此把范围裁成两处;实际同形的还有五处,不在其修法面,故独立成单,未认领。机理
与 #3842 逐字相同:「是否声明了
disabled/enabled门」的判定停在!= null,少了!== ''。于是disabled: ''被判成「声明了门」,verdict 交给求值入口,而求值入口把空谓词读成「没有条件 →true」—— 在disabled方向上true意味着禁用,空谓词从「没有门」变成「永久置灰」。完整机理与探针见 #3842。enabled那条 legacy 腿在这五处同样停在!= null,但该腿取反(disabled = !isEnabled),空谓词的true落成「不置灰」,与「没有门」同一结果 —— 所以enabled腿是行为等价、不是缺陷,改它只为「已声明」在两条腿上只有一种拼法(#3842 的 PR 里有四形状推演表)。五处落点(
origin/main=aca561a77fd0dc793ea76a7b46cd037e1731eb93)packages/components/src/renderers/action/action-icon.tsx:97action:iconpackages/components/src/renderers/action/action-group.tsx:106action:group内联按钮(InlineActionButton)packages/components/src/renderers/action/action-group.tsx:148action:group下拉项(DropdownActionItem)packages/components/src/renderers/action/action-menu.tsx:98action:menu项packages/plugin-detail/src/renderers/record-quick-actions.tsx:208DeclaredActionsBar同拼法,无enabled腿)这五处的
visible门都已经在读hasDeclaredVisibilityGate(#3812 / PR #3825、#3823 / PR #3836),同一文件同一按钮上,visible问「已声明」而disabled问!= null—— 一处组件里两种拼法。可达性
不需要重新论证:这五处的
visible门可达性已由 #3812 / #3823 建立并各自钉住(action:bar绕过SchemaRenderer直接把成员铺到子渲染器的 schema 上;action:group/action:menu自己 map 成员;record-quick-actions由 plugin-detail 直接挂载)。disabled与visible在同一个渲染函数体内,同一条路。差别在于
SchemaRenderer对这两个键不等价:packages/react/src/SchemaRenderer.tsx:323会读newSchema.disabled !== undefined(注意是!== undefined,又是第三种拼法),所以走SchemaRenderer的路径上还另有一层;action:bar成员路径不走它。实施时请按落点逐一确认,不要整批假设。影响
命中条件同 #3842(元数据里出现
disabled: '')。这五处是通用动作面(工具条、下拉、记录快捷动作),不像 #3842 的审批收件箱那样有单一高价值宿主,但覆盖面更广。严重度请分诊裁。修法(与 #3842 一致,应无新决定)
五处改读
hasDeclaredVisibilityGate(@object-ui/componentsbarrel 已导出;plugin-detail从 barrel 取,包内三处从./visibility-gate取),就地注释说明名称系历史、语义为谓词通用(#3842 已裁不重命名、不加别名)。钉子按 #3842 的形态:四形状(''不置灰 /true置灰 /false不置灰 / 未声明不置灰)× 每处落点,enabled腿按推演写明行为等价。反向验证方向可以预判:还原
!= null后''一例钉红(disabled侧''是真的变异探测器,与visible侧相反 —— 原因见 #3842)。Related: #3842(同族,已修两处,PR 分支
claude/issue-3842-disabled-declared-gate)、#3848(执行入口ActionRunner的同族半边)、#3492(不变量出处)、#3812 / #3823 / #3835(visible侧同批落点)。未认领。