<html>
    <head>
      <base href="https://bugs.webkit.org/">
    </head>
    <body>
      <p>
        <div>
            <b><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - [ESNext] Async iteration - Implement Async Generator"
   href="https://bugs.webkit.org/show_bug.cgi?id=166695#c52">Comment # 52</a>
              on <a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - [ESNext] Async iteration - Implement Async Generator"
   href="https://bugs.webkit.org/show_bug.cgi?id=166695">bug 166695</a>
              from <span class="vcard"><a class="email" href="mailto:gskachkov&#64;gmail.com" title="GSkachkov &lt;gskachkov&#64;gmail.com&gt;"> <span class="fn">GSkachkov</span></a>
</span></b>
        <pre>Comment on <span class=""><a href="attachment.cgi?id=305500&amp;action=diff" name="attach_305500" title="Patch">attachment 305500</a> <a href="attachment.cgi?id=305500&amp;action=edit" title="Patch">[details]</a></span>
Patch

View in context: <a href="https://bugs.webkit.org/attachment.cgi?id=305500&amp;action=review">https://bugs.webkit.org/attachment.cgi?id=305500&amp;action=review</a>

<span class="quote">&gt;&gt; Source/JavaScriptCore/builtins/AsyncGeneratorPrototype.js:117
&gt;&gt; +                                        } else {
&gt; 
&gt; So the last thing is these handlers.
&gt; 
&gt; You could simplify this:
&gt; 
&gt; ```
&gt; wrappedValue.&#64;promise.&#64;then(
&gt;     function(result) {
&gt;         const isDelegetedYield = generator.&#64;asyncGeneratorSuspendReason === &#64;AsyncGeneratorSuspendReasonDelegatedYield;
&gt;         generator.&#64;asyncGeneratorSuspendReason = &#64;AsyncGeneratorSuspendReasonNone;
&gt;         if (isDelegetedYield) {
&gt;             const isDone = false;
&gt;             &#64;asyncGeneratorResolve(generator, result.value, isDone);
&gt;         }
&gt;         return &#64;asyncGeneratorResumeNext(generator);
&gt;     },
&gt;     function(error) {
&gt;         generator.&#64;generatorState = &#64;AsyncGeneratorStateCompleted; // see note below
&gt;         &#64;asyncGeneratorReject(generator, error);
&gt;         &#64;asyncGeneratorResumeNext(generator);
&gt;     }
&gt; ```</span >

Yeah, it seems my patch is not clear enough, because in this asyncGeneratorResume function in resolve callback for wrappedValue, is handled case when we suspend execution control flow because of await or yield*: AsyncGeneratorSuspendReasonAwait/AsyncGeneratorSuspendReasonDelegatedYield
For suspended await we need run current function again because because we need to continue execution of function until faced with 'yield' or new await.
For value from async generator function that invoked by yield* we need to unwrap value, because it returns promise.

<span class="quote">&gt;&gt; Source/JavaScriptCore/builtins/AsyncGeneratorPrototype.js:123
&gt;&gt; +                                        generator.&#64;generatorState = &#64;AsyncGeneratorStateCompleted;
&gt; 
&gt; This actually looks wrong to me, per the current spec. Unless the committee decides to go with the &quot;yielded rejections don't affect control flow of the generator&quot; thing (which is admittedly pretty popular), closing the generator should be left up to &#64;asyncGeneratorResume().
&gt; 
&gt; Even if the proposal is changed, this will prevent finally blocks from being reached.
&gt; 
&gt; E.g.
&gt; 
&gt; ```js
&gt; let reject;
&gt; async function* foo() {
&gt;   try {
&gt;     yield new Promise(function(unused, rej) { reject = rej; });
&gt;   } finally {
&gt;     doImportantCleanupStuff(); // In this patch, this appears to be unreachable
&gt;     return 0;
&gt;   }
&gt; }
&gt; 
&gt; foo().next().then(x =&gt; print(x), e =&gt; print(e));
&gt; reject(&quot;Oop!&quot;);
&gt; ```
&gt; 
&gt; I could be wrong about this, but I _believe_ this is broken in this patch due to the generator state change here, and I think it is supposed to work in the current spec</span >

I see following result:

  do important staff
  returned value
  Oop!

Is this result close to spec or 'important staff' should be returned after Oop!
To test I used little bit modified function:
```
async function* foo() {
  try {
    yield new Promise(function(unused, rej) { reject = rej; });
  } finally {
    print('do important staff');
    return 'returned value';
  }
}

var f= foo()
f.next().then(({value}) =&gt; print(value), e =&gt; print(e));
reject(&quot;Oop!&quot;);
f.next().then(({value}) =&gt; print(value), e =&gt; print(e));
drainMicrotasks();
```</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are the assignee for the bug.</li>
      </ul>
    </body>
</html>