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