Skip to content

Commit

Permalink
Merge pull request #889 from zloirock/item-method
Browse files Browse the repository at this point in the history
  • Loading branch information
zloirock committed Nov 24, 2020
2 parents 744f617 + 9c07cee commit 5a1efc1
Show file tree
Hide file tree
Showing 29 changed files with 310 additions and 7 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,8 @@
## Changelog
##### Unreleased
- 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`
Expand All @@ -8,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
Expand Down
35 changes: 34 additions & 1 deletion README.md
Expand Up @@ -1778,7 +1778,40 @@ Promise.any([
core-js(-pure)/stage/3
```

None.
##### [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](#stringat), this method is not available on `String.prototype` in this version.**

```js
class Array {
at(index: int): any;
}
class [
Int8Array,
Uint8Array,
Uint8ClampedArray,
Int16Array,
Uint16Array,
Int32Array,
Uint32Array,
Float32Array,
Float64Array,
] {
at(index: int): any;
}
```
[*CommonJS entry points:*](#commonjs-api)
```
core-js/proposals/relative-indexing-method
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.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].at(1); // => 2
[1, 2, 3].at(-1); // => 3
```

#### Stage 2 proposals[⬆](#index)
[*CommonJS entry points:*](#commonjs-api)
Expand Down
4 changes: 4 additions & 0 deletions packages/core-js-compat/src/data.js
Expand Up @@ -1258,6 +1258,8 @@ const data = {
},
'esnext.array.is-template-object': {
},
'esnext.array.at': {
},
'esnext.array.last-index': {
},
'esnext.array.last-item': {
Expand Down Expand Up @@ -1492,6 +1494,8 @@ const data = {
// TODO: Remove from `core-js@4`
'esnext.symbol.replace-all': {
},
'esnext.typed-array.at': {
},
'esnext.typed-array.filter-out': {
},
'esnext.weak-map.delete-all': {
Expand Down
2 changes: 2 additions & 0 deletions packages/core-js-compat/src/modules-by-versions.js
Expand Up @@ -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',
],
};
@@ -0,0 +1 @@
// empty
4 changes: 4 additions & 0 deletions 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');
1 change: 1 addition & 0 deletions packages/core-js/features/array/index.js
@@ -1,5 +1,6 @@
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.last-item');
Expand Down
4 changes: 4 additions & 0 deletions 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;
2 changes: 2 additions & 0 deletions packages/core-js/features/array/virtual/index.js
@@ -1,4 +1,6 @@
var parent = require('../../../es/array/virtual');
require('../../../modules/esnext.array.at');
require('../../../modules/esnext.array.filter-out');
require('../../../modules/esnext.array.unique-by');

module.exports = parent;
10 changes: 7 additions & 3 deletions 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;
};
2 changes: 2 additions & 0 deletions packages/core-js/features/string/index.js
@@ -1,5 +1,7 @@
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');
// TODO: remove from `core-js@4`
require('../../modules/esnext.string.match-all');
Expand Down
2 changes: 2 additions & 0 deletions packages/core-js/features/string/virtual/index.js
@@ -1,5 +1,7 @@
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');
// TODO: remove from `core-js@4`
require('../../../modules/esnext.string.match-all');
Expand Down
1 change: 1 addition & 0 deletions packages/core-js/features/typed-array/at.js
@@ -0,0 +1 @@
require('../../modules/esnext.typed-array.at');
1 change: 1 addition & 0 deletions packages/core-js/features/typed-array/index.js
@@ -1,4 +1,5 @@
var parent = require('../../es/typed-array');
require('../../modules/esnext.typed-array.at');
require('../../modules/esnext.typed-array.filter-out');

module.exports = parent;
20 changes: 20 additions & 0 deletions packages/core-js/modules/esnext.array.at.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.at` method
// https://github.com/tc39/proposal-relative-indexing-method
$({ target: 'Array', proto: true }, {
at: function at(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('at');
23 changes: 23 additions & 0 deletions packages/core-js/modules/esnext.string.at-alternative.js
@@ -0,0 +1,23 @@
// 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');
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, forced: FORCED }, {
at: function at(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);
}
});
7 changes: 6 additions & 1 deletion 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);
}
Expand Down
17 changes: 17 additions & 0 deletions packages/core-js/modules/esnext.typed-array.at.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.at` method
// https://github.com/tc39/proposal-relative-indexing-method
exportTypedArrayMethod('at', function at(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];
});
5 changes: 5 additions & 0 deletions packages/core-js/proposals/relative-indexing-method.js
@@ -0,0 +1,5 @@
// https://github.com/tc39/proposal-relative-indexing-method
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');
1 change: 1 addition & 0 deletions packages/core-js/stage/3.js
@@ -1,3 +1,4 @@
require('../proposals/relative-indexing-method');
var parent = require('./4');

module.exports = parent;
10 changes: 9 additions & 1 deletion tests/commonjs.js
Expand Up @@ -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);
Expand Down Expand Up @@ -92,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);
Expand Down Expand Up @@ -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/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');
Expand Down Expand Up @@ -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/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');
Expand Down Expand Up @@ -977,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');
Expand All @@ -999,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');
Expand Down Expand Up @@ -1653,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');
Expand Down
8 changes: 7 additions & 1 deletion tests/compat/tests.js
Expand Up @@ -1100,6 +1100,9 @@ GLOBAL.tests = {
&& set.add({}) == set
&& set[Symbol.toStringTag];
}],
'esnext.array.at': function () {
return [].at;
},
'esnext.array.filter-out': function () {
return [].filterOut;
},
Expand Down Expand Up @@ -1422,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;
Expand All @@ -1440,6 +1443,9 @@ 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;
},
Expand Down
27 changes: 27 additions & 0 deletions 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);
}
});
28 changes: 28 additions & 0 deletions tests/pure/esnext.string.at-alternative.js
@@ -0,0 +1,28 @@
// 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('\uD842', at('𠮷'));
assert.same('1', at({ toString() { return '123'; } }, 0));
if (STRICT) {
assert.throws(() => at(null, 0), TypeError);
assert.throws(() => at(undefined, 0), TypeError);
}
});

0 comments on commit 5a1efc1

Please sign in to comment.