Skip to content

Commit 2e1b96a

Browse files
committed
Insert new tasks on the end.
This is a partial fix to d3#1245 whereby timer tasks are now invoked in the order in which they were registered, rather than in the reverse order. However, a better fix remains, which is to invoke tasks in the order of their start time rather than their registration time.
1 parent eb38418 commit 2e1b96a

File tree

4 files changed

+55
-29
lines changed

4 files changed

+55
-29
lines changed

d3.js

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,7 +1796,7 @@ d3 = function() {
17961796
}
17971797
d3.csv = d3_dsv(",", "text/csv");
17981798
d3.tsv = d3_dsv(" ", "text/tab-separated-values");
1799-
var d3_timer_id = 0, d3_timer_byId = {}, d3_timer_queue = null, d3_timer_interval, d3_timer_timeout;
1799+
var d3_timer_id = 0, d3_timer_byId = {}, d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout;
18001800
d3.timer = function(callback, delay, then) {
18011801
if (arguments.length < 3) {
18021802
if (arguments.length < 2) delay = 0; else if (!isFinite(delay)) return;
@@ -1806,20 +1806,24 @@ d3 = function() {
18061806
if (timer && timer.callback === callback) {
18071807
timer.then = then;
18081808
timer.delay = delay;
1809-
} else d3_timer_byId[callback.id = ++d3_timer_id] = d3_timer_queue = {
1810-
callback: callback,
1811-
then: then,
1812-
delay: delay,
1813-
next: d3_timer_queue
1814-
};
1809+
} else {
1810+
d3_timer_byId[callback.id = ++d3_timer_id] = timer = {
1811+
callback: callback,
1812+
then: then,
1813+
delay: delay,
1814+
next: null
1815+
};
1816+
if (d3_timer_queueTail) d3_timer_queueTail.next = timer; else d3_timer_queueHead = timer;
1817+
d3_timer_queueTail = timer;
1818+
}
18151819
if (!d3_timer_interval) {
18161820
d3_timer_timeout = clearTimeout(d3_timer_timeout);
18171821
d3_timer_interval = 1;
18181822
d3_timer_frame(d3_timer_step);
18191823
}
18201824
};
18211825
function d3_timer_step() {
1822-
var elapsed, now = Date.now(), t1 = d3_timer_queue;
1826+
var elapsed, now = Date.now(), t1 = d3_timer_queueHead;
18231827
while (t1) {
18241828
elapsed = now - t1.then;
18251829
if (elapsed >= t1.delay) t1.flush = t1.callback(elapsed);
@@ -1838,7 +1842,7 @@ d3 = function() {
18381842
}
18391843
}
18401844
d3.timer.flush = function() {
1841-
var elapsed, now = Date.now(), t1 = d3_timer_queue;
1845+
var elapsed, now = Date.now(), t1 = d3_timer_queueHead;
18421846
while (t1) {
18431847
elapsed = now - t1.then;
18441848
if (!t1.delay) t1.flush = t1.callback(elapsed);
@@ -1847,16 +1851,17 @@ d3 = function() {
18471851
d3_timer_flush();
18481852
};
18491853
function d3_timer_flush() {
1850-
var t0 = null, t1 = d3_timer_queue, then = Infinity;
1854+
var t0, t1 = d3_timer_queueHead, then = Infinity;
18511855
while (t1) {
18521856
if (t1.flush) {
18531857
delete d3_timer_byId[t1.callback.id];
1854-
t1 = t0 ? t0.next = t1.next : d3_timer_queue = t1.next;
1858+
t1 = t0 ? t0.next = t1.next : d3_timer_queueHead = t1.next;
18551859
} else {
18561860
then = Math.min(then, t1.then + t1.delay);
18571861
t1 = (t0 = t1).next;
18581862
}
18591863
}
1864+
d3_timer_queueTail = t0;
18601865
return then;
18611866
}
18621867
var d3_timer_frame = d3_window.requestAnimationFrame || d3_window.webkitRequestAnimationFrame || d3_window.mozRequestAnimationFrame || d3_window.oRequestAnimationFrame || d3_window.msRequestAnimationFrame || function(callback) {

d3.min.js

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/event/timer.js

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import "../core/document";
22

33
var d3_timer_id = 0,
44
d3_timer_byId = {},
5-
d3_timer_queue = null,
5+
d3_timer_queueHead,
6+
d3_timer_queueTail,
67
d3_timer_interval, // is an interval (or frame) active?
78
d3_timer_timeout; // is a timeout active?
89

@@ -21,13 +22,18 @@ d3.timer = function(callback, delay, then) {
2122
timer.delay = delay;
2223
}
2324

24-
// Otherwise, add the callback to the queue.
25-
else d3_timer_byId[callback.id = ++d3_timer_id] = d3_timer_queue = {
26-
callback: callback,
27-
then: then,
28-
delay: delay,
29-
next: d3_timer_queue
30-
};
25+
// Otherwise, add the callback to the tail of the queue.
26+
else {
27+
d3_timer_byId[callback.id = ++d3_timer_id] = timer = {
28+
callback: callback,
29+
then: then,
30+
delay: delay,
31+
next: null
32+
};
33+
if (d3_timer_queueTail) d3_timer_queueTail.next = timer;
34+
else d3_timer_queueHead = timer;
35+
d3_timer_queueTail = timer;
36+
}
3137

3238
// Start animatin'!
3339
if (!d3_timer_interval) {
@@ -40,7 +46,7 @@ d3.timer = function(callback, delay, then) {
4046
function d3_timer_step() {
4147
var elapsed,
4248
now = Date.now(),
43-
t1 = d3_timer_queue;
49+
t1 = d3_timer_queueHead;
4450

4551
while (t1) {
4652
elapsed = now - t1.then;
@@ -64,7 +70,7 @@ function d3_timer_step() {
6470
d3.timer.flush = function() {
6571
var elapsed,
6672
now = Date.now(),
67-
t1 = d3_timer_queue;
73+
t1 = d3_timer_queueHead;
6874

6975
while (t1) {
7076
elapsed = now - t1.then;
@@ -77,18 +83,19 @@ d3.timer.flush = function() {
7783

7884
// Flush after callbacks to avoid concurrent queue modification.
7985
function d3_timer_flush() {
80-
var t0 = null,
81-
t1 = d3_timer_queue,
86+
var t0,
87+
t1 = d3_timer_queueHead,
8288
then = Infinity;
8389
while (t1) {
8490
if (t1.flush) {
8591
delete d3_timer_byId[t1.callback.id];
86-
t1 = t0 ? t0.next = t1.next : d3_timer_queue = t1.next;
92+
t1 = t0 ? t0.next = t1.next : d3_timer_queueHead = t1.next;
8793
} else {
8894
then = Math.min(then, t1.then + t1.delay);
8995
t1 = (t0 = t1).next;
9096
}
9197
}
98+
d3_timer_queueTail = t0;
9299
return then;
93100
}
94101

test/event/timer-test.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,20 @@ suite.addBatch({
3232
"calls every 17 ms": function(info) {
3333
assert.inDelta(info.stop - info.start, 17 * 3, 20);
3434
}
35+
},
36+
37+
"with multiple registered tasks": {
38+
topic: function(timer) {
39+
var callback = this.callback,
40+
results = [];
41+
timer(function() { results.push("A"); return true; });
42+
timer(function() { results.push("B"); return true; });
43+
timer(function() { results.push("C"); return true; });
44+
timer(function() { callback(null, results); return true; })
45+
},
46+
"invokes tasks in the order they were registered": function(results) {
47+
assert.deepEqual(results, ["A", "B", "C"]);
48+
}
3549
}
3650
}
3751
});

0 commit comments

Comments
 (0)