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