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 // Flags: --expose-debug-as debug --allow-natives-syntax | |
7 | |
8 var Debug = debug.Debug; | |
9 var LiveEdit = Debug.LiveEdit; | |
10 | |
11 unique_id = 0; | |
12 | |
13 var AsyncFunction = (async function(){}).constructor; | |
14 | |
15 function assertPromiseValue(value, promise) { | |
16 promise.then(resolve => { | |
17 went = true; | |
18 if (resolve !== value) { | |
19 print(`expected ${value} found ${resolve}`); | |
20 quit(1); | |
21 } | |
22 }, reject => { | |
23 print(`rejected ${reject}`); | |
24 quit(1); | |
25 }); | |
26 } | |
27 | |
28 function MakeAsyncFunction() { | |
29 // Prevents eval script caching. | |
30 unique_id++; | |
31 return AsyncFunction('callback', | |
32 "/* " + unique_id + "*/\n" + | |
33 "await callback();\n" + | |
34 "return 'Cat';\n"); | |
35 } | |
36 | |
37 function MakeFunction() { | |
38 // Prevents eval script caching. | |
39 unique_id++; | |
40 return Function('callback', | |
41 "/* " + unique_id + "*/\n" + | |
42 "callback();\n" + | |
43 "return 'Cat';\n"); | |
44 } | |
45 | |
46 // First, try MakeGenerator with no perturbations. | |
47 (function(){ | |
48 var asyncfn = MakeAsyncFunction(); | |
49 function callback() {}; | |
50 var promise = asyncfn(callback); | |
51 assertPromiseValue('Cat', promise); | |
52 })(); | |
53 | |
54 function patch(fun, from, to) { | |
55 function debug() { | |
56 var log = new Array(); | |
57 var script = Debug.findScript(fun); | |
58 var pos = script.source.indexOf(from); | |
59 print(`pos ${pos}`); | |
60 try { | |
61 LiveEdit.TestApi.ApplySingleChunkPatch(script, pos, from.length, to, | |
62 log); | |
63 } finally { | |
64 print("Change log: " + JSON.stringify(log) + "\n"); | |
65 } | |
66 } | |
67 %ExecuteInDebugContext(debug); | |
68 } | |
69 | |
70 // Try to edit a MakeAsyncFunction while it's running, then again while it's | |
71 // stopped. | |
72 (function(){ | |
73 var asyncfn = MakeAsyncFunction(); | |
74 | |
75 var patch_attempted = false; | |
76 function attempt_patch() { | |
77 assertFalse(patch_attempted); | |
78 patch_attempted = true; | |
79 assertThrows(function() { patch(asyncfn, "'Cat'", "'Capybara'") }, | |
80 LiveEdit.Failure); | |
81 }; | |
82 var promise = asyncfn(attempt_patch); | |
83 // Patch should not succeed because there is a live async function activation | |
84 // on the stack. | |
85 assertPromiseValue("Cat", promise); | |
86 assertTrue(patch_attempted); | |
87 | |
88 %RunMicrotasks(); | |
89 | |
90 // At this point one iterator is live, but closed, so the patch will succeed. | |
91 patch(asyncfn, "'Cat'", "'Capybara'"); | |
92 promise = asyncfn(function(){}); | |
93 // Patch successful. | |
94 assertPromiseValue("Capybara", promise); | |
95 | |
96 // Patching will fail however when an async function is suspended. | |
97 var resolve; | |
98 promise = asyncfn(function(){return new Promise(function(r){resolve = r})}); | |
99 assertThrows(function() { patch(asyncfn, "'Capybara'", "'Tapir'") }, | |
100 LiveEdit.Failure); | |
101 resolve(); | |
102 assertPromiseValue("Capybara", promise); | |
103 | |
104 // Try to patch functions with activations inside and outside async | |
105 // function activations. We should succeed in the former case, but not in the | |
106 // latter. | |
107 var fun_outside = MakeFunction(); | |
108 var fun_inside = MakeFunction(); | |
109 var fun_patch_attempted = false; | |
110 var fun_patch_restarted = false; | |
111 function attempt_fun_patches() { | |
112 if (fun_patch_attempted) { | |
113 assertFalse(fun_patch_restarted); | |
114 fun_patch_restarted = true; | |
115 return; | |
116 } | |
117 fun_patch_attempted = true; | |
118 // Patching outside an async function activation must fail. | |
119 assertThrows(function() { patch(fun_outside, "'Cat'", "'Cobra'") }, | |
120 LiveEdit.Failure); | |
121 // Patching inside an async function activation may succeed. | |
122 patch(fun_inside, "'Cat'", "'Koala'"); | |
123 } | |
124 promise = asyncfn(function() { return fun_inside(attempt_fun_patches) }); | |
125 assertEquals('Cat', | |
126 fun_outside(function () { | |
127 assertPromiseValue('Capybara', promise); | |
128 assertTrue(fun_patch_restarted); | |
129 assertTrue(fun_inside.toString().includes("'Koala'")); | |
130 })); | |
131 })(); | |
132 | |
133 %RunMicrotasks(); | |
OLD | NEW |