import {
IS_CONCAT_SPREADABLE,
isAccessorDescriptor,
+ isDataDescriptor,
SPECIES,
toFunctionName,
toLength,
UNDEFINED,
} from "./value.js";
+const createArray = Array;
const { isArray } = Array;
const object = Object;
const {
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,
};
/**
- * 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.
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.
getMethod,
getOwnPropertyDescriptor,
getOwnPropertyDescriptors,
+ getOwnPropertyEntries,
getOwnPropertyKeys,
getOwnPropertyStrings,
getOwnPropertySymbols,
+ getOwnPropertyValue,
+ getOwnPropertyValues,
getPropertyValue,
getPrototype,
hasOwnProperty,
});
});
+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"]);
});
});
+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(