[2.0 / next] Reading a pending getter in equals leaves the UI stuck
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 5/5
- 预计耗时
- 一周以上
- 新手友好度
- 14/100
- Issue 类型
- 缺陷
- 描述清晰度
- 基本清楚
- 活跃度
- 活跃
- 技术栈
- javascript, typescript
- 领域
- frontend
调研方向
Start in packages/signals/src/core/core.ts around the synchronous comparator catch, and in packages/signals/src/core/async.ts around the async settlement catch and the shared handleError path. Both catches call notifyStatus(el, STATUS_ERROR, e) on NotReadyError, so pending reads are treated as terminal. Reproduce with the linked pending-getter playground, then check the cleanup regression in PR #3886. Done means the getter reaches Value: 2 and the cleanup test passes, which needs maintainer input on how suspension inside equals should behave.
由索引模型根据 Issue 内容生成。
描述
Describe the bug
A memo returns an object with a getter that reads an async memo. Reading the getter during rendering works with <Loading>, but reading it in equals produces an uncaught NotReadyError. The async work then resolves, yet the UI stays on the previous value.
Removing the custom comparator lets the same getter render the resolved value.
Your Example Website or App
https://s.olid.uk/id/-g2RtrPeRk-xTEPedugSCg
Steps to Reproduce the Bug or Issue
- Open the playground and wait for
Value: 0. - Click Run demo. The comparator reads the new object's getter while its async memo is unresolved. The console reports
NotReadyError. - After one second, the console logs
Resolved: 2, but the UI remains atValue: 0.
Control: remove the equals option and rebuild. Repeat the steps: the UI reaches Value: 2 without the error.
Expected behavior
A pending read through the getter should be handled by <Loading> and allow the UI to reach Value: 2 once the async work resolves. If reads that suspend are unsupported inside equals, a clear diagnostic would be preferable to an uncaught control-flow error that leaves updates halted.
Screenshots or Videos
No response
Platform
- OS: Linux
- Browser: Chromium 154.0.8037.57
- Solid: playground pinned to
next@d5e32a9af41c7bfe0bc090f7438ee4297d540b17. The comparator catches discussed below are also present on currentnext@ccd99481deed3ebb567ee11ab7a152ced84d122b.
Additional context
The comparator catches in synchronous recomputation and async settlement both unconditionally call notifyStatus(el, STATUS_ERROR, e). That appears to classify a pending read as a terminal error. Comparator reads also run outside the memo's tracking context, so classifying NotReadyError as pending alone would not establish the dependency needed to retry.
The async catch additionally bypasses the existing shared error handler, which handles promise rejections and errors from the async setter. A candidate change from #3886 is:
} catch (e) {
- notifyStatus(el, STATUS_ERROR, e);
+ handleError(e);
}
That change fixes a separate cleanup omission: if a lazy dependent loses its last consumer while the async source is pending, and the source's comparator throws on fulfillment, the dependent is left subscribed and its cleanup never runs. Cleanup playground: click Run demo and inspect Cleanup calls: 0; ordinary fulfillment and direct promise rejection each produce 1 in the same setup. The memo's owner stays alive; only its rendered consumer is removed.
Routing the async catch through handleError makes that cleanup regression pass, along with the existing comparator-error and pending-disposal tests. Non-lazy cleanup still waits for owner disposal in the tested case. However, this change alone does not make the pending-getter example recover: the async version instead reports an untracked-read diagnostic. The synchronous comparator catch and the intended handling of suspension inside comparators need consideration too.
#3886 contains the candidate async-handler change and cleanup regressions. That comparator-release case was outside #4085's held-error scope.
- 主要语言
- TypeScript
- 星标
- 36.2k
- 派生
- 1.1k
- 平均合并
- 11 小时 19 分钟
- 30 天内合并 PR
- 337
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
solidjs/solid 的其他 Issue
-
`lazy()`: remounting an already-loaded component renders empty (or the Suspense fallback) since 1.9.14可能已有人在做 @itisrmk 于 8 天前认领。 未关闭1.x
难度 2/5 1-3 小时 新手友好度 62/100
维护者通常 1 天内回复
-
2.0.0-rc.18 | `await refresh(memo)` hangs in an action after an optimistic write and a dependency change可能已有人在做 关联的 PR 仍在进行中或已合并。 未关闭
难度 4/5 3-5 天 新手友好度 57/100
维护者通常 1 天内回复
-
[2.0] IMMUTABLE_UPDATE_IN_STORE false positive when an in-place `splice` shifts the next item into the removed index可能已有人在做 关联的 PR 仍在进行中或已合并。 未关闭
难度 3/5 1-2 天 新手友好度 55/100
维护者通常 1 天内回复
-
enhancement
难度 5/5 一周以上 新手友好度 35/100
维护者通常 1 天内回复
-
`createRoot`'s dispose function keeps `fn` alive, so `<For>`/`<Index>` rows retain removed list items可能已有人在做 @boombang 于 11 天前认领。 未关闭1.x
难度 4/5 1-2 天 新手友好度 45/100
维护者通常 1 天内回复
相似的 Issue
-
bug
难度 2/5 1-3 小时 新手友好度 76/100
awslabs/visual-asset-management-system#804 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 70/100
restatedev/sdk-typescript#813 ·
-
bug desktop P1 session XS
难度 2/5 1-3 小时 新手友好度 82/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 62/100
Merit-Systems/x402scan#1312 ·
-
type:bug
难度 2/5 1-3 小时 新手友好度 78/100
Azure/apiops-cli#331 ·
维护者通常 3 天内回复