blob: 40adf5b2d2a3f35b4e92f790144518a3043176c1 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// 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.
Ben Murdoch8b112d22011-06-08 16:22:53 +010034Debug = debug.Debug;
Steve Blocka7e24c12009-10-30 11:49:00 +000035
Ben Murdoch8b112d22011-06-08 16:22:53 +010036var test_name;
Steve Blocka7e24c12009-10-30 11:49:00 +000037var listener_delegate;
38var listener_called;
39var exception;
40var begin_test_count = 0;
41var end_test_count = 0;
42var break_count = 0;
43
44
45// Debug event listener which delegates.
46function listener(event, exec_state, event_data, data) {
47 try {
48 if (event == Debug.DebugEvent.Break) {
49 break_count++;
50 listener_called = true;
Ben Murdoch8b112d22011-06-08 16:22:53 +010051 listener_delegate(exec_state);
Steve Blocka7e24c12009-10-30 11:49:00 +000052 }
53 } catch (e) {
54 exception = e;
55 }
56}
57
58// Add the debug event listener.
59Debug.setListener(listener);
60
61
Ben Murdoch8b112d22011-06-08 16:22:53 +010062// Initialize for a new test.
Steve Blocka7e24c12009-10-30 11:49:00 +000063function 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.
73function EndTest() {
74 assertTrue(listener_called, "listerner not called for " + test_name);
Ben Murdoch8b112d22011-06-08 16:22:53 +010075 assertNull(exception, test_name);
Steve Blocka7e24c12009-10-30 11:49:00 +000076 end_test_count++;
77}
78
79
80// Check that the scope chain contains the expected types of scopes.
81function 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());
Steve Block6ded16b2010-05-10 14:33:55 +010087
Steve Blocka7e24c12009-10-30 11:49:00 +000088 // Check the global object when hitting the global scope.
89 if (scopes[i] == debug.ScopeType.Global) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010090 // Objects don't have same class (one is "global", other is "Object",
91 // so just check the properties directly.
92 assertPropertiesEqual(this, scope.scopeObject().value());
Steve Blocka7e24c12009-10-30 11:49:00 +000093 }
94 }
Steve Block6ded16b2010-05-10 14:33:55 +010095
Steve Blocka7e24c12009-10-30 11:49:00 +000096 // Get the debug command processor.
Steve Block3ce2e202009-11-05 08:53:23 +000097 var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
Steve Block6ded16b2010-05-10 14:33:55 +010098
Steve Blocka7e24c12009-10-30 11:49:00 +000099 // Send a scopes request and check the result.
100 var json;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100101 var request_json = '{"seq":0,"type":"request","command":"scopes"}';
Steve Blocka7e24c12009-10-30 11:49:00 +0000102 var response_json = dcp.processDebugJSONRequest(request_json);
103 var response = JSON.parse(response_json);
104 assertEquals(scopes.length, response.body.scopes.length);
105 for (var i = 0; i < scopes.length; i++) {
106 assertEquals(i, response.body.scopes[i].index);
107 assertEquals(scopes[i], response.body.scopes[i].type);
108 if (scopes[i] == debug.ScopeType.Local ||
109 scopes[i] == debug.ScopeType.Closure) {
110 assertTrue(response.body.scopes[i].object.ref < 0);
111 } else {
112 assertTrue(response.body.scopes[i].object.ref >= 0);
113 }
114 var found = false;
115 for (var j = 0; j < response.refs.length && !found; j++) {
116 found = response.refs[j].handle == response.body.scopes[i].object.ref;
117 }
118 assertTrue(found, "Scope object " + response.body.scopes[i].object.ref + " not found");
119 }
120}
121
122
123// Check that the content of the scope is as expected. For functions just check
124// that there is a function.
125function CheckScopeContent(content, number, exec_state) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100126 var scope = exec_state.frame().scope(number);
Steve Blocka7e24c12009-10-30 11:49:00 +0000127 var count = 0;
128 for (var p in content) {
129 var property_mirror = scope.scopeObject().property(p);
130 assertFalse(property_mirror.isUndefined(), 'property ' + p + ' not found in scope');
131 if (typeof(content[p]) === 'function') {
132 assertTrue(property_mirror.value().isFunction());
133 } else {
134 assertEquals(content[p], property_mirror.value().value(), 'property ' + p + ' has unexpected value');
135 }
136 count++;
137 }
Steve Block6ded16b2010-05-10 14:33:55 +0100138
Steve Blocka7e24c12009-10-30 11:49:00 +0000139 // 'arguments' and might be exposed in the local and closure scope. Just
140 // ignore this.
141 var scope_size = scope.scopeObject().properties().length;
142 if (!scope.scopeObject().property('arguments').isUndefined()) {
143 scope_size--;
144 }
145 // Also ignore synthetic variable from catch block.
146 if (!scope.scopeObject().property('.catch-var').isUndefined()) {
147 scope_size--;
148 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100149 // Skip property with empty name.
150 if (!scope.scopeObject().property('').isUndefined()) {
151 scope_size--;
152 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000153
154 if (count != scope_size) {
155 print('Names found in scope:');
156 var names = scope.scopeObject().propertyNames();
157 for (var i = 0; i < names.length; i++) {
158 print(names[i]);
159 }
160 }
161 assertEquals(count, scope_size);
162
163 // Get the debug command processor.
Steve Block3ce2e202009-11-05 08:53:23 +0000164 var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
Steve Block6ded16b2010-05-10 14:33:55 +0100165
Steve Blocka7e24c12009-10-30 11:49:00 +0000166 // Send a scope request for information on a single scope and check the
167 // result.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100168 var request_json = '{"seq":0,"type":"request","command":"scope","arguments":{"number":';
Steve Blocka7e24c12009-10-30 11:49:00 +0000169 request_json += scope.scopeIndex();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100170 request_json += '}}';
Steve Blocka7e24c12009-10-30 11:49:00 +0000171 var response_json = dcp.processDebugJSONRequest(request_json);
172 var response = JSON.parse(response_json);
173 assertEquals(scope.scopeType(), response.body.type);
174 assertEquals(number, response.body.index);
175 if (scope.scopeType() == debug.ScopeType.Local ||
176 scope.scopeType() == debug.ScopeType.Closure) {
177 assertTrue(response.body.object.ref < 0);
178 } else {
179 assertTrue(response.body.object.ref >= 0);
180 }
181 var found = false;
182 for (var i = 0; i < response.refs.length && !found; i++) {
183 found = response.refs[i].handle == response.body.object.ref;
184 }
185 assertTrue(found, "Scope object " + response.body.object.ref + " not found");
186}
187
188
189// Simple empty local scope.
190BeginTest("Local 1");
191
192function local_1() {
193 debugger;
194}
195
196listener_delegate = function(exec_state) {
197 CheckScopeChain([debug.ScopeType.Local,
198 debug.ScopeType.Global], exec_state);
199 CheckScopeContent({}, 0, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100200};
201local_1();
Steve Blocka7e24c12009-10-30 11:49:00 +0000202EndTest();
203
204
205// Local scope with a parameter.
206BeginTest("Local 2");
207
208function local_2(a) {
209 debugger;
210}
211
212listener_delegate = function(exec_state) {
213 CheckScopeChain([debug.ScopeType.Local,
214 debug.ScopeType.Global], exec_state);
215 CheckScopeContent({a:1}, 0, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100216};
217local_2(1);
Steve Blocka7e24c12009-10-30 11:49:00 +0000218EndTest();
219
220
221// Local scope with a parameter and a local variable.
222BeginTest("Local 3");
223
224function local_3(a) {
225 var x = 3;
226 debugger;
227}
228
229listener_delegate = function(exec_state) {
230 CheckScopeChain([debug.ScopeType.Local,
231 debug.ScopeType.Global], exec_state);
232 CheckScopeContent({a:1,x:3}, 0, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100233};
234local_3(1);
Steve Blocka7e24c12009-10-30 11:49:00 +0000235EndTest();
236
237
238// Local scope with parameters and local variables.
239BeginTest("Local 4");
240
241function local_4(a, b) {
242 var x = 3;
243 var y = 4;
244 debugger;
245}
246
247listener_delegate = function(exec_state) {
248 CheckScopeChain([debug.ScopeType.Local,
249 debug.ScopeType.Global], exec_state);
250 CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100251};
252local_4(1, 2);
Steve Blocka7e24c12009-10-30 11:49:00 +0000253EndTest();
254
255
256// Empty local scope with use of eval.
257BeginTest("Local 5");
258
259function local_5() {
260 eval('');
261 debugger;
262}
263
264listener_delegate = function(exec_state) {
265 CheckScopeChain([debug.ScopeType.Local,
266 debug.ScopeType.Global], exec_state);
267 CheckScopeContent({}, 0, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100268};
269local_5();
Steve Blocka7e24c12009-10-30 11:49:00 +0000270EndTest();
271
272
273// Local introducing local variable using eval.
274BeginTest("Local 6");
275
276function local_6() {
277 eval('var i = 5');
278 debugger;
279}
280
281listener_delegate = function(exec_state) {
282 CheckScopeChain([debug.ScopeType.Local,
283 debug.ScopeType.Global], exec_state);
284 CheckScopeContent({i:5}, 0, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100285};
286local_6();
Steve Blocka7e24c12009-10-30 11:49:00 +0000287EndTest();
288
289
290// Local scope with parameters, local variables and local variable introduced
291// using eval.
292BeginTest("Local 7");
293
294function local_7(a, b) {
295 var x = 3;
296 var y = 4;
297 eval('var i = 5');
298 eval('var j = 6');
299 debugger;
300}
301
302listener_delegate = function(exec_state) {
303 CheckScopeChain([debug.ScopeType.Local,
304 debug.ScopeType.Global], exec_state);
305 CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 0, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100306};
307local_7(1, 2);
Steve Blocka7e24c12009-10-30 11:49:00 +0000308EndTest();
309
310
311// Single empty with block.
312BeginTest("With 1");
313
314function with_1() {
315 with({}) {
316 debugger;
317 }
318}
319
320listener_delegate = function(exec_state) {
321 CheckScopeChain([debug.ScopeType.With,
322 debug.ScopeType.Local,
323 debug.ScopeType.Global], exec_state);
324 CheckScopeContent({}, 0, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100325};
326with_1();
Steve Blocka7e24c12009-10-30 11:49:00 +0000327EndTest();
328
329
330// Nested empty with blocks.
331BeginTest("With 2");
332
333function with_2() {
334 with({}) {
335 with({}) {
336 debugger;
337 }
338 }
339}
340
341listener_delegate = function(exec_state) {
342 CheckScopeChain([debug.ScopeType.With,
343 debug.ScopeType.With,
344 debug.ScopeType.Local,
345 debug.ScopeType.Global], exec_state);
346 CheckScopeContent({}, 0, exec_state);
347 CheckScopeContent({}, 1, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100348};
349with_2();
Steve Blocka7e24c12009-10-30 11:49:00 +0000350EndTest();
351
352
353// With block using an in-place object literal.
354BeginTest("With 3");
355
356function with_3() {
357 with({a:1,b:2}) {
358 debugger;
359 }
360}
361
362listener_delegate = function(exec_state) {
363 CheckScopeChain([debug.ScopeType.With,
364 debug.ScopeType.Local,
365 debug.ScopeType.Global], exec_state);
366 CheckScopeContent({a:1,b:2}, 0, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100367};
368with_3();
Steve Blocka7e24c12009-10-30 11:49:00 +0000369EndTest();
370
371
372// Nested with blocks using in-place object literals.
373BeginTest("With 4");
374
375function with_4() {
376 with({a:1,b:2}) {
377 with({a:2,b:1}) {
378 debugger;
379 }
380 }
381}
382
383listener_delegate = function(exec_state) {
384 CheckScopeChain([debug.ScopeType.With,
385 debug.ScopeType.With,
386 debug.ScopeType.Local,
387 debug.ScopeType.Global], exec_state);
388 CheckScopeContent({a:2,b:1}, 0, exec_state);
389 CheckScopeContent({a:1,b:2}, 1, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100390};
391with_4();
Steve Blocka7e24c12009-10-30 11:49:00 +0000392EndTest();
393
394
395// Nested with blocks using existing object.
396BeginTest("With 5");
397
398var with_object = {c:3,d:4};
399function with_5() {
400 with(with_object) {
401 with(with_object) {
402 debugger;
403 }
404 }
405}
406
407listener_delegate = function(exec_state) {
408 CheckScopeChain([debug.ScopeType.With,
409 debug.ScopeType.With,
410 debug.ScopeType.Local,
411 debug.ScopeType.Global], exec_state);
412 CheckScopeContent(with_object, 0, exec_state);
413 CheckScopeContent(with_object, 1, exec_state);
414 assertEquals(exec_state.frame().scope(0).scopeObject(), exec_state.frame().scope(1).scopeObject());
415 assertEquals(with_object, exec_state.frame().scope(1).scopeObject().value());
Ben Murdoch8b112d22011-06-08 16:22:53 +0100416};
417with_5();
Steve Blocka7e24c12009-10-30 11:49:00 +0000418EndTest();
419
420
421// Simple closure formed by returning an inner function referering the outer
422// functions arguments.
423BeginTest("Closure 1");
424
425function closure_1(a) {
426 function f() {
427 debugger;
428 return a;
429 };
430 return f;
431}
432
433listener_delegate = function(exec_state) {
434 CheckScopeChain([debug.ScopeType.Local,
435 debug.ScopeType.Closure,
436 debug.ScopeType.Global], exec_state);
437 CheckScopeContent({a:1}, 1, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100438};
439closure_1(1)();
Steve Blocka7e24c12009-10-30 11:49:00 +0000440EndTest();
441
442
443// Simple closure formed by returning an inner function referering the outer
444// functions arguments. Due to VM optimizations parts of the actual closure is
445// missing from the debugger information.
446BeginTest("Closure 2");
447
448function closure_2(a, b) {
449 var x = a + 2;
450 var y = b + 2;
451 function f() {
452 debugger;
453 return a + x;
454 };
455 return f;
456}
457
458listener_delegate = function(exec_state) {
459 CheckScopeChain([debug.ScopeType.Local,
460 debug.ScopeType.Closure,
461 debug.ScopeType.Global], exec_state);
462 CheckScopeContent({a:1,x:3}, 1, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100463};
464closure_2(1, 2)();
Steve Blocka7e24c12009-10-30 11:49:00 +0000465EndTest();
466
467
468// Simple closure formed by returning an inner function referering the outer
469// functions arguments. Using all arguments and locals from the outer function
470// in the inner function makes these part of the debugger information on the
471// closure.
472BeginTest("Closure 3");
473
474function closure_3(a, b) {
475 var x = a + 2;
476 var y = b + 2;
477 function f() {
478 debugger;
479 return a + b + x + y;
480 };
481 return f;
482}
483
484listener_delegate = function(exec_state) {
485 CheckScopeChain([debug.ScopeType.Local,
486 debug.ScopeType.Closure,
487 debug.ScopeType.Global], exec_state);
488 CheckScopeContent({a:1,b:2,x:3,y:4}, 1, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100489};
490closure_3(1, 2)();
Steve Blocka7e24c12009-10-30 11:49:00 +0000491EndTest();
492
493
494
495// Simple closure formed by returning an inner function referering the outer
496// functions arguments. Using all arguments and locals from the outer function
497// in the inner function makes these part of the debugger information on the
498// closure. Use the inner function as well...
499BeginTest("Closure 4");
500
501function closure_4(a, b) {
502 var x = a + 2;
503 var y = b + 2;
504 function f() {
505 debugger;
506 if (f) {
507 return a + b + x + y;
508 }
509 };
510 return f;
511}
512
513listener_delegate = function(exec_state) {
514 CheckScopeChain([debug.ScopeType.Local,
515 debug.ScopeType.Closure,
516 debug.ScopeType.Global], exec_state);
517 CheckScopeContent({a:1,b:2,x:3,y:4,f:function(){}}, 1, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100518};
519closure_4(1, 2)();
Steve Blocka7e24c12009-10-30 11:49:00 +0000520EndTest();
521
522
523
524// Simple closure formed by returning an inner function referering the outer
525// functions arguments. In the presence of eval all arguments and locals
526// (including the inner function itself) from the outer function becomes part of
527// the debugger infformation on the closure.
528BeginTest("Closure 5");
529
530function closure_5(a, b) {
531 var x = 3;
532 var y = 4;
533 function f() {
534 eval('');
535 debugger;
536 return 1;
537 };
538 return f;
539}
540
541listener_delegate = function(exec_state) {
542 CheckScopeChain([debug.ScopeType.Local,
543 debug.ScopeType.Closure,
544 debug.ScopeType.Global], exec_state);
545 CheckScopeContent({a:1,b:2,x:3,y:4,f:function(){}}, 1, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100546};
547closure_5(1, 2)();
Steve Blocka7e24c12009-10-30 11:49:00 +0000548EndTest();
549
550
551// Two closures. Due to optimizations only the parts actually used are provided
552// through the debugger information.
553BeginTest("Closure 6");
554function closure_6(a, b) {
555 function f(a, b) {
556 var x = 3;
557 var y = 4;
558 return function() {
559 var x = 3;
560 var y = 4;
561 debugger;
562 some_global = a;
563 return f;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100564 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000565 }
566 return f(a, b);
567}
568
569listener_delegate = function(exec_state) {
570 CheckScopeChain([debug.ScopeType.Local,
571 debug.ScopeType.Closure,
572 debug.ScopeType.Closure,
573 debug.ScopeType.Global], exec_state);
574 CheckScopeContent({a:1}, 1, exec_state);
575 CheckScopeContent({f:function(){}}, 2, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100576};
577closure_6(1, 2)();
Steve Blocka7e24c12009-10-30 11:49:00 +0000578EndTest();
579
580
581// Two closures. In the presence of eval all information is provided as the
582// compiler cannot determine which parts are used.
583BeginTest("Closure 7");
584function closure_7(a, b) {
585 var x = 3;
586 var y = 4;
587 eval('var i = 5');
588 eval('var j = 6');
589 function f(a, b) {
590 var x = 3;
591 var y = 4;
592 eval('var i = 5');
593 eval('var j = 6');
594 return function() {
595 debugger;
596 some_global = a;
597 return f;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100598 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000599 }
600 return f(a, b);
601}
602
603listener_delegate = function(exec_state) {
604 CheckScopeChain([debug.ScopeType.Local,
605 debug.ScopeType.Closure,
606 debug.ScopeType.Closure,
607 debug.ScopeType.Global], exec_state);
608 CheckScopeContent({}, 0, exec_state);
609 CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 1, exec_state);
610 CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6,f:function(){}}, 2, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100611};
612closure_7(1, 2)();
613EndTest();
614
615
616// Closure that may be optimized out.
617BeginTest("Closure 8");
618function closure_8() {
619 (function inner(x) {
620 debugger;
621 })(2);
Steve Blocka7e24c12009-10-30 11:49:00 +0000622}
Ben Murdoch8b112d22011-06-08 16:22:53 +0100623
624listener_delegate = function(exec_state) {
625 CheckScopeChain([debug.ScopeType.Local,
626 debug.ScopeType.Global], exec_state);
627 CheckScopeContent({x: 2}, 0, exec_state);
628};
629closure_8();
630EndTest();
631
632
633BeginTest("Closure 9");
634function closure_9() {
635 eval("var y = 1;");
636 eval("var z = 1;");
637 (function inner(x) {
638 y++;
639 z++;
640 debugger;
641 })(2);
642}
643
644listener_delegate = function(exec_state) {
645 CheckScopeChain([debug.ScopeType.Local,
646 debug.ScopeType.Closure,
647 debug.ScopeType.Global], exec_state);
648};
649closure_9();
Steve Blocka7e24c12009-10-30 11:49:00 +0000650EndTest();
651
652
653// Test a mixture of scopes.
654BeginTest("The full monty");
655function the_full_monty(a, b) {
656 var x = 3;
657 var y = 4;
658 eval('var i = 5');
659 eval('var j = 6');
660 function f(a, b) {
661 var x = 9;
662 var y = 10;
663 eval('var i = 11');
664 eval('var j = 12');
665 with ({j:13}){
666 return function() {
667 var x = 14;
Steve Block6ded16b2010-05-10 14:33:55 +0100668 with ({a:15}) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000669 with ({b:16}) {
670 debugger;
671 some_global = a;
672 return f;
673 }
674 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100675 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000676 }
677 }
678 return f(a, b);
679}
680
681listener_delegate = function(exec_state) {
682 CheckScopeChain([debug.ScopeType.With,
683 debug.ScopeType.With,
684 debug.ScopeType.Local,
685 debug.ScopeType.With,
686 debug.ScopeType.Closure,
687 debug.ScopeType.Closure,
688 debug.ScopeType.Global], exec_state);
689 CheckScopeContent({b:16}, 0, exec_state);
690 CheckScopeContent({a:15}, 1, exec_state);
691 CheckScopeContent({x:14}, 2, exec_state);
692 CheckScopeContent({j:13}, 3, exec_state);
693 CheckScopeContent({a:1,b:2,x:9,y:10,i:11,j:12}, 4, exec_state);
694 CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6,f:function(){}}, 5, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100695};
696the_full_monty(1, 2)();
Steve Blocka7e24c12009-10-30 11:49:00 +0000697EndTest();
698
Ben Murdoch8b112d22011-06-08 16:22:53 +0100699
700BeginTest("Closure inside With 1");
701function closure_in_with_1() {
702 with({x:1}) {
703 (function inner(x) {
704 debugger;
705 })(2);
706 }
707}
708
709listener_delegate = function(exec_state) {
710 CheckScopeChain([debug.ScopeType.Local,
711 debug.ScopeType.With,
712 debug.ScopeType.Closure,
713 debug.ScopeType.Global], exec_state);
714 CheckScopeContent({x: 2}, 0, exec_state);
715};
716closure_in_with_1();
717EndTest();
718
719
720BeginTest("Closure inside With 2");
721function closure_in_with_2() {
722 with({x:1}) {
723 (function inner(x) {
724 with({x:3}) {
725 debugger;
726 }
727 })(2);
728 }
729}
730
731listener_delegate = function(exec_state) {
732 CheckScopeChain([debug.ScopeType.With,
733 debug.ScopeType.Local,
734 debug.ScopeType.With,
735 debug.ScopeType.Closure,
736 debug.ScopeType.Global], exec_state);
737 CheckScopeContent({x: 3}, 0, exec_state);
738 CheckScopeContent({x: 2}, 1, exec_state);
739 CheckScopeContent({x: 1}, 2, exec_state);
740};
741closure_in_with_2();
742EndTest();
743
744
745BeginTest("Closure inside With 3");
746function createClosure(a) {
747 var b = a + 1;
748 return function closure() {
749 var c = b;
750 (function inner(x) {
751 with({x:c}) {
752 debugger;
753 }
754 })(2);
755 };
756}
757
758function closure_in_with_3() {
759 var f = createClosure(0);
760 f();
761}
762
763listener_delegate = function(exec_state) {
764 CheckScopeChain([debug.ScopeType.With,
765 debug.ScopeType.Local,
766 debug.ScopeType.Closure,
767 debug.ScopeType.Closure,
768 debug.ScopeType.Global], exec_state);
769}
770closure_in_with_3();
771EndTest();
772
773
Steve Blocka7e24c12009-10-30 11:49:00 +0000774// Test global scope.
775BeginTest("Global");
776listener_delegate = function(exec_state) {
777 CheckScopeChain([debug.ScopeType.Global], exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100778};
Steve Blocka7e24c12009-10-30 11:49:00 +0000779debugger;
780EndTest();
781
782
783BeginTest("Catch block 1");
784function catch_block_1() {
785 try {
786 throw 'Exception';
787 } catch (e) {
788 debugger;
789 }
790};
791
792
793listener_delegate = function(exec_state) {
794 CheckScopeChain([debug.ScopeType.Catch,
795 debug.ScopeType.Local,
796 debug.ScopeType.Global], exec_state);
797 CheckScopeContent({e:'Exception'}, 0, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100798};
799catch_block_1();
Steve Blocka7e24c12009-10-30 11:49:00 +0000800EndTest();
801
802
803BeginTest("Catch block 2");
804function catch_block_2() {
805 try {
806 throw 'Exception';
807 } catch (e) {
808 with({n:10}) {
809 debugger;
810 }
811 }
812};
813
814
815listener_delegate = function(exec_state) {
816 CheckScopeChain([debug.ScopeType.With,
817 debug.ScopeType.Catch,
818 debug.ScopeType.Local,
819 debug.ScopeType.Global], exec_state);
820 CheckScopeContent({n:10}, 0, exec_state);
821 CheckScopeContent({e:'Exception'}, 1, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100822};
823catch_block_2();
Steve Blocka7e24c12009-10-30 11:49:00 +0000824EndTest();
825
826
827BeginTest("Catch block 3");
Steve Block6ded16b2010-05-10 14:33:55 +0100828function catch_block_3() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000829 // Do eval to dynamically declare a local variable so that the context's
830 // extension slot is initialized with JSContextExtensionObject.
831 eval("var y = 78;");
832 try {
833 throw 'Exception';
834 } catch (e) {
835 debugger;
836 }
837};
838
839
840listener_delegate = function(exec_state) {
841 CheckScopeChain([debug.ScopeType.Catch,
842 debug.ScopeType.Local,
843 debug.ScopeType.Global], exec_state);
844 CheckScopeContent({e:'Exception'}, 0, exec_state);
845 CheckScopeContent({y:78}, 1, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100846};
847catch_block_3();
Steve Blocka7e24c12009-10-30 11:49:00 +0000848EndTest();
849
850
851BeginTest("Catch block 4");
Steve Block6ded16b2010-05-10 14:33:55 +0100852function catch_block_4() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000853 // Do eval to dynamically declare a local variable so that the context's
854 // extension slot is initialized with JSContextExtensionObject.
855 eval("var y = 98;");
856 try {
857 throw 'Exception';
858 } catch (e) {
859 with({n:10}) {
860 debugger;
861 }
862 }
863};
864
865listener_delegate = function(exec_state) {
866 CheckScopeChain([debug.ScopeType.With,
867 debug.ScopeType.Catch,
868 debug.ScopeType.Local,
869 debug.ScopeType.Global], exec_state);
870 CheckScopeContent({n:10}, 0, exec_state);
871 CheckScopeContent({e:'Exception'}, 1, exec_state);
872 CheckScopeContent({y:98}, 2, exec_state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100873};
874catch_block_4();
Steve Blocka7e24c12009-10-30 11:49:00 +0000875EndTest();
876
877
Ben Murdoch8b112d22011-06-08 16:22:53 +0100878assertEquals(begin_test_count, break_count,
879 'one or more tests did not enter the debugger');
880assertEquals(begin_test_count, end_test_count,
881 'one or more tests did not have its result checked');