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