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
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.
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.
28 // Flags: --expose-debug-as debug --allow-natives-syntax --turbo-deoptimization
29 // The functions used for testing backtraces. They are at the top to make the
30 // testing of source line/column easier.
32 // Get the Debug object exposed from the debug context global object.
33 var Debug = debug.Debug;
36 var listener_delegate;
39 var begin_test_count = 0;
40 var end_test_count = 0;
44 // Debug event listener which delegates.
45 function listener(event, exec_state, event_data, data) {
47 if (event == Debug.DebugEvent.Break) {
49 listener_called = true;
50 listener_delegate(exec_state);
57 // Add the debug event listener.
58 Debug.setListener(listener);
61 // Initialize for a new test.
62 function BeginTest(name) {
64 listener_delegate = null;
65 listener_called = false;
71 // Check result of a test.
73 assertTrue(listener_called, "listerner not called for " + test_name);
74 assertNull(exception, test_name + " / " + exception);
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());
87 function CheckFastAllScopes(scopes, exec_state)
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());
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);
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());
118 CheckFastAllScopes(scopes, exec_state);
120 // Get the debug command processor.
121 var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
123 // Send a scopes request and check the result.
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);
137 assertTrue(response.body.scopes[i].object.ref >= 0);
140 for (var j = 0; j < response.refs.length && !found; j++) {
141 found = response.refs[j].handle == response.body.scopes[i].object.ref;
143 assertTrue(found, "Scope object " + response.body.scopes[i].object.ref + " not found");
148 // Check that the content of the scope is as expected. For functions just check
149 // that there is a function.
150 function CheckScopeContent(content, number, exec_state) {
151 var scope = exec_state.frame().scope(number);
153 for (var p in content) {
154 var property_mirror = scope.scopeObject().property(p);
155 assertFalse(property_mirror.isUndefined(), 'property ' + p + ' not found in scope');
156 if (typeof(content[p]) === 'function') {
157 assertTrue(property_mirror.value().isFunction());
159 assertEquals(content[p], property_mirror.value().value(), 'property ' + p + ' has unexpected value');
164 // 'arguments' and might be exposed in the local and closure scope. Just
166 var scope_size = scope.scopeObject().properties().length;
167 if (!scope.scopeObject().property('arguments').isUndefined()) {
170 // Skip property with empty name.
171 if (!scope.scopeObject().property('').isUndefined()) {
175 if (count != scope_size) {
176 print('Names found in scope:');
177 var names = scope.scopeObject().propertyNames();
178 for (var i = 0; i < names.length; i++) {
182 assertEquals(count, scope_size);
184 // Get the debug command processor.
185 var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
187 // Send a scope request for information on a single scope and check the
189 var request_json = '{"seq":0,"type":"request","command":"scope","arguments":{"number":';
190 request_json += scope.scopeIndex();
191 request_json += '}}';
192 var response_json = dcp.processDebugJSONRequest(request_json);
193 var response = JSON.parse(response_json);
194 assertEquals(scope.scopeType(), response.body.type);
195 assertEquals(number, response.body.index);
196 if (scope.scopeType() == debug.ScopeType.Local ||
197 scope.scopeType() == debug.ScopeType.Script ||
198 scope.scopeType() == debug.ScopeType.Closure) {
199 assertTrue(response.body.object.ref < 0);
201 assertTrue(response.body.object.ref >= 0);
204 for (var i = 0; i < response.refs.length && !found; i++) {
205 found = response.refs[i].handle == response.body.object.ref;
207 assertTrue(found, "Scope object " + response.body.object.ref + " not found");
211 // Simple empty local scope.
212 BeginTest("Local 1");
218 listener_delegate = function(exec_state) {
219 CheckScopeChain([debug.ScopeType.Local,
220 debug.ScopeType.Script,
221 debug.ScopeType.Global], exec_state);
222 CheckScopeContent({}, 0, exec_state);
228 // Local scope with a parameter.
229 BeginTest("Local 2");
231 function local_2(a) {
235 listener_delegate = function(exec_state) {
236 CheckScopeChain([debug.ScopeType.Local,
237 debug.ScopeType.Script,
238 debug.ScopeType.Global], exec_state);
239 CheckScopeContent({a:1}, 0, exec_state);
245 // Local scope with a parameter and a local variable.
246 BeginTest("Local 3");
248 function local_3(a) {
253 listener_delegate = function(exec_state) {
254 CheckScopeChain([debug.ScopeType.Local,
255 debug.ScopeType.Script,
256 debug.ScopeType.Global], exec_state);
257 CheckScopeContent({a:1,x:3}, 0, exec_state);
263 // Local scope with parameters and local variables.
264 BeginTest("Local 4");
266 function local_4(a, b) {
272 listener_delegate = function(exec_state) {
273 CheckScopeChain([debug.ScopeType.Local,
274 debug.ScopeType.Script,
275 debug.ScopeType.Global], exec_state);
276 CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state);
282 // Empty local scope with use of eval.
283 BeginTest("Local 5");
290 listener_delegate = function(exec_state) {
291 CheckScopeChain([debug.ScopeType.Local,
292 debug.ScopeType.Script,
293 debug.ScopeType.Global], exec_state);
294 CheckScopeContent({}, 0, exec_state);
300 // Local introducing local variable using eval.
301 BeginTest("Local 6");
308 listener_delegate = function(exec_state) {
309 CheckScopeChain([debug.ScopeType.Local,
310 debug.ScopeType.Script,
311 debug.ScopeType.Global], exec_state);
312 CheckScopeContent({i:5}, 0, exec_state);
318 // Local scope with parameters, local variables and local variable introduced
320 BeginTest("Local 7");
322 function local_7(a, b) {
330 listener_delegate = function(exec_state) {
331 CheckScopeChain([debug.ScopeType.Local,
332 debug.ScopeType.Script,
333 debug.ScopeType.Global], exec_state);
334 CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 0, exec_state);
340 // Single empty with block.
349 listener_delegate = function(exec_state) {
350 CheckScopeChain([debug.ScopeType.With,
351 debug.ScopeType.Local,
352 debug.ScopeType.Script,
353 debug.ScopeType.Global], exec_state);
354 CheckScopeContent({}, 0, exec_state);
360 // Nested empty with blocks.
371 listener_delegate = function(exec_state) {
372 CheckScopeChain([debug.ScopeType.With,
373 debug.ScopeType.With,
374 debug.ScopeType.Local,
375 debug.ScopeType.Script,
376 debug.ScopeType.Global], exec_state);
377 CheckScopeContent({}, 0, exec_state);
378 CheckScopeContent({}, 1, exec_state);
384 // With block using an in-place object literal.
393 listener_delegate = function(exec_state) {
394 CheckScopeChain([debug.ScopeType.With,
395 debug.ScopeType.Local,
396 debug.ScopeType.Script,
397 debug.ScopeType.Global], exec_state);
398 CheckScopeContent({a:1,b:2}, 0, exec_state);
404 // Nested with blocks using in-place object literals.
415 listener_delegate = function(exec_state) {
416 CheckScopeChain([debug.ScopeType.With,
417 debug.ScopeType.With,
418 debug.ScopeType.Local,
419 debug.ScopeType.Script,
420 debug.ScopeType.Global], exec_state);
421 CheckScopeContent({a:2,b:1}, 0, exec_state);
422 CheckScopeContent({a:1,b:2}, 1, exec_state);
428 // Nested with blocks using existing object.
431 var with_object = {c:3,d:4};
440 listener_delegate = function(exec_state) {
441 CheckScopeChain([debug.ScopeType.With,
442 debug.ScopeType.With,
443 debug.ScopeType.Local,
444 debug.ScopeType.Script,
445 debug.ScopeType.Global], exec_state);
446 CheckScopeContent(with_object, 0, exec_state);
447 CheckScopeContent(with_object, 1, exec_state);
448 assertEquals(exec_state.frame().scope(0).scopeObject(), exec_state.frame().scope(1).scopeObject());
449 assertEquals(with_object, exec_state.frame().scope(1).scopeObject().value());
455 // Nested with blocks using existing object in global code.
457 listener_delegate = function(exec_state) {
458 CheckScopeChain([debug.ScopeType.With,
459 debug.ScopeType.With,
460 debug.ScopeType.Script,
461 debug.ScopeType.Global], exec_state);
462 CheckScopeContent(with_object, 0, exec_state);
463 CheckScopeContent(with_object, 1, exec_state);
464 assertEquals(exec_state.frame().scope(0).scopeObject(), exec_state.frame().scope(1).scopeObject());
465 assertEquals(with_object, exec_state.frame().scope(1).scopeObject().value());
468 var with_object = {c:3,d:4};
477 // With block in function that is marked for optimization while being executed.
482 %OptimizeFunctionOnNextCall(with_7);
487 listener_delegate = function(exec_state) {
488 CheckScopeChain([debug.ScopeType.With,
489 debug.ScopeType.Local,
490 debug.ScopeType.Script,
491 debug.ScopeType.Global], exec_state);
492 CheckScopeContent({}, 0, exec_state);
498 // Simple closure formed by returning an inner function referering the outer
499 // functions arguments.
500 BeginTest("Closure 1");
502 function closure_1(a) {
510 listener_delegate = function(exec_state) {
511 CheckScopeChain([debug.ScopeType.Local,
512 debug.ScopeType.Closure,
513 debug.ScopeType.Script,
514 debug.ScopeType.Global], exec_state);
515 CheckScopeContent({a:1}, 1, exec_state);
521 // Simple closure formed by returning an inner function referering the outer
522 // functions arguments. Due to VM optimizations parts of the actual closure is
523 // missing from the debugger information.
524 BeginTest("Closure 2");
526 function closure_2(a, b) {
536 listener_delegate = function(exec_state) {
537 CheckScopeChain([debug.ScopeType.Local,
538 debug.ScopeType.Closure,
539 debug.ScopeType.Script,
540 debug.ScopeType.Global], exec_state);
541 CheckScopeContent({a:1,x:3}, 1, exec_state);
547 // Simple closure formed by returning an inner function referering the outer
548 // functions arguments. Using all arguments and locals from the outer function
549 // in the inner function makes these part of the debugger information on the
551 BeginTest("Closure 3");
553 function closure_3(a, b) {
558 return a + b + x + y;
563 listener_delegate = function(exec_state) {
564 CheckScopeChain([debug.ScopeType.Local,
565 debug.ScopeType.Closure,
566 debug.ScopeType.Script,
567 debug.ScopeType.Global], exec_state);
568 CheckScopeContent({a:1,b:2,x:3,y:4}, 1, exec_state);
575 // Simple closure formed by returning an inner function referering the outer
576 // functions arguments. Using all arguments and locals from the outer function
577 // in the inner function makes these part of the debugger information on the
578 // closure. Use the inner function as well...
579 BeginTest("Closure 4");
581 function closure_4(a, b) {
587 return a + b + x + y;
593 listener_delegate = function(exec_state) {
594 CheckScopeChain([debug.ScopeType.Local,
595 debug.ScopeType.Closure,
596 debug.ScopeType.Script,
597 debug.ScopeType.Global], exec_state);
598 CheckScopeContent({a:1,b:2,x:3,y:4,f:function(){}}, 1, exec_state);
605 // Simple closure formed by returning an inner function referering the outer
606 // functions arguments. In the presence of eval all arguments and locals
607 // (including the inner function itself) from the outer function becomes part of
608 // the debugger infformation on the closure.
609 BeginTest("Closure 5");
611 function closure_5(a, b) {
622 listener_delegate = function(exec_state) {
623 CheckScopeChain([debug.ScopeType.Local,
624 debug.ScopeType.Closure,
625 debug.ScopeType.Script,
626 debug.ScopeType.Global], exec_state);
627 CheckScopeContent({a:1,b:2,x:3,y:4,f:function(){}}, 1, exec_state);
633 // Two closures. Due to optimizations only the parts actually used are provided
634 // through the debugger information.
635 BeginTest("Closure 6");
636 function closure_6(a, b) {
651 listener_delegate = function(exec_state) {
652 CheckScopeChain([debug.ScopeType.Local,
653 debug.ScopeType.Closure,
654 debug.ScopeType.Closure,
655 debug.ScopeType.Script,
656 debug.ScopeType.Global], exec_state);
657 CheckScopeContent({a:1}, 1, exec_state);
658 CheckScopeContent({f:function(){}}, 2, exec_state);
664 // Two closures. In the presence of eval all information is provided as the
665 // compiler cannot determine which parts are used.
666 BeginTest("Closure 7");
667 function closure_7(a, b) {
686 listener_delegate = function(exec_state) {
687 CheckScopeChain([debug.ScopeType.Local,
688 debug.ScopeType.Closure,
689 debug.ScopeType.Closure,
690 debug.ScopeType.Script,
691 debug.ScopeType.Global], exec_state);
692 CheckScopeContent({}, 0, exec_state);
693 CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 1, exec_state);
694 CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6,f:function(){}}, 2, exec_state);
700 // Closure that may be optimized out.
701 BeginTest("Closure 8");
702 function closure_8() {
708 listener_delegate = function(exec_state) {
709 CheckScopeChain([debug.ScopeType.Local,
710 debug.ScopeType.Script,
711 debug.ScopeType.Global], exec_state);
712 CheckScopeContent({x: 2}, 0, exec_state);
718 BeginTest("Closure 9");
719 function closure_9() {
729 listener_delegate = function(exec_state) {
730 CheckScopeChain([debug.ScopeType.Local,
731 debug.ScopeType.Closure,
732 debug.ScopeType.Script,
733 debug.ScopeType.Global], exec_state);
739 // Test a mixture of scopes.
740 BeginTest("The full monty");
741 function the_full_monty(a, b) {
767 listener_delegate = function(exec_state) {
768 CheckScopeChain([debug.ScopeType.With,
769 debug.ScopeType.With,
770 debug.ScopeType.Local,
771 debug.ScopeType.With,
772 debug.ScopeType.Closure,
773 debug.ScopeType.Closure,
774 debug.ScopeType.Script,
775 debug.ScopeType.Global], exec_state);
776 CheckScopeContent({b:16}, 0, exec_state);
777 CheckScopeContent({a:15}, 1, exec_state);
778 CheckScopeContent({x:14}, 2, exec_state);
779 CheckScopeContent({j:13}, 3, exec_state);
780 CheckScopeContent({a:1,b:2,x:9,y:10,i:11,j:12}, 4, exec_state);
781 CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6,f:function(){}}, 5, exec_state);
783 the_full_monty(1, 2)();
787 BeginTest("Closure inside With 1");
788 function closure_in_with_1() {
796 listener_delegate = function(exec_state) {
797 CheckScopeChain([debug.ScopeType.Local,
798 debug.ScopeType.With,
799 debug.ScopeType.Closure,
800 debug.ScopeType.Script,
801 debug.ScopeType.Global], exec_state);
802 CheckScopeContent({x: 2}, 0, exec_state);
808 BeginTest("Closure inside With 2");
809 function closure_in_with_2() {
819 listener_delegate = function(exec_state) {
820 CheckScopeChain([debug.ScopeType.With,
821 debug.ScopeType.Local,
822 debug.ScopeType.With,
823 debug.ScopeType.Closure,
824 debug.ScopeType.Script,
825 debug.ScopeType.Global], exec_state);
826 CheckScopeContent({x: 3}, 0, exec_state);
827 CheckScopeContent({x: 2}, 1, exec_state);
828 CheckScopeContent({x: 1}, 2, exec_state);
834 BeginTest("Closure inside With 3");
835 function createClosure(a) {
837 return function closure() {
847 function closure_in_with_3() {
848 var f = createClosure(0);
852 listener_delegate = function(exec_state) {
853 CheckScopeChain([debug.ScopeType.With,
854 debug.ScopeType.Local,
855 debug.ScopeType.Closure,
856 debug.ScopeType.Closure,
857 debug.ScopeType.Script,
858 debug.ScopeType.Global], exec_state);
864 BeginTest("Closure inside With 4");
865 listener_delegate = function(exec_state) {
866 CheckScopeChain([debug.ScopeType.Local,
867 debug.ScopeType.With,
868 debug.ScopeType.Script,
869 debug.ScopeType.Global], exec_state);
870 CheckScopeContent({x: 2}, 0, exec_state);
871 CheckScopeContent({x: 1}, 1, exec_state);
882 // Test global scope.
884 listener_delegate = function(exec_state) {
885 CheckScopeChain([debug.ScopeType.Script, debug.ScopeType.Global], exec_state);
891 BeginTest("Catch block 1");
892 function catch_block_1() {
901 listener_delegate = function(exec_state) {
902 CheckScopeChain([debug.ScopeType.Catch,
903 debug.ScopeType.Local,
904 debug.ScopeType.Script,
905 debug.ScopeType.Global], exec_state);
906 CheckScopeContent({e:'Exception'}, 0, exec_state);
912 BeginTest("Catch block 2");
913 function catch_block_2() {
924 listener_delegate = function(exec_state) {
925 CheckScopeChain([debug.ScopeType.With,
926 debug.ScopeType.Catch,
927 debug.ScopeType.Local,
928 debug.ScopeType.Script,
929 debug.ScopeType.Global], exec_state);
930 CheckScopeContent({n:10}, 0, exec_state);
931 CheckScopeContent({e:'Exception'}, 1, exec_state);
937 BeginTest("Catch block 3");
938 function catch_block_3() {
939 // Do eval to dynamically declare a local variable so that the context's
940 // extension slot is initialized with JSContextExtensionObject.
950 listener_delegate = function(exec_state) {
951 CheckScopeChain([debug.ScopeType.Catch,
952 debug.ScopeType.Local,
953 debug.ScopeType.Script,
954 debug.ScopeType.Global], exec_state);
955 CheckScopeContent({e:'Exception'}, 0, exec_state);
956 CheckScopeContent({y:78}, 1, exec_state);
962 BeginTest("Catch block 4");
963 function catch_block_4() {
964 // Do eval to dynamically declare a local variable so that the context's
965 // extension slot is initialized with JSContextExtensionObject.
976 listener_delegate = function(exec_state) {
977 CheckScopeChain([debug.ScopeType.With,
978 debug.ScopeType.Catch,
979 debug.ScopeType.Local,
980 debug.ScopeType.Script,
981 debug.ScopeType.Global], exec_state);
982 CheckScopeContent({n:10}, 0, exec_state);
983 CheckScopeContent({e:'Exception'}, 1, exec_state);
984 CheckScopeContent({y:98}, 2, exec_state);
990 // Test catch in global scope.
991 BeginTest("Catch block 5");
992 listener_delegate = function(exec_state) {
993 CheckScopeChain([debug.ScopeType.Catch,
994 debug.ScopeType.Script,
995 debug.ScopeType.Global], exec_state);
996 CheckScopeContent({e:'Exception'}, 0, exec_state);
1008 // Closure inside catch in global code.
1009 BeginTest("Catch block 6");
1010 listener_delegate = function(exec_state) {
1011 CheckScopeChain([debug.ScopeType.Local,
1012 debug.ScopeType.Catch,
1013 debug.ScopeType.Script,
1014 debug.ScopeType.Global], exec_state);
1015 CheckScopeContent({x: 2}, 0, exec_state);
1016 CheckScopeContent({e:'Exception'}, 1, exec_state);
1029 // Catch block in function that is marked for optimization while being executed.
1030 BeginTest("Catch block 7");
1031 function catch_block_7() {
1032 %OptimizeFunctionOnNextCall(catch_block_7);
1041 listener_delegate = function(exec_state) {
1042 CheckScopeChain([debug.ScopeType.Catch,
1043 debug.ScopeType.Local,
1044 debug.ScopeType.Script,
1045 debug.ScopeType.Global], exec_state);
1046 CheckScopeContent({e:'Exception'}, 0, exec_state);
1052 assertEquals(begin_test_count, break_count,
1053 'one or more tests did not enter the debugger');
1054 assertEquals(begin_test_count, end_test_count,
1055 'one or more tests did not have its result checked');