scontainers
Version:
A container/collection/iterator library for JavaScript, comfortable to use, performant and versatile.
149 lines (109 loc) • 3.64 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 {
assert,
traits,
semantics,
toStr,
id,
KVN
} = require('../utils.js');
_testTraitSet(traits.utils);
_testTraitSet(traits.scontainers);
_testTraitSet(traits.semantics);
const _describeScontainer = _getSymbol("describeScontainer", traits.utils, traits.scontainers, traits.semantics);
const _implCoreGenerators = _getSymbol("implCoreGenerators", traits.utils, traits.scontainers, traits.semantics);
const _member = _getSymbol("member", traits.utils, traits.scontainers, traits.semantics);
const _call = _getSymbol("call", traits.utils, traits.scontainers, traits.semantics);
const _forIn = _getSymbol("forIn", traits.utils, traits.scontainers, traits.semantics);
const _if = _getSymbol("if", traits.utils, traits.scontainers, traits.semantics);
const _hasKey = _getSymbol("hasKey", traits.utils, traits.scontainers, traits.semantics);
const _implCoreTraits = _getSymbol("implCoreTraits", traits.utils, traits.scontainers, traits.semantics);
module.exports = function (ParentCollection) {
assert(ParentCollection === Object, `ObjectOwnProperties is only needed by Object...`);
return function () {
class OwnProperties {
static get name() {
return `ObjectOwnProperties`;
}
constructor(coll) {
this.object = coll;
}
toString() {
var _context;
return `${(_context = this.object, toStr).call(_context)}::ownProperties()`;
}
}
OwnProperties[_describeScontainer]({
argKeys: [id`object`]
});
OwnProperties[_implCoreGenerators]({
getUnchecked(key) {
return this.args.object[_member](key, true);
},
hasKey(key) {
return this.args.object[_member](`hasOwnProperty`)[_call](key);
},
loop() {
const key = this.createUniqueVariable(`key`);
this.body[_forIn](semantics.declare(key, undefined, `var`), this.args.object, semantics.block()[_if](this[_hasKey](key), this.body = semantics.block()));
return new KVN(key, this.args.object[_member](key, true));
}
});
OwnProperties[_implCoreTraits]({
getUnchecked(key) {
return this.object[key];
},
hasKey(key) {
return this.object.hasOwnProperty(key);
},
// set( key, value ) { this.object[key] = value; },},
*iterator() {
for (let key in this.object) {
if (this[_hasKey](key)) {
yield [key, this.object[key]];
}
}
},
kvIterator() {
return {
it: this[Symbol.iterator](),
next() {
const next = this.it.next();
if (!next.done) {
return new KVN(next.value[0], next.value[1]);
}
}
};
}
});
return OwnProperties;
};
};