X-Git-Url: https://git.ladys.computer/Pisces/blobdiff_plain/1d3702d7c4058cc6c8fa8927f0848a1bfb3c19fb..beab7268e7673b036222e64aac924f850e2b976e:/object.js?ds=inline diff --git a/object.js b/object.js index 83519fd..ee3d51d 100644 --- a/object.js +++ b/object.js @@ -13,7 +13,14 @@ import { createArrowFunction, toFunctionName, } from "./function.js"; -import { ITERATOR, SPECIES, toPrimitive, type } from "./value.js"; +import { + IS_CONCAT_SPREADABLE, + ITERATOR, + SPECIES, + toLength, + toPrimitive, + type, +} from "./value.js"; /** * An object whose properties are lazy‐loaded from the methods on the @@ -495,24 +502,9 @@ export const { isSealed, setPrototypeOf, } = Object; - const { [ITERATOR]: arrayIterator } = Array.prototype; - const { next: arrayIteratorNext } = getPrototypeOf([][ITERATOR]()); const { next: generatorIteratorNext, } = getPrototypeOf(function* () {}.prototype); - const splatIterablePrototype = { - [ITERATOR]() { - return { - next: bind( - arrayIteratorNext, - call(arrayIterator, this.args, []), - [], - ), - }; - }, - }; - const splatIterable = ($) => - create(splatIterablePrototype, { args: { value: $ } }); const propertyDescriptorEntryIterablePrototype = { [ITERATOR]() { return { @@ -527,8 +519,9 @@ export const { return { defineOwnProperties: (O, ...sources) => { - for (const source of splatIterable(sources)) { - defineProperties(O, source); + const { length } = sources; + for (let index = 0; index < length; ++index) { + defineProperties(O, sources[index]); } return O; }, @@ -804,6 +797,46 @@ export const hasOwnProperty = createArrowFunction(Object.hasOwn, { name: "hasOwnProperty", }); +/** Returns whether the provided value is an arraylike object. */ +export const isArraylikeObject = ($) => { + if (type($) !== "object") { + return false; + } else { + try { + lengthOfArraylike($); // throws if not arraylike + return true; + } catch { + return false; + } + } +}; + +export const { + /** + * Returns whether the provided value is spreadable during array + * concatenation. + * + * This is also used to determine which things should be treated as + * collections. + */ + isConcatSpreadableObject, +} = (() => { + const { isArray } = Array; + + return { + isConcatSpreadableObject: ($) => { + if (type($) !== "object") { + // The provided value is not an object. + return false; + } else { + // The provided value is an object. + const spreadable = $[IS_CONCAT_SPREADABLE]; + return spreadable !== undefined ? !!spreadable : isArray($); + } + }, + }; +})(); + /** * Returns whether the provided object is extensible. * @@ -816,6 +849,16 @@ export const isExtensibleObject = createArrowFunction( { name: "isExtensibleObject" }, ); +/** + * Returns the length of the provided arraylike value. + * + * This can produce larger lengths than can actually be stored in + * arrays, because no such restrictions exist on arraylike methods. + * + * ☡ This function throws if the provided value is not arraylike. + */ +export const lengthOfArraylike = ({ length }) => toLength(length); + /** * Returns an array of key~value pairs for the enumerable, * string‐valued property keys on the provided object.