Found while implementing #5201 by measuring which render path a non-builtin field type actually takes. Out of that card's scope (input branch only) — recorded, not fixed there.
观察到的现象(已实测,不是推断) packages/components/src/renderers/form/form.tsx 的字段渲染在没有 field: 命名空间 widget 时回退到 bare-name 解析 ComponentRegistry.get(type)。packages/components/src/renderers/form/input.tsx:89 把 email(以及 password)注册成 ui namespace 的 SDUI 节点渲染器 —— 它们是给顶层 { type: 'email' } 节点用的,不是 field widget。于是一张手写 FormSchema 里的 { name, type: 'email' } 字段,悄悄落进那条 "non-field component reached through the bare-name fallback" 的路径。
实测(渲染内建分支,不调 registerAllFields();dump getAttributeNames()):
ComponentRegistry.get('email') = true ComponentRegistry.get('field:email') = false
type:'email' + max_length: 50
attrs=["class","id","max_length","field","aria-describedby","aria-invalid","type","value","name"]
maxlength=null
两件事同时发生:
field 泄漏到 DOM。 它是 raw metadata 对象 ;该路径走 stripRegisteredFieldProps,而那份剥离表刻意保留 field(它是注册 widget 的元数据载体,objectui#3233),但这个组件不是 field widget —— 它把收到的 props 直接摊到元素上,于是 field 变成元素上的一个游离属性。同族口径见 plugin-dashboard: DashboardRenderer's widget grid spreads the whole SDUI node onto its container — 13 non-DOM attributes reach the DOM #4432 / finding(plugin-dashboard): the #3291 toDomProps whitelist stops at packages/fields — SDUI widgets elsewhere still close their DOM leak by hand, if at all #4425 (toDomProps 白名单只覆盖到 packages/fields)。max_length 同样泄漏,且没有任何上限 (maxlength=null)—— 与 内建 form 分支的 input 字段:legacy max_length 拼法拿不到任何 maxlength 上限,只在 DOM 上留下一个失效属性 #5201 、以及回退分支的那张同族卡一致。需要先判的那一问,不要直接改 这里有两种读法,通向两种架构,所以本单不带修复方案 :
两者的取舍不能从 #5201 的结论推出来,交 triage。
起点 检索记录 search_issues 跑过 email / bare-name fallback / SDUI node renderer / DOM leak 关键词;命中的 open 卡只有 #4425 (相关但不同面:它讲 plugin-dashboard 的 SDUI widget),无重复单。
Found while implementing #5201 by measuring which render path a non-builtin field
typeactually takes. Out of that card's scope (inputbranch only) — recorded, not fixed there.观察到的现象(已实测,不是推断)
packages/components/src/renderers/form/form.tsx的字段渲染在没有field:命名空间 widget 时回退到 bare-name 解析ComponentRegistry.get(type)。packages/components/src/renderers/form/input.tsx:89把email(以及password)注册成uinamespace 的 SDUI 节点渲染器 —— 它们是给顶层{ type: 'email' }节点用的,不是 field widget。于是一张手写FormSchema里的{ name, type: 'email' }字段,悄悄落进那条 "non-field component reached through the bare-name fallback" 的路径。实测(渲染内建分支,不调
registerAllFields();dumpgetAttributeNames()):两件事同时发生:
field泄漏到 DOM。 它是 raw metadata 对象;该路径走stripRegisteredFieldProps,而那份剥离表刻意保留field(它是注册 widget 的元数据载体,objectui#3233),但这个组件不是 field widget —— 它把收到的 props 直接摊到元素上,于是field变成元素上的一个游离属性。同族口径见 plugin-dashboard:DashboardRenderer's widget grid spreads the whole SDUI node onto its container — 13 non-DOM attributes reach the DOM #4432 / finding(plugin-dashboard): the #3291toDomPropswhitelist stops atpackages/fields— SDUI widgets elsewhere still close their DOM leak by hand, if at all #4425(toDomProps白名单只覆盖到packages/fields)。max_length同样泄漏,且没有任何上限(maxlength=null)—— 与 内建 form 分支的 input 字段:legacymax_length拼法拿不到任何 maxlength 上限,只在 DOM 上留下一个失效属性 #5201、以及回退分支的那张同族卡一致。需要先判的那一问,不要直接改
这里有两种读法,通向两种架构,所以本单不带修复方案:
toDomProps白名单,像 finding(plugin-dashboard): the #3291toDomPropswhitelist stops atpackages/fields— SDUI widgets elsewhere still close their DOM leak by hand, if at all #4425 说的那样把守卫推到packages/fields之外。范围小,但没解决「一个 form 字段本就不该落进 SDUI 节点渲染器」。uinamespace 的节点渲染器。那是更正的形状,但会改变type: 'email'/type: 'password'字段今天的渲染结果(它们目前确实渲染出一个可用的 input),属于行为改动,需要先定夺。两者的取舍不能从 #5201 的结论推出来,交 triage。
起点
packages/components/src/renderers/form/form.tsx——RegisteredComponent/namespacedWidget解析,以及其下 non-field 分支packages/components/src/renderers/form/input.tsx:89(email)与其后的password注册DashboardRenderer's widget grid spreads the whole SDUI node onto its container — 13 non-DOM attributes reach the DOM #4432(已关)、finding(plugin-dashboard): the #3291toDomPropswhitelist stops atpackages/fields— SDUI widgets elsewhere still close their DOM leak by hand, if at all #4425(open,toDomProps白名单覆盖面)检索记录
search_issues跑过 email / bare-name fallback / SDUI node renderer / DOM leak 关键词;命中的 open 卡只有 #4425(相关但不同面:它讲 plugin-dashboard 的 SDUI widget),无重复单。