[2.0 rc.20] SSR: concurrent renders sharing a lazy() component's first load read another render's async memo value
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 12/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- javascript, typescript
- 領域
- frontend
調査の方向性
Start with the repro gist and its run.mjs, which runs the concurrent renders and prints the per-render tag results. The bug is in the lazy() resolution path, so compare it with the async memo retry fix referenced as #3983, which covers a different path. Done means the gist prints ok for the lazy, no Loading, awaited case with each render showing its own tag.
索引モデルが issue の本文から書いたものです。
説明
Describe the bug
Concurrent server renders that share the first load of a module-level lazy() component read one render's async memo value in every other render. Six renders of the same app, each with its own tag, all print the first render's memo value:
LEAK lazy, no Loading, awaited a:a b:a c:a d:a e:a f:a
Each page prints <its tag>:<the tag its async memo resolved to>. The memo in render b is created with b and resolves to { tag: "b" }, yet render b's HTML shows a.
It takes all of these together:
- a module-level
lazy()component, whose first load the concurrent renders share (as a router's lazy route is on a cold server) - an async
createMemoinside it - no
<Loading>above it await renderToStream(...), the promise form
Each of these controls passes: the same component rendered eagerly, wrapped in <Loading>, streamed through .pipe(), or with the lazy component loaded once before the concurrent renders.
This looks like the same class as #3972 (an async memo's retry running under another concurrent render's context, fixed in #3983), reached through the lazy() resolution path, which that fix doesn't cover. It still reproduces on 2.0.0-rc.20.
Impact. A server that renders concurrent requests in one process, for example a Cloudflare Worker isolate or a Node server, shows one request's async data in another request's HTML whenever a lazy route's first load is shared. We hit it as prerendered pages in four locales showing a fifth locale's messages. For per-user data, it would show one user's data to another.
Your Example Website or App
https://gist.github.com/lovrozagar/ee7c5e9af6f593a98923595a658d3318
Steps to Reproduce the Bug or Issue
- Download the gist into a folder.
bun install(ornpm install).bun run repro, which runsvite build && node run.mjsand exits 1 on a leak.
Expected behavior
Every render shows its own memo value:
ok lazy, no Loading, awaited a:a b:b c:c d:d e:e f:f
Screenshots or Videos
Full output on 2.0.0-rc.20:
LEAK lazy, no Loading, awaited a:a b:a c:a d:a e:a f:a
ok eager, no Loading, awaited a:a b:b c:c d:d e:e f:f
ok lazy, in Loading, awaited a:a b:b c:c d:d e:e f:f
ok lazy, no Loading, piped a:a b:b c:c d:d e:e f:f
ok lazy already loaded, awaited a:a b:b c:c d:d e:e f:f
Platform
solid-js/@solidjs/web/@solidjs/signals: 2.0.0-rc.20 (same output on rc.18 and rc.19)@solidjs/vite-plugin: 3.0.0-next.55 (rc.18 run: 3.0.0-next.51)vite: 8.3.5- Node: 26.12.1, Linux
Additional context
In a real app the leaked value comes from the router's lazy route. A minimal version with @solidjs/router (createRouter({ routes: [{ path: "/:tag", component: lazy(...) }] }), rendered with no <Loading> above the router) shows the same pattern: the route params are right, but the memo's value is the first render's.
- 主要言語
- TypeScript
- スター
- 36.2k
- フォーク
- 1.1k
- 平均マージ
- 10時間 39分
- マージ済み PR(30日)
- 500
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
solidjs/solid のほかの issue
-
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
メンテナーはふだん 1 日以内に返信
-
難易度 3/5 1〜2日 初心者へのやさしさ 55/100
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
メンテナーはふだん 1 日以内に返信
-
[2.0 / next] Optimistic todo list with an "N left" memo loops forever when a toggle's save landsオープン
難易度 5/5 1週間以上 初心者へのやさしさ 15/100
メンテナーはふだん 1 日以内に返信
-
[2.0 / next] createOptimisticStore: add, delete, add with saves pending hands <For> an undefined rowオープン
難易度 4/5 3〜5日 初心者へのやさしさ 25/100
メンテナーはふだん 1 日以内に返信
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
pingdotgg/t3code#30228 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
-
ci-cd desktop size:low telemetry-improvement telemetry-round-1
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
vfarcic/dot-agent-deck#2079 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 83/100
メンテナーはふだん 1 日以内に返信