MatAtBread/fast-async

async/await with for...of cannot work

Otobelikethee opened this issue · 0 comments

  • sample code
async function validate(numbers) {
    let totalNumber;
    for (let number of numbers) {
        totalNumber += number;
    }

    if (totalNumber % 2 === 0) {
        return true;
    } else {
        throw new Error('the validation fails');
    }
}

validate([1,2,3,5]).then(() => {
  console.log(true);
})
.catch(err => {
  console.log(err);
})
  • partial transpiled code
function validate(numbers) {
  return new Promise(function ($return, $error) {
    var $Try_1_Finally = function ($Try_1_Exit) {
      return function ($Try_1_Value) {
        try {
          var $Try_2_Finally = function ($Try_2_Exit) {
            return function ($Try_2_Value) {
              try {
                if (_didIteratorError) {
                  throw _iteratorError;
                }

                return $Try_2_Exit && $Try_2_Exit.call(this, $Try_2_Value);
              } catch ($boundEx) {
                return $error($boundEx);
              }
            }.bind(this);
          }.bind(this);

          var $Try_2_Catch = function ($exception_3) {
            try {
              throw $exception_3;
            } catch ($boundEx) {
              return $Try_2_Finally($error)($boundEx);
            }
          }.bind(this);

          try {
            if (!_iteratorNormalCompletion && _iterator.return != null) {
              _iterator.return();
            }

            return $Try_2_Finally().call(this);
          } catch ($exception_3) {
            $Try_2_Catch($exception_3)
          }

          return $Try_1_Exit && $Try_1_Exit.call(this, $Try_1_Value);
        } catch ($boundEx) {
          return $error($boundEx);
        }
      }.bind(this);
    }.bind(this);

    var totalNumber;
    var _iteratorNormalCompletion = true;
    var _didIteratorError = false;
    var _iteratorError = undefined;

    var $Try_1_Post = function () {
      try {
        if (totalNumber % 2 === 0) {
          return $return(true);
        } else {
          return $error(new Error('the validation fails'));
        }

        return $return();
      } catch ($boundEx) {
        return $error($boundEx);
      }
    };

    var $Try_1_Catch = function (err) {
      try {
        _didIteratorError = true;
        _iteratorError = err;
        return $Try_1_Finally($Try_1_Post)();
      } catch ($boundEx) {
        return $Try_1_Finally($error)($boundEx);
      }
    };

    try {
      for (var _iterator = numbers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
        var number = _step.value;
        totalNumber += number;
      }

      return $Try_1_Finally($Try_1_Post)();
    } catch (err) {
      $Try_1_Catch(err)
    }
  });
}
  • Result and What I found

The promise doesn't get resolved / rejected. Because $Try_1_Finally never invoke the $Try_1_Exit.

 try {
            if (!_iteratorNormalCompletion && _iterator.return != null) {
              _iterator.return();
            }

            return $Try_2_Finally().call(this); // it returns here.
          } catch ($exception_3) {
            $Try_2_Catch($exception_3)
          }
          // will never get executed.
          return $Try_1_Exit && $Try_1_Exit.call(this, $Try_1_Value);
        } catch ($boundEx) {
          return $error($boundEx);
        }
  • temporary solution
function mapTryCatch(node, path, down) {
        if (node.$needsMapping) {
            var continuation, ctnName, catchBody;
            var ref = path[0];
            if ('index' in ref) {
                var i = ref.index + 1;
                var afterTry = ref.parent[ref.field].splice(i, ref.parent[ref.field].length - i);
                if (afterTry.length) {
                    ctnName = ident(node.$seh + "Post") ;
                    var afterContinuation = down(makeBoundFn(ctnName.name, afterTry, [], getExit(path, [opts]).$error));
                    ref.parent[ref.field].splice(ref.index, 0, afterContinuation);
                    continuation = parsePart("return $0()", [node.finalizer ? deferredFinally(node, ctnName) : ctnName]).body[0];
                } else if (node.finalizer) {
                   // change `returnThisCall` => `thisCall`
                    continuation = returnThisCall(deferredFinally(node)); 
                }
            } else {
                throw new Error(pr.filename + " - malformed try/catch blocks");
            }
  • .babelrc
{
    presets: [
    [
        '@babel/preset-env',
        {
            targets: {
                browsers: ['ie 11', 'last 2 major versions']
            },
            loose: false,
            modules: 'cjs',
            useBuiltIns: 'entry',
            exclude: ['transform-regenerator', 'transform-async-to-generator'],
            corejs: 2
        }
    ],
    '@babel/preset-react'
    ],
    plugins: [
        [
            'module:fast-async',
            {
                spec: true,
                useRuntimeModule: true
            }
        ],
        [
            '@babel/plugin-transform-runtime',
            {
                regenerator: false,
                useESModules: false,
                helpers: false
            }
        ],
        [
            '@babel/plugin-proposal-decorators',
            {
                legacy: true
            }
        ],
        '@babel/plugin-proposal-export-namespace-from',
        '@babel/plugin-proposal-export-default-from',
        '@babel/plugin-proposal-class-properties',
        '@babel/plugin-syntax-dynamic-import'
    ],
}

Versions

  • Babel 7.4.3
  • fast-async 7.0.6