on master help sign in
global timer and delay update at Elm.timer.{now(),addDelay(d)}
494dfdbMichael James
libraries/Native/Signal/Signal.js+1−1
@@ -138,7 +138,7 @@ Elm.Native.Signal.make = function(elm) {
138 }
138 }
139
139
140 function timestamp(a) {
140 function timestamp(a) {
141− function update() { return Utils.Tuple2(Date.now(), a.value); }
141+ function update() { return Utils.Tuple2(Elm.timer.now(), a.value); }
142 return new LiftN(update, [a]);
142 return new LiftN(update, [a]);
143 }
143 }
144
144
libraries/Native/Signal/Time.js+6−13
@@ -12,16 +12,10 @@ Elm.Native.Time.make = function(elm) {
12
12
13 function fpsWhen(desiredFPS, isOn) {
13 function fpsWhen(desiredFPS, isOn) {
14 var msPerFrame = 1000 / desiredFPS;
14 var msPerFrame = 1000 / desiredFPS;
15− var prev = Date.now(), curr = prev, diff = 0, wasOn = true;
15+ var prev = Elm.timer.now(), curr = prev, diff = 0, wasOn = true;
16 var ticker = NS.input(diff);
16 var ticker = NS.input(diff);
17− function tick(zero) { return function(offset) {
17+ function tick(zero) { return function() {
18− /**
19− * The offset is used for the debugger module. To pause and
20− * unpause time in a continuous way (not jumping ahead by seconds)
21− * or minutes, we introduce a way to offset real time by the amount
22− * of time spend paused.
23− */
24− curr = Date.now() - (offset|0);
18+ curr = Elm.timer.now();
25 diff = zero ? 0 : curr - prev;
19 diff = zero ? 0 : curr - prev;
26 prev = curr;
20 prev = curr;
27 elm.notify(ticker.id, diff);
21 elm.notify(ticker.id, diff);
@@ -41,10 +35,9 @@ Elm.Native.Time.make = function(elm) {
41 }
35 }
42
36
43 function every(t) {
37 function every(t) {
44− var clock = NS.input(Date.now());
38+ var clock = NS.input(Elm.timer.now());
45− function tellTime(offset) {
39+ function tellTime() {
46− // Leave the offset. It's for debugging. See above.
47− elm.notify(clock.id, Date.now() - (offset|0));
40+ elm.notify(clock.id, Elm.timer.now());
48 elm.runDelayed(tellTime, t);
41 elm.runDelayed(tellTime, t);
49 }
42 }
50 elm.runDelayed(tellTime, t);
43 elm.runDelayed(tellTime, t);
libraries/Native/Signal/Touch.js+2−2
@@ -61,11 +61,11 @@ Elm.Native.Touch.make = function(elm) {
61 dict.insert(e.identifier,
61 dict.insert(e.identifier,
62 {x: point._0,
62 {x: point._0,
63 y: point._1,
63 y: point._1,
64− t: Date.now()});
64+ t: Elm.timer.now()});
65 }
65 }
66 function end(e) {
66 function end(e) {
67 var t = dict.remove(e.identifier);
67 var t = dict.remove(e.identifier);
68− if (Date.now() - t.t < tapTime) {
68+ if (Elm.timer.now() - t.t < tapTime) {
69 hasTap = true;
69 hasTap = true;
70 tap = {_:{}, x:t.x, y:t.y};
70 tap = {_:{}, x:t.x, y:t.y};
71 }
71 }
runtime/Debugger.js+7−13
@@ -40,7 +40,6 @@ function debugModule(module, runtime) {
40 var recordedEvents = [];
40 var recordedEvents = [];
41 var asyncCallbacks = [];
41 var asyncCallbacks = [];
42 var watchTracker = Elm.Native.Debug.make(runtime).watchTracker;
42 var watchTracker = Elm.Native.Debug.make(runtime).watchTracker;
43− var timerOffset = 0;
44 var now = 0;
43 var now = 0;
45
44
46 function wrapNotify(id, v) {
45 function wrapNotify(id, v) {
@@ -70,7 +69,7 @@ function debugModule(module, runtime) {
70 var cbObj = { func:func, delayMs:delayMs, timerId:0, executed:false };
69 var cbObj = { func:func, delayMs:delayMs, timerId:0, executed:false };
71 var timerId = setTimeout(function() {
70 var timerId = setTimeout(function() {
72 cbObj.executed = true;
71 cbObj.executed = true;
73− func(timerOffset);
72+ func();
74 }, delayMs);
73 }, delayMs);
75 cbObj.timerId = timerId;
74 cbObj.timerId = timerId;
76 asyncCallbacks.push(cbObj);
75 asyncCallbacks.push(cbObj);
@@ -110,10 +109,6 @@ function debugModule(module, runtime) {
110 recordedEvents = events.slice();
109 recordedEvents = events.slice();
111 }
110 }
112
111
113− function resetTimeOffset() {
114− timerOffset = 0;
115− }
116−
117 function setPaused() {
112 function setPaused() {
118 programPaused = true;
113 programPaused = true;
119 clearAsyncCallbacks();
114 clearAsyncCallbacks();
@@ -122,13 +117,14 @@ function debugModule(module, runtime) {
122 }
117 }
123
118
124 function setContinue(position) {
119 function setContinue(position) {
125− timerOffset += Date.now() - now;
120+ var timerDelay = Date.now() - now;
121+ Elm.timer.addDelay(timerDelay);
126 programPaused = false;
122 programPaused = false;
127 if (position > 0) {
123 if (position > 0) {
128 // If we're not unpausing at the head, then we need to dump the
124 // If we're not unpausing at the head, then we need to dump the
129 // events that are ahead of where we're continuing.
125 // events that are ahead of where we're continuing.
130 recordedEvents = recordedEvents.slice(0,position);
126 recordedEvents = recordedEvents.slice(0,position);
131− executeCallbacks(asyncCallbacks, false, timerOffset);
127+ executeCallbacks(asyncCallbacks, false);
132 }
128 }
133 tracePath.startRecording();
129 tracePath.startRecording();
134 }
130 }
@@ -173,7 +169,6 @@ function debugModule(module, runtime) {
173 getRecordedEventAt: getRecordedEventAt,
169 getRecordedEventAt: getRecordedEventAt,
174 copyRecordedEvents: copyRecordedEvents,
170 copyRecordedEvents: copyRecordedEvents,
175 loadRecordedEvents: loadRecordedEvents,
171 loadRecordedEvents: loadRecordedEvents,
176− resetTimeOffset: resetTimeOffset,
177 getPaused: getPaused,
172 getPaused: getPaused,
178 setPaused: setPaused,
173 setPaused: setPaused,
179 setContinue: setContinue,
174 setContinue: setContinue,
@@ -197,8 +192,7 @@ function debuggerInit(debugModule, runtime, hotSwapState /* =undefined */) {
197 debugModule.tracePath.clearTraces();
192 debugModule.tracePath.clearTraces();
198 debugModule.clearRecordedEvents();
193 debugModule.clearRecordedEvents();
199 debugModule.setContinue(0);
194 debugModule.setContinue(0);
200− debugModule.resetTimeOffset();
201− executeCallbacks(debugModule.initialAsyncCallbacks, true, 0);
195+ executeCallbacks(debugModule.initialAsyncCallbacks, true);
202 }
196 }
203
197
204 function pauseProgram() {
198 function pauseProgram() {
@@ -453,12 +447,12 @@ function tracePathInit(runtime, mainNode) {
453}
447}
454
448
455
449
456−function executeCallbacks(callbacks, reexecute, offset) {
450+function executeCallbacks(callbacks, reexecute) {
457 callbacks.forEach(function(timer) {
451 callbacks.forEach(function(timer) {
458 if (reexecute || !timer.executed) {
452 if (reexecute || !timer.executed) {
459 var func = timer.func;
453 var func = timer.func;
460 timer.executed = true;
454 timer.executed = true;
461− func(offset);
455+ func();
462 }
456 }
463 });
457 });
464}
458}
runtime/Init.js+25−1
@@ -27,6 +27,30 @@ Elm.worker = function(module, ports) {
27 return init(ElmRuntime.Display.NONE, {}, module, ports || {});
27 return init(ElmRuntime.Display.NONE, {}, module, ports || {});
28};
28};
29
29
30+/* OFFSET
31+ * Elm's time traveling debugger lets you interrupt the smooth flow of time
32+ * by pausing and continuing program execution. To ensure the user sees a
33+ * program that moves smoothly through the pause/continue time gap,
34+ * we need to adjsut the value of Date.now().
35+ */
36+Elm.timer = function() {
37+ var inducedDelay = 0;
38+
39+ var now = function() {
40+ return Date.now() - inducedDelay;
41+ };
42+
43+ var addDelay = function(d) {
44+ var delay = (d|0);
45+ inducedDelay += delay;
46+ return inducedDelay;
47+ }
48+
49+ return { now : now
50+ , addDelay : addDelay
51+ }
52+}();
53+
30function init(display, container, module, ports, moduleToReplace) {
54function init(display, container, module, ports, moduleToReplace) {
31 // defining state needed for an instance of the Elm RTS
55 // defining state needed for an instance of the Elm RTS
32 var inputs = [];
56 var inputs = [];
@@ -40,7 +64,7 @@ function init(display, container, module, ports, moduleToReplace) {
40 'Definitely report this to <https://github.com/evancz/Elm/issues>\n');
64 'Definitely report this to <https://github.com/evancz/Elm/issues>\n');
41 }
65 }
42 updateInProgress = true;
66 updateInProgress = true;
43− var timestep = Date.now();
67+ var timestep = Elm.timer.now();
44 for (var i = inputs.length; i--; ) {
68 for (var i = inputs.length; i--; ) {
45 inputs[i].recv(timestep, id, v);
69 inputs[i].recv(timestep, id, v);
46 }
70 }