debug-handle.js revision a7e24c173cf37484693b9abb38e494fa7bd7baeb
1// Copyright 2009 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
29// Get the Debug object exposed from the debug context global object.
30Debug = debug.Debug
31
32listenerComplete = false;
33exception = false;
34
35function safeEval(code) {
36  try {
37    return eval('(' + code + ')');
38  } catch (e) {
39    assertEquals(void 0, e);
40    return undefined;
41  }
42}
43
44
45// Send an evaluation request and return the handle of the result.
46function evaluateRequest(dcp, arguments) {
47  // The base part of all evaluate requests.
48  var base_request = '"seq":0,"type":"request","command":"evaluate"'
49
50  // Generate request with the supplied arguments.
51  var request;
52  if (arguments) {
53    request = '{' + base_request + ',"arguments":' + arguments + '}';
54  } else {
55    request = '{' + base_request + '}'
56  }
57
58  var response = safeEval(dcp.processDebugJSONRequest(request));
59  assertTrue(response.success, request + ' -> ' + response.message);
60
61  return response.body.handle;
62}
63
64
65// Send a lookup request and return the evaluated JSON response.
66function lookupRequest(dcp, arguments, success) {
67  // The base part of all lookup requests.
68  var base_request = '"seq":0,"type":"request","command":"lookup"'
69
70  // Generate request with the supplied arguments.
71  var request;
72  if (arguments) {
73    request = '{' + base_request + ',"arguments":' + arguments + '}';
74  } else {
75    request = '{' + base_request + '}'
76  }
77
78  var response = safeEval(dcp.processDebugJSONRequest(request));
79  if (success) {
80    assertTrue(response.success, request + ' -> ' + response.message);
81  } else {
82    assertFalse(response.success, request + ' -> ' + response.message);
83  }
84  assertFalse(response.running, request + ' -> expected not running');
85
86  return response;
87}
88
89
90function listener(event, exec_state, event_data, data) {
91  try {
92  if (event == Debug.DebugEvent.Break) {
93    // Get the debug command processor.
94    var dcp = exec_state.debugCommandProcessor();
95
96    // Test some illegal lookup requests.
97    lookupRequest(dcp, void 0, false);
98    lookupRequest(dcp, '{"handles":["a"]}', false);
99    lookupRequest(dcp, '{"handles":[-1]}', false);
100
101    // Evaluate and get some handles.
102    var handle_o = evaluateRequest(dcp, '{"expression":"o"}');
103    var handle_p = evaluateRequest(dcp, '{"expression":"p"}');
104    var handle_b = evaluateRequest(dcp, '{"expression":"a"}');
105    var handle_a = evaluateRequest(dcp, '{"expression":"b","frame":1}');
106    assertEquals(handle_o, handle_a);
107    assertEquals(handle_a, handle_b);
108    assertFalse(handle_o == handle_p, "o and p have he same handle");
109
110    var response;
111    var count;
112    response = lookupRequest(dcp, '{"handles":[' + handle_o + ']}', true);
113    var obj = response.body[handle_o];
114    assertTrue(!!obj, 'Object not found: ' + handle_o);
115    assertEquals(handle_o, obj.handle);
116    count = 0;
117    for (i in obj.properties) {
118      switch (obj.properties[i].name) {
119        case 'o':
120          obj.properties[i].ref = handle_o;
121          count++;
122          break;
123        case 'p':
124          obj.properties[i].ref = handle_p;
125          count++;
126          break;
127      }
128    }
129    assertEquals(2, count, 'Either "o" or "p" not found');
130    response = lookupRequest(dcp, '{"handles":[' + handle_p + ']}', true);
131    obj = response.body[handle_p];
132    assertTrue(!!obj, 'Object not found: ' + handle_p);
133    assertEquals(handle_p, obj.handle);
134
135    // Check handles for functions on the stack.
136    var handle_f = evaluateRequest(dcp, '{"expression":"f"}');
137    var handle_g = evaluateRequest(dcp, '{"expression":"g"}');
138    var handle_caller = evaluateRequest(dcp, '{"expression":"f.caller"}');
139
140    assertFalse(handle_f == handle_g, "f and g have he same handle");
141    assertEquals(handle_g, handle_caller, "caller for f should be g");
142
143    response = lookupRequest(dcp, '{"handles":[' + handle_f + ']}', true);
144    obj = response.body[handle_f];
145    assertEquals(handle_f, obj.handle);
146
147    count = 0;
148    for (i in obj.properties) {
149      var ref = obj.properties[i].ref;
150      var arguments = '{"handles":[' + ref + ']}';
151      switch (obj.properties[i].name) {
152        case 'name':
153          var response_name;
154          response_name = lookupRequest(dcp, arguments, true);
155          assertEquals('string', response_name.body[ref].type);
156          assertEquals("f", response_name.body[ref].value);
157          count++;
158          break;
159        case 'length':
160          var response_length;
161          response_length = lookupRequest(dcp, arguments, true);
162          assertEquals('number', response_length.body[ref].type);
163          assertEquals(1, response_length.body[ref].value);
164          count++;
165          break;
166        case 'caller':
167          assertEquals(handle_g, obj.properties[i].ref);
168          count++;
169          break;
170      }
171    }
172    assertEquals(3, count, 'Either "name", "length" or "caller" not found');
173
174
175    // Resolve all at once.
176    var refs = [];
177    for (i in obj.properties) {
178      refs.push(obj.properties[i].ref);
179    }
180
181    var arguments = '{"handles":[' + refs.join(',') + ']}';
182    response = lookupRequest(dcp, arguments, true);
183    count = 0;
184    for (i in obj.properties) {
185      var ref = obj.properties[i].ref;
186      var val = response.body[ref];
187      assertTrue(!!val, 'Failed to lookup "' + obj.properties[i].name + '"');
188      switch (obj.properties[i].name) {
189        case 'name':
190          assertEquals('string', val.type);
191          assertEquals("f", val.value);
192          count++;
193          break;
194        case 'length':
195          assertEquals('number', val.type);
196          assertEquals(1, val.value);
197          count++;
198          break;
199        case 'caller':
200          assertEquals('function', val.type);
201          assertEquals(handle_g, ref);
202          count++;
203          break;
204      }
205    }
206    assertEquals(3, count, 'Either "name", "length" or "caller" not found');
207
208    count = 0;
209    for (var handle in response.body) {
210      assertTrue(refs.indexOf(parseInt(handle)) != -1,
211                 'Handle not in the request: ' + handle);
212      count++;
213    }
214    assertEquals(count, obj.properties.length,
215                 'Unexpected number of resolved objects');
216
217
218    // Indicate that all was processed.
219    listenerComplete = true;
220  }
221  } catch (e) {
222    exception = e
223  };
224};
225
226// Add the debug event listener.
227Debug.setListener(listener);
228
229function f(a) {
230  debugger;
231};
232
233function g(b) {
234  f(b);
235};
236
237// Set a break point at return in f and invoke g to hit the breakpoint.
238Debug.setBreakPoint(f, 2, 0);
239o = {};
240p = {}
241o.o = o;
242o.p = p;
243p.o = o;
244p.p = p;
245g(o);
246
247// Make sure that the debug event listener vas invoked.
248assertTrue(listenerComplete, "listener did not run to completion: " + exception);
249assertFalse(exception, "exception in listener")
250