@@ -60,6 +60,11 @@ function debugModule(module, runtime) {
62 function wrapRunDelayed(func, delayMs) {
62 function wrapRunDelayed(func, delayMs) {
64+ // Don't push timers and such to the callback stack while we're paused.
65+ // It causes too many callbacks to be fired during unpausing.
63 var cbObj = { func:func, delayMs:delayMs, timerId:0, executed:false };
68 var cbObj = { func:func, delayMs:delayMs, timerId:0, executed:false };
64 var timerId = setTimeout(function() {
69 var timerId = setTimeout(function() {
65 cbObj.executed = true;
70 cbObj.executed = true;
@@ -103,7 +108,7 @@ function debugModule(module, runtime) {
103 recordedEvents = events.slice();
108 recordedEvents = events.slice();
106− function setPaused(v) {
111+ function setPausedAt(v, position) {
107 programPaused = v;
112 programPaused = v;
108 if (programPaused) {
113 if (programPaused) {
109 clearAsyncCallbacks();
114 clearAsyncCallbacks();
@@ -111,7 +116,12 @@ function debugModule(module, runtime) {
113 // executeCallbacks should only be called when continuing, not when restarting.
118 // executeCallbacks should only be called when continuing, not when restarting.
120+ // If we're unpausing not at the head, then we need to dump the
121+ // events that are ahead of where we're continuing.
122+ recordedEvents = recordedEvents.slice(0,position);
114− //executeCallbacks(asyncCallbacks, false);
123+ executeCallbacks(asyncCallbacks, false);
115 tracePath.startRecording();
125 tracePath.startRecording();
@@ -157,7 +167,7 @@ function debugModule(module, runtime) {
157 copyRecordedEvents: copyRecordedEvents,
167 copyRecordedEvents: copyRecordedEvents,
158 loadRecordedEvents: loadRecordedEvents,
168 loadRecordedEvents: loadRecordedEvents,
159 getPaused: getPaused,
169 getPaused: getPaused,
160− setPaused: setPaused,
170+ setPausedAt: setPausedAt,
161 tracePath: tracePath,
171 tracePath: tracePath,
162 watchTracker: watchTracker,
172 watchTracker: watchTracker,
@@ -177,25 +187,25 @@ function debuggerInit(debugModule, runtime, hotSwapState /* =undefined */) {
177 debugModule.watchTracker.clear();
187 debugModule.watchTracker.clear();
178 debugModule.tracePath.clearTraces();
188 debugModule.tracePath.clearTraces();
179 debugModule.clearRecordedEvents();
189 debugModule.clearRecordedEvents();
180− debugModule.setPaused(false);
190+ debugModule.setPausedAt(false, 0);
181 executeCallbacks(debugModule.initialAsyncCallbacks, true);
191 executeCallbacks(debugModule.initialAsyncCallbacks, true);
184 function pauseProgram() {
194 function pauseProgram() {
185− debugModule.setPaused(true);
195+ debugModule.setPausedAt(true);
186 eventCounter = debugModule.getRecordedEventsLength();
196 eventCounter = debugModule.getRecordedEventsLength();
189 function continueProgram() {
199 function continueProgram() {
190 if (debugModule.getPaused())
200 if (debugModule.getPaused())
192− debugModule.setPaused(false);
202+ debugModule.setPausedAt(false, eventCounter);
196 function stepTo(index) {
206 function stepTo(index) {
197 if (!debugModule.getPaused()) {
207 if (!debugModule.getPaused()) {
198− debugModule.setPaused(true);
208+ debugModule.setPausedAt(true);
199 resetProgram();
209 resetProgram();
@@ -206,8 +216,11 @@ function debuggerInit(debugModule, runtime, hotSwapState /* =undefined */) {
206 if (index < eventCounter) {
216 if (index < eventCounter) {
207 resetProgram();
217 resetProgram();
208 eventCounter = 0;
218 eventCounter = 0;
219+ debugModule.tracePath.clearTraces();
222+ debugModule.tracePath.startRecording();
211 assert(index >= eventCounter, "index must be bad");
224 assert(index >= eventCounter, "index must be bad");
212 while (eventCounter < index) {
225 while (eventCounter < index) {
213 var nextEvent = debugModule.getRecordedEventAt(eventCounter);
226 var nextEvent = debugModule.getRecordedEventAt(eventCounter);
@@ -216,6 +229,7 @@ function debuggerInit(debugModule, runtime, hotSwapState /* =undefined */) {
216 eventCounter += 1;
229 eventCounter += 1;
218 assert(eventCounter == index, "while loop didn't work");
231 assert(eventCounter == index, "while loop didn't work");
232+ debugModule.tracePath.stopRecording();
221 function getMaxSteps() {
235 function getMaxSteps() {
@@ -258,7 +272,13 @@ function debuggerInit(debugModule, runtime, hotSwapState /* =undefined */) {
260 if (hotSwapState) {
274 if (hotSwapState) {
275+ // The problem is that we want to previous paused state. But
276+ // by the time JS reaches here, the old code has been swapped out
277+ // and the new modules are being generated. So we can ask the
278+ // debugging console what it thinks the pause state is and go
280+ var pauseState = top.debug.paused;
261− debugModule.setPaused(true);
281+ debugModule.setPausedAt(true);
262 debugModule.loadRecordedEvents(hotSwapState.recordedEvents);
282 debugModule.loadRecordedEvents(hotSwapState.recordedEvents);
264 // draw new trace path
284 // draw new trace path
@@ -267,6 +287,7 @@ function debuggerInit(debugModule, runtime, hotSwapState /* =undefined */) {
267 debugModule.tracePath.stopRecording();
287 debugModule.tracePath.stopRecording();
269 stepTo(hotSwapState.eventCounter);
289 stepTo(hotSwapState.eventCounter);
290+ debugModule.setPausedAt(pauseState, hotSwapState.eventCounter);
272 runtime.node.parentNode.appendChild(debugModule.tracePath.canvas);
293 runtime.node.parentNode.appendChild(debugModule.tracePath.canvas);
@@ -416,6 +437,7 @@ function executeCallbacks(callbacks, reexecute) {
416 callbacks.forEach(function(timer) {
437 callbacks.forEach(function(timer) {
417 if (reexecute || !timer.executed) {
438 if (reexecute || !timer.executed) {
418 var func = timer.func;
439 var func = timer.func;
440+ timer.executed = true;