diff --git a/builds/4chan-X.js b/builds/4chan-X.js index a0d5d6808..6819fc984 100644 --- a/builds/4chan-X.js +++ b/builds/4chan-X.js @@ -22,7 +22,7 @@ // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAgMAAAAqbBEUAAAACVBMVEUAAGcAAABmzDNZt9VtAAAAAXRSTlMAQObYZgAAAHFJREFUKFOt0LENACEIBdBv4Qju4wgWanEj3D6OcIVMKaitYHEU/jwTCQj8W75kiVCSBvdQ5/AvfVHBin11BgdRq3ysBgfwBDRrj3MCIA+oAQaku/Q1cNctrAmyDl577tOThYt/Y1RBM4DgOHzM0HFTAyLukH/cmRnqAAAAAElFTkSuQmCC // ==/UserScript== /* -* 4chan X - Version 1.1.0 - 2013-04-24 +* 4chan X - Version 1.1.0 - 2013-04-25 * * Licensed under the MIT license. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE @@ -9706,7 +9706,11 @@ Main.handleErrors(errors); } Main.callbackNodes(Thread, threads); - Main.callbackNodes(Post, posts); + Main.callbackNodesDB(Post, posts, function() { + $.event('4chanXInitFinished'); + return Main.checkUpdate(); + }); + return; } $.event('4chanXInitFinished'); return Main.checkUpdate(); @@ -9738,6 +9742,63 @@ return Main.handleErrors(errors); } }, + callbackNodesDB: function(klass, nodes, cb) { + var errors, func, i, len, node, queue, softTask; + + queue = []; + softTask = function() { + var args, func, task; + + if (!queue.length) { + return; + } + task = queue.shift(); + func = task[0]; + args = Array.prototype.slice.call(task, 1); + func.apply(func, args); + if ((queue.length % 7) === 0) { + return setTimeout(softTask, 0); + } else { + return softTask(); + } + }; + len = nodes.length; + i = 0; + errors = null; + func = function(node, i) { + var callback, err, _i, _len, _ref; + + _ref = klass.prototype.callbacks; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + callback = _ref[_i]; + try { + callback.cb.call(node); + } catch (_error) { + err = _error; + if (!errors) { + errors = []; + } + errors.push({ + message: "\"" + callback.name + "\" crashed on " + klass.name + " No." + node + " (/" + node.board + "/).", + error: err + }); + } + } + if (i === len) { + if (errors) { + Main.handleErrors(errors); + } + if (cb) { + return cb(); + } + } + }; + while (i < len) { + node = nodes[i]; + queue.push([func, node, ++i]); + } + return softTask(); + }, addCallback: function(e) { var Klass, obj; diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index 4c7c5d332..ca6e7a1c5 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -22,7 +22,7 @@ // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAgMAAAAqbBEUAAAACVBMVEUAAGcAAABmzDNZt9VtAAAAAXRSTlMAQObYZgAAAHFJREFUKFOt0LENACEIBdBv4Qju4wgWanEj3D6OcIVMKaitYHEU/jwTCQj8W75kiVCSBvdQ5/AvfVHBin11BgdRq3ysBgfwBDRrj3MCIA+oAQaku/Q1cNctrAmyDl577tOThYt/Y1RBM4DgOHzM0HFTAyLukH/cmRnqAAAAAElFTkSuQmCC // ==/UserScript== /* -* 4chan X - Version 1.1.0 - 2013-04-24 +* 4chan X - Version 1.1.0 - 2013-04-25 * * Licensed under the MIT license. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE @@ -9729,7 +9729,11 @@ Main.handleErrors(errors); } Main.callbackNodes(Thread, threads); - Main.callbackNodes(Post, posts); + Main.callbackNodesDB(Post, posts, function() { + $.event('4chanXInitFinished'); + return Main.checkUpdate(); + }); + return; } $.event('4chanXInitFinished'); return Main.checkUpdate(); @@ -9761,6 +9765,63 @@ return Main.handleErrors(errors); } }, + callbackNodesDB: function(klass, nodes, cb) { + var errors, func, i, len, node, queue, softTask; + + queue = []; + softTask = function() { + var args, func, task; + + if (!queue.length) { + return; + } + task = queue.shift(); + func = task[0]; + args = Array.prototype.slice.call(task, 1); + func.apply(func, args); + if ((queue.length % 7) === 0) { + return setTimeout(softTask, 0); + } else { + return softTask(); + } + }; + len = nodes.length; + i = 0; + errors = null; + func = function(node, i) { + var callback, err, _i, _len, _ref; + + _ref = klass.prototype.callbacks; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + callback = _ref[_i]; + try { + callback.cb.call(node); + } catch (_error) { + err = _error; + if (!errors) { + errors = []; + } + errors.push({ + message: "\"" + callback.name + "\" crashed on " + klass.name + " No." + node + " (/" + node.board + "/).", + error: err + }); + } + } + if (i === len) { + if (errors) { + Main.handleErrors(errors); + } + if (cb) { + return cb(); + } + } + }; + while (i < len) { + node = nodes[i]; + queue.push([func, node, ++i]); + } + return softTask(); + }, addCallback: function(e) { var Klass, obj; diff --git a/builds/crx/script.js b/builds/crx/script.js index 8aad8f8c1..55f652fa1 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -9572,7 +9572,11 @@ Main.handleErrors(errors); } Main.callbackNodes(Thread, threads); - Main.callbackNodes(Post, posts); + Main.callbackNodesDB(Post, posts, function() { + $.event('4chanXInitFinished'); + return Main.checkUpdate(); + }); + return; } $.event('4chanXInitFinished'); return Main.checkUpdate(); @@ -9604,6 +9608,63 @@ return Main.handleErrors(errors); } }, + callbackNodesDB: function(klass, nodes, cb) { + var errors, func, i, len, node, queue, softTask; + + queue = []; + softTask = function() { + var args, func, task; + + if (!queue.length) { + return; + } + task = queue.shift(); + func = task[0]; + args = Array.prototype.slice.call(task, 1); + func.apply(func, args); + if ((queue.length % 7) === 0) { + return setTimeout(softTask, 0); + } else { + return softTask(); + } + }; + len = nodes.length; + i = 0; + errors = null; + func = function(node, i) { + var callback, err, _i, _len, _ref; + + _ref = klass.prototype.callbacks; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + callback = _ref[_i]; + try { + callback.cb.call(node); + } catch (_error) { + err = _error; + if (!errors) { + errors = []; + } + errors.push({ + message: "\"" + callback.name + "\" crashed on " + klass.name + " No." + node + " (/" + node.board + "/).", + error: err + }); + } + } + if (i === len) { + if (errors) { + Main.handleErrors(errors); + } + if (cb) { + return cb(); + } + } + }; + while (i < len) { + node = nodes[i]; + queue.push([func, node, ++i]); + } + return softTask(); + }, addCallback: function(e) { var Klass, obj; diff --git a/src/lib/$.coffee b/src/lib/$.coffee index a92d19ac3..91daa0ae6 100644 --- a/src/lib/$.coffee +++ b/src/lib/$.coffee @@ -234,7 +234,7 @@ $.debounce = (wait, fn) -> # after wait, let next invocation execute immediately timeout = setTimeout exec, wait - + $.queueTask = do -> # inspired by https://www.w3.org/Bugs/Public/show_bug.cgi?id=15007 taskQueue = [] diff --git a/src/main.coffee b/src/main.coffee index d5a7fb58c..00e618a0b 100644 --- a/src/main.coffee +++ b/src/main.coffee @@ -52,7 +52,7 @@ Main = for name, module of features # c.time "#{name} initialization" try - do module.init + module.init() catch err Main.handleErrors message: "\"#{name}\" initialization crashed." @@ -195,7 +195,11 @@ Main = Main.handleErrors errors if errors Main.callbackNodes Thread, threads - Main.callbackNodes Post, posts + Main.callbackNodesDB Post, posts, -> + $.event '4chanXInitFinished' + Main.checkUpdate() + + return $.event '4chanXInitFinished' Main.checkUpdate() @@ -218,6 +222,45 @@ Main = # c.profileEnd callback.name Main.handleErrors errors if errors + callbackNodesDB: (klass, nodes, cb) -> + queue = [] + softTask = -> + return unless queue.length + task = queue.shift() + func = task[0] + args = Array::slice.call task, 1 + func.apply func, args + if (queue.length % 7) is 0 + setTimeout softTask, 0 + else + softTask() + + # get the nodes' length only once + len = nodes.length + i = 0 + errors = null + + func = (node, i) -> + for callback in klass::callbacks + try + callback.cb.call node + catch err + unless errors + errors = [] + errors.push + message: "\"#{callback.name}\" crashed on #{klass.name} No.#{node} (/#{node.board}/)." + error: err + # finish + if i is len + Main.handleErrors errors if errors + cb() if cb + + while i < len + node = nodes[i] + queue.push [func, node, ++i] + + softTask() + addCallback: (e) -> obj = e.detail unless typeof obj.callback.name is 'string'