Skip to content

Yields are ignored in finally block when async generator delegation is used #45400

Closed
@apendua

Description

@apendua

Bug Report

🔎 Search Terms

async
generator 
yield
finally

🕗 Version & Regression Information

Version: Version 4.3.5

  • This is the behavior in every version I tried (including nightly), and there doesn't seem to be any FAQ entries about this particular topic.

⏯ Playground Link

Playground link with relevant code

💻 Code

async function* generator1() {
  try {
    yield 1;
  } finally {
    yield 2;
  }
}

async function* generator2() {
  yield* generator1();
}

const it = generator2();

(async function () {
  console.log(await it.next());
  console.log(await it.return());
  console.log(await it.next());
}());

🙁 Actual behavior

The output of the above program is:

{ done: false, value: 1 }
{ done: true, value: undefined }
{ done: true, value: undefined }

This behavior can be observed for any compilation target lower than es2018. For es2018 and above there's no code transformation at all, and so the native implementation of async generators is used upon execution. This suggests that something is wrong with the corresponding polyfill. Indeed, after a closer examination:

var __asyncDelegator = (this && this.__asyncDelegator) || function (o) {
    var i, p;
    return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
    function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
};

seems to be ignoring the fact that calling it.return() does not necessarily result in { done: true }, which is effectively enforced by done: n === "return".

What is worth mentioning is the same problem doesn't occur for synchronous generators at all, which indicates that this is specific to how asynchronous generators are being handled.

🙂 Expected behavior

The output of the above program should be:

{ done: false, value: 1 }
{ done: false, value: 2 }
{ done: true, value: undefined }

which is in line with the behavior observed when native async generator implementation is used.

Metadata

Metadata

Assignees

Labels

Fix AvailableA PR has been opened for this issueNeeds InvestigationThis issue needs a team member to investigate its status.RescheduledThis issue was previously scheduled to an earlier milestone

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions