diff --git a/CHANGELOG.md b/CHANGELOG.md index af1571d516dd..eb7f2c673fa6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ ## Changelog ##### Unreleased +- Added [`Array` find from last stage 1 proposal](https://github.com/tc39/proposal-array-find-from-last) + - `Array#findLast` + - `Array#findLastIndex` + - `%TypedArray%#findLast` + - `%TypedArray%#findLastIndex` - Dropped `ToLength` detection from array methods feature detection which could cause hanging FF11-21 and some versions of old WebKit, [#764](https://github.com/zloirock/core-js/issues/764) - Minified bundle from `core-js-bundle` uses `terser` instead of `uglify-js` diff --git a/README.md b/README.md index 2b613ecef2fd..29e89bd035a3 100644 --- a/README.md +++ b/README.md @@ -2419,10 +2419,8 @@ class [ [*CommonJS entry points:*](#commonjs-api) ``` core-js/proposals/array-filtering -core-js(-pure)/features/array/filter-out -core-js(-pure)/features/array/virtual/filter-out +core-js(-pure)/features/array(/virtual)/filter-out core-js(-pure)/features/typed-array/filter-out -core-js(-pure)/features/typed-array/virtual/filter-out ``` [*Examples*](http://es6.zloirock.ru/#log(%5B1%2C%202%2C%203%2C%204%2C%205%5D.filterOut(it%20%3D%3E%20it%20%25%202))%3B%20%2F%2F%20%3D%3E%20%5B2%2C%204%5D): ```js @@ -2438,8 +2436,7 @@ class Array { [*CommonJS entry points:*](#commonjs-api) ``` core-js/proposals/array-unique -core-js(-pure)/features/array/unique-by -core-js(-pure)/features/array/virtual/unique-by +core-js(-pure)/features/array(/virtual)/unique-by ``` [*Examples*](http://es6.zloirock.ru/#log(%5B1%2C%202%2C%203%2C%202%2C%201%5D.uniqueBy())%3B%20%20%2F%2F%20%5B1%2C%202%2C%203%5D%0A%0Aconst%20data%20%3D%20%5B%0A%20%20%7B%20id%3A%201%2C%20uid%3A%2010000%20%7D%2C%0A%20%20%7B%20id%3A%202%2C%20uid%3A%2010000%20%7D%2C%0A%20%20%7B%20id%3A%203%2C%20uid%3A%2010001%20%7D%0A%5D%3B%0A%0Alog(data.uniqueBy('uid'))%3B%20%2F%2F%20%3D%3E%20%5B%7B%20id%3A%201%2C%20uid%3A%2010000%20%7D%2C%20%7B%20id%3A%203%2C%20uid%3A%2010001%20%7D%5D%0A%0Alog(data.uniqueBy((%7B%20id%2C%20uid%20%7D)%20%3D%3E%20%60%24%7Bid%7D-%24%7Buid%7D%60))%3B%20%2F%2F%20%3D%3E%20%5B%7B%20id%3A%201%2C%20uid%3A%2010000%20%7D%2C%20%7B%20id%3A%202%2C%20uid%3A%2010000%20%7D%2C%20%7B%20id%3A%203%2C%20uid%3A%2010001%20%7D%5D): ```js @@ -2451,6 +2448,42 @@ core-js(-pure)/features/array/virtual/unique-by { id: 3, uid: 10001 } ].uniqueBy(it => it.id); // => [{ id: 1, uid: 10000 }, { id: 3, uid: 10001 }] ``` +##### [Array find from last](https://github.com/tc39/proposal-array-find-from-last)[⬆](#index) +Modules [`esnext.array.find-last`](https://github.com/zloirock/core-js/blob/v3.8.3/packages/core-js/modules/esnext.array.find-last.js), [`esnext.array.find-last-index`](https://github.com/zloirock/core-js/blob/v3.8.3/packages/core-js/modules/esnext.array.find-last-index.js), [`esnext.typed-array.find-last`](https://github.com/zloirock/core-js/blob/v3.8.3/packages/core-js/modules/esnext.typed-array.find-last.js) and [`esnext.typed-array.find-last-index`](https://github.com/zloirock/core-js/blob/v3.8.3/packages/core-js/modules/esnext.typed-array.find-last-index.js). +```js +class Array { + findLast(callbackfn: (value: any, index: number, target: any) => boolean, thisArg?: any): any; + findLastIndex(callbackfn: (value: any, index: number, target: any) => boolean, thisArg?: any): uint; +} + +class [ + Int8Array, + Uint8Array, + Uint8ClampedArray, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array, +] { + findLast(callbackfn: (value: any, index: number, target: %TypedArray%) => boolean, thisArg?: any): any; + findLastIndex(callbackfn: (value: any, index: number, target: %TypedArray%) => boolean, thisArg?: any): uint; +} +``` +[*CommonJS entry points:*](#commonjs-api) +``` +core-js/proposals/array-find-from-last +core-js(-pure)/features(/virtual)/array/find-last +core-js(-pure)/features(/virtual)/array/find-last-index +core-js(-pure)/features/typed-array/find-last +core-js(-pure)/features/typed-array/find-last-index +``` +[*Examples*](http://es6.zloirock.ru/#log(%5B1%2C%202%2C%203%2C%204%5D.findLast(it%20%3D%3E%20it%20%25%202))%3B%20%20%20%20%20%20%2F%2F%20%3D%3E%203%0Alog(%5B1%2C%202%2C%203%2C%204%5D.findLastIndex(it%20%3D%3E%20it%20%25%202))%3B%20%2F%2F%20%3D%3E%202): +```js +[1, 2, 3, 4].findLast(it => it % 2); // => 3 +[1, 2, 3, 4].findLastIndex(it => it % 2); // => 2 +```` #### Stage 0 proposals[⬆](#index) [*CommonJS entry points:*](#commonjs-api) diff --git a/packages/core-js-compat/src/data.js b/packages/core-js-compat/src/data.js index e316e085de87..90f0d2ea2f2b 100644 --- a/packages/core-js-compat/src/data.js +++ b/packages/core-js-compat/src/data.js @@ -1258,6 +1258,10 @@ const data = { }, 'esnext.array.filter-out': { }, + 'esnext.array.find-last': { + }, + 'esnext.array.find-last-index': { + }, 'esnext.array.is-template-object': { }, 'esnext.array.last-index': { @@ -1498,6 +1502,10 @@ const data = { }, 'esnext.typed-array.filter-out': { }, + 'esnext.typed-array.find-last': { + }, + 'esnext.typed-array.find-last-index': { + }, 'esnext.weak-map.delete-all': { }, 'esnext.weak-map.from': { diff --git a/packages/core-js-compat/src/modules-by-versions.js b/packages/core-js-compat/src/modules-by-versions.js index 83485ff63626..3f52e1c95e50 100644 --- a/packages/core-js-compat/src/modules-by-versions.js +++ b/packages/core-js-compat/src/modules-by-versions.js @@ -73,4 +73,10 @@ module.exports = { 'esnext.typed-array.at', 'esnext.typed-array.filter-out', ], + 3.9: [ + 'esnext.array.find-last', + 'esnext.array.find-last-index', + 'esnext.typed-array.find-last', + 'esnext.typed-array.find-last-index', + ], }; diff --git a/packages/core-js-pure/override/modules/esnext.typed-array.find-last-index.js b/packages/core-js-pure/override/modules/esnext.typed-array.find-last-index.js new file mode 100644 index 000000000000..8b1a393741c9 --- /dev/null +++ b/packages/core-js-pure/override/modules/esnext.typed-array.find-last-index.js @@ -0,0 +1 @@ +// empty diff --git a/packages/core-js-pure/override/modules/esnext.typed-array.find-last.js b/packages/core-js-pure/override/modules/esnext.typed-array.find-last.js new file mode 100644 index 000000000000..8b1a393741c9 --- /dev/null +++ b/packages/core-js-pure/override/modules/esnext.typed-array.find-last.js @@ -0,0 +1 @@ +// empty diff --git a/packages/core-js/features/array/find-last-index.js b/packages/core-js/features/array/find-last-index.js new file mode 100644 index 000000000000..70ba3a234fe6 --- /dev/null +++ b/packages/core-js/features/array/find-last-index.js @@ -0,0 +1,4 @@ +require('../../modules/esnext.array.find-last-index'); +var entryUnbind = require('../../internals/entry-unbind'); + +module.exports = entryUnbind('Array', 'findLastIndex'); diff --git a/packages/core-js/features/array/find-last.js b/packages/core-js/features/array/find-last.js new file mode 100644 index 000000000000..9d10c47d7d8d --- /dev/null +++ b/packages/core-js/features/array/find-last.js @@ -0,0 +1,4 @@ +require('../../modules/esnext.array.find-last'); +var entryUnbind = require('../../internals/entry-unbind'); + +module.exports = entryUnbind('Array', 'findLast'); diff --git a/packages/core-js/features/array/index.js b/packages/core-js/features/array/index.js index eecc4b31cde9..c02a55b56804 100644 --- a/packages/core-js/features/array/index.js +++ b/packages/core-js/features/array/index.js @@ -2,6 +2,8 @@ var parent = require('../../es/array'); require('../../modules/es.map'); require('../../modules/esnext.array.at'); require('../../modules/esnext.array.filter-out'); +require('../../modules/esnext.array.find-last'); +require('../../modules/esnext.array.find-last-index'); require('../../modules/esnext.array.is-template-object'); require('../../modules/esnext.array.last-item'); require('../../modules/esnext.array.last-index'); diff --git a/packages/core-js/features/array/virtual/find-last-index.js b/packages/core-js/features/array/virtual/find-last-index.js new file mode 100644 index 000000000000..748cf5f2c9ae --- /dev/null +++ b/packages/core-js/features/array/virtual/find-last-index.js @@ -0,0 +1,4 @@ +require('../../../modules/esnext.array.find-last-index'); +var entryVirtual = require('../../../internals/entry-virtual'); + +module.exports = entryVirtual('Array').findLastIndex; diff --git a/packages/core-js/features/array/virtual/find-last.js b/packages/core-js/features/array/virtual/find-last.js new file mode 100644 index 000000000000..ab4f4ef6329c --- /dev/null +++ b/packages/core-js/features/array/virtual/find-last.js @@ -0,0 +1,4 @@ +require('../../../modules/esnext.array.find-last'); +var entryVirtual = require('../../../internals/entry-virtual'); + +module.exports = entryVirtual('Array').findLast; diff --git a/packages/core-js/features/array/virtual/index.js b/packages/core-js/features/array/virtual/index.js index 6572f923dc93..f10b61a66662 100644 --- a/packages/core-js/features/array/virtual/index.js +++ b/packages/core-js/features/array/virtual/index.js @@ -1,6 +1,8 @@ var parent = require('../../../es/array/virtual'); require('../../../modules/esnext.array.at'); require('../../../modules/esnext.array.filter-out'); +require('../../../modules/esnext.array.find-last'); +require('../../../modules/esnext.array.find-last-index'); require('../../../modules/esnext.array.unique-by'); module.exports = parent; diff --git a/packages/core-js/features/instance/find-last-index.js b/packages/core-js/features/instance/find-last-index.js new file mode 100644 index 000000000000..a20b5526ed6e --- /dev/null +++ b/packages/core-js/features/instance/find-last-index.js @@ -0,0 +1,8 @@ +var findLastIndex = require('../array/virtual/find-last-index'); + +var ArrayPrototype = Array.prototype; + +module.exports = function (it) { + var own = it.findLastIndex; + return it === ArrayPrototype || (it instanceof Array && own === ArrayPrototype.findLastIndex) ? findLastIndex : own; +}; diff --git a/packages/core-js/features/instance/find-last.js b/packages/core-js/features/instance/find-last.js new file mode 100644 index 000000000000..bdf4b385d756 --- /dev/null +++ b/packages/core-js/features/instance/find-last.js @@ -0,0 +1,8 @@ +var findLast = require('../array/virtual/find-last'); + +var ArrayPrototype = Array.prototype; + +module.exports = function (it) { + var own = it.findLast; + return it === ArrayPrototype || (it instanceof Array && own === ArrayPrototype.findLast) ? findLast : own; +}; diff --git a/packages/core-js/features/typed-array/find-last-index.js b/packages/core-js/features/typed-array/find-last-index.js new file mode 100644 index 000000000000..096a3a3fe85a --- /dev/null +++ b/packages/core-js/features/typed-array/find-last-index.js @@ -0,0 +1 @@ +require('../../modules/esnext.typed-array.find-last-index'); diff --git a/packages/core-js/features/typed-array/find-last.js b/packages/core-js/features/typed-array/find-last.js new file mode 100644 index 000000000000..af9a272e2efa --- /dev/null +++ b/packages/core-js/features/typed-array/find-last.js @@ -0,0 +1 @@ +require('../../modules/esnext.typed-array.find-last'); diff --git a/packages/core-js/features/typed-array/index.js b/packages/core-js/features/typed-array/index.js index db032de1171f..65c33e2b7876 100644 --- a/packages/core-js/features/typed-array/index.js +++ b/packages/core-js/features/typed-array/index.js @@ -1,5 +1,7 @@ var parent = require('../../es/typed-array'); require('../../modules/esnext.typed-array.at'); require('../../modules/esnext.typed-array.filter-out'); +require('../../modules/esnext.typed-array.find-last'); +require('../../modules/esnext.typed-array.find-last-index'); module.exports = parent; diff --git a/packages/core-js/internals/array-iteration-from-last.js b/packages/core-js/internals/array-iteration-from-last.js new file mode 100644 index 000000000000..b42669e34cfc --- /dev/null +++ b/packages/core-js/internals/array-iteration-from-last.js @@ -0,0 +1,34 @@ +var bind = require('../internals/function-bind-context'); +var IndexedObject = require('../internals/indexed-object'); +var toObject = require('../internals/to-object'); +var toLength = require('../internals/to-length'); + +// `Array.prototype.{ findLast, findLastIndex }` methods implementation +var createMethod = function (TYPE) { + var IS_FIND_INDEX = TYPE == 6; + return function ($this, callbackfn, that) { + var O = toObject($this); + var self = IndexedObject(O); + var boundFunction = bind(callbackfn, that, 3); + var index = toLength(self.length); + var value, result; + while (index-- > 0) { + value = self[index]; + result = boundFunction(value, index, O); + if (result) switch (TYPE) { + case 5: return value; // find + case 6: return index; // findIndex + } + } + return IS_FIND_INDEX ? -1 : undefined; + }; +}; + +module.exports = { + // `Array.prototype.findLast` method + // https://github.com/tc39/proposal-array-find-from-last + findLast: createMethod(5), + // `Array.prototype.findLastIndex` method + // https://github.com/tc39/proposal-array-find-from-last + findLastIndex: createMethod(6) +}; diff --git a/packages/core-js/modules/esnext.array.find-last-index.js b/packages/core-js/modules/esnext.array.find-last-index.js new file mode 100644 index 000000000000..3a4809fb816e --- /dev/null +++ b/packages/core-js/modules/esnext.array.find-last-index.js @@ -0,0 +1,14 @@ +'use strict'; +var $ = require('../internals/export'); +var $findLastIndex = require('../internals/array-iteration-from-last').findLastIndex; +var addToUnscopables = require('../internals/add-to-unscopables'); + +// `Array.prototype.findLastIndex` method +// https://github.com/tc39/proposal-array-find-from-last +$({ target: 'Array', proto: true }, { + findLastIndex: function findLastIndex(callbackfn /* , that = undefined */) { + return $findLastIndex(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } +}); + +addToUnscopables('findLastIndex'); diff --git a/packages/core-js/modules/esnext.array.find-last.js b/packages/core-js/modules/esnext.array.find-last.js new file mode 100644 index 000000000000..aa21a4664fc5 --- /dev/null +++ b/packages/core-js/modules/esnext.array.find-last.js @@ -0,0 +1,14 @@ +'use strict'; +var $ = require('../internals/export'); +var $findLast = require('../internals/array-iteration-from-last').findLast; +var addToUnscopables = require('../internals/add-to-unscopables'); + +// `Array.prototype.findLast` method +// https://github.com/tc39/proposal-array-find-from-last +$({ target: 'Array', proto: true }, { + findLast: function findLast(callbackfn /* , that = undefined */) { + return $findLast(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } +}); + +addToUnscopables('findLast'); diff --git a/packages/core-js/modules/esnext.typed-array.find-last-index.js b/packages/core-js/modules/esnext.typed-array.find-last-index.js new file mode 100644 index 000000000000..03e89d334594 --- /dev/null +++ b/packages/core-js/modules/esnext.typed-array.find-last-index.js @@ -0,0 +1,12 @@ +'use strict'; +var ArrayBufferViewCore = require('../internals/array-buffer-view-core'); +var $findLastIndex = require('../internals/array-iteration-from-last').findLastIndex; + +var aTypedArray = ArrayBufferViewCore.aTypedArray; +var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod; + +// `%TypedArray%.prototype.findLastIndex` method +// https://github.com/tc39/proposal-array-find-from-last +exportTypedArrayMethod('findLastIndex', function findLastIndex(predicate /* , thisArg */) { + return $findLastIndex(aTypedArray(this), predicate, arguments.length > 1 ? arguments[1] : undefined); +}); diff --git a/packages/core-js/modules/esnext.typed-array.find-last.js b/packages/core-js/modules/esnext.typed-array.find-last.js new file mode 100644 index 000000000000..8d0a8ef99da6 --- /dev/null +++ b/packages/core-js/modules/esnext.typed-array.find-last.js @@ -0,0 +1,12 @@ +'use strict'; +var ArrayBufferViewCore = require('../internals/array-buffer-view-core'); +var $findLast = require('../internals/array-iteration-from-last').findLast; + +var aTypedArray = ArrayBufferViewCore.aTypedArray; +var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod; + +// `%TypedArray%.prototype.findLast` method +// https://github.com/tc39/proposal-array-find-from-last +exportTypedArrayMethod('findLast', function findLast(predicate /* , thisArg */) { + return $findLast(aTypedArray(this), predicate, arguments.length > 1 ? arguments[1] : undefined); +}); diff --git a/packages/core-js/proposals/array-find-from-last.js b/packages/core-js/proposals/array-find-from-last.js new file mode 100644 index 000000000000..c69078def0ee --- /dev/null +++ b/packages/core-js/proposals/array-find-from-last.js @@ -0,0 +1,5 @@ +// https://github.com/tc39/proposal-array-find-from-last/ +require('../modules/esnext.array.find-last'); +require('../modules/esnext.array.find-last-index'); +require('../modules/esnext.typed-array.find-last'); +require('../modules/esnext.typed-array.find-last-index'); diff --git a/packages/core-js/stage/1.js b/packages/core-js/stage/1.js index af1220a5e4dc..13e008813b72 100644 --- a/packages/core-js/stage/1.js +++ b/packages/core-js/stage/1.js @@ -1,4 +1,5 @@ require('../proposals/array-filtering'); +require('../proposals/array-find-from-last'); require('../proposals/array-last'); require('../proposals/array-unique'); require('../proposals/collection-methods'); diff --git a/tests/commonjs.js b/tests/commonjs.js index 3541faf103b3..fcb86bc4da72 100644 --- a/tests/commonjs.js +++ b/tests/commonjs.js @@ -85,6 +85,8 @@ for (PATH of ['core-js-pure', 'core-js']) { ok(load('features/array/fill')(Array(5), 2)[0] === 2); ok(load('features/array/find')([2, 3, 4], it => it % 2) === 3); ok(load('features/array/find-index')([2, 3, 4], it => it % 2) === 1); + ok(load('features/array/find-last')([1, 2, 3], it => it % 2) === 3); + ok(load('features/array/find-last-index')([1, 2, 3], it => it % 2) === 2); ok('next' in load('features/array/keys')([])); ok('next' in load('features/array/values')([])); ok(load('features/array/includes')([1, 2, 3], 2)); @@ -114,6 +116,8 @@ for (PATH of ['core-js-pure', 'core-js']) { ok(load('features/array/virtual/fill').call(Array(5), 2)[0] === 2); ok(load('features/array/virtual/find').call([2, 3, 4], it => it % 2) === 3); ok(load('features/array/virtual/find-index').call([2, 3, 4], it => it % 2) === 1); + ok(load('features/array/virtual/find-last').call([1, 2, 3], it => it % 2) === 3); + ok(load('features/array/virtual/find-last-index').call([1, 2, 3], it => it % 2) === 2); ok('next' in load('features/array/virtual/keys').call([])); ok('next' in load('features/array/virtual/values').call([])); ok(load('features/array/virtual/includes').call([1, 2, 3], 2)); @@ -958,13 +962,19 @@ for (PATH of ['core-js-pure', 'core-js']) { ok(typeof load('web/url') === 'function'); ok(typeof load('web/url-search-params') === 'function'); ok('setImmediate' in load('web')); + load('proposals/array-filtering'); + load('proposals/array-find-from-last'); load('proposals/array-is-template-object'); load('proposals/array-last'); + load('proposals/array-unique'); load('proposals/collection-methods'); load('proposals/collection-of-from'); load('proposals/efficient-64-bit-arithmetic'); load('proposals/global-this'); load('proposals/iterator-helpers'); + load('proposals/keys-composition'); + load('proposals/map-update-or-insert'); + load('proposals/map-upsert'); load('proposals/math-extensions'); load('proposals/math-signbit'); load('proposals/number-from-string'); @@ -977,15 +987,14 @@ for (PATH of ['core-js-pure', 'core-js']) { load('proposals/promise-try'); load('proposals/reflect-metadata'); load('proposals/relative-indexing-method'); - load('proposals/keys-composition'); load('proposals/seeded-random'); load('proposals/set-methods'); load('proposals/string-at'); load('proposals/string-code-points'); load('proposals/string-match-all'); load('proposals/string-replace-all'); - load('proposals/using-statement'); load('proposals/url'); + load('proposals/using-statement'); load('proposals'); ok(load('stage/4')); ok(load('stage/3')); @@ -1192,6 +1201,18 @@ for (PATH of ['core-js-pure', 'core-js']) { ok(typeof instanceFind([]) === 'function'); ok(instanceFind([]).call([1, 2, 3], it => it % 2) === 1); + const instanceFindLastIndex = load('features/instance/find-last-index'); + ok(typeof instanceFindLastIndex === 'function'); + ok(instanceFindLastIndex({}) === undefined); + ok(typeof instanceFindLastIndex([]) === 'function'); + ok(instanceFindLastIndex([]).call([1, 2, 3], it => it % 2) === 2); + + const instanceFindLast = load('features/instance/find-last'); + ok(typeof instanceFindLast === 'function'); + ok(instanceFindLast({}) === undefined); + ok(typeof instanceFindLast([]) === 'function'); + ok(instanceFindLast([]).call([1, 2, 3], it => it % 2) === 3); + let instanceFlags = load('features/instance/flags'); ok(typeof instanceFlags === 'function'); ok(instanceFlags({}) === undefined); @@ -1664,6 +1685,8 @@ load('features/typed-array/filter'); load('features/typed-array/filter-out'); load('features/typed-array/find'); load('features/typed-array/find-index'); +load('features/typed-array/find-last'); +load('features/typed-array/find-last-index'); load('features/typed-array/for-each'); load('features/typed-array/from'); load('features/typed-array/includes'); diff --git a/tests/compat/tests.js b/tests/compat/tests.js index 48dc73a18dda..b34a22656ac0 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -1082,6 +1082,12 @@ GLOBAL.tests = { 'esnext.array.filter-out': function () { return [].filterOut; }, + 'esnext.array.find-last': function () { + return [].findLast; + }, + 'esnext.array.find-last-index': function () { + return [].findLastIndex; + }, 'esnext.array.last-index': function () { return [1, 2, 3].lastIndex && Array.prototype[Symbol.unscopables].lastIndex; }, @@ -1425,6 +1431,12 @@ GLOBAL.tests = { 'esnext.typed-array.filter-out': function () { return Int8Array.prototype.filterOut; }, + 'esnext.typed-array.find-last': function () { + return Int8Array.prototype.findLast; + }, + 'esnext.typed-array.find-last-index': function () { + return Int8Array.prototype.findLastIndex; + }, 'esnext.weak-map.delete-all': function () { return WeakMap.prototype.deleteAll; }, diff --git a/tests/pure/esnext.array.find-last-index.js b/tests/pure/esnext.array.find-last-index.js new file mode 100644 index 000000000000..10d87eae87df --- /dev/null +++ b/tests/pure/esnext.array.find-last-index.js @@ -0,0 +1,36 @@ +import { STRICT } from '../helpers/constants'; + +import findLastIndex from 'core-js-pure/features/array/find-last-index'; + +QUnit.test('Array#findLastIndex', assert => { + assert.isFunction(findLastIndex); + const array = [1]; + const context = {}; + findLastIndex(array, function (value, key, that) { + assert.same(arguments.length, 3, 'correct number of callback arguments'); + assert.same(value, 1, 'correct value in callback'); + assert.same(key, 0, 'correct index in callback'); + assert.same(that, array, 'correct link to array in callback'); + assert.same(this, context, 'correct callback context'); + }, context); + assert.same(findLastIndex([{}, 2, NaN, 42, 1], it => !(it % 2)), 3); + assert.same(findLastIndex([{}, 2, NaN, 42, 1], it => it === 43), -1); + let values = ''; + let keys = ''; + findLastIndex([1, 2, 3], (value, key) => { + values += value; + keys += key; + }); + assert.same(values, '321'); + assert.same(keys, '210'); + if (STRICT) { + assert.throws(() => findLastIndex(null, 0), TypeError); + assert.throws(() => findLastIndex(undefined, 0), TypeError); + } + assert.notThrows(() => findLastIndex({ + length: -1, + 0: 1, + }, () => { + throw new Error(); + }) === -1, 'uses ToLength'); +}); diff --git a/tests/pure/esnext.array.find-last.js b/tests/pure/esnext.array.find-last.js new file mode 100644 index 000000000000..13c84e38307f --- /dev/null +++ b/tests/pure/esnext.array.find-last.js @@ -0,0 +1,36 @@ +import { STRICT } from '../helpers/constants'; + +import findLast from 'core-js-pure/features/array/find-last'; + +QUnit.test('Array#findLast', assert => { + assert.isFunction(findLast); + const array = [1]; + const context = {}; + findLast(array, function (value, key, that) { + assert.same(arguments.length, 3, 'correct number of callback arguments'); + assert.same(value, 1, 'correct value in callback'); + assert.same(key, 0, 'correct index in callback'); + assert.same(that, array, 'correct link to array in callback'); + assert.same(this, context, 'correct callback context'); + }, context); + assert.same(findLast([{}, 2, NaN, 42, 1], it => !(it % 2)), 42); + assert.same(findLast([{}, 2, NaN, 42, 1], it => it === 43), undefined); + let values = ''; + let keys = ''; + findLast([1, 2, 3], (value, key) => { + values += value; + keys += key; + }); + assert.same(values, '321'); + assert.same(keys, '210'); + if (STRICT) { + assert.throws(() => findLast(null, 0), TypeError); + assert.throws(() => findLast(undefined, 0), TypeError); + } + assert.notThrows(() => findLast({ + length: -1, + 0: 1, + }, () => { + throw new Error(); + }) === undefined, 'uses ToLength'); +}); diff --git a/tests/pure/index.js b/tests/pure/index.js index 1c7553b27993..4526a93f9a6c 100644 --- a/tests/pure/index.js +++ b/tests/pure/index.js @@ -145,6 +145,8 @@ import './es.weak-set'; QUnit.module('ESNext'); import './esnext.array.at'; import './esnext.array.filter-out'; +import './esnext.array.find-last'; +import './esnext.array.find-last-index'; import './esnext.array.is-template-object'; import './esnext.array.unique-by'; import './esnext.async-iterator.constructor'; diff --git a/tests/tests/esnext.array.find-last-index.js b/tests/tests/esnext.array.find-last-index.js new file mode 100644 index 000000000000..a0f0b9fd884c --- /dev/null +++ b/tests/tests/esnext.array.find-last-index.js @@ -0,0 +1,40 @@ +import { STRICT } from '../helpers/constants'; + +QUnit.test('Array#findLastIndex', assert => { + const { findLastIndex } = Array.prototype; + assert.isFunction(findLastIndex); + assert.arity(findLastIndex, 1); + assert.name(findLastIndex, 'findLastIndex'); + assert.looksNative(findLastIndex); + assert.nonEnumerable(Array.prototype, 'findLastIndex'); + const array = [1]; + const context = {}; + array.findLastIndex(function (value, key, that) { + assert.same(arguments.length, 3, 'correct number of callback arguments'); + assert.same(value, 1, 'correct value in callback'); + assert.same(key, 0, 'correct index in callback'); + assert.same(that, array, 'correct link to array in callback'); + assert.same(this, context, 'correct callback context'); + }, context); + assert.same([{}, 2, NaN, 42, 1].findLastIndex(it => !(it % 2)), 3); + assert.same([{}, 2, NaN, 42, 1].findLastIndex(it => it === 43), -1); + let values = ''; + let keys = ''; + [1, 2, 3].findLastIndex((value, key) => { + values += value; + keys += key; + }); + assert.same(values, '321'); + assert.same(keys, '210'); + if (STRICT) { + assert.throws(() => findLastIndex.call(null, 0), TypeError); + assert.throws(() => findLastIndex.call(undefined, 0), TypeError); + } + assert.notThrows(() => findLastIndex.call({ + length: -1, + 0: 1, + }, () => { + throw new Error(); + }) === -1, 'uses ToLength'); + assert.ok('findLastIndex' in Array.prototype[Symbol.unscopables], 'In Array#@@unscopables'); +}); diff --git a/tests/tests/esnext.array.find-last.js b/tests/tests/esnext.array.find-last.js new file mode 100644 index 000000000000..0fe7fdd53800 --- /dev/null +++ b/tests/tests/esnext.array.find-last.js @@ -0,0 +1,40 @@ +import { STRICT } from '../helpers/constants'; + +QUnit.test('Array#findLast', assert => { + const { findLast } = Array.prototype; + assert.isFunction(findLast); + assert.arity(findLast, 1); + assert.name(findLast, 'findLast'); + assert.looksNative(findLast); + assert.nonEnumerable(Array.prototype, 'findLast'); + const array = [1]; + const context = {}; + array.findLast(function (value, key, that) { + assert.same(arguments.length, 3, 'correct number of callback arguments'); + assert.same(value, 1, 'correct value in callback'); + assert.same(key, 0, 'correct index in callback'); + assert.same(that, array, 'correct link to array in callback'); + assert.same(this, context, 'correct callback context'); + }, context); + assert.same([{}, 2, NaN, 42, 1].findLast(it => !(it % 2)), 42); + assert.same([{}, 2, NaN, 42, 1].findLast(it => it === 43), undefined); + let values = ''; + let keys = ''; + [1, 2, 3].findLast((value, key) => { + values += value; + keys += key; + }); + assert.same(values, '321'); + assert.same(keys, '210'); + if (STRICT) { + assert.throws(() => findLast.call(null, 0), TypeError); + assert.throws(() => findLast.call(undefined, 0), TypeError); + } + assert.notThrows(() => findLast.call({ + length: -1, + 0: 1, + }, () => { + throw new Error(); + }) === undefined, 'uses ToLength'); + assert.ok('find' in Array.prototype[Symbol.unscopables], 'In Array#@@unscopables'); +}); diff --git a/tests/tests/esnext.typed-array.find-last-index.js b/tests/tests/esnext.typed-array.find-last-index.js new file mode 100644 index 000000000000..a7176ccb8eb8 --- /dev/null +++ b/tests/tests/esnext.typed-array.find-last-index.js @@ -0,0 +1,33 @@ +import { DESCRIPTORS, GLOBAL, TYPED_ARRAYS } from '../helpers/constants'; + +if (DESCRIPTORS) QUnit.test('%TypedArrayPrototype%.findLastIndex', assert => { + // we can't implement %TypedArrayPrototype% in all engines, so run all tests for each typed array constructor + for (const name in TYPED_ARRAYS) { + const TypedArray = GLOBAL[name]; + const { findLastIndex } = TypedArray.prototype; + assert.isFunction(findLastIndex, `${ name }::findLastIndex is function`); + assert.arity(findLastIndex, 1, `${ name }::findLastIndex arity is 1`); + assert.name(findLastIndex, 'findLastIndex', `${ name }::findLastIndex name is 'findLastIndex'`); + assert.looksNative(findLastIndex, `${ name }::findLastIndex looks native`); + const array = new TypedArray([1]); + const context = {}; + array.findLastIndex(function (value, key, that) { + assert.same(arguments.length, 3, 'correct number of callback arguments'); + assert.same(value, 1, 'correct value in callback'); + assert.same(key, 0, 'correct index in callback'); + assert.same(that, array, 'correct link to array in callback'); + assert.same(this, context, 'correct callback context'); + }, context); + assert.same(new TypedArray([1, 2, 3, 2, 1]).findLastIndex(it => !(it % 2)), 3); + assert.same(new TypedArray([1, 2, 3, 2, 1]).findLastIndex(it => it === 4), -1); + let values = ''; + let keys = ''; + new TypedArray([1, 2, 3]).findLastIndex((value, key) => { + values += value; + keys += key; + }); + assert.same(values, '321'); + assert.same(keys, '210'); + assert.throws(() => findLastIndex.call([0], () => { /* empty */ }), "isn't generic"); + } +}); diff --git a/tests/tests/esnext.typed-array.find-last.js b/tests/tests/esnext.typed-array.find-last.js new file mode 100644 index 000000000000..8c429ab78db1 --- /dev/null +++ b/tests/tests/esnext.typed-array.find-last.js @@ -0,0 +1,33 @@ +import { DESCRIPTORS, GLOBAL, TYPED_ARRAYS } from '../helpers/constants'; + +if (DESCRIPTORS) QUnit.test('%TypedArrayPrototype%.findLast', assert => { + // we can't implement %TypedArrayPrototype% in all engines, so run all tests for each typed array constructor + for (const name in TYPED_ARRAYS) { + const TypedArray = GLOBAL[name]; + const { findLast } = TypedArray.prototype; + assert.isFunction(findLast, `${ name }::findLast is function`); + assert.arity(findLast, 1, `${ name }::findLast arity is 1`); + assert.name(findLast, 'findLast', `${ name }::findLast name is 'findLast'`); + assert.looksNative(findLast, `${ name }::findLast looks native`); + const array = new TypedArray([1]); + const context = {}; + array.findLast(function (value, key, that) { + assert.same(arguments.length, 3, 'correct number of callback arguments'); + assert.same(value, 1, 'correct value in callback'); + assert.same(key, 0, 'correct index in callback'); + assert.same(that, array, 'correct link to array in callback'); + assert.same(this, context, 'correct callback context'); + }, context); + assert.same(new TypedArray([1, 2, 3, 4, 5]).findLast(it => !(it % 2)), 4); + assert.same(new TypedArray([1, 2, 3, 4, 5]).findLast(it => it === 6), undefined); + let values = ''; + let keys = ''; + new TypedArray([1, 2, 3]).findLast((value, key) => { + values += value; + keys += key; + }); + assert.same(values, '321'); + assert.same(keys, '210'); + assert.throws(() => findLast.call([0], () => { /* empty */ }), "isn't generic"); + } +}); diff --git a/tests/tests/index.js b/tests/tests/index.js index ecda17caa6d0..150a24f8563d 100644 --- a/tests/tests/index.js +++ b/tests/tests/index.js @@ -197,9 +197,11 @@ import './es.weak-map'; import './es.weak-set'; QUnit.module('ESNext'); +import './esnext.array.at'; import './esnext.array.filter-out'; +import './esnext.array.find-last'; +import './esnext.array.find-last-index'; import './esnext.array.is-template-object'; -import './esnext.array.at'; import './esnext.array.last-item'; import './esnext.array.last-index'; import './esnext.array.unique-by'; @@ -312,6 +314,8 @@ import './esnext.symbol.pattern-match'; import './esnext.symbol.replace-all'; import './esnext.typed-array.at'; import './esnext.typed-array.filter-out'; +import './esnext.typed-array.find-last'; +import './esnext.typed-array.find-last-index'; import './esnext.weak-map.delete-all'; import './esnext.weak-map.from'; import './esnext.weak-map.of';