Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(366)

Side by Side Diff: test/mjsunit/debug-scopes.js

Issue 123021: Add scope chain information to the debugger (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/runtime.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ native
OLDNEW
(Empty)
1 // Copyright 2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 // Flags: --expose-debug-as debug
29 // The functions used for testing backtraces. They are at the top to make the
30 // testing of source line/column easier.
31
32
33 // Get the Debug object exposed from the debug context global object.
34 Debug = debug.Debug
35
36 var name;
37 var listener_delegate;
38 var listener_called;
39 var exception;
40 var begin_test_count = 0;
41 var end_test_count = 0;
42 var break_count = 0;
43
44
45 // Debug event listener which delegates.
46 function listener(event, exec_state, event_data, data) {
47 try {
48 if (event == Debug.DebugEvent.Break) {
49 break_count++;
50 listener_called = true;
51 listener_delegate(exec_state)
52 }
53 } catch (e) {
54 exception = e;
55 }
56 }
57
58 // Add the debug event listener.
59 Debug.setListener(listener);
60
61
62 // Initialize for a noew test.
63 function BeginTest(name) {
64 test_name = name;
65 listener_delegate = null;
66 listener_called = false;
67 exception = null;
68 begin_test_count++;
69 }
70
71
72 // Check result of a test.
73 function EndTest() {
74 assertTrue(listener_called, "listerner not called for " + test_name);
75 assertNull(exception, test_name)
76 end_test_count++;
77 }
78
79
80 // Check that the scope chain contains the expected types of scopes.
81 function CheckScopeChain(scopes, exec_state) {
82 assertEquals(scopes.length, exec_state.frame().scopeCount());
83 for (var i = 0; i < scopes.length; i++) {
84 var scope = exec_state.frame().scope(i);
85 assertTrue(scope.isScope());
86 assertEquals(scopes[i], scope.scopeType());
87
88 // Check the global object when hitting the global scope.
89 if (scopes[i] == debug.ScopeType.Global) {
90 assertEquals(this, scope.scopeObject().value());
91 }
92 }
93
94 // Get the debug command processor.
95 var dcp = exec_state.debugCommandProcessor();
96
97 // Send a scopes request and check the result.
98 var json;
99 request_json = '{"seq":0,"type":"request","command":"scopes"}'
100 var response_json = dcp.processDebugJSONRequest(request_json);
101 var response = JSON.parse(response_json);
102 assertEquals(scopes.length, response.body.scopes.length);
103 for (var i = 0; i < scopes.length; i++) {
104 assertEquals(i, response.body.scopes[i].index);
105 assertEquals(scopes[i], response.body.scopes[i].type);
106 if (scopes[i] == debug.ScopeType.Local ||
107 scopes[i] == debug.ScopeType.Closure) {
108 assertTrue(response.body.scopes[i].object.ref < 0);
109 } else {
110 assertTrue(response.body.scopes[i].object.ref >= 0);
111 }
112 var found = false;
113 for (var j = 0; j < response.refs.length && !found; j++) {
114 found = response.refs[j].handle == response.body.scopes[i].object.ref;
115 }
116 assertTrue(found, "Scope object " + response.body.scopes[i].object.ref + " n ot found");
117 }
118 }
119
120
121 // Check that the content of the scope is as expected. For functions just check
122 // that there is a function.
123 function CheckScopeContent(content, number, exec_state) {
124 var scope = exec_state.frame().scope(number)
125 var count = 0;
126 for (var p in content) {
127 var property_mirror = scope.scopeObject().property(p);
128 assertFalse(property_mirror.isUndefined(), 'property ' + p + ' not found in scope');
129 if (typeof(content[p]) === 'function') {
130 assertTrue(property_mirror.value().isFunction());
131 } else {
132 assertEquals(content[p], property_mirror.value().value(), 'property ' + p + ' has unexpected value');
133 }
134 count++;
135 }
136
137 // 'arguments' and might be exposed in the local and closure scope. Just
138 // ignore this.
139 var scope_size = scope.scopeObject().properties().length;
140 if (!scope.scopeObject().property('arguments').isUndefined()) {
141 scope_size--;
142 }
143 if (count != scope_size) {
144 print('Names found in scope:');
145 var names = scope.scopeObject().propertyNames();
146 for (var i = 0; i < names.length; i++) {
147 print(names[i]);
148 }
149 }
150 assertEquals(count, scope_size);
151
152 // Get the debug command processor.
153 var dcp = exec_state.debugCommandProcessor();
154
155 // Send a scope request for information on a single scope and check the
156 // result.
157 request_json = '{"seq":0,"type":"request","command":"scope","arguments":{"numb er":'
158 request_json += scope.scopeIndex();
159 request_json += '}}'
160 var response_json = dcp.processDebugJSONRequest(request_json);
161 var response = JSON.parse(response_json);
162 assertEquals(scope.scopeType(), response.body.type);
163 assertEquals(number, response.body.index);
164 if (scope.scopeType() == debug.ScopeType.Local ||
165 scope.scopeType() == debug.ScopeType.Closure) {
166 assertTrue(response.body.object.ref < 0);
167 } else {
168 assertTrue(response.body.object.ref >= 0);
169 }
170 var found = false;
171 for (var i = 0; i < response.refs.length && !found; i++) {
172 found = response.refs[i].handle == response.body.object.ref;
173 }
174 assertTrue(found, "Scope object " + response.body.object.ref + " not found");
175 }
176
177
178 // Simple empty local scope.
179 BeginTest("Local 1");
180
181 function local_1() {
182 debugger;
183 }
184
185 listener_delegate = function(exec_state) {
186 CheckScopeChain([debug.ScopeType.Local,
187 debug.ScopeType.Global], exec_state);
188 CheckScopeContent({}, 0, exec_state);
189 }
190 local_1()
191 EndTest();
192
193
194 // Local scope with a parameter.
195 BeginTest("Local 2");
196
197 function local_2(a) {
198 debugger;
199 }
200
201 listener_delegate = function(exec_state) {
202 CheckScopeChain([debug.ScopeType.Local,
203 debug.ScopeType.Global], exec_state);
204 CheckScopeContent({a:1}, 0, exec_state);
205 }
206 local_2(1)
207 EndTest();
208
209
210 // Local scope with a parameter and a local variable.
211 BeginTest("Local 3");
212
213 function local_3(a) {
214 var x = 3;
215 debugger;
216 }
217
218 listener_delegate = function(exec_state) {
219 CheckScopeChain([debug.ScopeType.Local,
220 debug.ScopeType.Global], exec_state);
221 CheckScopeContent({a:1,x:3}, 0, exec_state);
222 }
223 local_3(1)
224 EndTest();
225
226
227 // Local scope with parameters and local variables.
228 BeginTest("Local 4");
229
230 function local_4(a, b) {
231 var x = 3;
232 var y = 4;
233 debugger;
234 }
235
236 listener_delegate = function(exec_state) {
237 CheckScopeChain([debug.ScopeType.Local,
238 debug.ScopeType.Global], exec_state);
239 CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state);
240 }
241 local_4(1, 2)
242 EndTest();
243
244
245 // Empty local scope with use of eval.
246 BeginTest("Local 5");
247
248 function local_5() {
249 eval('');
250 debugger;
251 }
252
253 listener_delegate = function(exec_state) {
254 CheckScopeChain([debug.ScopeType.Local,
255 debug.ScopeType.Global], exec_state);
256 CheckScopeContent({}, 0, exec_state);
257 }
258 local_5()
259 EndTest();
260
261
262 // Local introducing local variable using eval.
263 BeginTest("Local 6");
264
265 function local_6() {
266 eval('var i = 5');
267 debugger;
268 }
269
270 listener_delegate = function(exec_state) {
271 CheckScopeChain([debug.ScopeType.Local,
272 debug.ScopeType.Global], exec_state);
273 CheckScopeContent({i:5}, 0, exec_state);
274 }
275 local_6()
276 EndTest();
277
278
279 // Local scope with parameters, local variables and local variable introduced
280 // using eval.
281 BeginTest("Local 7");
282
283 function local_7(a, b) {
284 var x = 3;
285 var y = 4;
286 eval('var i = 5');
287 eval('var j = 6');
288 debugger;
289 }
290
291 listener_delegate = function(exec_state) {
292 CheckScopeChain([debug.ScopeType.Local,
293 debug.ScopeType.Global], exec_state);
294 CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 0, exec_state);
295 }
296 local_7(1, 2)
297 EndTest();
298
299
300 // Single empty with block.
301 BeginTest("With 1");
302
303 function with_1() {
304 with({}) {
305 debugger;
306 }
307 }
308
309 listener_delegate = function(exec_state) {
310 CheckScopeChain([debug.ScopeType.With,
311 debug.ScopeType.Local,
312 debug.ScopeType.Global], exec_state);
313 CheckScopeContent({}, 0, exec_state);
314 }
315 with_1()
316 EndTest();
317
318
319 // Nested empty with blocks.
320 BeginTest("With 2");
321
322 function with_2() {
323 with({}) {
324 with({}) {
325 debugger;
326 }
327 }
328 }
329
330 listener_delegate = function(exec_state) {
331 CheckScopeChain([debug.ScopeType.With,
332 debug.ScopeType.With,
333 debug.ScopeType.Local,
334 debug.ScopeType.Global], exec_state);
335 CheckScopeContent({}, 0, exec_state);
336 CheckScopeContent({}, 1, exec_state);
337 }
338 with_2()
339 EndTest();
340
341
342 // With block using an in-place object literal.
343 BeginTest("With 3");
344
345 function with_3() {
346 with({a:1,b:2}) {
347 debugger;
348 }
349 }
350
351 listener_delegate = function(exec_state) {
352 CheckScopeChain([debug.ScopeType.With,
353 debug.ScopeType.Local,
354 debug.ScopeType.Global], exec_state);
355 CheckScopeContent({a:1,b:2}, 0, exec_state);
356 }
357 with_3()
358 EndTest();
359
360
361 // Nested with blocks using in-place object literals.
362 BeginTest("With 4");
363
364 function with_4() {
365 with({a:1,b:2}) {
366 with({a:2,b:1}) {
367 debugger;
368 }
369 }
370 }
371
372 listener_delegate = function(exec_state) {
373 CheckScopeChain([debug.ScopeType.With,
374 debug.ScopeType.With,
375 debug.ScopeType.Local,
376 debug.ScopeType.Global], exec_state);
377 CheckScopeContent({a:2,b:1}, 0, exec_state);
378 CheckScopeContent({a:1,b:2}, 1, exec_state);
379 }
380 with_4()
381 EndTest();
382
383
384 // Nested with blocks using existing object.
385 BeginTest("With 5");
386
387 var with_object = {c:3,d:4};
388 function with_5() {
389 with(with_object) {
390 with(with_object) {
391 debugger;
392 }
393 }
394 }
395
396 listener_delegate = function(exec_state) {
397 CheckScopeChain([debug.ScopeType.With,
398 debug.ScopeType.With,
399 debug.ScopeType.Local,
400 debug.ScopeType.Global], exec_state);
401 CheckScopeContent(with_object, 0, exec_state);
402 CheckScopeContent(with_object, 1, exec_state);
403 assertEquals(exec_state.frame().scope(0).scopeObject(), exec_state.frame().sco pe(1).scopeObject());
404 assertEquals(with_object, exec_state.frame().scope(1).scopeObject().value());
405 }
406 with_5()
407 EndTest();
408
409
410 // Simple closure formed by returning an inner function referering the outer
411 // functions arguments.
412 BeginTest("Closure 1");
413
414 function closure_1(a) {
415 function f() {
416 debugger;
417 return a;
418 };
419 return f;
420 }
421
422 listener_delegate = function(exec_state) {
423 CheckScopeChain([debug.ScopeType.Local,
424 debug.ScopeType.Closure,
425 debug.ScopeType.Global], exec_state);
426 CheckScopeContent({a:1}, 1, exec_state);
427 }
428 closure_1(1)()
429 EndTest();
430
431
432 // Simple closure formed by returning an inner function referering the outer
433 // functions arguments. Due to VM optimizations parts of the actual closure is
434 // missing from the debugger information.
435 BeginTest("Closure 2");
436
437 function closure_2(a, b) {
438 var x = a + 2;
439 var y = b + 2;
440 function f() {
441 debugger;
442 return a + x;
443 };
444 return f;
445 }
446
447 listener_delegate = function(exec_state) {
448 CheckScopeChain([debug.ScopeType.Local,
449 debug.ScopeType.Closure,
450 debug.ScopeType.Global], exec_state);
451 CheckScopeContent({a:1,x:3}, 1, exec_state);
452 }
453 closure_2(1, 2)()
454 EndTest();
455
456
457 // Simple closure formed by returning an inner function referering the outer
458 // functions arguments. Using all arguments and locals from the outer function
459 // in the inner function makes these part of the debugger information on the
460 // closure.
461 BeginTest("Closure 3");
462
463 function closure_3(a, b) {
464 var x = a + 2;
465 var y = b + 2;
466 function f() {
467 debugger;
468 return a + b + x + y;
469 };
470 return f;
471 }
472
473 listener_delegate = function(exec_state) {
474 CheckScopeChain([debug.ScopeType.Local,
475 debug.ScopeType.Closure,
476 debug.ScopeType.Global], exec_state);
477 CheckScopeContent({a:1,b:2,x:3,y:4}, 1, exec_state);
478 }
479 closure_3(1, 2)()
480 EndTest();
481
482
483
484 // Simple closure formed by returning an inner function referering the outer
485 // functions arguments. Using all arguments and locals from the outer function
486 // in the inner function makes these part of the debugger information on the
487 // closure. Use the inner function as well...
488 BeginTest("Closure 4");
489
490 function closure_4(a, b) {
491 var x = a + 2;
492 var y = b + 2;
493 function f() {
494 debugger;
495 if (f) {
496 return a + b + x + y;
497 }
498 };
499 return f;
500 }
501
502 listener_delegate = function(exec_state) {
503 CheckScopeChain([debug.ScopeType.Local,
504 debug.ScopeType.Closure,
505 debug.ScopeType.Global], exec_state);
506 CheckScopeContent({a:1,b:2,x:3,y:4,f:function(){}}, 1, exec_state);
507 }
508 closure_4(1, 2)()
509 EndTest();
510
511
512
513 // Simple closure formed by returning an inner function referering the outer
514 // functions arguments. In the presence of eval all arguments and locals
515 // (including the inner function itself) from the outer function becomes part of
516 // the debugger infformation on the closure.
517 BeginTest("Closure 5");
518
519 function closure_5(a, b) {
520 var x = 3;
521 var y = 4;
522 function f() {
523 eval('');
524 debugger;
525 return 1;
526 };
527 return f;
528 }
529
530 listener_delegate = function(exec_state) {
531 CheckScopeChain([debug.ScopeType.Local,
532 debug.ScopeType.Closure,
533 debug.ScopeType.Global], exec_state);
534 CheckScopeContent({a:1,b:2,x:3,y:4,f:function(){}}, 1, exec_state);
535 }
536 closure_5(1, 2)()
537 EndTest();
538
539
540 // Two closures. Due to optimizations only the parts actually used are provided
541 // through the debugger information.
542 BeginTest("Closure 6");
543 function closure_6(a, b) {
544 function f(a, b) {
545 var x = 3;
546 var y = 4;
547 return function() {
548 var x = 3;
549 var y = 4;
550 debugger;
551 some_global = a;
552 return f;
553 }
554 }
555 return f(a, b);
556 }
557
558 listener_delegate = function(exec_state) {
559 CheckScopeChain([debug.ScopeType.Local,
560 debug.ScopeType.Closure,
561 debug.ScopeType.Closure,
562 debug.ScopeType.Global], exec_state);
563 CheckScopeContent({a:1}, 1, exec_state);
564 CheckScopeContent({f:function(){}}, 2, exec_state);
565 }
566 closure_6(1, 2)()
567 EndTest();
568
569
570 // Two closures. In the presence of eval all information is provided as the
571 // compiler cannot determine which parts are used.
572 BeginTest("Closure 7");
573 function closure_7(a, b) {
574 var x = 3;
575 var y = 4;
576 eval('var i = 5');
577 eval('var j = 6');
578 function f(a, b) {
579 var x = 3;
580 var y = 4;
581 eval('var i = 5');
582 eval('var j = 6');
583 return function() {
584 debugger;
585 some_global = a;
586 return f;
587 }
588 }
589 return f(a, b);
590 }
591
592 listener_delegate = function(exec_state) {
593 CheckScopeChain([debug.ScopeType.Local,
594 debug.ScopeType.Closure,
595 debug.ScopeType.Closure,
596 debug.ScopeType.Global], exec_state);
597 CheckScopeContent({}, 0, exec_state);
598 CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 1, exec_state);
599 CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6,f:function(){}}, 2, exec_state);
600 }
601 closure_7(1, 2)()
602 EndTest();
603
604
605 // Test a mixture of scopes.
606 BeginTest("The full monty");
607 function the_full_monty(a, b) {
608 var x = 3;
609 var y = 4;
610 eval('var i = 5');
611 eval('var j = 6');
612 function f(a, b) {
613 var x = 9;
614 var y = 10;
615 eval('var i = 11');
616 eval('var j = 12');
617 with ({j:13}){
618 return function() {
619 var x = 14;
620 with ({a:15}) {
621 with ({b:16}) {
622 debugger;
623 some_global = a;
624 return f;
625 }
626 }
627 }
628 }
629 }
630 return f(a, b);
631 }
632
633 listener_delegate = function(exec_state) {
634 CheckScopeChain([debug.ScopeType.With,
635 debug.ScopeType.With,
636 debug.ScopeType.Local,
637 debug.ScopeType.With,
638 debug.ScopeType.Closure,
639 debug.ScopeType.Closure,
640 debug.ScopeType.Global], exec_state);
641 CheckScopeContent({b:16}, 0, exec_state);
642 CheckScopeContent({a:15}, 1, exec_state);
643 CheckScopeContent({x:14}, 2, exec_state);
644 CheckScopeContent({j:13}, 3, exec_state);
645 CheckScopeContent({a:1,b:2,x:9,y:10,i:11,j:12}, 4, exec_state);
646 CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6,f:function(){}}, 5, exec_state);
647 }
648 the_full_monty(1, 2)()
649 EndTest();
650
651 // Test global scope.
652 BeginTest("Global");
653 listener_delegate = function(exec_state) {
654 CheckScopeChain([debug.ScopeType.Global], exec_state);
655 }
656 debugger;
657 EndTest();
658
659 assertEquals(begin_test_count, break_count, 'one or more tests did not enter the debugger');
660 assertEquals(begin_test_count, end_test_count, 'one or more tests did not have i ts result checked');
OLDNEW
« no previous file with comments | « src/runtime.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698