-
-
Notifications
You must be signed in to change notification settings - Fork 33.6k
lib: ensure readable stream flows to end #24918
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from 6 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
6685360
lib: ensure readable stream flows to end
Rantanen a7cc7a3
lib: add parens to while condition
Rantanen a293112
lib: clarify maybeReadMore_ loop conditions
Rantanen 5d230ab
lib: improve variable scoping in maybeReadMore
Rantanen 7cb1ccc
lib: clarify hwm-0-async test description
Rantanen 30f6a50
lib: add readable stream flow/no-flow mixed test
Rantanen 216f5e0
lib: simplify the no-flow data test
Rantanen f2ab091
lib: implement review suggestions
Rantanen File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
test/parallel/test-stream-readable-flow-no-flow-mixed.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| 'use strict'; | ||
Rantanen marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| const common = require('../common'); | ||
|
|
||
| // This test ensures that Readable stream switches between flowing and | ||
| // non-flowing state properly when varying the 'readable' and 'data' event | ||
| // subscription. | ||
Rantanen marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| const assert = require('assert'); | ||
| const { Readable } = require('stream'); | ||
|
|
||
| const flowingData = [ | ||
| { value: 'a' }, | ||
| { value: 'b' }, | ||
| { value: 'c', subscribeData: true }, | ||
| { value: 'd' }, | ||
| { value: 'e' }, | ||
| { value: 'f', removeReadable: true }, | ||
| { value: 'g' }, | ||
| { value: 'h' }, | ||
| { value: 'i', subscribeReadable: true }, | ||
| null, | ||
| ]; | ||
|
|
||
| const r = new Readable({ | ||
| read: common.mustCall(() => { | ||
| process.nextTick(() => { | ||
| r.push(flowingData.shift()); | ||
| }); | ||
| }, flowingData.length), | ||
| objectMode: true, | ||
|
|
||
| // The water mark shouldn't matter but we'll want to ensure the stream won't | ||
| // buffer data before we have a chance to react to the subscribe/unsubscribe | ||
| // event controls. | ||
| highWaterMark: 0, | ||
| }); | ||
|
|
||
| // Store data received through 'readable' events and 'data' events. | ||
| const actualReadable = []; | ||
| const actualData = []; | ||
|
|
||
| r.on('end', common.mustCall(() => { | ||
| assert.deepStrictEqual(actualReadable, ['a', 'b', 'c', 'd', 'e', 'f']); | ||
| assert.deepStrictEqual(actualData, ['d', 'e', 'f', 'g', 'h', 'i']); | ||
| })); | ||
|
|
||
| // Subscribing 'readable' should set flowing state to false. | ||
| assert.strictEqual(r.readableFlowing, null); | ||
| r.on('readable', common.mustCall(() => { | ||
| const v = r.read(); | ||
| actualReadable.push(v.value); | ||
|
|
||
| if (v.subscribeData) { | ||
|
|
||
| // Subsribing 'data' should not change flowing state. | ||
| assert.strictEqual(r.readableFlowing, false); | ||
| r.on('data', common.mustCall((data) => { | ||
Rantanen marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| actualData.push(data.value); | ||
|
|
||
| if (data.subscribeReadable) { | ||
|
|
||
| // Re-subsribing readable should put the stream back to non-flowing | ||
| // state. | ||
| assert.strictEqual(r.readableFlowing, true); | ||
| r.on('readable', common.mustCall(() => { | ||
| // The stream is at the end, but 'readable' is signaled without the | ||
| // stream knowing this. The 'r.read()' here will result in _read | ||
| // getting executed, which will then push the final null. | ||
| // | ||
| // NOTE: The 'null' here signals non-synchronous read. It is NOT the | ||
| // same 'null' that the _read ends up pushing to signal end of | ||
| // stream. | ||
| assert.strictEqual(r.read(), null); | ||
| })); | ||
| assert.strictEqual(r.readableFlowing, false); | ||
| } | ||
| }, 6)); | ||
| assert.strictEqual(r.readableFlowing, false); | ||
| } | ||
|
|
||
| if (v.removeReadable) { | ||
| // Removing 'readable' should allow the stream to flow into 'data' without | ||
| // us calling 'read()' manually. | ||
| // | ||
| // This should also cahgne the flowing state - although it is delayed into | ||
| // the next tick (within removeAllListeners). | ||
| assert.strictEqual(r.readableFlowing, false); | ||
| r.removeAllListeners('readable'); | ||
| process.nextTick(() => { | ||
| assert.strictEqual(r.readableFlowing, true); | ||
| }); | ||
| } else { | ||
| // We'll need to call r.read() to trigger the next read. | ||
| // | ||
| // It should return 'null' as the actual _read implementation is | ||
| // asynchronous but we still need to call it to trigger the push on | ||
| // next tick. | ||
| assert.strictEqual(r.read(), null); | ||
| } | ||
| }, 6)); | ||
| assert.strictEqual(r.readableFlowing, false); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| 'use strict'; | ||
|
|
||
| const common = require('../common'); | ||
|
|
||
| // This test ensures that Readable stream will continue to call _read | ||
| // for streams with highWaterMark === 0 once the stream returns data | ||
| // by calling push() asynchronously. | ||
|
|
||
| const { Readable } = require('stream'); | ||
|
|
||
| let count = 5; | ||
|
|
||
| const r = new Readable({ | ||
| // Called 6 times: First 5 return data, last one signals end of stream. | ||
| read: common.mustCall(() => { | ||
| process.nextTick(common.mustCall(() => { | ||
| if (count--) | ||
| r.push('a'); | ||
| else | ||
| r.push(null); | ||
| })); | ||
| }, 6), | ||
| highWaterMark: 0, | ||
| }); | ||
|
|
||
| r.on('end', common.mustCall()); | ||
| r.on('data', common.mustCall(5)); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.