]> Lady’s Gitweb - Pisces/commitdiff
Improve object.js a·p·i
authorLady <redacted>
Sat, 21 Oct 2023 19:29:12 +0000 (15:29 -0400)
committerLady <redacted>
Sat, 21 Oct 2023 19:29:12 +0000 (15:29 -0400)
- Add tests for functions which were formerly just re·exports of
  standard library functions.

- Test constructibility, name, and length for all exported functions.

- Replace `isFrozenObject` and `isSealedObject` with `isUnfrozenObject`
  and `isUnsealedObject`, as the former versions return _true_, not
  _false_, when provided with a non·object argument.

- Revise `setPrototype` to have better behaviours than the Ecmascript
  implementation when provided with a non·object argument.

object.js
object.test.js

index 55593a390be0fa6ad1c963d83d8717f16c5929c4..3115c3bbfe6059b2edc437950daad8120932db7e 100644 (file)
--- a/object.js
+++ b/object.js
@@ -403,6 +403,14 @@ export const { PropertyDescriptor } = (() => {
 })();
 
 export const {
+  /**
+   * Defines an own property on the provided object on the provided
+   * property key using the provided property descriptor.
+   *
+   * ※ This is effectively an alias for `Object.defineProperty`.
+   */
+  defineOwnProperty,
+
   /**
    * Defines own properties on the provided object using the
    * descriptors on the enumerable own properties of the provided
@@ -412,36 +420,13 @@ export const {
    * multiple source objects.
    */
   defineOwnProperties,
-} = (() => {
-  const { defineProperties } = Object;
-  const { forEach: arrayForEach } = Array.prototype;
-  return {
-    defineOwnProperties: (O, ...sources) => {
-      call(
-        arrayForEach,
-        sources,
-        [(source) => defineProperties(O, source)],
-      );
-      return O;
-    },
-  };
-})();
-
-export const {
-  /**
-   * Defines an own property on the provided object on the provided
-   * property key using the provided property descriptor.
-   *
-   * ※ This is an alias for `Object.defineProperty`.
-   */
-  defineProperty: defineOwnProperty,
 
   /**
    * Marks the provided object as non·extensible and marks all its
    * properties as nonconfigurable and (if data properties)
    * nonwritable, and returns the object.
    *
-   * ※ This is an alias for `Object.freeze`.
+   * ※ This is effectively an alias for `Object.freeze`.
    */
   freeze,
 
@@ -450,7 +435,8 @@ export const {
    * provided property key on the provided object, or null if none
    * exists.
    *
-   * ※ This is an alias for `Object.getOwnPropertyDescriptor`.
+   * ※ This is effectively an alias for
+   * `Object.getOwnPropertyDescriptor`.
    */
   getOwnPropertyDescriptor,
 
@@ -458,7 +444,8 @@ export const {
    * Returns the property descriptors for the own properties on the
    * provided object.
    *
-   * ※ This is an alias for `Object.getOwnPropertyDescriptors`.
+   * ※ This is effectively an alias for
+   * `Object.getOwnPropertyDescriptors`.
    */
   getOwnPropertyDescriptors,
 
@@ -468,9 +455,9 @@ export const {
    *
    * ☡ This includes both enumerable and non·enumerable properties.
    *
-   * ※ This is an alias for `Object.getOwnPropertyNames`.
+   * ※ This is effectively an alias for `Object.getOwnPropertyNames`.
    */
-  getOwnPropertyNames: getOwnPropertyStrings,
+  getOwnPropertyStrings,
 
   /**
    * Returns an array of symbol‐valued own property keys on the
@@ -478,90 +465,97 @@ export const {
    *
    * ☡ This includes both enumerable and non·enumerable properties.
    *
-   * ※ This is an alias for `Object.getOwnPropertySymbols`.
+   * ※ This is effectively an alias for
+   * `Object.getOwnPropertySymbols`.
    */
   getOwnPropertySymbols,
 
   /**
    * Returns the prototype of the provided object.
    *
-   * ※ This is an alias for `Object.getPrototypeOf`.
+   * ※ This is effectively an alias for `Object.getPrototypeOf`.
    */
-  getPrototypeOf: getPrototype,
+  getPrototype,
 
   /**
    * Returns whether the provided object has an own property with the
    * provided property key.
    *
-   * ※ This is an alias for `Object.hasOwn`.
+   * ※ This is effectively an alias for `Object.hasOwn`.
    */
-  hasOwn: hasOwnProperty,
+  hasOwnProperty,
 
   /**
    * Returns whether the provided object is extensible.
    *
-   * ※ This is an alias for `Object.isExtensible`.
+   * ※ This function returns false for nonobjects.
+   *
+   * ※ This is effectively an alias for `Object.isExtensible`.
    */
-  isExtensible: isExtensibleObject,
+  isExtensibleObject,
 
   /**
    * Returns whether the provided object is frozen.
    *
-   * ※ This is an alias for `Object.isFrozen`.
+   * ※ This function returns false for nonobjects.
+   *
+   * ※ This is effectively an alias for `!Object.isFrozen`.
    */
-  isFrozen: isFrozenObject,
+  isUnfrozenObject,
 
   /**
    * Returns whether the provided object is sealed.
    *
-   * ※ This is an alias for `Object.isSealed`.
+   * ※ This function returns false for nonobjects.
+   *
+   * ※ This is effectively an alias for `!Object.isSealed`.
    */
-  isSealed: isSealedObject,
+  isUnsealedObject,
 
   /**
    * Returns an array of key~value pairs for the enumerable,
    * string‐valued property keys on the provided object.
    *
-   * ※ This is an alias for `Object.entries`.
+   * ※ This is effectively an alias for `Object.entries`.
    */
-  entries: namedEntries,
+  namedEntries,
 
   /**
    * Returns an array of the enumerable, string‐valued property keys on
    * the provided object.
    *
-   * ※ This is an alias for `Object.keys`.
+   * ※ This is effectively an alias for `Object.keys`.
    */
-  keys: namedKeys,
+  namedKeys,
 
   /**
    * Returns an array of property values for the enumerable,
    * string‐valued property keys on the provided object.
    *
-   * ※ This is an alias for `Object.values`.
+   * ※ This is effectively an alias for `Object.values`.
    */
-  values: namedValues,
+  namedValues,
 
   /**
    * Returns a new object with the provided prototype and property
    * descriptors.
    *
-   * ※ This is an alias for `Object.create`.
+   * ※ This is effectively an alias for `Object.create`.
    */
-  create: objectCreate,
+  objectCreate,
 
   /**
    * Returns a new object with the provided property keys and values.
    *
-   * ※ This is an alias for `Object.fromEntries`.
+   * ※ This is effectively an alias for `Object.fromEntries`.
    */
-  fromEntries: objectFromEntries,
+  objectFromEntries,
 
   /**
    * Marks the provided object as non·extensible, and returns the
    * object.
    *
-   * ※ This is an alias for `Object.preventExtensions`.
+   * ※ This is effectively an alias for `Object.preventExtensions`.
    */
   preventExtensions,
 
@@ -569,7 +563,7 @@ export const {
    * Marks the provided object as non·extensible and marks all its
    * properties as nonconfigurable, and returns the object.
    *
-   * ※ This is an alias for `Object.seal`.
+   * ※ This is effectively an alias for `Object.seal`.
    */
   seal,
 
@@ -577,18 +571,124 @@ export const {
    * Sets the values of the enumerable own properties of the provided
    * additional objects on the provided object.
    *
-   * ※ This is an alias for `Object.assign`.
+   * ※ This is effectively an alias for `Object.assign`.
    */
-  assign: setPropertyValues,
+  setPropertyValues,
 
   /**
    * Sets the prototype of the provided object to the provided value
    * and returns the object.
    *
-   * ※ This is an alias for `Object.setPrototypeOf`.
+   * ※ This is effectively an alias for `Object.setPrototypeOf`.
+   */
+  setPrototype,
+
+  /**
+   * Returns the provided value converted to an object.
+   *
+   * Existing objects are returned with no modification.
+   *
+   * ☡ This function throws if its argument is null or undefined.
    */
-  setPrototypeOf: setPrototype,
-} = Object;
+  toObject,
+} = (() => {
+  const createObject = Object;
+  const {
+    assign,
+    create,
+    defineProperty,
+    defineProperties,
+    entries,
+    freeze,
+    fromEntries,
+    getOwnPropertyDescriptor,
+    getOwnPropertyDescriptors,
+    getOwnPropertyNames,
+    getOwnPropertySymbols,
+    getPrototypeOf,
+    hasOwn,
+    isExtensible,
+    isFrozen,
+    isSealed,
+    keys,
+    preventExtensions,
+    seal,
+    setPrototypeOf,
+    values,
+  } = Object;
+  const { [ITERATOR]: arrayIterator } = Array.prototype;
+  const arrayIteratorNext = getPrototypeOf([][ITERATOR]()).next;
+  const splatIterablePrototype = {
+    [ITERATOR]() {
+      return {
+        next: bind(
+          arrayIteratorNext,
+          call(arrayIterator, this.args, []),
+          [],
+        ),
+      };
+    },
+  };
+  const splatIterable = ($) =>
+    create(splatIterablePrototype, { args: { value: $ } });
+
+  return {
+    defineOwnProperty: (O, P, Attributes) =>
+      defineProperty(O, P, Attributes),
+    defineOwnProperties: (O, ...sources) => {
+      for (const source of splatIterable(sources)) {
+        defineProperties(O, source);
+      }
+      return O;
+    },
+    freeze: (O) => freeze(O),
+    getOwnPropertyDescriptor: (O, P) => getOwnPropertyDescriptor(O, P),
+    getOwnPropertyDescriptors: (O) => getOwnPropertyDescriptors(O),
+    getOwnPropertyStrings: (O) => getOwnPropertyNames(O),
+    getOwnPropertySymbols: (O) => getOwnPropertySymbols(O),
+    getPrototype: (O) => getPrototypeOf(O),
+    hasOwnProperty: (O, P) => hasOwn(O, P),
+    isExtensibleObject: (O) => isExtensible(O),
+    isUnfrozenObject: (O) => !isFrozen(O),
+    isUnsealedObject: (O) => !isSealed(O),
+    namedEntries: (O) => entries(O),
+    namedKeys: (O) => keys(O),
+    namedValues: (O) => values(O),
+    objectCreate: (O, Properties) => create(O, Properties),
+    objectFromEntries: (iterable) => fromEntries(iterable),
+    preventExtensions: (O) => preventExtensions(O),
+    seal: (O) => seal(O),
+    setPropertyValues: (target, source, ...sources) =>
+      assign(target, source, ...splatIterable(sources)),
+    setPrototype: (O, proto) => {
+      const obj = toObject(O);
+      if (O === obj) {
+        // The provided value is an object; set its prototype normally.
+        return setPrototypeOf(O, proto);
+      } else {
+        // The provided value is not an object; attempt to set the
+        // prototype on a coerced version with extensions prevented,
+        // then return the provided value.
+        //
+        // This will throw if the given prototype does not match the
+        // existing one on the coerced object.
+        setPrototypeOf(preventExtensions(obj), proto);
+        return O;
+      }
+    },
+    toObject: ($) => {
+      if ($ == null) {
+        // The provided value is nullish; this is an error.
+        throw new TypeError(
+          `Piscēs: Cannot convert ${$} into an object.`,
+        );
+      } else {
+        // The provided value is not nullish; coerce it to an object.
+        return createObject($);
+      }
+    },
+  };
+})();
 
 export const {
   /**
@@ -796,33 +896,11 @@ export const getMethod = (V, P) => {
   }
 };
 
-/**
- * Returns the provided value converted to an object.
- *
- * Existing objects are returned with no modification.
- *
- * ☡ This function throws if its argument is null or undefined.
- */
-export const { toObject } = (() => {
-  const makeObject = Object;
-  return {
-    toObject: ($) => {
-      if ($ == null) {
-        throw new TypeError(
-          `Piscēs: Cannot convert ${$} into an object.`,
-        );
-      } else {
-        return makeObject($);
-      }
-    },
-  };
-})();
-
 /**
  * Returns the property key (symbol or string) corresponding to the
  * provided value.
  */
 export const toPropertyKey = ($) => {
   const key = toPrimitive($, "string");
-  return typeof key == "symbol" ? key : `${key}`;
+  return typeof key === "symbol" ? key : `${key}`;
 };
index 68e3264bb8b70d83353a7d56d2e3788c3833a2b1..d5a60bb68ed60b00f3f31be1c0d1e11b935ab48d 100644 (file)
@@ -20,15 +20,35 @@ import {
 } from "./dev-deps.js";
 import {
   defineOwnProperties,
+  defineOwnProperty,
   deleteOwnProperty,
+  freeze,
   frozenCopy,
   getMethod,
+  getOwnPropertyDescriptor,
+  getOwnPropertyDescriptors,
   getOwnPropertyKeys,
+  getOwnPropertyStrings,
+  getOwnPropertySymbols,
   getPropertyValue,
+  getPrototype,
+  hasOwnProperty,
   hasProperty,
+  isExtensibleObject,
+  isUnfrozenObject,
+  isUnsealedObject,
   LazyLoader,
+  namedEntries,
+  namedKeys,
+  namedValues,
+  objectCreate,
+  objectFromEntries,
+  preventExtensions,
   PropertyDescriptor,
+  seal,
   setPropertyValue,
+  setPropertyValues,
+  setPrototype,
   toObject,
   toPropertyKey,
 } from "./object.js";
@@ -80,6 +100,10 @@ describe("LazyLoader", () => {
     },
   );
 
+  it("[[Call]] throws an error", () => {
+    assertThrows(() => LazyLoader({}));
+  });
+
   it("[[Construct]] creates a new object which inherits from the correct prototype", () => {
     assertStrictEquals(
       Object.getPrototypeOf(new LazyLoader(methodsObject)),
@@ -269,9 +293,25 @@ describe("LazyLoader", () => {
       },
     );
   });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(LazyLoader.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(LazyLoader.name, "LazyLoader");
+    });
+  });
 });
 
 describe("PropertyDescriptor", () => {
+  it("[[Call]] throws an error", () => {
+    assertThrows(() => PropertyDescriptor({}));
+  });
+
   it("[[Construct]] creates a new PropertyDescriptor", () => {
     assertStrictEquals(
       Object.getPrototypeOf(new PropertyDescriptor({})),
@@ -283,6 +323,21 @@ describe("PropertyDescriptor", () => {
     assertThrows(() => new PropertyDescriptor("failure"));
   });
 
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(PropertyDescriptor.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        PropertyDescriptor.name,
+        "PropertyDescriptor",
+      );
+    });
+  });
+
   describe("::complete", () => {
     it("[[Call]] completes a generic descriptor", () => {
       const desc = {};
@@ -316,6 +371,24 @@ describe("PropertyDescriptor", () => {
         set: undefined,
       });
     });
+
+    describe(".length", () => {
+      it("[[Get]] returns the correct length", () => {
+        assertStrictEquals(
+          PropertyDescriptor.prototype.complete.length,
+          0,
+        );
+      });
+    });
+
+    describe(".name", () => {
+      it("[[Get]] returns the correct name", () => {
+        assertStrictEquals(
+          PropertyDescriptor.prototype.complete.name,
+          "complete",
+        );
+      });
+    });
   });
 
   describe("::isAccessorDescriptor", () => {
@@ -351,6 +424,30 @@ describe("PropertyDescriptor", () => {
         true,
       );
     });
+
+    describe("[[GetOwnProperty]].get.length", () => {
+      it("[[Get]] returns the correct length", () => {
+        assertStrictEquals(
+          Object.getOwnPropertyDescriptor(
+            PropertyDescriptor.prototype,
+            "isAccessorDescriptor",
+          ).get.length,
+          0,
+        );
+      });
+    });
+
+    describe("[[GetOwnProperty]].get.name", () => {
+      it("[[Get]] returns the correct name", () => {
+        assertStrictEquals(
+          Object.getOwnPropertyDescriptor(
+            PropertyDescriptor.prototype,
+            "isAccessorDescriptor",
+          ).get.name,
+          "get isAccessorDescriptor",
+        );
+      });
+    });
   });
 
   describe("::isDataDescriptor", () => {
@@ -386,6 +483,30 @@ describe("PropertyDescriptor", () => {
         false,
       );
     });
+
+    describe("[[GetOwnProperty]].get.length", () => {
+      it("[[Get]] returns the correct length", () => {
+        assertStrictEquals(
+          Object.getOwnPropertyDescriptor(
+            PropertyDescriptor.prototype,
+            "isDataDescriptor",
+          ).get.length,
+          0,
+        );
+      });
+    });
+
+    describe("[[GetOwnProperty]].get.name", () => {
+      it("[[Get]] returns the correct name", () => {
+        assertStrictEquals(
+          Object.getOwnPropertyDescriptor(
+            PropertyDescriptor.prototype,
+            "isDataDescriptor",
+          ).get.name,
+          "get isDataDescriptor",
+        );
+      });
+    });
   });
 
   describe("::isFullyPopulated", () => {
@@ -445,6 +566,30 @@ describe("PropertyDescriptor", () => {
         true,
       );
     });
+
+    describe("[[GetOwnProperty]].get.length", () => {
+      it("[[Get]] returns the correct length", () => {
+        assertStrictEquals(
+          Object.getOwnPropertyDescriptor(
+            PropertyDescriptor.prototype,
+            "isFullyPopulated",
+          ).get.length,
+          0,
+        );
+      });
+    });
+
+    describe("[[GetOwnProperty]].get.name", () => {
+      it("[[Get]] returns the correct name", () => {
+        assertStrictEquals(
+          Object.getOwnPropertyDescriptor(
+            PropertyDescriptor.prototype,
+            "isFullyPopulated",
+          ).get.name,
+          "get isFullyPopulated",
+        );
+      });
+    });
   });
 
   describe("::isGenericDescriptor", () => {
@@ -480,6 +625,30 @@ describe("PropertyDescriptor", () => {
         false,
       );
     });
+
+    describe("[[GetOwnProperty]].get.length", () => {
+      it("[[Get]] returns the correct length", () => {
+        assertStrictEquals(
+          Object.getOwnPropertyDescriptor(
+            PropertyDescriptor.prototype,
+            "isGenericDescriptor",
+          ).get.length,
+          0,
+        );
+      });
+    });
+
+    describe("[[GetOwnProperty]].get.name", () => {
+      it("[[Get]] returns the correct name", () => {
+        assertStrictEquals(
+          Object.getOwnPropertyDescriptor(
+            PropertyDescriptor.prototype,
+            "isGenericDescriptor",
+          ).get.name,
+          "get isGenericDescriptor",
+        );
+      });
+    });
   });
 
   describe("~configurable", () => {
@@ -711,6 +880,38 @@ describe("PropertyDescriptor", () => {
   });
 });
 
