Skip to main content

no-floating-web-stream-locks

Require Web Stream readers and writers to be retained so their locks can be released.

Rule catalog ID: R019

Targeted pattern scopeโ€‹

This type-aware rule targets lock-producing Web Streams methods:

  • ReadableStream#getReader()
  • WritableStream#getWriter()

The rule uses TypeScript parser services to confirm that the receiver is a Web ReadableStream or WritableStream. That avoids flagging project-local objects that happen to expose methods named getReader() or getWriter().

What this rule reportsโ€‹

The rule reports:

  • discarded stream readers
  • discarded stream writers
  • immediately chained reader or writer use where the reader/writer handle is lost

Immediate releaseLock() calls are allowed. The rule focuses on cases where the lock owner is unavailable to cleanup code.

Why this rule existsโ€‹

getReader() and getWriter() lock the stream to the returned reader or writer. The lock should be released with releaseLock() when the owner is done with the stream. If the reader or writer is discarded, later cleanup code cannot release that lock.

Incorrectโ€‹

new ReadableStream<Uint8Array>().getReader();
stream.getReader().read();
stream.getWriter().write(chunk);

Correctโ€‹

const reader = stream.getReader();

try {
await reader.read();
} finally {
reader.releaseLock();
}
function createReader(stream: ReadableStream<Uint8Array>) {
return stream.getReader();
}
streamReaderRegistry.add(stream.getReader());

Behavior and migration notesโ€‹

This rule is type-aware and requires parser services. Enable it through a type-checked preset or configure parserOptions.projectService yourself.

This rule does not autofix. Rewriting stream.getReader().read() into a retained reader requires a surrounding try/finally cleanup shape, which is too context-dependent for a safe automatic fix.

ESLint flat config exampleโ€‹

import runtimeCleanup from "eslint-plugin-runtime-cleanup";

export default [
runtimeCleanup.configs["recommended-type-checked"],
];

When not to use itโ€‹

Do not enable this rule in JavaScript-only projects without TypeScript parser services. For code that intentionally locks a stream for the entire process lifetime, use a narrow disable comment and document that ownership boundary.

Further readingโ€‹