]>
Lady’s Gitweb - Pisces/blob - function.test.js
   1 // ♓🌟 Piscēs ∷ function.test.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/>. 
  20 } from "./dev-deps.js"; 
  27   createCallableFunction
, 
  28   createIllegalConstructor
, 
  29   createProxyConstructor
, 
  35 } from "./function.js"; 
  37 describe("bind", () => { 
  38   it("[[Call]] binds this", () => { 
  51   it("[[Call]] binds arguments", () => { 
  55           return [this, ...args
]; 
  59       ).call("failure", "cmfwyp"), 
  60       ["etaoin", "shrdlu", "cmfwyp"], 
  64   it("[[Call]] works with any arraylike third argument", () => { 
  68           return [this, ...args
]; 
  76       ).call("failure", "cmfwyp"), 
  77       ["etaoin", undefined, "shrdlu", undefined, "cmfwyp"], 
  81   it("[[Construct]] throws an error", () => { 
  82     assertThrows(() => new bind(function () {})); 
  85   describe(".length", () => { 
  86     it("[[Get]] returns the correct length", () => { 
  87       assertStrictEquals(bind
.length
, 3); 
  91   describe(".name", () => { 
  92     it("[[Get]] returns the correct name", () => { 
  93       assertStrictEquals(bind
.name
, "bind"); 
  98 describe("call", () => { 
  99   it("[[Call]] calls with the provided this value", () => { 
 112   it("[[Call]] calls with the provided arguments", () => { 
 116           return [this, ...args
]; 
 119         ["shrdlu", "cmfwyp"], 
 121       ["etaoin", "shrdlu", "cmfwyp"], 
 125   it("[[Call]] works with any arraylike third argument", () => { 
 129           return [this, ...args
]; 
 139       ["etaoin", undefined, "shrdlu", undefined, "cmfwyp"], 
 143   it("[[Construct]] throws an error", () => { 
 144     assertThrows(() => new call(function () {}, null, [])); 
 147   describe(".length", () => { 
 148     it("[[Get]] returns the correct length", () => { 
 149       assertStrictEquals(call
.length
, 3); 
 153   describe(".name", () => { 
 154     it("[[Get]] returns the correct name", () => { 
 155       assertStrictEquals(call
.name
, "call"); 
 160 describe("completesNormally", () => { 
 161   it("[[Call]] returns true for functions which complete normally", () => { 
 162     assertStrictEquals(completesNormally(() => {}), true); 
 165   it("[[Call]] returns false for functions which throw", () => { 
 167       completesNormally(() => { 
 174   it("[[Call]] throws when the argument is not callable", () => { 
 175     assertThrows(() => completesNormally(null)); 
 178   it("[[Call]] throws when the argument is not provided", () => { 
 179     assertThrows(() => completesNormally()); 
 182   it("[[Construct]] throws an error", () => { 
 183     assertThrows(() => new completesNormally(function () {})); 
 186   describe(".length", () => { 
 187     it("[[Get]] returns the correct length", () => { 
 188       assertStrictEquals(completesNormally
.length
, 1); 
 192   describe(".name", () => { 
 193     it("[[Get]] returns the correct name", () => { 
 194       assertStrictEquals(completesNormally
.name
, "completesNormally"); 
 199 describe("construct", () => { 
 200   it("[[Call]] defaults to the constructor as the target", () => { 
 201     const constructor = class {}; 
 203       Object
.getPrototypeOf(construct( 
 207       constructor.prototype, 
 211   it("[[Call]] constructs with the provided new target", () => { 
 212     const target = function () {}; 
 225   it("[[Call]] constructs with the provided arguments", () => { 
 229           return [new.target
.value
, ...args
]; 
 231         ["shrdlu", "cmfwyp"], 
 232         Object
.assign(function () {}, { value: "etaoin" }), 
 234       ["etaoin", "shrdlu", "cmfwyp"], 
 238   it("[[Call]] works with any arraylike third argument", () => { 
 242           return [new.target
.value
, ...args
]; 
 250         Object
.assign(function () {}, { value: "etaoin" }), 
 252       ["etaoin", undefined, "shrdlu", undefined, "cmfwyp"], 
 256   it("[[Construct]] throws an error", () => { 
 257     assertThrows(() => new construct(function () {}, [])); 
 260   describe(".length", () => { 
 261     it("[[Get]] returns the correct length", () => { 
 262       assertStrictEquals(construct
.length
, 2); 
 266   describe(".name", () => { 
 267     it("[[Get]] returns the correct name", () => { 
 268       assertStrictEquals(construct
.name
, "construct"); 
 273 describe("createArrowFunction", () => { 
 274   it("[[Call]] sets this to undefined", () => { 
 285   it("[[Call]] transfers the provided arguments", () => { 
 289           return [this, ...args
]; 
 291       ).call("failure", "etaoin", "shrdlu", "cmfwyp"), 
 292       [undefined, "etaoin", "shrdlu", "cmfwyp"], 
 296   it("[[Call]] correctly sets the length", () => { 
 299         function (_a
, _b
, _c
) {}, 
 305   it("[[Call]] correctly sets the name", () => { 
 308         function etaoin() {}, 
 314   it("[[Call]] allows the length to be overridden", () => { 
 317         function etaoin() {}, 
 324   it("[[Call]] allows the name to be overridden", () => { 
 327         function etaoin() {}, 
 334   it("[[Call]] returns an arrow function", () => { 
 335     assertThrows(() => new (createArrowFunction(function () {}))()); 
 338   it("[[Call]] returns a function with no prototype property", () => { 
 341         createArrowFunction(function () {}, { prototype: {} })), 
 345   it("[[Construct]] throws an error", () => { 
 346     assertThrows(() => new createArrowFunction(function () {})); 
 349   describe(".length", () => { 
 350     it("[[Get]] returns the correct length", () => { 
 351       assertStrictEquals(createArrowFunction
.length
, 1); 
 355   describe(".name", () => { 
 356     it("[[Get]] returns the correct name", () => { 
 358         createArrowFunction
.name
, 
 359         "createArrowFunction", 
 365 describe("createCallableFunction", () => { 
 366   it("[[Call]] transfers the first argument to this", () => { 
 368       createCallableFunction( 
 372       ).call("fail", "pass"), 
 377   it("[[Call]] transfers the remaining arguments", () => { 
 379       createCallableFunction( 
 381           return [this, ...args
]; 
 383       ).call("failure", "etaoin", "shrdlu", "cmfwyp"), 
 384       ["etaoin", "shrdlu", "cmfwyp"], 
 388   it("[[Call]] correctly sets the length", () => { 
 390       createCallableFunction( 
 391         function (_a
, _b
, _c
) {}, 
 397   it("[[Call]] correctly sets the name", () => { 
 399       createCallableFunction( 
 400         function etaoin() {}, 
 406   it("[[Call]] allows the length to be overridden", () => { 
 408       createCallableFunction( 
 409         function etaoin() {}, 
 416   it("[[Call]] allows the name to be overridden", () => { 
 418       createCallableFunction( 
 419         function etaoin() {}, 
 426   it("[[Call]] returns an arrow function", () => { 
 427     assertThrows(() => new (createCallableFunction(function () {}))()); 
 430   it("[[Call]] returns a function with no prototype property", () => { 
 433         createCallableFunction(function () {}, { prototype: {} })), 
 437   it("[[Construct]] throws an error", () => { 
 438     assertThrows(() => new createCallableFunction(function () {})); 
 441   describe(".length", () => { 
 442     it("[[Get]] returns the correct length", () => { 
 443       assertStrictEquals(createCallableFunction
.length
, 1); 
 447   describe(".name", () => { 
 448     it("[[Get]] returns the correct name", () => { 
 450         createCallableFunction
.name
, 
 451         "createCallableFunction", 
 457 describe("createIllegalConstructor", () => { 
 458   it("[[Call]] returns a constructor", () => { 
 459     assert(isConstructor(createIllegalConstructor())); 
 462   it("[[Call]] works as expected when provided with no arguments", () => { 
 463     const constructor = createIllegalConstructor(); 
 465       Object
.getPrototypeOf(constructor), 
 469       Object
.getPrototypeOf(constructor.prototype), 
 473       Object
.getOwnPropertyDescriptors(constructor.prototype), 
 476       constructor.prototype, 
 477       Object
.create(Object
.prototype, { 
 487       !Object
.getOwnPropertyDescriptor(constructor, "prototype") 
 490     assertStrictEquals(constructor.name
, ""); 
 493   it("[[Call]] returns a correctly‐formed constructor when provided one argument", () => { 
 494     const constructorPrototype 
= Object
.create(null, { 
 495       name: { value: "etaoin" }, 
 496       length: { value: "3" }, 
 497       prototype: { value: {} }, 
 499     const constructor = createIllegalConstructor( 
 500       Object
.create(constructorPrototype
), 
 502     assert(isConstructor(constructor)); 
 504       Object
.getPrototypeOf(constructor), 
 505       constructorPrototype
, 
 507     assert(Object
.hasOwn(constructor, "prototype")); 
 509       constructor.prototype, 
 510       constructorPrototype
.prototype, 
 513       !Object
.getOwnPropertyDescriptor(constructor, "prototype") 
 516     assertStrictEquals(constructor.name
, "etaoin"); 
 517     assertStrictEquals(constructor.length
, 3); 
 520   it("[[Call]] allows the length to be overridden", () => { 
 522       createIllegalConstructor( 
 523         function etaoin() {}, 
 530   it("[[Call]] allows the name to be overridden", () => { 
 532       createIllegalConstructor( 
 533         function etaoin() {}, 
 540   it("[[Call]] allows the prototype to be overridden", () => { 
 543       createIllegalConstructor( 
 544         function etaoin() {}, 
 551   it("[[Construct]] throws an error", () => { 
 552     assertThrows(() => new createIllegalConstructor(function () {})); 
 555   describe(".length", () => { 
 556     it("[[Get]] returns the correct length", () => { 
 557       assertStrictEquals(createIllegalConstructor
.length
, 1); 
 561   describe(".name", () => { 
 562     it("[[Get]] returns the correct name", () => { 
 564         createIllegalConstructor
.name
, 
 565         "createIllegalConstructor", 
 570   describe("~", () => { 
 571     it("[[Call]] throws an error", () => { 
 573         createIllegalConstructor(function () {})(); 
 577     it("[[Construct]] throws an error", () => { 
 579         createIllegalConstructor(function () {})(); 
 585 describe("createProxyConstructor", () => { 
 586   it("[[Call]] returns a constructor", () => { 
 587     assert(isConstructor(createProxyConstructor({}))); 
 590   it("[[Call]] throws with no arguments", () => { 
 591     assertThrows(() => createProxyConstructor()); 
 594   it("[[Call]] throws if the second argument is not a constructor or undefined", () => { 
 595     assertThrows(() => createProxyConstructor({}, () => {})); 
 598   it("[[Call]] throws if the third argument is not a constructor or undefined", () => { 
 600       createProxyConstructor({}, undefined, () => {}) 
 604   it("[[Call]] creates a proper proxy constructor", () => { 
 605     const constructorPrototype 
= function etaoin(_
) {}; 
 606     const constructor = class Constructor
 
 607       extends constructorPrototype 
{ 
 608       constructor(_1
, _2
, _3
) {} 
 610     const proxyConstructor 
= createProxyConstructor( 
 614     assert(isConstructor(proxyConstructor
)); 
 616       Object
.getPrototypeOf(proxyConstructor
), 
 619     assertStrictEquals(proxyConstructor
.prototype, undefined); 
 620     assertStrictEquals(proxyConstructor
.name
, "ConstructorProxy"); 
 621     assertStrictEquals(proxyConstructor
.length
, 3); 
 624   it("[[Call]] allows the length to be overridden", () => { 
 626       createProxyConstructor({}, undefined, undefined, { 
 633   it("[[Call]] allows the name to be overridden", () => { 
 635       createProxyConstructor({}, function etaoin() {}, undefined, { 
 642   it("[[Call]] does not allow the prototype to be overridden", () => { 
 644       createProxyConstructor({}, undefined, undefined, { 
 651   it("[[Construct]] throws an error", () => { 
 652     assertThrows(() => new createProxyConstructor({})); 
 655   describe(".length", () => { 
 656     it("[[Get]] returns the correct length", () => { 
 657       assertStrictEquals(createProxyConstructor
.length
, 2); 
 661   describe(".name", () => { 
 662     it("[[Get]] returns the correct name", () => { 
 664         createProxyConstructor
.name
, 
 665         "createProxyConstructor", 
 670   describe("~", () => { 
 671     it("[[Call]] throws an error", () => { 
 673         createProxyConstructor({})(); 
 677     it("[[Construct]] produces a proxy", () => { 
 679       const proxyConstructor 
= createProxyConstructor({ 
 680         get(O
, P
, Receiver
) { 
 681           if (P 
=== "etaoin") { 
 682             return Reflect
.get(O
, P
, Receiver
) ?? "success"; 
 684             return Reflect
.get(O
, P
, Receiver
); 
 690       const proxy 
= new proxyConstructor(); 
 691       assertStrictEquals(proxy
.etaoin
, "success"); 
 692       obj
.etaoin 
= "shrdlu"; 
 693       assertStrictEquals(proxy
.etaoin
, "shrdlu"); 
 696     it("[[Construct]] receives the expected new.target", () => { 
 697       const constructor = function Constructor() { 
 698         return { name: new.target
.name 
}; 
 701         new (createProxyConstructor({}, constructor))().name
, 
 705         new (createProxyConstructor( 
 708           function NewTarget() {}, 
 715   describe("~length", () => { 
 716     it("[[GetOwnProperty]] has the correct descriptor", () => { 
 718         Object
.getOwnPropertyDescriptor( 
 719           createProxyConstructor({}), 
 732   describe("~name", () => { 
 733     it("[[GetOwnProperty]] has the correct descriptor", () => { 
 735         Object
.getOwnPropertyDescriptor( 
 736           createProxyConstructor({}), 
 742           value: "ObjectProxy", 
 749   describe("~prototype", () => { 
 750     it("[[GetOwnProperty]] has the correct descriptor", () => { 
 752         Object
.getOwnPropertyDescriptor( 
 753           createProxyConstructor({}), 
 766   describe("~revocable", () => { 
 767     it("[[Call]] produces a revocable proxy", () => { 
 769       const proxyConstructor 
= createProxyConstructor({ 
 770         get(O
, P
, Receiver
) { 
 771           if (P 
=== "etaoin") { 
 772             return Reflect
.get(O
, P
, Receiver
) ?? "success"; 
 774             return Reflect
.get(O
, P
, Receiver
); 
 780       const { proxy
, revoke 
} = proxyConstructor
.revocable(); 
 781       assertStrictEquals(proxy
.etaoin
, "success"); 
 782       obj
.etaoin 
= "shrdlu"; 
 783       assertStrictEquals(proxy
.etaoin
, "shrdlu"); 
 785       assertThrows(() => proxy
.etaoin
); 
 788     it("[[Call]] receives the expected new.target", () => { 
 789       const constructor = function Constructor() { 
 790         return { name: new.target
.name 
}; 
 793         createProxyConstructor({}, constructor).revocable().proxy
.name
, 
 797         createProxyConstructor( 
 800           function NewTarget() {}, 
 801         ).revocable().proxy
.name
, 
 806     it("[[Construct]] throws an error", () => { 
 807       assertThrows(() => new (createProxyConstructor({})).revocable()); 
 810     it("[[GetOwnProperty]] has the correct descriptor", () => { 
 811       const proxyConstructor 
= createProxyConstructor({}); 
 813         Object
.getOwnPropertyDescriptor(proxyConstructor
, "revocable"), 
 817           value: proxyConstructor
.revocable
, 
 825 describe("identity", () => { 
 826   it("[[Call]] returns what it is given", () => { 
 828     assertStrictEquals(identity(value
), value
); 
 831   it("[[Construct]] is constructable", () => { 
 833     assertStrictEquals(new identity(value
), value
); 
 836   it("[[Construct]] is subclassable", () => { 
 838     assertStrictEquals(new class extends identity 
{}(value
), value
); 
 841   describe(".length", () => { 
 842     it("[[Get]] returns the correct length", () => { 
 843       assertStrictEquals(identity
.length
, 1); 
 847   describe(".name", () => { 
 848     it("[[Get]] returns the correct name", () => { 
 849       assertStrictEquals(identity
.name
, "identity"); 
 854 describe("isCallable", () => { 
 855   it("[[Call]] returns true for ordinary functions", () => { 
 856     assertStrictEquals(isCallable(function () {}), true); 
 859   it("[[Call]] returns true for arrow functions", () => { 
 860     assertStrictEquals(isCallable(() => {}), true); 
 863   it("[[Call]] returns true for generator functions", () => { 
 864     assertStrictEquals(isCallable(function* () {}), true); 
 867   it("[[Call]] returns true for classes", () => { 
 868     assertStrictEquals(isCallable(class {}), true); 
 871   it("[[Call]] returns true for builtin functions", () => { 
 872     assertStrictEquals(isCallable(Math
.ceil
), true); 
 875   it("[[Call]] returns true for getters", () => { 
 878         Object
.getOwnPropertyDescriptor({ 
 888   it("[[Call]] returns true for setters", () => { 
 891         Object
.getOwnPropertyDescriptor({ 
 901   it("[[Call]] returns false for null", () => { 
 902     assertStrictEquals(isCallable(null), false); 
 905   it("[[Call]] returns false for objects", () => { 
 906     assertStrictEquals(isCallable({}), false); 
 909   it("[[Construct]] throws an error", () => { 
 910     assertThrows(() => new isCallable(function () {})); 
 913   describe(".length", () => { 
 914     it("[[Get]] returns the correct length", () => { 
 915       assertStrictEquals(isCallable
.length
, 1); 
 919   describe(".name", () => { 
 920     it("[[Get]] returns the correct name", () => { 
 921       assertStrictEquals(isCallable
.name
, "isCallable"); 
 926 describe("isConstructor", () => { 
 927   it("[[Call]] returns true for ordinary functions", () => { 
 928     assertStrictEquals(isConstructor(function () {}), true); 
 931   it("[[Call]] returns false for arrow functions", () => { 
 932     assertStrictEquals(isConstructor(() => {}), false); 
 935   it("[[Call]] returns false for generator functions", () => { 
 936     assertStrictEquals(isConstructor(function* () {}), false); 
 939   it("[[Call]] returns true for classes", () => { 
 940     assertStrictEquals(isConstructor(class {}), true); 
 943   it("[[Call]] returns false for builtin functions", () => { 
 944     assertStrictEquals(isConstructor(Math
.ceil
), false); 
 947   it("[[Call]] returns false for getters", () => { 
 950         Object
.getOwnPropertyDescriptor({ 
 960   it("[[Call]] returns false for setters", () => { 
 963         Object
.getOwnPropertyDescriptor({ 
 973   it("[[Call]] returns false for null", () => { 
 974     assertStrictEquals(isConstructor(null), false); 
 977   it("[[Call]] returns false for objects", () => { 
 978     assertStrictEquals(isConstructor({}), false); 
 981   it("[[Construct]] throws an error", () => { 
 982     assertThrows(() => new isConstructor(function () {})); 
 985   describe(".length", () => { 
 986     it("[[Get]] returns the correct length", () => { 
 987       assertStrictEquals(isConstructor
.length
, 1); 
 991   describe(".name", () => { 
 992     it("[[Get]] returns the correct name", () => { 
 993       assertStrictEquals(isConstructor
.name
, "isConstructor"); 
 998 describe("maybe", () => { 
 999   it("[[Call]] calls if not nullish", () => { 
1000     const wrapper 
= spy(() => "success"); 
1001     assertStrictEquals(maybe(0, wrapper
), "success"); 
1002     assertSpyCalls(wrapper
, 1); 
1003     assertSpyCall(wrapper
, 0, { 
1006       returned: "success", 
1010   it("[[Call]] does not call if nullish", () => { 
1011     const wrapper 
= spy(() => "success"); 
1012     assertStrictEquals(maybe(null, wrapper
), null); 
1013     assertStrictEquals(maybe(undefined, wrapper
), undefined); 
1014     assertSpyCalls(wrapper
, 0); 
1017   it("[[Construct]] throws an error", () => { 
1018     assertThrows(() => new maybe(true, ($) => $)); 
1021   describe(".length", () => { 
1022     it("[[Get]] returns the correct length", () => { 
1023       assertStrictEquals(maybe
.length
, 2); 
1027   describe(".name", () => { 
1028     it("[[Get]] returns the correct name", () => { 
1029       assertStrictEquals(maybe
.name
, "maybe"); 
1034 describe("ordinaryHasInstance", () => { 
1035   it("[[Call]] walks the prototype chain", () => { 
1036     const constructor = class { 
1037       [Symbol
.hasInstance
]() { 
1042       ordinaryHasInstance( 
1044         new class extends constructor {}(), 
1050   it("[[Construct]] throws an error", () => { 
1051     assertThrows(() => new ordinaryHasInstance(function () {}, {})); 
1054   describe(".length", () => { 
1055     it("[[Get]] returns the correct length", () => { 
1056       assertStrictEquals(ordinaryHasInstance
.length
, 2); 
1060   describe(".name", () => { 
1061     it("[[Get]] returns the correct name", () => { 
1063         ordinaryHasInstance
.name
, 
1064         "ordinaryHasInstance", 
 
This page took 0.120124 seconds  and 5 git commands  to generate.