on master help sign in
Debugger: split module wrapping into separate function; add trace path graphics.
92898acLaszlo Pandy
runtime/Debugger.js+126−49
@@ -3,27 +3,23 @@
3'use strict';
3'use strict';
4
4
5Elm.Debugger = null;
5Elm.Debugger = null;
6−Elm.debuggerInit = function(module) {
6+Elm.debuggerAttach = function(module) {
7 return {
7 return {
8 make: function(runtime) {
8 make: function(runtime) {
9− Elm.Debugger = debuggerInit(module, runtime);
9+ var wrappedModule = debugModule(module, runtime);
10+ Elm.debuggerInit = function() {
11+ Elm.Debugger = debuggerInit(wrappedModule, runtime);
12+ };
10− return Elm.Debugger.moduleInstance;
13+ return wrappedModule.moduleInstance;
11 }
14 }
12 };
15 };
13};
16};
14
17
15−function debuggerInit(module, runtime) {
18+function debugModule(module, runtime) {
16−
17 var programPaused = false;
19 var programPaused = false;
18− var allNodes = null;
19−
20 var recordedEvents = [];
20 var recordedEvents = [];
21 var eventCounter = 0;
21 var eventCounter = 0;
22 var asyncTimers = [];
22 var asyncTimers = [];
23− var initialProgramState = {
24− nodeValues: [],
25− asyncTimers: []
26− };
27
23
28 function wrapNotify(id, v) {
24 function wrapNotify(id, v) {
29 var timestep = Date.now();
25 var timestep = Date.now();
@@ -51,24 +47,131 @@ function debuggerInit(module, runtime) {
51 recordedEvents.push({ id:id, value:v, timestep:timestep });
47 recordedEvents.push({ id:id, value:v, timestep:timestep });
52 }
48 }
53
49
50+ function clearAsyncEvents() {
51+ asyncTimers.forEach(function(timer) {
52+ clearTimeout(timer.timerId);
53+ });
54+ }
55+
56+ function clearRecordedEvents() {
57+ recordedEvents = [];
58+ }
59+
60+ function getRecordedEvents() {
61+ return recordedEvents.slice();
62+ }
63+
64+ function setPaused(v) {
65+ programPaused = v;
66+ }
67+
68+ function getPaused() {
69+ return programPaused;
70+ }
71+
72+ var wrappedRuntime = {
73+ notify: wrapNotify,
74+ runDelayed: wrapRunDelayed,
75+ node: runtime.node,
76+ display: runtime.display,
77+ id: runtime.id,
78+ addListener: runtime.addListener,
79+ inputs: runtime.inputs
80+ };
81+
82+ var moduleInstance = module.make(wrappedRuntime);
83+ var moduleNodes = flattenNodes(wrappedRuntime.inputs);
84+
85+ return {
86+ moduleInstance: moduleInstance,
87+ moduleNodes: moduleNodes,
88+ initialNodeValues: saveNodeValues(moduleNodes),
89+ initialAsyncTimers: asyncTimers.slice(),
90+ // API functions
91+ clearAsyncEvents: clearAsyncEvents,
92+ clearRecordedEvents: clearRecordedEvents,
93+ getRecordedEvents: getRecordedEvents,
94+ getPaused: getPaused,
95+ setPaused: setPaused
96+ };
97+}
98+
99+function debuggerInit(debugModule, runtime) {
100+ var Signal = Elm.Signal.make(runtime);
101+ var List = Elm.List.make(runtime);
102+ var graphicsNode = debugModule.moduleInstance.main.kids[0];
103+
104+ var tracePathCanvas = document.createElement('canvas');
105+ tracePathCanvas.width = window.innerWidth;
106+ tracePathCanvas.height = window.innerHeight;
107+ tracePathCanvas.style.position = "absolute";
108+ tracePathCanvas.style.top = "0";
109+ tracePathCanvas.style.left = "0";
110+ runtime.node.parentNode.appendChild(tracePathCanvas);
111+
112+ function graphicsUpdate(currentScene) {
113+ var ctx = tracePathCanvas.getContext('2d');
114+ ctx.clearRect(0, 0, tracePathCanvas.width, tracePathCanvas.height);
115+ ctx.fillText("Debugger trace path", 20, 20);
116+
117+ function drawElement(elem) {
118+ if (elem.element.ctor == "Custom" && elem.element.type == "Collage")
119+ {
120+ List.map(drawForm)(elem.element.model.forms);
121+ }
122+ else if (elem.element.ctor == "Image")
123+ {
124+ var x = 0;
125+ var y = 0;
126+ ctx.beginPath();
127+ ctx.arc(x, y, 2, 0, 2*Math.PI);
128+ ctx.fillStyle = "grey";
129+ ctx.fill();
130+ ctx.lineWidth = 1;
131+ ctx.strokeStype = "black";
132+ ctx.stroke();
133+ }
134+ }
135+
136+ function drawForm(form) {
137+ ctx.save();
138+ ctx.scale(form.scale, form.scale);
139+ ctx.rotate(form.theta);
140+ ctx.translate(form.x, -form.y);
141+ if (form.form.ctor == "FElement")
142+ {
143+ drawElement(form.form._0);
144+ }
145+
146+ ctx.restore();
147+ }
148+
149+ ctx.save();
150+ ctx.translate(ctx.canvas.width/2, ctx.canvas.height/2);
151+ drawElement(currentScene);
152+ ctx.restore();
153+ }
154+
155+ var tracePathNode = A2(Signal.lift, graphicsUpdate, graphicsNode);
156+
54 function resetProgram() {
157 function resetProgram() {
55− clearAsyncEvents();
158+ debugModule.clearAsyncEvents();
56− restoreNodeValues(allNodes, initialProgramState.nodeValues);
159+ restoreNodeValues(debugModule.moduleNodes, debugModule.initialNodeValues);
57 redrawGraphics();
160 redrawGraphics();
58 }
161 }
59
162
60 function restartProgram() {
163 function restartProgram() {
61 resetProgram();
164 resetProgram();
62− recordedEvents = [];
165+ debugModule.clearRecordedEvents();
63− initialProgramState.asyncTimers.forEach(function(timer) {
166+ debugModule.initialAsyncTimers.forEach(function(timer) {
64 var func = timer.func;
167 var func = timer.func;
65 func();
168 func();
66 });
169 });
67 }
170 }
68
171
69 function stepTo(index) {
172 function stepTo(index) {
70− if (!programPaused) {
173+ if (!debugModule.getPaused()) {
71− programPaused = true;
174+ debugModule.setPaused(true);
72 resetProgram();
175 resetProgram();
73 }
176 }
74
177
@@ -95,12 +198,6 @@ function debuggerInit(module, runtime) {
95 return recordedEvents.length - 1;
198 return recordedEvents.length - 1;
96 }
199 }
97
200
98− function clearAsyncEvents() {
99− asyncTimers.forEach(function(timer) {
100− clearTimeout(timer.timerId);
101− });
102− }
103−
104 function doPlayback(eventList) {
201 function doPlayback(eventList) {
105 var x = eventList.shift();
202 var x = eventList.shift();
106 var time = x[2];
203 var time = x[2];
@@ -113,38 +210,18 @@ function debuggerInit(module, runtime) {
113 }
210 }
114
211
115 function redrawGraphics() {
212 function redrawGraphics() {
116− var graphicsFoldp = moduleInstance.main.kids[0];
117− graphicsFoldp.recv(Date.now(), true, moduleInstance.main.id);
213+ graphicsNode.recv(Date.now(), true, debugModule.moduleInstance.main.id);
118 }
214 }
119
215
120− var wrappedRuntime = {
121− notify: wrapNotify,
122− runDelayed: wrapRunDelayed,
123− node: runtime.node,
124− display: runtime.display,
125− id: runtime.id,
126− addListener: runtime.addListener,
127− inputs: runtime.inputs
128− };
129−
130− var moduleInstance = module.make(wrappedRuntime);
131−
132 var elmDebugger = {
216 var elmDebugger = {
133− moduleInstance: moduleInstance,
134−
135− // debugger functions
136− reset: resetProgram,
217+ reset: resetProgram,
137− restart: restartProgram,
218+ restart: restartProgram,
138− getMaxSteps: getMaxSteps,
219+ getMaxSteps: getMaxSteps,
139− stepTo: stepTo
220+ stepTo: stepTo
140 };
221 };
141
222
142− allNodes = flattenNodes(wrappedRuntime.inputs);
143− initialProgramState.nodeValues = saveNodeValues(allNodes);
144− initialProgramState.asyncTimers = asyncTimers.slice();
145−
146 return elmDebugger;
223 return elmDebugger;
147−};
224+}
148
225
149
226
150
227