Repository navigation
Replies: 2 comments
你把两件事串起来了,而两件我都能对上代码1. 插槽崩溃只留一个空 div——这点我核过
console.error(`slot entry crashed in '${this.props.slotKey}':`, error) // :413
if (this.state.failed) return <div data-slot-error={this.props.slotKey} /> // :417⇒ 一旦条目崩溃,它只渲染一个带 注意你报告里那句"abdicate 后又重新注册、再次崩溃"——这解释了刷屏:重新注册 ⇒ 新条目 ⇒ 再次崩溃,而没有退避或上限。建议把这句写成一条独立诉求:同一插槽反复崩溃时应有退避/上限。 2. 图标改名这条:导出面确实带
|
|
确认一下:这个缺陷在 0.2.1-rc.3 上仍然存在,而且触发面不止 我们遇到的真实案例(不是最小复现,是用户侧事故):一个第三方插件( 以下代码坐标都取自 0.2.1-rc.3 的 在楼主报告的基础上,我们往前多走了一步:那个空 div 是永久的楼主停在「边界接住后只渲染一个空 div」。实际链路还长一节:
我们现查了 所以用户侧的感受不是「某块渲染失败了」,而是「这块区域从来就不存在」。这一点比「空 div」更严重:空 div 至少还暗示「这里应该有东西」。 一个附带观察(供参考,不是本条的诉求)
诉求(与楼主一致,按我们的场景再压一遍)
我们这边能做的规避只是把风险从「整列消失」压回「图标不显示」(所有插件内组件都包了自己的边界),但那是每个插件作者各包一遍,治不了根。 Environment
🤖Powered by Gruu6y-DSH🤖 |
Uh oh!
There was an error while loading. Please reload this page.
Summary
第三方插件向
settings.section贡献的整个设置页,只要渲染期抛出一次异常,宿主就只渲染一个空的<div data-slot-error="settings.section">—— 用户看到的是一整块空白,没有任何可见提示;同时该条目被 abdicate 后又重新注册、再次崩溃,控制台被slot entry crashed in 'settings.section'刷屏。而这类异常极易被一个与业务无关的原因触发:
primitives种子包的图标导出在 dsh 0.2.0 里改名了(去掉尺寸后缀),第三方插件里写死的旧名取出来是undefined,jsx(undefined)即 React #130。也就是说,一个「图标缺了」级别的小问题,最终结果是第三方插件的整页设置面板消失。受影响对象:所有向
settings.section贡献页面、且引用了primitives.Icon*的第三方插件作者及其用户。Reproduction
最小复现(任意第三方插件客户端):
在 dsh 0.2.0-rc.2 上打开「设置」并选中该条目:
实际触发案例(从 0.2.0-rc.2 发布产物
@deepseek-ai/dsh-client-ui-primitives反查,三个旧名均已不存在):IconSkillOutline16IconSkillOutlineIconSearchOutline16IconSearchOutlineIconChevronDownOutline14IconChevronDownOutlineCurrent behavior
从 0.2.0-rc.2 发布产物
@deepseek-ai/dsh-client-ui-renderer反查到的行为:回退面不可见。
SlotErrorBoundary命中后只渲染一个空块:该 div 没有任何样式与文案,高度为 0 —— 用户侧的表现是「设置页没了」,无法区分是插件坏了、被卸载了,还是宿主出问题了。
崩溃被放大成循环。
componentDidCatch走reportEntryError(slotKey, entry, error, { abdicate: spec.kind !== "chain" }),settings.section是list槽所以会 abdicate;条目被摘除后插件侧ctx.slots.inject("settings.section", () => ctx.slots.register(…))再次注册,于是「注册 → 崩溃 → 摘除 → 再注册」循环,控制台被同一条错误刷屏。getDerivedStateFromError对两类错误一视同仁:SlotAssemblyError(宿主装配问题)主动 rethrow,其余渲染异常一律吞掉并渲染空 div。但上面这种「可选图标取不到」本质上是可降级的局部问题,不是装配错误。Expected behavior
data-slot-error容器带上可读文案与出错条目身份(slot key + entry id / label),例如「此设置页加载失败:技能(dsh-skill-mcp-panel)」。让用户与插件作者都能一眼定位是谁、哪个页面坏了。primitives种子契约的兼容或告警:图标这类导出跨版本改名时,要么保留旧名别名一个次版本周期,要么在插件物化阶段(materialize)就console.error明确列出缺失的导出名 —— 现在只能在渲染崩溃后从一条被 React 压缩过的 安全建议:在远程认证完善前,不建议绕过 dsh web 的非 loopback 暴露限制 #130 里反推,定位成本很高。onEntryError/ 自定义 fallback 的口子,让插件作者能渲染自己的降级 UI。Environment
@deepseek-ai/dsh-desktop-runtime0.2.0-rc.2(Electron 44.0.0 / Node 24.18.1)settings.section且引用primitives.Icon*的第三方插件附注
插件侧我已通过「图标兼容层 + 全部图标走解析函数」规避了这次崩溃(按新名→旧名取第一个存在的导出,全缺失时渲染 null),但这只是把风险从「整页空白」压回「图标不显示」。上面 1–3 才是治本:一个图标缺失,不应该让第三方插件的整页设置面板消失。
All reactions