// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
-import { bind, call, createArrowFunction } from "./function.js";
import {
IS_CONCAT_SPREADABLE,
- ITERATOR,
+ isAccessorDescriptor,
SPECIES,
toFunctionName,
toLength,
UNDEFINED,
} from "./value.js";
+const { isArray } = Array;
+const object = Object;
+const {
+ assign,
+ create,
+ defineProperty,
+ defineProperties,
+ entries,
+ freeze: objectFreeze,
+ fromEntries,
+ getOwnPropertyDescriptor: objectGetOwnPropertyDescriptor,
+ getOwnPropertyNames,
+ getOwnPropertySymbols: objectGetOwnPropertySymbols,
+ getPrototypeOf,
+ hasOwn,
+ isExtensible,
+ isFrozen,
+ isSealed,
+ keys,
+ preventExtensions: objectPreventExtensions,
+ seal: objectSeal,
+ setPrototypeOf,
+ values,
+} = Object;
+const {
+ apply: call,
+ deleteProperty,
+ get,
+ getOwnPropertyDescriptor: reflectGetOwnPropertyDescriptor,
+ has,
+ ownKeys,
+ set,
+} = Reflect;
+
/**
* An object whose properties are lazy‐loaded from the methods on the
* own properties of the provided object.
} else {
// The provided value is an object; process it and build the
// result.
- const result = objectCreate(getPrototype(loadMethods));
- const methodKeys = getOwnPropertyKeys(loadMethods);
+ const result = create(getPrototypeOf(loadMethods));
+ const methodKeys = ownKeys(loadMethods);
for (let index = 0; index < methodKeys.length; ++index) {
// Iterate over the property keys of the provided object and
// define getters and setters appropriately on the result.
const methodKey = methodKeys[index];
const { configurable, enumerable, writable } =
getOwnPropertyDescriptor(loadMethods, methodKey);
- defineOwnProperty(result, methodKey, {
- configurable: true,
- enumerable,
- get: defineOwnProperty(
- () => {
- const value = call(loadMethods[methodKey], result, []);
- defineOwnProperty(result, methodKey, {
- configurable,
- enumerable,
- value,
- writable,
- });
- return value;
- },
- "name",
- { value: toFunctionName(methodKey, "get") },
- ),
- set: writable
- ? defineOwnProperty(
- ($) =>
- defineOwnProperty(result, methodKey, {
- configurable,
- enumerable,
- value: $,
- writable,
- }),
+ defineProperty(
+ result,
+ methodKey,
+ assign(create(null), {
+ configurable: true,
+ enumerable,
+ get: defineProperty(
+ () => {
+ const value = call(loadMethods[methodKey], result, []);
+ defineProperty(
+ result,
+ methodKey,
+ assign(create(null), {
+ configurable,
+ enumerable,
+ value,
+ writable,
+ }),
+ );
+ return value;
+ },
"name",
- { value: toFunctionName(methodKey, "set") },
- )
- : void {},
- });
+ assign(create(null), {
+ value: toFunctionName(methodKey, "get"),
+ }),
+ ),
+ set: writable
+ ? defineProperty(
+ ($) =>
+ defineProperty(
+ result,
+ methodKey,
+ assign(create(null), {
+ configurable,
+ enumerable,
+ value: $,
+ writable,
+ }),
+ ),
+ "name",
+ assign(create(null), {
+ value: toFunctionName(methodKey, "set"),
+ }),
+ )
+ : UNDEFINED,
+ }),
+ );
}
return result;
}
}
}
+/**
+ * Defines an own enumerable data property on the provided object with
+ * the provided property key and value.
+ */
+export const defineOwnDataProperty = (O, P, V) =>
+ defineProperty(
+ O,
+ P,
+ assign(create(null), {
+ configurable: true,
+ enumerable: true,
+ value: V,
+ writable: true,
+ }),
+ );
+
+/**
+ * Defines an own nonenumerable data property on the provided object
+ * with the provided property key and value.
+ */
+export const defineOwnNonenumerableDataProperty = (O, P, V) =>
+ defineProperty(
+ O,
+ P,
+ assign(create(null), {
+ configurable: true,
+ enumerable: false,
+ value: V,
+ writable: true,
+ }),
+ );
+
/**
* 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`.
*/
-export const defineOwnProperty = createArrowFunction(
- Object.defineProperty,
- { name: "defineOwnProperty" },
-);
-
-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,
-
- /**
- * Returns a new frozen shallow copy of the enumerable own properties
- * of the provided object, according to the following rules :—
- *
- * - For data properties, create a nonconfigurable, nonwritable
- * property with the same value.
- *
- * - For accessor properties, create a nonconfigurable accessor
- * property with the same getter *and* setter.
- *
- * The prototype for the resulting object will be taken from the
- * `.prototype` property of the provided constructor, or the
- * `.prototype` of the `.constructor` of the provided object if the
- * provided constructor is undefined. If the used constructor has a
- * nonnullish `.[Symbol.species]`, that will be used instead. If the
- * used constructor or species is nullish or does not have a
- * `.prototype` property, the prototype is set to null.
- *
- * ※ The prototype of the provided object itself is ignored.
- */
- frozenCopy,
-
- /**
- * Returns the property descriptor record for the own property with
- * the provided property key on the provided object, or null if none
- * exists.
- *
- * ※ This is effectively an alias for
- * `Object.getOwnPropertyDescriptor`, but the return value is a
- * proxied object with null prototype.
- */
- getOwnPropertyDescriptor,
-
- /**
- * Returns the property descriptors for the own properties on the
- * provided object.
- *
- * ※ This is effectively an alias for
- * `Object.getOwnPropertyDescriptors`, but the values on the
- * resulting object are proxied objects with null prototypes.
- */
- getOwnPropertyDescriptors,
-
- /**
- * Returns whether the provided object is frozen.
- *
- * ※ This function returns false for nonobjects.
- *
- * ※ This is effectively an alias for `!Object.isFrozen`.
- */
- isUnfrozenObject,
-
- /**
- * Returns whether the provided object is sealed.
- *
- * ※ This function returns false for nonobjects.
- *
- * ※ This is effectively an alias for `!Object.isSealed`.
- */
- isUnsealedObject,
-
- /**
- * Sets the prototype of the provided object to the provided value
- * and returns the object.
- *
- * ※ This is effectively an alias for `Object.setPrototypeOf`.
- */
- setPrototype,
+export const defineOwnProperty = (O, P, Desc) =>
+ defineProperty(O, P, Desc);
- /**
- * 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.
- */
- toObject,
-} = (() => {
- const createObject = Object;
- const {
- create,
- defineProperties,
- getOwnPropertyDescriptor: objectGetOwnPropertyDescriptor,
- getPrototypeOf,
- isFrozen,
- isSealed,
- setPrototypeOf,
- } = Object;
- const {
- next: generatorIteratorNext,
- } = getPrototypeOf(function* () {}.prototype);
- const propertyDescriptorEntryIterablePrototype = {
- [ITERATOR]() {
- return {
- next: bind(generatorIteratorNext, this.generator(), []),
- };
- },
- };
- const propertyDescriptorEntryIterable = ($) =>
- create(propertyDescriptorEntryIterablePrototype, {
- generator: { value: $ },
- });
-
- return {
- defineOwnProperties: (O, ...sources) => {
- const { length } = sources;
- for (let index = 0; index < length; ++index) {
- defineProperties(O, sources[index]);
- }
- return O;
- },
- frozenCopy: (O, constructor = O?.constructor) => {
- if (O == null) {
- // O is null or undefined.
- throw new TypeError(
- "Piscēs: Cannot copy properties of null or undefined.",
- );
- } else {
- // O is not null or undefined.
- //
- // (If not provided, the constructor will be the value of
- // getting the `.constructor` property of O.)
- const species = constructor?.[SPECIES] ?? constructor;
- return preventExtensions(
- objectCreate(
- species == null || !("prototype" in species)
- ? null
- : species.prototype,
- objectFromEntries(
- propertyDescriptorEntryIterable(function* () {
- const ownPropertyKeys = getOwnPropertyKeys(O);
- for (
- let i = 0;
- i < ownPropertyKeys.length;
- ++i
- ) {
- const P = ownPropertyKeys[i];
- const Desc = getOwnPropertyDescriptor(O, P);
- if (Desc.enumerable) {
- // P is an enumerable property.
- yield [
- P,
- "get" in Desc || "set" in Desc
- ? {
- configurable: false,
- enumerable: true,
- get: Desc.get,
- set: Desc.set,
- }
- : {
- configurable: false,
- enumerable: true,
- value: Desc.value,
- writable: false,
- },
- ];
- } else {
- // P is not an enumerable property.
- /* do nothing */
- }
- }
- }),
- ),
- ),
- );
- }
- },
- getOwnPropertyDescriptor: (O, P) => {
- const desc = objectGetOwnPropertyDescriptor(O, P);
- return desc === UNDEFINED
- ? UNDEFINED
- : toPropertyDescriptor(desc);
- },
- getOwnPropertyDescriptors: (O) => {
- const obj = toObject(O);
- const ownKeys = getOwnPropertyKeys(obj);
- const descriptors = {};
- for (let k = 0; k < ownKeys.length; ++k) {
- const key = ownKeys[k];
- defineOwnProperty(descriptors, key, {
- configurable: true,
- enumerable: true,
- value: getOwnPropertyDescriptor(O, key),
- writable: true,
- });
- }
- return descriptors;
- },
- isUnfrozenObject: (O) => !isFrozen(O),
- isUnsealedObject: (O) => !isSealed(O),
- 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 {
- /**
- * Removes the provided property key from the provided object and
- * returns the object.
- *
- * ※ This function differs from `Reflect.deleteProperty` and the
- * `delete` operator in that it throws if the deletion is
- * unsuccessful.
- *
- * ☡ This function throws if the first argument is not an object.
- */
- deleteOwnProperty,
-
- /**
- * Returns an array of property keys on the provided object.
- *
- * ※ This is effectively an alias for `Reflect.ownKeys`, except that
- * it does not require that the argument be an object.
- */
- getOwnPropertyKeys,
-
- /**
- * Returns the value of the provided property key on the provided
- * object.
- *
- * ※ This is effectively an alias for `Reflect.get`, except that it
- * does not require that the argument be an object.
- */
- getPropertyValue,
-
- /**
- * Returns whether the provided property key exists on the provided
- * object.
- *
- * ※ This is effectively an alias for `Reflect.has`, except that it
- * does not require that the argument be an object.
- *
- * ※ This includes properties present on the prototype chain.
- */
- hasProperty,
+/**
+ * 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.
+ */
+export const defineOwnProperties = (O, ...sources) => {
+ const { length } = sources;
+ for (let k = 0; k < length; ++k) {
+ defineProperties(O, sources[k]);
+ }
+ return O;
+};
- /**
- * Sets the provided property key to the provided value on the
- * provided object and returns the object.
- *
- * ※ This function differs from `Reflect.set` in that it throws if
- * the setting is unsuccessful.
- *
- * ☡ This function throws if the first argument is not an object.
- */
- setPropertyValue,
-} = (() => {
- const { deleteProperty, get, has, ownKeys, set } = Reflect;
-
- return {
- deleteOwnProperty: (O, P) => {
- if (type(O) !== "object") {
- throw new TypeError(
- `Piscēs: Tried to set property but provided value was not an object: ${V}`,
- );
- } else if (!deleteProperty(O, P)) {
- throw new TypeError(
- `Piscēs: Tried to delete property from object but [[Delete]] returned false: ${P}`,
- );
- } else {
- return O;
- }
- },
- getOwnPropertyKeys: (O) => ownKeys(toObject(O)),
- getPropertyValue: (O, P, Receiver = O) =>
- get(toObject(O), P, Receiver),
- hasProperty: (O, P) => has(toObject(O), P),
- setPropertyValue: (O, P, V, Receiver = O) => {
- if (type(O) !== "object") {
- throw new TypeError(
- `Piscēs: Tried to set property but provided value was not an object: ${V}`,
- );
- } else if (!set(O, P, V, Receiver)) {
- throw new TypeError(
- `Piscēs: Tried to set property on object but [[Set]] returned false: ${P}`,
- );
- } else {
- return O;
- }
- },
- };
-})();
+/**
+ * Removes the provided property key from the provided object and
+ * returns the object.
+ *
+ * ※ This function differs from `Reflect.deleteProperty` and the
+ * `delete` operator in that it throws if the deletion is
+ * unsuccessful.
+ *
+ * ☡ This function throws if the first argument is not an object.
+ */
+export const deleteOwnProperty = (O, P) => {
+ if (type(O) !== "object") {
+ throw new TypeError(
+ `Piscēs: Tried to set property but provided value was not an object: ${V}`,
+ );
+ } else if (!deleteProperty(O, P)) {
+ throw new TypeError(
+ `Piscēs: Tried to delete property from object but [[Delete]] returned false: ${P}`,
+ );
+ } else {
+ return O;
+ }
+};
/**
* Marks the provided object as non·extensible and marks all its
*
* ※ This is effectively an alias for `Object.freeze`.
*/
-export const freeze = createArrowFunction(Object.freeze);
+export const freeze = (O) => objectFreeze(O);
+
+/**
+ * Returns a new frozen shallow copy of the enumerable own properties
+ * of the provided object, according to the following rules :—
+ *
+ * - For data properties, create a nonconfigurable, nonwritable
+ * property with the same value.
+ *
+ * - For accessor properties, create a nonconfigurable accessor
+ * property with the same getter *and* setter.
+ *
+ * The prototype for the resulting object will be taken from the
+ * `.prototype` property of the provided constructor, or the
+ * `.prototype` of the `.constructor` of the provided object if the
+ * provided constructor is undefined. If the used constructor has a
+ * nonnullish `.[Symbol.species]`, that will be used instead. If the
+ * used constructor or species is nullish or does not have a
+ * `.prototype` property, the prototype is set to null.
+ *
+ * ※ The prototype of the provided object itself is ignored.
+ */
+export const frozenCopy = (O, constructor = O?.constructor) => {
+ if (O == null) {
+ // O is null or undefined.
+ throw new TypeError(
+ "Piscēs: Cannot copy properties of null or undefined.",
+ );
+ } else {
+ // O is not null or undefined.
+ //
+ // (If not provided, the constructor will be the value of getting
+ // the `.constructor` property of O.)
+ const species = constructor?.[SPECIES] ?? constructor;
+ const copy = create(
+ species == null || !("prototype" in species)
+ ? null
+ : species.prototype,
+ );
+ const keys = ownKeys(O);
+ for (let k = 0; k < keys.length; ++k) {
+ const P = keys[k];
+ const Desc = getOwnPropertyDescriptor(O, P);
+ if (Desc.enumerable) {
+ // P is an enumerable property.
+ defineProperty(
+ copy,
+ P,
+ assign(
+ create(null),
+ isAccessorDescriptor(Desc)
+ ? {
+ configurable: false,
+ enumerable: true,
+ get: Desc.get,
+ set: Desc.set,
+ }
+ : {
+ configurable: false,
+ enumerable: true,
+ value: Desc.value,
+ writable: false,
+ },
+ ),
+ );
+ } else {
+ // P is not an enumerable property.
+ /* do nothing */
+ }
+ }
+ return objectPreventExtensions(copy);
+ }
+};
/**
* Returns the function on the provided value at the provided property
* associated value which is callable.
*/
export const getMethod = (V, P) => {
- const func = getPropertyValue(V, P);
+ const func = V[P];
if (func == null) {
return undefined;
} else if (typeof func !== "function") {
}
};
+/**
+ * Returns the property descriptor record for the own property with the
+ * provided property key on the provided value, or null if none exists.
+ *
+ * ※ This is effectively an alias for
+ * `Object.getOwnPropertyDescriptor`, but the return value is a proxied
+ * object with null prototype.
+ */
+export const getOwnPropertyDescriptor = (O, P) => {
+ const desc = objectGetOwnPropertyDescriptor(O, P);
+ return desc === UNDEFINED ? UNDEFINED : toPropertyDescriptor(desc);
+};
+
+/**
+ * Returns the property descriptors for the own properties on the
+ * provided value.
+ *
+ * ※ This is effectively an alias for
+ * `Object.getOwnPropertyDescriptors`, but the values on the resulting
+ * object are proxied objects with null prototypes.
+ */
+export const getOwnPropertyDescriptors = (O) => {
+ const obj = toObject(O);
+ const keys = ownKeys(obj);
+ const descriptors = {};
+ for (let k = 0; k < keys.length; ++k) {
+ const key = keys[k];
+ defineOwnDataProperty(
+ descriptors,
+ key,
+ getOwnPropertyDescriptor(O, key),
+ );
+ }
+ return descriptors;
+};
+
+/**
+ * Returns an array of property keys on the provided value.
+ *
+ * ※ This is effectively an alias for `Reflect.ownKeys`, except that
+ * it does not require that the argument be an object.
+ */
+export const getOwnPropertyKeys = (O) => ownKeys(toObject(O));
+
/**
* Returns an array of string‐valued own property keys on the
- * provided object.
+ * provided value.
*
* ☡ This includes both enumerable and non·enumerable properties.
*
* ※ This is effectively an alias for `Object.getOwnPropertyNames`.
*/
-export const getOwnPropertyStrings = createArrowFunction(
- Object.getOwnPropertyNames,
- { name: "getOwnPropertyStrings" },
-);
+export const getOwnPropertyStrings = (O) => getOwnPropertyNames(O);
/**
* Returns an array of symbol‐valued own property keys on the
- * provided object.
+ * provided value.
*
* ☡ This includes both enumerable and non·enumerable properties.
*
* ※ This is effectively an alias for
* `Object.getOwnPropertySymbols`.
*/
-export const getOwnPropertySymbols = createArrowFunction(
- Object.getOwnPropertySymbols,
-);
+export const getOwnPropertySymbols = (O) =>
+ objectGetOwnPropertySymbols(O);
+
+/**
+ * Returns the value of the provided property key on the provided
+ * value.
+ *
+ * ※ This is effectively an alias for `Reflect.get`, except that it
+ * does not require that the argument be an object.
+ */
+export const getPropertyValue = (O, P, Receiver = O) =>
+ get(toObject(O), P, Receiver);
/**
- * Returns the prototype of the provided object.
+ * Returns the prototype of the provided value.
*
* ※ This is effectively an alias for `Object.getPrototypeOf`.
*/
-export const getPrototype = createArrowFunction(
- Object.getPrototypeOf,
- { name: "getPrototype" },
-);
+export const getPrototype = (O) => getPrototypeOf(O);
/**
- * Returns whether the provided object has an own property with the
+ * Returns whether the provided value has an own property with the
* provided property key.
*
* ※ This is effectively an alias for `Object.hasOwn`.
*/
-export const hasOwnProperty = createArrowFunction(Object.hasOwn, {
- name: "hasOwnProperty",
-});
+export const hasOwnProperty = (O, P) => hasOwn(O, P);
+
+/**
+ * Returns whether the provided property key exists on the provided
+ * value.
+ *
+ * ※ This is effectively an alias for `Reflect.has`, except that it
+ * does not require that the argument be an object.
+ *
+ * ※ This includes properties present on the prototype chain.
+ */
+export const hasProperty = (O, P) => has(toObject(O), P);
/** Returns whether the provided value is an arraylike object. */
export const isArraylikeObject = ($) => {
}
};
-export const {
- /**
- * Returns whether the provided value is spreadable during array
- * concatenation.
- *
- * This is also used to determine which things should be treated as
- * collections.
- */
- isConcatSpreadableObject,
-} = (() => {
- const { isArray } = Array;
-
- return {
- isConcatSpreadableObject: ($) => {
- if (type($) !== "object") {
- // The provided value is not an object.
- return false;
- } else {
- // The provided value is an object.
- const spreadable = $[IS_CONCAT_SPREADABLE];
- return spreadable !== undefined ? !!spreadable : isArray($);
- }
- },
- };
-})();
+/**
+ * Returns whether the provided value is spreadable during array
+ * concatenation.
+ *
+ * This is also used to determine which things should be treated as
+ * collections.
+ */
+export const isConcatSpreadableObject = ($) => {
+ if (type($) !== "object") {
+ // The provided value is not an object.
+ return false;
+ } else {
+ // The provided value is an object.
+ const spreadable = $[IS_CONCAT_SPREADABLE];
+ return spreadable !== UNDEFINED ? !!spreadable : isArray($);
+ }
+};
/**
- * Returns whether the provided object is extensible.
+ * Returns whether the provided value is an extensible object.
*
* ※ This function returns false for nonobjects.
*
* ※ This is effectively an alias for `Object.isExtensible`.
*/
-export const isExtensibleObject = createArrowFunction(
- Object.isExtensible,
- { name: "isExtensibleObject" },
-);
+export const isExtensibleObject = (O) => isExtensible(O);
+
+/**
+ * Returns whether the provided value is an unfrozen object.
+ *
+ * ※ This function returns false for nonobjects.
+ *
+ * ※ This is effectively an alias for `!Object.isFrozen`.
+ */
+export const isUnfrozenObject = (O) => !isFrozen(O);
+
+/**
+ * Returns whether the provided value is an unsealed object.
+ *
+ * ※ This function returns false for nonobjects.
+ *
+ * ※ This is effectively an alias for `!Object.isSealed`.
+ */
+export const isUnsealedObject = (O) => !isSealed(O);
/**
* Returns the length of the provided arraylike value.
/**
* Returns an array of key~value pairs for the enumerable,
- * string‐valued property keys on the provided object.
+ * string‐valued property keys on the provided value.
*
* ※ This is effectively an alias for `Object.entries`.
*/
-export const namedEntries = createArrowFunction(Object.entries, {
- name: "namedEntries",
-});
+export const namedEntries = (O) => entries(O);
/**
* Returns an array of the enumerable, string‐valued property keys on
- * the provided object.
+ * the provided value.
*
* ※ This is effectively an alias for `Object.keys`.
*/
-export const namedKeys = createArrowFunction(Object.keys, {
- name: "namedKeys",
-});
+export const namedKeys = (O) => keys(O);
/**
* Returns an array of property values for the enumerable,
- * string‐valued property keys on the provided object.
+ * string‐valued property keys on the provided value.
*
* ※ This is effectively an alias for `Object.values`.
*/
-export const namedValues = createArrowFunction(Object.values, {
- name: "namedValues",
-});
+export const namedValues = (O) => values(O);
/**
* Returns a new object with the provided prototype and property
*
* ※ This is effectively an alias for `Object.create`.
*/
-export const objectCreate = createArrowFunction(Object.create, {
- name: "objectCreate",
-});
+export const objectCreate = (O, Properties) => create(O, Properties);
/**
- * Returns a new object with the provided property keys and values.
+ * Returns a new object with property keys and values from the provided
+ * iterable value.
*
* ※ This is effectively an alias for `Object.fromEntries`.
*/
-export const objectFromEntries = createArrowFunction(
- Object.fromEntries,
- { name: "objectFromEntries" },
-);
+export const objectFromEntries = (iterable) => fromEntries(iterable);
/**
* Marks the provided object as non·extensible, and returns the
*
* ※ This is effectively an alias for `Object.preventExtensions`.
*/
-export const preventExtensions = createArrowFunction(
- Object.preventExtensions,
-);
+export const preventExtensions = (O) => objectPreventExtensions(O);
/**
* Marks the provided object as non·extensible and marks all its
*
* ※ This is effectively an alias for `Object.seal`.
*/
-export const seal = createArrowFunction(Object.seal);
+export const seal = (O) => objectSeal(O);
+
+/**
+ * Sets the provided property key to the provided value on the provided
+ * object and returns the object.
+ *
+ * ※ This function differs from `Reflect.set` in that it throws if the
+ * setting is unsuccessful.
+ *
+ * ☡ This function throws if the first argument is not an object.
+ */
+export const setPropertyValue = (O, P, V, Receiver = O) => {
+ if (type(O) !== "object") {
+ throw new TypeError(
+ `Piscēs: Tried to set property but provided value was not an object: ${V}`,
+ );
+ } else if (!set(O, P, V, Receiver)) {
+ throw new TypeError(
+ `Piscēs: Tried to set property on object but [[Set]] returned false: ${P}`,
+ );
+ } else {
+ return O;
+ }
+};
/**
* Sets the values of the enumerable own properties of the provided
- * additional objects on the provided object.
+ * additional objects on the provided values.
*
* ※ This is effectively an alias for `Object.assign`.
*/
-export const setPropertyValues = createArrowFunction(Object.assign, {
- name: "setPropertyValues",
-});
+export const setPropertyValues = (target, source, ...sources) => {
+ const to = toObject(target);
+ for (let i = -1; i < sources.length; ++i) {
+ // Iterate over each source and set the appropriate property
+ // values.
+ const nextSource = i === -1 ? source : sources[i];
+ if (nextSource != null) {
+ // The current source is not nullish; handle its own properties.
+ const from = toObject(nextSource);
+ const keys = ownKeys(from);
+ for (let k = 0; k < keys.length; ++k) {
+ // Iterate over each key in the current source and set it in
+ // the target object if it is enumerable.
+ const nextKey = keys[k];
+ const desc = reflectGetOwnPropertyDescriptor(from, nextKey);
+ if (desc !== UNDEFINED && desc.enumerable) {
+ // The current key is present and enumerable; set it to its
+ // corresponding value.
+ const propValue = from[nextKey];
+ to[nextKey] = propValue;
+ } else {
+ // The current key is not present or not enumerable.
+ /* do nothing */
+ }
+ }
+ } else {
+ // The current source is nullish.
+ /* do nothing */
+ }
+ }
+ return to;
+};
+
+/**
+ * Sets the prototype of the provided object to the provided value and
+ * returns the object.
+ *
+ * ※ This is effectively an alias for `Object.setPrototypeOf`, but it
+ * won’t throw when setting the prototype of a primitive to its current
+ * value.
+ */
+export const 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(objectPreventExtensions(obj), proto);
+ return O;
+ }
+};
+
+/**
+ * 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 = ($) => {
+ 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 object($);
+ }
+};
/**
* Returns the property key (symbol or string) corresponding to the