Skip to content

Async iterator does not work with Duplex streams #33130

@szmarczak

Description

@szmarczak
  • Version: v14.0.0
  • Platform: Linux solus 5.5.11-151.current #1 SMP PREEMPT Tue Mar 24 18:06:46 UTC 2020 x86_64 GNU/Linux
  • Subsystem: stream

What steps will reproduce the bug?

const {Duplex, PassThrough} = require('stream');

const response = new PassThrough();
setTimeout(() => response.write('chunk 1'), 500);
setTimeout(() => response.write('chunk 2'), 1000);
setTimeout(() => response.write('chunk 3'), 1500);
setTimeout(() => response.end(), 2000);

class HelloWorld extends Duplex {
	constructor(response) {
		super();

		this.response = response;
		this.readMore = false;

		response.once('end', () => {
			this.push(null);
		});

		response.on('readable', () => {
			if (this.readMore) {
				this._read();
			}
		});
	}

	_read() {
		const {response} = this;

		this.readMore = true;

		if (response.readableLength) {
			this.readMore = false;
		}

		let data;
		while ((data = response.read()) !== null) {
			this.push(data);
		}
	}
}

const instance = new HelloWorld(response);
instance.end();

(async () => {
	await new Promise(resolve => setTimeout(resolve, 100));

	for await (const data of instance) {
		console.log(data.toString());
	}

	console.log('finished await');
})();

How often does it reproduce? Is there a required condition?

Always.

What is the expected behavior?

chunk 1
chunk 2
chunk 3
finished await

What do you see instead?

finished await

Additional information

Async iterator utilizes the end-of-stream module. The culprit is this:

(wState && wState.finished) || (rState && rState.endEmitted) ||

wState.finished is true, therefore the callback is called even though it should not.

Original Got issue: sindresorhus/got#1172

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions