Bug 1547039: Adjust async-generator state when manually closing an async-generator. r=arai
authorAndré Bargull <andre.bargull@gmail.com>
Tue, 07 May 2019 04:11:58 +0000
changeset 534838 c3ea428d6b2a4ab026fea0e1dc5c0776720d1b2d
parent 534837 723587a2ae497817823c4b42f339e91d640a6208
child 534839 c35863f496b662167c8c0c93e6f4b26670e70387
push id2082
push userffxbld-merge
push dateMon, 01 Jul 2019 08:34:18 +0000
treeherdermozilla-release@2fb19d0466d2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarai
bugs1547039
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1547039: Adjust async-generator state when manually closing an async-generator. r=arai Similar to AutoSetGeneratorRunning, AdjustGeneratorResumptionValue also needs to modify the async-generator state in addition to the shared generator state. Differential Revision: https://phabricator.services.mozilla.com/D30035
js/src/jit-test/tests/debug/onEnterFrame-async-resumption-13.js
js/src/vm/Debugger.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/onEnterFrame-async-resumption-13.js
@@ -0,0 +1,21 @@
+// An onPop handler can return its input argument for async generators. The
+// debugger correctly adjusts the state of the async generator object.
+
+let g = newGlobal({newCompartment: true});
+g.eval(`
+    async function* f() {}
+`);
+
+let hits = 0;
+let dbg = new Debugger(g);
+dbg.onEnterFrame = frame => {
+  frame.onPop = completion => {
+      hits++;
+      return completion;
+  };
+};
+
+let it = g.f();
+let p = it.next();
+
+assertEq(hits, 1);
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -1663,27 +1663,33 @@ static void AdjustGeneratorResumptionVal
 
     // 1.  `return <value>` creates and returns a new object,
     //     `{value: <value>, done: true}`.
     //
     // For non-async generators, the iterator result object is created in
     // bytecode, so we have to simulate that here. For async generators, our
     // C++ implementation of AsyncGeneratorResolve will do this. So don't do it
     // twice:
-    if (!frame.callee()->isAsync()) {
+    if (!genObj->is<AsyncGeneratorObject>()) {
       JSObject* pair = CreateIterResultObject(cx, vp, true);
       if (!pair) {
         getAndClearExceptionThenThrow();
         return;
       }
       vp.setObject(*pair);
     }
 
     // 2.  The generator must be closed.
     genObj->setClosed();
+
+    // Async generators have additionally bookkeeping which must be adjusted
+    // when switching over to the closed state.
+    if (genObj->is<AsyncGeneratorObject>()) {
+      genObj->as<AsyncGeneratorObject>().setCompleted();
+    }
   } else if (frame.callee()->isAsync()) {
     if (AbstractGeneratorObject* genObj =
             GetGeneratorObjectForFrame(cx, frame)) {
       // Throw doesn't require any special processing for async functions when
       // the internal generator object is already present.
       if (resumeMode == ResumeMode::Throw) {
         return;
       }