diff --git a/CHANGELOG.md b/CHANGELOG.md index 7326233e3028..1c8587039fca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ## Changelog ##### Unreleased -- Nothing +- Added a workaround of most cases breakage modern `String#at` after loading obsolete `String#at` proposal module, [#1019](https://github.com/zloirock/core-js/issues/1019) ##### 3.19.3 - 2021.12.06 - Fixed internal slots check in methods of some built-in types, [#1017](https://github.com/zloirock/core-js/issues/1017) diff --git a/packages/core-js/modules/es.string.at-alternative.js b/packages/core-js/modules/es.string.at-alternative.js index 6d8ed7a8ec18..3ffb5fed367a 100644 --- a/packages/core-js/modules/es.string.at-alternative.js +++ b/packages/core-js/modules/es.string.at-alternative.js @@ -9,7 +9,7 @@ var fails = require('../internals/fails'); var charAt = uncurryThis(''.charAt); var FORCED = fails(function () { - return '𠮷'.at(0) !== '\uD842'; + return '𠮷'.at(-2) !== '\uD842'; }); // `String.prototype.at` method diff --git a/packages/core-js/modules/esnext.string.at.js b/packages/core-js/modules/esnext.string.at.js index be0ce4049a40..e411f8f3ba24 100644 --- a/packages/core-js/modules/esnext.string.at.js +++ b/packages/core-js/modules/esnext.string.at.js @@ -2,15 +2,22 @@ var $ = require('../internals/export'); var charAt = require('../internals/string-multibyte').charAt; var fails = require('../internals/fails'); +var requireObjectCoercible = require('../internals/require-object-coercible'); +var toIntegerOrInfinity = require('../internals/to-integer-or-infinity'); +var toString = require('../internals/to-string'); var FORCED = fails(function () { - return '𠮷'.at(0) !== '𠮷'; + return '𠮷'.at(-2) !== '𠮷'; }); // `String.prototype.at` method // https://github.com/mathiasbynens/String.prototype.at $({ target: 'String', proto: true, forced: FORCED }, { - at: function at(pos) { - return charAt(this, pos); + at: function at(index) { + var S = toString(requireObjectCoercible(this)); + var len = S.length; + var relativeIndex = toIntegerOrInfinity(index); + var k = relativeIndex >= 0 ? relativeIndex : len + relativeIndex; + return (k < 0 || k >= len) ? undefined : charAt(S, k); } }); diff --git a/tests/compat/tests.js b/tests/compat/tests.js index 6831f37c0a8b..8c2b5744b9af 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -889,7 +889,7 @@ GLOBAL.tests = { && set[Symbol.toStringTag]; }], 'es.string.at-alternative': function () { - return 'a'.at(-1) === 'a'; + return '𠮷'.at(-2) === '\uD842'; }, 'es.string.code-point-at': function () { return String.prototype.codePointAt; diff --git a/tests/pure/es.string.at-alternative.js b/tests/pure/es.string.at-alternative.js index 7b4fc2f2c98e..3d0bb8034bf3 100644 --- a/tests/pure/es.string.at-alternative.js +++ b/tests/pure/es.string.at-alternative.js @@ -1,10 +1,9 @@ -// TODO: disabled by default because of the conflict with another proposal import { STRICT } from '../helpers/constants'; import at from 'core-js-pure/es/string/at'; import Symbol from 'core-js-pure/es/symbol'; -QUnit.skip('String#at', assert => { +QUnit.test('String#at', assert => { assert.isFunction(at); assert.same('1', at('123', 0)); assert.same('2', at('123', 1)); @@ -20,7 +19,8 @@ QUnit.skip('String#at', assert => { assert.same('1', at('1', NaN)); assert.same('1', at('1')); assert.same('1', at('123', -0)); - assert.same('\uD842', at('𠮷')); + // TODO: disabled by default because of the conflict with old proposal + // assert.same('\uD842', at('𠮷')); assert.same('1', at({ toString() { return '123'; } }, 0)); assert.throws(() => at(Symbol(), 0), 'throws on symbol context'); diff --git a/tests/pure/esnext.string.at.js b/tests/pure/esnext.string.at.js index 655ab35d699d..895652f1fb73 100644 --- a/tests/pure/esnext.string.at.js +++ b/tests/pure/esnext.string.at.js @@ -5,16 +5,16 @@ import at from 'core-js-pure/features/string/at'; QUnit.test('String#at', assert => { assert.isFunction(at); // String that starts with a BMP symbol - assert.same(at('abc\uD834\uDF06def', -Infinity), ''); - assert.same(at('abc\uD834\uDF06def', -1), ''); + // assert.same(at('abc\uD834\uDF06def', -Infinity), ''); + // assert.same(at('abc\uD834\uDF06def', -1), ''); assert.same(at('abc\uD834\uDF06def', -0), 'a'); assert.same(at('abc\uD834\uDF06def', +0), 'a'); assert.same(at('abc\uD834\uDF06def', 1), 'b'); assert.same(at('abc\uD834\uDF06def', 3), '\uD834\uDF06'); assert.same(at('abc\uD834\uDF06def', 4), '\uDF06'); assert.same(at('abc\uD834\uDF06def', 5), 'd'); - assert.same(at('abc\uD834\uDF06def', 42), ''); - assert.same(at('abc\uD834\uDF06def', Infinity), ''); + // assert.same(at('abc\uD834\uDF06def', 42), ''); + // assert.same(at('abc\uD834\uDF06def', Infinity), ''); assert.same(at('abc\uD834\uDF06def', null), 'a'); assert.same(at('abc\uD834\uDF06def', undefined), 'a'); assert.same(at('abc\uD834\uDF06def'), 'a'); @@ -28,18 +28,18 @@ QUnit.test('String#at', assert => { assert.same(at('abc\uD834\uDF06def', -0.9), 'a'); assert.same(at('abc\uD834\uDF06def', 1.9), 'b'); assert.same(at('abc\uD834\uDF06def', 7.9), 'f'); - assert.same(at('abc\uD834\uDF06def', 2 ** 32), ''); + // assert.same(at('abc\uD834\uDF06def', 2 ** 32), ''); // String that starts with an astral symbol - assert.same(at('\uD834\uDF06def', -Infinity), ''); - assert.same(at('\uD834\uDF06def', -1), ''); + // assert.same(at('\uD834\uDF06def', -Infinity), ''); + // assert.same(at('\uD834\uDF06def', -1), ''); assert.same(at('\uD834\uDF06def', -0), '\uD834\uDF06'); assert.same(at('\uD834\uDF06def', 0), '\uD834\uDF06'); assert.same(at('\uD834\uDF06def', 1), '\uDF06'); assert.same(at('\uD834\uDF06def', 2), 'd'); assert.same(at('\uD834\uDF06def', 3), 'e'); assert.same(at('\uD834\uDF06def', 4), 'f'); - assert.same(at('\uD834\uDF06def', 42), ''); - assert.same(at('\uD834\uDF06def', Infinity), ''); + // assert.same(at('\uD834\uDF06def', 42), ''); + // assert.same(at('\uD834\uDF06def', Infinity), ''); assert.same(at('\uD834\uDF06def', null), '\uD834\uDF06'); assert.same(at('\uD834\uDF06def', undefined), '\uD834\uDF06'); assert.same(at('\uD834\uDF06def'), '\uD834\uDF06'); @@ -49,13 +49,13 @@ QUnit.test('String#at', assert => { assert.same(at('\uD834\uDF06def', '_'), '\uD834\uDF06'); assert.same(at('\uD834\uDF06def', '1'), '\uDF06'); // Lone high surrogates - assert.same(at('\uD834abc', -Infinity), ''); - assert.same(at('\uD834abc', -1), ''); + // assert.same(at('\uD834abc', -Infinity), ''); + // assert.same(at('\uD834abc', -1), ''); assert.same(at('\uD834abc', -0), '\uD834'); assert.same(at('\uD834abc', 0), '\uD834'); assert.same(at('\uD834abc', 1), 'a'); - assert.same(at('\uD834abc', 42), ''); - assert.same(at('\uD834abc', Infinity), ''); + // assert.same(at('\uD834abc', 42), ''); + // assert.same(at('\uD834abc', Infinity), ''); assert.same(at('\uD834abc', null), '\uD834'); assert.same(at('\uD834abc', undefined), '\uD834'); assert.same(at('\uD834abc'), '\uD834'); @@ -65,13 +65,13 @@ QUnit.test('String#at', assert => { assert.same(at('\uD834abc', '_'), '\uD834'); assert.same(at('\uD834abc', '1'), 'a'); // Lone low surrogates - assert.same(at('\uDF06abc', -Infinity), ''); - assert.same(at('\uDF06abc', -1), ''); + // assert.same(at('\uDF06abc', -Infinity), ''); + // assert.same(at('\uDF06abc', -1), ''); assert.same(at('\uDF06abc', -0), '\uDF06'); assert.same(at('\uDF06abc', 0), '\uDF06'); assert.same(at('\uDF06abc', 1), 'a'); - assert.same(at('\uDF06abc', 42), ''); - assert.same(at('\uDF06abc', Infinity), ''); + // assert.same(at('\uDF06abc', 42), ''); + // assert.same(at('\uDF06abc', Infinity), ''); assert.same(at('\uDF06abc', null), '\uDF06'); assert.same(at('\uDF06abc', undefined), '\uDF06'); assert.same(at('\uDF06abc'), '\uDF06'); diff --git a/tests/tests/es.string.at-alternative.js b/tests/tests/es.string.at-alternative.js index 9df007315b92..c38bae24307f 100644 --- a/tests/tests/es.string.at-alternative.js +++ b/tests/tests/es.string.at-alternative.js @@ -1,7 +1,6 @@ -// TODO: disabled by default because of the conflict with another proposal import { STRICT } from '../helpers/constants'; -QUnit.skip('String#at', assert => { +QUnit.test('String#at', assert => { const { at } = String.prototype; assert.isFunction(at); assert.arity(at, 1); @@ -22,7 +21,8 @@ QUnit.skip('String#at', assert => { assert.same('1', '1'.at(NaN)); assert.same('1', '1'.at()); assert.same('1', '123'.at(-0)); - assert.same('\uD842', '𠮷'.at()); + // TODO: disabled by default because of the conflict with old proposal + // assert.same('\uD842', '𠮷'.at()); assert.same('1', at.call({ toString() { return '123'; } }, 0)); assert.throws(() => at.call(Symbol(), 0), 'throws on symbol context'); diff --git a/tests/tests/esnext.string.at.js b/tests/tests/esnext.string.at.js index 82806aa30f18..308c30df21f8 100644 --- a/tests/tests/esnext.string.at.js +++ b/tests/tests/esnext.string.at.js @@ -8,16 +8,16 @@ QUnit.test('String#at', assert => { assert.looksNative(at); assert.nonEnumerable(String.prototype, 'at'); // String that starts with a BMP symbol - assert.same('abc\uD834\uDF06def'.at(-Infinity), ''); - assert.same('abc\uD834\uDF06def'.at(-1), ''); + // assert.same('abc\uD834\uDF06def'.at(-Infinity), ''); + // assert.same('abc\uD834\uDF06def'.at(-1), ''); assert.same('abc\uD834\uDF06def'.at(-0), 'a'); assert.same('abc\uD834\uDF06def'.at(+0), 'a'); assert.same('abc\uD834\uDF06def'.at(1), 'b'); assert.same('abc\uD834\uDF06def'.at(3), '\uD834\uDF06'); assert.same('abc\uD834\uDF06def'.at(4), '\uDF06'); assert.same('abc\uD834\uDF06def'.at(5), 'd'); - assert.same('abc\uD834\uDF06def'.at(42), ''); - assert.same('abc\uD834\uDF06def'.at(Infinity), ''); + // assert.same('abc\uD834\uDF06def'.at(42), ''); + // assert.same('abc\uD834\uDF06def'.at(Infinity), ''); assert.same('abc\uD834\uDF06def'.at(null), 'a'); assert.same('abc\uD834\uDF06def'.at(undefined), 'a'); assert.same('abc\uD834\uDF06def'.at(), 'a'); @@ -31,18 +31,18 @@ QUnit.test('String#at', assert => { assert.same('abc\uD834\uDF06def'.at(-0.9), 'a'); assert.same('abc\uD834\uDF06def'.at(1.9), 'b'); assert.same('abc\uD834\uDF06def'.at(7.9), 'f'); - assert.same('abc\uD834\uDF06def'.at(2 ** 32), ''); + // assert.same('abc\uD834\uDF06def'.at(2 ** 32), ''); // String that starts with an astral symbol - assert.same('\uD834\uDF06def'.at(-Infinity), ''); - assert.same('\uD834\uDF06def'.at(-1), ''); + // assert.same('\uD834\uDF06def'.at(-Infinity), ''); + // assert.same('\uD834\uDF06def'.at(-1), ''); assert.same('\uD834\uDF06def'.at(-0), '\uD834\uDF06'); assert.same('\uD834\uDF06def'.at(0), '\uD834\uDF06'); assert.same('\uD834\uDF06def'.at(1), '\uDF06'); assert.same('\uD834\uDF06def'.at(2), 'd'); assert.same('\uD834\uDF06def'.at(3), 'e'); assert.same('\uD834\uDF06def'.at(4), 'f'); - assert.same('\uD834\uDF06def'.at(42), ''); - assert.same('\uD834\uDF06def'.at(Infinity), ''); + // assert.same('\uD834\uDF06def'.at(42), ''); + // assert.same('\uD834\uDF06def'.at(Infinity), ''); assert.same('\uD834\uDF06def'.at(null), '\uD834\uDF06'); assert.same('\uD834\uDF06def'.at(undefined), '\uD834\uDF06'); assert.same('\uD834\uDF06def'.at(), '\uD834\uDF06'); @@ -52,13 +52,13 @@ QUnit.test('String#at', assert => { assert.same('\uD834\uDF06def'.at('_'), '\uD834\uDF06'); assert.same('\uD834\uDF06def'.at('1'), '\uDF06'); // Lone high surrogates - assert.same('\uD834abc'.at(-Infinity), ''); - assert.same('\uD834abc'.at(-1), ''); + // assert.same('\uD834abc'.at(-Infinity), ''); + // assert.same('\uD834abc'.at(-1), ''); assert.same('\uD834abc'.at(-0), '\uD834'); assert.same('\uD834abc'.at(0), '\uD834'); assert.same('\uD834abc'.at(1), 'a'); - assert.same('\uD834abc'.at(42), ''); - assert.same('\uD834abc'.at(Infinity), ''); + // assert.same('\uD834abc'.at(42), ''); + // assert.same('\uD834abc'.at(Infinity), ''); assert.same('\uD834abc'.at(null), '\uD834'); assert.same('\uD834abc'.at(undefined), '\uD834'); assert.same('\uD834abc'.at(), '\uD834'); @@ -68,13 +68,13 @@ QUnit.test('String#at', assert => { assert.same('\uD834abc'.at('_'), '\uD834'); assert.same('\uD834abc'.at('1'), 'a'); // Lone low surrogates - assert.same('\uDF06abc'.at(-Infinity), ''); - assert.same('\uDF06abc'.at(-1), ''); + // assert.same('\uDF06abc'.at(-Infinity), ''); + // assert.same('\uDF06abc'.at(-1), ''); assert.same('\uDF06abc'.at(-0), '\uDF06'); assert.same('\uDF06abc'.at(0), '\uDF06'); assert.same('\uDF06abc'.at(1), 'a'); - assert.same('\uDF06abc'.at(42), ''); - assert.same('\uDF06abc'.at(Infinity), ''); + // assert.same('\uDF06abc'.at(42), ''); + // assert.same('\uDF06abc'.at(Infinity), ''); assert.same('\uDF06abc'.at(null), '\uDF06'); assert.same('\uDF06abc'.at(undefined), '\uDF06'); assert.same('\uDF06abc'.at(), '\uDF06');