// 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 { call, makeCallable } from "./function.js";
+import { call, createCallableFunction } from "./function.js";
import {
floor,
isIntegralNumber,
* Returns the result of catenating the provided arraylikes into a new
* collection according to the algorithm of `Array::concat`.
*/
-export const catenate = makeCallable(arrayPrototype.concat);
+export const catenate = createCallableFunction(
+ arrayPrototype.concat,
+ "catenate",
+);
/**
* Copies the items in the provided object to a new location according
* to the algorithm of `Array::copyWithin`.
*/
-export const copyWithin = makeCallable(arrayPrototype.copyWithin);
+export const copyWithin = createCallableFunction(
+ arrayPrototype.copyWithin,
+);
/**
* Fills the provided object with the provided value according to the
* algorithm of `Array::fill`.
*/
-export const fill = makeCallable(arrayPrototype.fill);
+export const fill = createCallableFunction(arrayPrototype.fill);
/**
* Returns the result of filtering the provided object with the
* provided callback, according to the algorithm of `Array::filter`.
*/
-export const filter = makeCallable(arrayPrototype.filter);
+export const filter = createCallableFunction(arrayPrototype.filter);
/**
* Returns the first index in the provided object whose value satisfies
* the provided callback according to the algorithm of
* `Array::findIndex`.
*/
-export const findIndex = makeCallable(arrayPrototype.findIndex);
+export const findIndex = createCallableFunction(
+ arrayPrototype.findIndex,
+);
/**
* Returns the first indexed entry in the provided object whose value
* satisfies the provided callback, according to the algorithm of
* `Array::find`.
*/
-export const findItem = makeCallable(arrayPrototype.find);
+export const findItem = createCallableFunction(
+ arrayPrototype.find,
+ "findItem",
+);
/**
* Returns the result of flatmapping the provided value with the
* provided callback according to the algorithm of `Array::flatMap`.
*/
-export const flatmap = makeCallable(arrayPrototype.flatMap);
+export const flatmap = createCallableFunction(
+ arrayPrototype.flatMap,
+ "flatmap",
+);
/**
* Returns the result of flattening the provided object according to
* the algorithm of `Array::flat`.
*/
-export const flatten = makeCallable(arrayPrototype.flat);
+export const flatten = createCallableFunction(
+ arrayPrototype.flat,
+ "flatten",
+);
/**
* Returns the first index of the provided object with a value
* equivalent to the provided value according to the algorithm of
* `Array::indexOf`.
*/
-export const getFirstIndex = makeCallable(arrayPrototype.indexOf);
+export const getFirstIndex = createCallableFunction(
+ arrayPrototype.indexOf,
+ "getFirstIndex",
+);
/**
* Returns the item on the provided object at the provided index
* according to the algorithm of `Array::at`.
*/
-export const getItem = makeCallable(arrayPrototype.at);
+export const getItem = createCallableFunction(
+ arrayPrototype.at,
+ "getItem",
+);
/**
* Returns the last index of the provided object with a value
* equivalent to the provided value according to the algorithm of
* `Array::lastIndexOf`.
*/
-export const getLastIndex = makeCallable(arrayPrototype.lastIndexOf);
+export const getLastIndex = createCallableFunction(
+ arrayPrototype.lastIndexOf,
+ "getLastIndex",
+);
/**
* Returns whether every indexed value in the provided object satisfies
* the provided function, according to the algorithm of `Array::every`.
*/
-export const hasEvery = makeCallable(arrayPrototype.every);
+export const hasEvery = createCallableFunction(
+ arrayPrototype.every,
+ "hasEvery",
+);
/**
* Returns whether the provided object has an indexed value which
* satisfies the provided function, according to the algorithm of
* `Array::some`.
*/
-export const hasSome = makeCallable(arrayPrototype.some);
+export const hasSome = createCallableFunction(
+ arrayPrototype.some,
+ "hasSome",
+);
/**
* Returns whether the provided object has an indexed value equivalent
* ※ This algorithm treats missing values as `undefined` rather than
* skipping them.
*/
-export const includes = makeCallable(arrayPrototype.includes);
+export const includes = createCallableFunction(
+ arrayPrototype.includes,
+);
/**
* Returns an iterator over the indexed entries in the provided value
* according to the algorithm of `Array::entries`.
*/
-export const indexedEntries = makeCallable(arrayPrototype.entries);
+export const indexedEntries = createCallableFunction(
+ arrayPrototype.entries,
+ "indexedEntries",
+);
/**
* Returns an iterator over the indices in the provided value according
* to the algorithm of `Array::keys`.
*/
-export const indices = makeCallable(arrayPrototype.keys);
+export const indices = createCallableFunction(
+ arrayPrototype.keys,
+ "indices",
+);
/** Returns whether the provided value is an array index string. */
export const isArrayIndexString = ($) => {
* Returns an iterator over the items in the provided value according
* to the algorithm of `Array::values`.
*/
-export const items = makeCallable(arrayPrototype.values);
+export const items = createCallableFunction(
+ arrayPrototype.values,
+ "items",
+);
/**
* Returns the length of the provided arraylike object.
* Returns the result of mapping the provided value with the provided
* callback according to the algorithm of `Array::map`.
*/
-export const map = makeCallable(arrayPrototype.map);
+export const map = createCallableFunction(arrayPrototype.map);
/**
* Pops from the provided value according to the algorithm of
* `Array::pop`.
*/
-export const pop = makeCallable(arrayPrototype.pop);
+export const pop = createCallableFunction(arrayPrototype.pop);
/**
* Pushes onto the provided value according to the algorithm of
* `Array::push`.
*/
-export const push = makeCallable(arrayPrototype.push);
+export const push = createCallableFunction(arrayPrototype.push);
/**
* Returns the result of reducing the provided value with the provided
* callback, according to the algorithm of `Array::reduce`.
*/
-export const reduce = makeCallable(arrayPrototype.reduce);
+export const reduce = createCallableFunction(arrayPrototype.reduce);
/**
* Reverses the provided value according to the algorithm of
* `Array::reverse`.
*/
-export const reverse = makeCallable(arrayPrototype.reverse);
+export const reverse = createCallableFunction(arrayPrototype.reverse);
/**
* Shifts the provided value according to the algorithm of
* `Array::shift`.
*/
-export const shift = makeCallable(arrayPrototype.shift);
+export const shift = createCallableFunction(arrayPrototype.shift);
/**
* Returns a slice of the provided value according to the algorithm of
* `Array::slice`.
*/
-export const slice = makeCallable(arrayPrototype.slice);
+export const slice = createCallableFunction(arrayPrototype.slice);
/**
* Sorts the provided value in‐place according to the algorithm of
* `Array::sort`.
*/
-export const sort = makeCallable(arrayPrototype.sort);
+export const sort = createCallableFunction(arrayPrototype.sort);
/**
* Splices into and out of the provided value according to the
* algorithm of `Array::splice`.
*/
-export const splice = makeCallable(arrayPrototype.splice);
+export const splice = createCallableFunction(arrayPrototype.splice);
/**
* Returns the result of converting the provided value to an array
* Unshifts the provided value according to the algorithm of
* `Array::unshift`.
*/
-export const unshift = makeCallable(arrayPrototype.unshift);
+export const unshift = createCallableFunction(arrayPrototype.unshift);
*
* ※ This is effectively an alias for `Function::call.bind`.
*/
- makeCallable,
+ createCallableFunction,
/**
* Returns a constructor which throws whenever it is called but has
* use that as its prototype; otherwise, it will use the prototype of
* the provided value.
*/
- makeIllegalConstructor,
+ createIllegalConstructor,
} = (() => {
// ☡ Because these functions are used to initialize module constants,
// they can’t depend on imports from elsewhere.
{ args: { value: boundArgs } },
),
),
- makeCallable: ($, name = undefined) =>
+ createCallableFunction: ($, name = undefined) =>
defineOwnProperties(callBind(functionCall, $), {
length: { value: $.length + 1 },
name: { value: name ?? $.name ?? "" },
}),
- makeIllegalConstructor: ($, proto = undefined) => {
+ createIllegalConstructor: ($, proto = undefined) => {
const constructor = function () {
throw new TypeError("Illegal constructor");
};
* Returns whether the provided object inherits from the prototype of
* the provided function.
*/
-export const ordinaryHasInstance = makeCallable(
+export const ordinaryHasInstance = createCallableFunction(
Function.prototype[Symbol.hasInstance],
"ordinaryHasInstance",
);
call,
completesNormally,
construct,
+ createCallableFunction,
+ createIllegalConstructor,
identity,
isCallable,
isConstructor,
- makeCallable,
- makeIllegalConstructor,
ordinaryHasInstance,
} from "./function.js";
});
});
+describe("createCallableFunction", () => {
+ it("[[Call]] transfers the first argument to this", () => {
+ assertStrictEquals(
+ createCallableFunction(
+ function () {
+ return this;
+ },
+ ).call("fail", "pass"),
+ "pass",
+ );
+ });
+
+ it("[[Call]] transfers the remaining arguments", () => {
+ assertEquals(
+ createCallableFunction(
+ function (...args) {
+ return [this, ...args];
+ },
+ ).call("failure", "etaoin", "shrdlu", "cmfwyp"),
+ ["etaoin", "shrdlu", "cmfwyp"],
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new createCallableFunction(function () {}));
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ createCallableFunction.name,
+ "createCallableFunction",
+ );
+ });
+ });
+});
+
+describe("createIllegalConstructor", () => {
+ it("[[Call]] returns a constructor", () => {
+ assert(isConstructor(createIllegalConstructor()));
+ });
+
+ it("[[Call]] works as expected when provided with no arguments", () => {
+ const constructor = createIllegalConstructor();
+ assertStrictEquals(
+ Object.getPrototypeOf(constructor),
+ Function.prototype,
+ );
+ assertStrictEquals(
+ Object.getPrototypeOf(constructor.prototype),
+ Object.prototype,
+ );
+ assertEquals(constructor.prototype, {});
+ assert(
+ !Object.getOwnPropertyDescriptor(constructor, "prototype")
+ .writable,
+ );
+ assertStrictEquals(constructor.name, "");
+ });
+
+ it("[[Call]] returns a correctly‐formed constructor when provided one argument", () => {
+ const constructorPrototype = Object.create(null, {
+ name: { value: "etaoin" },
+ prototype: { value: {} },
+ });
+ const constructor = createIllegalConstructor(
+ Object.create(constructorPrototype),
+ );
+ assert(isConstructor(constructor));
+ assertStrictEquals(
+ Object.getPrototypeOf(constructor),
+ constructorPrototype,
+ );
+ assert(Object.hasOwn(constructor, "prototype"));
+ assertEquals(
+ constructor.prototype,
+ constructorPrototype.prototype,
+ );
+ assert(
+ !Object.getOwnPropertyDescriptor(constructor, "prototype")
+ .writable,
+ );
+ assertStrictEquals(constructor.name, "etaoin");
+ });
+
+ it("[[Call]] allows the second argument to override the prototype of the constructor", () => {
+ const constructorPrototype = Object.create(null, {
+ name: { value: "etaoin" },
+ prototype: { value: {} },
+ });
+ const expectedPrototype = Object.create(null, {
+ name: { value: "shrdlu" },
+ prototype: { value: {} },
+ });
+ const constructor = createIllegalConstructor(
+ Object.create(constructorPrototype),
+ expectedPrototype,
+ );
+ assert(isConstructor(constructor));
+ assertStrictEquals(
+ Object.getPrototypeOf(constructor),
+ expectedPrototype,
+ );
+ assert(Object.hasOwn(constructor, "prototype"));
+ assertEquals(
+ constructor.prototype,
+ constructorPrototype.prototype,
+ );
+ assert(
+ !Object.getOwnPropertyDescriptor(constructor, "prototype")
+ .writable,
+ );
+ assertStrictEquals(constructor.name, "etaoin");
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new createIllegalConstructor(function () {}));
+ });
+
+ describe("~", () => {
+ it("[[Call]] throws an error", () => {
+ assertThrows(() => {
+ createIllegalConstructor(function () {})();
+ });
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => {
+ createIllegalConstructor(function () {})();
+ });
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ createIllegalConstructor.name,
+ "createIllegalConstructor",
+ );
+ });
+ });
+});
+
describe("identity", () => {
it("[[Call]] returns what it is given", () => {
const value = {};
});
});
-describe("makeCallable", () => {
- it("[[Call]] transfers the first argument to this", () => {
- assertStrictEquals(
- makeCallable(
- function () {
- return this;
- },
- ).call("fail", "pass"),
- "pass",
- );
- });
-
- it("[[Call]] transfers the remaining arguments", () => {
- assertEquals(
- makeCallable(
- function (...args) {
- return [this, ...args];
- },
- ).call("failure", "etaoin", "shrdlu", "cmfwyp"),
- ["etaoin", "shrdlu", "cmfwyp"],
- );
- });
-
- it("[[Construct]] throws an error", () => {
- assertThrows(() => new makeCallable(function () {}));
- });
-
- describe(".name", () => {
- it("[[Get]] returns the correct name", () => {
- assertStrictEquals(makeCallable.name, "makeCallable");
- });
- });
-});
-
-describe("makeIllegalConstructor", () => {
- it("[[Call]] returns a constructor", () => {
- assert(isConstructor(makeIllegalConstructor()));
- });
-
- it("[[Call]] works as expected when provided with no arguments", () => {
- const constructor = makeIllegalConstructor();
- assertStrictEquals(
- Object.getPrototypeOf(constructor),
- Function.prototype,
- );
- assertStrictEquals(
- Object.getPrototypeOf(constructor.prototype),
- Object.prototype,
- );
- assertEquals(constructor.prototype, {});
- assert(
- !Object.getOwnPropertyDescriptor(constructor, "prototype")
- .writable,
- );
- assertStrictEquals(constructor.name, "");
- });
-
- it("[[Call]] returns a correctly‐formed constructor when provided one argument", () => {
- const constructorPrototype = Object.create(null, {
- name: { value: "etaoin" },
- prototype: { value: {} },
- });
- const constructor = makeIllegalConstructor(
- Object.create(constructorPrototype),
- );
- assert(isConstructor(constructor));
- assertStrictEquals(
- Object.getPrototypeOf(constructor),
- constructorPrototype,
- );
- assert(Object.hasOwn(constructor, "prototype"));
- assertEquals(
- constructor.prototype,
- constructorPrototype.prototype,
- );
- assert(
- !Object.getOwnPropertyDescriptor(constructor, "prototype")
- .writable,
- );
- assertStrictEquals(constructor.name, "etaoin");
- });
-
- it("[[Call]] allows the second argument to override the prototype of the constructor", () => {
- const constructorPrototype = Object.create(null, {
- name: { value: "etaoin" },
- prototype: { value: {} },
- });
- const expectedPrototype = Object.create(null, {
- name: { value: "shrdlu" },
- prototype: { value: {} },
- });
- const constructor = makeIllegalConstructor(
- Object.create(constructorPrototype),
- expectedPrototype,
- );
- assert(isConstructor(constructor));
- assertStrictEquals(
- Object.getPrototypeOf(constructor),
- expectedPrototype,
- );
- assert(Object.hasOwn(constructor, "prototype"));
- assertEquals(
- constructor.prototype,
- constructorPrototype.prototype,
- );
- assert(
- !Object.getOwnPropertyDescriptor(constructor, "prototype")
- .writable,
- );
- assertStrictEquals(constructor.name, "etaoin");
- });
-
- it("[[Construct]] throws an error", () => {
- assertThrows(() => new makeIllegalConstructor(function () {}));
- });
-
- describe("~", () => {
- it("[[Call]] throws an error", () => {
- assertThrows(() => {
- makeIllegalConstructor(function () {})();
- });
- });
-
- it("[[Construct]] throws an error", () => {
- assertThrows(() => {
- makeIllegalConstructor(function () {})();
- });
- });
- });
-
- describe(".name", () => {
- it("[[Get]] returns the correct name", () => {
- assertStrictEquals(
- makeIllegalConstructor.name,
- "makeIllegalConstructor",
- );
- });
- });
-});
-
describe("ordinaryHasInstance", () => {
it("[[Call]] walks the prototype chain", () => {
const constructor = class {
// 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, identity, makeCallable } from "./function.js";
+import {
+ bind,
+ call,
+ createCallableFunction,
+ identity,
+} from "./function.js";
import {
arrayIteratorFunction,
stringIteratorFunction,
stringReplaceAll(
`${$}`,
/[A-Z]/gu,
- makeCallable(stringToLowercase),
+ createCallableFunction(stringToLowercase),
),
asciiUppercase: ($) =>
stringReplaceAll(
`${$}`,
/[a-z]/gu,
- makeCallable(stringToUppercase),
+ createCallableFunction(stringToUppercase),
),
};
})();
* of the provided value according to the algorithm of
* `String::[Symbol.iterator]`.
*/
-export const characters = makeCallable(
+export const characters = createCallableFunction(
stringPrototype[ITERATOR],
+ "characters",
);
/**
* representation of the provided value according to the algorithm of
* `String::charAt`.
*/
-export const getCodeUnit = makeCallable(stringPrototype.charCodeAt);
+export const getCodeUnit = createCallableFunction(
+ stringPrototype.charCodeAt,
+ "getCodeUnit",
+);
/**
* Returns the codepoint at the provided position in the string
* representation of the provided value according to the algorithm of
* `String::codePointAt`.
*/
-export const getCodepoint = makeCallable(stringPrototype.codePointAt);
+export const getCodepoint = createCallableFunction(
+ stringPrototype.codePointAt,
+ "getCodepoint",
+);
/**
* Returns the index of the first occurrence of the search string in
* the string representation of the provided value according to the
* algorithm of `String::indexOf`.
*/
-export const getFirstSubstringIndex = makeCallable(
+export const getFirstSubstringIndex = createCallableFunction(
stringPrototype.indexOf,
+ "getFirstSubstringIndex",
);
/**
* string representation of the provided value according to the
* algorithm of `String::lastIndexOf`.
*/
-export const getLastSubstringIndex = makeCallable(
+export const getLastSubstringIndex = createCallableFunction(
stringPrototype.lastIndexOf,
+ "getLastSubstringIndex",
);
/**
* provided values, returning a new string according to the algorithm
* of `String::concat`.
*/
-export const stringCatenate = makeCallable(stringPrototype.concat);
+export const stringCatenate = createCallableFunction(
+ stringPrototype.concat,
+ "stringCatenate",
+);
/**
* Returns whether the string representation of the provided value ends
* with the provided search string according to the algorithm of
* `String::endsWith`.
*/
-export const stringEndsWith = makeCallable(stringPrototype.endsWith);
+export const stringEndsWith = createCallableFunction(
+ stringPrototype.endsWith,
+ "stringEndsWith",
+);
/**
* Returns whether the string representation of the provided value
* contains the provided search string according to the algorithm of
* `String::includes`.
*/
-export const stringIncludes = makeCallable(stringPrototype.includes);
+export const stringIncludes = createCallableFunction(
+ stringPrototype.includes,
+ "stringIncludes",
+);
/**
* Returns the result of matching the string representation of the
* provided value with the provided matcher according to the algorithm
* of `String::match`.
*/
-export const stringMatch = makeCallable(stringPrototype.match);
+export const stringMatch = createCallableFunction(
+ stringPrototype.match,
+ "stringMatch",
+);
/**
* Returns the result of matching the string representation of the
* provided value with the provided matcher according to the algorithm
* of `String::matchAll`.
*/
-export const stringMatchAll = makeCallable(stringPrototype.matchAll);
+export const stringMatchAll = createCallableFunction(
+ stringPrototype.matchAll,
+ "stringMatchAll",
+);
/**
* Returns the normalized form of the string representation of the
* provided value according to the algorithm of `String::matchAll`.
*/
-export const stringNormalize = makeCallable(
+export const stringNormalize = createCallableFunction(
stringPrototype.normalize,
+ "stringNormalize",
);
/**
* of the provided value padded until it is the desired length
* according to the algorithm of `String::padEnd`.
*/
-export const stringPadEnd = makeCallable(stringPrototype.padEnd);
+export const stringPadEnd = createCallableFunction(
+ stringPrototype.padEnd,
+ "stringPadEnd",
+);
/**
* Returns the result of padding the start of the string representation
* of the provided value padded until it is the desired length
* according to the algorithm of `String::padStart`.
*/
-export const stringPadStart = makeCallable(stringPrototype.padStart);
+export const stringPadStart = createCallableFunction(
+ stringPrototype.padStart,
+ "stringPadStart",
+);
/**
* Returns the result of repeating the string representation of the
* provided value the provided number of times according to the
* algorithm of `String::repeat`.
*/
-export const stringRepeat = makeCallable(stringPrototype.repeat);
+export const stringRepeat = createCallableFunction(
+ stringPrototype.repeat,
+ "stringRepeat",
+);
/**
* Returns the result of replacing the string representation of the
* provided value with the provided replacement, using the provided
* matcher and according to the algorithm of `String::replace`.
*/
-export const stringReplace = makeCallable(stringPrototype.replace);
+export const stringReplace = createCallableFunction(
+ stringPrototype.replace,
+ "stringReplace",
+);
/**
* Returns the result of replacing the string representation of the
* provided value with the provided replacement, using the provided
* matcher and according to the algorithm of `String::replaceAll`.
*/
-export const stringReplaceAll = makeCallable(
+export const stringReplaceAll = createCallableFunction(
stringPrototype.replaceAll,
+ "stringReplaceAll",
);
/**
* provided value using the provided matcher and according to the
* algorithm of `String::search`.
*/
-export const stringSearch = makeCallable(stringPrototype.search);
+export const stringSearch = createCallableFunction(
+ stringPrototype.search,
+ "stringSearch",
+);
/**
* Returns a slice of the string representation of the provided value
* according to the algorithm of `String::slice`.
*/
-export const stringSlice = makeCallable(stringPrototype.slice);
+export const stringSlice = createCallableFunction(
+ stringPrototype.slice,
+ "stringSlice",
+);
/**
* Returns the result of splitting of the string representation of the
* provided value on the provided separator according to the algorithm
* of `String::split`.
*/
-export const stringSplit = makeCallable(stringPrototype.split);
+export const stringSplit = createCallableFunction(
+ stringPrototype.split,
+ "stringSplit",
+);
/**
* Returns whether the string representation of the provided value
* starts with the provided search string according to the algorithm of
* `String::startsWith`.
*/
-export const stringStartsWith = makeCallable(
+export const stringStartsWith = createCallableFunction(
stringPrototype.startsWith,
+ "stringStartsWith",
);
/**
* ☡ This function will throw if the provided object does not have a
* `[[StringData]]` internal slot.
*/
-export const stringValue = makeCallable(stringPrototype.valueOf);
+export const stringValue = createCallableFunction(
+ stringPrototype.valueOf,
+ "stringValue",
+);
/**
* Returns the result of stripping leading and trailing A·S·C·I·I
* Returns a substring of the string representation of the provided
* value according to the algorithm of `String::substring`.
*/
-export const substring = makeCallable(stringPrototype.substring);
+export const substring = createCallableFunction(
+ stringPrototype.substring,
+);
/**
* Returns the result of converting the provided value to a string.
// 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 { makeCallable } from "./function.js";
+import { createCallableFunction } from "./function.js";
import { getOwnPropertyDescriptor } from "./object.js";
/**
* ※ This is effectively an alias for the `Symbol::description`
* getter.
*/
-export const getSymbolDescription = makeCallable(
+export const getSymbolDescription = createCallableFunction(
getOwnPropertyDescriptor(Symbol.prototype, "description").get,
"getSymbolDescription",
);