From 11b6381c4f8cf7e2aab788f97afbd0e334399859 Mon Sep 17 00:00:00 2001 From: Andrew Pendleton Date: Fri, 1 Apr 2016 01:16:01 -0400 Subject: [PATCH] Another attempt at avoiding overflowing the callstack on geocoderDataIterator: every tenth time we call a callback, call it via setImmediate to reset the stack --- lib/mbtiles.js | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/mbtiles.js b/lib/mbtiles.js index b178a07..2e39329 100644 --- a/lib/mbtiles.js +++ b/lib/mbtiles.js @@ -615,6 +615,9 @@ MBTiles.prototype.putGeocoderData = function(type, shard, data, callback) { }); }; +var stackCounter = 0; +var stackMax = 10; + // Implements carmen#geocoderDataIterator method. MBTiles.prototype.geocoderDataIterator = function(type) { var chunkSize = 100; @@ -625,6 +628,20 @@ MBTiles.prototype.geocoderDataIterator = function(type) { var doneSentinel = {}; var _this = this; + // every tenth callback call (globally) do it via setImmediate + // to avoid callback loops that blow the callstack + var checkStack = function(cb, arg) { + if (stackCounter >= stackMax) { + stackCounter = 0; + setImmediate(function() { + cb(arg); + }) + } else { + stackCounter += 1; + cb(arg); + } + } + var sending = false; var sendIfAvailable = function() { if (sending) return; @@ -633,12 +650,12 @@ MBTiles.prototype.geocoderDataIterator = function(type) { while (nextQueue.length && dataQueue.length) { var nextCb = nextQueue.shift(), data; if (dataQueue[0] == doneSentinel) { - nextCb({value: undefined, done: true}); + checkStack(nextCb, {value: undefined, done: true}); } else { data = dataQueue.shift(); maybeRefillBuffer(); - nextCb({value: {shard: data.shard, data: zlib.inflateSync(data.data)}, done: false}); + checkStack(nextCb, {value: {shard: data.shard, data: zlib.inflateSync(data.data)}, done: false}); } }