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

Đang mở
#4,646 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ó
3/5
Thời gian dự kiến
1-2 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ệ
nodejs, typescript
Lĩnh vực
backend

Hướng nghiên cứu

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.

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

Mô tả

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.

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

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.