Skip to content

Commit afd50e8

Browse files
Update debugger file to use most recent one
1 parent 0dc5b5d commit afd50e8

File tree

3 files changed

+129
-42
lines changed

3 files changed

+129
-42
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ doc/static/skulpt.min.js
44
doc/static/debugger/debugger.js
55
doc/static/dist/*
66
doc/ProgMan/
7+
dist/
78
vendor/
89
node_modules/
910
*.pyc

debugger/debugger.js

+127-41
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Debugger support for skulpt module
33
*/
44

5-
var Sk = Sk || {}; //jshint ignore:line
5+
var Sk = window.Sk || {}; //jshint ignore:line
66

77
/**
88
* Changes :
@@ -22,7 +22,7 @@ var Sk = Sk || {}; //jshint ignore:line
2222
*/
2323

2424
var DEBUG_DEBUGGER = false;
25-
var debuggerLog = function() {
25+
var debuggerLog = function () {
2626
if (DEBUG_DEBUGGER) {
2727
// 1. Convert args to a normal array
2828
var args = Array.prototype.slice.call(arguments);
@@ -48,15 +48,15 @@ function debuggerHasOwnProperty(obj, prop) {
4848
(!(prop in proto) || proto[prop] !== obj[prop]);
4949
}
5050

51-
Sk.Breakpoint = function(filename, lineno, colno) {
51+
Sk.Breakpoint = function (filename, lineno, colno) {
5252
this.filename = filename;
5353
this.lineno = lineno;
5454
this.colno = colno;
5555
this.enabled = true;
5656
this.ignore_count = 0;
5757
};
5858

59-
Sk.Debugger = function(filename, output_callback) {
59+
Sk.Debugger = function (filename, output_callback) {
6060
this.dbg_breakpoints = {};
6161
this.tmp_breakpoints = {};
6262
this.suspension_stack = [];
@@ -66,60 +66,119 @@ Sk.Debugger = function(filename, output_callback) {
6666
this.output_callback = output_callback;
6767
this.step_mode = false;
6868
this.filename = filename;
69+
70+
/**
71+
* Contains the last references of objects that will be retrieved by Skulpt's promises.
72+
*
73+
* This is required because the way Skulpt handles classes is so as it stores the reference of
74+
* the class before calling a method, and then retrieves it after. Since the codecast implementation
75+
* modify the references each time something is modified into an object, we need to get the updated
76+
* object, hence the last reference of that object when we want to get the result of the promise.
77+
*
78+
* Storing references of objects would disable the garbage collector to clear those objects when necessary,
79+
* so we also want to clean those references when there are not needed anymore.
80+
* Since it's possible to have a method of an object that calls another, or itself recursively, we store
81+
* the number of use of the reference, so we know when we can safely clear the reference.
82+
*
83+
* {
84+
* UUID_OBJ_1 : {
85+
* reference: The object 1,
86+
* nb: The number of use
87+
* },
88+
* UUID_OBJ_2 : {
89+
* reference: The object 2,
90+
* nb: The number of use
91+
* }
92+
* }
93+
*
94+
* When nb becomes 0, we can remove the reference as we don't need it anymore.
95+
*/
96+
this._promise_references = {};
97+
};
98+
99+
/**
100+
* Add a reference of an object that will be retrieved later using a Skulpt promise, and which
101+
* may later have a new reference.
102+
*
103+
* @param object The object.
104+
*/
105+
Sk.Debugger.prototype.registerPromiseReference = function (object) {
106+
if (object.hasOwnProperty('_uuid')) {
107+
if (!this._promise_references.hasOwnProperty(object._uuid)) {
108+
this._promise_references[object._uuid] = {
109+
reference: object,
110+
nb: 0
111+
}
112+
}
113+
114+
this._promise_references[object._uuid].nb++;
115+
}
69116
};
70117

71-
Sk.Debugger.prototype.print = function(txt) {
118+
/**
119+
* Updates the promise reference of an object if it exists.
120+
*
121+
* @param object The new object reference.
122+
*/
123+
Sk.Debugger.prototype.updatePromiseReference = function (object) {
124+
if (object.hasOwnProperty('_uuid') && this._promise_references.hasOwnProperty(object._uuid)) {
125+
this._promise_references[object._uuid].reference = object;
126+
}
127+
};
128+
129+
Sk.Debugger.prototype.print = function (txt) {
72130
if (this.output_callback != null) {
73131
this.output_callback.print(txt + "\n");
74132
}
75133
};
76134

77-
Sk.Debugger.prototype.get_source_line = function(lineno) {
135+
Sk.Debugger.prototype.get_source_line = function (lineno) {
78136
if (this.output_callback != null) {
79137
return this.output_callback.get_source_line(lineno);
80138
}
81139

82140
return "";
83141
};
84142

85-
Sk.Debugger.prototype.move_up_the_stack = function() {
143+
Sk.Debugger.prototype.move_up_the_stack = function () {
86144
this.current_suspension = Math.min(this.current_suspension + 1, this.suspension_stack.length - 1);
87145
};
88146

89-
Sk.Debugger.prototype.move_down_the_stack = function() {
147+
Sk.Debugger.prototype.move_down_the_stack = function () {
90148
this.current_suspension = Math.max(this.current_suspension - 1, 0);
91149
};
92150

93-
Sk.Debugger.prototype.enable_step_mode = function() {
151+
Sk.Debugger.prototype.enable_step_mode = function () {
94152
this.step_mode = true;
95153
};
96154

97-
Sk.Debugger.prototype.disable_step_mode = function() {
155+
Sk.Debugger.prototype.disable_step_mode = function () {
98156
this.step_mode = false;
99157
};
100158

101-
Sk.Debugger.prototype.get_suspension_stack = function() {
159+
Sk.Debugger.prototype.get_suspension_stack = function () {
102160
return this.suspension_stack;
103161
};
104162

105-
Sk.Debugger.prototype.get_active_suspension = function() {
163+
Sk.Debugger.prototype.get_active_suspension = function () {
106164
if (this.suspension_stack.length === 0) {
107165
return null;
108166
}
109167

110168
return this.suspension_stack[this.current_suspension];
111169
};
112170

113-
Sk.Debugger.prototype.generate_breakpoint_key = function(filename, lineno, colno) {
171+
Sk.Debugger.prototype.generate_breakpoint_key = function (filename, lineno, colno) {
114172
var key = filename + "-" + lineno;
115173
return key;
116174
};
117175

118-
Sk.Debugger.prototype.check_breakpoints = function(filename, lineno, colno, globals, locals) {
176+
Sk.Debugger.prototype.check_breakpoints = function (filename, lineno, colno, globals, locals) {
119177
// debuggerLog('check_breakpoints', filename, lineno, colno, globals, locals);
120178

121179
// If Step mode is enabled then ignore breakpoints since we will just break
122180
// at every line.
181+
return true;
123182
if (this.step_mode === true) {
124183
return true;
125184
}
@@ -147,27 +206,27 @@ Sk.Debugger.prototype.check_breakpoints = function(filename, lineno, colno, glob
147206
return false;
148207
};
149208

150-
Sk.Debugger.prototype.get_breakpoints_list = function() {
209+
Sk.Debugger.prototype.get_breakpoints_list = function () {
151210
return this.dbg_breakpoints;
152211
};
153212

154-
Sk.Debugger.prototype.disable_breakpoint = function(filename, lineno, colno) {
213+
Sk.Debugger.prototype.disable_breakpoint = function (filename, lineno, colno) {
155214
var key = this.generate_breakpoint_key(filename, lineno, colno);
156215

157216
if (debuggerHasOwnProperty(this.dbg_breakpoints, key)) {
158217
this.dbg_breakpoints[key].enabled = false;
159218
}
160219
};
161220

162-
Sk.Debugger.prototype.enable_breakpoint = function(filename, lineno, colno) {
221+
Sk.Debugger.prototype.enable_breakpoint = function (filename, lineno, colno) {
163222
var key = this.generate_breakpoint_key(filename, lineno, colno);
164223

165224
if (debuggerHasOwnProperty(this.dbg_breakpoints, key)) {
166225
this.dbg_breakpoints[key].enabled = true;
167226
}
168227
};
169228

170-
Sk.Debugger.prototype.clear_breakpoint = function(filename, lineno, colno) {
229+
Sk.Debugger.prototype.clear_breakpoint = function (filename, lineno, colno) {
171230
var key = this.generate_breakpoint_key(filename, lineno, colno);
172231
if (debuggerHasOwnProperty(this.dbg_breakpoints, key)) {
173232
delete this.dbg_breakpoints[key];
@@ -177,20 +236,20 @@ Sk.Debugger.prototype.clear_breakpoint = function(filename, lineno, colno) {
177236
}
178237
};
179238

180-
Sk.Debugger.prototype.clear_all_breakpoints = function() {
239+
Sk.Debugger.prototype.clear_all_breakpoints = function () {
181240
this.dbg_breakpoints = {};
182241
this.tmp_breakpoints = {};
183242
};
184243

185-
Sk.Debugger.prototype.set_ignore_count = function(filename, lineno, colno, count) {
244+
Sk.Debugger.prototype.set_ignore_count = function (filename, lineno, colno, count) {
186245
var key = this.generate_breakpoint_key(filename, lineno, colno);
187246
if (debuggerHasOwnProperty(this.dbg_breakpoints, key)) {
188247
var bp = this.dbg_breakpoints[key];
189248
bp.ignore_count = count;
190249
}
191250
};
192251

193-
Sk.Debugger.prototype.set_condition = function(filename, lineno, colno, lhs, cond, rhs) {
252+
Sk.Debugger.prototype.set_condition = function (filename, lineno, colno, lhs, cond, rhs) {
194253
var key = this.generate_breakpoint_key(filename, lineno, colno);
195254
var bp;
196255
if (debuggerHasOwnProperty(this.dbg_breakpoints, key)) {
@@ -204,7 +263,7 @@ Sk.Debugger.prototype.set_condition = function(filename, lineno, colno, lhs, con
204263
this.dbg_breakpoints[key] = bp;
205264
};
206265

207-
Sk.Debugger.prototype.print_suspension_info = function(suspension) {
266+
Sk.Debugger.prototype.print_suspension_info = function (suspension) {
208267
var filename = suspension.$filename;
209268
var lineno = suspension.$lineno;
210269
var colno = suspension.$colno;
@@ -217,7 +276,7 @@ Sk.Debugger.prototype.print_suspension_info = function(suspension) {
217276
}
218277
};
219278

220-
Sk.Debugger.prototype.set_suspension = function(suspension) {
279+
Sk.Debugger.prototype.set_suspension = function (suspension) {
221280
debuggerLog('set_suspension', suspension);
222281

223282
var parent = null;
@@ -244,25 +303,25 @@ Sk.Debugger.prototype.set_suspension = function(suspension) {
244303
this.print_suspension_info(suspension);
245304
};
246305

247-
Sk.Debugger.prototype.add_breakpoint = function(filename, lineno, colno, temporary) {
306+
Sk.Debugger.prototype.add_breakpoint = function (filename, lineno, colno, temporary) {
248307
var key = this.generate_breakpoint_key(filename, lineno, colno);
249308
this.dbg_breakpoints[key] = new Sk.Breakpoint(filename, lineno, colno);
250309
if (temporary) {
251310
this.tmp_breakpoints[key] = true;
252311
}
253312
};
254313

255-
Sk.Debugger.prototype.suspension_handler = function(susp) {
256-
return new Promise(function(resolve, reject) {
314+
Sk.Debugger.prototype.suspension_handler = function (susp) {
315+
return new Promise(function (resolve, reject) {
257316
try {
258317
resolve(susp.resume());
259-
} catch(e) {
318+
} catch (e) {
260319
reject(e);
261320
}
262321
});
263322
};
264323

265-
Sk.Debugger.prototype.resume = function(resolve, reject) {
324+
Sk.Debugger.prototype.resume = function (resolve, reject) {
266325
debuggerLog('resume');
267326

268327
// Reset the suspension stack to the topmost
@@ -277,20 +336,47 @@ Sk.Debugger.prototype.resume = function(resolve, reject) {
277336
} else {
278337
var promise = this.suspension_handler(this.get_active_suspension());
279338
var self = this;
280-
promise.then(function(value) {
281-
self.success(value, resolve, reject);
282-
}, function(error) {
283-
self.error(error, reject);
339+
promise.then(function (value) {
340+
if (value && value.data && value.data.promise) {
341+
// If waiting for input, wait that it has resolved too before continuing.
342+
value.data.promise.then((inputValue) => {
343+
// Skulpt is taking the value into the result parameter, so let's put it in !
344+
value.data.result = inputValue;
345+
346+
self.success(value, resolve, reject);
347+
});
348+
} else if (value && value.hasOwnProperty('_uuid')) {
349+
/**
350+
* In the case the value is a class, its reference may have changed since the
351+
* creation of the Promise, which is done before the call to a method.
352+
* We want to get its last reference.
353+
*/
354+
value = self._promise_references[value._uuid].reference;
355+
self._promise_references[value._uuid].nb--;
356+
if (self._promise_references[value._uuid].nb < 1) {
357+
delete self._promise_references[value._uuid];
358+
}
359+
360+
self.success(value, resolve, reject);
361+
} else {
362+
self.success(value, resolve, reject);
363+
}
364+
}, function (error) {
365+
/**
366+
* Note : We call resolve and not reject in case of error because resolve throws an Exception
367+
* and breaks the player which stops when there is an exception.
368+
*/
369+
self.error(error, resolve);
284370
});
285371
}
286372
};
287373

288-
Sk.Debugger.prototype.pop_suspension_stack = function() {
374+
Sk.Debugger.prototype.pop_suspension_stack = function () {
289375
this.suspension_stack.pop();
290376
this.current_suspension -= 1;
291377
};
292378

293-
Sk.Debugger.prototype.success = function(r, resolve, reject) {
379+
Sk.Debugger.prototype.success = function (r, resolve, reject) {
294380
debuggerLog('success', r, resolve);
295381

296382
if (r instanceof Sk.misceval.Suspension) {
@@ -321,7 +407,7 @@ Sk.Debugger.prototype.success = function(r, resolve, reject) {
321407
var parent_suspension = this.get_active_suspension();
322408
// The child has completed the execution. So override the child's resume
323409
// so we can continue the execution.
324-
parent_suspension.child.resume = function() {
410+
parent_suspension.child.resume = function () {
325411
return r;
326412
};
327413

@@ -338,7 +424,7 @@ Sk.Debugger.prototype.success = function(r, resolve, reject) {
338424
}
339425
};
340426

341-
Sk.Debugger.prototype.error = function(e, reject) {
427+
Sk.Debugger.prototype.error = function (e, reject) {
342428
debuggerLog('error', e);
343429

344430
if (this.output_callback != null) {
@@ -363,20 +449,20 @@ Sk.Debugger.prototype.error = function(e, reject) {
363449
}
364450
};
365451

366-
Sk.Debugger.prototype.asyncToPromise = function(suspendablefn, suspHandlers, debugger_obj) {
367-
return new Promise(function(resolve, reject) {
452+
Sk.Debugger.prototype.asyncToPromise = function (suspendablefn, suspHandlers, debugger_obj) {
453+
return new Promise(function (resolve, reject) {
368454
try {
369455
var r = suspendablefn();
370456

371-
(function handleResponse (r) {
457+
(function handleResponse(r) {
372458
try {
373459
while (r instanceof Sk.misceval.Suspension) {
374460
debugger_obj.set_suspension(r);
375461
return;
376462
}
377463

378464
resolve(r);
379-
} catch(e) {
465+
} catch (e) {
380466
reject(e);
381467
}
382468
})(r);
@@ -387,7 +473,7 @@ Sk.Debugger.prototype.asyncToPromise = function(suspendablefn, suspHandlers, deb
387473
});
388474
};
389475

390-
Sk.Debugger.prototype.execute = function(suspendablefn, suspHandlers) {
476+
Sk.Debugger.prototype.execute = function (suspendablefn, suspHandlers) {
391477
var r = suspendablefn();
392478

393479
if (r instanceof Sk.misceval.Suspension) {

src/persistent.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const getCurrentSusp = function(susp) {
1414
if (susp.hasOwnProperty("$tmps")) {
1515
return susp;
1616
}
17-
if (susp.hasOwnProperty("child")) {
17+
if (susp.hasOwnProperty("child") && susp.child) {
1818
return getCurrentSusp(susp.child);
1919
}
2020

0 commit comments

Comments
 (0)