Comparing version 3.1.4 to 4.0.0
@@ -29,2 +29,23 @@ "use strict"; | ||
} | ||
/** | ||
* Utility function for mixing a number of prototypes into a target object. Utilizes getProtoChain() to intelligently | ||
* apply the mixing. | ||
*/ | ||
function mixPrototypes(target, ingredients, exclude) { | ||
if (exclude === void 0) { exclude = []; } | ||
var appliedPrototypes = []; | ||
for (var _i = 0, ingredients_1 = ingredients; _i < ingredients_1.length; _i++) { | ||
var prototype = ingredients_1[_i]; | ||
var protoChain = getProtoChain(prototype); | ||
// Apply the prototype chain in reverse order, so that old methods don't override newer ones; also make sure | ||
// that the same prototype is never applied more than once. | ||
for (var i = protoChain.length - 1; i >= 0; i--) { | ||
var newProto = protoChain[i]; | ||
if (appliedPrototypes.indexOf(newProto) === -1) { | ||
copyProps(target, protoChain[i], exclude); | ||
appliedPrototypes.push(newProto); | ||
} | ||
} | ||
} | ||
} | ||
function Mixin() { | ||
@@ -42,4 +63,4 @@ var ingredients = []; | ||
} | ||
for (var _a = 0, ingredients_3 = ingredients; _a < ingredients_3.length; _a++) { | ||
var constructor = ingredients_3[_a]; | ||
for (var _a = 0, ingredients_2 = ingredients; _a < ingredients_2.length; _a++) { | ||
var constructor = ingredients_2[_a]; | ||
// If the constructor is a callable JS function, we would prefer to apply it directly to `this`, | ||
@@ -56,50 +77,5 @@ if (!isClass(constructor)) | ||
// Apply prototypes, including those up the chain | ||
var mixedClassProto = Mixed.prototype, appliedPrototypes = []; | ||
for (var _a = 0, ingredients_1 = ingredients; _a < ingredients_1.length; _a++) { | ||
var item = ingredients_1[_a]; | ||
var protoChain = getProtoChain(item.prototype); | ||
// Apply the prototype chain in reverse order, so that old methods don't override newer ones; also make sure | ||
// that the same prototype is never applied more than once. | ||
for (var i = protoChain.length - 1; i >= 0; i--) { | ||
var newProto = protoChain[i]; | ||
if (appliedPrototypes.indexOf(newProto) === -1) { | ||
copyProps(mixedClassProto, protoChain[i], ['constructor']); | ||
appliedPrototypes.push(newProto); | ||
} | ||
} | ||
} | ||
var _loop_1 = function (constructor) { | ||
// Get the static properties on the constructor. Note that we must use getOwnPropertyDescriptors because static | ||
// methods are not enumerable and we also want to take special care of getters/setters. As a consequence, | ||
// prototype, length, and name (inherited from Function) must be filtered out | ||
var props = Object.getOwnPropertyDescriptors(constructor); | ||
['prototype', 'length', 'name'].forEach(function (prop) { return delete props[prop]; }); | ||
var _loop_2 = function (prop) { | ||
if (!Mixed.hasOwnProperty(prop)) { | ||
var descriptor = props[prop]; | ||
// If we are dealing with a plain property (i.e., no getter/setter), create a getter/setter property | ||
// that just links back to the original | ||
if (!(descriptor.get || descriptor.set)) { | ||
Object.defineProperty(Mixed, prop, { | ||
get: function () { return constructor[prop]; }, | ||
set: function (val) { constructor[prop] = val; }, | ||
enumerable: true, | ||
configurable: false | ||
}); | ||
} | ||
// Otherwise, replicate the property | ||
else { | ||
Object.defineProperty(Mixed, prop, descriptor); | ||
} | ||
} | ||
}; | ||
for (var prop in props) { | ||
_loop_2(prop); | ||
} | ||
}; | ||
// Mix static properties by linking to the original static props with getters/setters | ||
for (var _b = 0, ingredients_2 = ingredients; _b < ingredients_2.length; _b++) { | ||
var constructor = ingredients_2[_b]; | ||
_loop_1(constructor); | ||
} | ||
mixPrototypes(Mixed.prototype, ingredients.map(function (ctor) { return ctor.prototype; }), ['constructor']); | ||
// Mix static properties | ||
mixPrototypes(Mixed, ingredients, ['prototype', 'length', 'name']); | ||
return Mixed; | ||
@@ -106,0 +82,0 @@ } |
{ | ||
"name": "ts-mixer", | ||
"version": "3.1.4", | ||
"version": "4.0.0", | ||
"description": "A very small TypeScript library that provides tolerable Mixin functionality.", | ||
@@ -35,3 +35,3 @@ "main": "dist/mixins.js", | ||
"mocha": "^6.1.3", | ||
"nyc": "^14.1.1", | ||
"nyc": "14.1.1", | ||
"rimraf": "^2.6.3", | ||
@@ -38,0 +38,0 @@ "ts-node": "^8.1.0", |
@@ -21,3 +21,3 @@ # ts-mixer | ||
* Automatic inference of the mixed class type[¹](#caveats) | ||
* Proper handling of static properties [³](#caveats) | ||
* Support for static properties [³](#caveats) | ||
@@ -24,0 +24,0 @@ #### Caveats |
18381
125