From b62c28166de701c5b067658bfe94fe54f01ec0c6 Mon Sep 17 00:00:00 2001 From: Jimmy Rishe Date: Mon, 19 Oct 2020 16:17:22 +0900 Subject: [PATCH] Fix max call stack issue (#99) * Fix issue with RangeError called on concat.apply() When calling the flatten function with a sufficiently large array it will throw: RangeError: Maximum call stack size exceeded This was found when processing very large xml documents and using a // selector in select(). This is due to the maximum argument length limit in javascript/node. Calling apply() with a sufficiently large array will throw a RangeError. See https://bugs.webkit.org/show_bug.cgi?id=80797 for details. Chunk the array into chunks that are smaller than the maximum argument list size using `slice()` and call `concat.apply()` on each chunk so that we never get the range error. * Argument limit issue - remove use of prototypeSlice and unnecessary use of min() Co-authored-by: Mike Noseworthy --- xpath.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/xpath.js b/xpath.js index 0868428..4882a27 100644 --- a/xpath.js +++ b/xpath.js @@ -167,8 +167,19 @@ var xpath = (typeof exports === 'undefined') ? {} : exports; var prototypeConcat = Array.prototype.concat; + // .apply() fails above a certain number of arguments - https://github.com/goto100/xpath/pull/98 + var MAX_ARGUMENT_LENGTH = 32767; + function flatten(arr) { - return prototypeConcat.apply([], arr); + var result = []; + + for (var start = 0; start < arr.length; start += MAX_ARGUMENT_LENGTH) { + var chunk = arr.slice(start, start + MAX_ARGUMENT_LENGTH); + + result = prototypeConcat.apply(result, chunk); + } + + return result; } function assign(target, varArgs) { // .length of function is 2