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

stream: make virtual methods errors consistent #18813

Closed
wants to merge 1 commit into from

Conversation

lpinca
Copy link
Member

@lpinca lpinca commented Feb 16, 2018

Use the same error code and always emit the error instead of throwing it.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines
Affected core subsystem(s)

errors, stream

@nodejs-github-bot nodejs-github-bot added errors Issues and PRs related to JavaScript errors originated in Node.js core. stream Issues and PRs related to the stream subsystem. labels Feb 16, 2018
@lpinca lpinca added the semver-major PRs that contain breaking changes and should be released in the next major version. label Feb 16, 2018
@lpinca lpinca added the wip Issues and PRs that are still a work in progress. label Feb 16, 2018
@lpinca lpinca force-pushed the uniform/virtual-methods-errors branch 2 times, most recently from e5aa300 to 90809ef Compare February 16, 2018 12:52
@lpinca lpinca removed the wip Issues and PRs that are still a work in progress. label Feb 16, 2018
Copy link
Member

@BridgeAR BridgeAR left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@BridgeAR BridgeAR added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Feb 16, 2018
@BridgeAR BridgeAR requested a review from a team February 16, 2018 17:35
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the correct behavior for these is to emit('error'). Note that calling the callback with an error will have that result.

@@ -561,7 +561,7 @@ function maybeReadMore_(stream, state) {
// for virtual (non-string, non-buffer) streams, "length" is somewhat
// arbitrary, and perhaps not very meaningful.
Readable.prototype._read = function(n) {
this.emit('error', new errors.Error('ERR_STREAM_READ_NOT_IMPLEMENTED'));
throw new errors.Error('ERR_METHOD_NOT_IMPLEMENTED', '_read()');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would leave this as this.emit('error').

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate on the reasons?

@@ -157,7 +157,7 @@ Transform.prototype.push = function(chunk, encoding) {
// an error, then that'll put the hurt on the whole operation. If you
// never call cb(), then you'll never get another chunk.
Transform.prototype._transform = function(chunk, encoding, cb) {
throw new errors.Error('ERR_METHOD_NOT_IMPLEMENTED', '_transform');
throw new errors.Error('ERR_METHOD_NOT_IMPLEMENTED', '_transform()');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would change this as cb(new errors.Error()).

@@ -541,7 +541,7 @@ function clearBuffer(stream, state) {
}

Writable.prototype._write = function(chunk, encoding, cb) {
cb(new errors.Error('ERR_METHOD_NOT_IMPLEMENTED', '_write'));
throw new errors.Error('ERR_METHOD_NOT_IMPLEMENTED', '_write()');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would leave this as it was.

@@ -761,7 +761,6 @@ E('ERR_STDOUT_CLOSE', 'process.stdout cannot be closed');
E('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable');
E('ERR_STREAM_NULL_VALUES', 'May not write null values to stream');
E('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF');
E('ERR_STREAM_READ_NOT_IMPLEMENTED', '_read() is not implemented');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍!

@BridgeAR BridgeAR removed the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Feb 16, 2018
@lpinca
Copy link
Member Author

lpinca commented Feb 16, 2018

Note that calling the callback with an error will have that result.

Yes, I changed it because I think it doesn't make sense to emit the error, it should just crash as the method has not been implemented. If there is an 'error' listener this may go unnoticed.

Anyway happy to always emit the error instead of throwing if there is consensus.

@mcollina
Copy link
Member

I think throwing is not the way to go, mainly because that error is likely not to be catchable in any way.

@jasnell
Copy link
Member

jasnell commented Feb 16, 2018

I agree with @mcollina that these should be emit('error', ...) ... it's much more consistent with what users expect with stream implementations.

@lpinca
Copy link
Member Author

lpinca commented Feb 17, 2018

I think throwing is not the way to go, mainly because that error is likely not to be catchable in any way.

Isn't this the point of the error? We throw for invalid arguments or options, in my opinion this is the same kind of error (invalid implementation).

I guess this

throw new errors.Error('ERR_METHOD_NOT_IMPLEMENTED', '_implicitHeader()');
should also be emitted if we agree that these errors should be emitted.

@mcollina
Copy link
Member

The reason why these needs to be emitted is because they could be called asynchronously. In such cases it would be hard to track to which stream they belong.

@lpinca
Copy link
Member Author

lpinca commented Feb 17, 2018

I still fail to understand.

  1. If there is no 'error' listener the error will be thrown and the stack trace will be exactly the same as if the error was thrown in the first place.
  2. If there is at least an 'error' listener, the developer has to stop the process, add a proper implementation and restart it, and again the stack trace will be exactly the same as if the error was thrown. How can this help determine which stream generated the error?

That said, I will change this PR to always emit if this is the right thing to do.

Pinging @nodejs/collaborators.

@lpinca lpinca force-pushed the uniform/virtual-methods-errors branch from 90809ef to e19a9d1 Compare February 19, 2018 11:03
@lpinca
Copy link
Member Author

lpinca commented Feb 19, 2018

No one commented and there are 2 TSC members that prefer to emit, so I've updated accordingly.

@lpinca
Copy link
Member Author

lpinca commented Feb 19, 2018

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@mcollina
Copy link
Member

This needs a rebase

@lpinca lpinca force-pushed the uniform/virtual-methods-errors branch from e19a9d1 to 54c0ab1 Compare February 23, 2018 13:18
@lpinca
Copy link
Member Author

lpinca commented Feb 23, 2018

@BridgeAR
Copy link
Member

BridgeAR commented Mar 2, 2018

@mcollina @jasnell e.g. all our fs errors throw sync instead of returning the error in the callback. That is also true for any other part of the code. So I am still not convinced about using emit here. All of that code could be used async. The only way I can imagine how these functions could be called is by faulty user code. And for me that is the same as the fs case.

@mcollina
Copy link
Member

mcollina commented Mar 2, 2018

@BridgeAR I would agree if those function were called sync all the time. In non-trivial cases, those methods are called async.

@lpinca
Copy link
Member Author

lpinca commented Mar 2, 2018

@mcollina it doesn't matter imho, what's the difference, any method or function that throws synchronously can be called async.

@mcollina
Copy link
Member

mcollina commented Mar 2, 2018

All Node APIs can be called async from user code. These are called async from Node.js code.

@joyeecheung
Copy link
Member

I think when to throw such errors depends on the nature of those errors: can they be expected from a user, or are they just bugs/incorrect usage of APIs. In the first case it make sense to throw asynchronously because we cannot know the result of an async operation synchronously anyway. In the second case it makes sense to throw synchronously because those errors are more like assertions in nature. The async operations cannot even be initiated so there is not really much point to delay the notification.

Also the user cannot really handle those errors (type checking, streams not implemented, etc) in their code anyway. The only sane way to handle those errors is probably just throw it again. If they try to handle a ERR_INVALID_* or ERR_METHOD_NOT_IMPLEMENTED they are probably just going to leave their program in a really bad state.

@lpinca lpinca added this to the 10.0.0 milestone Mar 11, 2018
Use the same error code and always emit the error instead of
throwing it.
@lpinca lpinca force-pushed the uniform/virtual-methods-errors branch from 54c0ab1 to f8bd8ec Compare March 11, 2018 09:55
@lpinca
Copy link
Member Author

lpinca commented Mar 11, 2018

I will land this tomorrow, got bored of rebasing :)
CI: https://ci.nodejs.org/job/node-test-pull-request/13619/
CI: https://ci.nodejs.org/job/node-test-pull-request/13642/

lpinca added a commit that referenced this pull request Mar 12, 2018
Use the same error code and always emit the error instead of
throwing it.

PR-URL: #18813
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
Reviewed-By: Michaë Zasso <[email protected]>
Reviewed-By: Matteo Collina <[email protected]>
@lpinca
Copy link
Member Author

lpinca commented Mar 12, 2018

Landed in c979488.

@lpinca lpinca closed this Mar 12, 2018
@lpinca lpinca deleted the uniform/virtual-methods-errors branch March 12, 2018 13:30
MayaLekova pushed a commit to MayaLekova/node that referenced this pull request May 8, 2018
Use the same error code and always emit the error instead of
throwing it.

PR-URL: nodejs#18813
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
Reviewed-By: Michaë Zasso <[email protected]>
Reviewed-By: Matteo Collina <[email protected]>
ChALkeR added a commit to ChALkeR/io.js that referenced this pull request Aug 6, 2018
This removes two unused error codes:
 * ERR_STREAM_READ_NOT_IMPLEMENTED, removed in c979488 (PR nodejs#18813).
 * ERR_VALUE_OUT_OF_RANGE, removed in d022cb1 (PR nodejs#17648).

PR-URL: nodejs#21491
Reviewed-By: Michaël Zasso <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: Joyee Cheung <[email protected]>
Reviewed-By: Anatoli Papirovski <[email protected]>
targos pushed a commit that referenced this pull request Aug 6, 2018
This removes two unused error codes:
 * ERR_STREAM_READ_NOT_IMPLEMENTED, removed in c979488 (PR #18813).
 * ERR_VALUE_OUT_OF_RANGE, removed in d022cb1 (PR #17648).

PR-URL: #21491
Reviewed-By: Michaël Zasso <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: Joyee Cheung <[email protected]>
Reviewed-By: Anatoli Papirovski <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
errors Issues and PRs related to JavaScript errors originated in Node.js core. semver-major PRs that contain breaking changes and should be released in the next major version. stream Issues and PRs related to the stream subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants