98 lines
2.6 KiB
JavaScript
98 lines
2.6 KiB
JavaScript
var util = require('util');
|
|
|
|
/**
|
|
*
|
|
* @param newClass
|
|
* @param baseClass
|
|
*/
|
|
exports.inherits = function (newClass, baseClass, options) {
|
|
util.inherits(newClass, baseClass);
|
|
|
|
options = options || {
|
|
staticProperties: true,
|
|
override: false
|
|
};
|
|
|
|
if (options.staticProperties) {
|
|
Object.keys(baseClass).forEach(function (classProp) {
|
|
if (classProp !== 'super_' && (!newClass.hasOwnProperty(classProp)
|
|
|| options.override)) {
|
|
var pd = Object.getOwnPropertyDescriptor(baseClass, classProp);
|
|
Object.defineProperty(newClass, classProp, pd);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Mix in the a class into the new class
|
|
* @param newClass The target class to receive the mixin
|
|
* @param mixinClass The class to be mixed in
|
|
* @param options
|
|
*/
|
|
exports.mixin = function (newClass, mixinClass, options) {
|
|
if (Array.isArray(newClass._mixins)) {
|
|
if (newClass._mixins.indexOf(mixinClass) !== -1) {
|
|
return;
|
|
}
|
|
newClass._mixins.push(mixinClass);
|
|
} else {
|
|
newClass._mixins = [mixinClass];
|
|
}
|
|
|
|
options = options || {
|
|
staticProperties: true,
|
|
instanceProperties: true,
|
|
override: false,
|
|
proxyFunctions: false
|
|
};
|
|
|
|
if (options.staticProperties === undefined) {
|
|
options.staticProperties = true;
|
|
}
|
|
|
|
if (options.instanceProperties === undefined) {
|
|
options.instanceProperties = true;
|
|
}
|
|
|
|
if (options.staticProperties) {
|
|
mixInto(mixinClass, newClass, options);
|
|
}
|
|
|
|
if (options.instanceProperties && mixinClass.prototype) {
|
|
mixInto(mixinClass.prototype, newClass.prototype, options);
|
|
}
|
|
|
|
return newClass;
|
|
};
|
|
|
|
function mixInto(sourceScope, targetScope, options) {
|
|
Object.keys(sourceScope).forEach(function (propertyName) {
|
|
var targetPropertyExists = targetScope.hasOwnProperty(propertyName);
|
|
var sourceProperty = Object.getOwnPropertyDescriptor(sourceScope, propertyName);
|
|
var targetProperty = targetPropertyExists && Object.getOwnPropertyDescriptor(targetScope, propertyName);
|
|
var sourceIsFunc = typeof sourceProperty.value === 'function';
|
|
var isFunc = targetPropertyExists && typeof targetProperty.value === 'function';
|
|
var isDelegate = isFunc && targetProperty.value._delegate;
|
|
var shouldOverride = options.override || !targetPropertyExists || isDelegate;
|
|
|
|
if (propertyName == '_mixins') {
|
|
mergeMixins(sourceScope._mixins, targetScope._mixins);
|
|
return;
|
|
}
|
|
|
|
if (shouldOverride) {
|
|
Object.defineProperty(targetScope, propertyName, sourceProperty);
|
|
}
|
|
});
|
|
}
|
|
|
|
function mergeMixins(source, target) {
|
|
// hand-written equivalent of lodash.union()
|
|
for (var ix in source) {
|
|
var mx = source[ix];
|
|
if (target.indexOf(mx) === -1)
|
|
target.push(mx);
|
|
}
|
|
}
|