import { types as t, template } from "@babel/core"; const buildForAwait = template(` async function wrapper() { var ITERATOR_COMPLETION = true; 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) { } } catch (err) { ITERATOR_HAD_ERROR_KEY = true; ITERATOR_ERROR_KEY = err; } finally { try { if (!ITERATOR_COMPLETION && ITERATOR_KEY.return != null) { await ITERATOR_KEY.return(); } } finally { if (ITERATOR_HAD_ERROR_KEY) { throw ITERATOR_ERROR_KEY; } } } } `); export default function (path, { getAsyncIterator }) { const { node, scope, parent } = path; const stepKey = scope.generateUidIdentifier("step"); const stepValue = scope.generateUidIdentifier("value"); const left = node.left; let declar; if (t.isIdentifier(left) || t.isPattern(left) || t.isMemberExpression(left)) { // for await (i of test), for await ({ i } of test) declar = t.expressionStatement( t.assignmentExpression("=", left, stepValue), ); } else if (t.isVariableDeclaration(left)) { // for await (let i of test) declar = t.variableDeclaration(left.kind, [ t.variableDeclarator(left.declarations[0].id, stepValue), ]); } let template = buildForAwait({ ITERATOR_HAD_ERROR_KEY: scope.generateUidIdentifier("didIteratorError"), ITERATOR_COMPLETION: scope.generateUidIdentifier( "iteratorNormalCompletion", ), 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, }); // remove async function wrapper template = template.body.body; const isLabeledParent = t.isLabeledStatement(parent); const tryBody = template[3].block.body; const loop = tryBody[0]; if (isLabeledParent) { tryBody[0] = t.labeledStatement(parent.label, loop); } return { replaceParent: isLabeledParent, node: template, declar, loop, }; }