+describe("defineOwnProperty", () => {
+  it("[[Call]] defines the property", () => {
+    const obj = {};
+    defineOwnProperty(obj, "etaoin", {});
+    assert("etaoin" in obj);
+  });
+
+  it("[[Call]] returns the provided object", () => {
+    const obj = {};
+    assertStrictEquals(defineOwnProperty(obj, "etaoin", {}), obj);
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new defineOwnProperty(obj, "etaoin", {}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(defineOwnProperty.length, 3);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        defineOwnProperty.name,
+        "defineOwnProperty",
+      );
+    });
+  });
+});
+
 describe("defineOwnProperties", () => {
   it("[[Call]] defines properties from the provided objects", () => {
     const obj = {};
@@ -737,6 +938,25 @@ describe("defineOwnProperties", () => {
     const obj = {};
     assertStrictEquals(defineOwnProperties(obj), obj);
   });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new defineOwnProperties({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(defineOwnProperties.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        defineOwnProperties.name,
+        "defineOwnProperties",
+      );
+    });
+  });
 });
 
 describe("deleteOwnProperty", () => {
@@ -761,6 +981,51 @@ describe("deleteOwnProperty", () => {
     const obj = {};
     assertStrictEquals(deleteOwnProperty(obj, ""), obj);
   });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new deleteOwnProperty({}, ""));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(deleteOwnProperty.length, 2);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(deleteOwnProperty.name, "deleteOwnProperty");
+    });
+  });
+});
+
+describe("freeze", () => {
+  it("[[Call]] freezes the object", () => {
+    const obj = {};
+    freeze(obj);
+    assert(Object.isFrozen(obj));
+  });
+
+  it("[[Call]] returns the provided object", () => {
+    const obj = {};
+    assertStrictEquals(freeze(obj), obj);
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new freeze({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(freeze.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(freeze.name, "freeze");
+    });
+  });
 });
 
 describe("frozenCopy", () => {
@@ -877,6 +1142,22 @@ describe("frozenCopy", () => {
       null,
     );
   });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new frozenCopy({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(frozenCopy.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(frozenCopy.name, "frozenCopy");
+    });
+  });
 });
 
 describe("getMethod", () => {
@@ -897,6 +1178,103 @@ describe("getMethod", () => {
   it("[[Call]] throws if the resulting value isn’t callable", () => {
     assertThrows(() => getMethod({ "failure": true }, "failure"));
   });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new getMethod({ method() {} }, "method"));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(getMethod.length, 2);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(getMethod.name, "getMethod");
+    });
+  });
+});
+
+describe("getOwnPropertyDescriptor", () => {
+  it("[[Call]] gets the descriptor", () => {
+    assertEquals(
+      getOwnPropertyDescriptor({ success: true }, "success"),
+      {
+        configurable: true,
+        enumerable: true,
+        value: true,
+        writable: true,
+      },
+    );
+  });
+
+  it("[[Call]] returns undefined for non‐own properties", () => {
+    assertStrictEquals(
+      getOwnPropertyDescriptor({}, "valueOf"),
+      undefined,
+    );
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new getOwnPropertyDescriptor({}, ""));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(getOwnPropertyDescriptor.length, 2);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        getOwnPropertyDescriptor.name,
+        "getOwnPropertyDescriptor",
+      );
+    });
+  });
+});
+
+describe("getOwnPropertyDescriptors", () => {
+  it("[[Call]] gets the descriptors", () => {
+    assertEquals(
+      getOwnPropertyDescriptors({ success: true, etaoin: "shrdlu" }),
+      {
+        success: {
+          configurable: true,
+          enumerable: true,
+          value: true,
+          writable: true,
+        },
+        etaoin: {
+          configurable: true,
+          enumerable: true,
+          value: "shrdlu",
+          writable: true,
+        },
+      },
+    );
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new getOwnPropertyDescriptors({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(getOwnPropertyDescriptors.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        getOwnPropertyDescriptors.name,
+        "getOwnPropertyDescriptors",
+      );
+    });
+  });
 });
 
 describe("getOwnPropertyKeys", () => {
@@ -912,6 +1290,101 @@ describe("getOwnPropertyKeys", () => {
     assertThrows(() => getOwnPropertyKeys(null));
     assertThrows(() => getOwnPropertyKeys(undefined));
   });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new getOwnPropertyKeys({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(getOwnPropertyKeys.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        getOwnPropertyKeys.name,
+        "getOwnPropertyKeys",
+      );
+    });
+  });
+});
+
+describe("getOwnPropertyStrings", () => {
+  it("[[Call]] gets own string keys", () => {
+    assertEquals(getOwnPropertyStrings({ success: true }), [
+      "success",
+    ]);
+  });
+
+  it("[[Call]] works for values coercible to objects", () => {
+    assertEquals(getOwnPropertyStrings("foo"), [
+      "0",
+      "1",
+      "2",
+      "length",
+    ]);
+  });
+
+  it("[[Call]] throws for null and undefined", () => {
+    assertThrows(() => getOwnPropertyStrings(null));
+    assertThrows(() => getOwnPropertyStrings(undefined));
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new getOwnPropertyStrings({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(getOwnPropertyStrings.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        getOwnPropertyStrings.name,
+        "getOwnPropertyStrings",
+      );
+    });
+  });
+});
+
+describe("getOwnPropertySymbols", () => {
+  it("[[Call]] gets own symbol keys", () => {
+    const sym = Symbol();
+    assertEquals(getOwnPropertySymbols({ [sym]: true }), [sym]);
+  });
+
+  it("[[Call]] works for values coercible to objects", () => {
+    assertEquals(getOwnPropertySymbols("foo"), []);
+  });
+
+  it("[[Call]] throws for null and undefined", () => {
+    assertThrows(() => getOwnPropertySymbols(null));
+    assertThrows(() => getOwnPropertySymbols(undefined));
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new getOwnPropertySymbols({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(getOwnPropertySymbols.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        getOwnPropertySymbols.name,
+        "getOwnPropertySymbols",
+      );
+    });
+  });
 });
 
 describe("getPropertyValue", () => {
@@ -933,6 +1406,60 @@ describe("getPropertyValue", () => {
     assertThrows(() => getPropertyValue(null, "valueOf"));
     assertThrows(() => getPropertyValue(undefined, "valueOf"));
   });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new getPropertyValue({}, "valueOf"));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(getPropertyValue.length, 2);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(getPropertyValue.name, "getPropertyValue");
+    });
+  });
+});
+
+describe("getPrototype", () => {
+  it("[[Call]] gets object prototypes", () => {
+    assertStrictEquals(getPrototype({}), Object.prototype);
+    const proto = {};
+    assertStrictEquals(getPrototype(Object.create(proto)), proto);
+  });
+
+  it("[[Call]] gets null prototypes", () => {
+    assertStrictEquals(getPrototype(Object.create(null)), null);
+  });
+
+  it("[[Call]] gets prototypes for coercible primitives", () => {
+    assertStrictEquals(getPrototype(1), Number.prototype);
+    assertStrictEquals(getPrototype(Symbol()), Symbol.prototype);
+  });
+
+  it("[[Call]] throws for null and undefined", () => {
+    assertThrows(() => getPrototype(null));
+    assertThrows(() => getPrototype(undefined));
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new getPrototype({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(getPrototype.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(getPrototype.name, "getPrototype");
+    });
+  });
 });
 
 describe("hasProperty", () => {
@@ -941,9 +1468,11 @@ describe("hasProperty", () => {
       hasProperty({ success: "etaoin" }, "success"),
       true,
     );
+    assertStrictEquals(hasProperty({}, "hasOwnProperty"), true);
   });
 
   it("[[Call]] works for values coercible to objects", () => {
+    assertStrictEquals(hasProperty("", "length"), true);
     assertStrictEquals(hasProperty("", "toString"), true);
   });
 
@@ -951,23 +1480,458 @@ describe("hasProperty", () => {
     assertThrows(() => hasProperty(null, "valueOf"));
     assertThrows(() => hasProperty(undefined, "valueOf"));
   });
-});
 
