Skip to content
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

Use stdin readable event instead of data #616

Merged
merged 2 commits into from
Sep 1, 2023

Conversation

matteodepalo
Copy link
Contributor

By doing testing of the Shopify CLI on Windows we found that stdin could get in a broken (paused) state if pause and resume were called in rapid succession by mounting and unmounting components that use useInput. Not all components would do this which leads me to believe it's a timing issue.

Here's a video showcasing one of our text prompts getting into this broken state.

04-30-dwnm8-36awe.mp4

I've tracked down the issue and it seems like removing pause and resume and switching to the readable event fixes things. I don't think this project needs to keep supporting node <10 right? If so, this change should create no backwards compatibility issues.

@matteodepalo matteodepalo force-pushed the new-readable-api branch 6 times, most recently from 21a8cb6 to df02408 Compare August 7, 2023 14:43
@vadimdemedes
Copy link
Owner

Thank you, great catch! You're right, Ink doesn't need to support old Node.js versions before 14.x.

I pinned the XO version in 80239ca, so could you undo the lint fixes you've applied in this PR? They shouldn't be needed anymore.

@matteodepalo matteodepalo force-pushed the new-readable-api branch 3 times, most recently from 93111eb to a7eacc6 Compare August 8, 2023 13:30
@matteodepalo
Copy link
Contributor Author

matteodepalo commented Aug 9, 2023

The current approach works but I'm not a huge fan of mixing readable and data. The reason I have to do it is that calling read() consumes the data, so components subscribed to readable won't be receiving anything because the App event has already consumed all data in stdin. Calling read() triggers a data event so sub-components can received data that way.

The Node docs recommend against using this mixed approach:

The Readable stream API evolved across multiple Node.js versions and provides multiple methods of consuming stream data. In general, developers should choose one of the methods of consuming data and should never use multiple methods to consume data from a single stream. Specifically, using a combination of on('data'), on('readable'), pipe(), or async iterators could lead to unintuitive behavior.

I agree with this, it's not obvious that data is there to catch data after read() has been called.
I think the best solution is to create a custom EventEmitter, put it in the StdinContext and emit custom events that components using useInput can subscribe to. This could also allow us to emit an event like ready that tests can subscribe to so that they can wait before sending data, instead of waiting for 1000ms in certain places.

@vadimdemedes what do you think? Shall I go ahead with this approach?

@vadimdemedes
Copy link
Owner

Not sure I follow. I thought this PR stop relying on data event and starts using readable exclusively?

@matteodepalo
Copy link
Contributor Author

matteodepalo commented Aug 11, 2023

Yes the problem is that because we need to subscribe to incoming data in 2 places (App component and useInput) we cannot use readable for both since once the data is consumed by one event then the other event won't see anything. data was working fine because it was triggering in both places. That's why I proposed to create a new event emitter that useInput can subscribe to instead of subscribing directly to stdin's readable event.

EDIT: the alternative is to merge this as is, but it would mix both data and readable. This works without using pause and resume, the stream is remains in paused state because a readable event is attached before the data one. I don't quite like this hidden order of events changing the behavior of the stream.

@matteodepalo
Copy link
Contributor Author

I'll write the code I have in mind and ask for feedback there, probably easier to review 😄 I was just a bit wary of adding a new exported attribute in useStdin.

@matteodepalo
Copy link
Contributor Author

matteodepalo commented Aug 15, 2023

9c718b8 @vadimdemedes this commit does what I wanted to do. I've used the internal_ naming convention because it's not going to be used directly by consumers.

@vadimdemedes
Copy link
Owner

Makes sense. Thanks!

@vadimdemedes vadimdemedes merged commit 814f33e into vadimdemedes:master Sep 1, 2023
3 checks passed
@matteodepalo matteodepalo deleted the new-readable-api branch September 1, 2023 11:00
@ohana54
Copy link

ohana54 commented Sep 11, 2023

Hi, I think this PR breaks the testkit with testing input - #627

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants