[2.0 rc.20 / next] `await renderToStream` never settles when the render signal aborts

Cerrado
#4,646 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
3/5
Tiempo estimado
1-2 días
Aptitud para principiantes
55/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
nodejs, typescript
Área
backend

Línea de trabajo

Start with the reproduction script in the issue and packages/web/src/server.ts: the promise form of renderToStream settles only through onCompleteAll or onFailure, and the abandon path on disconnect calls onDisconnectedBeforeShell instead, which the promise form never sets (around L2220-L2223). Run repro.mjs and confirm it prints still pending. Done means the promise rejects with signal.reason after an abort, and the script prints a rejected outcome.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

When the signal passed to renderToStream aborts, the render is disposed, but the promise returned for await renderToStream(...) never settles. It neither resolves nor rejects, so the caller stays pending forever and keeps whatever it holds alive: the request, timers, a concurrency slot.

The pipe paths end on abort. Only the promise form is left hanging.

Versions

solid-js and @solidjs/web 2.0.0-rc.20 from npm, and next at ab29345. Node 26.13.0.

Reproduction

Save as repro.mjs in a project with solid-js and @solidjs/web 2.0.0-rc.20, then run node repro.mjs:

import { renderToStream, ssr, escape } from "@solidjs/web";
import { createMemo } from "solid-js";

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

function App() {
  const message = createMemo(() => sleep(500).then(() => "loaded"));
  return ssr(["<p>", "</p>"], () => escape(message()));
}

const controller = new AbortController();
const rendering = renderToStream(App, { signal: controller.signal });
setTimeout(() => controller.abort(new Error("client disconnected")), 50);

const outcome = await Promise.race([
  Promise.resolve(rendering).then(
    html => `resolved: ${html}`,
    error => `rejected: ${error?.message}`
  ),
  sleep(2000).then(() => "still pending after 2s")
]);
console.log(outcome);
process.exit(0);
Observed
still pending after 2s

Without the abort call, the same script prints resolved: <p>loaded</p>....

Expected

The promise settles once the render is abandoned. Rejecting with signal.reason would let the caller tell a cancellation apart from a finished render and release what it holds.

Cause

Inside then, the promise settles only through onCompleteAll or onFailure (packages/web/src/server.ts, L3525-L3550 on next). When abandon runs because of a disconnect, it skips onFailed and only calls onDisconnectedBeforeShell, which the promise form never sets (L2220-L2223), so neither path runs.

Lenguaje dominante
TypeScript
Estrellas
36.2k
Forks
1.1k
Merge medio
10 h 10 min
PR fusionados (30 d)
505

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de solidjs/solid

Todos los issues de solidjs/solid

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.