From 9b1ea68b6147d95be9c807244ac4131aac5c41c1 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Mon, 16 Nov 2020 01:23:15 +0700 Subject: [PATCH 1/8] add proposal for a `.item()` method on all the built-in indexables https://github.com/tc39/proposal-item-method --- README.md | 39 ++++++++++++++++++- packages/core-js-compat/src/data.js | 6 +++ .../modules/esnext.typed-array.item.js | 1 + packages/core-js/features/array/index.js | 1 + packages/core-js/features/array/item.js | 4 ++ .../core-js/features/array/virtual/index.js | 1 + .../core-js/features/array/virtual/item.js | 4 ++ packages/core-js/features/instance/item.js | 13 +++++++ packages/core-js/features/string/index.js | 1 + packages/core-js/features/string/item.js | 4 ++ .../core-js/features/string/virtual/index.js | 1 + .../core-js/features/string/virtual/item.js | 4 ++ .../core-js/features/typed-array/index.js | 1 + packages/core-js/features/typed-array/item.js | 1 + packages/core-js/modules/esnext.array.item.js | 20 ++++++++++ .../core-js/modules/esnext.string.item.js | 17 ++++++++ .../modules/esnext.typed-array.item.js | 17 ++++++++ packages/core-js/proposals/item-method.js | 4 ++ packages/core-js/stage/3.js | 1 + tests/commonjs.js | 13 +++++++ tests/compat/tests.js | 9 +++++ tests/pure/esnext.array.item.js | 27 +++++++++++++ tests/pure/esnext.string.item.js | 26 +++++++++++++ tests/pure/index.js | 2 + tests/tests/esnext.array.item.js | 30 ++++++++++++++ tests/tests/esnext.string.item.js | 29 ++++++++++++++ tests/tests/esnext.typed-array.item.js | 30 ++++++++++++++ tests/tests/index.js | 3 ++ 28 files changed, 308 insertions(+), 1 deletion(-) create mode 100644 packages/core-js-pure/override/modules/esnext.typed-array.item.js create mode 100644 packages/core-js/features/array/item.js create mode 100644 packages/core-js/features/array/virtual/item.js create mode 100644 packages/core-js/features/instance/item.js create mode 100644 packages/core-js/features/string/item.js create mode 100644 packages/core-js/features/string/virtual/item.js create mode 100644 packages/core-js/features/typed-array/item.js create mode 100644 packages/core-js/modules/esnext.array.item.js create mode 100644 packages/core-js/modules/esnext.string.item.js create mode 100644 packages/core-js/modules/esnext.typed-array.item.js create mode 100644 packages/core-js/proposals/item-method.js create mode 100644 tests/pure/esnext.array.item.js create mode 100644 tests/pure/esnext.string.item.js create mode 100644 tests/tests/esnext.array.item.js create mode 100644 tests/tests/esnext.string.item.js create mode 100644 tests/tests/esnext.typed-array.item.js diff --git a/README.md b/README.md index 9a2794f4cad4..71525ab7e61e 100644 --- a/README.md +++ b/README.md @@ -1778,7 +1778,44 @@ Promise.any([ core-js(-pure)/stage/3 ``` -None. +##### [`.item()` method on all the built-in indexables](https://github.com/tc39/proposal-item-method) +Modules [`esnext.array.item`](https://github.com/zloirock/core-js/blob/v3.7.0/packages/core-js/modules/esnext.array.item.js), [`esnext.string.item`](https://github.com/zloirock/core-js/blob/v3.7.0/packages/core-js/modules/esnext.string.item.js) and [`esnext.typed-array.item`](https://github.com/zloirock/core-js/blob/v3.7.0/packages/core-js/modules/esnext.typed-array.item.js) +```js +class Array { + item(index: int): any; +} + +class String { + item(index: int): string | undefined; +} + +class [ + Int8Array, + Uint8Array, + Uint8ClampedArray, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array, +] { + item(index: int): any; +} +``` +[*CommonJS entry points:*](#commonjs-api) +``` +core-js/proposals/item-method +core-js(-pure)/features/array/item +core-js(-pure)/features/string/item +core-js(-pure)/features/typed-array/item +``` +[*Examples*](http://es6.zloirock.ru/#log(%5B1%2C%202%2C%203%5D.item(1))%3B%20%20%2F%2F%20%3D%3E%202%0Alog(%5B1%2C%202%2C%203%5D.item(-1))%3B%20%2F%2F%20%3D%3E%203%0Alog('123'.item(-1))%3B%20%20%20%20%20%2F%2F%20%3D%3E%20'3'): +```js +[1, 2, 3].item(1); // => 2 +[1, 2, 3].item(-1); // => 3 +'123'.item(-1); // => '3' +``` #### Stage 2 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 a604eaf6ab27..eba25e7040ba 100644 --- a/packages/core-js-compat/src/data.js +++ b/packages/core-js-compat/src/data.js @@ -1258,6 +1258,8 @@ const data = { }, 'esnext.array.is-template-object': { }, + 'esnext.array.item': { + }, 'esnext.array.last-index': { }, 'esnext.array.last-item': { @@ -1478,6 +1480,8 @@ const data = { }, 'esnext.string.code-points': { }, + 'esnext.string.item': { + }, // TODO: Remove from `core-js@4` 'esnext.string.match-all': null, 'esnext.string.replace-all': null, @@ -1493,6 +1497,8 @@ const data = { 'esnext.symbol.replace-all': { }, 'esnext.typed-array.filter-out': { + } + 'esnext.typed-array.item': { }, 'esnext.weak-map.delete-all': { }, diff --git a/packages/core-js-pure/override/modules/esnext.typed-array.item.js b/packages/core-js-pure/override/modules/esnext.typed-array.item.js new file mode 100644 index 000000000000..8b1a393741c9 --- /dev/null +++ b/packages/core-js-pure/override/modules/esnext.typed-array.item.js @@ -0,0 +1 @@ +// empty diff --git a/packages/core-js/features/array/index.js b/packages/core-js/features/array/index.js index 150190dffd15..28ed5ae2699b 100644 --- a/packages/core-js/features/array/index.js +++ b/packages/core-js/features/array/index.js @@ -2,6 +2,7 @@ var parent = require('../../es/array'); require('../../modules/es.map'); require('../../modules/esnext.array.filter-out'); require('../../modules/esnext.array.is-template-object'); +require('../../modules/esnext.array.item'); require('../../modules/esnext.array.last-item'); require('../../modules/esnext.array.last-index'); require('../../modules/esnext.array.unique-by'); diff --git a/packages/core-js/features/array/item.js b/packages/core-js/features/array/item.js new file mode 100644 index 000000000000..dba4d5036b02 --- /dev/null +++ b/packages/core-js/features/array/item.js @@ -0,0 +1,4 @@ +require('../../modules/esnext.array.item'); +var entryUnbind = require('../../internals/entry-unbind'); + +module.exports = entryUnbind('Array', 'item'); diff --git a/packages/core-js/features/array/virtual/index.js b/packages/core-js/features/array/virtual/index.js index cb6a41868695..86150f97bb56 100644 --- a/packages/core-js/features/array/virtual/index.js +++ b/packages/core-js/features/array/virtual/index.js @@ -1,4 +1,5 @@ var parent = require('../../../es/array/virtual'); require('../../../modules/esnext.array.filter-out'); +require('../../../modules/esnext.array.item'); module.exports = parent; diff --git a/packages/core-js/features/array/virtual/item.js b/packages/core-js/features/array/virtual/item.js new file mode 100644 index 000000000000..0575cc53249b --- /dev/null +++ b/packages/core-js/features/array/virtual/item.js @@ -0,0 +1,4 @@ +require('../../../modules/esnext.array.item'); +var entryVirtual = require('../../../internals/entry-virtual'); + +module.exports = entryVirtual('Array').item; diff --git a/packages/core-js/features/instance/item.js b/packages/core-js/features/instance/item.js new file mode 100644 index 000000000000..2cc40a1748f3 --- /dev/null +++ b/packages/core-js/features/instance/item.js @@ -0,0 +1,13 @@ +var arrayItem = require('../array/virtual/item'); +var stringItem = require('../string/virtual/item'); + +var ArrayPrototype = Array.prototype; +var StringPrototype = String.prototype; + +module.exports = function (it) { + var own = it.item; + if (it === ArrayPrototype || (it instanceof Array && own === ArrayPrototype.item)) return arrayItem; + if (typeof it === 'string' || it === StringPrototype || (it instanceof String && own === StringPrototype.item)) { + return stringItem; + } return own; +}; diff --git a/packages/core-js/features/string/index.js b/packages/core-js/features/string/index.js index 7c7f167cf834..189cbfed791f 100644 --- a/packages/core-js/features/string/index.js +++ b/packages/core-js/features/string/index.js @@ -1,6 +1,7 @@ var parent = require('../../es/string'); require('../../modules/esnext.string.at'); require('../../modules/esnext.string.code-points'); +require('../../modules/esnext.string.item'); // TODO: remove from `core-js@4` require('../../modules/esnext.string.match-all'); require('../../modules/esnext.string.replace-all'); diff --git a/packages/core-js/features/string/item.js b/packages/core-js/features/string/item.js new file mode 100644 index 000000000000..33bd7de301ca --- /dev/null +++ b/packages/core-js/features/string/item.js @@ -0,0 +1,4 @@ +require('../../modules/esnext.string.item'); +var entryUnbind = require('../../internals/entry-unbind'); + +module.exports = entryUnbind('String', 'item'); diff --git a/packages/core-js/features/string/virtual/index.js b/packages/core-js/features/string/virtual/index.js index 50044779e648..8a88cfb10d7e 100644 --- a/packages/core-js/features/string/virtual/index.js +++ b/packages/core-js/features/string/virtual/index.js @@ -1,6 +1,7 @@ var parent = require('../../../es/string/virtual'); require('../../../modules/esnext.string.at'); require('../../../modules/esnext.string.code-points'); +require('../../../modules/esnext.string.item'); // TODO: remove from `core-js@4` require('../../../modules/esnext.string.match-all'); require('../../../modules/esnext.string.replace-all'); diff --git a/packages/core-js/features/string/virtual/item.js b/packages/core-js/features/string/virtual/item.js new file mode 100644 index 000000000000..2db37dfa3b82 --- /dev/null +++ b/packages/core-js/features/string/virtual/item.js @@ -0,0 +1,4 @@ +require('../../../modules/esnext.string.item'); +var entryVirtual = require('../../../internals/entry-virtual'); + +module.exports = entryVirtual('String').item; diff --git a/packages/core-js/features/typed-array/index.js b/packages/core-js/features/typed-array/index.js index 4ac587fca23a..a760207eae6b 100644 --- a/packages/core-js/features/typed-array/index.js +++ b/packages/core-js/features/typed-array/index.js @@ -1,4 +1,5 @@ var parent = require('../../es/typed-array'); require('../../modules/esnext.typed-array.filter-out'); +require('../../modules/esnext.typed-array.item'); module.exports = parent; diff --git a/packages/core-js/features/typed-array/item.js b/packages/core-js/features/typed-array/item.js new file mode 100644 index 000000000000..fac1053f5289 --- /dev/null +++ b/packages/core-js/features/typed-array/item.js @@ -0,0 +1 @@ +require('../../modules/esnext.typed-array.item'); diff --git a/packages/core-js/modules/esnext.array.item.js b/packages/core-js/modules/esnext.array.item.js new file mode 100644 index 000000000000..b3308f570791 --- /dev/null +++ b/packages/core-js/modules/esnext.array.item.js @@ -0,0 +1,20 @@ +'use strict'; +var $ = require('../internals/export'); +var toObject = require('../internals/to-object'); +var toLength = require('../internals/to-length'); +var toInteger = require('../internals/to-integer'); +var addToUnscopables = require('../internals/add-to-unscopables'); + +// `Array.prototype.item` method +// https://github.com/tc39/proposal-item-method +$({ target: 'Array', proto: true }, { + item: function item(index) { + var O = toObject(this); + var len = toLength(O.length); + var relativeIndex = toInteger(index); + var k = relativeIndex >= 0 ? relativeIndex : len + relativeIndex; + return (k < 0 || k >= len) ? undefined : O[k]; + } +}); + +addToUnscopables('item'); diff --git a/packages/core-js/modules/esnext.string.item.js b/packages/core-js/modules/esnext.string.item.js new file mode 100644 index 000000000000..2a008ea0051f --- /dev/null +++ b/packages/core-js/modules/esnext.string.item.js @@ -0,0 +1,17 @@ +'use strict'; +var $ = require('../internals/export'); +var requireObjectCoercible = require('../internals/require-object-coercible'); +var toLength = require('../internals/to-length'); +var toInteger = require('../internals/to-integer'); + +// `String.prototype.item` method +// https://github.com/tc39/proposal-item-method +$({ target: 'String', proto: true }, { + item: function item(index) { + var S = String(requireObjectCoercible(this)); + var len = toLength(S.length); + var relativeIndex = toInteger(index); + var k = relativeIndex >= 0 ? relativeIndex : len + relativeIndex; + return (k < 0 || k >= len) ? undefined : S.charAt(k); + } +}); diff --git a/packages/core-js/modules/esnext.typed-array.item.js b/packages/core-js/modules/esnext.typed-array.item.js new file mode 100644 index 000000000000..aa7fc140e760 --- /dev/null +++ b/packages/core-js/modules/esnext.typed-array.item.js @@ -0,0 +1,17 @@ +'use strict'; +var ArrayBufferViewCore = require('../internals/array-buffer-view-core'); +var toLength = require('../internals/to-length'); +var toInteger = require('../internals/to-integer'); + +var aTypedArray = ArrayBufferViewCore.aTypedArray; +var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod; + +// `%TypedArray%.prototype.item` method +// https://github.com/tc39/proposal-item-method +exportTypedArrayMethod('item', function item(index) { + var O = aTypedArray(this); + var len = toLength(O.length); + var relativeIndex = toInteger(index); + var k = relativeIndex >= 0 ? relativeIndex : len + relativeIndex; + return (k < 0 || k >= len) ? undefined : O[k]; +}); diff --git a/packages/core-js/proposals/item-method.js b/packages/core-js/proposals/item-method.js new file mode 100644 index 000000000000..124ec97f661b --- /dev/null +++ b/packages/core-js/proposals/item-method.js @@ -0,0 +1,4 @@ +// https://github.com/tc39/proposal-item-method +require('../modules/esnext.array.item'); +require('../modules/esnext.string.item'); +require('../modules/esnext.typed-array.item'); diff --git a/packages/core-js/stage/3.js b/packages/core-js/stage/3.js index 17c9a4db1172..71cbae04d693 100644 --- a/packages/core-js/stage/3.js +++ b/packages/core-js/stage/3.js @@ -1,3 +1,4 @@ +require('../proposals/item-method'); var parent = require('./4'); module.exports = parent; diff --git a/tests/commonjs.js b/tests/commonjs.js index c235c83f621f..566da4d04179 100644 --- a/tests/commonjs.js +++ b/tests/commonjs.js @@ -71,6 +71,7 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) { ok(typeof load('features/array/filter-out') === 'function'); ok(typeof load('features/array/flat') === 'function'); ok(typeof load('features/array/flat-map') === 'function'); + ok(load('features/array/item')([1, 2, 3], -2) === 2); ok(typeof load('features/array/some') === 'function'); ok(typeof load('features/array/every') === 'function'); ok(typeof load('features/array/reduce') === 'function'); @@ -102,6 +103,7 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) { ok(typeof load('features/array/virtual/filter-out') === 'function'); ok(typeof load('features/array/virtual/flat') === 'function'); ok(typeof load('features/array/virtual/flat-map') === 'function'); + ok(load('features/array/virtual/item').call([1, 2, 3], -2) === 2); ok(typeof load('features/array/virtual/some') === 'function'); ok(typeof load('features/array/virtual/every') === 'function'); ok(typeof load('features/array/virtual/reduce') === 'function'); @@ -210,6 +212,7 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) { ok(load('features/string/code-point-at')('a', 0) === 97); ok(load('features/string/ends-with')('qwe', 'we')); ok(load('features/string/includes')('qwe', 'w')); + ok(load('features/string/item')('123', -2) === '2'); ok(load('features/string/repeat')('q', 3) === 'qqq'); ok(load('features/string/starts-with')('qwe', 'qw')); ok(typeof load('features/string/anchor') === 'function'); @@ -239,6 +242,7 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) { ok(load('features/string/virtual/code-point-at').call('a', 0) === 97); ok(load('features/string/virtual/ends-with').call('qwe', 'we')); ok(load('features/string/virtual/includes').call('qwe', 'w')); + ok(load('features/string/virtual/item').call('123', -2) === '2'); ok(load('features/string/virtual/repeat').call('q', 3) === 'qqq'); ok(load('features/string/virtual/starts-with').call('qwe', 'qw')); ok(typeof load('features/string/virtual/anchor') === 'function'); @@ -1270,6 +1274,14 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) { ok(instanceIncludes([]).call([1, 2, 3], 2)); ok(instanceIncludes('').call('123', '2')); + const instanceItem = load('features/instance/item'); + ok(typeof instanceItem === 'function'); + ok(instanceItem({}) === undefined); + ok(typeof instanceItem([]) === 'function'); + ok(typeof instanceItem('') === 'function'); + ok(instanceItem([]).call([1, 2, 3], 2) === 3); + ok(instanceItem('').call('123', 2) === '3'); + let instanceIndexOf = load('features/instance/index-of'); ok(typeof instanceIndexOf === 'function'); ok(instanceIndexOf({}) === undefined); @@ -1665,6 +1677,7 @@ load('features/typed-array/for-each'); load('features/typed-array/from'); load('features/typed-array/includes'); load('features/typed-array/index-of'); +load('features/typed-array/item'); load('features/typed-array/iterator'); load('features/typed-array/join'); load('features/typed-array/keys'); diff --git a/tests/compat/tests.js b/tests/compat/tests.js index df59e89f0f1e..8d2d26261b0f 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -1102,6 +1102,9 @@ GLOBAL.tests = { }], 'esnext.array.filter-out': function () { return [].filterOut; + } + 'esnext.array.item': function () { + return [].item; }, 'esnext.array.last-index': function () { return [1, 2, 3].lastIndex && Array.prototype[Symbol.unscopables].lastIndex; @@ -1427,6 +1430,9 @@ GLOBAL.tests = { 'esnext.string.code-points': function () { return String.prototype.codePoints; }, + 'esnext.string.item': function () { + return ''.item; + }, 'esnext.symbol.dispose': function () { return Symbol.dispose; }, @@ -1442,6 +1448,9 @@ GLOBAL.tests = { }, 'esnext.typed-array.filter-out': function () { return Int8Array.prototype.filterOut; + } + 'esnext.typed-array.item': function () { + return Int8Array.prototype.item; }, 'esnext.weak-map.delete-all': function () { return WeakMap.prototype.deleteAll; diff --git a/tests/pure/esnext.array.item.js b/tests/pure/esnext.array.item.js new file mode 100644 index 000000000000..71a9b97c1dfd --- /dev/null +++ b/tests/pure/esnext.array.item.js @@ -0,0 +1,27 @@ +import { STRICT } from '../helpers/constants'; + +import item from 'core-js-pure/features/array/item'; + +QUnit.test('Array#item', assert => { + assert.isFunction(item); + assert.same(1, item([1, 2, 3], 0)); + assert.same(2, item([1, 2, 3], 1)); + assert.same(3, item([1, 2, 3], 2)); + assert.same(undefined, item([1, 2, 3], 3)); + assert.same(3, item([1, 2, 3], -1)); + assert.same(2, item([1, 2, 3], -2)); + assert.same(1, item([1, 2, 3], -3)); + assert.same(undefined, item([1, 2, 3], -4)); + assert.same(1, item([1, 2, 3], 0.4)); + assert.same(1, item([1, 2, 3], 0.5)); + assert.same(1, item([1, 2, 3], 0.6)); + assert.same(1, item([1], NaN)); + assert.same(1, item([1])); + assert.same(1, item([1, 2, 3], -0)); + assert.same(undefined, item(Array(1), 0)); + assert.same(1, item({ 0: 1, length: 1 }, 0)); + if (STRICT) { + assert.throws(() => item(null, 0), TypeError); + assert.throws(() => item(undefined, 0), TypeError); + } +}); diff --git a/tests/pure/esnext.string.item.js b/tests/pure/esnext.string.item.js new file mode 100644 index 000000000000..062f323e5645 --- /dev/null +++ b/tests/pure/esnext.string.item.js @@ -0,0 +1,26 @@ +import { STRICT } from '../helpers/constants'; + +import item from 'core-js-pure/features/string/item'; + +QUnit.test('String#item', assert => { + assert.isFunction(item); + assert.same('1', item('123', 0)); + assert.same('2', item('123', 1)); + assert.same('3', item('123', 2)); + assert.same(undefined, item('123', 3)); + assert.same('3', item('123', -1)); + assert.same('2', item('123', -2)); + assert.same('1', item('123', -3)); + assert.same(undefined, item('123', -4)); + assert.same('1', item('123', 0.4)); + assert.same('1', item('123', 0.5)); + assert.same('1', item('123', 0.6)); + assert.same('1', item('1', NaN)); + assert.same('1', item('1')); + assert.same('1', item('123', -0)); + assert.same('1', item({ toString() { return '123'; } }, 0)); + if (STRICT) { + assert.throws(() => item(null, 0), TypeError); + assert.throws(() => item(undefined, 0), TypeError); + } +}); diff --git a/tests/pure/index.js b/tests/pure/index.js index 1aa7700a15d3..f4d05b02a4a8 100644 --- a/tests/pure/index.js +++ b/tests/pure/index.js @@ -144,6 +144,7 @@ import './es.weak-set'; QUnit.module('ESNext'); import './esnext.array.filter-out'; +import './esnext.array.item'; import './esnext.array.is-template-object'; import './esnext.array.unique-by'; import './esnext.async-iterator.constructor'; @@ -246,6 +247,7 @@ import './esnext.set.symmetric-difference'; import './esnext.set.union'; import './esnext.string.at'; import './esnext.string.code-points'; +import './esnext.string.item'; import './esnext.symbol.async-dispose'; import './esnext.symbol.dispose'; import './esnext.symbol.observable'; diff --git a/tests/tests/esnext.array.item.js b/tests/tests/esnext.array.item.js new file mode 100644 index 000000000000..88aa2a648740 --- /dev/null +++ b/tests/tests/esnext.array.item.js @@ -0,0 +1,30 @@ +import { STRICT } from '../helpers/constants'; + +QUnit.test('Array#item', assert => { + const { item } = Array.prototype; + assert.isFunction(item); + assert.arity(item, 1); + assert.name(item, 'item'); + assert.looksNative(item); + assert.nonEnumerable(Array.prototype, 'item'); + assert.same(1, [1, 2, 3].item(0)); + assert.same(2, [1, 2, 3].item(1)); + assert.same(3, [1, 2, 3].item(2)); + assert.same(undefined, [1, 2, 3].item(3)); + assert.same(3, [1, 2, 3].item(-1)); + assert.same(2, [1, 2, 3].item(-2)); + assert.same(1, [1, 2, 3].item(-3)); + assert.same(undefined, [1, 2, 3].item(-4)); + assert.same(1, [1, 2, 3].item(0.4)); + assert.same(1, [1, 2, 3].item(0.5)); + assert.same(1, [1, 2, 3].item(0.6)); + assert.same(1, [1].item(NaN)); + assert.same(1, [1].item()); + assert.same(1, [1, 2, 3].item(-0)); + assert.same(undefined, Array(1).item(0)); + assert.same(1, item.call({ 0: 1, length: 1 }, 0)); + if (STRICT) { + assert.throws(() => item.call(null, 0), TypeError); + assert.throws(() => item.call(undefined, 0), TypeError); + } +}); diff --git a/tests/tests/esnext.string.item.js b/tests/tests/esnext.string.item.js new file mode 100644 index 000000000000..a9130c806b83 --- /dev/null +++ b/tests/tests/esnext.string.item.js @@ -0,0 +1,29 @@ +import { STRICT } from '../helpers/constants'; + +QUnit.test('String#item', assert => { + const { item } = String.prototype; + assert.isFunction(item); + assert.arity(item, 1); + assert.name(item, 'item'); + assert.looksNative(item); + assert.nonEnumerable(String.prototype, 'item'); + assert.same('1', '123'.item(0)); + assert.same('2', '123'.item(1)); + assert.same('3', '123'.item(2)); + assert.same(undefined, '123'.item(3)); + assert.same('3', '123'.item(-1)); + assert.same('2', '123'.item(-2)); + assert.same('1', '123'.item(-3)); + assert.same(undefined, '123'.item(-4)); + assert.same('1', '123'.item(0.4)); + assert.same('1', '123'.item(0.5)); + assert.same('1', '123'.item(0.6)); + assert.same('1', '1'.item(NaN)); + assert.same('1', '1'.item()); + assert.same('1', '123'.item(-0)); + assert.same('1', item.call({ toString() { return '123'; } }, 0)); + if (STRICT) { + assert.throws(() => item.call(null, 0), TypeError); + assert.throws(() => item.call(undefined, 0), TypeError); + } +}); diff --git a/tests/tests/esnext.typed-array.item.js b/tests/tests/esnext.typed-array.item.js new file mode 100644 index 000000000000..9761ecaefa4c --- /dev/null +++ b/tests/tests/esnext.typed-array.item.js @@ -0,0 +1,30 @@ +import { DESCRIPTORS, GLOBAL, TYPED_ARRAYS } from '../helpers/constants'; + +if (DESCRIPTORS) QUnit.test('%TypedArrayPrototype%.indexOf', 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 { item } = TypedArray.prototype; + assert.isFunction(item); + assert.arity(item, 1); + assert.name(item, 'item'); + assert.looksNative(item); + assert.same(1, new TypedArray([1, 2, 3]).item(0)); + assert.same(2, new TypedArray([1, 2, 3]).item(1)); + assert.same(3, new TypedArray([1, 2, 3]).item(2)); + assert.same(undefined, new TypedArray([1, 2, 3]).item(3)); + assert.same(3, new TypedArray([1, 2, 3]).item(-1)); + assert.same(2, new TypedArray([1, 2, 3]).item(-2)); + assert.same(1, new TypedArray([1, 2, 3]).item(-3)); + assert.same(undefined, new TypedArray([1, 2, 3]).item(-4)); + assert.same(1, new TypedArray([1, 2, 3]).item(0.4)); + assert.same(1, new TypedArray([1, 2, 3]).item(0.5)); + assert.same(1, new TypedArray([1, 2, 3]).item(0.6)); + assert.same(1, new TypedArray([1]).item(NaN)); + assert.same(1, new TypedArray([1]).item()); + assert.same(1, new TypedArray([1, 2, 3]).item(-0)); + assert.throws(() => item.call({ 0: 1, length: 1 }, 0), TypeError); + assert.throws(() => item.call(null, 0), TypeError); + assert.throws(() => item.call(undefined, 0), TypeError); + } +}); diff --git a/tests/tests/index.js b/tests/tests/index.js index 7ec3f696bbe1..d3b14f154021 100644 --- a/tests/tests/index.js +++ b/tests/tests/index.js @@ -199,6 +199,7 @@ import './es.weak-set'; QUnit.module('ESNext'); import './esnext.array.filter-out'; import './esnext.array.is-template-object'; +import './esnext.array.item'; import './esnext.array.last-item'; import './esnext.array.last-index'; import './esnext.array.unique-by'; @@ -302,12 +303,14 @@ import './esnext.set.symmetric-difference'; import './esnext.set.union'; import './esnext.string.at'; import './esnext.string.code-points'; +import './esnext.string.item'; import './esnext.symbol.async-dispose'; import './esnext.symbol.dispose'; import './esnext.symbol.observable'; import './esnext.symbol.pattern-match'; import './esnext.symbol.replace-all'; import './esnext.typed-array.filter-out'; +import './esnext.typed-array.item'; import './esnext.weak-map.delete-all'; import './esnext.weak-map.from'; import './esnext.weak-map.of'; From cdf08f2f53b8b34610176e5ec099cb3bf06e7298 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Mon, 16 Nov 2020 01:25:49 +0700 Subject: [PATCH 2/8] add a link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 71525ab7e61e..51edaa0366af 100644 --- a/README.md +++ b/README.md @@ -1778,7 +1778,7 @@ Promise.any([ core-js(-pure)/stage/3 ``` -##### [`.item()` method on all the built-in indexables](https://github.com/tc39/proposal-item-method) +##### [`.item()` method on all the built-in indexables](https://github.com/tc39/proposal-item-method)[⬆](#index) Modules [`esnext.array.item`](https://github.com/zloirock/core-js/blob/v3.7.0/packages/core-js/modules/esnext.array.item.js), [`esnext.string.item`](https://github.com/zloirock/core-js/blob/v3.7.0/packages/core-js/modules/esnext.string.item.js) and [`esnext.typed-array.item`](https://github.com/zloirock/core-js/blob/v3.7.0/packages/core-js/modules/esnext.typed-array.item.js) ```js class Array { From 81835d8263163b3d3d298cf83fb11ee9207f7d73 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Mon, 16 Nov 2020 02:25:19 +0700 Subject: [PATCH 3/8] update the changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f20ecdf7005c..0dc20da71c5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## Changelog ##### Unreleased +- Added [`.item()` method on all the built-in indexables stage 3 proposal](https://github.com/tc39/proposal-item-method) - Added [`Number.range` stage 1 proposal](https://github.com/tc39/proposal-Number.range) - `Number.range` - `BigInt.range` From 0bc85575f5d673fc5ab1126a045d972cacaa6499 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Sat, 21 Nov 2020 20:17:57 +0700 Subject: [PATCH 4/8] update the proposal name --- CHANGELOG.md | 2 +- README.md | 4 ++-- packages/core-js/modules/esnext.array.item.js | 2 +- packages/core-js/modules/esnext.string.item.js | 2 +- packages/core-js/modules/esnext.typed-array.item.js | 2 +- .../proposals/{item-method.js => relative-indexing-method.js} | 2 +- packages/core-js/stage/3.js | 2 +- tests/commonjs.js | 1 + 8 files changed, 9 insertions(+), 8 deletions(-) rename packages/core-js/proposals/{item-method.js => relative-indexing-method.js} (68%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0dc20da71c5a..1169d96bc79b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ## Changelog ##### Unreleased -- Added [`.item()` method on all the built-in indexables stage 3 proposal](https://github.com/tc39/proposal-item-method) +- Added [`.item()` method on all the built-in indexables stage 3 proposal](https://github.com/tc39/proposal-relative-indexing-method) - Added [`Number.range` stage 1 proposal](https://github.com/tc39/proposal-Number.range) - `Number.range` - `BigInt.range` diff --git a/README.md b/README.md index 51edaa0366af..ba0512b5df18 100644 --- a/README.md +++ b/README.md @@ -1778,7 +1778,7 @@ Promise.any([ core-js(-pure)/stage/3 ``` -##### [`.item()` method on all the built-in indexables](https://github.com/tc39/proposal-item-method)[⬆](#index) +##### [`.item()` method on all the built-in indexables](https://github.com/tc39/proposal-relative-indexing-method)[⬆](#index) Modules [`esnext.array.item`](https://github.com/zloirock/core-js/blob/v3.7.0/packages/core-js/modules/esnext.array.item.js), [`esnext.string.item`](https://github.com/zloirock/core-js/blob/v3.7.0/packages/core-js/modules/esnext.string.item.js) and [`esnext.typed-array.item`](https://github.com/zloirock/core-js/blob/v3.7.0/packages/core-js/modules/esnext.typed-array.item.js) ```js class Array { @@ -1805,7 +1805,7 @@ class [ ``` [*CommonJS entry points:*](#commonjs-api) ``` -core-js/proposals/item-method +core-js/proposals/relative-indexing-method core-js(-pure)/features/array/item core-js(-pure)/features/string/item core-js(-pure)/features/typed-array/item diff --git a/packages/core-js/modules/esnext.array.item.js b/packages/core-js/modules/esnext.array.item.js index b3308f570791..6767e63e788e 100644 --- a/packages/core-js/modules/esnext.array.item.js +++ b/packages/core-js/modules/esnext.array.item.js @@ -6,7 +6,7 @@ var toInteger = require('../internals/to-integer'); var addToUnscopables = require('../internals/add-to-unscopables'); // `Array.prototype.item` method -// https://github.com/tc39/proposal-item-method +// https://github.com/tc39/proposal-relative-indexing-method $({ target: 'Array', proto: true }, { item: function item(index) { var O = toObject(this); diff --git a/packages/core-js/modules/esnext.string.item.js b/packages/core-js/modules/esnext.string.item.js index 2a008ea0051f..81a972935f5a 100644 --- a/packages/core-js/modules/esnext.string.item.js +++ b/packages/core-js/modules/esnext.string.item.js @@ -5,7 +5,7 @@ var toLength = require('../internals/to-length'); var toInteger = require('../internals/to-integer'); // `String.prototype.item` method -// https://github.com/tc39/proposal-item-method +// https://github.com/tc39/proposal-relative-indexing-method $({ target: 'String', proto: true }, { item: function item(index) { var S = String(requireObjectCoercible(this)); diff --git a/packages/core-js/modules/esnext.typed-array.item.js b/packages/core-js/modules/esnext.typed-array.item.js index aa7fc140e760..0e69c5166091 100644 --- a/packages/core-js/modules/esnext.typed-array.item.js +++ b/packages/core-js/modules/esnext.typed-array.item.js @@ -7,7 +7,7 @@ var aTypedArray = ArrayBufferViewCore.aTypedArray; var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod; // `%TypedArray%.prototype.item` method -// https://github.com/tc39/proposal-item-method +// https://github.com/tc39/proposal-relative-indexing-method exportTypedArrayMethod('item', function item(index) { var O = aTypedArray(this); var len = toLength(O.length); diff --git a/packages/core-js/proposals/item-method.js b/packages/core-js/proposals/relative-indexing-method.js similarity index 68% rename from packages/core-js/proposals/item-method.js rename to packages/core-js/proposals/relative-indexing-method.js index 124ec97f661b..6ab4ac001acb 100644 --- a/packages/core-js/proposals/item-method.js +++ b/packages/core-js/proposals/relative-indexing-method.js @@ -1,4 +1,4 @@ -// https://github.com/tc39/proposal-item-method +// https://github.com/tc39/proposal-relative-indexing-method require('../modules/esnext.array.item'); require('../modules/esnext.string.item'); require('../modules/esnext.typed-array.item'); diff --git a/packages/core-js/stage/3.js b/packages/core-js/stage/3.js index 71cbae04d693..7f4ea8778a97 100644 --- a/packages/core-js/stage/3.js +++ b/packages/core-js/stage/3.js @@ -1,4 +1,4 @@ -require('../proposals/item-method'); +require('../proposals/relative-indexing-method'); var parent = require('./4'); module.exports = parent; diff --git a/tests/commonjs.js b/tests/commonjs.js index 566da4d04179..fd12d76aac02 100644 --- a/tests/commonjs.js +++ b/tests/commonjs.js @@ -981,6 +981,7 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) { load('proposals/promise-any'); 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'); From 7b65395fbec07fa0807e1e466cb016bc2d018283 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Sat, 21 Nov 2020 21:39:49 +0700 Subject: [PATCH 5/8] update the method name: `.item` -> `.at` --- CHANGELOG.md | 4 ++- README.md | 26 +++++++--------- packages/core-js-compat/src/data.js | 8 ++--- .../core-js-compat/src/modules-by-versions.js | 2 ++ ...array.item.js => esnext.typed-array.at.js} | 0 packages/core-js/features/array/at.js | 4 +++ packages/core-js/features/array/index.js | 2 +- packages/core-js/features/array/item.js | 4 --- packages/core-js/features/array/virtual/at.js | 4 +++ .../core-js/features/array/virtual/index.js | 3 +- .../core-js/features/array/virtual/item.js | 4 --- packages/core-js/features/instance/at.js | 10 +++++-- packages/core-js/features/instance/item.js | 13 -------- packages/core-js/features/string/index.js | 3 +- packages/core-js/features/string/item.js | 4 --- .../core-js/features/string/virtual/index.js | 3 +- .../core-js/features/string/virtual/item.js | 4 --- packages/core-js/features/typed-array/at.js | 1 + .../core-js/features/typed-array/index.js | 2 +- packages/core-js/features/typed-array/item.js | 1 - ...snext.array.item.js => esnext.array.at.js} | 6 ++-- ...tem.js => esnext.string.at-alternative.js} | 5 ++-- ...array.item.js => esnext.typed-array.at.js} | 4 +-- .../proposals/relative-indexing-method.js | 7 +++-- tests/commonjs.js | 22 +++++--------- tests/compat/tests.js | 15 ++++------ tests/pure/esnext.array.at.js | 27 +++++++++++++++++ tests/pure/esnext.array.item.js | 27 ----------------- tests/pure/esnext.string.at-alternative.js | 27 +++++++++++++++++ tests/pure/esnext.string.item.js | 26 ---------------- tests/pure/index.js | 5 ++-- tests/tests/esnext.array.at.js | 30 +++++++++++++++++++ tests/tests/esnext.array.item.js | 30 ------------------- tests/tests/esnext.string.at-alternative.js | 30 +++++++++++++++++++ tests/tests/esnext.string.item.js | 29 ------------------ tests/tests/esnext.typed-array.at.js | 30 +++++++++++++++++++ tests/tests/esnext.typed-array.item.js | 30 ------------------- tests/tests/index.js | 7 +++-- 38 files changed, 220 insertions(+), 239 deletions(-) rename packages/core-js-pure/override/modules/{esnext.typed-array.item.js => esnext.typed-array.at.js} (100%) create mode 100644 packages/core-js/features/array/at.js delete mode 100644 packages/core-js/features/array/item.js create mode 100644 packages/core-js/features/array/virtual/at.js delete mode 100644 packages/core-js/features/array/virtual/item.js delete mode 100644 packages/core-js/features/instance/item.js delete mode 100644 packages/core-js/features/string/item.js delete mode 100644 packages/core-js/features/string/virtual/item.js create mode 100644 packages/core-js/features/typed-array/at.js delete mode 100644 packages/core-js/features/typed-array/item.js rename packages/core-js/modules/{esnext.array.item.js => esnext.array.at.js} (87%) rename packages/core-js/modules/{esnext.string.item.js => esnext.string.at-alternative.js} (81%) rename packages/core-js/modules/{esnext.typed-array.item.js => esnext.typed-array.at.js} (86%) create mode 100644 tests/pure/esnext.array.at.js delete mode 100644 tests/pure/esnext.array.item.js create mode 100644 tests/pure/esnext.string.at-alternative.js delete mode 100644 tests/pure/esnext.string.item.js create mode 100644 tests/tests/esnext.array.at.js delete mode 100644 tests/tests/esnext.array.item.js create mode 100644 tests/tests/esnext.string.at-alternative.js delete mode 100644 tests/tests/esnext.string.item.js create mode 100644 tests/tests/esnext.typed-array.at.js delete mode 100644 tests/tests/esnext.typed-array.item.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 1169d96bc79b..747d5f7c7c67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ ## Changelog ##### Unreleased -- Added [`.item()` method on all the built-in indexables stage 3 proposal](https://github.com/tc39/proposal-relative-indexing-method) +- Added [relative indexing method stage 3 proposal](https://github.com/tc39/proposal-relative-indexing-method) + - `Array#at` + - `%TypedArray%#at` - Added [`Number.range` stage 1 proposal](https://github.com/tc39/proposal-Number.range) - `Number.range` - `BigInt.range` diff --git a/README.md b/README.md index ba0512b5df18..59980d45dc15 100644 --- a/README.md +++ b/README.md @@ -1778,15 +1778,13 @@ Promise.any([ core-js(-pure)/stage/3 ``` -##### [`.item()` method on all the built-in indexables](https://github.com/tc39/proposal-relative-indexing-method)[⬆](#index) -Modules [`esnext.array.item`](https://github.com/zloirock/core-js/blob/v3.7.0/packages/core-js/modules/esnext.array.item.js), [`esnext.string.item`](https://github.com/zloirock/core-js/blob/v3.7.0/packages/core-js/modules/esnext.string.item.js) and [`esnext.typed-array.item`](https://github.com/zloirock/core-js/blob/v3.7.0/packages/core-js/modules/esnext.typed-array.item.js) +##### [Relative indexing method](https://github.com/tc39/proposal-relative-indexing-method)[⬆](#index) +Modules [`esnext.array.at`](https://github.com/zloirock/core-js/blob/v3.7.0/packages/core-js/modules/esnext.array.at.js) and [`esnext.typed-array.at`](https://github.com/zloirock/core-js/blob/v3.7.0/packages/core-js/modules/esnext.typed-array.at.js) +> **Warning! Because of the conflict with another proposal, this method is not available on `String.prototype` in this version.** + ```js class Array { - item(index: int): any; -} - -class String { - item(index: int): string | undefined; + at(index: int): any; } class [ @@ -1800,21 +1798,19 @@ class [ Float32Array, Float64Array, ] { - item(index: int): any; + at(index: int): any; } ``` [*CommonJS entry points:*](#commonjs-api) ``` core-js/proposals/relative-indexing-method -core-js(-pure)/features/array/item -core-js(-pure)/features/string/item -core-js(-pure)/features/typed-array/item +core-js(-pure)/features/array/at +core-js(-pure)/features/typed-array/at ``` -[*Examples*](http://es6.zloirock.ru/#log(%5B1%2C%202%2C%203%5D.item(1))%3B%20%20%2F%2F%20%3D%3E%202%0Alog(%5B1%2C%202%2C%203%5D.item(-1))%3B%20%2F%2F%20%3D%3E%203%0Alog('123'.item(-1))%3B%20%20%20%20%20%2F%2F%20%3D%3E%20'3'): +[*Examples*](http://es6.zloirock.ru/#log(%5B1%2C%202%2C%203%5D.at(1))%3B%20%20%2F%2F%20%3D%3E%202%0Alog(%5B1%2C%202%2C%203%5D.at(-1))%3B%20%2F%2F%20%3D%3E%203): ```js -[1, 2, 3].item(1); // => 2 -[1, 2, 3].item(-1); // => 3 -'123'.item(-1); // => '3' +[1, 2, 3].at(1); // => 2 +[1, 2, 3].at(-1); // => 3 ``` #### Stage 2 proposals[⬆](#index) diff --git a/packages/core-js-compat/src/data.js b/packages/core-js-compat/src/data.js index eba25e7040ba..e792d91c930a 100644 --- a/packages/core-js-compat/src/data.js +++ b/packages/core-js-compat/src/data.js @@ -1258,7 +1258,7 @@ const data = { }, 'esnext.array.is-template-object': { }, - 'esnext.array.item': { + 'esnext.array.at': { }, 'esnext.array.last-index': { }, @@ -1480,8 +1480,6 @@ const data = { }, 'esnext.string.code-points': { }, - 'esnext.string.item': { - }, // TODO: Remove from `core-js@4` 'esnext.string.match-all': null, 'esnext.string.replace-all': null, @@ -1496,9 +1494,9 @@ const data = { // TODO: Remove from `core-js@4` 'esnext.symbol.replace-all': { }, - 'esnext.typed-array.filter-out': { + 'esnext.typed-array.at': { } - 'esnext.typed-array.item': { + 'esnext.typed-array.filter-out': { }, 'esnext.weak-map.delete-all': { }, diff --git a/packages/core-js-compat/src/modules-by-versions.js b/packages/core-js-compat/src/modules-by-versions.js index f01cbf3377d7..83485ff63626 100644 --- a/packages/core-js-compat/src/modules-by-versions.js +++ b/packages/core-js-compat/src/modules-by-versions.js @@ -65,10 +65,12 @@ module.exports = { 'esnext.weak-map.emplace', ], 3.8: [ + 'esnext.array.at', 'esnext.array.filter-out', 'esnext.array.unique-by', 'esnext.bigint.range', 'esnext.number.range', + 'esnext.typed-array.at', 'esnext.typed-array.filter-out', ], }; diff --git a/packages/core-js-pure/override/modules/esnext.typed-array.item.js b/packages/core-js-pure/override/modules/esnext.typed-array.at.js similarity index 100% rename from packages/core-js-pure/override/modules/esnext.typed-array.item.js rename to packages/core-js-pure/override/modules/esnext.typed-array.at.js diff --git a/packages/core-js/features/array/at.js b/packages/core-js/features/array/at.js new file mode 100644 index 000000000000..9b923f612724 --- /dev/null +++ b/packages/core-js/features/array/at.js @@ -0,0 +1,4 @@ +require('../../modules/esnext.array.at'); +var entryUnbind = require('../../internals/entry-unbind'); + +module.exports = entryUnbind('Array', 'at'); diff --git a/packages/core-js/features/array/index.js b/packages/core-js/features/array/index.js index 28ed5ae2699b..eecc4b31cde9 100644 --- a/packages/core-js/features/array/index.js +++ b/packages/core-js/features/array/index.js @@ -1,8 +1,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.is-template-object'); -require('../../modules/esnext.array.item'); require('../../modules/esnext.array.last-item'); require('../../modules/esnext.array.last-index'); require('../../modules/esnext.array.unique-by'); diff --git a/packages/core-js/features/array/item.js b/packages/core-js/features/array/item.js deleted file mode 100644 index dba4d5036b02..000000000000 --- a/packages/core-js/features/array/item.js +++ /dev/null @@ -1,4 +0,0 @@ -require('../../modules/esnext.array.item'); -var entryUnbind = require('../../internals/entry-unbind'); - -module.exports = entryUnbind('Array', 'item'); diff --git a/packages/core-js/features/array/virtual/at.js b/packages/core-js/features/array/virtual/at.js new file mode 100644 index 000000000000..14f8e5aff59d --- /dev/null +++ b/packages/core-js/features/array/virtual/at.js @@ -0,0 +1,4 @@ +require('../../../modules/esnext.array.at'); +var entryVirtual = require('../../../internals/entry-virtual'); + +module.exports = entryVirtual('Array').at; diff --git a/packages/core-js/features/array/virtual/index.js b/packages/core-js/features/array/virtual/index.js index 86150f97bb56..6572f923dc93 100644 --- a/packages/core-js/features/array/virtual/index.js +++ b/packages/core-js/features/array/virtual/index.js @@ -1,5 +1,6 @@ var parent = require('../../../es/array/virtual'); +require('../../../modules/esnext.array.at'); require('../../../modules/esnext.array.filter-out'); -require('../../../modules/esnext.array.item'); +require('../../../modules/esnext.array.unique-by'); module.exports = parent; diff --git a/packages/core-js/features/array/virtual/item.js b/packages/core-js/features/array/virtual/item.js deleted file mode 100644 index 0575cc53249b..000000000000 --- a/packages/core-js/features/array/virtual/item.js +++ /dev/null @@ -1,4 +0,0 @@ -require('../../../modules/esnext.array.item'); -var entryVirtual = require('../../../internals/entry-virtual'); - -module.exports = entryVirtual('Array').item; diff --git a/packages/core-js/features/instance/at.js b/packages/core-js/features/instance/at.js index f9b4f7986dcb..736ff4d34bc6 100644 --- a/packages/core-js/features/instance/at.js +++ b/packages/core-js/features/instance/at.js @@ -1,9 +1,13 @@ -var at = require('../string/virtual/at'); +var arrayAt = require('../array/virtual/at'); +var stringAt = require('../string/virtual/at'); +var ArrayPrototype = Array.prototype; var StringPrototype = String.prototype; module.exports = function (it) { var own = it.at; - return typeof it === 'string' || it === StringPrototype - || (it instanceof String && own === StringPrototype.at) ? at : own; + if (it === ArrayPrototype || (it instanceof Array && own === ArrayPrototype.at)) return arrayAt; + if (typeof it === 'string' || it === StringPrototype || (it instanceof String && own === StringPrototype.at)) { + return stringAt; + } return own; }; diff --git a/packages/core-js/features/instance/item.js b/packages/core-js/features/instance/item.js deleted file mode 100644 index 2cc40a1748f3..000000000000 --- a/packages/core-js/features/instance/item.js +++ /dev/null @@ -1,13 +0,0 @@ -var arrayItem = require('../array/virtual/item'); -var stringItem = require('../string/virtual/item'); - -var ArrayPrototype = Array.prototype; -var StringPrototype = String.prototype; - -module.exports = function (it) { - var own = it.item; - if (it === ArrayPrototype || (it instanceof Array && own === ArrayPrototype.item)) return arrayItem; - if (typeof it === 'string' || it === StringPrototype || (it instanceof String && own === StringPrototype.item)) { - return stringItem; - } return own; -}; diff --git a/packages/core-js/features/string/index.js b/packages/core-js/features/string/index.js index 189cbfed791f..28e5520c77da 100644 --- a/packages/core-js/features/string/index.js +++ b/packages/core-js/features/string/index.js @@ -1,7 +1,8 @@ var parent = require('../../es/string'); require('../../modules/esnext.string.at'); +// TODO: disabled by default because of the conflict with another proposal +// require('../../modules/esnext.string.at-alternative'); require('../../modules/esnext.string.code-points'); -require('../../modules/esnext.string.item'); // TODO: remove from `core-js@4` require('../../modules/esnext.string.match-all'); require('../../modules/esnext.string.replace-all'); diff --git a/packages/core-js/features/string/item.js b/packages/core-js/features/string/item.js deleted file mode 100644 index 33bd7de301ca..000000000000 --- a/packages/core-js/features/string/item.js +++ /dev/null @@ -1,4 +0,0 @@ -require('../../modules/esnext.string.item'); -var entryUnbind = require('../../internals/entry-unbind'); - -module.exports = entryUnbind('String', 'item'); diff --git a/packages/core-js/features/string/virtual/index.js b/packages/core-js/features/string/virtual/index.js index 8a88cfb10d7e..aaef5105ec36 100644 --- a/packages/core-js/features/string/virtual/index.js +++ b/packages/core-js/features/string/virtual/index.js @@ -1,7 +1,8 @@ var parent = require('../../../es/string/virtual'); require('../../../modules/esnext.string.at'); +// TODO: disabled by default because of the conflict with another proposal +// require('../../../modules/esnext.string.at-alternative'); require('../../../modules/esnext.string.code-points'); -require('../../../modules/esnext.string.item'); // TODO: remove from `core-js@4` require('../../../modules/esnext.string.match-all'); require('../../../modules/esnext.string.replace-all'); diff --git a/packages/core-js/features/string/virtual/item.js b/packages/core-js/features/string/virtual/item.js deleted file mode 100644 index 2db37dfa3b82..000000000000 --- a/packages/core-js/features/string/virtual/item.js +++ /dev/null @@ -1,4 +0,0 @@ -require('../../../modules/esnext.string.item'); -var entryVirtual = require('../../../internals/entry-virtual'); - -module.exports = entryVirtual('String').item; diff --git a/packages/core-js/features/typed-array/at.js b/packages/core-js/features/typed-array/at.js new file mode 100644 index 000000000000..4882b7edbd19 --- /dev/null +++ b/packages/core-js/features/typed-array/at.js @@ -0,0 +1 @@ +require('../../modules/esnext.typed-array.at'); diff --git a/packages/core-js/features/typed-array/index.js b/packages/core-js/features/typed-array/index.js index a760207eae6b..db032de1171f 100644 --- a/packages/core-js/features/typed-array/index.js +++ b/packages/core-js/features/typed-array/index.js @@ -1,5 +1,5 @@ var parent = require('../../es/typed-array'); +require('../../modules/esnext.typed-array.at'); require('../../modules/esnext.typed-array.filter-out'); -require('../../modules/esnext.typed-array.item'); module.exports = parent; diff --git a/packages/core-js/features/typed-array/item.js b/packages/core-js/features/typed-array/item.js deleted file mode 100644 index fac1053f5289..000000000000 --- a/packages/core-js/features/typed-array/item.js +++ /dev/null @@ -1 +0,0 @@ -require('../../modules/esnext.typed-array.item'); diff --git a/packages/core-js/modules/esnext.array.item.js b/packages/core-js/modules/esnext.array.at.js similarity index 87% rename from packages/core-js/modules/esnext.array.item.js rename to packages/core-js/modules/esnext.array.at.js index 6767e63e788e..0342f850617b 100644 --- a/packages/core-js/modules/esnext.array.item.js +++ b/packages/core-js/modules/esnext.array.at.js @@ -5,10 +5,10 @@ var toLength = require('../internals/to-length'); var toInteger = require('../internals/to-integer'); var addToUnscopables = require('../internals/add-to-unscopables'); -// `Array.prototype.item` method +// `Array.prototype.at` method // https://github.com/tc39/proposal-relative-indexing-method $({ target: 'Array', proto: true }, { - item: function item(index) { + at: function at(index) { var O = toObject(this); var len = toLength(O.length); var relativeIndex = toInteger(index); @@ -17,4 +17,4 @@ $({ target: 'Array', proto: true }, { } }); -addToUnscopables('item'); +addToUnscopables('at'); diff --git a/packages/core-js/modules/esnext.string.item.js b/packages/core-js/modules/esnext.string.at-alternative.js similarity index 81% rename from packages/core-js/modules/esnext.string.item.js rename to packages/core-js/modules/esnext.string.at-alternative.js index 81a972935f5a..5591cbcd59bd 100644 --- a/packages/core-js/modules/esnext.string.item.js +++ b/packages/core-js/modules/esnext.string.at-alternative.js @@ -1,13 +1,14 @@ +// TODO: disabled by default because of the conflict with another proposal 'use strict'; var $ = require('../internals/export'); var requireObjectCoercible = require('../internals/require-object-coercible'); var toLength = require('../internals/to-length'); var toInteger = require('../internals/to-integer'); -// `String.prototype.item` method +// `String.prototype.at` method // https://github.com/tc39/proposal-relative-indexing-method $({ target: 'String', proto: true }, { - item: function item(index) { + at: function at(index) { var S = String(requireObjectCoercible(this)); var len = toLength(S.length); var relativeIndex = toInteger(index); diff --git a/packages/core-js/modules/esnext.typed-array.item.js b/packages/core-js/modules/esnext.typed-array.at.js similarity index 86% rename from packages/core-js/modules/esnext.typed-array.item.js rename to packages/core-js/modules/esnext.typed-array.at.js index 0e69c5166091..f6da023cb98d 100644 --- a/packages/core-js/modules/esnext.typed-array.item.js +++ b/packages/core-js/modules/esnext.typed-array.at.js @@ -6,9 +6,9 @@ var toInteger = require('../internals/to-integer'); var aTypedArray = ArrayBufferViewCore.aTypedArray; var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod; -// `%TypedArray%.prototype.item` method +// `%TypedArray%.prototype.at` method // https://github.com/tc39/proposal-relative-indexing-method -exportTypedArrayMethod('item', function item(index) { +exportTypedArrayMethod('at', function at(index) { var O = aTypedArray(this); var len = toLength(O.length); var relativeIndex = toInteger(index); diff --git a/packages/core-js/proposals/relative-indexing-method.js b/packages/core-js/proposals/relative-indexing-method.js index 6ab4ac001acb..95e681400b58 100644 --- a/packages/core-js/proposals/relative-indexing-method.js +++ b/packages/core-js/proposals/relative-indexing-method.js @@ -1,4 +1,5 @@ // https://github.com/tc39/proposal-relative-indexing-method -require('../modules/esnext.array.item'); -require('../modules/esnext.string.item'); -require('../modules/esnext.typed-array.item'); +require('../modules/esnext.array.at'); +// TODO: disabled by default because of the conflict with another proposal +// require('../modules/esnext.string.at-alternative'); +require('../modules/esnext.typed-array.at'); diff --git a/tests/commonjs.js b/tests/commonjs.js index fd12d76aac02..5866dbe0ddf9 100644 --- a/tests/commonjs.js +++ b/tests/commonjs.js @@ -62,6 +62,7 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) { ok(typeof load('features/array/is-template-object') === 'function'); ok(Array.isArray(load('features/array/from')('qwe'))); ok(Array.isArray(load('features/array/of')('q', 'w', 'e'))); + ok(load('features/array/at')([1, 2, 3], -2) === 2); ok(load('features/array/join')('qwe', 1) === 'q1w1e'); ok(load('features/array/slice')('qwe', 1)[1] === 'e'); ok(load('features/array/sort')([1, 3, 2])[1] === 2); @@ -71,7 +72,6 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) { ok(typeof load('features/array/filter-out') === 'function'); ok(typeof load('features/array/flat') === 'function'); ok(typeof load('features/array/flat-map') === 'function'); - ok(load('features/array/item')([1, 2, 3], -2) === 2); ok(typeof load('features/array/some') === 'function'); ok(typeof load('features/array/every') === 'function'); ok(typeof load('features/array/reduce') === 'function'); @@ -93,6 +93,7 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) { ok(load('features/array/includes')([1, 2, 3], 2)); ok('next' in load('features/array/iterator')([])); ok(typeof load('features/array/unique-by') === 'function'); + ok(load('features/array/virtual/at').call([1, 2, 3], -2) === 2); ok(load('features/array/virtual/join').call('qwe', 1) === 'q1w1e'); ok(load('features/array/virtual/slice').call('qwe', 1)[1] === 'e'); ok(load('features/array/virtual/splice').call([1, 2, 3], 1, 2)[0] === 2); @@ -103,7 +104,6 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) { ok(typeof load('features/array/virtual/filter-out') === 'function'); ok(typeof load('features/array/virtual/flat') === 'function'); ok(typeof load('features/array/virtual/flat-map') === 'function'); - ok(load('features/array/virtual/item').call([1, 2, 3], -2) === 2); ok(typeof load('features/array/virtual/some') === 'function'); ok(typeof load('features/array/virtual/every') === 'function'); ok(typeof load('features/array/virtual/reduce') === 'function'); @@ -212,7 +212,7 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) { ok(load('features/string/code-point-at')('a', 0) === 97); ok(load('features/string/ends-with')('qwe', 'we')); ok(load('features/string/includes')('qwe', 'w')); - ok(load('features/string/item')('123', -2) === '2'); + // ok(load('features/string/at-alternative')('123', -2) === '2'); ok(load('features/string/repeat')('q', 3) === 'qqq'); ok(load('features/string/starts-with')('qwe', 'qw')); ok(typeof load('features/string/anchor') === 'function'); @@ -242,7 +242,7 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) { ok(load('features/string/virtual/code-point-at').call('a', 0) === 97); ok(load('features/string/virtual/ends-with').call('qwe', 'we')); ok(load('features/string/virtual/includes').call('qwe', 'w')); - ok(load('features/string/virtual/item').call('123', -2) === '2'); + // ok(load('features/string/virtual/at-alternative').call('123', -2) === '2'); ok(load('features/string/virtual/repeat').call('q', 3) === 'qqq'); ok(load('features/string/virtual/starts-with').call('qwe', 'qw')); ok(typeof load('features/string/virtual/anchor') === 'function'); @@ -1004,8 +1004,10 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) { const instanceAt = load('features/instance/at'); ok(typeof instanceAt === 'function'); ok(instanceAt({}) === undefined); + ok(typeof instanceAt([]) === 'function'); ok(typeof instanceAt('') === 'function'); - ok(instanceAt('').call('abc', 1) === 'b'); + ok(instanceAt([]).call([1, 2, 3], 2) === 3); + ok(instanceAt('').call('123', 2) === '3'); let instanceBind = load('features/instance/bind'); ok(typeof instanceBind === 'function'); @@ -1275,14 +1277,6 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) { ok(instanceIncludes([]).call([1, 2, 3], 2)); ok(instanceIncludes('').call('123', '2')); - const instanceItem = load('features/instance/item'); - ok(typeof instanceItem === 'function'); - ok(instanceItem({}) === undefined); - ok(typeof instanceItem([]) === 'function'); - ok(typeof instanceItem('') === 'function'); - ok(instanceItem([]).call([1, 2, 3], 2) === 3); - ok(instanceItem('').call('123', 2) === '3'); - let instanceIndexOf = load('features/instance/index-of'); ok(typeof instanceIndexOf === 'function'); ok(instanceIndexOf({}) === undefined); @@ -1666,6 +1660,7 @@ ok(typeof load('features/typed-array/int32-array') === 'function'); ok(typeof load('features/typed-array/uint32-array') === 'function'); ok(typeof load('features/typed-array/float32-array') === 'function'); ok(typeof load('features/typed-array/float64-array') === 'function'); +load('features/typed-array/at'); load('features/typed-array/copy-within'); load('features/typed-array/entries'); load('features/typed-array/every'); @@ -1678,7 +1673,6 @@ load('features/typed-array/for-each'); load('features/typed-array/from'); load('features/typed-array/includes'); load('features/typed-array/index-of'); -load('features/typed-array/item'); load('features/typed-array/iterator'); load('features/typed-array/join'); load('features/typed-array/keys'); diff --git a/tests/compat/tests.js b/tests/compat/tests.js index 8d2d26261b0f..05507898dd62 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -1100,12 +1100,12 @@ GLOBAL.tests = { && set.add({}) == set && set[Symbol.toStringTag]; }], + 'esnext.array.at': function () { + return [].at; + }, 'esnext.array.filter-out': function () { return [].filterOut; } - 'esnext.array.item': function () { - return [].item; - }, 'esnext.array.last-index': function () { return [1, 2, 3].lastIndex && Array.prototype[Symbol.unscopables].lastIndex; }, @@ -1430,9 +1430,6 @@ GLOBAL.tests = { 'esnext.string.code-points': function () { return String.prototype.codePoints; }, - 'esnext.string.item': function () { - return ''.item; - }, 'esnext.symbol.dispose': function () { return Symbol.dispose; }, @@ -1446,12 +1443,12 @@ GLOBAL.tests = { 'esnext.symbol.replace-all': function () { return Symbol.replaceAll; }, + 'esnext.typed-array.at': function () { + return Int8Array.prototype.at; + }, 'esnext.typed-array.filter-out': function () { return Int8Array.prototype.filterOut; } - 'esnext.typed-array.item': function () { - return Int8Array.prototype.item; - }, 'esnext.weak-map.delete-all': function () { return WeakMap.prototype.deleteAll; }, diff --git a/tests/pure/esnext.array.at.js b/tests/pure/esnext.array.at.js new file mode 100644 index 000000000000..926f967626b2 --- /dev/null +++ b/tests/pure/esnext.array.at.js @@ -0,0 +1,27 @@ +import { STRICT } from '../helpers/constants'; + +import at from 'core-js-pure/features/array/at'; + +QUnit.test('Array#at', assert => { + assert.isFunction(at); + assert.same(1, at([1, 2, 3], 0)); + assert.same(2, at([1, 2, 3], 1)); + assert.same(3, at([1, 2, 3], 2)); + assert.same(undefined, at([1, 2, 3], 3)); + assert.same(3, at([1, 2, 3], -1)); + assert.same(2, at([1, 2, 3], -2)); + assert.same(1, at([1, 2, 3], -3)); + assert.same(undefined, at([1, 2, 3], -4)); + assert.same(1, at([1, 2, 3], 0.4)); + assert.same(1, at([1, 2, 3], 0.5)); + assert.same(1, at([1, 2, 3], 0.6)); + assert.same(1, at([1], NaN)); + assert.same(1, at([1])); + assert.same(1, at([1, 2, 3], -0)); + assert.same(undefined, at(Array(1), 0)); + assert.same(1, at({ 0: 1, length: 1 }, 0)); + if (STRICT) { + assert.throws(() => at(null, 0), TypeError); + assert.throws(() => at(undefined, 0), TypeError); + } +}); diff --git a/tests/pure/esnext.array.item.js b/tests/pure/esnext.array.item.js deleted file mode 100644 index 71a9b97c1dfd..000000000000 --- a/tests/pure/esnext.array.item.js +++ /dev/null @@ -1,27 +0,0 @@ -import { STRICT } from '../helpers/constants'; - -import item from 'core-js-pure/features/array/item'; - -QUnit.test('Array#item', assert => { - assert.isFunction(item); - assert.same(1, item([1, 2, 3], 0)); - assert.same(2, item([1, 2, 3], 1)); - assert.same(3, item([1, 2, 3], 2)); - assert.same(undefined, item([1, 2, 3], 3)); - assert.same(3, item([1, 2, 3], -1)); - assert.same(2, item([1, 2, 3], -2)); - assert.same(1, item([1, 2, 3], -3)); - assert.same(undefined, item([1, 2, 3], -4)); - assert.same(1, item([1, 2, 3], 0.4)); - assert.same(1, item([1, 2, 3], 0.5)); - assert.same(1, item([1, 2, 3], 0.6)); - assert.same(1, item([1], NaN)); - assert.same(1, item([1])); - assert.same(1, item([1, 2, 3], -0)); - assert.same(undefined, item(Array(1), 0)); - assert.same(1, item({ 0: 1, length: 1 }, 0)); - if (STRICT) { - assert.throws(() => item(null, 0), TypeError); - assert.throws(() => item(undefined, 0), TypeError); - } -}); diff --git a/tests/pure/esnext.string.at-alternative.js b/tests/pure/esnext.string.at-alternative.js new file mode 100644 index 000000000000..bcd26e9bddff --- /dev/null +++ b/tests/pure/esnext.string.at-alternative.js @@ -0,0 +1,27 @@ +// TODO: disabled by default because of the conflict with another proposal +import { STRICT } from '../helpers/constants'; + +import at from 'core-js-pure/features/string/at'; + +QUnit.test('String#at', assert => { + assert.isFunction(at); + assert.same('1', at('123', 0)); + assert.same('2', at('123', 1)); + assert.same('3', at('123', 2)); + assert.same(undefined, at('123', 3)); + assert.same('3', at('123', -1)); + assert.same('2', at('123', -2)); + assert.same('1', at('123', -3)); + assert.same(undefined, at('123', -4)); + assert.same('1', at('123', 0.4)); + assert.same('1', at('123', 0.5)); + assert.same('1', at('123', 0.6)); + assert.same('1', at('1', NaN)); + assert.same('1', at('1')); + assert.same('1', at('123', -0)); + assert.same('1', at({ toString() { return '123'; } }, 0)); + if (STRICT) { + assert.throws(() => at(null, 0), TypeError); + assert.throws(() => at(undefined, 0), TypeError); + } +}); diff --git a/tests/pure/esnext.string.item.js b/tests/pure/esnext.string.item.js deleted file mode 100644 index 062f323e5645..000000000000 --- a/tests/pure/esnext.string.item.js +++ /dev/null @@ -1,26 +0,0 @@ -import { STRICT } from '../helpers/constants'; - -import item from 'core-js-pure/features/string/item'; - -QUnit.test('String#item', assert => { - assert.isFunction(item); - assert.same('1', item('123', 0)); - assert.same('2', item('123', 1)); - assert.same('3', item('123', 2)); - assert.same(undefined, item('123', 3)); - assert.same('3', item('123', -1)); - assert.same('2', item('123', -2)); - assert.same('1', item('123', -3)); - assert.same(undefined, item('123', -4)); - assert.same('1', item('123', 0.4)); - assert.same('1', item('123', 0.5)); - assert.same('1', item('123', 0.6)); - assert.same('1', item('1', NaN)); - assert.same('1', item('1')); - assert.same('1', item('123', -0)); - assert.same('1', item({ toString() { return '123'; } }, 0)); - if (STRICT) { - assert.throws(() => item(null, 0), TypeError); - assert.throws(() => item(undefined, 0), TypeError); - } -}); diff --git a/tests/pure/index.js b/tests/pure/index.js index f4d05b02a4a8..604eca82ff26 100644 --- a/tests/pure/index.js +++ b/tests/pure/index.js @@ -143,8 +143,8 @@ import './es.weak-map'; import './es.weak-set'; QUnit.module('ESNext'); +import './esnext.array.at'; import './esnext.array.filter-out'; -import './esnext.array.item'; import './esnext.array.is-template-object'; import './esnext.array.unique-by'; import './esnext.async-iterator.constructor'; @@ -246,8 +246,9 @@ import './esnext.set.some'; import './esnext.set.symmetric-difference'; import './esnext.set.union'; import './esnext.string.at'; +// TODO: disabled by default because of the conflict with another proposal +// import './esnext.string.at-alternative'; import './esnext.string.code-points'; -import './esnext.string.item'; import './esnext.symbol.async-dispose'; import './esnext.symbol.dispose'; import './esnext.symbol.observable'; diff --git a/tests/tests/esnext.array.at.js b/tests/tests/esnext.array.at.js new file mode 100644 index 000000000000..f0ea6572fd3c --- /dev/null +++ b/tests/tests/esnext.array.at.js @@ -0,0 +1,30 @@ +import { STRICT } from '../helpers/constants'; + +QUnit.test('Array#at', assert => { + const { at } = Array.prototype; + assert.isFunction(at); + assert.arity(at, 1); + assert.name(at, 'at'); + assert.looksNative(at); + assert.nonEnumerable(Array.prototype, 'at'); + assert.same(1, [1, 2, 3].at(0)); + assert.same(2, [1, 2, 3].at(1)); + assert.same(3, [1, 2, 3].at(2)); + assert.same(undefined, [1, 2, 3].at(3)); + assert.same(3, [1, 2, 3].at(-1)); + assert.same(2, [1, 2, 3].at(-2)); + assert.same(1, [1, 2, 3].at(-3)); + assert.same(undefined, [1, 2, 3].at(-4)); + assert.same(1, [1, 2, 3].at(0.4)); + assert.same(1, [1, 2, 3].at(0.5)); + assert.same(1, [1, 2, 3].at(0.6)); + assert.same(1, [1].at(NaN)); + assert.same(1, [1].at()); + assert.same(1, [1, 2, 3].at(-0)); + assert.same(undefined, Array(1).at(0)); + assert.same(1, at.call({ 0: 1, length: 1 }, 0)); + if (STRICT) { + assert.throws(() => at.call(null, 0), TypeError); + assert.throws(() => at.call(undefined, 0), TypeError); + } +}); diff --git a/tests/tests/esnext.array.item.js b/tests/tests/esnext.array.item.js deleted file mode 100644 index 88aa2a648740..000000000000 --- a/tests/tests/esnext.array.item.js +++ /dev/null @@ -1,30 +0,0 @@ -import { STRICT } from '../helpers/constants'; - -QUnit.test('Array#item', assert => { - const { item } = Array.prototype; - assert.isFunction(item); - assert.arity(item, 1); - assert.name(item, 'item'); - assert.looksNative(item); - assert.nonEnumerable(Array.prototype, 'item'); - assert.same(1, [1, 2, 3].item(0)); - assert.same(2, [1, 2, 3].item(1)); - assert.same(3, [1, 2, 3].item(2)); - assert.same(undefined, [1, 2, 3].item(3)); - assert.same(3, [1, 2, 3].item(-1)); - assert.same(2, [1, 2, 3].item(-2)); - assert.same(1, [1, 2, 3].item(-3)); - assert.same(undefined, [1, 2, 3].item(-4)); - assert.same(1, [1, 2, 3].item(0.4)); - assert.same(1, [1, 2, 3].item(0.5)); - assert.same(1, [1, 2, 3].item(0.6)); - assert.same(1, [1].item(NaN)); - assert.same(1, [1].item()); - assert.same(1, [1, 2, 3].item(-0)); - assert.same(undefined, Array(1).item(0)); - assert.same(1, item.call({ 0: 1, length: 1 }, 0)); - if (STRICT) { - assert.throws(() => item.call(null, 0), TypeError); - assert.throws(() => item.call(undefined, 0), TypeError); - } -}); diff --git a/tests/tests/esnext.string.at-alternative.js b/tests/tests/esnext.string.at-alternative.js new file mode 100644 index 000000000000..78a070deedea --- /dev/null +++ b/tests/tests/esnext.string.at-alternative.js @@ -0,0 +1,30 @@ +// TODO: disabled by default because of the conflict with another proposal +import { STRICT } from '../helpers/constants'; + +QUnit.test('String#at', assert => { + const { at } = String.prototype; + assert.isFunction(at); + assert.arity(at, 1); + assert.name(at, 'at'); + assert.looksNative(at); + assert.nonEnumerable(String.prototype, 'at'); + assert.same('1', '123'.at(0)); + assert.same('2', '123'.at(1)); + assert.same('3', '123'.at(2)); + assert.same(undefined, '123'.at(3)); + assert.same('3', '123'.at(-1)); + assert.same('2', '123'.at(-2)); + assert.same('1', '123'.at(-3)); + assert.same(undefined, '123'.at(-4)); + assert.same('1', '123'.at(0.4)); + assert.same('1', '123'.at(0.5)); + assert.same('1', '123'.at(0.6)); + assert.same('1', '1'.at(NaN)); + assert.same('1', '1'.at()); + assert.same('1', '123'.at(-0)); + assert.same('1', at.call({ toString() { return '123'; } }, 0)); + if (STRICT) { + assert.throws(() => at.call(null, 0), TypeError); + assert.throws(() => at.call(undefined, 0), TypeError); + } +}); diff --git a/tests/tests/esnext.string.item.js b/tests/tests/esnext.string.item.js deleted file mode 100644 index a9130c806b83..000000000000 --- a/tests/tests/esnext.string.item.js +++ /dev/null @@ -1,29 +0,0 @@ -import { STRICT } from '../helpers/constants'; - -QUnit.test('String#item', assert => { - const { item } = String.prototype; - assert.isFunction(item); - assert.arity(item, 1); - assert.name(item, 'item'); - assert.looksNative(item); - assert.nonEnumerable(String.prototype, 'item'); - assert.same('1', '123'.item(0)); - assert.same('2', '123'.item(1)); - assert.same('3', '123'.item(2)); - assert.same(undefined, '123'.item(3)); - assert.same('3', '123'.item(-1)); - assert.same('2', '123'.item(-2)); - assert.same('1', '123'.item(-3)); - assert.same(undefined, '123'.item(-4)); - assert.same('1', '123'.item(0.4)); - assert.same('1', '123'.item(0.5)); - assert.same('1', '123'.item(0.6)); - assert.same('1', '1'.item(NaN)); - assert.same('1', '1'.item()); - assert.same('1', '123'.item(-0)); - assert.same('1', item.call({ toString() { return '123'; } }, 0)); - if (STRICT) { - assert.throws(() => item.call(null, 0), TypeError); - assert.throws(() => item.call(undefined, 0), TypeError); - } -}); diff --git a/tests/tests/esnext.typed-array.at.js b/tests/tests/esnext.typed-array.at.js new file mode 100644 index 000000000000..df17e436eed3 --- /dev/null +++ b/tests/tests/esnext.typed-array.at.js @@ -0,0 +1,30 @@ +import { DESCRIPTORS, GLOBAL, TYPED_ARRAYS } from '../helpers/constants'; + +if (DESCRIPTORS) QUnit.test('%TypedArrayPrototype%.indexOf', 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 { at } = TypedArray.prototype; + assert.isFunction(at); + assert.arity(at, 1); + assert.name(at, 'at'); + assert.looksNative(at); + assert.same(1, new TypedArray([1, 2, 3]).at(0)); + assert.same(2, new TypedArray([1, 2, 3]).at(1)); + assert.same(3, new TypedArray([1, 2, 3]).at(2)); + assert.same(undefined, new TypedArray([1, 2, 3]).at(3)); + assert.same(3, new TypedArray([1, 2, 3]).at(-1)); + assert.same(2, new TypedArray([1, 2, 3]).at(-2)); + assert.same(1, new TypedArray([1, 2, 3]).at(-3)); + assert.same(undefined, new TypedArray([1, 2, 3]).at(-4)); + assert.same(1, new TypedArray([1, 2, 3]).at(0.4)); + assert.same(1, new TypedArray([1, 2, 3]).at(0.5)); + assert.same(1, new TypedArray([1, 2, 3]).at(0.6)); + assert.same(1, new TypedArray([1]).at(NaN)); + assert.same(1, new TypedArray([1]).at()); + assert.same(1, new TypedArray([1, 2, 3]).at(-0)); + assert.throws(() => at.call({ 0: 1, length: 1 }, 0), TypeError); + assert.throws(() => at.call(null, 0), TypeError); + assert.throws(() => at.call(undefined, 0), TypeError); + } +}); diff --git a/tests/tests/esnext.typed-array.item.js b/tests/tests/esnext.typed-array.item.js deleted file mode 100644 index 9761ecaefa4c..000000000000 --- a/tests/tests/esnext.typed-array.item.js +++ /dev/null @@ -1,30 +0,0 @@ -import { DESCRIPTORS, GLOBAL, TYPED_ARRAYS } from '../helpers/constants'; - -if (DESCRIPTORS) QUnit.test('%TypedArrayPrototype%.indexOf', 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 { item } = TypedArray.prototype; - assert.isFunction(item); - assert.arity(item, 1); - assert.name(item, 'item'); - assert.looksNative(item); - assert.same(1, new TypedArray([1, 2, 3]).item(0)); - assert.same(2, new TypedArray([1, 2, 3]).item(1)); - assert.same(3, new TypedArray([1, 2, 3]).item(2)); - assert.same(undefined, new TypedArray([1, 2, 3]).item(3)); - assert.same(3, new TypedArray([1, 2, 3]).item(-1)); - assert.same(2, new TypedArray([1, 2, 3]).item(-2)); - assert.same(1, new TypedArray([1, 2, 3]).item(-3)); - assert.same(undefined, new TypedArray([1, 2, 3]).item(-4)); - assert.same(1, new TypedArray([1, 2, 3]).item(0.4)); - assert.same(1, new TypedArray([1, 2, 3]).item(0.5)); - assert.same(1, new TypedArray([1, 2, 3]).item(0.6)); - assert.same(1, new TypedArray([1]).item(NaN)); - assert.same(1, new TypedArray([1]).item()); - assert.same(1, new TypedArray([1, 2, 3]).item(-0)); - assert.throws(() => item.call({ 0: 1, length: 1 }, 0), TypeError); - assert.throws(() => item.call(null, 0), TypeError); - assert.throws(() => item.call(undefined, 0), TypeError); - } -}); diff --git a/tests/tests/index.js b/tests/tests/index.js index d3b14f154021..02cd2672444d 100644 --- a/tests/tests/index.js +++ b/tests/tests/index.js @@ -199,7 +199,7 @@ import './es.weak-set'; QUnit.module('ESNext'); import './esnext.array.filter-out'; import './esnext.array.is-template-object'; -import './esnext.array.item'; +import './esnext.array.at'; import './esnext.array.last-item'; import './esnext.array.last-index'; import './esnext.array.unique-by'; @@ -302,15 +302,16 @@ import './esnext.set.some'; import './esnext.set.symmetric-difference'; import './esnext.set.union'; import './esnext.string.at'; +// TODO: disabled by default because of the conflict with another proposal +// import './esnext.string.at-alternative'; import './esnext.string.code-points'; -import './esnext.string.item'; import './esnext.symbol.async-dispose'; import './esnext.symbol.dispose'; import './esnext.symbol.observable'; 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.item'; import './esnext.weak-map.delete-all'; import './esnext.weak-map.from'; import './esnext.weak-map.of'; From 8e2fc9fafec698b68704482ffd8c93fb0b255b40 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Sun, 22 Nov 2020 14:24:17 +0700 Subject: [PATCH 6/8] add a link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 59980d45dc15..33da0f587750 100644 --- a/README.md +++ b/README.md @@ -1780,7 +1780,7 @@ core-js(-pure)/stage/3 ##### [Relative indexing method](https://github.com/tc39/proposal-relative-indexing-method)[⬆](#index) Modules [`esnext.array.at`](https://github.com/zloirock/core-js/blob/v3.7.0/packages/core-js/modules/esnext.array.at.js) and [`esnext.typed-array.at`](https://github.com/zloirock/core-js/blob/v3.7.0/packages/core-js/modules/esnext.typed-array.at.js) -> **Warning! Because of the conflict with another proposal, this method is not available on `String.prototype` in this version.** +> **Warning! Because of the conflict with [another proposal](#stringat), this method is not available on `String.prototype` in this version.** ```js class Array { From 1b27991206772bb80278358d3c4b909e98f56b94 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Mon, 23 Nov 2020 02:17:15 +0700 Subject: [PATCH 7/8] fix some typos after rebasing --- packages/core-js-compat/src/data.js | 2 +- tests/compat/tests.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core-js-compat/src/data.js b/packages/core-js-compat/src/data.js index e792d91c930a..c30d045b7c10 100644 --- a/packages/core-js-compat/src/data.js +++ b/packages/core-js-compat/src/data.js @@ -1495,7 +1495,7 @@ const data = { 'esnext.symbol.replace-all': { }, 'esnext.typed-array.at': { - } + }, 'esnext.typed-array.filter-out': { }, 'esnext.weak-map.delete-all': { diff --git a/tests/compat/tests.js b/tests/compat/tests.js index 05507898dd62..0e60dd11e051 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -1105,7 +1105,7 @@ GLOBAL.tests = { }, 'esnext.array.filter-out': function () { return [].filterOut; - } + }, 'esnext.array.last-index': function () { return [1, 2, 3].lastIndex && Array.prototype[Symbol.unscopables].lastIndex; }, @@ -1448,7 +1448,7 @@ GLOBAL.tests = { }, 'esnext.typed-array.filter-out': function () { return Int8Array.prototype.filterOut; - } + }, 'esnext.weak-map.delete-all': function () { return WeakMap.prototype.deleteAll; }, From 9c07cee78d3b3d5cb2765dcedd3ec9f66c9a363a Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Tue, 24 Nov 2020 15:17:30 +0700 Subject: [PATCH 8/8] add code points / code units explicit feature detection for `String#at` --- CHANGELOG.md | 1 + packages/core-js/modules/esnext.string.at-alternative.js | 7 ++++++- packages/core-js/modules/esnext.string.at.js | 7 ++++++- tests/compat/tests.js | 2 +- tests/pure/esnext.string.at-alternative.js | 1 + tests/tests/esnext.string.at-alternative.js | 1 + 6 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 747d5f7c7c67..d5ce626f9891 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - `%TypedArray%#filterOut` - Added [array deduplication stage 1 proposal](https://github.com/tc39/proposal-array-unique) - `Array#uniqueBy` +- Added code points / code units explicit feature detection in `String#at` for preventing breakage code which use obsolete `String#at` proposal polyfill - Added the missed `(es|stable)/instance/replace-all` entries - Updated compat data mapping for Opera - from Opera 69, the difference with Chrome versions increased to 14 - Compat data mapping for modern Android WebView to Chrome moved from targets parser directly to compat data diff --git a/packages/core-js/modules/esnext.string.at-alternative.js b/packages/core-js/modules/esnext.string.at-alternative.js index 5591cbcd59bd..5158e2e75594 100644 --- a/packages/core-js/modules/esnext.string.at-alternative.js +++ b/packages/core-js/modules/esnext.string.at-alternative.js @@ -4,10 +4,15 @@ var $ = require('../internals/export'); var requireObjectCoercible = require('../internals/require-object-coercible'); var toLength = require('../internals/to-length'); var toInteger = require('../internals/to-integer'); +var fails = require('../internals/fails'); + +var FORCED = fails(function () { + return '𠮷'.at(0) !== '\uD842'; +}); // `String.prototype.at` method // https://github.com/tc39/proposal-relative-indexing-method -$({ target: 'String', proto: true }, { +$({ target: 'String', proto: true, forced: FORCED }, { at: function at(index) { var S = String(requireObjectCoercible(this)); var len = toLength(S.length); diff --git a/packages/core-js/modules/esnext.string.at.js b/packages/core-js/modules/esnext.string.at.js index fc3c44a76063..be0ce4049a40 100644 --- a/packages/core-js/modules/esnext.string.at.js +++ b/packages/core-js/modules/esnext.string.at.js @@ -1,10 +1,15 @@ 'use strict'; var $ = require('../internals/export'); var charAt = require('../internals/string-multibyte').charAt; +var fails = require('../internals/fails'); + +var FORCED = fails(function () { + return '𠮷'.at(0) !== '𠮷'; +}); // `String.prototype.at` method // https://github.com/mathiasbynens/String.prototype.at -$({ target: 'String', proto: true }, { +$({ target: 'String', proto: true, forced: FORCED }, { at: function at(pos) { return charAt(this, pos); } diff --git a/tests/compat/tests.js b/tests/compat/tests.js index 0e60dd11e051..9a8cded1617e 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -1425,7 +1425,7 @@ GLOBAL.tests = { return Set.prototype.union; }, 'esnext.string.at': function () { - return String.prototype.at; + return '𠮷'.at(0) === '𠮷'; }, 'esnext.string.code-points': function () { return String.prototype.codePoints; diff --git a/tests/pure/esnext.string.at-alternative.js b/tests/pure/esnext.string.at-alternative.js index bcd26e9bddff..834298592aaf 100644 --- a/tests/pure/esnext.string.at-alternative.js +++ b/tests/pure/esnext.string.at-alternative.js @@ -19,6 +19,7 @@ QUnit.test('String#at', assert => { assert.same('1', at('1', NaN)); assert.same('1', at('1')); assert.same('1', at('123', -0)); + assert.same('\uD842', at('𠮷')); assert.same('1', at({ toString() { return '123'; } }, 0)); if (STRICT) { assert.throws(() => at(null, 0), TypeError); diff --git a/tests/tests/esnext.string.at-alternative.js b/tests/tests/esnext.string.at-alternative.js index 78a070deedea..e84bcf3fadea 100644 --- a/tests/tests/esnext.string.at-alternative.js +++ b/tests/tests/esnext.string.at-alternative.js @@ -22,6 +22,7 @@ QUnit.test('String#at', assert => { assert.same('1', '1'.at(NaN)); assert.same('1', '1'.at()); assert.same('1', '123'.at(-0)); + assert.same('\uD842', '𠮷'.at()); assert.same('1', at.call({ toString() { return '123'; } }, 0)); if (STRICT) { assert.throws(() => at.call(null, 0), TypeError);