diff options
author | sowgro <tpoke.ferrari@gmail.com> | 2023-09-02 19:12:47 -0400 |
---|---|---|
committer | sowgro <tpoke.ferrari@gmail.com> | 2023-09-02 19:12:47 -0400 |
commit | e4450c8417624b71d779cb4f41692538f9165e10 (patch) | |
tree | b70826542223ecdf8a7a259f61b0a1abb8a217d8 /node_modules/ts-mixer/dist/cjs/util.js | |
download | sowbot3-e4450c8417624b71d779cb4f41692538f9165e10.tar.gz sowbot3-e4450c8417624b71d779cb4f41692538f9165e10.tar.bz2 sowbot3-e4450c8417624b71d779cb4f41692538f9165e10.zip |
first commit
Diffstat (limited to 'node_modules/ts-mixer/dist/cjs/util.js')
-rw-r--r-- | node_modules/ts-mixer/dist/cjs/util.js | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/node_modules/ts-mixer/dist/cjs/util.js b/node_modules/ts-mixer/dist/cjs/util.js new file mode 100644 index 0000000..5151696 --- /dev/null +++ b/node_modules/ts-mixer/dist/cjs/util.js @@ -0,0 +1,85 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.flatten = exports.unique = exports.hardMixProtos = exports.nearestCommonProto = exports.protoChain = exports.copyProps = void 0; +/** + * Utility function that works like `Object.apply`, but copies getters and setters properly as well. Additionally gives + * the option to exclude properties by name. + */ +const copyProps = (dest, src, exclude = []) => { + const props = Object.getOwnPropertyDescriptors(src); + for (let prop of exclude) + delete props[prop]; + Object.defineProperties(dest, props); +}; +exports.copyProps = copyProps; +/** + * Returns the full chain of prototypes up until Object.prototype given a starting object. The order of prototypes will + * be closest to farthest in the chain. + */ +const protoChain = (obj, currentChain = [obj]) => { + const proto = Object.getPrototypeOf(obj); + if (proto === null) + return currentChain; + return (0, exports.protoChain)(proto, [...currentChain, proto]); +}; +exports.protoChain = protoChain; +/** + * Identifies the nearest ancestor common to all the given objects in their prototype chains. For most unrelated + * objects, this function should return Object.prototype. + */ +const nearestCommonProto = (...objs) => { + if (objs.length === 0) + return undefined; + let commonProto = undefined; + const protoChains = objs.map(obj => (0, exports.protoChain)(obj)); + while (protoChains.every(protoChain => protoChain.length > 0)) { + const protos = protoChains.map(protoChain => protoChain.pop()); + const potentialCommonProto = protos[0]; + if (protos.every(proto => proto === potentialCommonProto)) + commonProto = potentialCommonProto; + else + break; + } + return commonProto; +}; +exports.nearestCommonProto = nearestCommonProto; +/** + * Creates a new prototype object that is a mixture of the given prototypes. The mixing is achieved by first + * identifying the nearest common ancestor and using it as the prototype for a new object. Then all properties/methods + * downstream of this prototype (ONLY downstream) are copied into the new object. + * + * The resulting prototype is more performant than softMixProtos(...), as well as ES5 compatible. However, it's not as + * flexible as updates to the source prototypes aren't captured by the mixed result. See softMixProtos for why you may + * want to use that instead. + */ +const hardMixProtos = (ingredients, constructor, exclude = []) => { + var _a; + const base = (_a = (0, exports.nearestCommonProto)(...ingredients)) !== null && _a !== void 0 ? _a : Object.prototype; + const mixedProto = Object.create(base); + // Keeps track of prototypes we've already visited to avoid copying the same properties multiple times. We init the + // list with the proto chain below the nearest common ancestor because we don't want any of those methods mixed in + // when they will already be accessible via prototype access. + const visitedProtos = (0, exports.protoChain)(base); + for (let prototype of ingredients) { + let protos = (0, exports.protoChain)(prototype); + // Apply the prototype chain in reverse order so that old methods don't override newer ones. + for (let i = protos.length - 1; i >= 0; i--) { + let newProto = protos[i]; + if (visitedProtos.indexOf(newProto) === -1) { + (0, exports.copyProps)(mixedProto, newProto, ['constructor', ...exclude]); + visitedProtos.push(newProto); + } + } + } + mixedProto.constructor = constructor; + return mixedProto; +}; +exports.hardMixProtos = hardMixProtos; +const unique = (arr) => arr.filter((e, i) => arr.indexOf(e) == i); +exports.unique = unique; +const flatten = (arr) => arr.length === 0 + ? [] + : arr.length === 1 + ? arr[0] + : arr.reduce((a1, a2) => [...a1, ...a2]); +exports.flatten = flatten; |