Skip to content

Commit

Permalink
fix early implementations of Array#{ slice, splice } for the usage …
Browse files Browse the repository at this point in the history
…of `ToLength`
  • Loading branch information
zloirock committed Dec 27, 2019
1 parent e4cea55 commit 0186287
Show file tree
Hide file tree
Showing 14 changed files with 57 additions and 30 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Changelog
##### Unreleased
- Fixed early implementations of `Array#{ every, forEach, includes, indexOf, lastIndexOf, reduce, reduceRight, some }` for the usage of `ToLength`
- Fixed early implementations of `Array#{ every, forEach, includes, indexOf, lastIndexOf, reduce, reduceRight, slice, some, splice }` for the usage of `ToLength`

##### 3.6.1 - 2019.12.25
- Fixed a bug related `Symbol` with multiple copies of `core-js` (for `3.4.2-3.6.0`), [#736](https://github.com/zloirock/core-js/issues/736)
Expand Down
8 changes: 4 additions & 4 deletions packages/core-js-compat/src/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,9 +217,9 @@ const data = {
},
'es.array.slice': {
chrome: '51',
edge: '13',
edge: '15',
firefox: '48',
safari: '10.0',
safari: '11.0',
},
'es.array.some': {
chrome: '48',
Expand All @@ -241,9 +241,9 @@ const data = {
},
'es.array.splice': {
chrome: '51',
edge: '13',
edge: '15',
firefox: '49',
safari: '10.0',
safari: '11.0',
},
'es.array.unscopables.flat': {
chrome: '73',
Expand Down
2 changes: 1 addition & 1 deletion packages/core-js/internals/array-last-index-of.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ var min = Math.min;
var nativeLastIndexOf = [].lastIndexOf;
var NEGATIVE_ZERO = !!nativeLastIndexOf && 1 / [1].lastIndexOf(1, -0) < 0;
var SLOPPY_METHOD = sloppyArrayMethod('lastIndexOf');
var USES_TO_LENGTH = arrayMethodUsesToLength('lastIndexOf', 2147483647, true);
var USES_TO_LENGTH = arrayMethodUsesToLength('lastIndexOf', { ACCESSORS: true, 1: 2147483647 });
var FORCED = NEGATIVE_ZERO || SLOPPY_METHOD || !USES_TO_LENGTH;

// `Array.prototype.lastIndexOf` method implementation
Expand Down
17 changes: 11 additions & 6 deletions packages/core-js/internals/array-method-uses-to-length.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
var DESCRIPTORS = require('../internals/descriptors');
var fails = require('../internals/fails');
var has = require('../internals/has');

var defineProperty = Object.defineProperty;

var thrower = function (it) { throw it; };

module.exports = function (METHOD_NAME, argument, ACCESSORS) {
module.exports = function (METHOD_NAME, options) {
if (!options) options = {};
var method = [][METHOD_NAME];
var ACCESSORS = has(options, 'ACCESSORS') ? options.ACCESSORS : false;
var argument0 = has(options, 0) ? options[0] : thrower;
var argument1 = has(options, 1) ? options[1] : undefined;

return !!method && !fails(function () {
if (ACCESSORS && !DESCRIPTORS) return true;
var O = { length: -1 };

var add = function (key) {
var addTrap = function (key) {
if (ACCESSORS) defineProperty(O, key, { enumerable: true, get: thrower });
else O[key] = 1;
};

add(1);
add(2147483646);
add(4294967294);
method.call(O, thrower, argument);
addTrap(1);
addTrap(2147483646);
addTrap(4294967294);
method.call(O, argument0, argument1);
});
};
2 changes: 1 addition & 1 deletion packages/core-js/modules/es.array.includes.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ var $includes = require('../internals/array-includes').includes;
var addToUnscopables = require('../internals/add-to-unscopables');
var arrayMethodUsesToLength = require('../internals/array-method-uses-to-length');

var USES_TO_LENGTH = arrayMethodUsesToLength('indexOf', 0, true);
var USES_TO_LENGTH = arrayMethodUsesToLength('indexOf', { ACCESSORS: true, 1: 0 });

// `Array.prototype.includes` method
// https://tc39.github.io/ecma262/#sec-array.prototype.includes
Expand Down
2 changes: 1 addition & 1 deletion packages/core-js/modules/es.array.index-of.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ var nativeIndexOf = [].indexOf;

var NEGATIVE_ZERO = !!nativeIndexOf && 1 / [1].indexOf(1, -0) < 0;
var SLOPPY_METHOD = sloppyArrayMethod('indexOf');
var USES_TO_LENGTH = arrayMethodUsesToLength('indexOf', 0, true);
var USES_TO_LENGTH = arrayMethodUsesToLength('indexOf', { ACCESSORS: true, 1: 0 });

// `Array.prototype.indexOf` method
// https://tc39.github.io/ecma262/#sec-array.prototype.indexof
Expand Down
2 changes: 1 addition & 1 deletion packages/core-js/modules/es.array.reduce-right.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ var sloppyArrayMethod = require('../internals/sloppy-array-method');
var arrayMethodUsesToLength = require('../internals/array-method-uses-to-length');

var SLOPPY_METHOD = sloppyArrayMethod('reduceRight');
var USES_TO_LENGTH = arrayMethodUsesToLength('reduceRight', 0);
var USES_TO_LENGTH = arrayMethodUsesToLength('reduceRight', { 1: 0 });

// `Array.prototype.reduceRight` method
// https://tc39.github.io/ecma262/#sec-array.prototype.reduceright
Expand Down
2 changes: 1 addition & 1 deletion packages/core-js/modules/es.array.reduce.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ var sloppyArrayMethod = require('../internals/sloppy-array-method');
var arrayMethodUsesToLength = require('../internals/array-method-uses-to-length');

var SLOPPY_METHOD = sloppyArrayMethod('reduce');
var USES_TO_LENGTH = arrayMethodUsesToLength('reduce', 0);
var USES_TO_LENGTH = arrayMethodUsesToLength('reduce', { 1: 0 });

// `Array.prototype.reduce` method
// https://tc39.github.io/ecma262/#sec-array.prototype.reduce
Expand Down
8 changes: 6 additions & 2 deletions packages/core-js/modules/es.array.slice.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ var toAbsoluteIndex = require('../internals/to-absolute-index');
var toLength = require('../internals/to-length');
var toIndexedObject = require('../internals/to-indexed-object');
var createProperty = require('../internals/create-property');
var arrayMethodHasSpeciesSupport = require('../internals/array-method-has-species-support');
var wellKnownSymbol = require('../internals/well-known-symbol');
var arrayMethodHasSpeciesSupport = require('../internals/array-method-has-species-support');
var arrayMethodUsesToLength = require('../internals/array-method-uses-to-length');

var HAS_SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('slice');
var USES_TO_LENGTH = arrayMethodUsesToLength('slice', { ACCESSORS: true, 0: 0, 1: 2 });

var SPECIES = wellKnownSymbol('species');
var nativeSlice = [].slice;
Expand All @@ -16,7 +20,7 @@ var max = Math.max;
// `Array.prototype.slice` method
// https://tc39.github.io/ecma262/#sec-array.prototype.slice
// fallback for not array-like ES3 strings and DOM objects
$({ target: 'Array', proto: true, forced: !arrayMethodHasSpeciesSupport('slice') }, {
$({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT || !USES_TO_LENGTH }, {
slice: function slice(start, end) {
var O = toIndexedObject(this);
var length = toLength(O.length);
Expand Down
6 changes: 5 additions & 1 deletion packages/core-js/modules/es.array.splice.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ var toObject = require('../internals/to-object');
var arraySpeciesCreate = require('../internals/array-species-create');
var createProperty = require('../internals/create-property');
var arrayMethodHasSpeciesSupport = require('../internals/array-method-has-species-support');
var arrayMethodUsesToLength = require('../internals/array-method-uses-to-length');

var HAS_SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('splice');
var USES_TO_LENGTH = arrayMethodUsesToLength('splice', { ACCESSORS: true, 0: 0, 1: 2 });

var max = Math.max;
var min = Math.min;
Expand All @@ -16,7 +20,7 @@ var MAXIMUM_ALLOWED_LENGTH_EXCEEDED = 'Maximum allowed length exceeded';
// `Array.prototype.splice` method
// https://tc39.github.io/ecma262/#sec-array.prototype.splice
// with adding support of @@species
$({ target: 'Array', proto: true, forced: !arrayMethodHasSpeciesSupport('splice') }, {
$({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT || !USES_TO_LENGTH }, {
splice: function splice(start, deleteCount /* , ...items */) {
var O = toObject(this);
var len = toLength(O.length);
Expand Down
5 changes: 5 additions & 0 deletions tests/compat/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ GLOBAL.tests = {
return String(test) !== String(test.reverse());
},
'es.array.slice': function () {
if ([].slice.call({ length: -1, 0: 1 }, 0, 1).length) return false;
var array = [];
var constructor = array.constructor = {};
constructor[Symbol.species] = function () {
Expand Down Expand Up @@ -402,6 +403,10 @@ GLOBAL.tests = {
return Array[Symbol.species];
}],
'es.array.splice': function () {
[].splice.call(Object.defineProperty({ length: -1 }, 0, {
enumerable: true,
get: function (it) { throw it; }
}), 0, 1);
var array = [];
var constructor = array.constructor = {};
constructor[Symbol.species] = function () {
Expand Down
1 change: 1 addition & 0 deletions tests/tests/es.array.flat.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ QUnit.test('Array#flat', assert => {
}
if (DESCRIPTORS) {
assert.notThrows(() => flat.call(defineProperty({ length: -1 }, 0, {
enumerable: true,
get() {
throw new Error();
},
Expand Down
18 changes: 8 additions & 10 deletions tests/tests/es.array.slice.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GLOBAL, NATIVE, STRICT } from '../helpers/constants';
import { GLOBAL, STRICT } from '../helpers/constants';

QUnit.test('Array#slice', assert => {
const { slice } = Array.prototype;
Expand Down Expand Up @@ -26,16 +26,14 @@ QUnit.test('Array#slice', assert => {
if (list) {
assert.notThrows(() => isArray(slice.call(list)), 'works on NodeList');
}
if (NATIVE) {
if (STRICT) {
assert.throws(() => slice.call(null), TypeError);
assert.throws(() => slice.call(undefined), TypeError);
}
assert.deepEqual(slice.call({
length: -1,
0: 1,
}, 0, 1), [], 'uses ToLength');
if (STRICT) {
assert.throws(() => slice.call(null), TypeError);
assert.throws(() => slice.call(undefined), TypeError);
}
assert.deepEqual(slice.call({
length: -1,
0: 1,
}, 0, 1), [], 'uses ToLength');
array = [];
array.constructor = { [Symbol.species]: function () { // eslint-disable-line object-shorthand
return { foo: 1 };
Expand Down
12 changes: 11 additions & 1 deletion tests/tests/es.array.splice.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { STRICT } from '../helpers/constants';
import { DESCRIPTORS, STRICT } from '../helpers/constants';

QUnit.test('Array#splice', assert => {
const { splice } = Array.prototype;
Expand Down Expand Up @@ -35,4 +35,14 @@ QUnit.test('Array#splice', assert => {
return { foo: 1 };
} };
assert.same(array.splice().foo, 1, '@@species');
if (DESCRIPTORS) {
assert.notThrows(() => splice.call(Object.defineProperty({
length: -1,
}, 0, {
enumerable: true,
get() {
throw new Error();
},
}), 0, 2).length === 0, 'uses ToLength');
}
});

0 comments on commit 0186287

Please sign in to comment.