+ 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", () => {
+ it("[[Call]] gets own (but not inherited) property keys", () => {
+ assertEquals(getOwnPropertyKeys({ success: true }), ["success"]);
+ });
+
+ it("[[Call]] works for values coercible to objects", () => {
+ assertEquals(getOwnPropertyKeys("foo"), ["0", "1", "2", "length"]);
+ });
+
+ it("[[Call]] throws for null and undefined", () => {
+ 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", () => {
+ it("[[Call]] gets property values on the provided object", () => {
+ assertStrictEquals(
+ getPropertyValue({ success: true }, "success"),
+ true,
+ );
+ });
+
+ it("[[Call]] works for values coercible to objects", () => {
+ assertStrictEquals(
+ getPropertyValue("", "toString"),
+ String.prototype.toString,
+ );
+ });
+
+ it("[[Call]] throws for null and undefined", () => {
+ 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", () => {
+ it("[[Call]] gets whether a property exists on the provided object", () => {
+ assertStrictEquals(
+ 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);
+ });
+
+ it("[[Call]] throws for null and undefined", () => {
+ assertThrows(() => hasProperty(null, "valueOf"));
+ assertThrows(() => hasProperty(undefined, "valueOf"));
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new hasProperty({}, "valueOf"));
+ });
+
+ 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("isArraylikeObject", () => {
+ it("[[Call]] returns false for primitives", () => {
+ assertStrictEquals(isArraylikeObject("failure"), false);
+ });
+
+ it("[[Call]] returns false if length throws", () => {
+ assertStrictEquals(
+ isArraylikeObject({
+ get length() {
+ throw void {};
+ },
+ }),
+ false,
+ );
+ });
+
+ it("[[Call]] returns false if length is not a number and cannot be converted to one", () => {
+ assertStrictEquals(isArraylikeObject({ length: 1n }), false);
+ });
+
+ it("[[Call]] returns true if length is convertable to a number", () => {
+ assertStrictEquals(isArraylikeObject({ length: -0 }), true);
+ assertStrictEquals(isArraylikeObject({ length: 1 }), true);
+ assertStrictEquals(isArraylikeObject({ length: -1.25 }), true);
+ assertStrictEquals(
+ isArraylikeObject({ length: 9007199254740992 }),
+ true,
+ );
+ assertStrictEquals(isArraylikeObject({ length: Infinity }), true);
+ assertStrictEquals(isArraylikeObject({ length: "success" }), true);
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new isArraylikeObject({}));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(isArraylikeObject.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ isArraylikeObject.name,
+ "isArraylikeObject",
+ );
+ });
+ });
+});
+
+describe("isConcatSpreadableObject", () => {
+ it("[[Call]] returns false for primitives", () => {
+ assertStrictEquals(isConcatSpreadableObject("failure"), false);
+ });
+
+ it("[[Call]] returns false if [Symbol.isConcatSpreadable] is null or false", () => {
+ assertStrictEquals(
+ isConcatSpreadableObject(
+ Object.assign([], { [Symbol.isConcatSpreadable]: null }),
+ ),
+ false,
+ );
+ assertStrictEquals(
+ isConcatSpreadableObject(
+ Object.assign([], { [Symbol.isConcatSpreadable]: false }),
+ ),
+ false,
+ );
+ });
+
+ it("[[Call]] returns true if [Symbol.isConcatSpreadable] is undefined and the object is an array", () => {
+ assertStrictEquals(
+ isConcatSpreadableObject(
+ Object.assign([], { [Symbol.isConcatSpreadable]: undefined }),
+ ),
+ true,
+ );
+ });
+
+ it("[[Call]] returns true if [Symbol.isConcatSpreadable] is true", () => {
+ assertStrictEquals(
+ isConcatSpreadableObject({ [Symbol.isConcatSpreadable]: true }),
+ true,
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new isConcatSpreadableObject({}));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(isConcatSpreadableObject.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ isConcatSpreadableObject.name,
+ "isConcatSpreadableObject",
+ );
+ });
+ });
+});
+
+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("lengthOfArraylike", () => {
+ it("[[Call]] returns the length", () => {
+ assertStrictEquals(
+ lengthOfArraylike({ length: 9007199254740991 }),
+ 9007199254740991,
+ );
+ });
+
+ it("[[Call]] returns a non·nan result", () => {
+ assertStrictEquals(lengthOfArraylike({ length: NaN }), 0);
+ assertStrictEquals(lengthOfArraylike({ length: "failure" }), 0);
+ });
+
+ it("[[Call]] returns an integral result", () => {
+ assertStrictEquals(lengthOfArraylike({ length: 0.25 }), 0);
+ assertStrictEquals(lengthOfArraylike({ length: 1.1 }), 1);
+ });
+
+ it("[[Call]] returns a result greater than or equal to zero", () => {
+ assertStrictEquals(lengthOfArraylike({ length: -0 }), 0);
+ assertStrictEquals(lengthOfArraylike({ length: -1 }), 0);
+ assertStrictEquals(lengthOfArraylike({ length: -Infinity }), 0);
+ });
+
+ it("[[Call]] returns a result less than 2 ** 53", () => {
+ assertStrictEquals(
+ lengthOfArraylike({ length: 9007199254740992 }),
+ 9007199254740991,
+ );
+ assertStrictEquals(
+ lengthOfArraylike({ length: Infinity }),
+ 9007199254740991,
+ );
+ });
+
+ it("[[Call]] does not require an object argument", () => {
+ assertStrictEquals(lengthOfArraylike("string"), 6);
+ assertStrictEquals(lengthOfArraylike(Symbol()), 0);
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new lengthOfArraylike(""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(lengthOfArraylike.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(lengthOfArraylike.name, "lengthOfArraylike");
+ });
+ });
+});
+
+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"],
+ ]);