X-Git-Url: https://git.ladys.computer/Pisces/blobdiff_plain/6f1ff895670d04034ef09faea4779923a85097fb..a63ba5294bd5cc847a192f6737bc386bfe7187f8:/function.js?ds=sidebyside diff --git a/function.js b/function.js index 0b9ebcc..46cab86 100644 --- a/function.js +++ b/function.js @@ -7,22 +7,71 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at . -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 }, + ), + }; })(); /** @@ -43,47 +92,40 @@ export const call = Reflect.apply; */ 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], );