Skip to content

Commit

Permalink
Core: Use Array.prototype.flat where supported
Browse files Browse the repository at this point in the history
Calling `Array.prototype.concat.apply( [], inputArray )` to flatten `inputArray`
crashes for large arrays; using `Array.prototype.flat` avoids these issues in
browsers that support it. In case it's necessary to support these large arrays
even in older browsers, a polyfill for `Array.prototype.flat` can be loaded.
This is already being done by many applications.

(cherry picked from 9df4f1d)

Fixes jquerygh-4320
Closes jquerygh-4459
  • Loading branch information
aelafifi authored and mgol committed Sep 25, 2019
1 parent 78ff24d commit 2f666c1
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 15 deletions.
7 changes: 3 additions & 4 deletions src/core.js
Expand Up @@ -4,10 +4,9 @@

define( [
"./var/arr",
"./var/document",
"./var/getProto",
"./var/slice",
"./var/concat",
"./var/flat",
"./var/push",
"./var/indexOf",
"./var/class2type",
Expand All @@ -20,7 +19,7 @@ define( [
"./var/isWindow",
"./core/DOMEval",
"./core/toType"
], function( arr, document, getProto, slice, concat, push, indexOf,
], function( arr, getProto, slice, flat, push, indexOf,
class2type, toString, hasOwn, fnToString, ObjectFunctionString,
support, isFunction, isWindow, DOMEval, toType ) {

Expand Down Expand Up @@ -369,7 +368,7 @@ jQuery.extend( {
}

// Flatten any nested arrays
return concat.apply( [], ret );
return flat( ret );
},

// A global GUID counter for objects
Expand Down
6 changes: 3 additions & 3 deletions src/manipulation.js
@@ -1,7 +1,7 @@
define( [
"./core",
"./core/isAttached",
"./var/concat",
"./var/flat",
"./var/isFunction",
"./var/push",
"./var/rcheckableType",
Expand All @@ -24,7 +24,7 @@ define( [
"./traversing",
"./selector",
"./event"
], function( jQuery, isAttached, concat, isFunction, push, rcheckableType,
], function( jQuery, isAttached, flat, isFunction, push, rcheckableType,
access, rtagName, rscriptType,
wrapMap, getAll, setGlobalEval, buildFragment, support,
dataPriv, dataUser, acceptData, DOMEval, nodeName ) {
Expand Down Expand Up @@ -126,7 +126,7 @@ function fixInput( src, dest ) {
function domManip( collection, args, callback, ignored ) {

// Flatten any nested arrays
args = concat.apply( [], args );
args = flat( args );

var fragment, first, scripts, hasScripts, node, doc,
i = 0,
Expand Down
7 changes: 0 additions & 7 deletions src/var/concat.js

This file was deleted.

16 changes: 16 additions & 0 deletions src/var/flat.js
@@ -0,0 +1,16 @@
define( [
"./arr"
], function( arr ) {

"use strict";

// Support: IE 9 - 11+, Edge 18+, Android Browser 4.0 - 4.3 only, iOS 7 - 11 only, Safari 11 only,
// Firefox <= 61 only
// Provide fallback for browsers without Array#flat.
return arr.flat ? function( array ) {
return arr.flat.call( array );
} : function( array ) {
return arr.concat.apply( [], array );
};

} );
20 changes: 19 additions & 1 deletion test/unit/core.js
Expand Up @@ -703,7 +703,7 @@ QUnit.test( "map()", function( assert ) {
} );

QUnit.test( "jQuery.map", function( assert ) {
assert.expect( 25 );
assert.expect( 28 );

var i, label, result, callback;

Expand Down Expand Up @@ -803,6 +803,24 @@ QUnit.test( "jQuery.map", function( assert ) {
return k % 2 ? k : [ k, k, k ];
} );
assert.equal( result.join( "" ), "00012223", "Array results flattened (#2616)" );

result = jQuery.map( [ [ [ 1, 2 ], 3 ], 4 ], function( v, k ) {
return v;
} );
assert.equal( result.length, 3, "Array flatten only one level down" );
assert.ok( Array.isArray( result[ 0 ] ), "Array flatten only one level down" );

// Support: IE 9 - 11+, Edge 18+, Android Browser 4.0 - 4.3 only, iOS 7 - 11 only,
// Safari 11 only, Firefox <= 61 only
// Skip the test in browsers without Array#flat.
if ( Array.prototype.flat ) {
result = jQuery.map( Array( 300000 ), function( v, k ) {
return k;
} );
assert.equal( result.length, 300000, "Able to map 300000 records without any problems (#4320)" );
} else {
assert.ok( "skip", "Array#flat doesn't supported on all browsers" );
}
} );

QUnit.test( "jQuery.merge()", function( assert ) {
Expand Down

0 comments on commit 2f666c1

Please sign in to comment.