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

util: util.deprecate improvement #1892

Closed

Conversation

thefourtheye
Copy link
Contributor

Follow up of #1883.

Changes included in this PR are

  1. Making the deprecation messages consistent. The messages will be in
    the following format

    x is deprecated. Use y instead.
    

    If there is no alternative for x, then the Use y instead. part
    will not be there in the message.

  2. All the internal deprecation messages are printed with the prefix
    (node), except when the --trace-deprecation flag is set.

@thefourtheye thefourtheye force-pushed the deprecate-improvement branch from f7e2ba5 to 08e57b4 Compare June 4, 2015 06:17
@brendanashworth brendanashworth added the util Issues and PRs related to the built-in util module. label Jun 4, 2015
@silverwind
Copy link
Contributor

Regarding [node]: There is this one (and presumably only) case where we print with a (node) prefix. I have no preference for a parens style, but we should keep it consistent.

@thefourtheye
Copy link
Contributor Author

@silverwind Oh, shall I change [node]s to (node)s?

@silverwind
Copy link
Contributor

Yeah, probably best of you'd change that.

function deprecated() {
var location = (new Error()).stack.match(/.*?\n.*\n.*?\((.*?:\d+):/)[1];
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't seem to match the correct line of the call. Here's a random test I put into an app of mine:

Stack:

Error
    at startListeners (/Users/silverwind/git/droppy/server/server.js:121:18)
    at /Users/silverwind/git/droppy/server/server.js:77:45
    at /Users/silverwind/git/droppy/node_modules/async/lib/async.js:695:13
    at iterate (/Users/silverwind/git/droppy/node_modules/async/lib/async.js:256:13)
    at doNTCallback0 (node.js:408:9)
    at process._tickCallback (node.js:337:13)

Output of your regex:

/Users/silverwind/git/droppy/node_modules/async/lib/async.js:256

You should try matching the first line here (server.js:121).

Copy link
Contributor

Choose a reason for hiding this comment

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

I haven't tested this with a real deprecate yet, so maybe I'm wrong 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@silverwind You are correct, I am rebasing now. I ll fix it in that. I didn't know that we will get lines like

at /Users/silverwind/git/droppy/server/server.js:77:45

this in the trace. Probably, I ll split the stack, take the second line and then parse it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@silverwind Do you have the change which landed today? This should ideally have an entry for deprecated. Are you doing only new Error().stack?

Copy link
Contributor

Choose a reason for hiding this comment

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

That line above was produced by just

console.log(stack.match(/.*?\n.*\n.*?\((.*?:\d+):/)[1]);

I think the lines without parens are anonymous functions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@silverwind For anonymous functions, I am getting Object.<anonymous>. The lines without parens are for the calls directly from the modules, I think.

@silverwind
Copy link
Contributor

Also, apparently your branch is outdated and the PR needs a rebase already.

@vkurchatkin
Copy link
Contributor

If we actually want this it makes sense to use internal wrapper that prepends (node) automatically

@silverwind
Copy link
Contributor

@vkurchatkin not a huge fan of a wrapper. Maybe there's a way to detect an internal call to deprecate and prepend (node) in that case?

@thefourtheye
Copy link
Contributor Author

@silverwind @vkurchatkin Why don't we accept the prefix as a parameter?

@vkurchatkin
Copy link
Contributor

@silverwind why not? just use require('internal/util').deprecate

@thefourtheye concatenating strings is something that users can do on their own

@silverwind
Copy link
Contributor

@vkurchatkin guess I could live with something like internal/util 👍

@thefourtheye
Copy link
Contributor Author

You guys mean, deprecate function in 'internal/util will add (node)? Can you please explain this a bit more?

@silverwind
Copy link
Contributor

Add a wrapper function in lib/internal/util.js that uses util.deprecate and prepends (node) to the message string. Afterwards include it through require('internal/util').deprecate in all files that do deprecations and use it.

@thefourtheye thefourtheye force-pushed the deprecate-improvement branch from 08e57b4 to 0570e40 Compare June 4, 2015 16:09
@thefourtheye
Copy link
Contributor Author

@silverwind @vkurchatkin Thanks for the suggestions :-) I updated the PR. Please review.

@thefourtheye thefourtheye force-pushed the deprecate-improvement branch from 0570e40 to 2aa754e Compare June 4, 2015 18:18


exports.pump = exports.deprecate(function(readStream, writeStream, callback) {
exports.pump = internalUtil.deprecate(function(readStream, writeStream, cb) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had to change this because of the line length restriction

@thefourtheye thefourtheye force-pushed the deprecate-improvement branch from 2aa754e to 876ff26 Compare June 4, 2015 18:26
@thefourtheye
Copy link
Contributor Author

@silverwind I think I addressed all the comments and included a test with parenthesis in the file name. Please check now.

@@ -3,4 +3,4 @@
const util = require('internal/util');

module.exports = require('internal/smalloc');
util.printDeprecationMessage('smalloc is deprecated.');
util.deprecate('smalloc is deprecated. Use typed arrays.');
Copy link
Member

Choose a reason for hiding this comment

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

I don't think it will work here. The idea is to print a deprecation message when this line is executed.
printDeprecationMessage should stay but we have a problem with the --trace-deprecation flag. The actual caller location is where require('smalloc') is done.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@targos Oh, you are correct. printDeprecationMessage should stay. But, in case of require, we can print only once. So, --trace-deprecation cannot do much here, right?

@thefourtheye thefourtheye force-pushed the deprecate-improvement branch from 876ff26 to 6d4a717 Compare June 4, 2015 19:39
@silverwind
Copy link
Contributor

Is there a test yet to assert file and line numbers are correct? I can see this getting broken easily when the call stack to deprecate ever changes, so I think such a test is necessary.

@thefourtheye thefourtheye force-pushed the deprecate-improvement branch from 6d4a717 to a24698a Compare June 6, 2015 15:24
@thefourtheye
Copy link
Contributor Author

@silverwind Oh yeah. You are correct. I updated one of the tests to include the checks. Please check now.

@thefourtheye thefourtheye force-pushed the deprecate-improvement branch from a24698a to 5e165c5 Compare June 7, 2015 16:17
assert.equal(stack.pop(), '\'This is deprecated\'');
console.log('trace ok');
});

Copy link
Contributor

Choose a reason for hiding this comment

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

Very minor, But one newline is enough here :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@silverwind Only line 114 is left empty, right? I thought that it would improve readability.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm talking about the final line of this file. git apply also complains: new blank line at EOF

@silverwind
Copy link
Contributor

Gave it a try, seems the file and line number isn't always correct:

$ >t.js
require("smalloc")
^C
$ ./iojs t.js
(node) smalloc is deprecated. Use typed arrays.
Used at: node.js:937

Strangely, --trace-deprecation doesn't show anything in this simple test.

Also, I'd prefer a single-line style. Maybe just cut out the path and use only the filename to keep it short:

(node) in node.js:937: smalloc is deprecated. Use typed arrays.

or postfix, I have no preference:

(node) smalloc is deprecated. Use typed arrays. (node.js:937)

@thefourtheye
Copy link
Contributor Author

Ah, that is a corner case where we skip the util.deprecate and directly call printDeprecationMessage. I ll fix it by adding a flag in the parameter.

@thefourtheye
Copy link
Contributor Author

@silverwind Why don't we change the newly landed deprecate to _deprecate? Its used in only one place.

@silverwind
Copy link
Contributor

That could work too, just seems a bit confusing at first glance that _deprecate is the one used by public code. It's not much of an issue and I'd be fine if you chose to do so.

@thefourtheye
Copy link
Contributor Author

@brendanashworth Thanks for the heads up :-)

@silverwind I renamed it to _internalDeprecate and removed the util dependency.

@@ -10,7 +18,7 @@ exports.printDeprecationMessage = function(msg, warned) {
if (process.throwDeprecation)
throw new Error(msg);
else if (process.traceDeprecation)
console.trace(msg);
console.trace(msg.replace(new RegExp(`^\\(${prefix}\\) `), ''));
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure I understand why this double escaping is needed. Wouldn't a literal like /^\(${prefix}\) / work?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@silverwind Will the string substitution work in RegEx literals also?

Copy link
Contributor

Choose a reason for hiding this comment

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

Of course:

> '(node) something'.replace(/\(node\) /,'')
'something'

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is not substitution right? I stored node in a variable. How can that be substituted in the RegEx literal?

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, right. Template string substitution won't work inside a regex literal, so this is fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@silverwind Actually, the ES6 proposal had re Quasi literal function though :-)

@silverwind
Copy link
Contributor

Sorry, but still not totally satisfied yet. Here's what I suggest to fix the remaining issues:

  • _internalDeprecate isn't really clear either for the purpose, let's just call it _deprecate.
  • Add a _printDeprecationMessage that does not prefix
  • Change printDeprecationMessage to add the prefix and call into _printDeprecationMessage
  • Remove all remaining prefixes from printDeprecationMessage calls.

@silverwind
Copy link
Contributor

Also, I think you should squash into a single commit now. I can't apply this PR on top of master because of previous patches that don't apply anymore.

@thefourtheye thefourtheye force-pushed the deprecate-improvement branch 5 times, most recently from 9825c35 to 416a134 Compare June 18, 2015 13:23
@thefourtheye
Copy link
Contributor Author

@silverwind I updated the PR with the review comments. Please review now.

Changes included in this commit are

   1. Making the deprecation messages consistent. The messages will be in
      the following format

           x is deprecated. Use y instead.

      If there is no alternative for `x`, then the ` Use y instead.` part
      will not be there in the message.

   2. All the internal deprecation messages are printed with the prefix
      `(node) `, except when the `--trace-deprecation` flag is set.
@silverwind
Copy link
Contributor

Sorry for the delay. LGTM

@mscdex
Copy link
Contributor

mscdex commented Jun 28, 2015

Would it make more sense to have a deprecate() that automatically includes the boilerplate text? Like:

exports.deprecate = function(oldValue, newValue) {
  // using whatever appropriate internal util function instead of `console.log` of course
  console.log('%s is deprecated. Use %s instead.', oldValue, newValue);
};

@silverwind
Copy link
Contributor

I see some use in something like that (primarily the part of forcing the maintainer to point to an alternative). But remember this is public API which would force a semver-major.

@mscdex
Copy link
Contributor

mscdex commented Jun 28, 2015

Well, there could be a conditional to check if arguments.length === 1 and if so, only log the %s is deprecated. part.

@thefourtheye
Copy link
Contributor Author

What if the users want to give a custom message? Let's say "Feature X is deprecated and removed in version 1.0.0. Use Y instead"

@silverwind
Copy link
Contributor

I'm feeling more inclined to leave it as is with a simple string for flexibility.

@thefourtheye
Copy link
Contributor Author

@silverwind What if we use @mscdex's suggestion for the internal deprecations?

@silverwind
Copy link
Contributor

I'd decide against it. We can just make sure the future deprecation messages follow this scheme. No hand-holding needed there imho :)

@silverwind
Copy link
Contributor

I'll most likely land this tomorrow, unless further objections are made.

@thefourtheye
Copy link
Contributor Author

OSM :-)

silverwind pushed a commit that referenced this pull request Jul 3, 2015
Changes included in this commit are

   1. Making the deprecation messages consistent. The messages will be in
      the following format

           x is deprecated. Use y instead.

      If there is no alternative for `x`, then the ` Use y instead.` part
      will not be there in the message.

   2. All the internal deprecation messages are printed with the prefix
      `(node) `, except when the `--trace-deprecation` flag is set.

Fixes: #1883
PR-URL: #1892
Reviewed-By: Roman Reiss <[email protected]>
@silverwind
Copy link
Contributor

Landed in 9cd44bb

@silverwind silverwind closed this Jul 3, 2015
@thefourtheye thefourtheye deleted the deprecate-improvement branch July 3, 2015 17:21
mscdex pushed a commit to mscdex/io.js that referenced this pull request Jul 9, 2015
Changes included in this commit are

   1. Making the deprecation messages consistent. The messages will be in
      the following format

           x is deprecated. Use y instead.

      If there is no alternative for `x`, then the ` Use y instead.` part
      will not be there in the message.

   2. All the internal deprecation messages are printed with the prefix
      `(node) `, except when the `--trace-deprecation` flag is set.

Fixes: nodejs#1883
PR-URL: nodejs#1892
Reviewed-By: Roman Reiss <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
util Issues and PRs related to the built-in util module.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants