Skip to content

Commit

Permalink
Fix _step.value access in for await (babel#13491)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo committed Jul 30, 2021
1 parent 3bd3cdd commit fa7852c
Show file tree
Hide file tree
Showing 17 changed files with 160 additions and 41 deletions.
Expand Up @@ -2,26 +2,22 @@ import { types as t, template } from "@babel/core";

const buildForAwait = template(`
async function wrapper() {
var ITERATOR_COMPLETION = true;
var ITERATOR_ABRUPT_COMPLETION = false;
var ITERATOR_HAD_ERROR_KEY = false;
var ITERATOR_ERROR_KEY;
try {
for (
var ITERATOR_KEY = GET_ITERATOR(OBJECT), STEP_KEY, STEP_VALUE;
(
STEP_KEY = await ITERATOR_KEY.next(),
ITERATOR_COMPLETION = STEP_KEY.done,
STEP_VALUE = await STEP_KEY.value,
!ITERATOR_COMPLETION
);
ITERATOR_COMPLETION = true) {
var ITERATOR_KEY = GET_ITERATOR(OBJECT), STEP_KEY;
ITERATOR_ABRUPT_COMPLETION = !(STEP_KEY = await ITERATOR_KEY.next()).done;
ITERATOR_ABRUPT_COMPLETION = false
) {
}
} catch (err) {
ITERATOR_HAD_ERROR_KEY = true;
ITERATOR_ERROR_KEY = err;
} finally {
try {
if (!ITERATOR_COMPLETION && ITERATOR_KEY.return != null) {
if (ITERATOR_ABRUPT_COMPLETION && ITERATOR_KEY.return != null) {
await ITERATOR_KEY.return();
}
} finally {
Expand All @@ -37,7 +33,7 @@ export default function (path, { getAsyncIterator }) {
const { node, scope, parent } = path;

const stepKey = scope.generateUidIdentifier("step");
const stepValue = scope.generateUidIdentifier("value");
const stepValue = t.memberExpression(stepKey, t.identifier("value"));
const left = node.left;
let declar;

Expand All @@ -54,15 +50,14 @@ export default function (path, { getAsyncIterator }) {
}
let template = buildForAwait({
ITERATOR_HAD_ERROR_KEY: scope.generateUidIdentifier("didIteratorError"),
ITERATOR_COMPLETION: scope.generateUidIdentifier(
"iteratorNormalCompletion",
ITERATOR_ABRUPT_COMPLETION: scope.generateUidIdentifier(
"iteratorAbruptCompletion",
),
ITERATOR_ERROR_KEY: scope.generateUidIdentifier("iteratorError"),
ITERATOR_KEY: scope.generateUidIdentifier("iterator"),
GET_ITERATOR: getAsyncIterator,
OBJECT: node.right,
STEP_VALUE: t.cloneNode(stepValue),
STEP_KEY: stepKey,
STEP_KEY: t.cloneNode(stepKey),
});

// remove async function wrapper
Expand Down
@@ -1,21 +1,21 @@
/*#__PURE__*/
babelHelpers.asyncToGenerator(function* () {
var _iteratorNormalCompletion = true;
var _iteratorAbruptCompletion = false;
var _didIteratorError = false;

var _iteratorError;

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

var _iteratorError;

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

function _f() {
_f = babelHelpers.asyncToGenerator(function* () {
var _iteratorNormalCompletion = true;
var _iteratorAbruptCompletion = false;
var _didIteratorError = false;

var _iteratorError;

try {
for (var _iterator = babelHelpers.asyncIterator(y), _step, _value; _step = yield _iterator.next(), _iteratorNormalCompletion = _step.done, _value = yield _step.value, !_iteratorNormalCompletion; _iteratorNormalCompletion = true) {
let x = _value;
for (var _iterator = babelHelpers.asyncIterator(y), _step; _iteratorAbruptCompletion = !(_step = yield _iterator.next()).done; _iteratorAbruptCompletion = false) {
let x = _step.value;
g(x);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return != null) {
if (_iteratorAbruptCompletion && _iterator.return != null) {
yield _iterator.return();
}
} finally {
Expand Down
Expand Up @@ -4,22 +4,22 @@ function g() {

function _g() {
_g = babelHelpers.wrapAsyncGenerator(function* () {
var _iteratorNormalCompletion = true;
var _iteratorAbruptCompletion = false;
var _didIteratorError = false;

var _iteratorError;

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) {
let x = _value;
for (var _iterator = babelHelpers.asyncIterator(y), _step; _iteratorAbruptCompletion = !(_step = yield babelHelpers.awaitAsyncGenerator(_iterator.next())).done; _iteratorAbruptCompletion = false) {
let x = _step.value;
f(x);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return != null) {
if (_iteratorAbruptCompletion && _iterator.return != null) {
yield babelHelpers.awaitAsyncGenerator(_iterator.return());
}
} finally {
Expand Down
Expand Up @@ -4,25 +4,25 @@ function f() {

function _f() {
_f = babelHelpers.asyncToGenerator(function* () {
var _iteratorNormalCompletion = true;
var _iteratorAbruptCompletion = false;
var _didIteratorError = false;

var _iteratorError;

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 {
x,
y: [z]
} = _value;
} = _step.value;
g(x, z);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return != null) {
if (_iteratorAbruptCompletion && _iterator.return != null) {
yield _iterator.return();
}
} finally {
Expand Down
@@ -0,0 +1,6 @@
return async function () {
let obj = {};
for await (obj.x of [1, 2]);

expect(obj.x).toBe(2);
}();
@@ -0,0 +1,3 @@
(async function () {
for await (obj.x of y) {}
})();
@@ -0,0 +1,5 @@
{
"parserOpts": {
"allowReturnOutsideFunction": true
}
}
@@ -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;
}
}
}
})();
@@ -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]);
});
@@ -0,0 +1,5 @@
{
"parserOpts": {
"allowReturnOutsideFunction": true
}
}
@@ -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);
}();
@@ -0,0 +1,5 @@
{
"parserOpts": {
"allowReturnOutsideFunction": true
}
}
@@ -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);
}();
@@ -0,0 +1,5 @@
{
"parserOpts": {
"allowReturnOutsideFunction": true
}
}
@@ -1,21 +1,20 @@
(async () => {
var _iteratorNormalCompletion = true;
var _iteratorAbruptCompletion = false;
var _didIteratorError = false;

var _iteratorError;

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

0 comments on commit fa7852c

Please sign in to comment.