Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AsyncIterator#return not called when error thrown in for await of loop #3971

Closed
trxcllnt opened this issue Jul 27, 2022 · 3 comments
Closed
Assignees
Labels
internal-issue-created An internal Google issue has been created to track this GitHub issue triage-done Has been reviewed by someone on triage rotation.

Comments

@trxcllnt
Copy link

The AsyncIterator#return method should be called by closure-compiler's async iteration polyfills, but doesn't seem to be (compiling with advanced opts):

$ node test.js 
> next: 0
> next: 1
> next: 2
> return called
> catch block
> finally block
all done

$ node test.min.js 
> next: 0
> next: 1
> next: 2
> catch block
> finally block
all done
test.js:
test().then(() => console.log('all done'));

async function test() {
try {
for await (const i of source()) {
console.log(`> next: ${i}`);
if (i === 2) {
throw new Error('');
}
}
console.log(`> done`);
} catch (e) {
console.log(`> catch block`);
} finally {
console.log(`> finally block`);
}
}

function source() {
return {
i: 0,
n: 3,
[Symbol.asyncIterator]() { return this; },
async next() {
if (this.i < this.n) {
return { done: false, value: this.i++ };
}
return { done: true };
},
async throw() {
console.log(`> throw called`);
return { done: true, value: undefined };
},
async return() {
console.log(`> return called`);
return { done: true, value: undefined };
}
};
}
test.min.js:
function $$jscomp$arrayIteratorImpl$$($array$jscomp$6$$) {
var $index$jscomp$100$$ = 0;
return function () {
return $index$jscomp$100$$ < $array$jscomp$6$$.length ? { done: !1, value: $array$jscomp$6$$[$index$jscomp$100$$++], } : { done: !0 };
};
}
var $$jscomp$defineProperty$$ = "function" == typeof Object.defineProperties ? Object.defineProperty : function ($target$jscomp$92$$, $property$jscomp$5$$, $descriptor$jscomp$1$$) {
if ($target$jscomp$92$$ == Array.prototype || $target$jscomp$92$$ == Object.prototype) {
return $target$jscomp$92$$;
}
$target$jscomp$92$$[$property$jscomp$5$$] = $descriptor$jscomp$1$$.value;
return $target$jscomp$92$$;
};
function $$jscomp$getGlobal$$($passedInThis_possibleGlobals$$) {
$passedInThis_possibleGlobals$$ = ["object" == typeof globalThis && globalThis, $passedInThis_possibleGlobals$$, "object" == typeof window && window, "object" == typeof self && self, "object" == typeof global && global,];
for (var $i$jscomp$3$$ = 0; $i$jscomp$3$$ < $passedInThis_possibleGlobals$$.length; ++$i$jscomp$3$$) {
var $maybeGlobal$$ = $passedInThis_possibleGlobals$$[$i$jscomp$3$$];
if ($maybeGlobal$$ && $maybeGlobal$$.Math == Math) {
return $maybeGlobal$$;
}
}
throw Error("Cannot find global object");
}
var $$jscomp$global$$ = $$jscomp$getGlobal$$(this);
function $$jscomp$polyfill$$($property$jscomp$inline_10_split$jscomp$inline_7_target$jscomp$94$$, $impl$jscomp$inline_12_polyfill$jscomp$1$$) {
if ($impl$jscomp$inline_12_polyfill$jscomp$1$$) {
a: {
var $obj$jscomp$inline_6$$ = $$jscomp$global$$;
$property$jscomp$inline_10_split$jscomp$inline_7_target$jscomp$94$$ = $property$jscomp$inline_10_split$jscomp$inline_7_target$jscomp$94$$.split(".");
for (var $i$jscomp$inline_8_orig$jscomp$inline_11$$ = 0; $i$jscomp$inline_8_orig$jscomp$inline_11$$ < $property$jscomp$inline_10_split$jscomp$inline_7_target$jscomp$94$$.length - 1; $i$jscomp$inline_8_orig$jscomp$inline_11$$++) {
var $key$jscomp$inline_9$$ = $property$jscomp$inline_10_split$jscomp$inline_7_target$jscomp$94$$[$i$jscomp$inline_8_orig$jscomp$inline_11$$];
if (!($key$jscomp$inline_9$$ in $obj$jscomp$inline_6$$)) {
break a;
}
$obj$jscomp$inline_6$$ = $obj$jscomp$inline_6$$[$key$jscomp$inline_9$$];
}
$property$jscomp$inline_10_split$jscomp$inline_7_target$jscomp$94$$ = $property$jscomp$inline_10_split$jscomp$inline_7_target$jscomp$94$$[$property$jscomp$inline_10_split$jscomp$inline_7_target$jscomp$94$$.length - 1];
$i$jscomp$inline_8_orig$jscomp$inline_11$$ = $obj$jscomp$inline_6$$[$property$jscomp$inline_10_split$jscomp$inline_7_target$jscomp$94$$];
$impl$jscomp$inline_12_polyfill$jscomp$1$$ = $impl$jscomp$inline_12_polyfill$jscomp$1$$($i$jscomp$inline_8_orig$jscomp$inline_11$$);
$impl$jscomp$inline_12_polyfill$jscomp$1$$ != $i$jscomp$inline_8_orig$jscomp$inline_11$$ && null != $impl$jscomp$inline_12_polyfill$jscomp$1$$ && $$jscomp$defineProperty$$($obj$jscomp$inline_6$$, $property$jscomp$inline_10_split$jscomp$inline_7_target$jscomp$94$$, { configurable: !0, writable: !0, value: $impl$jscomp$inline_12_polyfill$jscomp$1$$ });
}
}
}
$$jscomp$polyfill$$("Symbol", function ($orig$jscomp$1$$) {
function $symbolPolyfill$$($opt_description$jscomp$2$$) {
if (this instanceof $symbolPolyfill$$) {
throw new TypeError("Symbol is not a constructor");
}
return new $SymbolClass$$($SYMBOL_PREFIX$$ + ($opt_description$jscomp$2$$ || "") + "_" + $counter$$++, $opt_description$jscomp$2$$);
}
function $SymbolClass$$($id$jscomp$5$$, $opt_description$jscomp$1$$) {
this.$$jscomp$symbol$id_$ = $id$jscomp$5$$;
$$jscomp$defineProperty$$(this, "description", { configurable: !0, writable: !0, value: $opt_description$jscomp$1$$ });
}
if ($orig$jscomp$1$$) {
return $orig$jscomp$1$$;
}
$SymbolClass$$.prototype.toString = function () {
return this.$$jscomp$symbol$id_$;
};
var $SYMBOL_PREFIX$$ = "jscomp_symbol_" + (1E9 * Math.random() >>> 0) + "_", $counter$$ = 0;
return $symbolPolyfill$$;
});
$$jscomp$polyfill$$("Symbol.iterator", function ($orig$jscomp$2_symbolIterator$$) {
if ($orig$jscomp$2_symbolIterator$$) {
return $orig$jscomp$2_symbolIterator$$;
}
$orig$jscomp$2_symbolIterator$$ = Symbol("Symbol.iterator");
for (var $arrayLikes$$ = "Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "), $i$jscomp$6$$ = 0; $i$jscomp$6$$ < $arrayLikes$$.length; $i$jscomp$6$$++) {
var $ArrayLikeCtor$$ = $$jscomp$global$$[$arrayLikes$$[$i$jscomp$6$$]];
"function" === typeof $ArrayLikeCtor$$ && "function" != typeof $ArrayLikeCtor$$.prototype[$orig$jscomp$2_symbolIterator$$] && $$jscomp$defineProperty$$($ArrayLikeCtor$$.prototype, $orig$jscomp$2_symbolIterator$$, {
configurable: !0, writable: !0, value: function () {
return $$jscomp$iteratorPrototype$$($$jscomp$arrayIteratorImpl$$(this));
}
});
}
return $orig$jscomp$2_symbolIterator$$;
});
$$jscomp$polyfill$$("Symbol.asyncIterator", function ($orig$jscomp$3$$) {
return $orig$jscomp$3$$ ? $orig$jscomp$3$$ : Symbol("Symbol.asyncIterator");
});
function $$jscomp$iteratorPrototype$$($iterator$jscomp$6_next$$) {
$iterator$jscomp$6_next$$ = { next: $iterator$jscomp$6_next$$ };
$iterator$jscomp$6_next$$[Symbol.iterator] = function () {
return this;
};
return $iterator$jscomp$6_next$$;
}
function $$jscomp$asyncExecutePromiseGenerator$$($generator$jscomp$1$$) {
function $passValueToGenerator$$($value$jscomp$99$$) {
return $generator$jscomp$1$$.next($value$jscomp$99$$);
}
function $passErrorToGenerator$$($error$jscomp$2$$) {
return $generator$jscomp$1$$.throw($error$jscomp$2$$);
}
return new Promise(function ($resolve$$, $reject$$) {
function $handleGeneratorRecord$$($genRec$$) {
$genRec$$.done ? $resolve$$($genRec$$.value) : Promise.resolve($genRec$$.value).then($passValueToGenerator$$, $passErrorToGenerator$$).then($handleGeneratorRecord$$, $reject$$);
}
$handleGeneratorRecord$$($generator$jscomp$1$$.next());
});
}
function $$jscomp$AsyncIteratorFromSyncWrapper$$($iterator$jscomp$8$$) {
this[Symbol.asyncIterator] = function () {
return this;
};
this[Symbol.iterator] = function () {
return $iterator$jscomp$8$$;
};
this.next = function ($param$jscomp$6$$) {
return Promise.resolve($iterator$jscomp$8$$.next($param$jscomp$6$$));
};
void 0 !== $iterator$jscomp$8$$["throw"] && (this["throw"] = function ($param$jscomp$7$$) {
return Promise.resolve($iterator$jscomp$8$$["throw"]($param$jscomp$7$$));
});
void 0 !== $iterator$jscomp$8$$["return"] && (this["return"] = function ($param$jscomp$8$$) {
return Promise.resolve($iterator$jscomp$8$$["return"]($param$jscomp$8$$));
});
}
function $__await$$module$node_modules$tslib$tslib_es6$$($v$jscomp$2$$) {
return this instanceof $__await$$module$node_modules$tslib$tslib_es6$$ ? this : new $__await$$module$node_modules$tslib$tslib_es6$$($v$jscomp$2$$);
}
; $__await$$module$node_modules$tslib$tslib_es6$$.prototype[Symbol.toStringTag] = "__await";
Object.defineProperty($__await$$module$node_modules$tslib$tslib_es6$$, Symbol.hasInstance, {
writable: !0, configurable: !0, value($inst$$) {
return !(!$inst$$ || "__await" !== $inst$$[Symbol.toStringTag]);
}
});
function $source$jscomp$17$$() {
return {
$i$: 0, n: 3, [Symbol.asyncIterator]() {
return this;
}, next() {
const $$jscomp$async$this$$ = this;
return $$jscomp$asyncExecutePromiseGenerator$$(function* () {
return $$jscomp$async$this$$.$i$ < $$jscomp$async$this$$.n ? { done: !1, value: $$jscomp$async$this$$.$i$++ } : { done: !0 };
}());
}, throw() {
return $$jscomp$asyncExecutePromiseGenerator$$(function* () {
console.log("> throw called");
return { done: !0, value: void 0 };
}());
}, return() {
return $$jscomp$asyncExecutePromiseGenerator$$(function* () {
console.log("> return called");
return { done: !0, value: void 0 };
}());
}
};
}
(function () {
return $$jscomp$asyncExecutePromiseGenerator$$(function* () {
try {
var $$jscomp$forAwait$tempIterator0_JSCompiler_inline_result$jscomp$2$$, $iterable$jscomp$inline_14$$ = $source$jscomp$17$$(), $asyncIteratorFunction$jscomp$inline_15$$ = $iterable$jscomp$inline_14$$[Symbol.asyncIterator];
if (void 0 !== $asyncIteratorFunction$jscomp$inline_15$$) {
var $JSCompiler_temp$jscomp$17$$ = $asyncIteratorFunction$jscomp$inline_15$$.call($iterable$jscomp$inline_14$$);
} else {
var $iteratorFunction$jscomp$inline_21$$ = "undefined" != typeof Symbol && Symbol.iterator && $iterable$jscomp$inline_14$$[Symbol.iterator];
var $JSCompiler_inline_result$jscomp$19$$ = $iteratorFunction$jscomp$inline_21$$ ? $iteratorFunction$jscomp$inline_21$$.call($iterable$jscomp$inline_14$$) : { next: $$jscomp$arrayIteratorImpl$$($iterable$jscomp$inline_14$$) };
$JSCompiler_temp$jscomp$17$$ = new $$jscomp$AsyncIteratorFromSyncWrapper$$($JSCompiler_inline_result$jscomp$19$$);
}
for ($$jscomp$forAwait$tempIterator0_JSCompiler_inline_result$jscomp$2$$ = $JSCompiler_temp$jscomp$17$$; ;) {
const $$jscomp$forAwait$tempResult0$$ = yield $$jscomp$forAwait$tempIterator0_JSCompiler_inline_result$jscomp$2$$.next();
if ($$jscomp$forAwait$tempResult0$$.done) {
break;
}
const $i$jscomp$18$$ = $$jscomp$forAwait$tempResult0$$.value;
console.log(`> next: ${$i$jscomp$18$$}`);
if (2 === $i$jscomp$18$$) {
throw Error("");
}
}
console.log("> done");
} catch ($e$jscomp$18$$) {
console.log("> catch block");
} finally {
console.log("> finally block");
}
}());
})().then(() => console.log("all done"));
@lauraharker
Copy link
Contributor

Thanks for the report, definitely looks like a bug.

@rishipal rishipal added triage-done Has been reviewed by someone on triage rotation. internal-issue-created An internal Google issue has been created to track this GitHub issue labels Aug 24, 2022
@rishipal
Copy link
Contributor

Update: The fix for this caused runtime errors in a few internal tests. WIP fixing.

@rishipal
Copy link
Contributor

Fixed with. d228c12

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
internal-issue-created An internal Google issue has been created to track this GitHub issue triage-done Has been reviewed by someone on triage rotation.
Projects
None yet
Development

No branches or pull requests

3 participants