From 29da8cf8d7ab8f66b9091ab22664067d4468461e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Tue, 20 Oct 2015 21:39:49 +0200 Subject: [PATCH] util: make inherits work with classes The current implementation overwrites the prototype of the target constructor. It is not allowed with ES2015 classes because the prototype property is read only. Use Object.setPrototypeOf instead. Fixes: https://github.com/nodejs/node/issues/3452 PR-URL: https://github.com/nodejs/node/pull/3455 Reviewed-By: Sakthipriyan Vairamani Reviewed-By: James M Snell --- lib/util.js | 9 +------- test/parallel/test-util-inherits.js | 34 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/lib/util.js b/lib/util.js index 19d3d464f1..d143552615 100644 --- a/lib/util.js +++ b/lib/util.js @@ -761,14 +761,7 @@ exports.inherits = function(ctor, superCtor) { 'have a prototype.'); ctor.super_ = superCtor; - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); + Object.setPrototypeOf(ctor.prototype, superCtor.prototype); }; exports._extend = function(origin, add) { diff --git a/test/parallel/test-util-inherits.js b/test/parallel/test-util-inherits.js index baa77ea440..a3c5786fe2 100644 --- a/test/parallel/test-util-inherits.js +++ b/test/parallel/test-util-inherits.js @@ -40,6 +40,40 @@ const c = new C(); assert.strictEqual(c.getValue(), 'abc'); assert.strictEqual(c.constructor, C); +// inherits can be called after setting prototype properties +function D() { + C.call(this); + this._d = 'd'; +} + +D.prototype.d = function() { return this._d; }; +inherits(D, C); + +assert.strictEqual(D.super_, C); + +const d = new D(); +assert.strictEqual(d.c(), 'c'); +assert.strictEqual(d.d(), 'd'); +assert.strictEqual(d.constructor, D); + +// ES6 classes can inherit from a constructor function +class E { + constructor() { + D.call(this); + this._e = 'e'; + } + e() { return this._e; } +} +inherits(E, D); + +assert.strictEqual(E.super_, D); + +const e = new E(); +assert.strictEqual(e.getValue(), 'abc'); +assert.strictEqual(e.d(), 'd'); +assert.strictEqual(e.e(), 'e'); +assert.strictEqual(e.constructor, E); + // should throw with invalid arguments assert.throws(function() { inherits(A, {}); }, TypeError); assert.throws(function() { inherits(A, null); }, TypeError);