1b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// Copyright 2011 the V8 project authors. All rights reserved. 2b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// Redistribution and use in source and binary forms, with or without 3b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// modification, are permitted provided that the following conditions are 4b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// met: 5b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// 6b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// * Redistributions of source code must retain the above copyright 7b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// notice, this list of conditions and the following disclaimer. 8b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// * Redistributions in binary form must reproduce the above 9b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// copyright notice, this list of conditions and the following 10b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// disclaimer in the documentation and/or other materials provided 11b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// with the distribution. 12b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// * Neither the name of Google Inc. nor the names of its 13b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// contributors may be used to endorse or promote products derived 14b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// from this software without specific prior written permission. 15b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// 16b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 28b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org// Flags: --expose-debug-as debug --harmony-scoping 29b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// The functions used for testing backtraces. They are at the top to make the 30b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// testing of source line/column easier. 31b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 32b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 33b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// Get the Debug object exposed from the debug context global object. 34b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgDebug = debug.Debug; 35b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 36b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgvar test_name; 37b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgvar listener_delegate; 38b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgvar listener_called; 39b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgvar exception; 40b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgvar begin_test_count = 0; 41b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgvar end_test_count = 0; 42b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgvar break_count = 0; 43b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 44b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 45b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// Debug event listener which delegates. 46b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgfunction listener(event, exec_state, event_data, data) { 47b645116853c677aca8a316381b87441ba6004f67danno@chromium.org try { 48b645116853c677aca8a316381b87441ba6004f67danno@chromium.org if (event == Debug.DebugEvent.Break) { 49b645116853c677aca8a316381b87441ba6004f67danno@chromium.org break_count++; 50b645116853c677aca8a316381b87441ba6004f67danno@chromium.org listener_called = true; 51b645116853c677aca8a316381b87441ba6004f67danno@chromium.org listener_delegate(exec_state); 52b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } 53b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } catch (e) { 54b645116853c677aca8a316381b87441ba6004f67danno@chromium.org exception = e; 55b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } 56b645116853c677aca8a316381b87441ba6004f67danno@chromium.org} 57b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 58b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// Add the debug event listener. 59b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgDebug.setListener(listener); 60b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 61b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 62b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// Initialize for a new test. 63b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgfunction BeginTest(name) { 64b645116853c677aca8a316381b87441ba6004f67danno@chromium.org test_name = name; 65b645116853c677aca8a316381b87441ba6004f67danno@chromium.org listener_delegate = null; 66b645116853c677aca8a316381b87441ba6004f67danno@chromium.org listener_called = false; 67b645116853c677aca8a316381b87441ba6004f67danno@chromium.org exception = null; 68b645116853c677aca8a316381b87441ba6004f67danno@chromium.org begin_test_count++; 69b645116853c677aca8a316381b87441ba6004f67danno@chromium.org} 70b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 71b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 72b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// Check result of a test. 73b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgfunction EndTest() { 74b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertTrue(listener_called, "listerner not called for " + test_name); 75b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertNull(exception, test_name); 76b645116853c677aca8a316381b87441ba6004f67danno@chromium.org end_test_count++; 77b645116853c677aca8a316381b87441ba6004f67danno@chromium.org} 78b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 79b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 80b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// Check that the scope chain contains the expected types of scopes. 81b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgfunction CheckScopeChain(scopes, exec_state) { 82b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertEquals(scopes.length, exec_state.frame().scopeCount()); 83b645116853c677aca8a316381b87441ba6004f67danno@chromium.org for (var i = 0; i < scopes.length; i++) { 84b645116853c677aca8a316381b87441ba6004f67danno@chromium.org var scope = exec_state.frame().scope(i); 85b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertTrue(scope.isScope()); 86b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertEquals(scopes[i], scope.scopeType()); 87b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 88b645116853c677aca8a316381b87441ba6004f67danno@chromium.org // Check the global object when hitting the global scope. 89b645116853c677aca8a316381b87441ba6004f67danno@chromium.org if (scopes[i] == debug.ScopeType.Global) { 90b645116853c677aca8a316381b87441ba6004f67danno@chromium.org // Objects don't have same class (one is "global", other is "Object", 91b645116853c677aca8a316381b87441ba6004f67danno@chromium.org // so just check the properties directly. 92b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertPropertiesEqual(this, scope.scopeObject().value()); 93b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } 94b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } 95b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 96b645116853c677aca8a316381b87441ba6004f67danno@chromium.org // Get the debug command processor. 97b645116853c677aca8a316381b87441ba6004f67danno@chromium.org var dcp = exec_state.debugCommandProcessor("unspecified_running_state"); 98b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 99b645116853c677aca8a316381b87441ba6004f67danno@chromium.org // Send a scopes request and check the result. 100b645116853c677aca8a316381b87441ba6004f67danno@chromium.org var json; 101b645116853c677aca8a316381b87441ba6004f67danno@chromium.org var request_json = '{"seq":0,"type":"request","command":"scopes"}'; 102b645116853c677aca8a316381b87441ba6004f67danno@chromium.org var response_json = dcp.processDebugJSONRequest(request_json); 103b645116853c677aca8a316381b87441ba6004f67danno@chromium.org var response = JSON.parse(response_json); 104b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertEquals(scopes.length, response.body.scopes.length); 105b645116853c677aca8a316381b87441ba6004f67danno@chromium.org for (var i = 0; i < scopes.length; i++) { 106b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertEquals(i, response.body.scopes[i].index); 107b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertEquals(scopes[i], response.body.scopes[i].type); 108b645116853c677aca8a316381b87441ba6004f67danno@chromium.org if (scopes[i] == debug.ScopeType.Local || 109b645116853c677aca8a316381b87441ba6004f67danno@chromium.org scopes[i] == debug.ScopeType.Closure) { 110b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertTrue(response.body.scopes[i].object.ref < 0); 111b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } else { 112b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertTrue(response.body.scopes[i].object.ref >= 0); 113b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } 114b645116853c677aca8a316381b87441ba6004f67danno@chromium.org var found = false; 115b645116853c677aca8a316381b87441ba6004f67danno@chromium.org for (var j = 0; j < response.refs.length && !found; j++) { 116b645116853c677aca8a316381b87441ba6004f67danno@chromium.org found = response.refs[j].handle == response.body.scopes[i].object.ref; 117b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } 118b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertTrue(found, "Scope object " + response.body.scopes[i].object.ref + " not found"); 119b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } 120b645116853c677aca8a316381b87441ba6004f67danno@chromium.org} 121b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 122b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// Check that the content of the scope is as expected. For functions just check 123b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// that there is a function. 124b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgfunction CheckScopeContent(content, number, exec_state) { 125b645116853c677aca8a316381b87441ba6004f67danno@chromium.org var scope = exec_state.frame().scope(number); 126b645116853c677aca8a316381b87441ba6004f67danno@chromium.org var count = 0; 127b645116853c677aca8a316381b87441ba6004f67danno@chromium.org for (var p in content) { 128b645116853c677aca8a316381b87441ba6004f67danno@chromium.org var property_mirror = scope.scopeObject().property(p); 129b645116853c677aca8a316381b87441ba6004f67danno@chromium.org if (property_mirror.isUndefined()) { 130b645116853c677aca8a316381b87441ba6004f67danno@chromium.org print('property ' + p + ' not found in scope'); 131b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } 132b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertFalse(property_mirror.isUndefined(), 'property ' + p + ' not found in scope'); 133b645116853c677aca8a316381b87441ba6004f67danno@chromium.org if (typeof(content[p]) === 'function') { 134b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertTrue(property_mirror.value().isFunction()); 135b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } else { 136b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertEquals(content[p], property_mirror.value().value(), 'property ' + p + ' has unexpected value'); 137b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } 138b645116853c677aca8a316381b87441ba6004f67danno@chromium.org count++; 139b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } 140b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 141b645116853c677aca8a316381b87441ba6004f67danno@chromium.org // 'arguments' and might be exposed in the local and closure scope. Just 142b645116853c677aca8a316381b87441ba6004f67danno@chromium.org // ignore this. 143b645116853c677aca8a316381b87441ba6004f67danno@chromium.org var scope_size = scope.scopeObject().properties().length; 144b645116853c677aca8a316381b87441ba6004f67danno@chromium.org if (!scope.scopeObject().property('arguments').isUndefined()) { 145b645116853c677aca8a316381b87441ba6004f67danno@chromium.org scope_size--; 146b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } 147b645116853c677aca8a316381b87441ba6004f67danno@chromium.org // Skip property with empty name. 148b645116853c677aca8a316381b87441ba6004f67danno@chromium.org if (!scope.scopeObject().property('').isUndefined()) { 149b645116853c677aca8a316381b87441ba6004f67danno@chromium.org scope_size--; 150b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } 151b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 152b645116853c677aca8a316381b87441ba6004f67danno@chromium.org if (count != scope_size) { 153b645116853c677aca8a316381b87441ba6004f67danno@chromium.org print('Names found in scope:'); 154b645116853c677aca8a316381b87441ba6004f67danno@chromium.org var names = scope.scopeObject().propertyNames(); 155b645116853c677aca8a316381b87441ba6004f67danno@chromium.org for (var i = 0; i < names.length; i++) { 156b645116853c677aca8a316381b87441ba6004f67danno@chromium.org print(names[i]); 157b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } 158b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } 159b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertEquals(count, scope_size); 160b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 161b645116853c677aca8a316381b87441ba6004f67danno@chromium.org // Get the debug command processor. 162b645116853c677aca8a316381b87441ba6004f67danno@chromium.org var dcp = exec_state.debugCommandProcessor("unspecified_running_state"); 163b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 164b645116853c677aca8a316381b87441ba6004f67danno@chromium.org // Send a scope request for information on a single scope and check the 165b645116853c677aca8a316381b87441ba6004f67danno@chromium.org // result. 166b645116853c677aca8a316381b87441ba6004f67danno@chromium.org var request_json = '{"seq":0,"type":"request","command":"scope","arguments":{"number":'; 167b645116853c677aca8a316381b87441ba6004f67danno@chromium.org request_json += scope.scopeIndex(); 168b645116853c677aca8a316381b87441ba6004f67danno@chromium.org request_json += '}}'; 169b645116853c677aca8a316381b87441ba6004f67danno@chromium.org var response_json = dcp.processDebugJSONRequest(request_json); 170b645116853c677aca8a316381b87441ba6004f67danno@chromium.org var response = JSON.parse(response_json); 171b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertEquals(scope.scopeType(), response.body.type); 172b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertEquals(number, response.body.index); 173b645116853c677aca8a316381b87441ba6004f67danno@chromium.org if (scope.scopeType() == debug.ScopeType.Local || 174b645116853c677aca8a316381b87441ba6004f67danno@chromium.org scope.scopeType() == debug.ScopeType.Closure) { 175b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertTrue(response.body.object.ref < 0); 176b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } else { 177b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertTrue(response.body.object.ref >= 0); 178b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } 179b645116853c677aca8a316381b87441ba6004f67danno@chromium.org var found = false; 180b645116853c677aca8a316381b87441ba6004f67danno@chromium.org for (var i = 0; i < response.refs.length && !found; i++) { 181b645116853c677aca8a316381b87441ba6004f67danno@chromium.org found = response.refs[i].handle == response.body.object.ref; 182b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } 183b645116853c677aca8a316381b87441ba6004f67danno@chromium.org assertTrue(found, "Scope object " + response.body.object.ref + " not found"); 184b645116853c677aca8a316381b87441ba6004f67danno@chromium.org} 185b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 186b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 187b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// Simple closure formed by returning an inner function referering to an outer 188b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// block local variable and an outer function's parameter. Due to VM 189b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// optimizations parts of the actual closure is missing from the debugger 190b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// information. 191b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgBeginTest("Closure 1"); 192b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 193b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgfunction closure_1(a) { 194b645116853c677aca8a316381b87441ba6004f67danno@chromium.org var x = 2; 195b645116853c677aca8a316381b87441ba6004f67danno@chromium.org let y = 3; 196b645116853c677aca8a316381b87441ba6004f67danno@chromium.org if (true) { 197b645116853c677aca8a316381b87441ba6004f67danno@chromium.org let z = 4; 198b645116853c677aca8a316381b87441ba6004f67danno@chromium.org function f() { 199b645116853c677aca8a316381b87441ba6004f67danno@chromium.org debugger; 200b645116853c677aca8a316381b87441ba6004f67danno@chromium.org return a + x + y + z; 201b645116853c677aca8a316381b87441ba6004f67danno@chromium.org }; 202b645116853c677aca8a316381b87441ba6004f67danno@chromium.org return f; 203b645116853c677aca8a316381b87441ba6004f67danno@chromium.org } 204b645116853c677aca8a316381b87441ba6004f67danno@chromium.org} 205b645116853c677aca8a316381b87441ba6004f67danno@chromium.org 206b645116853c677aca8a316381b87441ba6004f67danno@chromium.orglistener_delegate = function(exec_state) { 207b645116853c677aca8a316381b87441ba6004f67danno@chromium.org CheckScopeChain([debug.ScopeType.Local, 208b645116853c677aca8a316381b87441ba6004f67danno@chromium.org debug.ScopeType.Block, 209b645116853c677aca8a316381b87441ba6004f67danno@chromium.org debug.ScopeType.Closure, 210b645116853c677aca8a316381b87441ba6004f67danno@chromium.org debug.ScopeType.Global], exec_state); 211b645116853c677aca8a316381b87441ba6004f67danno@chromium.org CheckScopeContent({}, 0, exec_state); 212b645116853c677aca8a316381b87441ba6004f67danno@chromium.org CheckScopeContent({z:4}, 1, exec_state); 213b645116853c677aca8a316381b87441ba6004f67danno@chromium.org CheckScopeContent({a:1,x:2,y:3}, 2, exec_state); 214b645116853c677aca8a316381b87441ba6004f67danno@chromium.org}; 215b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgclosure_1(1)(); 216b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgEndTest(); 217