array_findlast.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
  3. // Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
  4. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  5. //-------------------------------------------------------------------------------------------------------
  6. WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
  7. const tests = [
  8. {
  9. name : "name",
  10. body : function ()
  11. {
  12. assert.areEqual(Array.prototype.findLast.name, "findLast");
  13. }
  14. },
  15. {
  16. name : "length",
  17. body : function ()
  18. {
  19. assert.areEqual(Array.prototype.findLast.length, 1);
  20. }
  21. },
  22. {
  23. name : "call with boolean",
  24. body : function ()
  25. {
  26. assert.areEqual(undefined, Array.prototype.findLast.call(true, () => {}));
  27. assert.areEqual(undefined, Array.prototype.findLast.call(false, () => {}));
  28. }
  29. },
  30. {
  31. name : "altered during loop",
  32. body : function ()
  33. {
  34. var arr = ["Shoes", "Car", "Bike"];
  35. var results = [];
  36. arr.findLast(function(kValue) {
  37. if (results.length === 0) {
  38. arr.splice(1, 1);
  39. }
  40. results.push(kValue);
  41. });
  42. assert.areEqual(3, results.length, "predicate called three times");
  43. assert.areEqual("Bike", results[0]);
  44. assert.areEqual("Bike", results[1]);
  45. assert.areEqual("Shoes", results[2]);
  46. results = [];
  47. arr = ["Skateboard", "Barefoot"];
  48. arr.findLast(function(kValue) {
  49. if (results.length === 0) {
  50. arr.unshift("Motorcycle");
  51. arr[0] = "Magic Carpet";
  52. }
  53. results.push(kValue);
  54. });
  55. assert.areEqual(2, results.length, "predicate called twice");
  56. assert.areEqual("Barefoot", results[0]);
  57. assert.areEqual("Magic Carpet", results[1]);
  58. }
  59. },
  60. {
  61. name : "not a constructor",
  62. body : function ()
  63. {
  64. assert.throws(function (){
  65. new Array.prototype.findLast(() => {});
  66. }, TypeError)
  67. }
  68. },
  69. {
  70. name : "predicate call parameters",
  71. body : function ()
  72. {
  73. var arr = ["Mike", "Rick", "Leo"];
  74. var results = [];
  75. arr.findLast(function(kValue, k, O) {
  76. results.push(arguments);
  77. });
  78. assert.areEqual(results.length, 3);
  79. var result = results[0];
  80. assert.areEqual("Leo", result[0]);
  81. assert.areEqual(2, result[1]);
  82. assert.areEqual(arr, result[2]);
  83. assert.areEqual(3, result.length);
  84. result = results[1];
  85. assert.areEqual("Rick", result[0]);
  86. assert.areEqual(1, result[1]);
  87. assert.areEqual(arr, result[2]);
  88. assert.areEqual(3, result.length);
  89. result = results[2];
  90. assert.areEqual("Mike", result[0]);
  91. assert.areEqual(0, result[1]);
  92. assert.areEqual(arr, result[2]);
  93. assert.areEqual(3, result.length);
  94. }
  95. },
  96. {
  97. name : "predicate call this non strict",
  98. body : function ()
  99. {
  100. var result;
  101. [1].findLast(function(kValue, k, O) {
  102. result = this;
  103. });
  104. assert.areEqual(this, result);
  105. var o = {};
  106. [1].findLast(function() {
  107. result = this;
  108. }, o);
  109. assert.areEqual(o, result);
  110. }
  111. },
  112. {
  113. name : "predicate call this strict",
  114. body : function ()
  115. {
  116. "use strict";
  117. var result;
  118. [1].findLast(function(kValue, k, O) {
  119. result = this;
  120. });
  121. assert.areEqual(undefined, result);
  122. var o = {};
  123. [1].findLast(function() {
  124. result = this;
  125. }, o);
  126. assert.areEqual(o, result);
  127. }
  128. },
  129. {
  130. name : "predicate called for each array property",
  131. body : function ()
  132. {
  133. var arr = [undefined, , , "foo"];
  134. var called = 0;
  135. arr.findLast(function() {
  136. called++;
  137. });
  138. assert.areEqual(4, called);
  139. }
  140. },
  141. {
  142. name : "predicate is not callable throws",
  143. body : function ()
  144. {
  145. assert.throws(() => {
  146. [].findLast({});
  147. }, TypeError);
  148. assert.throws(() => {
  149. [].findLast(null);
  150. }, TypeError);
  151. assert.throws(() => {
  152. [].findLast(undefined);
  153. }, TypeError);
  154. assert.throws(() => {
  155. [].findLast(true);
  156. }, TypeError);
  157. assert.throws(() => {
  158. [].findLast(1);
  159. }, TypeError);
  160. assert.throws(() => {
  161. [].findLast("");
  162. }, TypeError);
  163. assert.throws(() => {
  164. [].findLast(1);
  165. }, TypeError);
  166. assert.throws(() => {
  167. [].findLast([]);
  168. }, TypeError);
  169. assert.throws(() => {
  170. [].findLast(/./);
  171. }, TypeError);
  172. }
  173. },
  174. {
  175. name : "predicate not called on empty array",
  176. body : function ()
  177. {
  178. var called = false;
  179. var predicate = function() {
  180. called = true;
  181. return true;
  182. };
  183. var result = [].findLast(predicate);
  184. assert.areEqual(undefined, result);
  185. assert.areEqual(false, called);
  186. }
  187. },
  188. {
  189. name : "return abrupt from predicate call",
  190. body : function ()
  191. {
  192. class TestError extends Error { }
  193. var predicate = function() {
  194. throw new TestError();
  195. };
  196. assert.throws(function() {
  197. [1].findLast(predicate);
  198. }, TestError);
  199. }
  200. },
  201. {
  202. name : "return abrupt from property",
  203. body : function ()
  204. {
  205. class TestError extends Error { }
  206. var o = {
  207. length: 1
  208. };
  209. Object.defineProperty(o, 0, {
  210. get: function() {
  211. throw new TestError();
  212. }
  213. });
  214. assert.throws(function() {
  215. [].findLast.call(o, function() {});
  216. }, TestError);
  217. }
  218. },
  219. {
  220. name : "return abrupt from this length as symbol",
  221. body : function ()
  222. {
  223. var o = {};
  224. o.length = Symbol(1);
  225. assert.throws(function() {
  226. [].findLast.call(o, function() {});
  227. }, TypeError);
  228. }
  229. },
  230. {
  231. name : "return abrupt from this length",
  232. body : function ()
  233. {
  234. class TestError extends Error { }
  235. var o1 = {};
  236. Object.defineProperty(o1, "length", {
  237. get: function() {
  238. throw new TestError();
  239. },
  240. configurable: true
  241. });
  242. assert.throws(function() {
  243. [].findLast.call(o1);
  244. }, TestError);
  245. var o2 = {
  246. length: {
  247. valueOf: function() {
  248. throw new TestError();
  249. }
  250. }
  251. };
  252. assert.throws(function() {
  253. [].findLast.call(o2);
  254. }, TestError);
  255. }
  256. },
  257. {
  258. name : "return abrupt from this",
  259. body : function ()
  260. {
  261. assert.throws(function() {
  262. Array.prototype.findLast.call(undefined, function() { });
  263. }, TypeError);
  264. assert.throws(function() {
  265. Array.prototype.findLast.call(null, function() { });
  266. }, TypeError);
  267. }
  268. },
  269. {
  270. name : "return found value predicate result is true",
  271. body : function ()
  272. {
  273. var arr = ["Shoes", "Car", "Bike"];
  274. var called = 0;
  275. var result = arr.findLast(function(val) {
  276. called++;
  277. return true;
  278. });
  279. assert.areEqual("Bike", result);
  280. assert.areEqual(1, called, "predicate was called once");
  281. called = 0;
  282. result = arr.findLast(function(val) {
  283. called++;
  284. return val === "Bike";
  285. });
  286. assert.areEqual(1, called, "predicate was called three times");
  287. assert.areEqual("Bike", result);
  288. called = 0;
  289. result = arr.findLast(function(val) {
  290. called++;
  291. return val === "Shoes";
  292. });
  293. assert.areEqual(3, called, "predicate was called three times");
  294. assert.areEqual("Shoes", result);
  295. result = arr.findLast(function(val) {
  296. return "string";
  297. });
  298. assert.areEqual("Bike", result, "coerced string");
  299. result = arr.findLast(function(val) {
  300. return {};
  301. });
  302. assert.areEqual("Bike", result, "coerced object");
  303. result = arr.findLast(function(val) {
  304. return Symbol("");
  305. });
  306. assert.areEqual("Bike", result, "coerced Symbol");
  307. result = arr.findLast(function(val) {
  308. return 1;
  309. });
  310. assert.areEqual("Bike", result, "coerced number");
  311. result = arr.findLast(function(val) {
  312. return -1;
  313. });
  314. assert.areEqual("Bike", result, "coerced negative number");
  315. }
  316. },
  317. {
  318. name : "return undefined if predicate returns false value",
  319. body : function ()
  320. {
  321. var arr = ["Shoes", "Car", "Bike"];
  322. var called = 0;
  323. var result = arr.findLast(function(val) {
  324. called++;
  325. return false;
  326. });
  327. assert.areEqual(3, called, "predicate was called three times");
  328. assert.areEqual(undefined, result);
  329. result = arr.findLast(function(val) {
  330. return "";
  331. });
  332. assert.areEqual(undefined, result, "coerced string");
  333. result = arr.findLast(function(val) {
  334. return undefined;
  335. });
  336. assert.areEqual(undefined, result, "coerced undefined");
  337. result = arr.findLast(function(val) {
  338. return null;
  339. });
  340. assert.areEqual(undefined, result, "coerced null");
  341. result = arr.findLast(function(val) {
  342. return 0;
  343. });
  344. assert.areEqual(undefined, result, "coerced 0");
  345. result = arr.findLast(function(val) {
  346. return NaN;
  347. });
  348. assert.areEqual(undefined, result, "coerced NaN");
  349. }
  350. },
  351. {
  352. name : "return last item",
  353. body : function ()
  354. {
  355. var arr = [ { value: "Shoes" }, { value: "Car" }, { value: "Shoes" }, { value: "Bike" } ];
  356. var called = 0;
  357. var result = arr.findLast(function (val) {
  358. called++;
  359. return val.value === "Shoes";
  360. });
  361. assert.areEqual("Shoes", result.value);
  362. assert.areEqual(arr[2], result);
  363. assert.areEqual(2, called);
  364. }
  365. },
  366. {
  367. name : "length limit and behavior",
  368. body : function () {
  369. var arrZero = [];
  370. var arrOne = [{ value: 1 }];
  371. var arrMax = [];
  372. arrMax.length = 2 ** 32 - 1;
  373. var maxResult = arrMax[2 ** 32 - 2] = { value: 1 };
  374. var result = arrZero.findLast(function (x) {
  375. return x.value === 1
  376. });
  377. assert.areEqual(undefined, result);
  378. result = arrOne.findLast(function (x) {
  379. return x.value === 1
  380. });
  381. assert.areEqual(arrOne[0], result);
  382. result = arrOne.findLast(function (x) {
  383. return x.value === 2
  384. });
  385. assert.areEqual(undefined, result);
  386. result = arrMax.findLast(function (x) {
  387. return x.value === 1
  388. });
  389. assert.areEqual(maxResult, result);
  390. }
  391. }
  392. ]
  393. testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });