🌐 AI搜索 & 代理 主页
Skip to content

Commit 2f666c1

Browse files
aelafifimgol
authored andcommitted
Core: Use Array.prototype.flat where supported
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 gh-4320 Closes gh-4459
1 parent 78ff24d commit 2f666c1

File tree

5 files changed

+41
-15
lines changed

5 files changed

+41
-15
lines changed

src/core.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44

55
define( [
66
"./var/arr",
7-
"./var/document",
87
"./var/getProto",
98
"./var/slice",
10-
"./var/concat",
9+
"./var/flat",
1110
"./var/push",
1211
"./var/indexOf",
1312
"./var/class2type",
@@ -20,7 +19,7 @@ define( [
2019
"./var/isWindow",
2120
"./core/DOMEval",
2221
"./core/toType"
23-
], function( arr, document, getProto, slice, concat, push, indexOf,
22+
], function( arr, getProto, slice, flat, push, indexOf,
2423
class2type, toString, hasOwn, fnToString, ObjectFunctionString,
2524
support, isFunction, isWindow, DOMEval, toType ) {
2625

@@ -369,7 +368,7 @@ jQuery.extend( {
369368
}
370369

371370
// Flatten any nested arrays
372-
return concat.apply( [], ret );
371+
return flat( ret );
373372
},
374373

375374
// A global GUID counter for objects

src/manipulation.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
define( [
22
"./core",
33
"./core/isAttached",
4-
"./var/concat",
4+
"./var/flat",
55
"./var/isFunction",
66
"./var/push",
77
"./var/rcheckableType",
@@ -24,7 +24,7 @@ define( [
2424
"./traversing",
2525
"./selector",
2626
"./event"
27-
], function( jQuery, isAttached, concat, isFunction, push, rcheckableType,
27+
], function( jQuery, isAttached, flat, isFunction, push, rcheckableType,
2828
access, rtagName, rscriptType,
2929
wrapMap, getAll, setGlobalEval, buildFragment, support,
3030
dataPriv, dataUser, acceptData, DOMEval, nodeName ) {
@@ -126,7 +126,7 @@ function fixInput( src, dest ) {
126126
function domManip( collection, args, callback, ignored ) {
127127

128128
// Flatten any nested arrays
129-
args = concat.apply( [], args );
129+
args = flat( args );
130130

131131
var fragment, first, scripts, hasScripts, node, doc,
132132
i = 0,

src/var/concat.js

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/var/flat.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
define( [
2+
"./arr"
3+
], function( arr ) {
4+
5+
"use strict";
6+
7+
// Support: IE 9 - 11+, Edge 18+, Android Browser 4.0 - 4.3 only, iOS 7 - 11 only, Safari 11 only,
8+
// Firefox <= 61 only
9+
// Provide fallback for browsers without Array#flat.
10+
return arr.flat ? function( array ) {
11+
return arr.flat.call( array );
12+
} : function( array ) {
13+
return arr.concat.apply( [], array );
14+
};
15+
16+
} );

test/unit/core.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ QUnit.test( "map()", function( assert ) {
703703
} );
704704

705705
QUnit.test( "jQuery.map", function( assert ) {
706-
assert.expect( 25 );
706+
assert.expect( 28 );
707707

708708
var i, label, result, callback;
709709

@@ -803,6 +803,24 @@ QUnit.test( "jQuery.map", function( assert ) {
803803
return k % 2 ? k : [ k, k, k ];
804804
} );
805805
assert.equal( result.join( "" ), "00012223", "Array results flattened (#2616)" );
806+
807+
result = jQuery.map( [ [ [ 1, 2 ], 3 ], 4 ], function( v, k ) {
808+
return v;
809+
} );
810+
assert.equal( result.length, 3, "Array flatten only one level down" );
811+
assert.ok( Array.isArray( result[ 0 ] ), "Array flatten only one level down" );
812+
813+
// Support: IE 9 - 11+, Edge 18+, Android Browser 4.0 - 4.3 only, iOS 7 - 11 only,
814+
// Safari 11 only, Firefox <= 61 only
815+
// Skip the test in browsers without Array#flat.
816+
if ( Array.prototype.flat ) {
817+
result = jQuery.map( Array( 300000 ), function( v, k ) {
818+
return k;
819+
} );
820+
assert.equal( result.length, 300000, "Able to map 300000 records without any problems (#4320)" );
821+
} else {
822+
assert.ok( "skip", "Array#flat doesn't supported on all browsers" );
823+
}
806824
} );
807825

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

0 commit comments

Comments
 (0)