closure-compiler icon indicating copy to clipboard operation
closure-compiler copied to clipboard

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

Open trxcllnt opened this issue 1 year ago • 1 comments

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 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$$ };
}
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$$ 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$$ 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$$ 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$ }());
}, 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"));

trxcllnt avatar Jul 27 '22 18:07 trxcllnt

Thanks for the report, definitely looks like a bug.

lauraharker avatar Jul 27 '22 21:07 lauraharker

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

rishipal avatar Oct 18 '22 18:10 rishipal

Fixed with. d228c12c1b10833634654e19d091cd726ab0c713

rishipal avatar Nov 29 '22 17:11 rishipal