|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 /** |
|
5 * Bug 727429: Test the debugger watch expressions. |
|
6 */ |
|
7 |
|
8 const TAB_URL = EXAMPLE_URL + "doc_watch-expressions.html"; |
|
9 |
|
10 function test() { |
|
11 // Debug test slaves are a bit slow at this test. |
|
12 requestLongerTimeout(2); |
|
13 |
|
14 let gTab, gDebuggee, gPanel, gDebugger; |
|
15 let gWatch, gVariables; |
|
16 |
|
17 initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { |
|
18 gTab = aTab; |
|
19 gDebuggee = aDebuggee; |
|
20 gPanel = aPanel; |
|
21 gDebugger = gPanel.panelWin; |
|
22 gWatch = gDebugger.DebuggerView.WatchExpressions; |
|
23 gVariables = gDebugger.DebuggerView.Variables; |
|
24 |
|
25 gDebugger.DebuggerView.toggleInstrumentsPane({ visible: true, animated: false }); |
|
26 |
|
27 waitForSourceShown(gPanel, ".html", 1) |
|
28 .then(() => addExpressions()) |
|
29 .then(() => performTest()) |
|
30 .then(() => finishTest()) |
|
31 .then(() => closeDebuggerAndFinish(gPanel)) |
|
32 .then(null, aError => { |
|
33 ok(false, "Got an error: " + aError.message + "\n" + aError.stack); |
|
34 }); |
|
35 }); |
|
36 |
|
37 function addExpressions() { |
|
38 gWatch.addExpression("'a'"); |
|
39 gWatch.addExpression("\"a\""); |
|
40 gWatch.addExpression("'a\"\"'"); |
|
41 gWatch.addExpression("\"a''\""); |
|
42 gWatch.addExpression("?"); |
|
43 gWatch.addExpression("a"); |
|
44 gWatch.addExpression("this"); |
|
45 gWatch.addExpression("this.canada"); |
|
46 gWatch.addExpression("[1, 2, 3]"); |
|
47 gWatch.addExpression("x = [1, 2, 3]"); |
|
48 gWatch.addExpression("y = [1, 2, 3]; y.test = 4"); |
|
49 gWatch.addExpression("z = [1, 2, 3]; z.test = 4; z"); |
|
50 gWatch.addExpression("t = [1, 2, 3]; t.test = 4; !t"); |
|
51 gWatch.addExpression("arguments[0]"); |
|
52 gWatch.addExpression("encodeURI(\"\\\")"); |
|
53 gWatch.addExpression("decodeURI(\"\\\")"); |
|
54 gWatch.addExpression("decodeURIComponent(\"%\")"); |
|
55 gWatch.addExpression("//"); |
|
56 gWatch.addExpression("// 42"); |
|
57 gWatch.addExpression("{}.foo"); |
|
58 gWatch.addExpression("{}.foo()"); |
|
59 gWatch.addExpression("({}).foo()"); |
|
60 gWatch.addExpression("new Array(-1)"); |
|
61 gWatch.addExpression("4.2.toExponential(-4.2)"); |
|
62 gWatch.addExpression("throw new Error(\"bazinga\")"); |
|
63 gWatch.addExpression("({ get error() { throw new Error(\"bazinga\") } }).error"); |
|
64 gWatch.addExpression("throw { get name() { throw \"bazinga\" } }"); |
|
65 } |
|
66 |
|
67 function performTest() { |
|
68 let deferred = promise.defer(); |
|
69 |
|
70 is(gDebugger.document.querySelectorAll(".dbg-expression[hidden=true]").length, 0, |
|
71 "There should be 0 hidden nodes in the watch expressions container"); |
|
72 is(gDebugger.document.querySelectorAll(".dbg-expression:not([hidden=true])").length, 27, |
|
73 "There should be 27 visible nodes in the watch expressions container"); |
|
74 |
|
75 test1(function() { |
|
76 test2(function() { |
|
77 test3(function() { |
|
78 test4(function() { |
|
79 test5(function() { |
|
80 test6(function() { |
|
81 test7(function() { |
|
82 test8(function() { |
|
83 test9(function() { |
|
84 deferred.resolve(); |
|
85 }); |
|
86 }); |
|
87 }); |
|
88 }); |
|
89 }); |
|
90 }); |
|
91 }); |
|
92 }); |
|
93 }); |
|
94 |
|
95 return deferred.promise; |
|
96 } |
|
97 |
|
98 function finishTest() { |
|
99 is(gDebugger.document.querySelectorAll(".dbg-expression[hidden=true]").length, 0, |
|
100 "There should be 0 hidden nodes in the watch expressions container"); |
|
101 is(gDebugger.document.querySelectorAll(".dbg-expression:not([hidden=true])").length, 27, |
|
102 "There should be 27 visible nodes in the watch expressions container"); |
|
103 } |
|
104 |
|
105 function test1(aCallback) { |
|
106 gDebugger.once(gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS, () => { |
|
107 checkWatchExpressions(26, { |
|
108 a: "ReferenceError: a is not defined", |
|
109 this: { type: "object", class: "Object" }, |
|
110 prop: { type: "object", class: "String" }, |
|
111 args: { type: "undefined" } |
|
112 }); |
|
113 aCallback(); |
|
114 }); |
|
115 |
|
116 gDebuggee.test(); |
|
117 } |
|
118 |
|
119 function test2(aCallback) { |
|
120 gDebugger.once(gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS, () => { |
|
121 checkWatchExpressions(26, { |
|
122 a: { type: "undefined" }, |
|
123 this: { type: "object", class: "Window" }, |
|
124 prop: { type: "undefined" }, |
|
125 args: "sensational" |
|
126 }); |
|
127 aCallback(); |
|
128 }); |
|
129 |
|
130 EventUtils.sendMouseEvent({ type: "mousedown" }, |
|
131 gDebugger.document.getElementById("resume"), |
|
132 gDebugger); |
|
133 } |
|
134 |
|
135 function test3(aCallback) { |
|
136 gDebugger.once(gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS, () => { |
|
137 checkWatchExpressions(26, { |
|
138 a: { type: "object", class: "Object" }, |
|
139 this: { type: "object", class: "Window" }, |
|
140 prop: { type: "undefined" }, |
|
141 args: "sensational" |
|
142 }); |
|
143 aCallback(); |
|
144 }); |
|
145 |
|
146 EventUtils.sendMouseEvent({ type: "mousedown" }, |
|
147 gDebugger.document.getElementById("resume"), |
|
148 gDebugger); |
|
149 } |
|
150 |
|
151 function test4(aCallback) { |
|
152 gDebugger.once(gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS, () => { |
|
153 checkWatchExpressions(27, { |
|
154 a: 5, |
|
155 this: { type: "object", class: "Window" }, |
|
156 prop: { type: "undefined" }, |
|
157 args: "sensational" |
|
158 }); |
|
159 aCallback(); |
|
160 }); |
|
161 |
|
162 gWatch.addExpression("a = 5"); |
|
163 EventUtils.sendKey("RETURN", gDebugger); |
|
164 } |
|
165 |
|
166 function test5(aCallback) { |
|
167 gDebugger.once(gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS, () => { |
|
168 checkWatchExpressions(27, { |
|
169 a: 5, |
|
170 this: { type: "object", class: "Window" }, |
|
171 prop: { type: "undefined" }, |
|
172 args: "sensational" |
|
173 }); |
|
174 aCallback(); |
|
175 }); |
|
176 |
|
177 gWatch.addExpression("encodeURI(\"\\\")"); |
|
178 EventUtils.sendKey("RETURN", gDebugger); |
|
179 } |
|
180 |
|
181 function test6(aCallback) { |
|
182 gDebugger.once(gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS, () => { |
|
183 checkWatchExpressions(27, { |
|
184 a: 5, |
|
185 this: { type: "object", class: "Window" }, |
|
186 prop: { type: "undefined" }, |
|
187 args: "sensational" |
|
188 }); |
|
189 aCallback(); |
|
190 }) |
|
191 |
|
192 gWatch.addExpression("decodeURI(\"\\\")"); |
|
193 EventUtils.sendKey("RETURN", gDebugger); |
|
194 } |
|
195 |
|
196 function test7(aCallback) { |
|
197 gDebugger.once(gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS, () => { |
|
198 checkWatchExpressions(27, { |
|
199 a: 5, |
|
200 this: { type: "object", class: "Window" }, |
|
201 prop: { type: "undefined" }, |
|
202 args: "sensational" |
|
203 }); |
|
204 aCallback(); |
|
205 }); |
|
206 |
|
207 gWatch.addExpression("?"); |
|
208 EventUtils.sendKey("RETURN", gDebugger); |
|
209 } |
|
210 |
|
211 function test8(aCallback) { |
|
212 gDebugger.once(gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS, () => { |
|
213 checkWatchExpressions(27, { |
|
214 a: 5, |
|
215 this: { type: "object", class: "Window" }, |
|
216 prop: { type: "undefined" }, |
|
217 args: "sensational" |
|
218 }); |
|
219 aCallback(); |
|
220 }); |
|
221 |
|
222 gWatch.addExpression("a"); |
|
223 EventUtils.sendKey("RETURN", gDebugger); |
|
224 } |
|
225 |
|
226 function test9(aCallback) { |
|
227 gDebugger.once(gDebugger.EVENTS.AFTER_FRAMES_CLEARED, () => { |
|
228 aCallback(); |
|
229 }); |
|
230 |
|
231 EventUtils.sendMouseEvent({ type: "mousedown" }, |
|
232 gDebugger.document.getElementById("resume"), |
|
233 gDebugger); |
|
234 } |
|
235 |
|
236 function checkWatchExpressions(aTotal, aExpectedExpressions) { |
|
237 let { |
|
238 a: expected_a, |
|
239 this: expected_this, |
|
240 prop: expected_prop, |
|
241 args: expected_args |
|
242 } = aExpectedExpressions; |
|
243 |
|
244 is(gDebugger.document.querySelectorAll(".dbg-expression[hidden=true]").length, aTotal, |
|
245 "There should be " + aTotal + " hidden nodes in the watch expressions container."); |
|
246 is(gDebugger.document.querySelectorAll(".dbg-expression:not([hidden=true])").length, 0, |
|
247 "There should be 0 visible nodes in the watch expressions container."); |
|
248 |
|
249 let label = gDebugger.L10N.getStr("watchExpressionsScopeLabel"); |
|
250 let scope = gVariables._currHierarchy.get(label); |
|
251 |
|
252 ok(scope, "There should be a wach expressions scope in the variables view."); |
|
253 is(scope._store.size, aTotal, "There should be " + aTotal + " evaluations availalble."); |
|
254 |
|
255 let w1 = scope.get("'a'"); |
|
256 let w2 = scope.get("\"a\""); |
|
257 let w3 = scope.get("'a\"\"'"); |
|
258 let w4 = scope.get("\"a''\""); |
|
259 let w5 = scope.get("?"); |
|
260 let w6 = scope.get("a"); |
|
261 let w7 = scope.get("this"); |
|
262 let w8 = scope.get("this.canada"); |
|
263 let w9 = scope.get("[1, 2, 3]"); |
|
264 let w10 = scope.get("x = [1, 2, 3]"); |
|
265 let w11 = scope.get("y = [1, 2, 3]; y.test = 4"); |
|
266 let w12 = scope.get("z = [1, 2, 3]; z.test = 4; z"); |
|
267 let w13 = scope.get("t = [1, 2, 3]; t.test = 4; !t"); |
|
268 let w14 = scope.get("arguments[0]"); |
|
269 let w15 = scope.get("encodeURI(\"\\\")"); |
|
270 let w16 = scope.get("decodeURI(\"\\\")"); |
|
271 let w17 = scope.get("decodeURIComponent(\"%\")"); |
|
272 let w18 = scope.get("//"); |
|
273 let w19 = scope.get("// 42"); |
|
274 let w20 = scope.get("{}.foo"); |
|
275 let w21 = scope.get("{}.foo()"); |
|
276 let w22 = scope.get("({}).foo()"); |
|
277 let w23 = scope.get("new Array(-1)"); |
|
278 let w24 = scope.get("4.2.toExponential(-4.2)"); |
|
279 let w25 = scope.get("throw new Error(\"bazinga\")"); |
|
280 let w26 = scope.get("({ get error() { throw new Error(\"bazinga\") } }).error"); |
|
281 let w27 = scope.get("throw { get name() { throw \"bazinga\" } }"); |
|
282 |
|
283 ok(w1, "The first watch expression should be present in the scope."); |
|
284 ok(w2, "The second watch expression should be present in the scope."); |
|
285 ok(w3, "The third watch expression should be present in the scope."); |
|
286 ok(w4, "The fourth watch expression should be present in the scope."); |
|
287 ok(w5, "The fifth watch expression should be present in the scope."); |
|
288 ok(w6, "The sixth watch expression should be present in the scope."); |
|
289 ok(w7, "The seventh watch expression should be present in the scope."); |
|
290 ok(w8, "The eight watch expression should be present in the scope."); |
|
291 ok(w9, "The ninth watch expression should be present in the scope."); |
|
292 ok(w10, "The tenth watch expression should be present in the scope."); |
|
293 ok(w11, "The eleventh watch expression should be present in the scope."); |
|
294 ok(w12, "The twelfth watch expression should be present in the scope."); |
|
295 ok(w13, "The 13th watch expression should be present in the scope."); |
|
296 ok(w14, "The 14th watch expression should be present in the scope."); |
|
297 ok(w15, "The 15th watch expression should be present in the scope."); |
|
298 ok(w16, "The 16th watch expression should be present in the scope."); |
|
299 ok(w17, "The 17th watch expression should be present in the scope."); |
|
300 ok(w18, "The 18th watch expression should be present in the scope."); |
|
301 ok(w19, "The 19th watch expression should be present in the scope."); |
|
302 ok(w20, "The 20th watch expression should be present in the scope."); |
|
303 ok(w21, "The 21st watch expression should be present in the scope."); |
|
304 ok(w22, "The 22nd watch expression should be present in the scope."); |
|
305 ok(w23, "The 23nd watch expression should be present in the scope."); |
|
306 ok(w24, "The 24th watch expression should be present in the scope."); |
|
307 ok(w25, "The 25th watch expression should be present in the scope."); |
|
308 ok(w26, "The 26th watch expression should be present in the scope."); |
|
309 ok(!w27, "The 27th watch expression should not be present in the scope."); |
|
310 |
|
311 is(w1.value, "a", "The first value is correct."); |
|
312 is(w2.value, "a", "The second value is correct."); |
|
313 is(w3.value, "a\"\"", "The third value is correct."); |
|
314 is(w4.value, "a''", "The fourth value is correct."); |
|
315 is(w5.value, "SyntaxError: syntax error", "The fifth value is correct."); |
|
316 |
|
317 if (typeof expected_a == "object") { |
|
318 is(w6.value.type, expected_a.type, "The sixth value type is correct."); |
|
319 is(w6.value.class, expected_a.class, "The sixth value class is correct."); |
|
320 } else { |
|
321 is(w6.value, expected_a, "The sixth value is correct."); |
|
322 } |
|
323 |
|
324 if (typeof expected_this == "object") { |
|
325 is(w7.value.type, expected_this.type, "The seventh value type is correct."); |
|
326 is(w7.value.class, expected_this.class, "The seventh value class is correct."); |
|
327 } else { |
|
328 is(w7.value, expected_this, "The seventh value is correct."); |
|
329 } |
|
330 |
|
331 if (typeof expected_prop == "object") { |
|
332 is(w8.value.type, expected_prop.type, "The eighth value type is correct."); |
|
333 is(w8.value.class, expected_prop.class, "The eighth value class is correct."); |
|
334 } else { |
|
335 is(w8.value, expected_prop, "The eighth value is correct."); |
|
336 } |
|
337 |
|
338 is(w9.value.type, "object", "The ninth value type is correct."); |
|
339 is(w9.value.class, "Array", "The ninth value class is correct."); |
|
340 is(w10.value.type, "object", "The tenth value type is correct."); |
|
341 is(w10.value.class, "Array", "The tenth value class is correct."); |
|
342 is(w11.value, "4", "The eleventh value is correct."); |
|
343 is(w12.value.type, "object", "The eleventh value type is correct."); |
|
344 is(w12.value.class, "Array", "The twelfth value class is correct."); |
|
345 is(w13.value, false, "The 13th value is correct."); |
|
346 |
|
347 if (typeof expected_args == "object") { |
|
348 is(w14.value.type, expected_args.type, "The 14th value type is correct."); |
|
349 is(w14.value.class, expected_args.class, "The 14th value class is correct."); |
|
350 } else { |
|
351 is(w14.value, expected_args, "The 14th value is correct."); |
|
352 } |
|
353 |
|
354 is(w15.value, "SyntaxError: unterminated string literal", "The 15th value is correct."); |
|
355 is(w16.value, "SyntaxError: unterminated string literal", "The 16th value is correct."); |
|
356 is(w17.value, "URIError: malformed URI sequence", "The 17th value is correct."); |
|
357 |
|
358 is(w18.value.type, "undefined", "The 18th value type is correct."); |
|
359 is(w18.value.class, undefined, "The 18th value class is correct."); |
|
360 |
|
361 is(w19.value.type, "undefined", "The 19th value type is correct."); |
|
362 is(w19.value.class, undefined, "The 19th value class is correct."); |
|
363 |
|
364 is(w20.value, "SyntaxError: syntax error", "The 20th value is correct."); |
|
365 is(w21.value, "SyntaxError: syntax error", "The 21th value is correct."); |
|
366 is(w22.value, "TypeError: (intermediate value).foo is not a function", "The 22th value is correct."); |
|
367 is(w23.value, "RangeError: invalid array length", "The 23th value is correct."); |
|
368 is(w24.value, "RangeError: precision -4 out of range", "The 24th value is correct."); |
|
369 is(w25.value, "Error: bazinga", "The 25th value is correct."); |
|
370 is(w26.value, "Error: bazinga", "The 26th value is correct."); |
|
371 } |
|
372 } |