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