1// Copyright 2011 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 --allow-natives-syntax
29// The functions used for testing backtraces. They are at the top to make the
30// testing of source line/column easier.
31
32// Get the Debug object exposed from the debug context global object.
33var Debug = debug.Debug;
34
35var test_name;
36var listener_delegate;
37var listener_called;
38var exception;
39var begin_test_count = 0;
40var end_test_count = 0;
41var break_count = 0;
42
43
44// Debug event listener which delegates.
45function listener(event, exec_state, event_data, data) {
46  try {
47    if (event == Debug.DebugEvent.Break) {
48      break_count++;
49      listener_called = true;
50      listener_delegate(exec_state);
51    }
52  } catch (e) {
53    exception = e;
54  }
55}
56
57// Add the debug event listener.
58Debug.setListener(listener);
59
60
61// Initialize for a new test.
62function BeginTest(name) {
63  test_name = name;
64  listener_delegate = null;
65  listener_called = false;
66  exception = null;
67  begin_test_count++;
68}
69
70
71// Check result of a test.
72function EndTest() {
73  assertTrue(listener_called, "listerner not called for " + test_name);
74  assertNull(exception, test_name);
75  end_test_count++;
76}
77
78
79// Check that the scope chain contains the expected types of scopes.
80function CheckScopeChain(scopes, exec_state) {
81  assertEquals(scopes.length, exec_state.frame().scopeCount());
82  for (var i = 0; i < scopes.length; i++) {
83    var scope = exec_state.frame().scope(i);
84    assertTrue(scope.isScope());
85    assertEquals(scopes[i], scope.scopeType());
86
87    // Check the global object when hitting the global scope.
88    if (scopes[i] == debug.ScopeType.Global) {
89      // Objects don't have same class (one is "global", other is "Object",
90      // so just check the properties directly.
91      assertPropertiesEqual(this, scope.scopeObject().value());
92    }
93  }
94
95  // Get the debug command processor.
96  var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
97
98  // Send a scopes request and check the result.
99  var json;
100  var request_json = '{"seq":0,"type":"request","command":"scopes"}';
101  var response_json = dcp.processDebugJSONRequest(request_json);
102  var response = JSON.parse(response_json);
103  assertEquals(scopes.length, response.body.scopes.length);
104  for (var i = 0; i < scopes.length; i++) {
105    assertEquals(i, response.body.scopes[i].index);
106    assertEquals(scopes[i], response.body.scopes[i].type);
107    if (scopes[i] == debug.ScopeType.Local ||
108        scopes[i] == debug.ScopeType.Closure) {
109      assertTrue(response.body.scopes[i].object.ref < 0);
110    } else {
111      assertTrue(response.body.scopes[i].object.ref >= 0);
112    }
113    var found = false;
114    for (var j = 0; j < response.refs.length && !found; j++) {
115      found = response.refs[j].handle == response.body.scopes[i].object.ref;
116    }
117    assertTrue(found, "Scope object " + response.body.scopes[i].object.ref + " not found");
118  }
119}
120
121
122// Check that the content of the scope is as expected. For functions just check
123// that there is a function.
124function CheckScopeContent(content, number, exec_state) {
125  var scope = exec_state.frame().scope(number);
126  var count = 0;
127  for (var p in content) {
128    var property_mirror = scope.scopeObject().property(p);
129    assertFalse(property_mirror.isUndefined(), 'property ' + p + ' not found in scope');
130    if (typeof(content[p]) === 'function') {
131      assertTrue(property_mirror.value().isFunction());
132    } else {
133      assertEquals(content[p], property_mirror.value().value(), 'property ' + p + ' has unexpected value');
134    }
135    count++;
136  }
137
138  // 'arguments' and might be exposed in the local and closure scope. Just
139  // ignore this.
140  var scope_size = scope.scopeObject().properties().length;
141  if (!scope.scopeObject().property('arguments').isUndefined()) {
142    scope_size--;
143  }
144  // Also ignore synthetic variable from catch block.
145  if (!scope.scopeObject().property('.catch-var').isUndefined()) {
146    scope_size--;
147  }
148  // Skip property with empty name.
149  if (!scope.scopeObject().property('').isUndefined()) {
150    scope_size--;
151  }
152
153  if (count != scope_size) {
154    print('Names found in scope:');
155    var names = scope.scopeObject().propertyNames();
156    for (var i = 0; i < names.length; i++) {
157      print(names[i]);
158    }
159  }
160  assertEquals(count, scope_size);
161
162  // Get the debug command processor.
163  var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
164
165  // Send a scope request for information on a single scope and check the
166  // result.
167  var request_json = '{"seq":0,"type":"request","command":"scope","arguments":{"number":';
168  request_json += scope.scopeIndex();
169  request_json += '}}';
170  var response_json = dcp.processDebugJSONRequest(request_json);
171  var response = JSON.parse(response_json);
172  assertEquals(scope.scopeType(), response.body.type);
173  assertEquals(number, response.body.index);
174  if (scope.scopeType() == debug.ScopeType.Local ||
175      scope.scopeType() == debug.ScopeType.Closure) {
176    assertTrue(response.body.object.ref < 0);
177  } else {
178    assertTrue(response.body.object.ref >= 0);
179  }
180  var found = false;
181  for (var i = 0; i < response.refs.length && !found; i++) {
182    found = response.refs[i].handle == response.body.object.ref;
183  }
184  assertTrue(found, "Scope object " + response.body.object.ref + " not found");
185}
186
187
188// Simple empty local scope.
189BeginTest("Local 1");
190
191function local_1() {
192  debugger;
193}
194
195listener_delegate = function(exec_state) {
196  CheckScopeChain([debug.ScopeType.Local,
197                   debug.ScopeType.Global], exec_state);
198  CheckScopeContent({}, 0, exec_state);
199};
200local_1();
201EndTest();
202
203
204// Local scope with a parameter.
205BeginTest("Local 2");
206
207function local_2(a) {
208  debugger;
209}
210
211listener_delegate = function(exec_state) {
212  CheckScopeChain([debug.ScopeType.Local,
213                   debug.ScopeType.Global], exec_state);
214  CheckScopeContent({a:1}, 0, exec_state);
215};
216local_2(1);
217EndTest();
218
219
220// Local scope with a parameter and a local variable.
221BeginTest("Local 3");
222
223function local_3(a) {
224  var x = 3;
225  debugger;
226}
227
228listener_delegate = function(exec_state) {
229  CheckScopeChain([debug.ScopeType.Local,
230                   debug.ScopeType.Global], exec_state);
231  CheckScopeContent({a:1,x:3}, 0, exec_state);
232};
233local_3(1);
234EndTest();
235
236
237// Local scope with parameters and local variables.
238BeginTest("Local 4");
239
240function local_4(a, b) {
241  var x = 3;
242  var y = 4;
243  debugger;
244}
245
246listener_delegate = function(exec_state) {
247  CheckScopeChain([debug.ScopeType.Local,
248                   debug.ScopeType.Global], exec_state);
249  CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state);
250};
251local_4(1, 2);
252EndTest();
253
254
255// Empty local scope with use of eval.
256BeginTest("Local 5");
257
258function local_5() {
259  eval('');
260  debugger;
261}
262
263listener_delegate = function(exec_state) {
264  CheckScopeChain([debug.ScopeType.Local,
265                   debug.ScopeType.Global], exec_state);
266  CheckScopeContent({}, 0, exec_state);
267};
268local_5();
269EndTest();
270
271
272// Local introducing local variable using eval.
273BeginTest("Local 6");
274
275function local_6() {
276  eval('var i = 5');
277  debugger;
278}
279
280listener_delegate = function(exec_state) {
281  CheckScopeChain([debug.ScopeType.Local,
282                   debug.ScopeType.Global], exec_state);
283  CheckScopeContent({i:5}, 0, exec_state);
284};
285local_6();
286EndTest();
287
288
289// Local scope with parameters, local variables and local variable introduced
290// using eval.
291BeginTest("Local 7");
292
293function local_7(a, b) {
294  var x = 3;
295  var y = 4;
296  eval('var i = 5');
297  eval('var j = 6');
298  debugger;
299}
300
301listener_delegate = function(exec_state) {
302  CheckScopeChain([debug.ScopeType.Local,
303                   debug.ScopeType.Global], exec_state);
304  CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 0, exec_state);
305};
306local_7(1, 2);
307EndTest();
308
309
310// Single empty with block.
311BeginTest("With 1");
312
313function with_1() {
314  with({}) {
315    debugger;
316  }
317}
318
319listener_delegate = function(exec_state) {
320  CheckScopeChain([debug.ScopeType.With,
321                   debug.ScopeType.Local,
322                   debug.ScopeType.Global], exec_state);
323  CheckScopeContent({}, 0, exec_state);
324};
325with_1();
326EndTest();
327
328
329// Nested empty with blocks.
330BeginTest("With 2");
331
332function with_2() {
333  with({}) {
334    with({}) {
335      debugger;
336    }
337  }
338}
339
340listener_delegate = function(exec_state) {
341  CheckScopeChain([debug.ScopeType.With,
342                   debug.ScopeType.With,
343                   debug.ScopeType.Local,
344                   debug.ScopeType.Global], exec_state);
345  CheckScopeContent({}, 0, exec_state);
346  CheckScopeContent({}, 1, exec_state);
347};
348with_2();
349EndTest();
350
351
352// With block using an in-place object literal.
353BeginTest("With 3");
354
355function with_3() {
356  with({a:1,b:2}) {
357    debugger;
358  }
359}
360
361listener_delegate = function(exec_state) {
362  CheckScopeChain([debug.ScopeType.With,
363                   debug.ScopeType.Local,
364                   debug.ScopeType.Global], exec_state);
365  CheckScopeContent({a:1,b:2}, 0, exec_state);
366};
367with_3();
368EndTest();
369
370
371// Nested with blocks using in-place object literals.
372BeginTest("With 4");
373
374function with_4() {
375  with({a:1,b:2}) {
376    with({a:2,b:1}) {
377      debugger;
378    }
379  }
380}
381
382listener_delegate = function(exec_state) {
383  CheckScopeChain([debug.ScopeType.With,
384                   debug.ScopeType.With,
385                   debug.ScopeType.Local,
386                   debug.ScopeType.Global], exec_state);
387  CheckScopeContent({a:2,b:1}, 0, exec_state);
388  CheckScopeContent({a:1,b:2}, 1, exec_state);
389};
390with_4();
391EndTest();
392
393
394// Nested with blocks using existing object.
395BeginTest("With 5");
396
397var with_object = {c:3,d:4};
398function with_5() {
399  with(with_object) {
400    with(with_object) {
401      debugger;
402    }
403  }
404}
405
406listener_delegate = function(exec_state) {
407  CheckScopeChain([debug.ScopeType.With,
408                   debug.ScopeType.With,
409                   debug.ScopeType.Local,
410                   debug.ScopeType.Global], exec_state);
411  CheckScopeContent(with_object, 0, exec_state);
412  CheckScopeContent(with_object, 1, exec_state);
413  assertEquals(exec_state.frame().scope(0).scopeObject(), exec_state.frame().scope(1).scopeObject());
414  assertEquals(with_object, exec_state.frame().scope(1).scopeObject().value());
415};
416with_5();
417EndTest();
418
419
420// Nested with blocks using existing object in global code.
421BeginTest("With 6");
422listener_delegate = function(exec_state) {
423  CheckScopeChain([debug.ScopeType.With,
424                   debug.ScopeType.With,
425                   debug.ScopeType.Global], exec_state);
426  CheckScopeContent(with_object, 0, exec_state);
427  CheckScopeContent(with_object, 1, exec_state);
428  assertEquals(exec_state.frame().scope(0).scopeObject(), exec_state.frame().scope(1).scopeObject());
429  assertEquals(with_object, exec_state.frame().scope(1).scopeObject().value());
430};
431
432var with_object = {c:3,d:4};
433with(with_object) {
434  with(with_object) {
435    debugger;
436  }
437}
438EndTest();
439
440
441// With block in function that is marked for optimization while being executed.
442BeginTest("With 7");
443
444function with_7() {
445  with({}) {
446    %OptimizeFunctionOnNextCall(with_7);
447    debugger;
448  }
449}
450
451listener_delegate = function(exec_state) {
452  CheckScopeChain([debug.ScopeType.With,
453                   debug.ScopeType.Local,
454                   debug.ScopeType.Global], exec_state);
455  CheckScopeContent({}, 0, exec_state);
456};
457with_7();
458EndTest();
459
460
461// Simple closure formed by returning an inner function referering the outer
462// functions arguments.
463BeginTest("Closure 1");
464
465function closure_1(a) {
466  function f() {
467    debugger;
468    return a;
469  };
470  return f;
471}
472
473listener_delegate = function(exec_state) {
474  CheckScopeChain([debug.ScopeType.Local,
475                   debug.ScopeType.Closure,
476                   debug.ScopeType.Global], exec_state);
477  CheckScopeContent({a:1}, 1, exec_state);
478};
479closure_1(1)();
480EndTest();
481
482
483// Simple closure formed by returning an inner function referering the outer
484// functions arguments. Due to VM optimizations parts of the actual closure is
485// missing from the debugger information.
486BeginTest("Closure 2");
487
488function closure_2(a, b) {
489  var x = a + 2;
490  var y = b + 2;
491  function f() {
492    debugger;
493    return a + x;
494  };
495  return f;
496}
497
498listener_delegate = function(exec_state) {
499  CheckScopeChain([debug.ScopeType.Local,
500                   debug.ScopeType.Closure,
501                   debug.ScopeType.Global], exec_state);
502  CheckScopeContent({a:1,x:3}, 1, exec_state);
503};
504closure_2(1, 2)();
505EndTest();
506
507
508// Simple closure formed by returning an inner function referering the outer
509// functions arguments. Using all arguments and locals from the outer function
510// in the inner function makes these part of the debugger information on the
511// closure.
512BeginTest("Closure 3");
513
514function closure_3(a, b) {
515  var x = a + 2;
516  var y = b + 2;
517  function f() {
518    debugger;
519    return a + b + x + y;
520  };
521  return f;
522}
523
524listener_delegate = function(exec_state) {
525  CheckScopeChain([debug.ScopeType.Local,
526                   debug.ScopeType.Closure,
527                   debug.ScopeType.Global], exec_state);
528  CheckScopeContent({a:1,b:2,x:3,y:4}, 1, exec_state);
529};
530closure_3(1, 2)();
531EndTest();
532
533
534
535// Simple closure formed by returning an inner function referering the outer
536// functions arguments. Using all arguments and locals from the outer function
537// in the inner function makes these part of the debugger information on the
538// closure. Use the inner function as well...
539BeginTest("Closure 4");
540
541function closure_4(a, b) {
542  var x = a + 2;
543  var y = b + 2;
544  function f() {
545    debugger;
546    if (f) {
547      return a + b + x + y;
548    }
549  };
550  return f;
551}
552
553listener_delegate = function(exec_state) {
554  CheckScopeChain([debug.ScopeType.Local,
555                   debug.ScopeType.Closure,
556                   debug.ScopeType.Global], exec_state);
557  CheckScopeContent({a:1,b:2,x:3,y:4,f:function(){}}, 1, exec_state);
558};
559closure_4(1, 2)();
560EndTest();
561
562
563
564// Simple closure formed by returning an inner function referering the outer
565// functions arguments. In the presence of eval all arguments and locals
566// (including the inner function itself) from the outer function becomes part of
567// the debugger infformation on the closure.
568BeginTest("Closure 5");
569
570function closure_5(a, b) {
571  var x = 3;
572  var y = 4;
573  function f() {
574    eval('');
575    debugger;
576    return 1;
577  };
578  return f;
579}
580
581listener_delegate = function(exec_state) {
582  CheckScopeChain([debug.ScopeType.Local,
583                   debug.ScopeType.Closure,
584                   debug.ScopeType.Global], exec_state);
585  CheckScopeContent({a:1,b:2,x:3,y:4,f:function(){}}, 1, exec_state);
586};
587closure_5(1, 2)();
588EndTest();
589
590
591// Two closures. Due to optimizations only the parts actually used are provided
592// through the debugger information.
593BeginTest("Closure 6");
594function closure_6(a, b) {
595  function f(a, b) {
596    var x = 3;
597    var y = 4;
598    return function() {
599      var x = 3;
600      var y = 4;
601      debugger;
602      some_global = a;
603      return f;
604    };
605  }
606  return f(a, b);
607}
608
609listener_delegate = function(exec_state) {
610  CheckScopeChain([debug.ScopeType.Local,
611                   debug.ScopeType.Closure,
612                   debug.ScopeType.Closure,
613                   debug.ScopeType.Global], exec_state);
614  CheckScopeContent({a:1}, 1, exec_state);
615  CheckScopeContent({f:function(){}}, 2, exec_state);
616};
617closure_6(1, 2)();
618EndTest();
619
620
621// Two closures. In the presence of eval all information is provided as the
622// compiler cannot determine which parts are used.
623BeginTest("Closure 7");
624function closure_7(a, b) {
625  var x = 3;
626  var y = 4;
627  eval('var i = 5');
628  eval('var j = 6');
629  function f(a, b) {
630    var x = 3;
631    var y = 4;
632    eval('var i = 5');
633    eval('var j = 6');
634    return function() {
635      debugger;
636      some_global = a;
637      return f;
638    };
639  }
640  return f(a, b);
641}
642
643listener_delegate = function(exec_state) {
644  CheckScopeChain([debug.ScopeType.Local,
645                   debug.ScopeType.Closure,
646                   debug.ScopeType.Closure,
647                   debug.ScopeType.Global], exec_state);
648  CheckScopeContent({}, 0, exec_state);
649  CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 1, exec_state);
650  CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6,f:function(){}}, 2, exec_state);
651};
652closure_7(1, 2)();
653EndTest();
654
655
656// Closure that may be optimized out.
657BeginTest("Closure 8");
658function closure_8() {
659  (function inner(x) {
660    debugger;
661  })(2);
662}
663
664listener_delegate = function(exec_state) {
665  CheckScopeChain([debug.ScopeType.Local,
666                   debug.ScopeType.Global], exec_state);
667  CheckScopeContent({x: 2}, 0, exec_state);
668};
669closure_8();
670EndTest();
671
672
673BeginTest("Closure 9");
674function closure_9() {
675  eval("var y = 1;");
676  eval("var z = 1;");
677  (function inner(x) {
678    y++;
679    z++;
680    debugger;
681  })(2);
682}
683
684listener_delegate = function(exec_state) {
685  CheckScopeChain([debug.ScopeType.Local,
686                   debug.ScopeType.Closure,
687                   debug.ScopeType.Global], exec_state);
688};
689closure_9();
690EndTest();
691
692
693// Test a mixture of scopes.
694BeginTest("The full monty");
695function the_full_monty(a, b) {
696  var x = 3;
697  var y = 4;
698  eval('var i = 5');
699  eval('var j = 6');
700  function f(a, b) {
701    var x = 9;
702    var y = 10;
703    eval('var i = 11');
704    eval('var j = 12');
705    with ({j:13}){
706      return function() {
707        var x = 14;
708        with ({a:15}) {
709          with ({b:16}) {
710            debugger;
711            some_global = a;
712            return f;
713          }
714        }
715      };
716    }
717  }
718  return f(a, b);
719}
720
721listener_delegate = function(exec_state) {
722  CheckScopeChain([debug.ScopeType.With,
723                   debug.ScopeType.With,
724                   debug.ScopeType.Local,
725                   debug.ScopeType.With,
726                   debug.ScopeType.Closure,
727                   debug.ScopeType.Closure,
728                   debug.ScopeType.Global], exec_state);
729  CheckScopeContent({b:16}, 0, exec_state);
730  CheckScopeContent({a:15}, 1, exec_state);
731  CheckScopeContent({x:14}, 2, exec_state);
732  CheckScopeContent({j:13}, 3, exec_state);
733  CheckScopeContent({a:1,b:2,x:9,y:10,i:11,j:12}, 4, exec_state);
734  CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6,f:function(){}}, 5, exec_state);
735};
736the_full_monty(1, 2)();
737EndTest();
738
739
740BeginTest("Closure inside With 1");
741function closure_in_with_1() {
742  with({x:1}) {
743    (function inner(x) {
744      debugger;
745    })(2);
746  }
747}
748
749listener_delegate = function(exec_state) {
750  CheckScopeChain([debug.ScopeType.Local,
751                   debug.ScopeType.With,
752                   debug.ScopeType.Closure,
753                   debug.ScopeType.Global], exec_state);
754  CheckScopeContent({x: 2}, 0, exec_state);
755};
756closure_in_with_1();
757EndTest();
758
759
760BeginTest("Closure inside With 2");
761function closure_in_with_2() {
762  with({x:1}) {
763    (function inner(x) {
764      with({x:3}) {
765        debugger;
766      }
767    })(2);
768  }
769}
770
771listener_delegate = function(exec_state) {
772  CheckScopeChain([debug.ScopeType.With,
773                   debug.ScopeType.Local,
774                   debug.ScopeType.With,
775                   debug.ScopeType.Closure,
776                   debug.ScopeType.Global], exec_state);
777  CheckScopeContent({x: 3}, 0, exec_state);
778  CheckScopeContent({x: 2}, 1, exec_state);
779  CheckScopeContent({x: 1}, 2, exec_state);
780};
781closure_in_with_2();
782EndTest();
783
784
785BeginTest("Closure inside With 3");
786function createClosure(a) {
787   var b = a + 1;
788   return function closure() {
789     var c = b;
790     (function inner(x) {
791       with({x:c}) {
792         debugger;
793       }
794     })(2);
795   };
796}
797
798function closure_in_with_3() {
799  var f = createClosure(0);
800  f();
801}
802
803listener_delegate = function(exec_state) {
804  CheckScopeChain([debug.ScopeType.With,
805                   debug.ScopeType.Local,
806                   debug.ScopeType.Closure,
807                   debug.ScopeType.Closure,
808                   debug.ScopeType.Global], exec_state);
809}
810closure_in_with_3();
811EndTest();
812
813
814BeginTest("Closure inside With 4");
815listener_delegate = function(exec_state) {
816  CheckScopeChain([debug.ScopeType.Local,
817                   debug.ScopeType.With,
818                   debug.ScopeType.Global], exec_state);
819  CheckScopeContent({x: 2}, 0, exec_state);
820  CheckScopeContent({x: 1}, 1, exec_state);
821};
822
823with({x:1}) {
824  (function(x) {
825    debugger;
826  })(2);
827}
828EndTest();
829
830
831// Test global scope.
832BeginTest("Global");
833listener_delegate = function(exec_state) {
834  CheckScopeChain([debug.ScopeType.Global], exec_state);
835};
836debugger;
837EndTest();
838
839
840BeginTest("Catch block 1");
841function catch_block_1() {
842  try {
843    throw 'Exception';
844  } catch (e) {
845    debugger;
846  }
847};
848
849
850listener_delegate = function(exec_state) {
851  CheckScopeChain([debug.ScopeType.Catch,
852                   debug.ScopeType.Local,
853                   debug.ScopeType.Global], exec_state);
854  CheckScopeContent({e:'Exception'}, 0, exec_state);
855};
856catch_block_1();
857EndTest();
858
859
860BeginTest("Catch block 2");
861function catch_block_2() {
862  try {
863    throw 'Exception';
864  } catch (e) {
865    with({n:10}) {
866      debugger;
867    }
868  }
869};
870
871
872listener_delegate = function(exec_state) {
873  CheckScopeChain([debug.ScopeType.With,
874                   debug.ScopeType.Catch,
875                   debug.ScopeType.Local,
876                   debug.ScopeType.Global], exec_state);
877  CheckScopeContent({n:10}, 0, exec_state);
878  CheckScopeContent({e:'Exception'}, 1, exec_state);
879};
880catch_block_2();
881EndTest();
882
883
884BeginTest("Catch block 3");
885function catch_block_3() {
886  // Do eval to dynamically declare a local variable so that the context's
887  // extension slot is initialized with JSContextExtensionObject.
888  eval("var y = 78;");
889  try {
890    throw 'Exception';
891  } catch (e) {
892    debugger;
893  }
894};
895
896
897listener_delegate = function(exec_state) {
898  CheckScopeChain([debug.ScopeType.Catch,
899                   debug.ScopeType.Local,
900                   debug.ScopeType.Global], exec_state);
901  CheckScopeContent({e:'Exception'}, 0, exec_state);
902  CheckScopeContent({y:78}, 1, exec_state);
903};
904catch_block_3();
905EndTest();
906
907
908BeginTest("Catch block 4");
909function catch_block_4() {
910  // Do eval to dynamically declare a local variable so that the context's
911  // extension slot is initialized with JSContextExtensionObject.
912  eval("var y = 98;");
913  try {
914    throw 'Exception';
915  } catch (e) {
916    with({n:10}) {
917      debugger;
918    }
919  }
920};
921
922listener_delegate = function(exec_state) {
923  CheckScopeChain([debug.ScopeType.With,
924                   debug.ScopeType.Catch,
925                   debug.ScopeType.Local,
926                   debug.ScopeType.Global], exec_state);
927  CheckScopeContent({n:10}, 0, exec_state);
928  CheckScopeContent({e:'Exception'}, 1, exec_state);
929  CheckScopeContent({y:98}, 2, exec_state);
930};
931catch_block_4();
932EndTest();
933
934
935// Test catch in global scope.
936BeginTest("Catch block 5");
937listener_delegate = function(exec_state) {
938  CheckScopeChain([debug.ScopeType.Catch,
939                   debug.ScopeType.Global], exec_state);
940  CheckScopeContent({e:'Exception'}, 0, exec_state);
941};
942
943try {
944  throw 'Exception';
945} catch (e) {
946  debugger;
947}
948
949EndTest();
950
951
952// Closure inside catch in global code.
953BeginTest("Catch block 6");
954listener_delegate = function(exec_state) {
955  CheckScopeChain([debug.ScopeType.Local,
956                   debug.ScopeType.Catch,
957                   debug.ScopeType.Global], exec_state);
958  CheckScopeContent({x: 2}, 0, exec_state);
959  CheckScopeContent({e:'Exception'}, 1, exec_state);
960};
961
962try {
963  throw 'Exception';
964} catch (e) {
965  (function(x) {
966    debugger;
967  })(2);
968}
969EndTest();
970
971
972// Catch block in function that is marked for optimization while being executed.
973BeginTest("Catch block 7");
974function catch_block_7() {
975  %OptimizeFunctionOnNextCall(catch_block_7);
976  try {
977    throw 'Exception';
978  } catch (e) {
979    debugger;
980  }
981};
982
983
984listener_delegate = function(exec_state) {
985  CheckScopeChain([debug.ScopeType.Catch,
986                   debug.ScopeType.Local,
987                   debug.ScopeType.Global], exec_state);
988  CheckScopeContent({e:'Exception'}, 0, exec_state);
989};
990catch_block_7();
991EndTest();
992
993
994assertEquals(begin_test_count, break_count,
995             'one or more tests did not enter the debugger');
996assertEquals(begin_test_count, end_test_count,
997             'one or more tests did not have its result checked');
998