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. 33 var Debug = debug.Debug; 34 35 var test_name; 36 var listener_delegate; 37 var listener_called; 38 var exception; 39 var begin_test_count = 0; 40 var end_test_count = 0; 41 var break_count = 0; 42 43 44 // Debug event listener which delegates. 45 function 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. 58 Debug.setListener(listener); 59 60 61 // Initialize for a new test. 62 function 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. 72 function 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. 80 function 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 87 function 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. 101 function 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. 149 function 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. 210 BeginTest("Local 1"); 211 212 function local_1() { 213 debugger; 214 } 215 216 listener_delegate = function(exec_state) { 217 CheckScopeChain([debug.ScopeType.Local, 218 debug.ScopeType.Global], exec_state); 219 CheckScopeContent({}, 0, exec_state); 220 }; 221 local_1(); 222 EndTest(); 223 224 225 // Local scope with a parameter. 226 BeginTest("Local 2"); 227 228 function local_2(a) { 229 debugger; 230 } 231 232 listener_delegate = function(exec_state) { 233 CheckScopeChain([debug.ScopeType.Local, 234 debug.ScopeType.Global], exec_state); 235 CheckScopeContent({a:1}, 0, exec_state); 236 }; 237 local_2(1); 238 EndTest(); 239 240 241 // Local scope with a parameter and a local variable. 242 BeginTest("Local 3"); 243 244 function local_3(a) { 245 var x = 3; 246 debugger; 247 } 248 249 listener_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 }; 254 local_3(1); 255 EndTest(); 256 257 258 // Local scope with parameters and local variables. 259 BeginTest("Local 4"); 260 261 function local_4(a, b) { 262 var x = 3; 263 var y = 4; 264 debugger; 265 } 266 267 listener_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 }; 272 local_4(1, 2); 273 EndTest(); 274 275 276 // Empty local scope with use of eval. 277 BeginTest("Local 5"); 278 279 function local_5() { 280 eval(''); 281 debugger; 282 } 283 284 listener_delegate = function(exec_state) { 285 CheckScopeChain([debug.ScopeType.Local, 286 debug.ScopeType.Global], exec_state); 287 CheckScopeContent({}, 0, exec_state); 288 }; 289 local_5(); 290 EndTest(); 291 292 293 // Local introducing local variable using eval. 294 BeginTest("Local 6"); 295 296 function local_6() { 297 eval('var i = 5'); 298 debugger; 299 } 300 301 listener_delegate = function(exec_state) { 302 CheckScopeChain([debug.ScopeType.Local, 303 debug.ScopeType.Global], exec_state); 304 CheckScopeContent({i:5}, 0, exec_state); 305 }; 306 local_6(); 307 EndTest(); 308 309 310 // Local scope with parameters, local variables and local variable introduced 311 // using eval. 312 BeginTest("Local 7"); 313 314 function 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 322 listener_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 }; 327 local_7(1, 2); 328 EndTest(); 329 330 331 // Single empty with block. 332 BeginTest("With 1"); 333 334 function with_1() { 335 with({}) { 336 debugger; 337 } 338 } 339 340 listener_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 }; 346 with_1(); 347 EndTest(); 348 349 350 // Nested empty with blocks. 351 BeginTest("With 2"); 352 353 function with_2() { 354 with({}) { 355 with({}) { 356 debugger; 357 } 358 } 359 } 360 361 listener_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 }; 369 with_2(); 370 EndTest(); 371 372 373 // With block using an in-place object literal. 374 BeginTest("With 3"); 375 376 function with_3() { 377 with({a:1,b:2}) { 378 debugger; 379 } 380 } 381 382 listener_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 }; 388 with_3(); 389 EndTest(); 390 391 392 // Nested with blocks using in-place object literals. 393 BeginTest("With 4"); 394 395 function with_4() { 396 with({a:1,b:2}) { 397 with({a:2,b:1}) { 398 debugger; 399 } 400 } 401 } 402 403 listener_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 }; 411 with_4(); 412 EndTest(); 413 414 415 // Nested with blocks using existing object. 416 BeginTest("With 5"); 417 418 var with_object = {c:3,d:4}; 419 function with_5() { 420 with(with_object) { 421 with(with_object) { 422 debugger; 423 } 424 } 425 } 426 427 listener_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 }; 437 with_5(); 438 EndTest(); 439 440 441 // Nested with blocks using existing object in global code. 442 BeginTest("With 6"); 443 listener_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 453 var with_object = {c:3,d:4}; 454 with(with_object) { 455 with(with_object) { 456 debugger; 457 } 458 } 459 EndTest(); 460 461 462 // With block in function that is marked for optimization while being executed. 463 BeginTest("With 7"); 464 465 function with_7() { 466 with({}) { 467 %OptimizeFunctionOnNextCall(with_7); 468 debugger; 469 } 470 } 471 472 listener_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 }; 478 with_7(); 479 EndTest(); 480 481 482 // Simple closure formed by returning an inner function referering the outer 483 // functions arguments. 484 BeginTest("Closure 1"); 485 486 function closure_1(a) { 487 function f() { 488 debugger; 489 return a; 490 }; 491 return f; 492 } 493 494 listener_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 }; 500 closure_1(1)(); 501 EndTest(); 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. 507 BeginTest("Closure 2"); 508 509 function 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 519 listener_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 }; 525 closure_2(1, 2)(); 526 EndTest(); 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. 533 BeginTest("Closure 3"); 534 535 function 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 545 listener_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 }; 551 closure_3(1, 2)(); 552 EndTest(); 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... 560 BeginTest("Closure 4"); 561 562 function 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 574 listener_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 }; 580 closure_4(1, 2)(); 581 EndTest(); 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. 589 BeginTest("Closure 5"); 590 591 function 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 602 listener_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 }; 608 closure_5(1, 2)(); 609 EndTest(); 610 611 612 // Two closures. Due to optimizations only the parts actually used are provided 613 // through the debugger information. 614 BeginTest("Closure 6"); 615 function 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 630 listener_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 }; 638 closure_6(1, 2)(); 639 EndTest(); 640 641 642 // Two closures. In the presence of eval all information is provided as the 643 // compiler cannot determine which parts are used. 644 BeginTest("Closure 7"); 645 function 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 664 listener_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 }; 673 closure_7(1, 2)(); 674 EndTest(); 675 676 677 // Closure that may be optimized out. 678 BeginTest("Closure 8"); 679 function closure_8() { 680 (function inner(x) { 681 debugger; 682 })(2); 683 } 684 685 listener_delegate = function(exec_state) { 686 CheckScopeChain([debug.ScopeType.Local, 687 debug.ScopeType.Global], exec_state); 688 CheckScopeContent({x: 2}, 0, exec_state); 689 }; 690 closure_8(); 691 EndTest(); 692 693 694 BeginTest("Closure 9"); 695 function 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 705 listener_delegate = function(exec_state) { 706 CheckScopeChain([debug.ScopeType.Local, 707 debug.ScopeType.Closure, 708 debug.ScopeType.Global], exec_state); 709 }; 710 closure_9(); 711 EndTest(); 712 713 714 // Test a mixture of scopes. 715 BeginTest("The full monty"); 716 function 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 742 listener_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 }; 757 the_full_monty(1, 2)(); 758 EndTest(); 759 760 761 BeginTest("Closure inside With 1"); 762 function closure_in_with_1() { 763 with({x:1}) { 764 (function inner(x) { 765 debugger; 766 })(2); 767 } 768 } 769 770 listener_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 }; 777 closure_in_with_1(); 778 EndTest(); 779 780 781 BeginTest("Closure inside With 2"); 782 function closure_in_with_2() { 783 with({x:1}) { 784 (function inner(x) { 785 with({x:3}) { 786 debugger; 787 } 788 })(2); 789 } 790 } 791 792 listener_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 }; 802 closure_in_with_2(); 803 EndTest(); 804 805 806 BeginTest("Closure inside With 3"); 807 function 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 819 function closure_in_with_3() { 820 var f = createClosure(0); 821 f(); 822 } 823 824 listener_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 } 831 closure_in_with_3(); 832 EndTest(); 833 834 835 BeginTest("Closure inside With 4"); 836 listener_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 844 with({x:1}) { 845 (function(x) { 846 debugger; 847 })(2); 848 } 849 EndTest(); 850 851 852 // Test global scope. 853 BeginTest("Global"); 854 listener_delegate = function(exec_state) { 855 CheckScopeChain([debug.ScopeType.Global], exec_state); 856 }; 857 debugger; 858 EndTest(); 859 860 861 BeginTest("Catch block 1"); 862 function catch_block_1() { 863 try { 864 throw 'Exception'; 865 } catch (e) { 866 debugger; 867 } 868 }; 869 870 871 listener_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 }; 877 catch_block_1(); 878 EndTest(); 879 880 881 BeginTest("Catch block 2"); 882 function catch_block_2() { 883 try { 884 throw 'Exception'; 885 } catch (e) { 886 with({n:10}) { 887 debugger; 888 } 889 } 890 }; 891 892 893 listener_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 }; 901 catch_block_2(); 902 EndTest(); 903 904 905 BeginTest("Catch block 3"); 906 function 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 918 listener_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 }; 925 catch_block_3(); 926 EndTest(); 927 928 929 BeginTest("Catch block 4"); 930 function 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 943 listener_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 }; 952 catch_block_4(); 953 EndTest(); 954 955 956 // Test catch in global scope. 957 BeginTest("Catch block 5"); 958 listener_delegate = function(exec_state) { 959 CheckScopeChain([debug.ScopeType.Catch, 960 debug.ScopeType.Global], exec_state); 961 CheckScopeContent({e:'Exception'}, 0, exec_state); 962 }; 963 964 try { 965 throw 'Exception'; 966 } catch (e) { 967 debugger; 968 } 969 970 EndTest(); 971 972 973 // Closure inside catch in global code. 974 BeginTest("Catch block 6"); 975 listener_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 983 try { 984 throw 'Exception'; 985 } catch (e) { 986 (function(x) { 987 debugger; 988 })(2); 989 } 990 EndTest(); 991 992 993 // Catch block in function that is marked for optimization while being executed. 994 BeginTest("Catch block 7"); 995 function catch_block_7() { 996 %OptimizeFunctionOnNextCall(catch_block_7); 997 try { 998 throw 'Exception'; 999 } catch (e) { 1000 debugger; 1001 } 1002 }; 1003 1004 1005 listener_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 }; 1011 catch_block_7(); 1012 EndTest(); 1013 1014 1015 assertEquals(begin_test_count, break_count, 1016 'one or more tests did not enter the debugger'); 1017 assertEquals(begin_test_count, end_test_count, 1018 'one or more tests did not have its result checked'); 1019