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