]> Lady’s Gitweb - Pisces/commitdiff
Add methods for own entries and values to object.js current
authorLady <redacted>
Sun, 3 Dec 2023 19:51:19 +0000 (14:51 -0500)
committerLady <redacted>
Sun, 3 Dec 2023 19:51:19 +0000 (14:51 -0500)
object.js
object.test.js

index bd310ca87946e2990a2fb2a5731198c1f6f043fa..3221e1da360305d4da5fa5582355cee6cf896e03 100644 (file)
--- a/object.js
+++ b/object.js
@@ -10,6 +10,7 @@
 import {
   IS_CONCAT_SPREADABLE,
   isAccessorDescriptor,
+  isDataDescriptor,
   SPECIES,
   toFunctionName,
   toLength,
@@ -17,6 +18,7 @@ import {
   UNDEFINED,
 } from "./value.js";
 
+const createArray = Array;
 const { isArray } = Array;
 const object = Object;
 const {
@@ -357,6 +359,8 @@ export const getOwnPropertyDescriptors = (O) => {
   const keys = ownKeys(obj);
   const descriptors = {};
   for (let k = 0; k < keys.length; ++k) {
+    // Iterate over the keys of the provided object and collect its
+    // descriptors.
     const key = keys[k];
     defineOwnDataProperty(
       descriptors,
@@ -368,7 +372,29 @@ export const getOwnPropertyDescriptors = (O) => {
 };
 
 /**
- * Returns an array of property keys on the provided value.
+ * Returns an array of own property entries on the provided value,
+ * using the provided receiver if given.
+ */
+export const getOwnPropertyEntries = (O, Receiver = O) => {
+  const obj = toObject(O);
+  const keys = ownKeys(obj);
+  const target = Receiver === UNDEFINED ? obj : toObject(Receiver);
+  const result = createArray(keys.length);
+  for (let k = 0; k < keys.length; ++k) {
+    // Iterate over each key and add the corresponding entry to the
+    // result.
+    const key = keys[k];
+    defineOwnDataProperty(
+      result,
+      k,
+      [key, getOwnPropertyValue(obj, keys[k], target)],
+    );
+  }
+  return result;
+};
+
+/**
+ * Returns an array of own property keys on the provided value.
  *
  * ※ This is effectively an alias for `Reflect.ownKeys`, except that
  * it does not require that the argument be an object.
@@ -397,6 +423,53 @@ export const getOwnPropertyStrings = (O) => getOwnPropertyNames(O);
 export const getOwnPropertySymbols = (O) =>
   objectGetOwnPropertySymbols(O);
 
+/**
+ * Returns the value of the provided own property on the provided
+ * value using the provided receiver, or undefined if the provided
+ * property is not an own property on the provided value.
+ *
+ * ※ If the receiver is not provided, it defaults to the provided
+ * value.
+ */
+export const getOwnPropertyValue = (O, P, Receiver = UNDEFINED) => {
+  const obj = toObject(O);
+  const desc = getOwnPropertyDescriptor(O, P);
+  if (desc === UNDEFINED) {
+    // The provided property is not an own property on the provided
+    // value; return undefined.
+    return UNDEFINED;
+  }
+  if (isDataDescriptor(desc)) {
+    // The provided property is a data property; return its value.
+    return desc.value;
+  } else {
+    // The provided property is an accessor property; get its value
+    // using the appropriate receiver.
+    const target = Receiver === UNDEFINED ? obj : toObject(Receiver);
+    return call(desc.get, target, []);
+  }
+};
+
+/**
+ * Returns an array of own property values on the provided value, using
+ * the provided receiver if given.
+ */
+export const getOwnPropertyValues = (O, Receiver = O) => {
+  const obj = toObject(O);
+  const keys = ownKeys(obj);
+  const target = Receiver === UNDEFINED ? obj : toObject(Receiver);
+  const result = createArray(keys.length);
+  for (let k = 0; k < keys.length; ++k) {
+    // Iterate over each key and collect the values.
+    defineOwnDataProperty(
+      result,
+      k,
+      getOwnPropertyValue(obj, keys[k], target),
+    );
+  }
+  return result;
+};
+
 /**
  * Returns the value of the provided property key on the provided
  * value.
index 348d06da83332901c8047288658ab08c607cfa56..cba44b948824ba411ecb966ae3e80a1265a3f5c4 100644 (file)
@@ -30,9 +30,12 @@ import {
   getMethod,
   getOwnPropertyDescriptor,
   getOwnPropertyDescriptors,
+  getOwnPropertyEntries,
   getOwnPropertyKeys,
   getOwnPropertyStrings,
   getOwnPropertySymbols,
+  getOwnPropertyValue,
+  getOwnPropertyValues,
   getPropertyValue,
   getPrototype,
   hasOwnProperty,
@@ -840,6 +843,58 @@ describe("getOwnPropertyDescriptors", () => {
   });
 });
 
+describe("getOwnPropertyEntries", () => {
+  it("[[Call]] gets own (but not inherited) property entries", () => {
+    assertEquals(
+      getOwnPropertyEntries({ success: true }),
+      [["success", true]],
+    );
+  });
+
+  it("[[Call]] works for values coercible to objects", () => {
+    assertEquals(
+      getOwnPropertyEntries("foo"),
+      [["0", "f"], ["1", "o"], ["2", "o"], ["length", 3]],
+    );
+  });
+
+  it("[[Call]] uses the provided receiver", () => {
+    const target = {};
+    assertEquals(
+      getOwnPropertyEntries({
+        get success() {
+          return this;
+        },
+      }, target),
+      [["success", target]],
+    );
+  });
+
+  it("[[Call]] throws for null and undefined", () => {
+    assertThrows(() => getOwnPropertyEntries(null));
+    assertThrows(() => getOwnPropertyEntries(undefined));
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new getOwnPropertyEntries({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(getOwnPropertyEntries.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        getOwnPropertyEntries.name,
+        "getOwnPropertyEntries",
+      );
+    });
+  });
+});
+
 describe("getOwnPropertyKeys", () => {
   it("[[Call]] gets own (but not inherited) property keys", () => {
     assertEquals(getOwnPropertyKeys({ success: true }), ["success"]);
@@ -950,6 +1005,115 @@ describe("getOwnPropertySymbols", () => {
   });
 });
 
+describe("getOwnPropertyValue", () => {
+  it("[[Call]] gets the own property value", () => {
+    assertStrictEquals(
+      getOwnPropertyValue({ success: true }, "success"),
+      true,
+    );
+  });
+
+  it("[[Call]] returns undefined for non‐own properties", () => {
+    assertStrictEquals(
+      getOwnPropertyValue(Object.create({ success: true }), "success"),
+      undefined,
+    );
+  });
+
+  it("[[Call]] works for values coercible to objects", () => {
+    assertStrictEquals(getOwnPropertyValue("foo", "length"), 3);
+  });
+
+  it("[[Call]] uses the provided receiver", () => {
+    const target = {};
+    assertStrictEquals(
+      getOwnPropertyValue(
+        {
+          get success() {
+            return this;
+          },
+        },
+        "success",
+        target,
+      ),
+      target,
+    );
+  });
+
+  it("[[Call]] throws for null and undefined", () => {
+    assertThrows(() => getOwnPropertyValue(null));
+    assertThrows(() => getOwnPropertyValue(undefined));
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new getOwnPropertyValue({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(getOwnPropertyValue.length, 2);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        getOwnPropertyValue.name,
+        "getOwnPropertyValue",
+      );
+    });
+  });
+});
+
+describe("getOwnPropertyValues", () => {
+  it("[[Call]] gets own (but not inherited) property values", () => {
+    assertEquals(getOwnPropertyValues({ success: true }), [true]);
+  });
+
+  it("[[Call]] works for values coercible to objects", () => {
+    assertEquals(
+      getOwnPropertyValues("foo"),
+      ["f", "o", "o", 3],
+    );
+  });
+
+  it("[[Call]] uses the provided receiver", () => {
+    const target = {};
+    assertEquals(
+      getOwnPropertyValues({
+        get success() {
+          return this;
+        },
+      }, target),
+      [target],
+    );
+  });
+
+  it("[[Call]] throws for null and undefined", () => {
+    assertThrows(() => getOwnPropertyValues(null));
+    assertThrows(() => getOwnPropertyValues(undefined));
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new getOwnPropertyValues({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(getOwnPropertyValues.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        getOwnPropertyValues.name,
+        "getOwnPropertyValues",
+      );
+    });
+  });
+});
+
 describe("getPropertyValue", () => {
   it("[[Call]] gets property values on the provided object", () => {
     assertStrictEquals(
This page took 0.06661 seconds and 4 git commands to generate.