})();
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
* 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,
* 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,
* 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,
*
* ☡ 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
*
* ☡ 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,
* 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,
* 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 {
/**
}
};
-/**
- * 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}`;
};
} 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";
},
);
+ 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)),
},
);
});
+
+ 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({})),
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 = {};
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", () => {
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", () => {
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", () => {
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", () => {
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", () => {
});
});
+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 = {};
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", () => {
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", () => {
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", () => {
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", () => {
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", () => {
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", () => {
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);
});
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,
});
});
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", () => {
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", () => {
"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");
+ });
+ });
});