| 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 |