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