Skip to content

Commit

Permalink
add proposal for a .item() method on all the built-in indexables
Browse files Browse the repository at this point in the history
  • Loading branch information
zloirock committed Nov 15, 2020
1 parent 063adf7 commit 546d802
Show file tree
Hide file tree
Showing 28 changed files with 308 additions and 1 deletion.
39 changes: 38 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1778,7 +1778,44 @@ Promise.any([

#### Stage 3 proposals[⬆](#index)

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)
Expand Down
6 changes: 6 additions & 0 deletions packages/core-js-compat/src/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -1256,6 +1256,8 @@ const data = {
'esnext.aggregate-error': null,
'esnext.array.is-template-object': {
},
'esnext.array.item': {
},
'esnext.array.last-index': {
},
'esnext.array.last-item': {
Expand Down Expand Up @@ -1470,6 +1472,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,
Expand All @@ -1484,6 +1488,8 @@ const data = {
// TODO: Remove from `core-js@4`
'esnext.symbol.replace-all': {
},
'esnext.typed-array.item': {
},
'esnext.weak-map.delete-all': {
},
'esnext.weak-map.from': {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// empty
1 change: 1 addition & 0 deletions packages/core-js/features/array/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var parent = require('../../es/array');
require('../../modules/esnext.array.is-template-object');
require('../../modules/esnext.array.item');
require('../../modules/esnext.array.last-item');
require('../../modules/esnext.array.last-index');

Expand Down
4 changes: 4 additions & 0 deletions packages/core-js/features/array/item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require('../../modules/esnext.array.item');
var entryUnbind = require('../../internals/entry-unbind');

module.exports = entryUnbind('Array', 'item');
1 change: 1 addition & 0 deletions packages/core-js/features/array/virtual/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
var parent = require('../../../es/array/virtual');
require('../../../modules/esnext.array.item');

module.exports = parent;
4 changes: 4 additions & 0 deletions packages/core-js/features/array/virtual/item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require('../../../modules/esnext.array.item');
var entryVirtual = require('../../../internals/entry-virtual');

module.exports = entryVirtual('Array').item;
13 changes: 13 additions & 0 deletions packages/core-js/features/instance/item.js
Original file line number Diff line number Diff line change
@@ -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;
};
1 change: 1 addition & 0 deletions packages/core-js/features/string/index.js
Original file line number Diff line number Diff line change
@@ -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');
Expand Down
4 changes: 4 additions & 0 deletions packages/core-js/features/string/item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require('../../modules/esnext.string.item');
var entryUnbind = require('../../internals/entry-unbind');

module.exports = entryUnbind('String', 'item');
1 change: 1 addition & 0 deletions packages/core-js/features/string/virtual/index.js
Original file line number Diff line number Diff line change
@@ -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');
Expand Down
4 changes: 4 additions & 0 deletions packages/core-js/features/string/virtual/item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require('../../../modules/esnext.string.item');
var entryVirtual = require('../../../internals/entry-virtual');

module.exports = entryVirtual('String').item;
1 change: 1 addition & 0 deletions packages/core-js/features/typed-array/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
var parent = require('../../es/typed-array');
require('../../modules/esnext.typed-array.item');

module.exports = parent;
1 change: 1 addition & 0 deletions packages/core-js/features/typed-array/item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require('../../modules/esnext.typed-array.item');
20 changes: 20 additions & 0 deletions packages/core-js/modules/esnext.array.item.js
Original file line number Diff line number Diff line change
@@ -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');
17 changes: 17 additions & 0 deletions packages/core-js/modules/esnext.string.item.js
Original file line number Diff line number Diff line change
@@ -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);
}
});
17 changes: 17 additions & 0 deletions packages/core-js/modules/esnext.typed-array.item.js
Original file line number Diff line number Diff line change
@@ -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];
});
4 changes: 4 additions & 0 deletions packages/core-js/proposals/item-method.js
Original file line number Diff line number Diff line change
@@ -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');
1 change: 1 addition & 0 deletions packages/core-js/stage/3.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require('../proposals/item-method');
var parent = require('./4');

module.exports = parent;
13 changes: 13 additions & 0 deletions tests/commonjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) {
ok(typeof load('features/array/filter') === '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');
Expand Down Expand Up @@ -98,6 +99,7 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) {
ok(typeof load('features/array/virtual/filter') === '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');
Expand Down Expand Up @@ -203,6 +205,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');
Expand Down Expand Up @@ -232,6 +235,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');
Expand Down Expand Up @@ -1256,6 +1260,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);
Expand Down Expand Up @@ -1634,6 +1646,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');
Expand Down
9 changes: 9 additions & 0 deletions tests/compat/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,9 @@ GLOBAL.tests = {
&& set.add({}) == set
&& set[Symbol.toStringTag];
}],
'esnext.array.item': function () {
return [].item;
},
'esnext.array.last-index': function () {
return [1, 2, 3].lastIndex && Array.prototype[Symbol.unscopables].lastIndex;
},
Expand Down Expand Up @@ -1414,6 +1417,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;
},
Expand All @@ -1427,6 +1433,9 @@ GLOBAL.tests = {
'esnext.symbol.replace-all': function () {
return Symbol.replaceAll;
},
'esnext.typed-array.item': function () {
return Int8Array.prototype.item;
},
'esnext.weak-map.delete-all': function () {
return WeakMap.prototype.deleteAll;
},
Expand Down
27 changes: 27 additions & 0 deletions tests/pure/esnext.array.item.js
Original file line number Diff line number Diff line change
@@ -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);
}
});
26 changes: 26 additions & 0 deletions tests/pure/esnext.string.item.js
Original file line number Diff line number Diff line change
@@ -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);
}
});
2 changes: 2 additions & 0 deletions tests/pure/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ import './es.weak-map';
import './es.weak-set';

QUnit.module('ESNext');
import './esnext.array.item';
import './esnext.array.is-template-object';
import './esnext.async-iterator.constructor';
import './esnext.async-iterator.as-indexed-pairs';
Expand Down Expand Up @@ -242,6 +243,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';
Expand Down
30 changes: 30 additions & 0 deletions tests/tests/esnext.array.item.js
Original file line number Diff line number Diff line change
@@ -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);
}
});

0 comments on commit 546d802

Please sign in to comment.