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