Browse Source

util: support classes in util.deprecate()

Classes cannot be instantiated without new, but util.deprecate()
uses Function.prototype.apply(). This commit uses new.target to
detect constructor calls, allowing classes to be deprecated.

PR-URL: https://github.com/nodejs/node/pull/7690
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Michaël Zasso <mic.besace@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
v7.x
vladimir 9 years ago
committed by cjihrig
parent
commit
320f433dcd
  1. 2
      doc/api/util.md
  2. 9
      lib/internal/util.js
  3. 12
      test/fixtures/deprecated-userland-class.js
  4. 19
      test/fixtures/deprecated-userland-subclass.js
  5. 24
      test/sequential/test-deprecation-flags.js

2
doc/api/util.md

@ -46,7 +46,7 @@ environment variable. For example: `NODE_DEBUG=fs,net,tls`.
## util.deprecate(function, string)
The `util.deprecate()` method wraps the given `function` in such a way that
The `util.deprecate()` method wraps the given `function` or class in such a way that
it is marked as deprecated.
```js

9
lib/internal/util.js

@ -60,9 +60,18 @@ exports._deprecate = function(fn, msg) {
var warned = false;
function deprecated() {
warned = exports.printDeprecationMessage(msg, warned, deprecated);
if (new.target) {
return Reflect.construct(fn, arguments, new.target);
}
return fn.apply(this, arguments);
}
// The wrapper will keep the same prototype as fn to maintain prototype chain
Object.setPrototypeOf(deprecated, fn);
if (fn.prototype) {
Object.setPrototypeOf(deprecated.prototype, fn.prototype);
}
return deprecated;
};

12
test/fixtures/deprecated-userland-class.js

@ -0,0 +1,12 @@
const util = require('util');
const assert = require('assert');
class deprecatedClass {
}
const deprecated = util.deprecate(deprecatedClass, 'deprecatedClass is deprecated.');
const instance = new deprecated();
assert(instance instanceof deprecated);
assert(instance instanceof deprecatedClass);

19
test/fixtures/deprecated-userland-subclass.js

@ -0,0 +1,19 @@
const util = require('util');
const assert = require('assert');
class deprecatedClass {
}
const deprecated = util.deprecate(deprecatedClass, 'deprecatedClass is deprecated.');
class subclass extends deprecated {
constructor() {
super();
}
}
const instance = new subclass();
assert(instance instanceof subclass);
assert(instance instanceof deprecated);
assert(instance instanceof deprecatedClass);

24
test/sequential/test-deprecation-flags.js

@ -5,8 +5,14 @@ const execFile = require('child_process').execFile;
const depmod = require.resolve(common.fixturesDir + '/deprecated.js');
const node = process.execPath;
const depUserland =
require.resolve(common.fixturesDir + '/deprecated-userland-function.js');
const depUserlandFunction =
require.resolve(common.fixturesDir + '/deprecated-userland-function.js');
const depUserlandClass =
require.resolve(common.fixturesDir + '/deprecated-userland-class.js');
const depUserlandSubClass =
require.resolve(common.fixturesDir + '/deprecated-userland-subclass.js');
const normal = [depmod];
const noDep = ['--no-deprecation', depmod];
@ -39,10 +45,22 @@ execFile(node, traceDep, function(er, stdout, stderr) {
console.log('trace ok');
});
execFile(node, [depUserland], function(er, stdout, stderr) {
execFile(node, [depUserlandFunction], function(er, stdout, stderr) {
console.error('normal: testing deprecated userland function');
assert.equal(er, null);
assert.equal(stdout, '');
assert(/deprecatedFunction is deprecated/.test(stderr));
console.error('normal: ok');
});
execFile(node, [depUserlandClass], function(er, stdout, stderr) {
assert.strictEqual(er, null);
assert.strictEqual(stdout, '');
assert(/deprecatedClass is deprecated/.test(stderr));
});
execFile(node, [depUserlandSubClass], function(er, stdout, stderr) {
assert.strictEqual(er, null);
assert.strictEqual(stdout, '');
assert(/deprecatedClass is deprecated/.test(stderr));
});

Loading…
Cancel
Save