// 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 { defineOwnProperty, isObject } from "./object.js";
+export const {
+ /**
+ * Creates a bound function from the provided function using the
+ * provided this value and arguments list.
+ *
+ * ☡ As with call and construct, the arguments must be passed as an
+ * array.
+ */
+ bind,
-/**
- * Creates a bound function from the provided function using the
- * provided this value and arguments list.
- *
- * ☡ As with call and construct, the arguments must be passed as an
- * array.
- */
-export const bind = (() => {
- const callBind = Function.prototype.call.bind(
- Function.prototype.bind,
- );
- const bind = ($, boundThis, boundArgs) =>
- callBind($, boundThis, ...boundArgs);
- return bind;
+ /**
+ * Returns a new function which calls the provided function with its
+ * first argument as the `this` value and the remaining arguments
+ * passed through.
+ *
+ * ※ This is effectively an alias for Function.prototype.call.bind.
+ */
+ makeCallable,
+} = (() => {
+ // ☡ Because these functions are used to initialize module constants,
+ // they can’t depend on imports from elsewhere.
+ const {
+ bind: functionBind,
+ call: functionCall,
+ } = Function.prototype;
+ const callBind = Reflect.apply(functionBind, functionCall, [
+ functionBind,
+ ]);
+ const {
+ create: objectCreate,
+ defineProperty: defineOwnProperty,
+ getPrototypeOf: getPrototype,
+ } = Object;
+ const { iterator: iteratorSymbol } = Symbol;
+ const { [iteratorSymbol]: arrayIterator } = Array.prototype;
+ const {
+ next: arrayIteratorNext,
+ } = getPrototype([][iteratorSymbol]());
+ const argumentIterablePrototype = {
+ [iteratorSymbol]() {
+ return {
+ next: callBind(
+ arrayIteratorNext,
+ call(arrayIterator, this.args, []),
+ ),
+ };
+ },
+ };
+ return {
+ bind: ($, boundThis, boundArgs) =>
+ callBind(
+ $,
+ boundThis,
+ ...objectCreate(
+ argumentIterablePrototype,
+ { args: { value: boundArgs } },
+ ),
+ ),
+ makeCallable: ($) =>
+ defineOwnProperty(
+ callBind(functionCall, $),
+ "length",
+ { value: $.length + 1 },
+ ),
+ };
})();
/**
*/
export const construct = Reflect.construct;
+/**
+ * Returns the provided value.
+ *
+ * ※ This function can be called as a constructor. When used in an
+ * `extends` clause and called via `super`, it will set the value of
+ * `this` to the provided value, enabling it to be extended with
+ * private class features.
+ */
+export const identity = function ($) {
+ return $;
+};
+
+/** Returns whether the provided value is callable. */
+export const isCallable = ($) => typeof $ === "function";
+
/** Returns whether the provided value is a constructor. */
export const isConstructor = ($) => {
- if (!isObject($)) {
- // The provided value is not an object.
+ // The provided value is an object.
+ try {
+ construct(
+ function () {},
+ [],
+ $,
+ ); // will throw if $ is not a constructor
+ return true;
+ } catch {
return false;
- } else {
- // The provided value is an object.
- try {
- construct(
- function () {},
- [],
- $,
- ); // will throw if $ is not a constructor
- return true;
- } catch {
- return false;
- }
}
};
-/**
- * Returns a new function which calls the provided function with its
- * first argument as the `this` value and the remaining arguments
- * passed through.
- *
- * ※ This is effectively an alias for Function.prototype.call.bind.
- */
-export const makeCallable = (() => {
- const functionCall = Function.prototype.call;
- const callable = ($) => defineOwnProperty(
- bind(functionCall, $, []),
- "length",
- { value: $.length + 1 },
- );
- return callable;
-})();
-
/**
* Returns whether the provided object inherits from the prototype of
* the provided function.
*/
export const ordinaryHasInstance = makeCallable(
- Function.prototype[Symbol.hasInstance],
+ Function.prototype[Symbol.hasInstance],
);