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
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 {
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;
},
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.
*
{ 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.