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.
34Debug = debug.Debug
35
36var name;
37var 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;
51      listener_delegate(exec_state)
52    }
53  } catch (e) {
54    exception = e;
55  }
56}
57
58// Add the debug event listener.
59Debug.setListener(listener);
60
61
62// Initialize for a noew test.
63function 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);
75  assertNull(exception, test_name)
76  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());
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("unspecified_running_state");
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 + " not 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.
123function 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  // Also ignore synthetic variable from catch block.
144  if (!scope.scopeObject().property('.catch-var').isUndefined()) {
145    scope_size--;
146  }
147  // Skip property with empty name.
148  if (!scope.scopeObject().property('').isUndefined()) {
149    scope_size--;
150  }
151
152  if (count != scope_size) {
153    print('Names found in scope:');
154    var names = scope.scopeObject().propertyNames();
155    for (var i = 0; i < names.length; i++) {
156      print(names[i]);
157    }
158  }
159  assertEquals(count, scope_size);
160
161  // Get the debug command processor.
162  var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
163
164  // Send a scope request for information on a single scope and check the
165  // result.
166  request_json = '{"seq":0,"type":"request","command":"scope","arguments":{"number":'
167  request_json += scope.scopeIndex();
168  request_json += '}}'
169  var response_json = dcp.processDebugJSONRequest(request_json);
170  var response = JSON.parse(response_json);
171  assertEquals(scope.scopeType(), response.body.type);
172  assertEquals(number, response.body.index);
173  if (scope.scopeType() == debug.ScopeType.Local ||
174      scope.scopeType() == debug.ScopeType.Closure) {
175    assertTrue(response.body.object.ref < 0);
176  } else {
177    assertTrue(response.body.object.ref >= 0);
178  }
179  var found = false;
180  for (var i = 0; i < response.refs.length && !found; i++) {
181    found = response.refs[i].handle == response.body.object.ref;
182  }
183  assertTrue(found, "Scope object " + response.body.object.ref + " not found");
184}
185
186
187// Simple empty local scope.
188BeginTest("Local 1");
189
190function local_1() {
191  debugger;
192}
193
194listener_delegate = function(exec_state) {
195  CheckScopeChain([debug.ScopeType.Local,
196                   debug.ScopeType.Global], exec_state);
197  CheckScopeContent({}, 0, exec_state);
198}
199local_1()
200EndTest();
201
202
203// Local scope with a parameter.
204BeginTest("Local 2");
205
206function local_2(a) {
207  debugger;
208}
209
210listener_delegate = function(exec_state) {
211  CheckScopeChain([debug.ScopeType.Local,
212                   debug.ScopeType.Global], exec_state);
213  CheckScopeContent({a:1}, 0, exec_state);
214}
215local_2(1)
216EndTest();
217
218
219// Local scope with a parameter and a local variable.
220BeginTest("Local 3");
221
222function local_3(a) {
223  var x = 3;
224  debugger;
225}
226
227listener_delegate = function(exec_state) {
228  CheckScopeChain([debug.ScopeType.Local,
229                   debug.ScopeType.Global], exec_state);
230  CheckScopeContent({a:1,x:3}, 0, exec_state);
231}
232local_3(1)
233EndTest();
234
235
236// Local scope with parameters and local variables.
237BeginTest("Local 4");
238
239function local_4(a, b) {
240  var x = 3;
241  var y = 4;
242  debugger;
243}
244
245listener_delegate = function(exec_state) {
246  CheckScopeChain([debug.ScopeType.Local,
247                   debug.ScopeType.Global], exec_state);
248  CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state);
249}
250local_4(1, 2)
251EndTest();
252
253
254// Empty local scope with use of eval.
255BeginTest("Local 5");
256
257function local_5() {
258  eval('');
259  debugger;
260}
261
262listener_delegate = function(exec_state) {
263  CheckScopeChain([debug.ScopeType.Local,
264                   debug.ScopeType.Global], exec_state);
265  CheckScopeContent({}, 0, exec_state);
266}
267local_5()
268EndTest();
269
270
271// Local introducing local variable using eval.
272BeginTest("Local 6");
273
274function local_6() {
275  eval('var i = 5');
276  debugger;
277}
278
279listener_delegate = function(exec_state) {
280  CheckScopeChain([debug.ScopeType.Local,
281                   debug.ScopeType.Global], exec_state);
282  CheckScopeContent({i:5}, 0, exec_state);
283}
284local_6()
285EndTest();
286
287
288// Local scope with parameters, local variables and local variable introduced
289// using eval.
290BeginTest("Local 7");
291
292function local_7(a, b) {
293  var x = 3;
294  var y = 4;
295  eval('var i = 5');
296  eval('var j = 6');
297  debugger;
298}
299
300listener_delegate = function(exec_state) {
301  CheckScopeChain([debug.ScopeType.Local,
302                   debug.ScopeType.Global], exec_state);
303  CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 0, exec_state);
304}
305local_7(1, 2)
306EndTest();
307
308
309// Single empty with block.
310BeginTest("With 1");
311
312function with_1() {
313  with({}) {
314    debugger;
315  }
316}
317
318listener_delegate = function(exec_state) {
319  CheckScopeChain([debug.ScopeType.With,
320                   debug.ScopeType.Local,
321                   debug.ScopeType.Global], exec_state);
322  CheckScopeContent({}, 0, exec_state);
323}
324with_1()
325EndTest();
326
327
328// Nested empty with blocks.
329BeginTest("With 2");
330
331function with_2() {
332  with({}) {
333    with({}) {
334      debugger;
335    }
336  }
337}
338
339listener_delegate = function(exec_state) {
340  CheckScopeChain([debug.ScopeType.With,
341                   debug.ScopeType.With,
342                   debug.ScopeType.Local,
343                   debug.ScopeType.Global], exec_state);
344  CheckScopeContent({}, 0, exec_state);
345  CheckScopeContent({}, 1, exec_state);
346}
347with_2()
348EndTest();
349
350
351// With block using an in-place object literal.
352BeginTest("With 3");
353
354function with_3() {
355  with({a:1,b:2}) {
356    debugger;
357  }
358}
359
360listener_delegate = function(exec_state) {
361  CheckScopeChain([debug.ScopeType.With,
362                   debug.ScopeType.Local,
363                   debug.ScopeType.Global], exec_state);
364  CheckScopeContent({a:1,b:2}, 0, exec_state);
365}
366with_3()
367EndTest();
368
369
370// Nested with blocks using in-place object literals.
371BeginTest("With 4");
372
373function with_4() {
374  with({a:1,b:2}) {
375    with({a:2,b:1}) {
376      debugger;
377    }
378  }
379}
380
381listener_delegate = function(exec_state) {
382  CheckScopeChain([debug.ScopeType.With,
383                   debug.ScopeType.With,
384                   debug.ScopeType.Local,
385                   debug.ScopeType.Global], exec_state);
386  CheckScopeContent({a:2,b:1}, 0, exec_state);
387  CheckScopeContent({a:1,b:2}, 1, exec_state);
388}
389with_4()
390EndTest();
391
392
393// Nested with blocks using existing object.
394BeginTest("With 5");
395
396var with_object = {c:3,d:4};
397function with_5() {
398  with(with_object) {
399    with(with_object) {
400      debugger;
401    }
402  }
403}
404
405listener_delegate = function(exec_state) {
406  CheckScopeChain([debug.ScopeType.With,
407                   debug.ScopeType.With,
408                   debug.ScopeType.Local,
409                   debug.ScopeType.Global], exec_state);
410  CheckScopeContent(with_object, 0, exec_state);
411  CheckScopeContent(with_object, 1, exec_state);
412  assertEquals(exec_state.frame().scope(0).scopeObject(), exec_state.frame().scope(1).scopeObject());
413  assertEquals(with_object, exec_state.frame().scope(1).scopeObject().value());
414}
415with_5()
416EndTest();
417
418
419// Simple closure formed by returning an inner function referering the outer
420// functions arguments.
421BeginTest("Closure 1");
422
423function closure_1(a) {
424  function f() {
425    debugger;
426    return a;
427  };
428  return f;
429}
430
431listener_delegate = function(exec_state) {
432  CheckScopeChain([debug.ScopeType.Local,
433                   debug.ScopeType.Closure,
434                   debug.ScopeType.Global], exec_state);
435  CheckScopeContent({a:1}, 1, exec_state);
436}
437closure_1(1)()
438EndTest();
439
440
441// Simple closure formed by returning an inner function referering the outer
442// functions arguments. Due to VM optimizations parts of the actual closure is
443// missing from the debugger information.
444BeginTest("Closure 2");
445
446function closure_2(a, b) {
447  var x = a + 2;
448  var y = b + 2;
449  function f() {
450    debugger;
451    return a + x;
452  };
453  return f;
454}
455
456listener_delegate = function(exec_state) {
457  CheckScopeChain([debug.ScopeType.Local,
458                   debug.ScopeType.Closure,
459                   debug.ScopeType.Global], exec_state);
460  CheckScopeContent({a:1,x:3}, 1, exec_state);
461}
462closure_2(1, 2)()
463EndTest();
464
465
466// Simple closure formed by returning an inner function referering the outer
467// functions arguments. Using all arguments and locals from the outer function
468// in the inner function makes these part of the debugger information on the
469// closure.
470BeginTest("Closure 3");
471
472function closure_3(a, b) {
473  var x = a + 2;
474  var y = b + 2;
475  function f() {
476    debugger;
477    return a + b + x + y;
478  };
479  return f;
480}
481
482listener_delegate = function(exec_state) {
483  CheckScopeChain([debug.ScopeType.Local,
484                   debug.ScopeType.Closure,
485                   debug.ScopeType.Global], exec_state);
486  CheckScopeContent({a:1,b:2,x:3,y:4}, 1, exec_state);
487}
488closure_3(1, 2)()
489EndTest();
490
491
492
493// Simple closure formed by returning an inner function referering the outer
494// functions arguments. Using all arguments and locals from the outer function
495// in the inner function makes these part of the debugger information on the
496// closure. Use the inner function as well...
497BeginTest("Closure 4");
498
499function closure_4(a, b) {
500  var x = a + 2;
501  var y = b + 2;
502  function f() {
503    debugger;
504    if (f) {
505      return a + b + x + y;
506    }
507  };
508  return f;
509}
510
511listener_delegate = function(exec_state) {
512  CheckScopeChain([debug.ScopeType.Local,
513                   debug.ScopeType.Closure,
514                   debug.ScopeType.Global], exec_state);
515  CheckScopeContent({a:1,b:2,x:3,y:4,f:function(){}}, 1, exec_state);
516}
517closure_4(1, 2)()
518EndTest();
519
520
521
522// Simple closure formed by returning an inner function referering the outer
523// functions arguments. In the presence of eval all arguments and locals
524// (including the inner function itself) from the outer function becomes part of
525// the debugger infformation on the closure.
526BeginTest("Closure 5");
527
528function closure_5(a, b) {
529  var x = 3;
530  var y = 4;
531  function f() {
532    eval('');
533    debugger;
534    return 1;
535  };
536  return f;
537}
538
539listener_delegate = function(exec_state) {
540  CheckScopeChain([debug.ScopeType.Local,
541                   debug.ScopeType.Closure,
542                   debug.ScopeType.Global], exec_state);
543  CheckScopeContent({a:1,b:2,x:3,y:4,f:function(){}}, 1, exec_state);
544}
545closure_5(1, 2)()
546EndTest();
547
548
549// Two closures. Due to optimizations only the parts actually used are provided
550// through the debugger information.
551BeginTest("Closure 6");
552function closure_6(a, b) {
553  function f(a, b) {
554    var x = 3;
555    var y = 4;
556    return function() {
557      var x = 3;
558      var y = 4;
559      debugger;
560      some_global = a;
561      return f;
562    }
563  }
564  return f(a, b);
565}
566
567listener_delegate = function(exec_state) {
568  CheckScopeChain([debug.ScopeType.Local,
569                   debug.ScopeType.Closure,
570                   debug.ScopeType.Closure,
571                   debug.ScopeType.Global], exec_state);
572  CheckScopeContent({a:1}, 1, exec_state);
573  CheckScopeContent({f:function(){}}, 2, exec_state);
574}
575closure_6(1, 2)()
576EndTest();
577
578
579// Two closures. In the presence of eval all information is provided as the
580// compiler cannot determine which parts are used.
581BeginTest("Closure 7");
582function closure_7(a, b) {
583  var x = 3;
584  var y = 4;
585  eval('var i = 5');
586  eval('var j = 6');
587  function f(a, b) {
588    var x = 3;
589    var y = 4;
590    eval('var i = 5');
591    eval('var j = 6');
592    return function() {
593      debugger;
594      some_global = a;
595      return f;
596    }
597  }
598  return f(a, b);
599}
600
601listener_delegate = function(exec_state) {
602  CheckScopeChain([debug.ScopeType.Local,
603                   debug.ScopeType.Closure,
604                   debug.ScopeType.Closure,
605                   debug.ScopeType.Global], exec_state);
606  CheckScopeContent({}, 0, exec_state);
607  CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 1, exec_state);
608  CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6,f:function(){}}, 2, exec_state);
609}
610closure_7(1, 2)()
611EndTest();
612
613
614// Closure that may be optimized out.
615BeginTest("Closure 8");
616function closure_8() {
617  (function inner(x) {
618    debugger;
619  })(2);
620}
621
622listener_delegate = function(exec_state) {
623  CheckScopeChain([debug.ScopeType.Local,
624                   debug.ScopeType.Global], exec_state);
625  CheckScopeContent({x: 2}, 0, exec_state);
626}
627closure_8();
628EndTest();
629
630
631BeginTest("Closure 9");
632function closure_9() {
633  eval("var y = 1;");
634  eval("var z = 1;");
635  (function inner(x) {
636    y++;
637    z++;
638    debugger;
639  })(2);
640}
641
642listener_delegate = function(exec_state) {
643  CheckScopeChain([debug.ScopeType.Local,
644                   debug.ScopeType.Closure,
645                   debug.ScopeType.Global], exec_state);
646}
647closure_9();
648EndTest();
649
650
651// Test a mixture of scopes.
652BeginTest("The full monty");
653function the_full_monty(a, b) {
654  var x = 3;
655  var y = 4;
656  eval('var i = 5');
657  eval('var j = 6');
658  function f(a, b) {
659    var x = 9;
660    var y = 10;
661    eval('var i = 11');
662    eval('var j = 12');
663    with ({j:13}){
664      return function() {
665        var x = 14;
666        with ({a:15}) {
667          with ({b:16}) {
668            debugger;
669            some_global = a;
670            return f;
671          }
672        }
673      }
674    }
675  }
676  return f(a, b);
677}
678
679listener_delegate = function(exec_state) {
680  CheckScopeChain([debug.ScopeType.With,
681                   debug.ScopeType.With,
682                   debug.ScopeType.Local,
683                   debug.ScopeType.With,
684                   debug.ScopeType.Closure,
685                   debug.ScopeType.Closure,
686                   debug.ScopeType.Global], exec_state);
687  CheckScopeContent({b:16}, 0, exec_state);
688  CheckScopeContent({a:15}, 1, exec_state);
689  CheckScopeContent({x:14}, 2, exec_state);
690  CheckScopeContent({j:13}, 3, exec_state);
691  CheckScopeContent({a:1,b:2,x:9,y:10,i:11,j:12}, 4, exec_state);
692  CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6,f:function(){}}, 5, exec_state);
693}
694the_full_monty(1, 2)()
695EndTest();
696
697
698BeginTest("Closure inside With 1");
699function closure_in_with_1() {
700  with({x:1}) {
701    (function inner(x) {
702      debugger;
703    })(2);
704  }
705}
706
707listener_delegate = function(exec_state) {
708  CheckScopeChain([debug.ScopeType.Local,
709                   debug.ScopeType.With,
710                   debug.ScopeType.Closure,
711                   debug.ScopeType.Global], exec_state);
712  CheckScopeContent({x: 2}, 0, exec_state);
713}
714closure_in_with_1();
715EndTest();
716
717
718BeginTest("Closure inside With 2");
719function closure_in_with_2() {
720  with({x:1}) {
721    (function inner(x) {
722      with({x:3}) {
723        debugger;
724      }
725    })(2);
726  }
727}
728
729listener_delegate = function(exec_state) {
730  CheckScopeChain([debug.ScopeType.With,
731                   debug.ScopeType.Local,
732                   debug.ScopeType.With,
733                   debug.ScopeType.Closure,
734                   debug.ScopeType.Global], exec_state);
735  CheckScopeContent({x: 3}, 0, exec_state);
736  CheckScopeContent({x: 2}, 1, exec_state);
737  CheckScopeContent({x: 1}, 2, exec_state);
738}
739closure_in_with_2();
740EndTest();
741
742
743BeginTest("Closure inside With 3");
744function createClosure(a) {
745   var b = a + 1;
746   return function closure() {
747     var c = b;
748     (function inner(x) {
749       with({x:c}) {
750         debugger;
751       }
752     })(2);
753   }
754}
755
756function closure_in_with_3() {
757  var f = createClosure(0);
758  f();
759}
760
761listener_delegate = function(exec_state) {
762  CheckScopeChain([debug.ScopeType.With,
763                   debug.ScopeType.Local,
764                   debug.ScopeType.Closure,
765                   debug.ScopeType.Closure,
766                   debug.ScopeType.Global], exec_state);
767}
768closure_in_with_3();
769EndTest();
770
771
772// Test global scope.
773BeginTest("Global");
774listener_delegate = function(exec_state) {
775  CheckScopeChain([debug.ScopeType.Global], exec_state);
776}
777debugger;
778EndTest();
779
780
781BeginTest("Catch block 1");
782function catch_block_1() {
783  try {
784    throw 'Exception';
785  } catch (e) {
786    debugger;
787  }
788};
789
790
791listener_delegate = function(exec_state) {
792  CheckScopeChain([debug.ScopeType.Catch,
793                   debug.ScopeType.Local,
794                   debug.ScopeType.Global], exec_state);
795  CheckScopeContent({e:'Exception'}, 0, exec_state);
796}
797catch_block_1()
798EndTest();
799
800
801BeginTest("Catch block 2");
802function catch_block_2() {
803  try {
804    throw 'Exception';
805  } catch (e) {
806    with({n:10}) {
807      debugger;
808    }
809  }
810};
811
812
813listener_delegate = function(exec_state) {
814  CheckScopeChain([debug.ScopeType.With,
815                   debug.ScopeType.Catch,
816                   debug.ScopeType.Local,
817                   debug.ScopeType.Global], exec_state);
818  CheckScopeContent({n:10}, 0, exec_state);
819  CheckScopeContent({e:'Exception'}, 1, exec_state);
820}
821catch_block_2()
822EndTest();
823
824
825BeginTest("Catch block 3");
826function catch_block_3() {
827  // Do eval to dynamically declare a local variable so that the context's
828  // extension slot is initialized with JSContextExtensionObject.
829  eval("var y = 78;");
830  try {
831    throw 'Exception';
832  } catch (e) {
833    debugger;
834  }
835};
836
837
838listener_delegate = function(exec_state) {
839  CheckScopeChain([debug.ScopeType.Catch,
840                   debug.ScopeType.Local,
841                   debug.ScopeType.Global], exec_state);
842  CheckScopeContent({e:'Exception'}, 0, exec_state);
843  CheckScopeContent({y:78}, 1, exec_state);
844}
845catch_block_3()
846EndTest();
847
848
849BeginTest("Catch block 4");
850function catch_block_4() {
851  // Do eval to dynamically declare a local variable so that the context's
852  // extension slot is initialized with JSContextExtensionObject.
853  eval("var y = 98;");
854  try {
855    throw 'Exception';
856  } catch (e) {
857    with({n:10}) {
858      debugger;
859    }
860  }
861};
862
863listener_delegate = function(exec_state) {
864  CheckScopeChain([debug.ScopeType.With,
865                   debug.ScopeType.Catch,
866                   debug.ScopeType.Local,
867                   debug.ScopeType.Global], exec_state);
868  CheckScopeContent({n:10}, 0, exec_state);
869  CheckScopeContent({e:'Exception'}, 1, exec_state);
870  CheckScopeContent({y:98}, 2, exec_state);
871}
872catch_block_4()
873EndTest();
874
875
876assertEquals(begin_test_count, break_count, 'one or more tests did not enter the debugger');
877assertEquals(begin_test_count, end_test_count, 'one or more tests did not have its result checked');
878