latest() of an unread identity memo returns undefined when first read in the flush that re-asks its source

Chiusa
#4,474 3 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
52/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
typescript
Ambito
frontend

Direzione di ricerca

Start with the issue’s reproducer and trace the first read of latest(id) alongside isPending(id) when the Loading boundary mounts. Compare that case with creating the identity memo inside the mounted content, where the bug does not occur. Done when the reproducer no longer yields latest(id) === undefined after m has answered, while pending behavior remains correct.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

On next (e49b0c769), latest() can return undefined, which D-22 rules out ("It returns T, never undefined").

Setup:

  • m is an async memo, and id = createMemo(() => m()) is an identity memo created at the root. Nothing reads id yet.
  • m's first answer (2) lands in its own flush.
  • A write then re-asks m. In that same flush, a Loading boundary mounts content whose render effect reads latest(id) and isPending(id).

The effect's first run sees latest(id) === undefined and isPending(id) === true. Because m has been answered, latest(id) should be 2. If id is created inside the mounted content instead, the bug does not happen.

const asks: { v: number; resolve: (v: number) => void }[] = [];
const [s, setS] = createSignal(1);
const m = createMemo(() => { const v = 1 + s(); return new Promise<number>(resolve => asks.push({ v, resolve })); });
const id = createMemo(() => m());
const leaves: string[] = [];
createRoot(() => {
  const b = createLoadingBoundary(() => {
    const gate = createMemo(() => s() > 1);
    return createMemo(() => {
      if (!gate()) return "off";
      createRenderEffect(() => `l:${latest(id)} p:${isPending(id)}`, v => void leaves.push(v));
      return "on";
    });
  }, () => "fallback");
  createRenderEffect(() => { let v: any = b; while (typeof v === "function") v = v(); return v; }, () => {});
});
flush(); await task(); flush();
const first = asks.shift()!; first.resolve(first.v);
await task(); flush();          // m's answer (2) lands on its own
setS(2); await task(); flush(); // re-ask m and mount the content
// leaves: ["l:undefined p:true", ...]

Found while reviewing #4459; #4459 does not change it.

Lingua principale
TypeScript
Stelle
36.2k
Fork
1.1k
Merge medio
11h 5m
PR unite (30g)
475

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di solidjs/solid

Tutte le issue di solidjs/solid

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.