OLD | NEW |
| (Empty) |
1 // Copyright 2016 the V8 project authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // Flags: --harmony-async-await | |
6 | |
7 var Debug = debug.Debug; | |
8 var global_marker = 7; | |
9 | |
10 async function thrower() { throw 'Exception'; } | |
11 | |
12 async function test(name, func, args, handler, continuation) { | |
13 var handler_called = false; | |
14 var exception = null; | |
15 | |
16 function listener(event, exec_state, event_data, data) { | |
17 try { | |
18 if (event == Debug.DebugEvent.Break) { | |
19 handler_called = true; | |
20 handler(exec_state); | |
21 } | |
22 } catch (e) { | |
23 exception = e; | |
24 } | |
25 } | |
26 | |
27 Debug.setListener(listener); | |
28 | |
29 var result; | |
30 if (typeof func === "object") | |
31 result = await func.method.apply(func, args); | |
32 else | |
33 result = await func.apply(null, args); | |
34 | |
35 if (typeof continuation === "function") { | |
36 await continuation(result); | |
37 } | |
38 | |
39 assertTrue(handler_called, `Expected ${name} handler to be called`); | |
40 if (exception) { | |
41 exception.message = `${name} / ${exception.message}`; | |
42 print(exception.stack); | |
43 quit(1); | |
44 } | |
45 | |
46 Debug.setListener(null); | |
47 } | |
48 | |
49 async function runTests() { | |
50 | |
51 // Simple | |
52 await test( | |
53 "(AsyncFunctionExpression) Local 1", | |
54 async function() { debugger; }, [], | |
55 exec_state => { | |
56 CheckScopeChain([debug.ScopeType.Local, | |
57 debug.ScopeType.Closure, | |
58 debug.ScopeType.Script, | |
59 debug.ScopeType.Global], exec_state); | |
60 CheckScopeContent({}, 0, exec_state); | |
61 }); | |
62 | |
63 await test( | |
64 "(AsyncFunctionExpression) Local 1 --- resume normal", | |
65 async function() { let z = await 2; debugger; }, [], | |
66 exec_state => { | |
67 CheckScopeChain([debug.ScopeType.Local, | |
68 debug.ScopeType.Closure, | |
69 debug.ScopeType.Script, | |
70 debug.ScopeType.Global], exec_state); | |
71 CheckScopeContent({z: 2}, 0, exec_state); | |
72 }); | |
73 | |
74 await test( | |
75 "(AsyncFunctionExpression) Local 1 --- resume throw", | |
76 async function() { let q = await 1; | |
77 try { let z = await thrower(); } | |
78 catch (e) { debugger; } }, [], | |
79 exec_state => { | |
80 CheckScopeChain([debug.ScopeType.Catch, | |
81 debug.ScopeType.Local, | |
82 debug.ScopeType.Closure, | |
83 debug.ScopeType.Script, | |
84 debug.ScopeType.Global], exec_state); | |
85 CheckScopeContent({e: 'Exception'}, 0, exec_state); | |
86 CheckScopeContent({q: 1}, 1, exec_state); | |
87 | |
88 }); | |
89 | |
90 // Simple With Parameter | |
91 await test( | |
92 "(AsyncFunctionExpression) Local 2", | |
93 async function(a) { debugger; }, [1], | |
94 exec_state => { | |
95 CheckScopeChain([debug.ScopeType.Local, | |
96 debug.ScopeType.Closure, | |
97 debug.ScopeType.Script, | |
98 debug.ScopeType.Global], exec_state); | |
99 CheckScopeContent({ a: 1 }, 0, exec_state); | |
100 }); | |
101 | |
102 await test( | |
103 "(AsyncFunctionExpression) Local 2 --- resume normal", | |
104 async function(a) { let z = await 2; debugger; }, [1], | |
105 exec_state => { | |
106 CheckScopeChain([debug.ScopeType.Local, | |
107 debug.ScopeType.Closure, | |
108 debug.ScopeType.Script, | |
109 debug.ScopeType.Global], exec_state); | |
110 CheckScopeContent({ a: 1, z: 2 }, 0, exec_state); | |
111 }); | |
112 | |
113 await test( | |
114 "(AsyncFunctionExpression) Local 2 --- resume throw", | |
115 async function(a) { let z = await 2; | |
116 try { await thrower(); } catch (e) { debugger; } }, [1], | |
117 exec_state => { | |
118 CheckScopeChain([debug.ScopeType.Catch, | |
119 debug.ScopeType.Local, | |
120 debug.ScopeType.Closure, | |
121 debug.ScopeType.Script, | |
122 debug.ScopeType.Global], exec_state); | |
123 CheckScopeContent({ e: 'Exception' }, 0, exec_state); | |
124 CheckScopeContent({ a: 1, z: 2 }, 1, exec_state); | |
125 }); | |
126 | |
127 // Simple With Parameter and Variable | |
128 await test( | |
129 "(AsyncFunctionExpression) Local 3", | |
130 async function(a) { var b = 2; debugger; }, [1], | |
131 exec_state => { | |
132 CheckScopeChain([debug.ScopeType.Local, | |
133 debug.ScopeType.Closure, | |
134 debug.ScopeType.Script, | |
135 debug.ScopeType.Global], exec_state); | |
136 CheckScopeContent({ a: 1, b: 2 }, 0, exec_state); | |
137 }); | |
138 | |
139 await test( | |
140 "(AsyncFunctionExpression) Local 3 --- resume normal", | |
141 async function(a) { let y = await 3; var b = 2; let z = await 4; | |
142 debugger; }, [1], | |
143 exec_state => { | |
144 CheckScopeChain([debug.ScopeType.Local, | |
145 debug.ScopeType.Closure, | |
146 debug.ScopeType.Script, | |
147 debug.ScopeType.Global], exec_state); | |
148 CheckScopeContent({ a: 1, b: 2, y: 3, z: 4 }, 0, exec_state); | |
149 }); | |
150 | |
151 await test( | |
152 "(AsyncFunctionExpression) Local 3 --- resume throw", | |
153 async function(a) { let y = await 3; | |
154 try { var b = 2; let z = await thrower(); } | |
155 catch (e) { debugger; } }, [1], | |
156 exec_state => { | |
157 CheckScopeChain([debug.ScopeType.Catch, | |
158 debug.ScopeType.Local, | |
159 debug.ScopeType.Closure, | |
160 debug.ScopeType.Script, | |
161 debug.ScopeType.Global], exec_state); | |
162 CheckScopeContent({ e: 'Exception' }, 0, exec_state); | |
163 CheckScopeContent({ a: 1, b: 2, y: 3 }, 1, exec_state); | |
164 }); | |
165 | |
166 // Local scope with parameters and local variables. | |
167 await test( | |
168 "(AsyncFunctionExpression) Local 4", | |
169 async function(a, b) { var x = 3; var y = 4; debugger; }, [1, 2], | |
170 exec_state => { | |
171 CheckScopeChain([debug.ScopeType.Local, | |
172 debug.ScopeType.Closure, | |
173 debug.ScopeType.Script, | |
174 debug.ScopeType.Global], exec_state); | |
175 CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state); | |
176 }); | |
177 | |
178 await test( | |
179 "(AsyncFunctionExpression) Local 4 --- resume normal", | |
180 async function(a, b) { let q = await 5; var x = 3; var y = 4; | |
181 let r = await 6; debugger; }, [1, 2], | |
182 exec_state => { | |
183 CheckScopeChain([debug.ScopeType.Local, | |
184 debug.ScopeType.Closure, | |
185 debug.ScopeType.Script, | |
186 debug.ScopeType.Global], exec_state); | |
187 CheckScopeContent({a:1,b:2,x:3,y:4, q: 5, r: 6}, 0, exec_state); | |
188 }); | |
189 | |
190 await test( | |
191 "(AsyncFunctionExpression) Local 4 --- resume throw", | |
192 async function(a, b) { let q = await 5; var x = 3; var y = 4; | |
193 try { let r = await thrower(); } | |
194 catch (e) { debugger; } }, [1, 2], | |
195 exec_state => { | |
196 CheckScopeChain([debug.ScopeType.Catch, | |
197 debug.ScopeType.Local, | |
198 debug.ScopeType.Closure, | |
199 debug.ScopeType.Script, | |
200 debug.ScopeType.Global], exec_state); | |
201 CheckScopeContent({e: 'Exception'}, 0, exec_state); | |
202 CheckScopeContent({a:1,b:2,x:3,y:4, q: 5}, 1, exec_state); | |
203 }); | |
204 | |
205 // Empty local scope with use of eval. | |
206 await test( | |
207 "(AsyncFunctionExpression) Local 5", | |
208 async function() { eval(""); debugger; }, [], | |
209 exec_state => { | |
210 CheckScopeChain([debug.ScopeType.Local, | |
211 debug.ScopeType.Closure, | |
212 debug.ScopeType.Script, | |
213 debug.ScopeType.Global], exec_state); | |
214 CheckScopeContent({}, 0, exec_state); | |
215 }); | |
216 | |
217 await test( | |
218 "(AsyncFunctionExpression) Local 5 --- resume normal", | |
219 async function() { let x = await 1; eval(""); let y = await 2; | |
220 debugger; }, [], | |
221 exec_state => { | |
222 CheckScopeChain([debug.ScopeType.Local, | |
223 debug.ScopeType.Closure, | |
224 debug.ScopeType.Script, | |
225 debug.ScopeType.Global], exec_state); | |
226 CheckScopeContent({ x: 1, y: 2 }, 0, exec_state); | |
227 }); | |
228 | |
229 await test( | |
230 "(AsyncFunctionExpression) Local 5 --- resume throw", | |
231 async function() { let x = await 1; eval(""); | |
232 try { let y = await thrower(); } | |
233 catch (e) { debugger; } }, [], | |
234 exec_state => { | |
235 CheckScopeChain([debug.ScopeType.Catch, | |
236 debug.ScopeType.Local, | |
237 debug.ScopeType.Closure, | |
238 debug.ScopeType.Script, | |
239 debug.ScopeType.Global], exec_state); | |
240 CheckScopeContent({ e: 'Exception' }, 0, exec_state); | |
241 CheckScopeContent({ x: 1 }, 1, exec_state); | |
242 }); | |
243 | |
244 // Local introducing local variable using eval. | |
245 await test( | |
246 "(AsyncFunctionExpression) Local 6", | |
247 async function() { eval("var i = 5"); debugger; }, [], | |
248 exec_state => { | |
249 CheckScopeChain([debug.ScopeType.Local, | |
250 debug.ScopeType.Closure, | |
251 debug.ScopeType.Script, | |
252 debug.ScopeType.Global], exec_state); | |
253 CheckScopeContent({i:5}, 0, exec_state); | |
254 }); | |
255 | |
256 await test( | |
257 "(AsyncFunctionExpression) Local 6 --- resume normal", | |
258 async function() { let x = await 1; eval("var i = 5"); let y = await 2; | |
259 debugger; }, [], | |
260 exec_state => { | |
261 CheckScopeChain([debug.ScopeType.Local, | |
262 debug.ScopeType.Closure, | |
263 debug.ScopeType.Script, | |
264 debug.ScopeType.Global], exec_state); | |
265 CheckScopeContent({i:5, x: 1, y: 2}, 0, exec_state); | |
266 }); | |
267 | |
268 await test( | |
269 "(AsyncFunctionExpression) Local 6 --- resume throw", | |
270 async function() { let x = await 1; eval("var i = 5"); | |
271 try { let y = await thrower(); } | |
272 catch (e) { debugger; } }, [], | |
273 exec_state => { | |
274 CheckScopeChain([debug.ScopeType.Catch, | |
275 debug.ScopeType.Local, | |
276 debug.ScopeType.Closure, | |
277 debug.ScopeType.Script, | |
278 debug.ScopeType.Global], exec_state); | |
279 CheckScopeContent({e: 'Exception' }, 0, exec_state); | |
280 CheckScopeContent({i:5, x: 1}, 1, exec_state); | |
281 }); | |
282 | |
283 // Local scope with parameters, local variables and local variable introduced | |
284 // using eval. | |
285 await test( | |
286 "(AsyncFunctionExpression) Local 7", | |
287 async function(a, b) { var x = 3; var y = 4; | |
288 eval("var i = 5;"); eval("var j = 6"); | |
289 debugger; }, [1, 2], | |
290 exec_state => { | |
291 CheckScopeChain([debug.ScopeType.Local, | |
292 debug.ScopeType.Closure, | |
293 debug.ScopeType.Script, | |
294 debug.ScopeType.Global], exec_state); | |
295 CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 0, exec_state); | |
296 }); | |
297 | |
298 await test( | |
299 "(AsyncFunctionExpression) Local 7 --- resume normal", | |
300 async function(a, b) { let z = await 7; var x = 3; var y = 4; | |
301 eval("var i = 5;"); eval("var j = 6"); | |
302 let q = await 8; | |
303 debugger; }, [1, 2], | |
304 exec_state => { | |
305 CheckScopeChain([debug.ScopeType.Local, | |
306 debug.ScopeType.Closure, | |
307 debug.ScopeType.Script, | |
308 debug.ScopeType.Global], exec_state); | |
309 CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6, z:7, q:8}, 0, exec_state); | |
310 }); | |
311 | |
312 await test( | |
313 "(AsyncFunctionExpression) Local 7 --- resume throw", | |
314 async function(a, b) { let z = await 7; var x = 3; var y = 4; | |
315 eval("var i = 5;"); eval("var j = 6"); | |
316 try { let q = await thrower(); } | |
317 catch (e) { debugger; } }, [1, 2], | |
318 exec_state => { | |
319 CheckScopeChain([debug.ScopeType.Catch, | |
320 debug.ScopeType.Local, | |
321 debug.ScopeType.Closure, | |
322 debug.ScopeType.Script, | |
323 debug.ScopeType.Global], exec_state); | |
324 CheckScopeContent({e: 'Exception'}, 0, exec_state); | |
325 //CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6, z:7}, 1, exec_state); | |
326 }); | |
327 | |
328 // Nested empty with blocks. | |
329 await test( | |
330 "(AsyncFunctionExpression) With", | |
331 async function() { with ({}) { with ({}) { debugger; } } }, [], | |
332 exec_state => { | |
333 CheckScopeChain([debug.ScopeType.With, | |
334 debug.ScopeType.With, | |
335 debug.ScopeType.Local, | |
336 debug.ScopeType.Closure, | |
337 debug.ScopeType.Script, | |
338 debug.ScopeType.Global], exec_state); | |
339 CheckScopeContent({}, 0, exec_state); | |
340 CheckScopeContent({}, 1, exec_state); | |
341 }); | |
342 | |
343 await test( | |
344 "(AsyncFunctionExpression) With --- resume normal", | |
345 async function() { let x = await 1; with ({}) { with ({}) { | |
346 let y = await 2; debugger; } } }, [], | |
347 exec_state => { | |
348 CheckScopeChain([debug.ScopeType.Block, | |
349 debug.ScopeType.With, | |
350 debug.ScopeType.With, | |
351 debug.ScopeType.Local, | |
352 debug.ScopeType.Closure, | |
353 debug.ScopeType.Script, | |
354 debug.ScopeType.Global], exec_state); | |
355 CheckScopeContent({y:2}, 0, exec_state); | |
356 CheckScopeContent({}, 1, exec_state); | |
357 CheckScopeContent({}, 2, exec_state); | |
358 CheckScopeContent({x:1}, 3, exec_state); | |
359 }); | |
360 | |
361 await test( | |
362 "(AsyncFunctionExpression) With --- resume throw", | |
363 async function() { let x = await 1; with ({}) { with ({}) { | |
364 try { let y = await thrower(); } | |
365 catch (e) { debugger; } } } }, [], | |
366 exec_state => { | |
367 CheckScopeChain([debug.ScopeType.Catch, | |
368 debug.ScopeType.With, | |
369 debug.ScopeType.With, | |
370 debug.ScopeType.Local, | |
371 debug.ScopeType.Closure, | |
372 debug.ScopeType.Script, | |
373 debug.ScopeType.Global], exec_state); | |
374 CheckScopeContent({ e: 'Exception'}, 0, exec_state); | |
375 CheckScopeContent({}, 1, exec_state); | |
376 CheckScopeContent({}, 2, exec_state); | |
377 CheckScopeContent({x:1}, 3, exec_state); | |
378 }); | |
379 | |
380 // Simple closure formed by returning an inner function referering the outer | |
381 // functions arguments. | |
382 await test( | |
383 "(AsyncFunctionExpression) Closure 1", | |
384 async function(a) { return function() { debugger; return a; } }, [1], | |
385 exec_state => { | |
386 CheckScopeChain([debug.ScopeType.Local, | |
387 debug.ScopeType.Closure, | |
388 debug.ScopeType.Closure, | |
389 debug.ScopeType.Script, | |
390 debug.ScopeType.Global], exec_state); | |
391 CheckScopeContent({a:1}, 1, exec_state); | |
392 }, | |
393 result => result()); | |
394 | |
395 await test( | |
396 "(AsyncFunctionExpression) Closure 1 --- resume normal", | |
397 async function(a) { let x = await 2; | |
398 return function() { debugger; return a; } }, [1], | |
399 exec_state => { | |
400 CheckScopeChain([debug.ScopeType.Local, | |
401 debug.ScopeType.Closure, | |
402 debug.ScopeType.Closure, | |
403 debug.ScopeType.Script, | |
404 debug.ScopeType.Global], exec_state); | |
405 CheckScopeContent({a:1, x: 2}, 1, exec_state); | |
406 }, | |
407 result => result()); | |
408 | |
409 await test( | |
410 "(AsyncFunctionExpression) Closure 1 --- resume throw", | |
411 async function(a) { let x = await 2; | |
412 return async function() { | |
413 try { await thrower(); } | |
414 catch (e) { debugger; } return a; }; }, [1], | |
415 exec_state => { | |
416 CheckScopeChain([debug.ScopeType.Catch, | |
417 debug.ScopeType.Local, | |
418 debug.ScopeType.Closure, | |
419 debug.ScopeType.Closure, | |
420 debug.ScopeType.Script, | |
421 debug.ScopeType.Global], exec_state); | |
422 CheckScopeContent({e: 'Exception'}, 0, exec_state); | |
423 CheckScopeContent({a:1, x: 2}, 2, exec_state); | |
424 }, | |
425 result => result()); | |
426 | |
427 await test( | |
428 "(AsyncFunctionExpression) Catch block 1", | |
429 async function() { try { throw 'Exception'; } catch (e) { debugger; } }, [], | |
430 exec_state => { | |
431 CheckScopeChain([debug.ScopeType.Catch, | |
432 debug.ScopeType.Local, | |
433 debug.ScopeType.Closure, | |
434 debug.ScopeType.Script, | |
435 debug.ScopeType.Global], exec_state); | |
436 CheckScopeContent({e:'Exception'}, 0, exec_state); | |
437 }); | |
438 | |
439 await test( | |
440 "(AsyncFunctionExpression) Catch block 1 --- resume normal", | |
441 async function() { | |
442 let x = await 1; | |
443 try { throw 'Exception'; } catch (e) { let y = await 2; debugger; } }, [], | |
444 exec_state => { | |
445 CheckScopeChain([debug.ScopeType.Block, | |
446 debug.ScopeType.Catch, | |
447 debug.ScopeType.Local, | |
448 debug.ScopeType.Closure, | |
449 debug.ScopeType.Script, | |
450 debug.ScopeType.Global], exec_state); | |
451 CheckScopeContent({y: 2}, 0, exec_state); | |
452 CheckScopeContent({e:'Exception'}, 1, exec_state); | |
453 CheckScopeContent({x: 1}, 2, exec_state); | |
454 }); | |
455 | |
456 await test( | |
457 "(AsyncFunctionExpression) Catch block 1 --- resume throw", | |
458 async function() { | |
459 let x = await 1; | |
460 try { throw 'Exception!'; } catch (e) { | |
461 try { let y = await thrower(); } catch (e) { debugger; } } }, [], | |
462 exec_state => { | |
463 CheckScopeChain([debug.ScopeType.Catch, | |
464 debug.ScopeType.Catch, | |
465 debug.ScopeType.Local, | |
466 debug.ScopeType.Closure, | |
467 debug.ScopeType.Script, | |
468 debug.ScopeType.Global], exec_state); | |
469 CheckScopeContent({e:'Exception'}, 0, exec_state); | |
470 CheckScopeContent({e:'Exception!'}, 1, exec_state); | |
471 CheckScopeContent({x: 1}, 2, exec_state); | |
472 }); | |
473 } | |
474 | |
475 runTests().catch(error => { | |
476 print(error.stack); | |
477 quit(1); | |
478 }) | |
479 | |
480 // Check that two scope are the same. | |
481 function assertScopeMirrorEquals(scope1, scope2) { | |
482 assertEquals(scope1.scopeType(), scope2.scopeType()); | |
483 assertEquals(scope1.frameIndex(), scope2.frameIndex()); | |
484 assertEquals(scope1.scopeIndex(), scope2.scopeIndex()); | |
485 assertPropertiesEqual( | |
486 scope1.scopeObject().value(), scope2.scopeObject().value()); | |
487 } | |
488 | |
489 function CheckFastAllScopes(scopes, exec_state) { | |
490 var fast_all_scopes = exec_state.frame().allScopes(true); | |
491 var length = fast_all_scopes.length; | |
492 assertTrue(scopes.length >= length); | |
493 for (var i = 0; i < scopes.length && i < length; i++) { | |
494 var scope = fast_all_scopes[length - i - 1]; | |
495 assertEquals(scopes[scopes.length - i - 1], scope.scopeType()); | |
496 } | |
497 } | |
498 | |
499 // Check that the scope chain contains the expected types of scopes. | |
500 function CheckScopeChain(scopes, exec_state) { | |
501 var all_scopes = exec_state.frame().allScopes(); | |
502 assertEquals( | |
503 scopes.length, all_scopes.length, "FrameMirror.allScopes length"); | |
504 for (var i = 0; i < scopes.length; i++) { | |
505 var scope = exec_state.frame().scope(i); | |
506 assertEquals(scopes[i], scope.scopeType()); | |
507 assertScopeMirrorEquals(all_scopes[i], scope); | |
508 | |
509 // Check the global object when hitting the global scope. | |
510 if (scopes[i] == debug.ScopeType.Global) { | |
511 assertEquals(global_marker, scope.scopeObject().value().global_marker); | |
512 } | |
513 } | |
514 CheckFastAllScopes(scopes, exec_state); | |
515 } | |
516 | |
517 // Check that the content of the scope is as expected. For functions just check | |
518 // that there is a function. | |
519 function CheckScopeContent(content, number, exec_state) { | |
520 var scope = exec_state.frame().scope(number); | |
521 var count = 0; | |
522 for (var p in content) { | |
523 var property_mirror = scope.scopeObject().property(p); | |
524 assertFalse(property_mirror.isUndefined(), | |
525 `property ${p} not found in scope`); | |
526 assertEquals(content[p], property_mirror.value().value(), | |
527 `property ${p} has unexpected value`); | |
528 count++; | |
529 } | |
530 | |
531 // 'arguments' and might be exposed in the local and closure scope. Just | |
532 // ignore this. | |
533 var scope_size = scope.scopeObject().properties().length; | |
534 if (!scope.scopeObject().property('arguments').isUndefined()) { | |
535 scope_size--; | |
536 } | |
537 // Skip property with empty name. | |
538 if (!scope.scopeObject().property('').isUndefined()) { | |
539 scope_size--; | |
540 } | |
541 | |
542 if (scope_size < count) { | |
543 print('Names found in scope:'); | |
544 var names = scope.scopeObject().propertyNames(); | |
545 for (var i = 0; i < names.length; i++) { | |
546 print(names[i]); | |
547 } | |
548 } | |
549 assertTrue(scope_size >= count); | |
550 } | |
OLD | NEW |