-describe("setPropertyValue", () => {
-  it("[[Call]] sets the provided property on the provided object", () => {
-    const obj = {};
-    setPropertyValue(obj, "success", true);
-    assertStrictEquals(obj.success, true);
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new hasProperty({}, "valueOf"));
   });
 
-  it("[[Call]] calls setters", () => {
-    const setter = spy((_) => {});
-    const obj = Object.create(null, { success: { set: setter } });
-    setPropertyValue(obj, "success", true);
-    assertSpyCalls(setter, 1);
-    assertSpyCall(setter, 0, {
-      args: [true],
-      self: obj,
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(hasProperty.length, 2);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(hasProperty.name, "hasProperty");
+    });
+  });
+});
+
+describe("hasOwnProperty", () => {
+  it("[[Call]] gets whether an own property exists on the provided object", () => {
+    assertStrictEquals(
+      hasOwnProperty({ success: "etaoin" }, "success"),
+      true,
+    );
+    assertStrictEquals(hasOwnProperty({}, "hasOwnProperty"), false);
+  });
+
+  it("[[Call]] works for values coercible to objects", () => {
+    assertStrictEquals(hasOwnProperty("", "length"), true);
+    assertStrictEquals(hasOwnProperty("", "toString"), false);
+  });
+
+  it("[[Call]] throws for null and undefined", () => {
+    assertThrows(() => hasOwnProperty(null, "valueOf"));
+    assertThrows(() => hasOwnProperty(undefined, "valueOf"));
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new hasOwnProperty({}, "valueOf"));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(hasOwnProperty.length, 2);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(hasOwnProperty.name, "hasOwnProperty");
+    });
+  });
+});
+
+describe("isExtensibleObject", () => {
+  it("[[Call]] returns true for extensible objects", () => {
+    assertStrictEquals(isExtensibleObject({}), true);
+  });
+
+  it("[[Call]] returns false for coercible primitives", () => {
+    assertStrictEquals(isExtensibleObject(1), false);
+    assertStrictEquals(isExtensibleObject(Symbol()), false);
+  });
+
+  it("[[Call]] returns false for non·extensible objects", () => {
+    assertStrictEquals(
+      isExtensibleObject(Object.preventExtensions({})),
+      false,
+    );
+  });
+
+  it("[[Call]] returns false for null and undefined", () => {
+    assertStrictEquals(isExtensibleObject(null), false);
+    assertStrictEquals(isExtensibleObject(undefined), false);
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new isExtensibleObject({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(isExtensibleObject.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        isExtensibleObject.name,
+        "isExtensibleObject",
+      );
+    });
+  });
+});
+
+describe("isUnfrozenObject", () => {
+  it("[[Call]] returns true for unfrozen objects", () => {
+    assertStrictEquals(isUnfrozenObject({}), true);
+  });
+
+  it("[[Call]] returns false for coercible primitives", () => {
+    assertStrictEquals(isUnfrozenObject(1), false);
+    assertStrictEquals(isUnfrozenObject(Symbol()), false);
+  });
+
+  it("[[Call]] returns false for frozen objects", () => {
+    assertStrictEquals(isUnfrozenObject(Object.freeze({})), false);
+  });
+
+  it("[[Call]] returns false for null and undefined", () => {
+    assertStrictEquals(isUnfrozenObject(null), false);
+    assertStrictEquals(isUnfrozenObject(undefined), false);
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new isUnfrozenObject({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(isUnfrozenObject.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(isUnfrozenObject.name, "isUnfrozenObject");
+    });
+  });
+});
+
+describe("isUnsealedObject", () => {
+  it("[[Call]] returns true for unsealed objects", () => {
+    assertStrictEquals(isUnsealedObject({}), true);
+  });
+
+  it("[[Call]] returns false for coercible primitives", () => {
+    assertStrictEquals(isUnsealedObject(1), false);
+    assertStrictEquals(isUnsealedObject(Symbol()), false);
+  });
+
+  it("[[Call]] returns false for sealed objects", () => {
+    assertStrictEquals(isUnsealedObject(Object.seal({})), false);
+  });
+
+  it("[[Call]] returns false for null and undefined", () => {
+    assertStrictEquals(isUnsealedObject(null), false);
+    assertStrictEquals(isUnsealedObject(undefined), false);
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new isUnsealedObject({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(isUnsealedObject.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(isUnsealedObject.name, "isUnsealedObject");
+    });
+  });
+});
+
+describe("namedEntries", () => {
+  it("[[Call]] gets named entries", () => {
+    assertEquals(namedEntries({ success: true }), [["success", true]]);
+  });
+
+  it("[[Call]] works for values coercible to objects", () => {
+    assertEquals(namedEntries("foo"), [
+      ["0", "f"],
+      ["1", "o"],
+      ["2", "o"],
+    ]);
+  });
+
+  it("[[Call]] throws for null and undefined", () => {
+    assertThrows(() => namedEntries(null));
+    assertThrows(() => namedEntries(undefined));
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new namedEntries({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(namedEntries.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(namedEntries.name, "namedEntries");
+    });
+  });
+});
+
+describe("namedKeys", () => {
+  it("[[Call]] gets named keys", () => {
+    assertEquals(namedKeys({ success: true }), ["success"]);
+  });
+
+  it("[[Call]] works for values coercible to objects", () => {
+    assertEquals(namedKeys("foo"), [
+      "0",
+      "1",
+      "2",
+    ]);
+  });
+
+  it("[[Call]] throws for null and undefined", () => {
+    assertThrows(() => namedKeys(null));
+    assertThrows(() => namedKeys(undefined));
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new namedKeys({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(namedKeys.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(namedKeys.name, "namedKeys");
+    });
+  });
+});
+
+describe("namedValues", () => {
+  it("[[Call]] gets named values", () => {
+    assertEquals(namedValues({ success: true }), [true]);
+  });
+
+  it("[[Call]] works for values coercible to objects", () => {
+    assertEquals(namedValues("foo"), [
+      "f",
+      "o",
+      "o",
+    ]);
+  });
+
+  it("[[Call]] throws for null and undefined", () => {
+    assertThrows(() => namedValues(null));
+    assertThrows(() => namedValues(undefined));
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new namedValues({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(namedValues.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(namedValues.name, "namedValues");
+    });
+  });
+});
+
+describe("objectCreate", () => {
+  it("[[Call]] creates an object", () => {
+    const obj = objectCreate(null);
+    assertStrictEquals(Object(obj), obj);
+  });
+
+  it("[[Call]] correctly sets the prototype", () => {
+    const proto = {};
+    assertStrictEquals(
+      Object.getPrototypeOf(objectCreate(proto)),
+      proto,
+    );
+    assertStrictEquals(
+      Object.getPrototypeOf(objectCreate(null)),
+      null,
+    );
+  });
+
+  it("[[Call]] correctly sets own properties", () => {
+    assertEquals(
+      Object.getOwnPropertyDescriptors(
+        objectCreate(null, { success: { value: true } }),
+      ),
+      {
+        success: {
+          configurable: false,
+          enumerable: false,
+          value: true,
+          writable: false,
+        },
+      },
+    );
+  });
+
+  it("[[Call]] throws for coercible primitives", () => {
+    assertThrows(() => objectCreate(1));
+    assertThrows(() => objectCreate(Symbol()));
+  });
+
+  it("[[Call]] throws for undefined", () => {
+    assertThrows(() => objectCreate(undefined));
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new objectCreate({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(objectCreate.length, 2);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(objectCreate.name, "objectCreate");
+    });
+  });
+});
+
+describe("objectFromEntries", () => {
+  it("[[Call]] creates an object", () => {
+    const obj = objectFromEntries([]);
+    assertStrictEquals(Object(obj), obj);
+  });
+
+  it("[[Call]] correctly sets the prototype", () => {
+    assertStrictEquals(
+      Object.getPrototypeOf(objectFromEntries([])),
+      Object.prototype,
+    );
+  });
+
+  it("[[Call]] correctly sets own properties", () => {
+    assertEquals(
+      Object.entries(objectFromEntries([["success", true]])),
+      [["success", true]],
+    );
+  });
+
+  it("[[Call]] throws if the argument is not a nested arraylike", () => {
+    assertThrows(() => objectFromEntries(1));
+    assertThrows(() => objectFromEntries(Symbol()));
+    assertThrows(() => objectFromEntries(null));
+    assertThrows(() => objectFromEntries(undefined));
+    assertThrows(() => objectFromEntries({}));
+    assertThrows(() => objectFromEntries([undefined]));
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new objectFromEntries([]));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(objectFromEntries.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(objectFromEntries.name, "objectFromEntries");
+    });
+  });
+});
+
+describe("preventExtensions", () => {
+  it("[[Call]] prevents extensions on the object", () => {
+    const obj = {};
+    preventExtensions(obj);
+    assert(!Object.isExtensible(obj));
+  });
+
+  it("[[Call]] returns the provided object", () => {
+    const obj = {};
+    assertStrictEquals(preventExtensions(obj), obj);
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new preventExtensions({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(preventExtensions.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(preventExtensions.name, "preventExtensions");
+    });
+  });
+});
+
+describe("seal", () => {
+  it("[[Call]] seals the object", () => {
+    const obj = {};
+    seal(obj);
+    assert(Object.isSealed(obj));
+  });
+
+  it("[[Call]] returns the provided object", () => {
+    const obj = {};
+    assertStrictEquals(seal(obj), obj);
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new seal({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(seal.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(seal.name, "seal");
+    });
+  });
+});
+
+describe("setPropertyValue", () => {
+  it("[[Call]] sets the provided property on the provided object", () => {
+    const obj = {};
+    setPropertyValue(obj, "success", true);
+    assertStrictEquals(obj.success, true);
+  });
+
+  it("[[Call]] calls setters", () => {
+    const setter = spy((_) => {});
+    const obj = Object.create(null, { success: { set: setter } });
+    setPropertyValue(obj, "success", true);
+    assertSpyCalls(setter, 1);
+    assertSpyCall(setter, 0, {
+      args: [true],
+      self: obj,
     });
   });
 
@@ -1005,6 +1969,165 @@ describe("setPropertyValue", () => {
     const obj = {};
     assertStrictEquals(setPropertyValue(obj, "", undefined), obj);
   });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new setPropertyValue({}, "", undefined));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(setPropertyValue.length, 3);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(setPropertyValue.name, "setPropertyValue");
+    });
+  });
+});
+
+describe("setPropertyValues", () => {
+  it("[[Call]] sets the provided properties on the provided object", () => {
+    const obj = {};
+    setPropertyValues(obj, { success: true, all: "good" });
+    assertStrictEquals(obj.success, true);
+    assertStrictEquals(obj.all, "good");
+  });
+
+  it("[[Call]] can take multiple objects", () => {
+    const obj = {};
+    setPropertyValues(
+      obj,
+      { success: false, all: "good" },
+      { success: true },
+    );
+    assertStrictEquals(obj.success, true);
+    assertStrictEquals(obj.all, "good");
+  });
+
+  it("[[Call]] ignores nullish arguments", () => {
+    const obj = {};
+    setPropertyValues(obj, null, undefined, { success: true });
+    assertStrictEquals(obj.success, true);
+  });
+
+  it("[[Call]] calls setters", () => {
+    const setter = spy((_) => {});
+    const obj = Object.create(null, { success: { set: setter } });
+    setPropertyValues(obj, { success: true });
+    assertSpyCalls(setter, 1);
+    assertSpyCall(setter, 0, {
+      args: [true],
+      self: obj,
+    });
+  });
+
+  it("[[Call]] calls setters multiple times if property appears more than once", () => {
+    const setter = spy((_) => {});
+    const obj = Object.create(null, { success: { set: setter } });
+    setPropertyValues(obj, { success: false }, { success: true });
+    assertSpyCalls(setter, 2);
+    assertSpyCall(setter, 0, {
+      args: [false],
+      self: obj,
+    });
+    assertSpyCall(setter, 1, {
+      args: [true],
+      self: obj,
+    });
+  });
+
+  it("[[Call]] walks the prototype chain", () => {
+    const setter = spy((_) => {});
+    const obj = Object.create(
+      Object.create(null, { success: { set: setter } }),
+    );
+    setPropertyValues(obj, { success: true });
+    assertSpyCalls(setter, 1);
+    assertSpyCall(setter, 0, {
+      args: [true],
+      self: obj,
+    });
+  });
+
+  it("[[Call]] throws if the property can’t be set", () => {
+    const obj = Object.freeze({ failure: undefined });
+    assertThrows(() => setPropertyValues(obj, { failure: true }));
+  });
+
+  it("[[Call]] returns the provided object", () => {
+    const obj = {};
+    assertStrictEquals(setPropertyValues(obj, { "": undefined }), obj);
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new setPropertyValues(obj, { "": undefined }));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(setPropertyValues.length, 2);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(setPropertyValues.name, "setPropertyValues");
+    });
+  });
+});
+
+describe("setPrototype", () => {
+  it("[[Call]] sets object prototypes", () => {
+    const obj = {};
+    const proto = {};
+    setPrototype(obj, proto);
+    assertStrictEquals(Object.getPrototypeOf(obj), proto);
+  });
+
+  it("[[Call]] sets null prototypes", () => {
+    const obj = {};
+    setPrototype(obj, null);
+    assertStrictEquals(Object.getPrototypeOf(obj), null);
+  });
+
+  it("[[Call]] can set coercible primitives to their same prototype", () => {
+    setPrototype(1, Number.prototype);
+    setPrototype(Symbol(), Symbol.prototype);
+  });
+
+  it("[[Call]] throws when setting coercible primitives to a different prototype", () => {
+    assertThrows(() => setPrototype(1, Object.prototype));
+    assertThrows(() => setPrototype(Symbol(), Object.prototype));
+  });
+
+  it("[[Call]] throws for null and undefined", () => {
+    assertThrows(() => setPrototype(null, Object.prototype));
+    assertThrows(() => setPrototype(undefined, Object.prototype));
+  });
+
+  it("[[Call]] returns the provided value", () => {
+    const obj = {};
+    assertStrictEquals(setPrototype(obj, null), obj);
+    assertStrictEquals(setPrototype(1, Number.prototype), 1);
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new setPrototype({}, null));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(setPrototype.length, 2);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(setPrototype.name, "setPrototype");
+    });
+  });
 });
 
 describe("toObject", () => {
@@ -1023,6 +2146,22 @@ describe("toObject", () => {
     assertStrictEquals(typeof toObject(sym), "object");
     assertStrictEquals(toObject(sym).valueOf(), sym);
   });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new toObject({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(toObject.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(toObject.name, "toObject");
+    });
+  });
 });
 
 describe("toPropertyKey", () => {
@@ -1048,4 +2187,20 @@ describe("toPropertyKey", () => {
       "success",
     );
   });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new toPropertyKey(""));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(toPropertyKey.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(toPropertyKey.name, "toPropertyKey");
+    });
+  });
 });
This page took 0.061133 seconds and 4 git commands to generate.