+}
+
+/**
+ * A property descriptor object.
+ *
+ * Actually constructing a property descriptor object using this class
+ * is only necessary if you need strict guarantees about the types of
+ * its properties; the resulting object is proxied to ensure the types
+ * match what one would expect from composing FromPropertyDescriptor
+ * and ToPropertyDescriptor in the Ecmascript specification.
+ *
+ * Otherwise, the instance properties and methods are generic.
+ */
+export const { PropertyDescriptor } = (() => {
+ class PropertyDescriptor extends null {
+ /**
+ * Constructs a new property descriptor object from the provided
+ * object.
+ *
+ * The resulting object is proxied to enforce types (for example,
+ * its `.enumerable` property, if defined, will always be a
+ * boolean).
+ */
+ constructor(O) {
+ if (type(O) !== "object") {
+ // The provided value is not an object.
+ throw new TypeError(
+ `Piscēs: Cannot convert primitive to property descriptor: ${O}.`,
+ );
+ } else {
+ // The provided value is an object.
+ const desc = objectCreate(propertyDescriptorPrototype);
+ if ("enumerable" in O) {
+ // An enumerable property is specified.
+ desc.enumerable = !!O.enumerable;
+ } else {
+ // An enumerable property is not specified.
+ /* do nothing */
+ }
+ if ("configurable" in O) {
+ // A configurable property is specified.
+ desc.configurable = !!O.configurable;
+ } else {
+ // A configurable property is not specified.
+ /* do nothing */
+ }
+ if ("value" in O) {
+ // A value property is specified.
+ desc.value = O.value;
+ } else {
+ // A value property is not specified.
+ /* do nothing */
+ }
+ if ("writable" in O) {
+ // A writable property is specified.
+ desc.writable = !!O.writable;
+ } else {
+ // A writable property is not specified.
+ /* do nothing */
+ }
+ if ("get" in O) {
+ // A get property is specified.
+ const getter = O.get;
+ if (getter !== undefined && typeof getter !== "function") {
+ // The getter is not callable.
+ throw new TypeError("Piscēs: Getters must be callable.");
+ } else {
+ // The getter is callable.
+ desc.get = getter;
+ }
+ } else {
+ // A get property is not specified.
+ /* do nothing */
+ }
+ if ("set" in O) {
+ // A set property is specified.
+ const setter = O.set;
+ if (setter !== undefined && typeof setter !== "function") {
+ // The setter is not callable.
+ throw new TypeError("Piscēs: Setters must be callable.");
+ } else {
+ // The setter is callable.
+ desc.set = setter;
+ }
+ } else {
+ // A set property is not specified.
+ /* do nothing */
+ }
+ if (
+ ("get" in desc || "set" in desc) &&
+ ("value" in desc || "writable" in desc)
+ ) {
+ // Both accessor and data attributes have been defined.
+ throw new TypeError(
+ "Piscēs: Property descriptors cannot specify both accessor and data attributes.",
+ );
+ } else {
+ // The property descriptor is valid.
+ return new Proxy(desc, propertyDescriptorProxyHandler);
+ }
+ }
+ }
+
+ /**
+ * Completes this property descriptor by setting missing values to
+ * their defaults.
+ *
+ * This method modifies this object and returns undefined.
+ */
+ complete() {
+ if (this !== undefined && !("get" in this || "set" in this)) {
+ // This is a generic or data descriptor.
+ if (!("value" in this)) {
+ // `value` is not defined on this.
+ this.value = undefined;
+ } else {
+ // `value` is already defined on this.
+ /* do nothing */
+ }
+ if (!("writable" in this)) {
+ // `writable` is not defined on this.
+ this.writable = false;
+ } else {
+ // `writable` is already defined on this.
+ /* do nothing */
+ }
+ } else {
+ // This is not a generic or data descriptor.
+ if (!("get" in this)) {
+ // `get` is not defined on this.
+ this.get = undefined;
+ } else {
+ // `get` is already defined on this.
+ /* do nothing */
+ }
+ if (!("set" in this)) {
+ // `set` is not defined on this.
+ this.set = undefined;
+ } else {
+ // `set` is already defined on this.
+ /* do nothing */
+ }
+ }
+ if (!("enumerable" in this)) {
+ // `enumerable` is not defined on this.
+ this.enumerable = false;
+ } else {
+ // `enumerable` is already defined on this.
+ /* do nothing */
+ }
+ if (!("configurable" in this)) {
+ // `configurable` is not defined on this.
+ this.configurable = false;
+ } else {
+ // `configurable` is already defined on this.
+ /* do nothing */
+ }
+ }
+
+ /** Gets whether this is an accessor descrtiptor. */
+ get isAccessorDescriptor() {
+ return this !== undefined && ("get" in this || "set" in this);
+ }
+
+ /** Gets whether this is a data descrtiptor. */
+ get isDataDescriptor() {
+ return this !== undefined &&
+ ("value" in this || "writable" in this);
+ }
+
+ /** Gets whether this is a fully‐populated property descriptor. */
+ get isFullyPopulated() {
+ return this !== undefined &&
+ ("value" in this && "writable" in this ||
+ "get" in this && "set" in this) &&
+ "enumerable" in this && "configurable" in this;
+ }
+
+ /**
+ * Gets whether this is a generic (not accessor or data)
+ * descrtiptor.
+ */
+ get isGenericDescriptor() {
+ return this !== undefined &&
+ !("get" in this || "set" in this || "value" in this ||
+ "writable" in this);
+ }
+ }
+
+ const coercePropertyDescriptorValue = (P, V) => {
+ switch (P) {
+ case "configurable":
+ case "enumerable":
+ case "writable":
+ return !!V;
+ case "value":
+ return V;
+ case "get":
+ if (V !== undefined && typeof V !== "function") {
+ throw new TypeError(
+ "Piscēs: Getters must be callable.",
+ );
+ } else {
+ return V;
+ }
+ case "set":
+ if (V !== undefined && typeof V !== "function") {
+ throw new TypeError(
+ "Piscēs: Setters must be callable.",
+ );
+ } else {
+ return V;
+ }
+ default:
+ return V;
+ }
+ };
+
+ const {
+ prototype: propertyDescriptorPrototype,
+ } = PropertyDescriptor;
+
+ const propertyDescriptorProxyHandler = Object.assign(
+ Object.create(null),
+ {
+ defineProperty(O, P, Desc) {
+ if (
+ P === "configurable" || P === "enumerable" ||
+ P === "writable" || P === "value" ||
+ P === "get" || P === "set"
+ ) {
+ // P is a property descriptor attribute.
+ const desc = new PropertyDescriptor(Desc);
+ if ("get" in desc || "set" in desc) {
+ // Desc is an accessor property descriptor.
+ throw new TypeError(
+ "Piscēs: Property descriptor attributes must be data properties.",
+ );
+ } else if ("value" in desc || !(P in O)) {
+ // Desc has a value or P does not already exist on O.
+ desc.value = coercePropertyDescriptorValue(P, desc.value);
+ } else {
+ // Desc is not an accessor property descriptor and has no
+ // value.
+ /* do nothing */
+ }
+ const isAccessorDescriptor = "get" === P || "set" === P ||
+ "get" in O || "set" in O;
+ const isDataDescriptor = "value" === P || "writable" === P ||
+ "value" in O || "writable" in O;
+ if (isAccessorDescriptor && isDataDescriptor) {
+ // Both accessor and data attributes will be present on O
+ // after defining P.
+ throw new TypeError(
+ "Piscēs: Property descriptors cannot specify both accessor and data attributes.",
+ );
+ } else {
+ // P can be safely defined on O.
+ return defineOwnProperty(O, P, desc);
+ }
+ } else {
+ // P is not a property descriptor attribute.
+ return defineOwnProperty(O, P, Desc);
+ }
+ },
+ set(O, P, V, Receiver) {
+ if (
+ P === "configurable" || P === "enumerable" ||
+ P === "writable" || P === "value" ||
+ P === "get" || P === "set"
+ ) {
+ // P is a property descriptor attribute.
+ const newValue = coercePropertyDescriptorValue(P, V);
+ const isAccessorDescriptor = "get" === P || "set" === P ||
+ "get" in O || "set" in O;
+ const isDataDescriptor = "value" === P || "writable" === P ||
+ "value" in O || "writable" in O;
+ if (isAccessorDescriptor && isDataDescriptor) {
+ // Both accessor and data attributes will be present on O
+ // after defining P.
+ throw new TypeError(
+ "Piscēs: Property descriptors cannot specify both accessor and data attributes.",
+ );
+ } else {
+ // P can be safely defined on O.
+ //
+ // ☡ Receiver will be the *proxied* object, so passing it
+ // through to setPropertyValue here would produce an
+ // infinite loop.
+ //
+ // ☡ This has implications on objects with a proxied
+ // PropertyDescriptor in their prototype.
+ return setPropertyValue(O, P, newValue, O);
+ }
+ } else {
+ return setPropertyValue(O, P, V, Receiver);
+ }
+ },
+ setPrototypeOf(O, V) {
+ if (V !== propertyDescriptorPrototype) {
+ // V is not the property descriptor prototype.
+ return false;
+ } else {
+ // V is the property descriptor prototype.
+ return setPrototype(O, V);
+ }
+ },
+ },
+ );
+
+ return { PropertyDescriptor };
+})();
+
+export const {
+ /**
+ * Defines own properties on the provided object using the
+ * descriptors on the enumerable own properties of the provided
+ * additional objects.
+ *
+ * ※ This differs from `Object.defineProperties` in that it can take
+ * 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`.
+ */
+ freeze,
+
+ /**
+ * Returns the property descriptor for the own property with the
+ * provided property key on the provided object, or null if none
+ * exists.
+ *
+ * ※ This is 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`.
+ */
+ getOwnPropertyDescriptors,
+
+ /**
+ * Returns an array of string‐valued own property keys on the
+ * provided object.
+ *
+ * ☡ This includes both enumerable and non·enumerable properties.
+ *
+ * ※ This is an alias for `Object.getOwnPropertyNames`.
+ */
+ getOwnPropertyNames: getOwnPropertyStrings,