signals: a chain's verdict flips to false mid-hold where a diamond's stays true (graph shape is observable)
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 15/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- typescript
- Lĩnh vực
- frontend
Hướng nghiên cứu
Start with settlePendingSource in packages/signals/src/core/async.ts, tracing how a superseded flight's settle retires a pending node's state. Compare the single-arrival chain path with the second-arrival diamond path that re-marks staged errors. Use packages/signals/tests/settle-diamond-revisit.test.ts as the template for a chain pin. Done when the chain yields false:3, true:3, E:boomA, false:6.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
What happens
The same reads produce different frames depending on whether the derivation is a chain or a diamond. During a held action, a chain's isPending drops to false while the hold is still open. A diamond's stays true until the commit. Graph shape shouldn't be observable.
Found while reviewing #4560. It reproduces the same way on next (404d06a) and on #4560, so it isn't caused by that PR.
Repro
const [s, setS] = createSignal(0);
const A = createMemo(async () => {
const v = s();
await Promise.resolve();
if (v === 2) throw new Error("boomA");
return v;
});
const B = createMemo(() => A() + 1);
// chain: C = B + 2; D = C
// diamond: C = A + 2; D = B + C
const view = createErrorBoundary(() => `${isPending(D)}:` + D(), e => `E:${e().message}`);
createRenderEffect(view, v => log.push(v));
Steps:
- Let the first load settle.
setS(1); flush().- Run
action(function* () { setS(2); yield new Promise(r => (release = r)); })()and let it tick. - Call
release()and let it tick twice. setS(3); flush(), then let it tick.
| Shape | Frames |
|---|---|
| diamond | false:3, true:3, E:boomA, false:9 |
| chain | false:3, true:3, false:3, E:boomA, false:6 |
The diamond's frames are pinned in packages/signals/tests/settle-diamond-revisit.test.ts (#4560).
The frames
false:3: the first load committed (A = 0).true:3:s = 1is a new question. A's flight is out, D's dependents are pending, and the screen keeps 3.- The action's
setS(2)re-asks A inside a hold, superseding thes = 1flight. That flight throwsboomA, and the error is staged in the hold (D-41). The hold stays open untilrelease(). - Chain only,
false:3: while the hold is still open, the view re-runs and readsisPending(D) === falsewith the committed 3. The diamond emits nothing here. E:boomA: the commit publishes the staged error.false:6/false:9:s = 3lands.
Ruling: the chain is wrong (F-9, with F-2)
- F-9.
isPending(x)is true "iff x's value is not the final answer to a new question: an input changed and the new answer has not been committed, a landed answer waits in a hold…". At frame 4 the input has changed (sis 1, then 2 in the hold), no new answer has been committed, and the staged answer is still waiting in the hold. Nothing has answered thes = 1question; the hold superseded it. SoisPending(D)must staytrueuntil the commit, which is what the diamond shows. - F-2. "A change that needs async to be shown is held; the screen keeps what it showed." The screen showed
true:3. Flipping it tofalse:3mid-hold changes what is shown before the commit, with no commit behind the change.
So the expected chain frames are false:3, true:3, E:boomA, false:6.
Where to look
The difference lives in settlePendingSource (packages/signals/src/core/async.ts).
When the superseded flight's source settles, the walk retires D's pending state through the branch that carried it. In the diamond, D is reached a second time through the other branch. That second arrival takes the walk's early-return path, which re-runs a verdict reader or marks a staged error (stageMark), and that keeps D's verdict tied to the staged frame. In the chain there is only one arrival, so nothing re-marks D, and the view re-derives isPending(D) as settled while the hold is still open.
A likely fix is for the chain's single arrival to do what the diamond's second arrival does: a node that inherits the staged error, or whose verdict reads the hold, keeps that mark rather than reading as settled. Pin the chain frames above alongside the diamond pin.
Not fixed in #4560 on purpose: that PR keeps next's behaviour exactly.
- Ngôn ngữ chính
- TypeScript
- Star
- 36.2k
- Fork
- 1.1k
- Merge trung bình
- 10 giờ 39 phút
- Pull request đã merge (30 ngày)
- 500
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của solidjs/solid
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 55/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
Maintainer thường phản hồi trong vòng 1 ngày
-
[2.0 / next] Optimistic todo list with an "N left" memo loops forever when a toggle's save landsĐang mở
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 15/100
Maintainer thường phản hồi trong vòng 1 ngày
-
[2.0 / next] createOptimisticStore: add, delete, add with saves pending hands <For> an undefined rowĐang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 25/100
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của solidjs/solid
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Broken links in the docsĐang mở
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 83/100
Maintainer thường phản hồi trong vòng 1 ngày
-
🔊 a11y
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
betagouv/mon-entreprise#4726 ·
Maintainer thường phản hồi trong vòng 9 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
Deltares/fews-pi-requests#357 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug confirmed js v6
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
Maintainer thường phản hồi trong vòng 1 ngày