Skip to content

Commit

Permalink
b36b84d58cc245eb0b1509164be6f74f083c1193 Fix: Potential stack overflo…
Browse files Browse the repository at this point in the history
…w issues in Chrome when making large arrays

https://datatables.net/forums/discussion/comment/236656/#Comment_236656

Sync to source repo @b36b84d58cc245eb0b1509164be6f74f083c1193
  • Loading branch information
dtbuild committed Nov 11, 2024
1 parent db8dd97 commit d1df775
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 33 deletions.
2 changes: 1 addition & 1 deletion datatables.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
],
"src-repo": "http://github.com/DataTables/DataTablesSrc",
"last-tag": "2.1.8",
"last-sync": "d8f2161ebd1abb553db12d25997dd5aa1784cb50"
"last-sync": "b36b84d58cc245eb0b1509164be6f74f083c1193"
}
43 changes: 28 additions & 15 deletions js/dataTables.js
Original file line number Diff line number Diff line change
Expand Up @@ -4511,7 +4511,7 @@
// So the array reference doesn't break set the results into the
// existing array
displayRows.length = 0;
displayRows.push.apply(displayRows, rows);
_fnArrayApply(displayRows, rows);
}
}

Expand Down Expand Up @@ -6635,6 +6635,30 @@
replace(/_ENTRIES-TOTAL_/g, settings.api.i18n('entries', '', vis) );
}

/**
* Add elements to an array as quickly as possible, but stack stafe.
*
* @param {*} arr Array to add the data to
* @param {*} data Data array that is to be added
* @returns
*/
function _fnArrayApply(arr, data) {
if (! data) {
return;
}

// Chrome can throw a max stack error if apply is called with
// too large an array, but apply is faster.
if (data.length < 10000) {
arr.push.apply(arr, data);
}
else {
for (i=0 ; i<data.length ; i++) {
arr.push(data[i]);
}
}
}



/**
Expand Down Expand Up @@ -6827,18 +6851,7 @@
: settings;

// Initial data
if ( data ) {
// Chrome can throw a max stack error if apply is called with
// too large an array, but apply is faster.
if (data.length < 10000) {
this.push.apply(this, data);
}
else {
for (i=0 ; i<data.length ; i++) {
this.push(data[i]);
}
}
}
_fnArrayApply(this, data);

// selector
this.selector = {
Expand Down Expand Up @@ -7219,7 +7232,7 @@
selector.forEach(function (sel) {
var inner = __table_selector(sel, a);

result.push.apply(result, inner);
_fnArrayApply(result, inner);
});

return result.filter( function (item) {
Expand Down Expand Up @@ -8073,7 +8086,7 @@
// Return an Api.rows() extended instance, so rows().nodes() etc can be used
var modRows = this.rows( -1 );
modRows.pop();
modRows.push.apply(modRows, newRows);
_fnArrayApply(modRows, newRows);

return modRows;
} );
Expand Down
2 changes: 1 addition & 1 deletion js/dataTables.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/dataTables.min.mjs

Large diffs are not rendered by default.

43 changes: 28 additions & 15 deletions js/dataTables.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4458,7 +4458,7 @@ function _fnFilterCustom( settings )
// So the array reference doesn't break set the results into the
// existing array
displayRows.length = 0;
displayRows.push.apply(displayRows, rows);
_fnArrayApply(displayRows, rows);
}
}

Expand Down Expand Up @@ -6582,6 +6582,30 @@ function _fnMacros ( settings, str, entries )
replace(/_ENTRIES-TOTAL_/g, settings.api.i18n('entries', '', vis) );
}

/**
* Add elements to an array as quickly as possible, but stack stafe.
*
* @param {*} arr Array to add the data to
* @param {*} data Data array that is to be added
* @returns
*/
function _fnArrayApply(arr, data) {
if (! data) {
return;
}

// Chrome can throw a max stack error if apply is called with
// too large an array, but apply is faster.
if (data.length < 10000) {
arr.push.apply(arr, data);
}
else {
for (i=0 ; i<data.length ; i++) {
arr.push(data[i]);
}
}
}



/**
Expand Down Expand Up @@ -6774,18 +6798,7 @@ _Api = function ( context, data )
: settings;

// Initial data
if ( data ) {
// Chrome can throw a max stack error if apply is called with
// too large an array, but apply is faster.
if (data.length < 10000) {
this.push.apply(this, data);
}
else {
for (i=0 ; i<data.length ; i++) {
this.push(data[i]);
}
}
}
_fnArrayApply(this, data);

// selector
this.selector = {
Expand Down Expand Up @@ -7166,7 +7179,7 @@ var __table_selector = function ( selector, a )
selector.forEach(function (sel) {
var inner = __table_selector(sel, a);

result.push.apply(result, inner);
_fnArrayApply(result, inner);
});

return result.filter( function (item) {
Expand Down Expand Up @@ -8020,7 +8033,7 @@ _api_register( 'rows.add()', function ( rows ) {
// Return an Api.rows() extended instance, so rows().nodes() etc can be used
var modRows = this.rows( -1 );
modRows.pop();
modRows.push.apply(modRows, newRows);
_fnArrayApply(modRows, newRows);

return modRows;
} );
Expand Down

0 comments on commit d1df775

Please sign in to comment.