Skip to content

runtime: await Promise.all([...]) never resumes when inputs settle via executor-captured resolvers — program silently exits 0 #6328

Description

@proggeramlug

Summary

await Promise.all([...]) never resumes when the input promises are settled through executor-captured resolvers. The program does not hang — it silently exits 0 having printed nothing, which is worse: no crash, no diagnostic, just a missing result.

The .then() form of the same code works. Confirmed on clean origin/main (0960415ad).

Repro

async function main() {
  const resolvers: ((v: number) => void)[] = [];
  const ps = Array.from({ length: 100 }, () => new Promise<number>((res) => { resolvers.push(res); }));
  const all = Promise.all(ps);
  for (let i = 0; i < 100; i++) resolvers[i](i);
  const r = await all;               // never resumes
  console.log("awaited", r.length);
}
main();
output exit
node 26 awaited 100 0
perry main (nothing) 0

Notes

  • The resolvers are captured out of the new Promise executor and invoked synchronously, after Promise.all(ps) has already been constructed.
  • Replacing await all with all.then(r => console.log("awaited", r.length)) works, so the combinator itself settles — it is the await resumption that is lost.
  • A variant where the resolvers are invoked later from a setTimeout does work, so the synchronous-settle-after-construction ordering appears to be load-bearing.

Surfaced while working on #6084 (PR #6327, promise side-table O(N^2)); that PR does not touch this and the bug reproduces identically without it. Filed separately so the perf work isn't blocked.

Silent wrong answer with a zero exit code — an async entry point can evaporate and CI would call it a pass.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugConfirmed defect or regression

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions