Closed
Description
The downlevel emit for async functions is missing support for handling captured block-scope variables.
Example:
async function fn() {
for (let i = 0; i < 1; i++) return await () => i;
}
Actual:
function fn() {
return __awaiter(this, void 0, void 0, function () {
var _loop_1, i;
return __generator(this, function (_a) {
_loop_1 = function (i) {
return { value: yield (function () { return i; }) };
};
for (i = 0; i < 1; i++) {
var state_1 = _loop_1(i);
if (typeof state_1 === "object")
return state_1.value;
}
return [2 /*return*/];
});
});
}
The yield
in _loop_1
is incorrect, since _loop_1
is not a generator.
The simplest solution is to turn the _loop_1
function into a generator, and add the yield*
support from #10106, allowing us to delegate the yield
expression inside of _loop_1
to __awaiter
, but preserve the same return semantics used by the loop body transform.
The resulting emit should be something more like this:
function fn() {
return __awaiter(this, void 0, void 0, function () {
var _loop_1, i, state_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_loop_1 = function (i) {
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = {};
return [4 /*yield*/, (function () { return i; })];
case 1: return [2 /*return*/, (_a.value = _b.sent(), _a)];
}
});
};
i = 0;
_a.label = 1;
case 1:
if (!(i < 1))
return [3 /*break*/, 4];
return [5 /*yield**/, _loop_1(i)];
case 2:
state_1 = _a.sent();
if (typeof state_1 === "object")
return [2 /*return*/, state_1.value];
_a.label = 3;
case 3:
i++;
return [3 /*break*/, 1];
case 4: return [2 /*return*/];
}
});
});
}