Skip to content

Commit 320f433

Browse files
vdeturckheimcjihrig
authored andcommitted
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: nodejs#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>
1 parent e1643cc commit 320f433

File tree

5 files changed

+62
-4
lines changed

5 files changed

+62
-4
lines changed

doc/api/util.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ environment variable. For example: `NODE_DEBUG=fs,net,tls`.
4646

4747
## util.deprecate(function, string)
4848

49-
The `util.deprecate()` method wraps the given `function` in such a way that
49+
The `util.deprecate()` method wraps the given `function` or class in such a way that
5050
it is marked as deprecated.
5151

5252
```js

lib/internal/util.js

+9
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,18 @@ exports._deprecate = function(fn, msg) {
6060
var warned = false;
6161
function deprecated() {
6262
warned = exports.printDeprecationMessage(msg, warned, deprecated);
63+
if (new.target) {
64+
return Reflect.construct(fn, arguments, new.target);
65+
}
6366
return fn.apply(this, arguments);
6467
}
6568

69+
// The wrapper will keep the same prototype as fn to maintain prototype chain
70+
Object.setPrototypeOf(deprecated, fn);
71+
if (fn.prototype) {
72+
Object.setPrototypeOf(deprecated.prototype, fn.prototype);
73+
}
74+
6675
return deprecated;
6776
};
6877

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const util = require('util');
2+
const assert = require('assert');
3+
4+
class deprecatedClass {
5+
}
6+
7+
const deprecated = util.deprecate(deprecatedClass, 'deprecatedClass is deprecated.');
8+
9+
const instance = new deprecated();
10+
11+
assert(instance instanceof deprecated);
12+
assert(instance instanceof deprecatedClass);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
const util = require('util');
2+
const assert = require('assert');
3+
4+
class deprecatedClass {
5+
}
6+
7+
const deprecated = util.deprecate(deprecatedClass, 'deprecatedClass is deprecated.');
8+
9+
class subclass extends deprecated {
10+
constructor() {
11+
super();
12+
}
13+
}
14+
15+
const instance = new subclass();
16+
17+
assert(instance instanceof subclass);
18+
assert(instance instanceof deprecated);
19+
assert(instance instanceof deprecatedClass);

test/sequential/test-deprecation-flags.js

+21-3
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@ const execFile = require('child_process').execFile;
55
const depmod = require.resolve(common.fixturesDir + '/deprecated.js');
66
const node = process.execPath;
77

8-
const depUserland =
9-
require.resolve(common.fixturesDir + '/deprecated-userland-function.js');
8+
const depUserlandFunction =
9+
require.resolve(common.fixturesDir + '/deprecated-userland-function.js');
10+
11+
const depUserlandClass =
12+
require.resolve(common.fixturesDir + '/deprecated-userland-class.js');
13+
14+
const depUserlandSubClass =
15+
require.resolve(common.fixturesDir + '/deprecated-userland-subclass.js');
1016

1117
const normal = [depmod];
1218
const noDep = ['--no-deprecation', depmod];
@@ -39,10 +45,22 @@ execFile(node, traceDep, function(er, stdout, stderr) {
3945
console.log('trace ok');
4046
});
4147

42-
execFile(node, [depUserland], function(er, stdout, stderr) {
48+
execFile(node, [depUserlandFunction], function(er, stdout, stderr) {
4349
console.error('normal: testing deprecated userland function');
4450
assert.equal(er, null);
4551
assert.equal(stdout, '');
4652
assert(/deprecatedFunction is deprecated/.test(stderr));
4753
console.error('normal: ok');
4854
});
55+
56+
execFile(node, [depUserlandClass], function(er, stdout, stderr) {
57+
assert.strictEqual(er, null);
58+
assert.strictEqual(stdout, '');
59+
assert(/deprecatedClass is deprecated/.test(stderr));
60+
});
61+
62+
execFile(node, [depUserlandSubClass], function(er, stdout, stderr) {
63+
assert.strictEqual(er, null);
64+
assert.strictEqual(stdout, '');
65+
assert(/deprecatedClass is deprecated/.test(stderr));
66+
});

0 commit comments

Comments
 (0)