OLD | NEW |
| (Empty) |
1 // Copyright 2011 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 --allow-natives-syntax --noanalyze-environment
-liveness | |
29 // The functions used for testing backtraces. They are at the top to make the | |
30 // testing of source line/column easier. | |
31 | |
32 // Get the Debug object exposed from the debug context global object. | |
33 var Debug = debug.Debug; | |
34 | |
35 var test_name; | |
36 var listener_delegate; | |
37 var listener_called; | |
38 var exception; | |
39 var begin_test_count = 0; | |
40 var end_test_count = 0; | |
41 var break_count = 0; | |
42 | |
43 | |
44 // Debug event listener which delegates. | |
45 function listener(event, exec_state, event_data, data) { | |
46 try { | |
47 if (event == Debug.DebugEvent.Break) { | |
48 break_count++; | |
49 listener_called = true; | |
50 listener_delegate(exec_state); | |
51 } | |
52 } catch (e) { | |
53 exception = e; | |
54 } | |
55 } | |
56 | |
57 // Add the debug event listener. | |
58 Debug.setListener(listener); | |
59 | |
60 | |
61 // Initialize for a new test. | |
62 function BeginTest(name) { | |
63 test_name = name; | |
64 listener_delegate = null; | |
65 listener_called = false; | |
66 exception = null; | |
67 begin_test_count++; | |
68 } | |
69 | |
70 | |
71 // Check result of a test. | |
72 function EndTest() { | |
73 assertTrue(listener_called, "listerner not called for " + test_name); | |
74 assertNull(exception, test_name + " / " + exception); | |
75 end_test_count++; | |
76 } | |
77 | |
78 | |
79 // Check that two scope are the same. | |
80 function assertScopeMirrorEquals(scope1, scope2) { | |
81 assertEquals(scope1.scopeType(), scope2.scopeType()); | |
82 assertEquals(scope1.frameIndex(), scope2.frameIndex()); | |
83 assertEquals(scope1.scopeIndex(), scope2.scopeIndex()); | |
84 assertPropertiesEqual(scope1.scopeObject().value(), scope2.scopeObject().value
()); | |
85 } | |
86 | |
87 function CheckFastAllScopes(scopes, exec_state) | |
88 { | |
89 var fast_all_scopes = exec_state.frame().allScopes(true); | |
90 var length = fast_all_scopes.length; | |
91 assertTrue(scopes.length >= length); | |
92 for (var i = 0; i < scopes.length && i < length; i++) { | |
93 var scope = fast_all_scopes[length - i - 1]; | |
94 assertTrue(scope.isScope()); | |
95 assertEquals(scopes[scopes.length - i - 1], scope.scopeType()); | |
96 } | |
97 } | |
98 | |
99 | |
100 // Check that the scope chain contains the expected types of scopes. | |
101 function CheckScopeChain(scopes, exec_state) { | |
102 var all_scopes = exec_state.frame().allScopes(); | |
103 assertEquals(scopes.length, exec_state.frame().scopeCount()); | |
104 assertEquals(scopes.length, all_scopes.length, "FrameMirror.allScopes length")
; | |
105 for (var i = 0; i < scopes.length; i++) { | |
106 var scope = exec_state.frame().scope(i); | |
107 assertTrue(scope.isScope()); | |
108 assertEquals(scopes[i], scope.scopeType()); | |
109 assertScopeMirrorEquals(all_scopes[i], scope); | |
110 | |
111 // Check the global object when hitting the global scope. | |
112 if (scopes[i] == debug.ScopeType.Global) { | |
113 // Objects don't have same class (one is "global", other is "Object", | |
114 // so just check the properties directly. | |
115 assertPropertiesEqual(this, scope.scopeObject().value()); | |
116 } | |
117 } | |
118 CheckFastAllScopes(scopes, exec_state); | |
119 } | |
120 | |
121 | |
122 // Check that the scope chain contains the expected names of scopes. | |
123 function CheckScopeChainNames(names, exec_state) { | |
124 var all_scopes = exec_state.frame().allScopes(); | |
125 assertEquals(names.length, all_scopes.length, "FrameMirror.allScopes length"); | |
126 for (var i = 0; i < names.length; i++) { | |
127 var scope = exec_state.frame().scope(i); | |
128 assertTrue(scope.isScope()); | |
129 assertEquals(names[i], scope.details().name()) | |
130 } | |
131 } | |
132 | |
133 | |
134 // Check that the scope contains at least minimum_content. For functions just | |
135 // check that there is a function. | |
136 function CheckScopeContent(minimum_content, number, exec_state) { | |
137 var scope = exec_state.frame().scope(number); | |
138 var minimum_count = 0; | |
139 for (var p in minimum_content) { | |
140 var property_mirror = scope.scopeObject().property(p); | |
141 assertFalse(property_mirror.isUndefined(), | |
142 'property ' + p + ' not found in scope'); | |
143 if (typeof(minimum_content[p]) === 'function') { | |
144 assertTrue(property_mirror.value().isFunction()); | |
145 } else { | |
146 assertEquals(minimum_content[p], property_mirror.value().value(), | |
147 'property ' + p + ' has unexpected value'); | |
148 } | |
149 minimum_count++; | |
150 } | |
151 | |
152 // 'arguments' and might be exposed in the local and closure scope. Just | |
153 // ignore this. | |
154 var scope_size = scope.scopeObject().properties().length; | |
155 if (!scope.scopeObject().property('arguments').isUndefined()) { | |
156 scope_size--; | |
157 } | |
158 // Ditto for 'this'. | |
159 if (!scope.scopeObject().property('this').isUndefined()) { | |
160 scope_size--; | |
161 } | |
162 // Temporary variables introduced by the parser have not been materialized. | |
163 assertTrue(scope.scopeObject().property('').isUndefined()); | |
164 | |
165 if (scope_size < minimum_count) { | |
166 print('Names found in scope:'); | |
167 var names = scope.scopeObject().propertyNames(); | |
168 for (var i = 0; i < names.length; i++) { | |
169 print(names[i]); | |
170 } | |
171 } | |
172 assertTrue(scope_size >= minimum_count); | |
173 } | |
174 | |
175 // Check that the scopes have positions as expected. | |
176 function CheckScopeChainPositions(positions, exec_state) { | |
177 var all_scopes = exec_state.frame().allScopes(); | |
178 assertEquals(positions.length, all_scopes.length, "FrameMirror.allScopes lengt
h"); | |
179 for (var i = 0; i < positions.length; i++) { | |
180 var scope = exec_state.frame().scope(i); | |
181 assertTrue(scope.isScope()); | |
182 var position = positions[i]; | |
183 if (!position) | |
184 continue; | |
185 | |
186 assertEquals(position.start, scope.details().startPosition()) | |
187 assertEquals(position.end, scope.details().endPosition()) | |
188 } | |
189 } | |
190 | |
191 // Simple empty local scope. | |
192 BeginTest("Local 1"); | |
193 | |
194 function local_1() { | |
195 debugger; | |
196 } | |
197 | |
198 listener_delegate = function(exec_state) { | |
199 CheckScopeChain([debug.ScopeType.Local, | |
200 debug.ScopeType.Script, | |
201 debug.ScopeType.Global], exec_state); | |
202 CheckScopeContent({}, 0, exec_state); | |
203 }; | |
204 local_1(); | |
205 EndTest(); | |
206 | |
207 | |
208 // Local scope with a parameter. | |
209 BeginTest("Local 2"); | |
210 | |
211 function local_2(a) { | |
212 debugger; | |
213 } | |
214 | |
215 listener_delegate = function(exec_state) { | |
216 CheckScopeChain([debug.ScopeType.Local, | |
217 debug.ScopeType.Script, | |
218 debug.ScopeType.Global], exec_state); | |
219 CheckScopeContent({a:1}, 0, exec_state); | |
220 }; | |
221 local_2(1); | |
222 EndTest(); | |
223 | |
224 | |
225 // Local scope with a parameter and a local variable. | |
226 BeginTest("Local 3"); | |
227 | |
228 function local_3(a) { | |
229 var x = 3; | |
230 debugger; | |
231 } | |
232 | |
233 listener_delegate = function(exec_state) { | |
234 CheckScopeChain([debug.ScopeType.Local, | |
235 debug.ScopeType.Script, | |
236 debug.ScopeType.Global], exec_state); | |
237 CheckScopeContent({a:1,x:3}, 0, exec_state); | |
238 }; | |
239 local_3(1); | |
240 EndTest(); | |
241 | |
242 | |
243 // Local scope with parameters and local variables. | |
244 BeginTest("Local 4"); | |
245 | |
246 function local_4(a, b) { | |
247 var x = 3; | |
248 var y = 4; | |
249 debugger; | |
250 } | |
251 | |
252 listener_delegate = function(exec_state) { | |
253 CheckScopeChain([debug.ScopeType.Local, | |
254 debug.ScopeType.Script, | |
255 debug.ScopeType.Global], exec_state); | |
256 CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state); | |
257 }; | |
258 local_4(1, 2); | |
259 EndTest(); | |
260 | |
261 | |
262 // Empty local scope with use of eval. | |
263 BeginTest("Local 5"); | |
264 | |
265 function local_5() { | |
266 eval(''); | |
267 debugger; | |
268 } | |
269 | |
270 listener_delegate = function(exec_state) { | |
271 CheckScopeChain([debug.ScopeType.Local, | |
272 debug.ScopeType.Script, | |
273 debug.ScopeType.Global], exec_state); | |
274 CheckScopeContent({}, 0, exec_state); | |
275 }; | |
276 local_5(); | |
277 EndTest(); | |
278 | |
279 | |
280 // Local introducing local variable using eval. | |
281 BeginTest("Local 6"); | |
282 | |
283 function local_6() { | |
284 eval('var i = 5'); | |
285 debugger; | |
286 } | |
287 | |
288 listener_delegate = function(exec_state) { | |
289 CheckScopeChain([debug.ScopeType.Local, | |
290 debug.ScopeType.Script, | |
291 debug.ScopeType.Global], exec_state); | |
292 CheckScopeContent({i:5}, 0, exec_state); | |
293 }; | |
294 local_6(); | |
295 EndTest(); | |
296 | |
297 | |
298 // Local scope with parameters, local variables and local variable introduced | |
299 // using eval. | |
300 BeginTest("Local 7"); | |
301 | |
302 function local_7(a, b) { | |
303 var x = 3; | |
304 var y = 4; | |
305 eval('var i = 5'); | |
306 eval('var j = 6'); | |
307 debugger; | |
308 } | |
309 | |
310 listener_delegate = function(exec_state) { | |
311 CheckScopeChain([debug.ScopeType.Local, | |
312 debug.ScopeType.Script, | |
313 debug.ScopeType.Global], exec_state); | |
314 CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 0, exec_state); | |
315 }; | |
316 local_7(1, 2); | |
317 EndTest(); | |
318 | |
319 | |
320 // Single empty with block. | |
321 BeginTest("With 1"); | |
322 | |
323 function with_1() { | |
324 with({}) { | |
325 debugger; | |
326 } | |
327 } | |
328 | |
329 listener_delegate = function(exec_state) { | |
330 CheckScopeChain([debug.ScopeType.With, | |
331 debug.ScopeType.Local, | |
332 debug.ScopeType.Script, | |
333 debug.ScopeType.Global], exec_state); | |
334 CheckScopeContent({}, 0, exec_state); | |
335 }; | |
336 with_1(); | |
337 EndTest(); | |
338 | |
339 | |
340 // Nested empty with blocks. | |
341 BeginTest("With 2"); | |
342 | |
343 function with_2() { | |
344 with({}) { | |
345 with({}) { | |
346 debugger; | |
347 } | |
348 } | |
349 } | |
350 | |
351 listener_delegate = function(exec_state) { | |
352 CheckScopeChain([debug.ScopeType.With, | |
353 debug.ScopeType.With, | |
354 debug.ScopeType.Local, | |
355 debug.ScopeType.Script, | |
356 debug.ScopeType.Global], exec_state); | |
357 CheckScopeContent({}, 0, exec_state); | |
358 CheckScopeContent({}, 1, exec_state); | |
359 }; | |
360 with_2(); | |
361 EndTest(); | |
362 | |
363 | |
364 // With block using an in-place object literal. | |
365 BeginTest("With 3"); | |
366 | |
367 function with_3() { | |
368 with({a:1,b:2}) { | |
369 debugger; | |
370 } | |
371 } | |
372 | |
373 listener_delegate = function(exec_state) { | |
374 CheckScopeChain([debug.ScopeType.With, | |
375 debug.ScopeType.Local, | |
376 debug.ScopeType.Script, | |
377 debug.ScopeType.Global], exec_state); | |
378 CheckScopeContent({a:1,b:2}, 0, exec_state); | |
379 }; | |
380 with_3(); | |
381 EndTest(); | |
382 | |
383 | |
384 // Nested with blocks using in-place object literals. | |
385 BeginTest("With 4"); | |
386 | |
387 function with_4() { | |
388 with({a:1,b:2}) { | |
389 with({a:2,b:1}) { | |
390 debugger; | |
391 } | |
392 } | |
393 } | |
394 | |
395 listener_delegate = function(exec_state) { | |
396 CheckScopeChain([debug.ScopeType.With, | |
397 debug.ScopeType.With, | |
398 debug.ScopeType.Local, | |
399 debug.ScopeType.Script, | |
400 debug.ScopeType.Global], exec_state); | |
401 CheckScopeContent({a:2,b:1}, 0, exec_state); | |
402 CheckScopeContent({a:1,b:2}, 1, exec_state); | |
403 }; | |
404 with_4(); | |
405 EndTest(); | |
406 | |
407 | |
408 // Nested with blocks using existing object. | |
409 BeginTest("With 5"); | |
410 | |
411 var with_object = {c:3,d:4}; | |
412 function with_5() { | |
413 with(with_object) { | |
414 with(with_object) { | |
415 debugger; | |
416 } | |
417 } | |
418 } | |
419 | |
420 listener_delegate = function(exec_state) { | |
421 CheckScopeChain([debug.ScopeType.With, | |
422 debug.ScopeType.With, | |
423 debug.ScopeType.Local, | |
424 debug.ScopeType.Script, | |
425 debug.ScopeType.Global], exec_state); | |
426 CheckScopeContent(with_object, 0, exec_state); | |
427 CheckScopeContent(with_object, 1, exec_state); | |
428 assertEquals(exec_state.frame().scope(0).scopeObject(), | |
429 exec_state.frame().scope(1).scopeObject()); | |
430 assertEquals(with_object, exec_state.frame().scope(1).scopeObject().value()); | |
431 }; | |
432 with_5(); | |
433 EndTest(); | |
434 | |
435 | |
436 // Nested with blocks using existing object in global code. | |
437 BeginTest("With 6"); | |
438 listener_delegate = function(exec_state) { | |
439 CheckScopeChain([debug.ScopeType.With, | |
440 debug.ScopeType.With, | |
441 debug.ScopeType.Script, | |
442 debug.ScopeType.Global], exec_state); | |
443 CheckScopeContent(with_object, 0, exec_state); | |
444 CheckScopeContent(with_object, 1, exec_state); | |
445 assertEquals(exec_state.frame().scope(0).scopeObject(), | |
446 exec_state.frame().scope(1).scopeObject()); | |
447 assertEquals(with_object, exec_state.frame().scope(1).scopeObject().value()); | |
448 }; | |
449 | |
450 var with_object = {c:3,d:4}; | |
451 with(with_object) { | |
452 with(with_object) { | |
453 debugger; | |
454 } | |
455 } | |
456 EndTest(); | |
457 | |
458 | |
459 // With block in function that is marked for optimization while being executed. | |
460 BeginTest("With 7"); | |
461 | |
462 function with_7() { | |
463 with({}) { | |
464 %OptimizeFunctionOnNextCall(with_7); | |
465 debugger; | |
466 } | |
467 } | |
468 | |
469 listener_delegate = function(exec_state) { | |
470 CheckScopeChain([debug.ScopeType.With, | |
471 debug.ScopeType.Local, | |
472 debug.ScopeType.Script, | |
473 debug.ScopeType.Global], exec_state); | |
474 CheckScopeContent({}, 0, exec_state); | |
475 }; | |
476 with_7(); | |
477 EndTest(); | |
478 | |
479 | |
480 // Simple closure formed by returning an inner function referering the outer | |
481 // functions arguments. | |
482 BeginTest("Closure 1"); | |
483 | |
484 function closure_1(a) { | |
485 function f() { | |
486 debugger; | |
487 return a; | |
488 }; | |
489 return f; | |
490 } | |
491 | |
492 listener_delegate = function(exec_state) { | |
493 CheckScopeChain([debug.ScopeType.Local, | |
494 debug.ScopeType.Closure, | |
495 debug.ScopeType.Script, | |
496 debug.ScopeType.Global], exec_state); | |
497 CheckScopeContent({a:1}, 1, exec_state); | |
498 CheckScopeChainNames(["f", "closure_1", undefined, undefined], exec_state); | |
499 }; | |
500 closure_1(1)(); | |
501 EndTest(); | |
502 | |
503 | |
504 // Simple closure formed by returning an inner function referering the outer | |
505 // functions arguments. Due to VM optimizations parts of the actual closure is | |
506 // missing from the debugger information. | |
507 BeginTest("Closure 2"); | |
508 | |
509 function closure_2(a, b) { | |
510 var x = a + 2; | |
511 var y = b + 2; | |
512 function f() { | |
513 debugger; | |
514 return a + x; | |
515 }; | |
516 return f; | |
517 } | |
518 | |
519 listener_delegate = function(exec_state) { | |
520 CheckScopeChain([debug.ScopeType.Local, | |
521 debug.ScopeType.Closure, | |
522 debug.ScopeType.Script, | |
523 debug.ScopeType.Global], exec_state); | |
524 CheckScopeContent({a:1,x:3}, 1, exec_state); | |
525 CheckScopeChainNames(["f", "closure_2", undefined, undefined], exec_state); | |
526 }; | |
527 closure_2(1, 2)(); | |
528 EndTest(); | |
529 | |
530 | |
531 // Simple closure formed by returning an inner function referering the outer | |
532 // functions arguments. Using all arguments and locals from the outer function | |
533 // in the inner function makes these part of the debugger information on the | |
534 // closure. | |
535 BeginTest("Closure 3"); | |
536 | |
537 function closure_3(a, b) { | |
538 var x = a + 2; | |
539 var y = b + 2; | |
540 function f() { | |
541 debugger; | |
542 return a + b + x + y; | |
543 }; | |
544 return f; | |
545 } | |
546 | |
547 listener_delegate = function(exec_state) { | |
548 CheckScopeChain([debug.ScopeType.Local, | |
549 debug.ScopeType.Closure, | |
550 debug.ScopeType.Script, | |
551 debug.ScopeType.Global], exec_state); | |
552 CheckScopeContent({a:1,b:2,x:3,y:4}, 1, exec_state); | |
553 CheckScopeChainNames(["f", "closure_3", undefined, undefined], exec_state); | |
554 }; | |
555 closure_3(1, 2)(); | |
556 EndTest(); | |
557 | |
558 | |
559 | |
560 // Simple closure formed by returning an inner function referering the outer | |
561 // functions arguments. Using all arguments and locals from the outer function | |
562 // in the inner function makes these part of the debugger information on the | |
563 // closure. Use the inner function as well... | |
564 BeginTest("Closure 4"); | |
565 | |
566 function closure_4(a, b) { | |
567 var x = a + 2; | |
568 var y = b + 2; | |
569 function f() { | |
570 debugger; | |
571 if (f) { | |
572 return a + b + x + y; | |
573 } | |
574 }; | |
575 return f; | |
576 } | |
577 | |
578 listener_delegate = function(exec_state) { | |
579 CheckScopeChain([debug.ScopeType.Local, | |
580 debug.ScopeType.Closure, | |
581 debug.ScopeType.Script, | |
582 debug.ScopeType.Global], exec_state); | |
583 CheckScopeContent({a:1,b:2,x:3,y:4,f:function(){}}, 1, exec_state); | |
584 CheckScopeChainNames(["f", "closure_4", undefined, undefined], exec_state); | |
585 }; | |
586 closure_4(1, 2)(); | |
587 EndTest(); | |
588 | |
589 | |
590 | |
591 // Simple closure formed by returning an inner function referering the outer | |
592 // functions arguments. In the presence of eval all arguments and locals | |
593 // (including the inner function itself) from the outer function becomes part of | |
594 // the debugger infformation on the closure. | |
595 BeginTest("Closure 5"); | |
596 | |
597 function closure_5(a, b) { | |
598 var x = 3; | |
599 var y = 4; | |
600 function f() { | |
601 eval(''); | |
602 debugger; | |
603 return 1; | |
604 }; | |
605 return f; | |
606 } | |
607 | |
608 listener_delegate = function(exec_state) { | |
609 CheckScopeChain([debug.ScopeType.Local, | |
610 debug.ScopeType.Closure, | |
611 debug.ScopeType.Script, | |
612 debug.ScopeType.Global], exec_state); | |
613 CheckScopeContent({a:1,b:2,x:3,y:4,f:function(){}}, 1, exec_state); | |
614 CheckScopeChainNames(["f", "closure_5", undefined, undefined], exec_state) | |
615 }; | |
616 closure_5(1, 2)(); | |
617 EndTest(); | |
618 | |
619 | |
620 // Two closures. Due to optimizations only the parts actually used are provided | |
621 // through the debugger information. | |
622 BeginTest("Closure 6"); | |
623 function closure_6(a, b) { | |
624 function f(a, b) { | |
625 var x = 3; | |
626 var y = 4; | |
627 return function() { | |
628 var x = 3; | |
629 var y = 4; | |
630 debugger; | |
631 some_global = a; | |
632 return f; | |
633 }; | |
634 } | |
635 return f(a, b); | |
636 } | |
637 | |
638 listener_delegate = function(exec_state) { | |
639 CheckScopeChain([debug.ScopeType.Local, | |
640 debug.ScopeType.Closure, | |
641 debug.ScopeType.Closure, | |
642 debug.ScopeType.Script, | |
643 debug.ScopeType.Global], exec_state); | |
644 CheckScopeContent({a:1}, 1, exec_state); | |
645 CheckScopeContent({f:function(){}}, 2, exec_state); | |
646 CheckScopeChainNames([undefined, "f", "closure_6", undefined, undefined], | |
647 exec_state); | |
648 }; | |
649 closure_6(1, 2)(); | |
650 EndTest(); | |
651 | |
652 | |
653 // Two closures. In the presence of eval all information is provided as the | |
654 // compiler cannot determine which parts are used. | |
655 BeginTest("Closure 7"); | |
656 function closure_7(a, b) { | |
657 var x = 3; | |
658 var y = 4; | |
659 eval('var i = 5'); | |
660 eval('var j = 6'); | |
661 function f(a, b) { | |
662 var x = 3; | |
663 var y = 4; | |
664 eval('var i = 5'); | |
665 eval('var j = 6'); | |
666 return function() { | |
667 debugger; | |
668 some_global = a; | |
669 return f; | |
670 }; | |
671 } | |
672 return f(a, b); | |
673 } | |
674 | |
675 listener_delegate = function(exec_state) { | |
676 CheckScopeChain([debug.ScopeType.Local, | |
677 debug.ScopeType.Closure, | |
678 debug.ScopeType.Closure, | |
679 debug.ScopeType.Script, | |
680 debug.ScopeType.Global], exec_state); | |
681 CheckScopeContent({}, 0, exec_state); | |
682 CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 1, exec_state); | |
683 CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6,f:function(){}}, 2, exec_state); | |
684 CheckScopeChainNames([undefined, "f", "closure_7", undefined, undefined], | |
685 exec_state); | |
686 }; | |
687 closure_7(1, 2)(); | |
688 EndTest(); | |
689 | |
690 | |
691 // Closure that may be optimized out. | |
692 BeginTest("Closure 8"); | |
693 function closure_8() { | |
694 (function inner(x) { | |
695 debugger; | |
696 })(2); | |
697 } | |
698 | |
699 listener_delegate = function(exec_state) { | |
700 CheckScopeChain([debug.ScopeType.Local, | |
701 debug.ScopeType.Script, | |
702 debug.ScopeType.Global], exec_state); | |
703 CheckScopeContent({x: 2}, 0, exec_state); | |
704 CheckScopeChainNames(["inner", undefined, undefined], exec_state); | |
705 }; | |
706 closure_8(); | |
707 EndTest(); | |
708 | |
709 | |
710 BeginTest("Closure 9"); | |
711 function closure_9() { | |
712 eval("var y = 1;"); | |
713 eval("var z = 1;"); | |
714 (function inner(x) { | |
715 y++; | |
716 z++; | |
717 debugger; | |
718 })(2); | |
719 } | |
720 | |
721 listener_delegate = function(exec_state) { | |
722 CheckScopeChain([debug.ScopeType.Local, | |
723 debug.ScopeType.Closure, | |
724 debug.ScopeType.Script, | |
725 debug.ScopeType.Global], exec_state); | |
726 CheckScopeChainNames(["inner", "closure_9", undefined, undefined], | |
727 exec_state); | |
728 }; | |
729 closure_9(); | |
730 EndTest(); | |
731 | |
732 | |
733 // Test a mixture of scopes. | |
734 BeginTest("The full monty"); | |
735 function the_full_monty(a, b) { | |
736 var x = 3; | |
737 var y = 4; | |
738 eval('var i = 5'); | |
739 eval('var j = 6'); | |
740 function f(a, b) { | |
741 var x = 9; | |
742 var y = 10; | |
743 eval('var i = 11'); | |
744 eval('var j = 12'); | |
745 with ({j:13}){ | |
746 return function() { | |
747 var x = 14; | |
748 with ({a:15}) { | |
749 with ({b:16}) { | |
750 debugger; | |
751 some_global = a; | |
752 return f; | |
753 } | |
754 } | |
755 }; | |
756 } | |
757 } | |
758 return f(a, b); | |
759 } | |
760 | |
761 listener_delegate = function(exec_state) { | |
762 CheckScopeChain([debug.ScopeType.With, | |
763 debug.ScopeType.With, | |
764 debug.ScopeType.Local, | |
765 debug.ScopeType.With, | |
766 debug.ScopeType.Closure, | |
767 debug.ScopeType.Closure, | |
768 debug.ScopeType.Script, | |
769 debug.ScopeType.Global], exec_state); | |
770 CheckScopeContent({b:16}, 0, exec_state); | |
771 CheckScopeContent({a:15}, 1, exec_state); | |
772 CheckScopeContent({x:14}, 2, exec_state); | |
773 CheckScopeContent({j:13}, 3, exec_state); | |
774 CheckScopeContent({a:1,b:2,x:9,y:10,i:11,j:12}, 4, exec_state); | |
775 CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6,f:function(){}}, 5, exec_state); | |
776 CheckScopeChainNames([undefined, undefined, undefined, "f", "f", | |
777 "the_full_monty", undefined, undefined], exec_state); | |
778 }; | |
779 the_full_monty(1, 2)(); | |
780 EndTest(); | |
781 | |
782 | |
783 BeginTest("Closure inside With 1"); | |
784 function closure_in_with_1() { | |
785 with({x:1}) { | |
786 (function inner(x) { | |
787 debugger; | |
788 })(2); | |
789 } | |
790 } | |
791 | |
792 listener_delegate = function(exec_state) { | |
793 CheckScopeChain([debug.ScopeType.Local, | |
794 debug.ScopeType.With, | |
795 debug.ScopeType.Script, | |
796 debug.ScopeType.Global], exec_state); | |
797 CheckScopeContent({x: 2}, 0, exec_state); | |
798 CheckScopeContent({x: 1}, 1, exec_state); | |
799 }; | |
800 closure_in_with_1(); | |
801 EndTest(); | |
802 | |
803 | |
804 BeginTest("Closure inside With 2"); | |
805 function closure_in_with_2() { | |
806 with({x:1}) { | |
807 (function inner(x) { | |
808 with({x:3}) { | |
809 debugger; | |
810 } | |
811 })(2); | |
812 } | |
813 } | |
814 | |
815 listener_delegate = function(exec_state) { | |
816 CheckScopeChain([debug.ScopeType.With, | |
817 debug.ScopeType.Local, | |
818 debug.ScopeType.With, | |
819 debug.ScopeType.Script, | |
820 debug.ScopeType.Global], exec_state); | |
821 CheckScopeContent({x: 3}, 0, exec_state); | |
822 CheckScopeContent({x: 2}, 1, exec_state); | |
823 CheckScopeContent({x: 1}, 2, exec_state); | |
824 CheckScopeChainNames(["inner", "inner", "closure_in_with_2", | |
825 undefined, undefined], exec_state); | |
826 }; | |
827 closure_in_with_2(); | |
828 EndTest(); | |
829 | |
830 | |
831 BeginTest("Closure inside With 3"); | |
832 function createClosure(a) { | |
833 var b = a + 1; | |
834 return function closure() { | |
835 var c = b; | |
836 (function inner(x) { | |
837 with({x:c}) { | |
838 debugger; | |
839 } | |
840 })(2); | |
841 }; | |
842 } | |
843 | |
844 function closure_in_with_3() { | |
845 var f = createClosure(0); | |
846 f(); | |
847 } | |
848 | |
849 listener_delegate = function(exec_state) { | |
850 CheckScopeChain([debug.ScopeType.With, | |
851 debug.ScopeType.Local, | |
852 debug.ScopeType.Closure, | |
853 debug.ScopeType.Closure, | |
854 debug.ScopeType.Script, | |
855 debug.ScopeType.Global], exec_state); | |
856 CheckScopeChainNames(["inner", "inner", "closure", "createClosure", | |
857 undefined, undefined], exec_state); | |
858 } | |
859 closure_in_with_3(); | |
860 EndTest(); | |
861 | |
862 | |
863 BeginTest("Closure inside With 4"); | |
864 listener_delegate = function(exec_state) { | |
865 CheckScopeChain([debug.ScopeType.Local, | |
866 debug.ScopeType.With, | |
867 debug.ScopeType.Script, | |
868 debug.ScopeType.Global], exec_state); | |
869 CheckScopeContent({x: 2}, 0, exec_state); | |
870 CheckScopeContent({x: 1}, 1, exec_state); | |
871 CheckScopeChainNames([undefined, undefined, undefined, undefined], | |
872 exec_state); | |
873 }; | |
874 | |
875 with({x:1}) { | |
876 (function(x) { | |
877 debugger; | |
878 })(2); | |
879 } | |
880 EndTest(); | |
881 | |
882 | |
883 // Test global scope. | |
884 BeginTest("Global"); | |
885 listener_delegate = function(exec_state) { | |
886 CheckScopeChain([debug.ScopeType.Script, debug.ScopeType.Global], | |
887 exec_state); | |
888 CheckScopeChainNames([undefined, undefined], exec_state); | |
889 }; | |
890 debugger; | |
891 EndTest(); | |
892 | |
893 | |
894 BeginTest("Catch block 1"); | |
895 function catch_block_1() { | |
896 try { | |
897 throw 'Exception'; | |
898 } catch (e) { | |
899 debugger; | |
900 } | |
901 }; | |
902 | |
903 | |
904 listener_delegate = function(exec_state) { | |
905 CheckScopeChain([debug.ScopeType.Catch, | |
906 debug.ScopeType.Local, | |
907 debug.ScopeType.Script, | |
908 debug.ScopeType.Global], exec_state); | |
909 CheckScopeContent({e:'Exception'}, 0, exec_state); | |
910 CheckScopeChainNames(["catch_block_1", "catch_block_1", | |
911 undefined, undefined], exec_state); | |
912 }; | |
913 catch_block_1(); | |
914 EndTest(); | |
915 | |
916 | |
917 BeginTest("Catch block 2"); | |
918 function catch_block_2() { | |
919 try { | |
920 throw 'Exception'; | |
921 } catch (e) { | |
922 with({n:10}) { | |
923 debugger; | |
924 } | |
925 } | |
926 }; | |
927 | |
928 | |
929 listener_delegate = function(exec_state) { | |
930 CheckScopeChain([debug.ScopeType.With, | |
931 debug.ScopeType.Catch, | |
932 debug.ScopeType.Local, | |
933 debug.ScopeType.Script, | |
934 debug.ScopeType.Global], exec_state); | |
935 CheckScopeContent({n:10}, 0, exec_state); | |
936 CheckScopeContent({e:'Exception'}, 1, exec_state); | |
937 CheckScopeChainNames(["catch_block_2", "catch_block_2", "catch_block_2", | |
938 undefined, undefined], exec_state); | |
939 }; | |
940 catch_block_2(); | |
941 EndTest(); | |
942 | |
943 | |
944 BeginTest("Catch block 3"); | |
945 function catch_block_3() { | |
946 // Do eval to dynamically declare a local variable so that the context's | |
947 // extension slot is initialized with JSContextExtensionObject. | |
948 eval("var y = 78;"); | |
949 try { | |
950 throw 'Exception'; | |
951 } catch (e) { | |
952 debugger; | |
953 } | |
954 }; | |
955 | |
956 | |
957 listener_delegate = function(exec_state) { | |
958 CheckScopeChain([debug.ScopeType.Catch, | |
959 debug.ScopeType.Local, | |
960 debug.ScopeType.Script, | |
961 debug.ScopeType.Global], exec_state); | |
962 CheckScopeContent({e:'Exception'}, 0, exec_state); | |
963 CheckScopeContent({y:78}, 1, exec_state); | |
964 CheckScopeChainNames(["catch_block_3", "catch_block_3", | |
965 undefined, undefined], exec_state); | |
966 }; | |
967 catch_block_3(); | |
968 EndTest(); | |
969 | |
970 | |
971 BeginTest("Catch block 4"); | |
972 function catch_block_4() { | |
973 // Do eval to dynamically declare a local variable so that the context's | |
974 // extension slot is initialized with JSContextExtensionObject. | |
975 eval("var y = 98;"); | |
976 try { | |
977 throw 'Exception'; | |
978 } catch (e) { | |
979 with({n:10}) { | |
980 debugger; | |
981 } | |
982 } | |
983 }; | |
984 | |
985 listener_delegate = function(exec_state) { | |
986 CheckScopeChain([debug.ScopeType.With, | |
987 debug.ScopeType.Catch, | |
988 debug.ScopeType.Local, | |
989 debug.ScopeType.Script, | |
990 debug.ScopeType.Global], exec_state); | |
991 CheckScopeContent({n:10}, 0, exec_state); | |
992 CheckScopeContent({e:'Exception'}, 1, exec_state); | |
993 CheckScopeContent({y:98}, 2, exec_state); | |
994 CheckScopeChainNames(["catch_block_4", "catch_block_4", "catch_block_4", | |
995 undefined, undefined], exec_state); | |
996 }; | |
997 catch_block_4(); | |
998 EndTest(); | |
999 | |
1000 | |
1001 // Test catch in global scope. | |
1002 BeginTest("Catch block 5"); | |
1003 listener_delegate = function(exec_state) { | |
1004 CheckScopeChain([debug.ScopeType.Catch, | |
1005 debug.ScopeType.Script, | |
1006 debug.ScopeType.Global], exec_state); | |
1007 CheckScopeContent({e:'Exception'}, 0, exec_state); | |
1008 CheckScopeChainNames([undefined, undefined, undefined], exec_state); | |
1009 }; | |
1010 | |
1011 try { | |
1012 throw 'Exception'; | |
1013 } catch (e) { | |
1014 debugger; | |
1015 } | |
1016 | |
1017 EndTest(); | |
1018 | |
1019 | |
1020 // Closure inside catch in global code. | |
1021 BeginTest("Catch block 6"); | |
1022 listener_delegate = function(exec_state) { | |
1023 CheckScopeChain([debug.ScopeType.Local, | |
1024 debug.ScopeType.Catch, | |
1025 debug.ScopeType.Script, | |
1026 debug.ScopeType.Global], exec_state); | |
1027 CheckScopeContent({x: 2}, 0, exec_state); | |
1028 CheckScopeContent({e:'Exception'}, 1, exec_state); | |
1029 CheckScopeChainNames([undefined, undefined, undefined, undefined], | |
1030 exec_state); | |
1031 }; | |
1032 | |
1033 try { | |
1034 throw 'Exception'; | |
1035 } catch (e) { | |
1036 (function(x) { | |
1037 debugger; | |
1038 })(2); | |
1039 } | |
1040 EndTest(); | |
1041 | |
1042 | |
1043 // Catch block in function that is marked for optimization while being executed. | |
1044 BeginTest("Catch block 7"); | |
1045 function catch_block_7() { | |
1046 %OptimizeFunctionOnNextCall(catch_block_7); | |
1047 try { | |
1048 throw 'Exception'; | |
1049 } catch (e) { | |
1050 debugger; | |
1051 } | |
1052 }; | |
1053 | |
1054 | |
1055 listener_delegate = function(exec_state) { | |
1056 CheckScopeChain([debug.ScopeType.Catch, | |
1057 debug.ScopeType.Local, | |
1058 debug.ScopeType.Script, | |
1059 debug.ScopeType.Global], exec_state); | |
1060 CheckScopeContent({e:'Exception'}, 0, exec_state); | |
1061 CheckScopeChainNames(["catch_block_7", "catch_block_7", | |
1062 undefined, undefined], exec_state); | |
1063 }; | |
1064 catch_block_7(); | |
1065 EndTest(); | |
1066 | |
1067 | |
1068 BeginTest("Classes and methods 1"); | |
1069 | |
1070 listener_delegate = function(exec_state) { | |
1071 "use strict" | |
1072 CheckScopeChain([debug.ScopeType.Local, | |
1073 debug.ScopeType.Script, | |
1074 debug.ScopeType.Global], exec_state); | |
1075 CheckScopeContent({}, 1, exec_state); | |
1076 CheckScopeChainNames(["m", undefined, undefined], exec_state); | |
1077 }; | |
1078 | |
1079 (function() { | |
1080 "use strict"; | |
1081 class C1 { | |
1082 m() { | |
1083 debugger; | |
1084 } | |
1085 } | |
1086 new C1().m(); | |
1087 })(); | |
1088 | |
1089 EndTest(); | |
1090 | |
1091 BeginTest("Scope positions"); | |
1092 var code1 = "function f() { \n" + | |
1093 " var a = 1; \n" + | |
1094 " function b() { \n" + | |
1095 " debugger; \n" + | |
1096 " return a + 1; \n" + | |
1097 " } \n" + | |
1098 " b(); \n" + | |
1099 "} \n" + | |
1100 "f(); \n"; | |
1101 | |
1102 listener_delegate = function(exec_state) { | |
1103 CheckScopeChainPositions( | |
1104 [{start: 58, end: 118}, {start: 10, end: 162}, {}, {}], exec_state); | |
1105 } | |
1106 eval(code1); | |
1107 EndTest(); | |
1108 | |
1109 | |
1110 function catch_block_2() { | |
1111 try { | |
1112 throw 'Exception'; | |
1113 } catch (e) { | |
1114 with({n:10}) { | |
1115 debugger; | |
1116 } | |
1117 } | |
1118 }; | |
1119 | |
1120 BeginTest("Scope positions in catch and 'with' statement"); | |
1121 var code2 = "function catch_block() { \n" + | |
1122 " try { \n" + | |
1123 " throw 'Exception'; \n" + | |
1124 " } catch (e) { \n" + | |
1125 " with({n : 10}) { \n" + | |
1126 " debugger; \n" + | |
1127 " } \n" + | |
1128 " } \n" + | |
1129 "} \n" + | |
1130 "catch_block(); \n"; | |
1131 | |
1132 listener_delegate = function(exec_state) { | |
1133 CheckScopeChainPositions([{start: 131, end: 173}, | |
1134 {start: 94, end: 199}, | |
1135 {start: 20, end: 225}, | |
1136 {}, {}], exec_state); | |
1137 } | |
1138 eval(code2); | |
1139 EndTest(); | |
1140 | |
1141 BeginTest("Scope positions in for statement"); | |
1142 var code3 = "function for_statement() { \n" + | |
1143 " for (let i = 0; i < 1; i++) { \n" + | |
1144 " debugger; \n" + | |
1145 " } \n" + | |
1146 "} \n" + | |
1147 "for_statement(); \n"; | |
1148 | |
1149 listener_delegate = function(exec_state) { | |
1150 CheckScopeChain([debug.ScopeType.Block, | |
1151 debug.ScopeType.Local, | |
1152 debug.ScopeType.Script, | |
1153 debug.ScopeType.Global], exec_state); | |
1154 CheckScopeChainPositions( | |
1155 [{start: 52, end: 111}, {start: 22, end: 145}, {}, {}], exec_state); | |
1156 } | |
1157 eval(code3); | |
1158 EndTest(); | |
1159 | |
1160 BeginTest("Scope positions in for statement with lexical block"); | |
1161 var code4 = "function for_statement() { \n" + | |
1162 " for (let i = 0; i < 1; i++) { \n" + | |
1163 " let j; \n" + | |
1164 " debugger; \n" + | |
1165 " } \n" + | |
1166 "} \n" + | |
1167 "for_statement(); \n"; | |
1168 | |
1169 listener_delegate = function(exec_state) { | |
1170 CheckScopeChain([debug.ScopeType.Block, | |
1171 debug.ScopeType.Block, | |
1172 debug.ScopeType.Local, | |
1173 debug.ScopeType.Script, | |
1174 debug.ScopeType.Global], exec_state); | |
1175 CheckScopeChainPositions([{start: 66, end: 147}, | |
1176 {start: 52, end: 147}, | |
1177 {start: 22, end: 181}, | |
1178 {}, {}], exec_state); | |
1179 } | |
1180 eval(code4); | |
1181 EndTest(); | |
1182 | |
1183 BeginTest("Scope positions in lexical for each statement"); | |
1184 var code5 = "function for_each_statement() { \n" + | |
1185 " for (let i of [0]) { \n" + | |
1186 " debugger; \n" + | |
1187 " } \n" + | |
1188 "} \n" + | |
1189 "for_each_statement(); \n"; | |
1190 | |
1191 listener_delegate = function(exec_state) { | |
1192 CheckScopeChain([debug.ScopeType.Block, | |
1193 debug.ScopeType.Local, | |
1194 debug.ScopeType.Script, | |
1195 debug.ScopeType.Global], exec_state); | |
1196 CheckScopeChainPositions( | |
1197 [{start: 55, end: 111}, {start: 27, end: 145}, {}, {}], exec_state); | |
1198 } | |
1199 eval(code5); | |
1200 EndTest(); | |
1201 | |
1202 BeginTest("Scope positions in lexical for each statement with lexical block"); | |
1203 var code6 = "function for_each_statement() { \n" + | |
1204 " for (let i of [0]) { \n" + | |
1205 " let j; \n" + | |
1206 " debugger; \n" + | |
1207 " } \n" + | |
1208 "} \n" + | |
1209 "for_each_statement(); \n"; | |
1210 | |
1211 listener_delegate = function(exec_state) { | |
1212 CheckScopeChain([debug.ScopeType.Block, | |
1213 debug.ScopeType.Block, | |
1214 debug.ScopeType.Local, | |
1215 debug.ScopeType.Script, | |
1216 debug.ScopeType.Global], exec_state); | |
1217 CheckScopeChainPositions([{start: 57, end: 147}, | |
1218 {start: 55, end: 147}, | |
1219 {start: 27, end: 181}, | |
1220 {}, {}], exec_state); | |
1221 } | |
1222 eval(code6); | |
1223 EndTest(); | |
1224 | |
1225 BeginTest("Scope positions in non-lexical for each statement"); | |
1226 var code7 = "function for_each_statement() { \n" + | |
1227 " var i; \n" + | |
1228 " for (i of [0]) { \n" + | |
1229 " debugger; \n" + | |
1230 " } \n" + | |
1231 "} \n" + | |
1232 "for_each_statement(); \n"; | |
1233 | |
1234 listener_delegate = function(exec_state) { | |
1235 CheckScopeChain([debug.ScopeType.Local, | |
1236 debug.ScopeType.Script, | |
1237 debug.ScopeType.Global], exec_state); | |
1238 CheckScopeChainPositions([{start: 27, end: 181}, {}, {}], exec_state); | |
1239 } | |
1240 eval(code7); | |
1241 EndTest(); | |
1242 | |
1243 BeginTest( | |
1244 "Scope positions in non-lexical for each statement with lexical block"); | |
1245 var code8 = "function for_each_statement() { \n" + | |
1246 " var i; \n" + | |
1247 " for (i of [0]) { \n" + | |
1248 " let j; \n" + | |
1249 " debugger; \n" + | |
1250 " } \n" + | |
1251 "} \n" + | |
1252 "for_each_statement(); \n"; | |
1253 | |
1254 listener_delegate = function(exec_state) { | |
1255 CheckScopeChain([debug.ScopeType.Block, | |
1256 debug.ScopeType.Local, | |
1257 debug.ScopeType.Script, | |
1258 debug.ScopeType.Global], exec_state); | |
1259 CheckScopeChainPositions( | |
1260 [{start: 89, end: 183}, {start: 27, end: 217}, {}, {}], exec_state); | |
1261 } | |
1262 eval(code8); | |
1263 EndTest(); | |
1264 | |
1265 assertEquals(begin_test_count, break_count, | |
1266 'one or more tests did not enter the debugger'); | |
1267 assertEquals(begin_test_count, end_test_count, | |
1268 'one or more tests did not have its result checked'); | |
OLD | NEW |