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