diff --git a/lib/nesting-graph.js b/lib/nesting-graph.js index f5927bdf..d80a9cab 100644 --- a/lib/nesting-graph.js +++ b/lib/nesting-graph.js @@ -31,7 +31,8 @@ module.exports = { function run(g) { let root = util.addDummyNode(g, "root", {}, "_root"); let depths = treeDepths(g); - let height = Math.max(...Object.values(depths)) - 1; // Note: depths is an Object not an array + let depthsArr = Object.values(depths); + let height = util.applyWithChunking(Math.max, depthsArr) - 1; // Note: depths is an Object not an array let nodeSep = 2 * height + 1; g.graph().nestingRoot = root; diff --git a/lib/order/init-order.js b/lib/order/init-order.js index ea901b63..6274dbf7 100644 --- a/lib/order/init-order.js +++ b/lib/order/init-order.js @@ -18,7 +18,8 @@ module.exports = initOrder; function initOrder(g) { let visited = {}; let simpleNodes = g.nodes().filter(v => !g.children(v).length); - let maxRank = Math.max(...simpleNodes.map(v => g.node(v).rank)); + let simpleNodesRanks = simpleNodes.map(v => g.node(v).rank); + let maxRank = util.applyWithChunking(Math.max, simpleNodesRanks); let layers = util.range(maxRank + 1).map(() => []); function dfs(v) { diff --git a/lib/position/bk.js b/lib/position/bk.js index e6740b50..14fbfa86 100644 --- a/lib/position/bk.js +++ b/lib/position/bk.js @@ -313,8 +313,8 @@ function findSmallestWidthAlignment(g, xss) { */ function alignCoordinates(xss, alignTo) { let alignToVals = Object.values(alignTo), - alignToMin = Math.min(...alignToVals), - alignToMax = Math.max(...alignToVals); + alignToMin = util.applyWithChunking(Math.min, alignToVals), + alignToMax = util.applyWithChunking(Math.max, alignToVals); ["u", "d"].forEach(vert => { ["l", "r"].forEach(horiz => { @@ -324,9 +324,9 @@ function alignCoordinates(xss, alignTo) { if (xs === alignTo) return; let xsVals = Object.values(xs); - let delta = alignToMin - Math.min(...xsVals); + let delta = alignToMin - util.applyWithChunking(Math.min, xsVals); if (horiz !== "l") { - delta = alignToMax - Math.max(...xsVals); + delta = alignToMax - util.applyWithChunking(Math.max,xsVals); } if (delta) { diff --git a/lib/rank/util.js b/lib/rank/util.js index ca576acf..452b88ab 100644 --- a/lib/rank/util.js +++ b/lib/rank/util.js @@ -1,5 +1,7 @@ "use strict"; +const { applyWithChunking } = require("../util"); + module.exports = { longestPath: longestPath, slack: slack @@ -36,13 +38,15 @@ function longestPath(g) { } visited[v] = true; - var rank = Math.min(...g.outEdges(v).map(e => { + let outEdgesMinLens = g.outEdges(v).map(e => { if (e == null) { return Number.POSITIVE_INFINITY; } return dfs(e.w) - g.edge(e).minlen; - })); + }); + + var rank = applyWithChunking(Math.min, outEdgesMinLens); if (rank === Number.POSITIVE_INFINITY) { rank = 0; diff --git a/lib/util.js b/lib/util.js index 807da23a..17bedbc4 100644 --- a/lib/util.js +++ b/lib/util.js @@ -7,6 +7,7 @@ let Graph = require("@dagrejs/graphlib").Graph; module.exports = { addBorderNode, addDummyNode, + applyWithChunking, asNonCompoundGraph, buildLayerMatrix, intersectRect, @@ -153,14 +154,15 @@ function buildLayerMatrix(g) { * rank(v) >= 0 and at least one node w has rank(w) = 0. */ function normalizeRanks(g) { - let min = Math.min(...g.nodes().map(v => { + let nodeRanks = g.nodes().map(v => { let rank = g.node(v).rank; if (rank === undefined) { return Number.MAX_VALUE; } return rank; - })); + }); + let min = applyWithChunking(Math.min, nodeRanks); g.nodes().forEach(v => { let node = g.node(v); if (node.hasOwnProperty("rank")) { @@ -171,7 +173,8 @@ function normalizeRanks(g) { function removeEmptyRanks(g) { // Ranks may not start at 0, so we need to offset them - let offset = Math.min(...g.nodes().map(v => g.node(v).rank)); + let nodeRanks = g.nodes().map(v => g.node(v).rank); + let offset = applyWithChunking(Math.min, nodeRanks); let layers = []; g.nodes().forEach(v => { @@ -205,15 +208,37 @@ function addBorderNode(g, prefix, rank, order) { return addDummyNode(g, "border", node, prefix); } +function splitToChunks(array, chunkSize = CHUNKING_THRESHOLD) { + const chunks = []; + for (let i = 0; i < array.length; i += chunkSize) { + const chunk = array.slice(i, i + chunkSize); + chunks.push(chunk); + } + return chunks; +} + +const CHUNKING_THRESHOLD = 65535; + +function applyWithChunking(fn, argsArray) { + if(argsArray.length > CHUNKING_THRESHOLD) { + const chunks = splitToChunks(argsArray); + return fn.apply(null, chunks.map(chunk => fn.apply(null, chunk))); + } else { + return fn.apply(null, argsArray); + } +} + function maxRank(g) { - return Math.max(...g.nodes().map(v => { + const nodes = g.nodes(); + const nodeRanks = nodes.map(v => { let rank = g.node(v).rank; if (rank === undefined) { return Number.MIN_VALUE; } - return rank; - })); + }); + + return applyWithChunking(Math.max, nodeRanks); } /*