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