Fix _step.value access in for await (#13491)

This commit is contained in:
Nicolò Ribaudo 2021-07-21 19:12:18 +02:00 committed by GitHub
parent b67ea12c4d
commit 2b6acada3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 160 additions and 41 deletions

View File

@ -2,26 +2,22 @@ import { types as t, template } from "@babel/core";
const buildForAwait = template(` const buildForAwait = template(`
async function wrapper() { async function wrapper() {
var ITERATOR_COMPLETION = true; var ITERATOR_ABRUPT_COMPLETION = false;
var ITERATOR_HAD_ERROR_KEY = false; var ITERATOR_HAD_ERROR_KEY = false;
var ITERATOR_ERROR_KEY; var ITERATOR_ERROR_KEY;
try { try {
for ( for (
var ITERATOR_KEY = GET_ITERATOR(OBJECT), STEP_KEY, STEP_VALUE; var ITERATOR_KEY = GET_ITERATOR(OBJECT), STEP_KEY;
( ITERATOR_ABRUPT_COMPLETION = !(STEP_KEY = await ITERATOR_KEY.next()).done;
STEP_KEY = await ITERATOR_KEY.next(), ITERATOR_ABRUPT_COMPLETION = false
ITERATOR_COMPLETION = STEP_KEY.done, ) {
STEP_VALUE = await STEP_KEY.value,
!ITERATOR_COMPLETION
);
ITERATOR_COMPLETION = true) {
} }
} catch (err) { } catch (err) {
ITERATOR_HAD_ERROR_KEY = true; ITERATOR_HAD_ERROR_KEY = true;
ITERATOR_ERROR_KEY = err; ITERATOR_ERROR_KEY = err;
} finally { } finally {
try { try {
if (!ITERATOR_COMPLETION && ITERATOR_KEY.return != null) { if (ITERATOR_ABRUPT_COMPLETION && ITERATOR_KEY.return != null) {
await ITERATOR_KEY.return(); await ITERATOR_KEY.return();
} }
} finally { } finally {
@ -37,7 +33,7 @@ export default function (path, { getAsyncIterator }) {
const { node, scope, parent } = path; const { node, scope, parent } = path;
const stepKey = scope.generateUidIdentifier("step"); const stepKey = scope.generateUidIdentifier("step");
const stepValue = scope.generateUidIdentifier("value"); const stepValue = t.memberExpression(stepKey, t.identifier("value"));
const left = node.left; const left = node.left;
let declar; let declar;
@ -54,15 +50,14 @@ export default function (path, { getAsyncIterator }) {
} }
let template = buildForAwait({ let template = buildForAwait({
ITERATOR_HAD_ERROR_KEY: scope.generateUidIdentifier("didIteratorError"), ITERATOR_HAD_ERROR_KEY: scope.generateUidIdentifier("didIteratorError"),
ITERATOR_COMPLETION: scope.generateUidIdentifier( ITERATOR_ABRUPT_COMPLETION: scope.generateUidIdentifier(
"iteratorNormalCompletion", "iteratorAbruptCompletion",
), ),
ITERATOR_ERROR_KEY: scope.generateUidIdentifier("iteratorError"), ITERATOR_ERROR_KEY: scope.generateUidIdentifier("iteratorError"),
ITERATOR_KEY: scope.generateUidIdentifier("iterator"), ITERATOR_KEY: scope.generateUidIdentifier("iterator"),
GET_ITERATOR: getAsyncIterator, GET_ITERATOR: getAsyncIterator,
OBJECT: node.right, OBJECT: node.right,
STEP_VALUE: t.cloneNode(stepValue), STEP_KEY: t.cloneNode(stepKey),
STEP_KEY: stepKey,
}); });
// remove async function wrapper // remove async function wrapper

View File

@ -1,13 +1,13 @@
/*#__PURE__*/ /*#__PURE__*/
babelHelpers.asyncToGenerator(function* () { babelHelpers.asyncToGenerator(function* () {
var _iteratorNormalCompletion = true; var _iteratorAbruptCompletion = false;
var _didIteratorError = false; var _didIteratorError = false;
var _iteratorError; var _iteratorError;
try { try {
for (var _iterator = babelHelpers.asyncIterator(y), _step, _value; _step = yield _iterator.next(), _iteratorNormalCompletion = _step.done, _value = yield _step.value, !_iteratorNormalCompletion; _iteratorNormalCompletion = true) { for (var _iterator = babelHelpers.asyncIterator(y), _step; _iteratorAbruptCompletion = !(_step = yield _iterator.next()).done; _iteratorAbruptCompletion = false) {
let x = _value; let x = _step.value;
f(x); f(x);
} }
} catch (err) { } catch (err) {
@ -15,7 +15,7 @@ babelHelpers.asyncToGenerator(function* () {
_iteratorError = err; _iteratorError = err;
} finally { } finally {
try { try {
if (!_iteratorNormalCompletion && _iterator.return != null) { if (_iteratorAbruptCompletion && _iterator.return != null) {
yield _iterator.return(); yield _iterator.return();
} }
} finally { } finally {

View File

@ -1,19 +1,19 @@
async function foo() { async function foo() {
var _iteratorNormalCompletion = true; var _iteratorAbruptCompletion = false;
var _didIteratorError = false; var _didIteratorError = false;
var _iteratorError; var _iteratorError;
try { try {
for (var _iterator = babelHelpers.asyncIterator(y), _step, _value; _step = await _iterator.next(), _iteratorNormalCompletion = _step.done, _value = await _step.value, !_iteratorNormalCompletion; _iteratorNormalCompletion = true) { for (var _iterator = babelHelpers.asyncIterator(y), _step; _iteratorAbruptCompletion = !(_step = await _iterator.next()).done; _iteratorAbruptCompletion = false) {
const x = _value; const x = _step.value;
} }
} catch (err) { } catch (err) {
_didIteratorError = true; _didIteratorError = true;
_iteratorError = err; _iteratorError = err;
} finally { } finally {
try { try {
if (!_iteratorNormalCompletion && _iterator.return != null) { if (_iteratorAbruptCompletion && _iterator.return != null) {
await _iterator.return(); await _iterator.return();
} }
} finally { } finally {

View File

@ -4,14 +4,14 @@ function f() {
function _f() { function _f() {
_f = babelHelpers.asyncToGenerator(function* () { _f = babelHelpers.asyncToGenerator(function* () {
var _iteratorNormalCompletion = true; var _iteratorAbruptCompletion = false;
var _didIteratorError = false; var _didIteratorError = false;
var _iteratorError; var _iteratorError;
try { try {
for (var _iterator = babelHelpers.asyncIterator(y), _step, _value; _step = yield _iterator.next(), _iteratorNormalCompletion = _step.done, _value = yield _step.value, !_iteratorNormalCompletion; _iteratorNormalCompletion = true) { for (var _iterator = babelHelpers.asyncIterator(y), _step; _iteratorAbruptCompletion = !(_step = yield _iterator.next()).done; _iteratorAbruptCompletion = false) {
let x = _value; let x = _step.value;
g(x); g(x);
} }
} catch (err) { } catch (err) {
@ -19,7 +19,7 @@ function _f() {
_iteratorError = err; _iteratorError = err;
} finally { } finally {
try { try {
if (!_iteratorNormalCompletion && _iterator.return != null) { if (_iteratorAbruptCompletion && _iterator.return != null) {
yield _iterator.return(); yield _iterator.return();
} }
} finally { } finally {

View File

@ -4,14 +4,14 @@ function g() {
function _g() { function _g() {
_g = babelHelpers.wrapAsyncGenerator(function* () { _g = babelHelpers.wrapAsyncGenerator(function* () {
var _iteratorNormalCompletion = true; var _iteratorAbruptCompletion = false;
var _didIteratorError = false; var _didIteratorError = false;
var _iteratorError; var _iteratorError;
try { try {
for (var _iterator = babelHelpers.asyncIterator(y), _step, _value; _step = yield babelHelpers.awaitAsyncGenerator(_iterator.next()), _iteratorNormalCompletion = _step.done, _value = yield babelHelpers.awaitAsyncGenerator(_step.value), !_iteratorNormalCompletion; _iteratorNormalCompletion = true) { for (var _iterator = babelHelpers.asyncIterator(y), _step; _iteratorAbruptCompletion = !(_step = yield babelHelpers.awaitAsyncGenerator(_iterator.next())).done; _iteratorAbruptCompletion = false) {
let x = _value; let x = _step.value;
f(x); f(x);
} }
} catch (err) { } catch (err) {
@ -19,7 +19,7 @@ function _g() {
_iteratorError = err; _iteratorError = err;
} finally { } finally {
try { try {
if (!_iteratorNormalCompletion && _iterator.return != null) { if (_iteratorAbruptCompletion && _iterator.return != null) {
yield babelHelpers.awaitAsyncGenerator(_iterator.return()); yield babelHelpers.awaitAsyncGenerator(_iterator.return());
} }
} finally { } finally {

View File

@ -4,17 +4,17 @@ function f() {
function _f() { function _f() {
_f = babelHelpers.asyncToGenerator(function* () { _f = babelHelpers.asyncToGenerator(function* () {
var _iteratorNormalCompletion = true; var _iteratorAbruptCompletion = false;
var _didIteratorError = false; var _didIteratorError = false;
var _iteratorError; var _iteratorError;
try { try {
for (var _iterator = babelHelpers.asyncIterator(a), _step, _value; _step = yield _iterator.next(), _iteratorNormalCompletion = _step.done, _value = yield _step.value, !_iteratorNormalCompletion; _iteratorNormalCompletion = true) { for (var _iterator = babelHelpers.asyncIterator(a), _step; _iteratorAbruptCompletion = !(_step = yield _iterator.next()).done; _iteratorAbruptCompletion = false) {
let { let {
x, x,
y: [z] y: [z]
} = _value; } = _step.value;
g(x, z); g(x, z);
} }
} catch (err) { } catch (err) {
@ -22,7 +22,7 @@ function _f() {
_iteratorError = err; _iteratorError = err;
} finally { } finally {
try { try {
if (!_iteratorNormalCompletion && _iterator.return != null) { if (_iteratorAbruptCompletion && _iterator.return != null) {
yield _iterator.return(); yield _iterator.return();
} }
} finally { } finally {

View File

@ -0,0 +1,6 @@
return async function () {
let obj = {};
for await (obj.x of [1, 2]);
expect(obj.x).toBe(2);
}();

View File

@ -0,0 +1,3 @@
(async function () {
for await (obj.x of y) {}
})();

View File

@ -0,0 +1,5 @@
{
"parserOpts": {
"allowReturnOutsideFunction": true
}
}

View File

@ -0,0 +1,25 @@
babelHelpers.asyncToGenerator(function* () {
var _iteratorAbruptCompletion = false;
var _didIteratorError = false;
var _iteratorError;
try {
for (var _iterator = babelHelpers.asyncIterator(y), _step; _iteratorAbruptCompletion = !(_step = yield _iterator.next()).done; _iteratorAbruptCompletion = false) {
obj.x = _step.value;
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (_iteratorAbruptCompletion && _iterator.return != null) {
yield _iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
})();

View File

@ -0,0 +1,31 @@
let resolve;
let promise = new Promise((r) => (resolve = r));
let iterable = {
[Symbol.asyncIterator || "@@asyncIterator"]() {
return {
next: () => promise,
};
},
};
let values = [];
return Promise.all([
async function () {
for await (let value of iterable) {
values.push(value);
}
}(),
async function () {
resolve({ value: 0, done: false });
promise = new Promise((r) => (resolve = r));
await null;
resolve({ value: 1, done: false });
promise = new Promise((r) => (resolve = r));
resolve({ value: undefined, done: true });
}(),
]).then(() => {
expect(values).toEqual([0, 1]);
});

View File

@ -0,0 +1,5 @@
{
"parserOpts": {
"allowReturnOutsideFunction": true
}
}

View File

@ -0,0 +1,22 @@
let steps = [
{ done: false, value: Promise.resolve(1) },
{ done: true, value: undefined }
];
let iterable = {
[Symbol.asyncIterator || "@@asyncIterator"]() {
return {
next: () => steps.shift(),
};
},
};
let values = [];
return async function () {
let value;
for await (value of iterable);
expect(value).toBeInstanceOf(Promise);
await expect(value).resolves.toBe(1);
}();

View File

@ -0,0 +1,5 @@
{
"parserOpts": {
"allowReturnOutsideFunction": true
}
}

View File

@ -0,0 +1,18 @@
let gotValue = false;
let iterable = {
[Symbol.asyncIterator || "@@asyncIterator"]() {
return {
next: () => Promise.resolve({
get value() { gotValue = true },
done: true
})
};
},
};
return async function () {
for await (let value of iterable) {}
expect(gotValue).toBe(false);
}();

View File

@ -0,0 +1,5 @@
{
"parserOpts": {
"allowReturnOutsideFunction": true
}
}

View File

@ -1,21 +1,20 @@
(async () => { (async () => {
var _iteratorNormalCompletion = true; var _iteratorAbruptCompletion = false;
var _didIteratorError = false; var _didIteratorError = false;
var _iteratorError; var _iteratorError;
try { try {
for (var _iterator = babelHelpers.asyncIterator(iterable), _step, _value; _step = await _iterator.next(), _iteratorNormalCompletion = _step.done, _value = await _step.value, !_iteratorNormalCompletion; _iteratorNormalCompletion = true) { for (var _iterator = babelHelpers.asyncIterator(iterable), _step; _iteratorAbruptCompletion = !(_step = await _iterator.next()).done; _iteratorAbruptCompletion = false) {
const _value2 = _value, const _step$value = babelHelpers.slicedToArray(_step.value, 1),
_value3 = babelHelpers.slicedToArray(_value2, 1), value = _step$value[0];
value = _value3[0];
} }
} catch (err) { } catch (err) {
_didIteratorError = true; _didIteratorError = true;
_iteratorError = err; _iteratorError = err;
} finally { } finally {
try { try {
if (!_iteratorNormalCompletion && _iterator.return != null) { if (_iteratorAbruptCompletion && _iterator.return != null) {
await _iterator.return(); await _iterator.return();
} }
} finally { } finally {