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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions