1 // ♓🌟 Piscēs ∷ function.js
2 // ====================================================================
4 // Copyright © 2022‐2023 Lady [@ Lady’s Computer].
6 // This Source Code Form is subject to the terms of the Mozilla Public
7 // License, v. 2.0. If a copy of the MPL was not distributed with this
8 // file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
10 import { ITERATOR
} from "./value.js";
14 * Creates a bound function from the provided function using the
15 * provided this value and arguments list.
17 * ☡ As with `call` and `construct`, the arguments must be passed as
23 * Returns a new function which calls the provided function with its
24 * first argument as the `this` value and the remaining arguments
27 * ※ This is effectively an alias for `Function::call.bind`.
31 // ☡ Because these functions are used to initialize module constants,
32 // they can’t depend on imports from elsewhere.
36 } = Function
.prototype;
37 const callBind
= Reflect
.apply(functionBind
, functionCall
, [
42 defineProperties
: defineOwnProperties
,
43 getPrototypeOf
: getPrototype
,
45 const { [ITERATOR
]: arrayIterator
} = Array
.prototype;
47 next
: arrayIteratorNext
,
48 } = getPrototype([][ITERATOR
]());
49 const argumentIterablePrototype
= {
54 call(arrayIterator
, this.args
, []),
60 bind
: ($, boundThis
, boundArgs
) =>
65 argumentIterablePrototype
,
66 { args
: { value
: boundArgs
} },
69 makeCallable
: ($, name
= undefined) =>
70 defineOwnProperties(callBind(functionCall
, $), {
71 length
: { value
: $.length
+ 1 },
72 name
: { value
: name
?? $.name
?? "" },
79 * Calls the provided function with the provided this value and
82 * ☡ This is effectively an alias for `Reflect.apply`—the arguments
83 * must be passed as an arraylike.
88 * Constructs the provided function with the provided arguments list
91 * ☡ This is effectively an alias for `Reflect.construct`—the
92 * arguments must be passed as an arraylike.
96 /** Returns whether the provided value is a constructor. */
99 const { apply
, construct
} = Reflect
;
101 call
: (target
, thisArgument
, argumentsList
) =>
102 apply(target
, thisArgument
, argumentsList
),
103 construct
: (target
, argumentsList
, ...args
) =>
105 ? construct(target
, argumentsList
, args
[0])
106 : construct(target
, argumentsList
),
107 isConstructor
: ($) =>
108 completesNormally(() =>
109 // Try constructing a new object with the provided value as its
110 // `new.target`. This will throw if the provided value is not a
112 construct(function () {}, [], $)
118 * Returns whether calling the provided function with no `this` value
119 * or arguments completes normally; that is, does not throw an error.
121 * ☡ This function will throw an error if the provided argument is not
124 export const completesNormally
= ($) => {
125 if (!isCallable($)) {
126 // The provided value is not callable; this is an error.
128 `Piscēs: Cannot determine completion of noncallable value: ${$}`,
131 // The provided value is callable.
133 // Attempt to call the function and return true if this succeeds.
137 // Calling the function did not succeed; return false.
144 * Returns the provided value.
146 * ※ This function can be called as a constructor. When used in an
147 * `extends` clause and called via `super`, it will set the value of
148 * `this` to the provided value, enabling it to be extended with
149 * private class features.
151 export const identity = function ($) {
155 /** Returns whether the provided value is callable. */
156 export const isCallable
= ($) => typeof $ === "function";
159 * Returns whether the provided object inherits from the prototype of
160 * the provided function.
162 export const ordinaryHasInstance
= makeCallable(
163 Function
.prototype[Symbol
.hasInstance
],
164 "ordinaryHasInstance",