UNPKG

immutable-tuple

Version:

Immutable finite list objects with constant-time equality testing (===) and no memory leaks

85 lines (75 loc) 2.39 kB
// Although `Symbol` is widely supported these days, we can safely fall // back to using a non-enumerable string property without violating any // assumptions elsewhere in the implementation. const useSymbol = typeof Symbol === "function" && typeof Symbol.for === "function"; // Used to mark `tuple.prototype` so that all objects that inherit from // any `tuple.prototype` object (there could be more than one) will test // positive according to `tuple.isTuple`. export const brand = useSymbol ? Symbol.for("immutable-tuple") : "@@__IMMUTABLE_TUPLE__@@"; // Used to save a reference to the globally shared `UniversalWeakMap` that // stores all known `tuple` objects. export const globalKey = useSymbol ? Symbol.for("immutable-tuple-root") : "@@__IMMUTABLE_TUPLE_ROOT__@@"; // Convenient helper for defining hidden immutable properties. export function def(obj, name, value, enumerable) { Object.defineProperty(obj, name, { value: value, enumerable: !! enumerable, writable: false, configurable: false }); return value; } export const freeze = Object.freeze || function (obj) { return obj; }; export function isObjRef(value) { switch (typeof value) { case "object": if (value === null) { return false; } case "function": return true; default: return false; } } // The `mustConvertThisToArray` value is true when the corresponding // `Array` method does not attempt to modify `this`, which means we can // pass a `tuple` object as `this` without first converting it to an // `Array`. export function forEachArrayMethod(fn) { function call(name, mustConvertThisToArray) { const desc = Object.getOwnPropertyDescriptor(Array.prototype, name); fn(name, desc, !! mustConvertThisToArray); } call("every"); call("filter"); call("find"); call("findIndex"); call("forEach"); call("includes"); call("indexOf"); call("join"); call("lastIndexOf"); call("map"); call("reduce"); call("reduceRight"); call("slice"); call("some"); call("toLocaleString"); call("toString"); // The `reverse` and `sort` methods are usually destructive, but for // `tuple` objects they return a new `tuple` object that has been // appropriately reversed/sorted. call("reverse", true); call("sort", true); // Make `[...someTuple]` work. call(useSymbol && Symbol.iterator || "@@iterator"); }