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 <thechargingvolcano@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
Michaël Zasso 2015-10-20 21:39:49 +02:00
parent 437930c0cc
commit 29da8cf8d7
2 changed files with 35 additions and 8 deletions

View File

@ -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) {

View File

@ -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);