Add --no-deprecation and --trace-deprecation flags
authorisaacs <i@izs.me>
Thu, 21 Jun 2012 18:42:33 +0000 (11:42 -0700)
committerisaacs <i@izs.me>
Thu, 21 Jun 2012 19:05:33 +0000 (12:05 -0700)
doc/node.1
lib/fs.js
lib/http.js
lib/net.js
lib/os.js
lib/path.js
lib/tty.js
lib/util.js
src/node.cc
src/node.js
test/simple/test-deprecation-flags.js [new file with mode: 0644]

index 2621b94..9603a91 100644 (file)
@@ -41,6 +41,26 @@ focused on creating simple, easy to build network clients
 and servers.
 
 
+.SH OPTIONS
+
+  -v, --version          print node's version
+
+  -e, --eval script      evaluate script
+
+  -p, --print            print result of --eval
+
+  -i, --interactive      always enter the REPL even if stdin
+                         does not appear to be a terminal
+
+  --no-deprecation       silence deprecation warnings
+
+  --trace-deprecation    show stack traces on deprecations
+
+  --v8-options           print v8 command line options
+
+  --max-stack-size=val   set max v8 stack size (bytes)
+
+
 .SH ENVIRONMENT VARIABLES
 
 .IP NODE_PATH
index 4872427..8bfc10c 100644 (file)
--- a/lib/fs.js
+++ b/lib/fs.js
@@ -919,7 +919,7 @@ fs.watchFile = function(filename) {
     // a little on the slow side but let's stick with it for now to keep
     // behavioral changes to a minimum.
     interval: 5007,
-    persistent: true,
+    persistent: true
   };
 
   if ('object' == typeof arguments[1]) {
index b4b6edc..01aa4eb 100644 (file)
@@ -1831,12 +1831,9 @@ Client.prototype.request = function(method, path, headers) {
   return c;
 };
 
-exports.Client = Client;
+exports.Client = util.deprecate(Client,
+    'http.Client will be removed soon. Do not use it.');
 
-// TODO http.Client can be removed in v0.9. Until then leave this message.
-module.deprecate('Client', 'It will be removed soon. Do not use it.');
-
-exports.createClient = function(port, host) {
+exports.createClient = util.deprecate(function(port, host) {
   return new Client(port, host);
-};
-module.deprecate('createClient', 'Use `http.request` instead.');
+}, 'http.createClient is deprecated. Use `http.request` instead.');
index 5ffbea7..9f03259 100644 (file)
@@ -133,14 +133,7 @@ function Socket(options) {
 
   if (typeof options == 'number') {
     // Legacy interface.
-    // Must support legacy interface. Old versions of npm depend on it.
-    // https://github.com/isaacs/npm/blob/c7824f412f0cb59d6f55cf0bc220253c39e6029f/lib/utils/output.js#L110
     var fd = options;
-
-    // Uncomment the following lines after libuv backend is stable and API
-    // compatibile with legaacy.
-    //   console.error('Deprecated interface net.Socket(fd).');
-    //   console.trace();
     this._handle = createPipe();
     this._handle.open(fd);
     this.readable = this.writable = true;
@@ -1092,14 +1085,9 @@ Server.prototype._emitCloseIfDrained = function() {
 };
 
 
-var listenFDwarn = false;
-Server.prototype.listenFD = function(fd, type) {
-  if (!listenFDwarn) {
-    console.error('listenFD is deprecated. Use server.listen()');
-    listenFDwarn = true;
-  }
-  this.listen({ fd: fd });
-};
+Server.prototype.listenFD = util.deprecate(function(fd, type) {
+  return this.listen({ fd: fd });
+}, 'listenFD is deprecated. Use listen({fd: <number>}).');
 
 // when sending a socket using fork IPC this function is executed
 Server.prototype._setupSlave = function(socketList) {
index 47d1c56..1fe8731 100644 (file)
--- a/lib/os.js
+++ b/lib/os.js
@@ -20,6 +20,7 @@
 // USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 var binding = process.binding('os');
+var util = require('util');
 
 exports.hostname = binding.getHostname;
 exports.loadavg = binding.getLoadAvg;
@@ -46,10 +47,8 @@ exports.tmpDir = function() {
          (process.platform === 'win32' ? 'c:\\windows\\temp' : '/tmp');
 };
 
-exports.getNetworkInterfaces = function() {
+exports.getNetworkInterfaces = util.deprecate(function() {
   return exports.networkInterfaces();
-};
-module.deprecate('getNetworkInterfaces',
-                 'It is now called `os.networkInterfaces`.');
+}, 'getNetworkInterfaces is now called `os.networkInterfaces`.');
 
 exports.EOL = process.platform === 'win32' ? '\r\n' : '\n';
index 961dc40..438b05d 100644 (file)
@@ -21,7 +21,7 @@
 
 
 var isWindows = process.platform === 'win32';
-var _deprecationWarning = require('util')._deprecationWarning;
+var util = require('util');
 
 
 // resolves . and .. elements in a path array with directory names there
@@ -415,16 +415,14 @@ exports.extname = function(path) {
 };
 
 
-exports.exists = function(path, callback) {
+exports.exists = util.deprecate(function(path, callback) {
   require('fs').exists(path, callback);
-};
-module.deprecate('exists', 'It is now called `fs.exists`.');
+}, 'path.exists is now called `fs.exists`.');
 
 
-exports.existsSync = function(path) {
+exports.existsSync = util.deprecate(function(path) {
   return require('fs').existsSync(path);
-};
-module.deprecate('existsSync', 'It is now called `fs.existsSync`.');
+}, 'path.existsSync is now called `fs.existsSync`.');
 
 
 if (isWindows) {
index 414eed6..9fa18fd 100644 (file)
@@ -24,6 +24,7 @@ var inherits = require('util').inherits;
 var net = require('net');
 var TTY = process.binding('tty_wrap').TTY;
 var isTTY = process.binding('tty_wrap').isTTY;
+var util = require('util');
 
 exports.isatty = function(fd) {
   return isTTY(fd);
@@ -31,13 +32,12 @@ exports.isatty = function(fd) {
 
 
 // backwards-compat
-exports.setRawMode = function(flag) {
+exports.setRawMode = util.deprecate(function(flag) {
   if (!process.stdin.isTTY) {
     throw new Error('can\'t set raw mode on non-tty');
   }
   process.stdin.setRawMode(flag);
-};
-module.deprecate('setRawMode', 'Use `process.stdin.setRawMode()` instead.');
+}, 'tty.setRawMode: Use `process.stdin.setRawMode()` instead.');
 
 
 function ReadStream(fd) {
index 50595fd..580aa81 100644 (file)
@@ -54,6 +54,31 @@ exports.format = function(f) {
 };
 
 
+// Mark that a method should not be used.
+// Returns a modified function which warns once by default.
+// If --no-deprecation is set, then it is a no-op.
+exports.deprecate = function(fn, msg) {
+  if (process.noDeprecation === true) {
+    return fn;
+  }
+
+  var warned = false;
+  function deprecated() {
+    if (!warned) {
+      if (process.traceDeprecation) {
+        console.trace(msg);
+      } else {
+        console.error(msg);
+      }
+      warned = true;
+    }
+    return fn.apply(this, arguments);
+  }
+
+  return deprecated;
+};
+
+
 exports.print = function() {
   for (var i = 0, len = arguments.length; i < len; ++i) {
     process.stdout.write(String(arguments[i]));
@@ -407,12 +432,11 @@ function objectToString(o) {
 }
 
 
-exports.p = function() {
+exports.p = exports.deprecate(function() {
   for (var i = 0, len = arguments.length; i < len; ++i) {
     error(exports.inspect(arguments[i]));
   }
-};
-module.deprecate('p', 'Use `util.puts(util.inspect())` instead.');
+}, 'util.p: Use console.error() instead.');
 
 
 function pad(n) {
@@ -438,10 +462,9 @@ exports.log = function(msg) {
 };
 
 
-exports.exec = function() {
+exports.exec = exports.deprecate(function() {
   return require('child_process').exec.apply(this, arguments);
-};
-module.deprecate('exec', 'It is now called `child_process.exec`.');
+}, 'util.exec is now called `child_process.exec`.');
 
 
 exports.pump = function(readStream, writeStream, callback) {
index d71a21b..94cc2a5 100644 (file)
@@ -120,6 +120,8 @@ static Persistent<String> disposed_symbol;
 
 static bool print_eval = false;
 static bool force_repl = false;
+static bool no_deprecation = false;
+static bool trace_deprecation = false;
 static char *eval_string = NULL;
 static int option_end_index = 0;
 static bool use_debug_agent = false;
@@ -1094,12 +1096,16 @@ enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
   } else if (strcasecmp(*encoding, "hex") == 0) {
     return HEX;
   } else if (strcasecmp(*encoding, "raw") == 0) {
-    fprintf(stderr, "'raw' (array of integers) has been removed. "
-                    "Use 'binary'.\n");
+    if (!no_deprecation) {
+      fprintf(stderr, "'raw' (array of integers) has been removed. "
+                      "Use 'binary'.\n");
+    }
     return BINARY;
   } else if (strcasecmp(*encoding, "raws") == 0) {
-    fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
-                    "Please update your code.\n");
+    if (!no_deprecation) {
+      fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
+                      "Please update your code.\n");
+    }
     return BINARY;
   } else {
     return _default;
@@ -2224,6 +2230,16 @@ Handle<Object> SetupProcessObject(int argc, char *argv[]) {
     process->Set(String::NewSymbol("_forceRepl"), True());
   }
 
+  // --no-deprecation
+  if (no_deprecation) {
+    process->Set(String::NewSymbol("noDeprecation"), True());
+  }
+
+  // --trace-deprecation
+  if (trace_deprecation) {
+    process->Set(String::NewSymbol("traceDeprecation"), True());
+  }
+
   size_t size = 2*PATH_MAX;
   char* execPath = new char[size];
   if (uv_exepath(execPath, &size) != 0) {
@@ -2371,6 +2387,8 @@ static void PrintHelp() {
          "  -p, --print          print result of --eval\n"
          "  -i, --interactive    always enter the REPL even if stdin\n"
          "                       does not appear to be a terminal\n"
+         "  --no-deprecation     silence deprecation warnings\n"
+         "  --trace-deprecation  show stack traces on deprecations\n"
          "  --v8-options         print v8 command line options\n"
          "  --max-stack-size=val set max v8 stack size (bytes)\n"
          "\n"
@@ -2428,6 +2446,12 @@ static void ParseArgs(int argc, char **argv) {
       argv[i] = const_cast<char*>("");
     } else if (strcmp(arg, "--v8-options") == 0) {
       argv[i] = const_cast<char*>("--help");
+    } else if (strcmp(arg, "--no-deprecation") == 0) {
+      argv[i] = const_cast<char*>("");
+      no_deprecation = true;
+    } else if (strcmp(arg, "--trace-deprecation") == 0) {
+      argv[i] = const_cast<char*>("");
+      trace_deprecation = true;
     } else if (argv[i][0] != '-') {
       break;
     }
index b2a0277..6a202fb 100644 (file)
     NativeModule._cache[this.id] = this;
   };
 
-  // Wrap a core module's method in a wrapper that will warn on first use
-  // and then return the result of invoking the original function. After
-  // first being called the original method is restored.
-  NativeModule.prototype.deprecate = function(method, message) {
-    var original = this.exports[method];
-    var self = this;
-    var warned = false;
-    message = message || '';
-
-    Object.defineProperty(this.exports, method, {
-      enumerable: false,
-      value: function() {
-        if (!warned) {
-          warned = true;
-          message = self.id + '.' + method + ' is deprecated. ' + message;
-
-          var moduleIdCheck = new RegExp('\\b' + self.id + '\\b');
-          if (moduleIdCheck.test(process.env.NODE_DEBUG))
-            console.trace(message);
-          else
-            console.error(message);
-
-          self.exports[method] = original;
-        }
-        return original.apply(this, arguments);
-      }
-    });
-  };
-
   startup();
 });
diff --git a/test/simple/test-deprecation-flags.js b/test/simple/test-deprecation-flags.js
new file mode 100644 (file)
index 0000000..81605da
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+var execFile = require('child_process').execFile;
+var depmod = require.resolve('../fixtures/deprecated.js');
+var node = process.execPath;
+
+var normal = [depmod];
+var noDep = ['--no-deprecation', depmod];
+var traceDep = ['--trace-deprecation', depmod];
+
+execFile(node, normal, function(er, stdout, stderr) {
+  console.error('normal: show deprecation warning');
+  assert.equal(er, null);
+  assert.equal(stdout, '');
+  assert.equal(stderr, 'util.p: Use console.error() instead.\n\'This is deprecated\'\n');
+  console.log('normal ok');
+});
+
+execFile(node, noDep, function(er, stdout, stderr) {
+  console.error('--no-deprecation: silence deprecations');
+  assert.equal(er, null);
+  assert.equal(stdout, '');
+  assert.equal(stderr, '\'This is deprecated\'\n');
+  console.log('silent ok');
+});
+
+execFile(node, traceDep, function(er, stdout, stderr) {
+  console.error('--trace-deprecation: show stack');
+  assert.equal(er, null);
+  assert.equal(stdout, '');
+  var stack = stderr.trim().split('\n');
+  // just check the top and bottom.
+  assert.equal(stack[0], 'Trace: util.p: Use console.error() instead.');
+  assert.equal(stack.pop(), '\'This is deprecated\'');
+  console.log('trace ok');
+});