OLD | NEW |
| (Empty) |
1 // Copyright 2008 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 --nocrankshaft | |
29 // Get the Debug object exposed from the debug context global object. | |
30 Debug = debug.Debug | |
31 | |
32 function DebuggerStatement() { | |
33 debugger; /*pause*/ | |
34 } | |
35 | |
36 function TestCase(fun, frame_number, line_number) { | |
37 var exception = false; | |
38 var codeSnippet = undefined; | |
39 var resultPositions = undefined; | |
40 var step = 0; | |
41 | |
42 function listener(event, exec_state, event_data, data) { | |
43 try { | |
44 if (event == Debug.DebugEvent.Break || | |
45 event == Debug.DebugEvent.Exception) { | |
46 if (step++ > 0) return; | |
47 assertHasLineMark(/pause/, exec_state.frame(0)); | |
48 assertHasLineMark(/positions/, exec_state.frame(frame_number)); | |
49 var frame = exec_state.frame(frame_number); | |
50 codeSnippet = frame.sourceLineText(); | |
51 resultPositions = frame.stepInPositions(); | |
52 } | |
53 } catch (e) { | |
54 exception = e | |
55 } | |
56 | |
57 function assertHasLineMark(mark, frame) { | |
58 var line = frame.sourceLineText(); | |
59 if (!mark.exec(frame.sourceLineText())) { | |
60 throw new Error("Line " + line + " should contain mark " + mark); | |
61 } | |
62 } | |
63 } | |
64 | |
65 Debug.setListener(listener); | |
66 | |
67 var breakpointId; | |
68 if (line_number) breakpointId = Debug.setBreakPoint(fun, line_number); | |
69 | |
70 fun(); | |
71 | |
72 if (line_number) Debug.clearBreakPoint(breakpointId); | |
73 | |
74 Debug.setListener(null); | |
75 | |
76 assertTrue(!exception, exception); | |
77 | |
78 var expectedPositions = {}; | |
79 var markPattern = new RegExp("/\\*#\\*/", "g"); | |
80 | |
81 var matchResult; | |
82 while ( (matchResult = markPattern.exec(codeSnippet)) ) { | |
83 expectedPositions[matchResult.index] = true; | |
84 } | |
85 | |
86 print(codeSnippet); | |
87 | |
88 var decoratedResult = codeSnippet; | |
89 | |
90 function replaceStringRange(s, pos, substitute) { | |
91 return s.substring(0, pos) + substitute + | |
92 s.substring(pos + substitute.length); | |
93 } | |
94 | |
95 var markLength = 5; | |
96 var unexpectedPositionFound = false; | |
97 | |
98 for (var i = 0; i < resultPositions.length; i++) { | |
99 var col = resultPositions[i].position.column - markLength; | |
100 if (expectedPositions[col]) { | |
101 delete expectedPositions[col]; | |
102 decoratedResult = replaceStringRange(decoratedResult, col, "*YES*"); | |
103 } else { | |
104 decoratedResult = replaceStringRange(decoratedResult, col, "!BAD!"); | |
105 unexpectedPositionFound = true; | |
106 } | |
107 } | |
108 | |
109 print(decoratedResult); | |
110 | |
111 for (var n in expectedPositions) { | |
112 assertTrue(false, "Some positions are not reported: " + decoratedResult); | |
113 break; | |
114 } | |
115 assertFalse(unexpectedPositionFound, "Found unexpected position: " + | |
116 decoratedResult); | |
117 } | |
118 | |
119 function TestCaseWithDebugger(fun) { | |
120 TestCase(fun, 1); | |
121 } | |
122 | |
123 function TestCaseWithBreakpoint(fun, line_number, frame_number) { | |
124 TestCase(fun, frame_number, line_number); | |
125 } | |
126 | |
127 function TestCaseWithException(fun, frame_number) { | |
128 Debug.setBreakOnException(); | |
129 TestCase(fun, frame_number); | |
130 Debug.clearBreakOnException(); | |
131 } | |
132 | |
133 | |
134 // Test cases. | |
135 | |
136 // Step in position, when the function call that we are standing at is already | |
137 // being executed. | |
138 var fun = function() { | |
139 function g(p) { | |
140 throw String(p); /*pause*/ | |
141 } | |
142 try { | |
143 var res = [ g(1), /*#*/g(2) ]; /*positions*/ | |
144 } catch (e) { | |
145 } | |
146 }; | |
147 TestCaseWithBreakpoint(fun, 2, 1); | |
148 TestCaseWithException(fun, 1); | |
149 | |
150 | |
151 // Step in position, when the function call that we are standing at is raising | |
152 // an exception. | |
153 var fun = function() { | |
154 var o = { | |
155 g: function(p) { | |
156 throw p; | |
157 } | |
158 }; | |
159 try { | |
160 var res = [ /*#*/f(1), /*#*/g(2) ]; /*pause, positions*/ | |
161 } catch (e) { | |
162 } | |
163 }; | |
164 TestCaseWithException(fun, 0); | |
165 | |
166 | |
167 // Step-in position, when already paused almost on the first call site. | |
168 var fun = function() { | |
169 function g(p) { | |
170 throw p; | |
171 } | |
172 try { | |
173 var res = [ /*#*/g(Math.rand), /*#*/g(2) ]; /*pause, positions*/ | |
174 } catch (e) { | |
175 } | |
176 }; | |
177 TestCaseWithBreakpoint(fun, 5, 0); | |
178 | |
179 // Step-in position, when already paused on the first call site. | |
180 var fun = function() { | |
181 function g() { | |
182 throw "Debug"; | |
183 } | |
184 try { | |
185 var res = [ /*#*/g(), /*#*/g() ]; /*pause, positions*/ | |
186 } catch (e) { | |
187 } | |
188 }; | |
189 TestCaseWithBreakpoint(fun, 5, 0); | |
190 | |
191 | |
192 // Method calls. | |
193 var fun = function() { | |
194 var data = { | |
195 a: function() {} | |
196 }; | |
197 var res = [ DebuggerStatement(), data./*#*/a(), data[/*#*/String("a")]/*#*/(),
data["a"]/*#*/(), data.a, data["a"] ]; /*positions*/ | |
198 }; | |
199 TestCaseWithDebugger(fun); | |
200 | |
201 // Function call on a value. | |
202 var fun = function() { | |
203 function g(p) { | |
204 return g; | |
205 } | |
206 var res = [ DebuggerStatement(), /*#*/g(2), /*#*/g(2)/*#*/(3), /*#*/g(0)/*#*/(
0)/*#*/(g) ]; /*positions*/ | |
207 }; | |
208 TestCaseWithDebugger(fun); | |
209 | |
210 // Local function call, closure function call, | |
211 // local function construction call. | |
212 var fun = (function(p) { | |
213 return function() { | |
214 function f(a, b) { | |
215 } | |
216 var res = /*#*/f(DebuggerStatement(), /*#*/p(/*#*/new f())); /*positions*/ | |
217 }; | |
218 })(Object); | |
219 TestCaseWithDebugger(fun); | |
220 | |
221 // Global function, global object construction, calls before pause point. | |
222 var fun = (function(p) { | |
223 return function() { | |
224 var res = [ Math.abs(new Object()), DebuggerStatement(), Math./*#*/abs(4), /
*#*/new Object()./*#*/toString() ]; /*positions*/ | |
225 }; | |
226 })(Object); | |
227 TestCaseWithDebugger(fun); | |
OLD | NEW |