diff --git a/doc/api/util.md b/doc/api/util.md index 34c6839333..6f011929a2 100644 --- a/doc/api/util.md +++ b/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 diff --git a/lib/internal/util.js b/lib/internal/util.js index e3d9a66b3b..073879d9e9 100644 --- a/lib/internal/util.js +++ b/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; }; diff --git a/test/fixtures/deprecated-userland-class.js b/test/fixtures/deprecated-userland-class.js new file mode 100644 index 0000000000..867bbbf2ae --- /dev/null +++ b/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); diff --git a/test/fixtures/deprecated-userland-subclass.js b/test/fixtures/deprecated-userland-subclass.js new file mode 100644 index 0000000000..2df374ad7d --- /dev/null +++ b/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); diff --git a/test/sequential/test-deprecation-flags.js b/test/sequential/test-deprecation-flags.js index bbb5ecb700..e9f5ee673d 100644 --- a/test/sequential/test-deprecation-flags.js +++ b/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)); +});