[2.0 / next] laneRead's D-28 verdict-seat reset compares verdict lanes by identity; a merged transaction's lane reads as another hold's

Đã đóng
#4,427 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

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
1-2 ngày
Mức phù hợp với người mới
43/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ệ
javascript, typescript
Lĩnh vực
frontend, performance

Hướng nghiên cứu

Start by reading the D-28 reset and reader-seat logic referenced in #4275, #4284, and #4395, then reproduce the reported case in packages/web/test/async-gen with seed 3289, case #43. Check how the verdict-seat comparison handles transactions merged through _into; done when the merged hold keeps the reader seated and reads the lane value, with the async-gen regression case passing.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Summary

laneRead's D-28 reset (#4275, #4284) — "a verdict lane's seat does not carry a leaf into another lane" — compares verdict lanes by object identity: passLane !== l && passLane._parent._verdict === passLane. After a transaction merge (A._into = B), A's verdict lane and B's verdict lane are two objects for one hold. A render effect seated as B's verdict reader (its latest() of a node B holds routed it to verdictLane(txOf(el)), resolved) then reads a derivation that still sits in A._verdict (its _x._transaction was stamped before the merge): the reset fires as if the leaf had crossed into another hold's lane, passLane is cleared, and the leaf is served the staging through the L7' arm (c held by the flush's transaction) instead of staying seated and reading the lane's value.

The hold is the same; only the lane object differs. The leaf leaves its own hold's verdict seat for the rest of the pass.

Reproduction

async-gen seed 3289 case #43 (packages/web/test/async-gen):

const sc = fc.sample(scenarioArb(), { seed: 3289, numRuns: 44 })[43];
await runScenario(sc);
[s0=1 s1=2 m0=memo(latest(s1) !%4=3) m1=async(latest(s1) !%4=0)]
<span split[s1()]>s0()</span><Show when=m0()><span></span></Show><Loading><span fx[latest(s1),m1()]>m0()</span></Loading>
:: f A(s1=1) s0=1 s1=0 s0=3 s0=3 m S1 A(s0=3)
scenario JSON
{"signals":[1,2],"memos":[{"async":false,"deps":[{"src":{"k":"s","i":1},"how":"latest"}],"poison":3},{"async":true,"deps":[{"src":{"k":"s","i":1},"how":"latest"}],"poison":0}],"tree":{"t":"group","kids":[{"t":"leaf","text":[{"how":"plain","src":{"k":"s","i":0}}],"attrs":[{"how":"plain","src":{"k":"s","i":1}}],"grouped":false},{"t":"show","when":{"how":"plain","src":{"k":"m","i":0}},"child":{"t":"leaf","text":[],"attrs":[],"grouped":true},"fallback":false},{"t":"loading","child":{"t":"leaf","text":[{"how":"plain","src":{"k":"m","i":0}}],"attrs":[{"how":"latest","src":{"k":"s","i":1}},{"how":"plain","src":{"k":"m","i":1}}],"grouped":true}}]},"steps":[{"t":"flush"},{"t":"action","s":1,"v":1},{"t":"write","s":0,"v":1},{"t":"write","s":1,"v":0},{"t":"write","s":0,"v":3},{"t":"write","s":0,"v":3},{"t":"micro"},{"t":"settle","pick":1},{"t":"action","s":0,"v":3}]}

The fx[latest(s1), m1()] render effect reads latest(s1) (held → seated as the hold's verdict reader), then m1 — a verdict-lane derivation whose lane's _parent has been merged (resolveTx(l._parent) !== l._parent) into the very hold the leaf is seated for. Observed: passLane reset, m1's staging served (L7'). The reader-seat table (#4395, row V6/L6) compares holds, not lane objects: no leave, the lane's value.

Found by the S1 reader-seat differential: class V6 expected Lv, got P — slot (V posture; s u d ip vlane parentMerged shown · cU cH cOtherTx t1 w2 vseat oldNoLane flushTx flushNotElTx) plus the downstream verdict seat at the pass's end (old none, new seated), 1 case in the 1500-case regression gate, none in the signals or web suites. The case's screens are all [ROOT-E] (the m0 poison), so nothing visible differs here; the mechanism is wrong independent of the screen.

Why it is a bug

  • D-28 / #4284: the leaf leaves the verdict seat for a lane that is not that hold's. A merged transaction's verdict lane is that hold's.
  • Lane identity surviving a merge is a #3905-adjacent artifact (verdictLane(t) is per transaction object; nodes stamped before the merge keep the old lane). Every other seat comparison in the engine resolves (txOf, resolveTx); this one does not.

Intended fix

The reader-seat rebuild S1 (#4395) decides the leave from the seat's hold (resolveTx(vhold) !== resolveTx(l._parent)), which fixes this by construction. Until the swap lands, the shadow carries this as a known class (shadowKnown, this issue). #3905 (transaction merging) is the structural fix for lanes keeping pre-merge identities and stays out of scope here.

Ngôn ngữ chính
TypeScript
Star
36.2k
Fork
1.1k
Merge trung bình
11 giờ 5 phút
Pull request đã merge (30 ngày)
475

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. 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.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của solidjs/solid

Tất cả issue của solidjs/solid

Issue tương tự

Thêm issue về TypeScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.