Index: test/mjsunit/harmony/generators-debug-liveedit.js |
diff --git a/test/mjsunit/harmony/generators-debug-liveedit.js b/test/mjsunit/harmony/generators-debug-liveedit.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..341ef483c538047d6d8894101377ca7fed0f7c3d |
--- /dev/null |
+++ b/test/mjsunit/harmony/generators-debug-liveedit.js |
@@ -0,0 +1,119 @@ |
+// Copyright 2014 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+// Flags: --expose-debug-as debug --harmony-generators |
+ |
+var Debug = debug.Debug; |
+var LiveEdit = Debug.LiveEdit; |
+ |
+unique_id = 0; |
+ |
+var Generator = (function*(){}).constructor; |
+ |
+function assertIteratorResult(value, done, result) { |
+ assertEquals({value: value, done: done}, result); |
+} |
+ |
+function MakeGenerator() { |
+ // Prevents eval script caching. |
+ unique_id++; |
+ return Generator('callback', |
+ "/* " + unique_id + "*/\n" + |
+ "yield callback();\n" + |
+ "return 'Cat';\n"); |
+} |
+ |
+function MakeFunction() { |
+ // Prevents eval script caching. |
+ unique_id++; |
+ return Function('callback', |
+ "/* " + unique_id + "*/\n" + |
+ "callback();\n" + |
+ "return 'Cat';\n"); |
+} |
+ |
+// First, try MakeGenerator with no perturbations. |
+(function(){ |
+ var generator = MakeGenerator(); |
+ function callback() {}; |
+ var iter = generator(callback); |
+ assertIteratorResult(undefined, false, iter.next()); |
+ assertIteratorResult("Cat", true, iter.next()); |
+})(); |
+ |
+function patch(fun, from, to) { |
+ function debug() { |
+ var log = new Array(); |
+ var script = Debug.findScript(fun); |
+ var pos = script.source.indexOf(from); |
+ try { |
+ LiveEdit.TestApi.ApplySingleChunkPatch(script, pos, from.length, to, |
+ log); |
+ } finally { |
+ print("Change log: " + JSON.stringify(log) + "\n"); |
+ } |
+ } |
+ Debug.ExecuteInDebugContext(debug, false); |
+} |
+ |
+// Try to edit a MakeGenerator while it's running, then again while it's |
+// stopped. |
+(function(){ |
+ var generator = MakeGenerator(); |
+ |
+ var gen_patch_attempted = false; |
+ function attempt_gen_patch() { |
+ assertFalse(gen_patch_attempted); |
+ gen_patch_attempted = true; |
+ assertThrows(function() { patch(generator, "'Cat'", "'Capybara'") }, |
+ LiveEdit.Failure); |
+ }; |
+ var iter = generator(attempt_gen_patch); |
+ assertIteratorResult(undefined, false, iter.next()); |
+ // Patch should not succeed because there is a live generator activation on |
+ // the stack. |
+ assertIteratorResult("Cat", true, iter.next()); |
+ assertTrue(gen_patch_attempted); |
+ |
+ // At this point one iterator is live, but closed, so the patch will succeed. |
+ patch(generator, "'Cat'", "'Capybara'"); |
+ iter = generator(function(){}); |
+ assertIteratorResult(undefined, false, iter.next()); |
+ // Patch successful. |
+ assertIteratorResult("Capybara", true, iter.next()); |
+ |
+ // Patching will fail however when a live iterator is suspended. |
+ iter = generator(function(){}); |
+ assertIteratorResult(undefined, false, iter.next()); |
+ assertThrows(function() { patch(generator, "'Capybara'", "'Tapir'") }, |
+ LiveEdit.Failure); |
+ assertIteratorResult("Capybara", true, iter.next()); |
+ |
+ // Try to patch functions with activations inside and outside generator |
+ // function activations. We should succeed in the former case, but not in the |
+ // latter. |
+ var fun_outside = MakeFunction(); |
+ var fun_inside = MakeFunction(); |
+ var fun_patch_attempted = false; |
+ var fun_patch_restarted = false; |
+ function attempt_fun_patches() { |
+ if (fun_patch_attempted) { |
+ assertFalse(fun_patch_restarted); |
+ fun_patch_restarted = true; |
+ return; |
+ } |
+ fun_patch_attempted = true; |
+ // Patching outside a generator activation must fail. |
+ assertThrows(function() { patch(fun_outside, "'Cat'", "'Cobra'") }, |
+ LiveEdit.Failure); |
+ // Patching inside a generator activation may succeed. |
+ patch(fun_inside, "'Cat'", "'Koala'"); |
+ } |
+ iter = generator(function() { return fun_inside(attempt_fun_patches) }); |
+ assertEquals('Cat', |
+ fun_outside(function () { |
+ assertIteratorResult('Koala', false, iter.next()); |
+ assertTrue(fun_patch_restarted); |
+ })); |
+})(); |