scontainers
Version:
A container/collection/iterator library for JavaScript, comfortable to use, performant and versatile.
120 lines (89 loc) • 3.04 kB
JavaScript
;
function _implSymbol(target, sym, value) {
Object.defineProperty(target, sym, {
value,
configurable: true
});
return target[sym];
}
function _getSymbol(targetSymName, ...traitSets) {
let symbol;
traitSets.forEach(traitSet => {
const sym = traitSet[targetSymName];
if (typeof sym === 'symbol') {
if (!!symbol && symbol !== sym) {
throw new Error(`Symbol ${targetSymName} offered by multiple trait sets.`);
}
symbol = sym;
}
});
if (!symbol) {
throw new Error(`No trait set is providing symbol ${targetSymName}.`);
}
return symbol;
}
function _testTraitSet(traitSet) {
if (!traitSet || typeof traitSet === 'boolean' || typeof traitSet === 'number' || typeof traitSet === 'string') {
throw new Error(`${traitSet} cannot be used as a trait set.`);
}
}
const straits = require('straits');
const semanticTraits = require('esast/dist/semantics.js');
const descriptorTraits = require('./traits/descriptor.js');
const generatorTraits = require('./traits/generators.js');
const scontainerTraits = require('./traits/scontainers.js');
const utilTraits = require('./traits/utils.js');
const {
ReorderedIterator
} = require('./reordered_iterator.js');
const utilsLight = require('./utils_light.js');
const {
assert
} = utilsLight;
_testTraitSet(utilTraits);
_testTraitSet(scontainerTraits);
const _asMethod = _getSymbol("asMethod", utilTraits, scontainerTraits);
const _addTraitFactories = _getSymbol("addTraitFactories", utilTraits, scontainerTraits);
const _wrapScontainer = _getSymbol("wrapScontainer", utilTraits, scontainerTraits);
const _implScontainer = _getSymbol("implScontainer", utilTraits, scontainerTraits);
const utils = {
ReorderedIterator,
traits: {
descriptors: descriptorTraits,
generators: generatorTraits,
scontainers: scontainerTraits,
utils: utilTraits,
semantics: semanticTraits
},
toStr: straits.common.toString[_asMethod]()
};
Object.assign(utils, utilsLight); // implementing util traits
{
_implSymbol(Object.prototype, _implScontainer, function (implementationObj) {
const factoryObj = {};
for (let key in implementationObj) {
factoryObj[key] = function () {
return implementationObj[key];
};
} // return scontainerTraits._Straits.addTrait( this, implementationObj );
return scontainerTraits[_addTraitFactories](this, factoryObj);
});
_implSymbol(Object.prototype, _wrapScontainer, function (decoratorFactoryFactory) {
const Container = this;
const decoratorFactory = decoratorFactoryFactory(Container);
if (!decoratorFactory) {
// this decorator can't be implemented on `Type`
return;
}
return {
factory() {
const Decorator = decoratorFactory(Container);
assert(typeof Decorator === 'function', `${decoratorFactory.name} is broken.`);
return function (...args) {
return new Decorator(this, ...args);
};
}
};
});
}
module.exports = utils;