]> Lady’s Gitweb - Pisces/blobdiff - object.js
Move isConcatSpreadable[Object] into object.js
[Pisces] / object.js
index 83519fd8b0f9a9f0a59517631c30be4fbfa97453..ee3d51da336d6f1c5a09123cd41b8ec921550f80 100644 (file)
--- 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.
This page took 0.022571 seconds and 4 git commands to generate.