L2: mount triggered by latest() shows content beside the committed value
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
- 55/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả 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 the provided failing vitest repro under packages/signals/tests, run it to confirm slot reads "content 1" while screenX stays 0. Then read the first-pass lane rule in recompute (packages/signals/src/core/core.ts) alongside the SPEC's lane rule and A29 boundary-scope note to see why a pass created inside a verdict lane inherits that lane instead of staying mainline. Done means the repro passes (slot equals "fallback" during the hold) without breaking the existing lane, loading-boundary and optimistic-lane tests — expect to consult the SPEC draft for proto/3540-boundary-scope before touching semantics.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Summary
Inside an action, a <Show when={latest(x) > 0}> opens at once, which is expected, because latest() is display-ahead. But the new <Loading> it mounts shows content 1 while everything else on screen still shows the committed x = 0. Under the lane rule, a verdict lane's mounts stay mainline, so the mounted content belongs to the screen's world, not the proposal's. This is a torn frame.
Repro (packages/signals/tests, vitest)
import { expect, it } from "vitest";
import {
action,
createLoadingBoundary,
createMemo,
createRenderEffect,
createRoot,
createSignal,
flush,
latest,
untrack
} from "../src/index.js";
const settle = async () => {
for (let i = 0; i < 3; i++) {
await new Promise(r => setTimeout(r, 0));
flush();
}
};
it("a mount triggered by latest() shows its content beside the committed value", async () => {
const [x, setX] = createSignal(0);
let screenX: unknown;
let slot: unknown;
createRoot(() => {
// <p>{x()}</p>
createRenderEffect(x, v => {
screenX = v;
});
// <Show when={latest(x) > 0}>
// <Loading fallback="fallback">content {x()}</Loading>
// </Show>
const when = createMemo(() => latest(x) > 0);
const children = createMemo(() =>
when()
? untrack(() =>
createLoadingBoundary(
() => `content ${x()}`,
() => "fallback"
)
)
: "closed"
);
createRenderEffect(
() => {
const c = children();
return typeof c === "function" ? c() : c;
},
v => {
slot = v;
}
);
});
flush();
expect([screenX, slot]).toEqual([0, "closed"]);
let release!: () => void;
const done = action(function* () {
setX(1);
yield new Promise<void>(r => (release = r));
})();
await settle();
// The action holds x = 1; the screen still shows x = 0.
expect(screenX).toBe(0);
// Actual: "content 1" beside the committed 0.
expect(slot).toBe("fallback");
release();
await done;
await settle();
expect([screenX, slot]).toEqual([1, "content 1"]);
});
The repro fails at expect(slot).toBe("fallback") with Received: "content 1". The same thing happens when the content is a memo, createMemo(() => \content ${x()}`)`.
Expected vs actual
| Checkpoint | Expected | Actual |
|---|---|---|
| Before the action | x = 0, slot closed |
x = 0, slot closed |
Action holds x = 1 |
x = 0, slot fallback |
x = 0, slot content 1 |
| Action ends | x = 1, slot content 1 |
x = 1, slot content 1 |
Rules involved
- The lane rule: an optimistic lane sees the screen plus its own guesses, and its mounts' children are the lane's. A verdict lane computes the real outcome, and its mounts stay mainline. Here the
Showcondition is verdict-lane work, and its children are seated in that lane. The newLoading's first pass inherits the lane from the pass that created it, so it reads the proposalx = 1. - A29's boundary scope (2026-10-06): a loading boundary that has not shown content owns its subtree. Content that reads a hold waits behind the boundary's fallback, and it appears at the hold's commit.
- No tearing: content on screen agrees with the screen's value of what it reads.
The suspected site is the first-pass lane rule in recompute (core/core.ts). A first pass takes its creator's lane, which is right for an optimistic lane (ruling A). For a verdict lane, it should stay mainline.
Where it reproduces
next(ba67ddbaa)- #3835's branch (
ae59c7682) - #3824's head (
3ab71b0dc) proto/3540-boundary-scope(60d2f1ded). Its SPEC draft already lists this shape as open ("a boundary a verdict reader mounts … shows the held derivation now rather than its fallback").
Provenance
Found by the semantic fuzzer's mount-under-hold cohort, verdict family (fuzz/semantic-fuzzer-l2, b2bdf125a, rules MH1 and MH5). It probably shares a root with the read-order mount family (fuzzer cases 827, 416 and 936). There, a latest() read routes a freshly mounted child into the verdict lane, its mount control publishes alone, and the slot stays empty. In both cases a pass picks up verdict-lane membership that the lane rule says stays mainline: through a read in the read-order family, and through its creator here.
- Ngôn ngữ chính
- TypeScript
- Star
- 36.1k
- Fork
- 1.1k
- Merge trung bình
- 11 giờ 25 phút
- Pull request đã merge (30 ngày)
- 345
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ó 5/5 Hơn một tuần Mức phù hợp với người mới 12/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Select loses its bound value when options load asynchronouslyCó thể đã có người làm @MokiMeow đã nhận hôm nay. Đang mở
Độ khó 3/5 Nửa ngày Mức phù hợp với người mới 45/100
solidjs/solid#3928 · 1 bình luận ·
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 18/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 24/100
solidjs/solid#3923 · 1 bình luận ·
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ự
-
Mondriaan
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
knaw-huc/textannoviz#709 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Add: YRF Music NepalĐang mởstreams:add
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 62/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
walletbeat/walletbeat#1558 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
hawk-digital-environments/HAWKI#438 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
good first issue
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
OktoLabsAI/okto-pulse#114 ·
Maintainer thường phản hồi trong vòng 1 ngày