Code Monkey home page Code Monkey logo

fast-async's People

Contributors

amilajack avatar chrisantaki avatar ephemer avatar fend25 avatar matatbread avatar matatwork avatar phyllisstein avatar simondegraeve avatar strate avatar z-vr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fast-async's Issues

Strange "unexpected token" errors

Sorry for being vague, but I think there is something funny going on with this plugin.

When I use these plugins,

'syntax-async-functions',
'transform-async-to-generator',
'transform-regenerator',
["transform-runtime", {
    "polyfill": true,
    "regenerator": true,
}],

My project compiles fine, but when I try with:

'syntax-async-functions',
['fast-async',{
    compiler: {
        promises: true,
        generators: false
    }
}],
["transform-runtime", {
    "polyfill": true,
    "regenerator": false,
}],

I get a bunch of errors like this:

ERROR in ./assets/scripts/lib/DynamicSelect.js
Module parse failed: /home/mpenner/Projects/webenginex/node_modules/babel-loader/index.js?{"presets":[],"plugins":["syntax-flow","syntax-trailing-function-commas","check-es2015-constants","transform-flow-strip-types","transform-es3-member-expression-literals","transform-es3-property-literals","transform-es5-property-mutators",["transform-es2015-modules-commonjs",{"loose":true}],"transform-class-constructor-call","transform-class-properties","transform-decorators","transform-export-extensions","transform-object-rest-spread","transform-exponentiation-operator","transform-es2015-arrow-functions","transform-es2015-block-scoped-functions","transform-es2015-block-scoping","transform-es2015-classes","transform-es2015-computed-properties","transform-es2015-destructuring","transform-es2015-for-of","transform-es2015-function-name","transform-es2015-literals","transform-es2015-object-super","transform-es2015-parameters","transform-es2015-shorthand-properties","transform-es2015-spread","transform-es2015-sticky-regex","transform-es2015-template-literals","transform-es2015-typeof-symbol","transform-es2015-unicode-regex","syntax-async-functions",["fast-async",{"compiler":{"promises":true,"generators":false}}],["transform-runtime",{"polyfill":true,"regenerator":false}]],"compact":false}!/home/mpenner/Projects/webenginex/assets/scripts/lib/DynamicSelect.js Line 71: Unexpected token
You may need an appropriate loader to handle this file type.
| var $ = require('jquery');
| 
| export {};
| export {};
| 
 @ ./assets/main.js 149:35-73

I'm not even sure what the syntax error is. Those empty export {};s weren't in my code, but I don't think they're a syntax error. And async isn't even used in this file. So I really have no idea what's going on, but I'm pretty sure it has something to do with fast-async.

Merge this project into the official async plugin for Babel?

Right now there are a few ways to use (non-native) async in Babel:

We also had a module called async-to-module-method but it seemed weird to make it separate so I just merged that as an option in the other async plugin.

I'd like to propose we just merge everything into 1 plugin?

So in v7 it would be called @babel/plugin-async-functions and it would have an option to compile using generators (async-to-gen) and promises (using a port of this plugin + kneden).

I'd like this because regenerator has to have a runtime, it's large, and still under the BSD+Patents by FB (waiting for them to change it). If in the meantime we can get this working I'm cool with just switching it out by default and other people can opt-in to using regenerator if they want but it would be outside of our repo.

Would that be desirable? Basically for this new plugin I would want everything in fast-async that is related to compiling async to promises but nothing else (so don't need the logic for generators, or any non-spec behavior that is in nodent). Let me know if that would be cool, or if we can get someone else in the community to do this if you are busy

So the new version wouldn't need all of https://github.com/MatAtBread/nodent or https://github.com/MatAtBread/nodent-runtime or the options

Warning: a promise was created in a handler at eval at processIncludes

Not sure if this is relevant but when I changed my config to fast-async I started getting such warnings from bluebird:

(node:22057) Warning: a promise was created in a handler at eval at processIncludes (/code/project/node_modules/nodent-runtime/runtime.js:1:0), <anonymous>:3:4642 but was not returned from it, see http://goo.gl/rRqMUw

I'd rather not disable the warning itself as it may be useful on other occasions.

Do you think it's a problem in fast-async? or maybe in bluebird? or maybe the change has just uncovered my own bug...

Strict mode transformation bug on IOS

Code:

class exampleClass {
    async fun1(){}
    async fun2() {
        const channel = await this.fun1();
        try {return await this.fun1();} catch(e) {
            return false;
        }
    }
}
export default EpgController;

which is trasformed to:

(...)
"use strict";
(...)

var exampleClass = function () {
    function exampleClass() {
        _classCallCheck(this, exampleClass);
    }

    _createClass(exampleClass, [{
        key: "fun1",
        value: function fun1() {
            return new Promise(function ($return, $error) {
                return $return();
            }.bind(this));
        }
    }, {
        key: "fun2",
        value: function fun2() {
            return new Promise(function ($return, $error) {
                var channel;
                return this.fun1().then(function ($await_2) {
                    try {
                        channel = $await_2;

                        function $Try_1_Post() {
                            return $return();
                        }

                        var $Try_1_Catch = function (e) {
                            try {
                                return $return(false);
                            } catch ($boundEx) {
                                return $error($boundEx);
                            }
                        }.bind(this);try {
                            return this.fun1().then($return, $Try_1_Catch);
                        } catch (e) {
                            $Try_1_Catch(e)
                        }
                    } catch ($boundEx) {
                        return $error($boundEx);
                    }
                }.bind(this), $error);
            }.bind(this));
        }
    }]);

    return exampleClass;
}();

On IOS I get error
Strict mode does not allow function declarations in a lexically nested statement.
connected with code:

try {
        function $Try_1_Post() {
            return $return();
        }
}

Any ideas how to fix it?

for...of inside async function inside an if blows up

export default async function blowUp(obj) {
  if (obj) {
    for (const fk of Object.keys(obj)) {
     console.log(x);
    }
  }
}

Results in:

TypeError: src/fastasync.js: Cannot read property '0' of undefined
    at Buffer._append (/my-serv/node_modules/babel-generator/lib/buffer.js:95:25)
    at Buffer.append (/my-serv/node_modules/babel-generator/lib/buffer.js:72:10)
    at Generator._append (/my-serv/node_modules/babel-generator/lib/printer.js:206:52)
    at Generator.word (/my-serv/node_modules/babel-generator/lib/printer.js:131:10)
    at Generator.Identifier (/my-serv/node_modules/babel-generator/lib/generators/types.js:38:8)
    at /my-serv/node_modules/babel-generator/lib/printer.js:298:23
    at Buffer.withSource (/my-serv/node_modules/babel-generator/lib/buffer.js:168:5)
    at Generator.withSource (/my-serv/node_modules/babel-generator/lib/printer.js:189:15)
    at Generator.print (/my-serv/node_modules/babel-generator/lib/printer.js:297:10)
    at Generator.printJoin (/my-serv/node_modules/babel-generator/lib/printer.js:366:12)

Cannot await non-Promises.

Using Babel 6, it appears right now that I cannot await any non-Promise value. E.g.

(async () => { await 1 })()

throws Uncaught (in promise) TypeError: 1.then is not a function. Is this by design, or is there something wrong with my setup?

Babel: Plugin no longer emits Function.prototype.$asyncbind since 6.0.34

As in the title. The plugin has been unusable since 6.0.34 for us because - although it seems to transform the async functions correctly - it doesn't provide the core runtime functionality ($asyncbind).

We only output $asyncbind to one file as per the docs:

{
    "presets": ["es2015"],
    "plugins": [
        ["fast-async", {
            "runtimePattern": "src/index.js"
        }]
    ]
}

In 6.0.34 this works. In 6.1+ the transform appears to work but src/index.js doesn't receive $asyncbind. This may be because src/index itself doesn't contain any async functions itself?

can't call await on normal functions + can't use es2015 preset

The idea to use fast-async in Next.js came up, but there were these concerns:

  • Apparently fast-async doesn't support calling await on normal functions that don't return a Promise. So if you, for example make a component which has a static getInitialProps instead of static async getInitialProps it will fail
  • would have to drop the es2015 preset to implement fast-async, since it conflicts with babel-plugin-transform-runtime ๐Ÿ˜ข

Is that accurate? If these limitations do exist, is there a possibility/plan to address them? How do other users circumvent them?

for ... of produces `Cannot read property 'length' of undefined` error

However, this code is valid. I don't know why, but my own local setup doesn't compile it.

Content of package.json:

{
  "name": "fast-test",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "build": "babel -d lib src"
  },
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-plugin-transform-es2015-spread": "^6.22.0",
    "babel-plugin-transform-flow-strip-types": "^6.22.0",
    "babel-plugin-transform-object-rest-spread": "^6.26.0",
    "babel-preset-es2015": "^6.24.1",
    "fast-async": "^6.3.0"
  }
}

Content of .babelrc:

{
  "presets": [
    "es2015"
  ],
  "plugins": [
    [
      "fast-async",
      {
        "env": {
          "log": false
        },
        "compiler": {
          "promises": true,
          "generators": false
        },
        "runtimePattern": "directive",
        "useRuntimeModule": false
      }
    ],
    "transform-flow-strip-types",
    "transform-es2015-spread",
    "transform-object-rest-spread"
  ]
}

Content of src/index.js:

async function on(id, cbk) {
  if (!id || !cbk) return;
  for (const sub of this.subs) {
    if (sub.id === id && sub.cbk === cbk) return sub;
  }

  const sub = new Subscription(this, id, cbk);
  this.subs.push(sub);
  await sub.on();
  return sub;
}

And the output is:

โ–ณ ~/Projects/fast-test yarn build
yarn run v1.3.2
$ babel -d lib src
TypeError: src/index.js: Cannot read property 'length' of undefined
    at Buffer._append (/Users/olebedev/Projects/fast-test/node_modules/babel-generator/lib/buffer.js:100:26)
    at Buffer.append (/Users/olebedev/Projects/fast-test/node_modules/babel-generator/lib/buffer.js:72:10)
    at Generator._append (/Users/olebedev/Projects/fast-test/node_modules/babel-generator/lib/printer.js:206:52)
    at Generator.word (/Users/olebedev/Projects/fast-test/node_modules/babel-generator/lib/printer.js:131:10)
    at Generator.Identifier (/Users/olebedev/Projects/fast-test/node_modules/babel-generator/lib/generators/types.js:38:8)
    at /Users/olebedev/Projects/fast-test/node_modules/babel-generator/lib/printer.js:298:23
    at Buffer.withSource (/Users/olebedev/Projects/fast-test/node_modules/babel-generator/lib/buffer.js:159:28)
    at Generator.withSource (/Users/olebedev/Projects/fast-test/node_modules/babel-generator/lib/printer.js:189:15)
    at Generator.print (/Users/olebedev/Projects/fast-test/node_modules/babel-generator/lib/printer.js:297:10)
    at Generator.printJoin (/Users/olebedev/Projects/fast-test/node_modules/babel-generator/lib/printer.js:366:12)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

What I am doing wrong?


I've added workaround into babel-generator and the result we surprised for me. Here to finction above, complied by babel in command line:

function on(id, cbk) {
  return new Promise(function ($return, $error) {
    var $Try_1_Finally = function ($Try_1_Exit) {
      return function ($Try_1_Value) {
        var $Try_2_Finally = function ($Try_2_Exit) {
          return function ($Try_2_Value) {
            if (_didIteratorError) {
              throw _iteratorError;
            }

            return $Try_2_Exit && $Try_2_Exit.call(this, $Try_2_Value);
          }.$asyncbind(this, $error);
        }.$asyncbind(this);

        var $Try_2_Catch = function ($exception_3) {
          throw $exception_3;
        }.$asyncbind(this, $Try_2_Finally($error));
        try {
          if (!_iteratorNormalCompletion && _iterator.return) {
            _iterator.return();
          }

          return $Try_2_Finally()();
        } catch ($exception_3) {
          $Try_2_Catch($exception_3)
        }

        return $Try_1_Exit && $Try_1_Exit.call(this, $Try_1_Value);
      }.$asyncbind(this, $error);
    }.$asyncbind(this);

    var _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, _sub, sub;

    if (!id || !cbk) return $return();
    _iteratorNormalCompletion = true;
    _didIteratorError = false;
    _iteratorError = undefined;
    var $Try_1_Post = function () {

      sub = new Subscription(this, id, cbk);
      this.subs.push(sub);
      return sub.on().then(function ($await_11) {
        return $return(sub);
      }.$asyncbind(this, $error), $error);
    }.$asyncbind(this, $error);var $Try_1_Catch = function (err) {
      _didIteratorError = true;
      _iteratorError = err;
      return $Try_1_Finally($Try_1_Post)();
    }.$asyncbind(this, $Try_1_Finally($error));
    try {
      for (_iterator = this.subs[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
        _sub = _step.value;

        if (_sub.id === id && _sub.cbk === cbk) return $Try_1_Finally($return)(_sub);
      }return $Try_1_Finally($Try_1_Post)();
    } catch (err) {
      $Try_1_Catch(err)
    }
  }.$asyncbind(this));
}

Compare it with nodent.mailed.me.uk's result, the difference is a huge. The question is, why so? And, how to setup babel to have a nice output like from nodent.mailed.me.uk ?

/cc @MatAtBread

try/finally not working?

I don't have detailed repro steps yet, but this seems to confuse fast-async:

try {
  // some stuff
  try {
    // some more stuff
  } finally {
    // cleanup stuff
  }
  // super important stuff
} catch (error) {
  // whatever
}

Basically, after "cleanup stuff" is run, it just falls off into the ether somewhere. "super important stuff" is never run.

About a webpack warning: Duplicate declaration

When using await within for..of
Here is a warning

webpack: wait until bundle finished:
	Duplicate declaration '_iterator = _isArray ? _iterator : _iterator[Symbol.iterator]()'
	Duplicate declaration '_iterator = _isArray ? _iterator : _iterator[Symbol.iterator]()'


 DONE  Compiled successfully in 5303ms

I'm usingwebpack 2.3.3

Is there a way to remove this warning, I know this is just a Duplicate declaration

When using await within for..of , You can see this warning, like below:

async function loadCityList(Vue, store, city = "") {

  if (store.getters.getCityList.length > 0) return store.getters.getCityList()

  let cityList = await Vue.$api.supplier.getSupplierCityList({city})

  if (cityList.length == 0) return cityList

  let _cityList = []

  for (let city of cityList) {
    city = {
      cityCode: city.city,
      cityName: city.strCity,
      baiduAreaCode: city.baiduAreaCode,
      supplierList: []  
    }

    let supplierList = await Vue.$api.supplier.getSupplierList({
      "city": city.cityCode,
      "userId": 0,
      "weCharOpenId": Vue.$config.weCharOpenId
    })

    city.supplierList = supplierList.map(supplier => {
      return {
        city: city,
        strVal1: supplier.strVal1,
        supplierId: supplier.supplierId,
        supplierLogo: supplier.supplierLogo,
        supplierPic: supplier.supplierPic,
        supplierCode: supplier.supplierCode,
        supplierName: supplier.supplierName,
        supplierFullName: supplier.supplierFullName,
      }
    })
    _cityList.push(city)
  }

after build:

function loadCityList(Vue, store) {
  var $args = arguments;return new Promise(function ($return, $error) {
    var city, cityList, _cityList, _loop, _iterator, _isArray, _i, _ref, _city;

    city = $args.length > 2 && $args[2] !== undefined ? $args[2] : "";

    if (store.getters.getCityList.length > 0) return $return(store.getters.getCityList());

    return Vue.$api.supplier.getSupplierCityList({ city: city }).then(function ($await_3) {
      cityList = $await_3;

      if (cityList.length == 0) return $return(cityList);

      _cityList = [];

      _loop = function _loop(_city2) {
        return new Promise(function ($return, $error) {
          var supplierList;

          _city2 = {
            cityCode: _city2.city,
            cityName: _city2.strCity,
            baiduAreaCode: _city2.baiduAreaCode,
            supplierList: [] };

          return Vue.$api.supplier.getSupplierList({
            "city": _city2.cityCode,
            "userId": 0,
            "weCharOpenId": Vue.$config.weCharOpenId
          }).then(function ($await_4) {
            supplierList = $await_4;

            _city2.supplierList = supplierList.map(function (supplier) {
              return {
                city: _city2,
                strVal1: supplier.strVal1,
                supplierId: supplier.supplierId,
                supplierLogo: supplier.supplierLogo,
                supplierPic: supplier.supplierPic,
                supplierCode: supplier.supplierCode,
                supplierName: supplier.supplierName,
                supplierFullName: supplier.supplierFullName
              };
            });
            _cityList.push(_city2);
            _city = _city2;
            return $return();
          }.$asyncbind(this, $error), $error);
        }.$asyncbind(this));
      };
       // Here is the warning source...
       // Duplicate declaration '_iterator = _isArray ? _iterator : _iterator[Symbol.iterator]()'
      _iterator = cityList, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();
      return Function.$asyncbind.trampoline(this, $Loop_1_exit, $Loop_1, $error, true)($Loop_1);

      function $Loop_1() {
        if (true) {
          if (_isArray) {
            if (_i >= _iterator.length) return [1];
            _ref = _iterator[_i++];
          } else {
            _i = _iterator.next();
            if (_i.done) return [1];
            _ref = _i.value;
          }

          _city = _ref;
          return _loop(_city).then(function ($await_5) {
            return $Loop_1;
          }.$asyncbind(this, $error), $error);
        } else return [1];
      }

      function $Loop_1_exit() {
        store.commit("updateCityList", _cityList);

        store.commit("updateCurrentSupplierId", store.getters.getCurrentSupplierId || _cityList[0].supplierList[0].supplierId);

        store.commit("updateCurrentCityId", store.getters.getCurrentSupplier.city.cityCode);

        return $return(_cityList);
      }
    }.$asyncbind(this, $error), $error);
  }.$asyncbind(this));
}

Here is my .babelrc:

{
  "presets": [
    ["env", {
      "modules": false,
      "debug": false,
      "useBuiltIns": true,
      "loose": true,
      "exclude": [
        // for using fast-async
        "transform-regenerator",
        "transform-async-to-generator",

        "transform-es2015-unicode-regex",
        "transform-exponentiation-operator",
      ]
    }],
    // "stage-3" just use babel-plugin-transform-object-rest-spread
  ],
  "plugins": [
    "babel-plugin-transform-object-rest-spread",
    // https://github.com/MatAtBread/fast-async
    ["fast-async", {
      "env": {
        "augmentObject": false,
        "dontMapStackTraces": true,
        "dontInstallRequireHook": true
      },
      "compiler": {
        "promises": true,
        "generators": false
      },
      "runtimePattern": null,
      // using nodent-runtime like transform-runtime of babel
      "useRuntimeModule": true
    }],
    // "transform-runtime"
  ],
  "comments": false,
  "env": {
    "test": {
      "presets": ["env", "stage-2"],
      "plugins": [ "istanbul" ]
    }
  }
}

Destructuring still broken?

      const { body: responseBody, status } = customerSearchResults;
      const { _embedded = {} } = responseBody;
      const { customers = [] } = _embedded || {};
      const [customer] = customers || [];
      const { id: customerId } = customer || {};

I end up with an error saying _embedded is not defined (probably on line 3 there if the sourcemap is to be believed).

It transpiles to this:

              ({ body: responseBody, status } = customerSearchResults);
              ({ _embedded = {} } = responseBody);
              ({ customers = [] } = _embedded || {});
              [customer] = customers || [];
              ({ id: customerId } = customer || {});

Which doesn't look wrong, but somehow ends up failing, perhaps because of the 'use strict'?

Non-trivial destructuring initializers are broken

fast-async badly transforms destructuring initializers using anything other than the trivial forms const [a, b, c] = ... or const { a, b, c } = ...; inside any async functions, even if the RHS is not an await expression.
Further, it fails to parse array rest (ES2015, so not #6), and fails while transforming array eliding.

// work
async function trivialArray() {
  const [a, b] = await Promise.resolve([1, 2]);
  console.log(a, b);
}
async function trivialObject() {
  const { a, b } = await Promise.resolve({ a: 1, b: 2 });
  console.log(a, b);
}

// fails in parse
//async function arraySpread() {
//  const [a, ...b, c] = await Promise.resolve([1, 2, 3, 4]);
//  console.log(a, b, c);
//}

// fails in transform
//async function arrayElide() {
//  const [,a,,b] = await Promise.resolve([1, 2, 3, 4]);
//  console.log(a, b);
//}

// generate bad code, only declaring `var a, b`
async function rename() {
  const { a, b: c } = await Promise.resolve({ a: 1, b: 2 });
  console.log(a, c);
}
async function key() {
  const { a, ['b']: c } = await Promise.resolve({ a: 1, b: 2 });
  console.log(a, c);
}
async function nestedArray() {
  const { a, b: [c, d] } = await Promise.resolve({ a: 1, b: [2, 3] });
  console.log(a, c, d);
}
async function nestedObject() {
  const { a, b: { c, d } } = await Promise.resolve({ a: 1, b: { c: 2, d: 3 } });
  console.log(a, c, d);
}
async function indirect() {
  const result = await Promise.resolve({ a: 1, b: 2 });
  const { a, b: c } = result;
  console.log(a, c);
}

Output is:

% babel --preset es2015 --plugins syntax-async-functions,fast-async async.js
Function.prototype.$asyncbind = <snip>

// work
function trivialArray() {
  return new Promise(function ($return, $error) {
    var a, b;
    return Promise.resolve([1, 2]).then(function ($await_1) {
      [a, b] = $await_1;

      console.log(a, b);
      return $return();
    }.$asyncbind(this, $error), $error);
  }.$asyncbind(this));
}
function trivialObject() {
  return new Promise(function ($return, $error) {
    var a, b;
    return Promise.resolve({ a: 1, b: 2 }).then(function ($await_2) {
      ({ a, b } = $await_2);

      console.log(a, b);
      return $return();
    }.$asyncbind(this, $error), $error);
  }.$asyncbind(this));
}

// fails in parse
//async function arraySpread() {
//  const [a, ...b, c] = await Promise.resolve([1, 2, 3, 4]);
//  console.log(a, b, c);
//}

// fails in transform
//async function arrayElide() {
//  const [,a,,b] = await Promise.resolve([1, 2, 3, 4]);
//  console.log(a, b);
//}

// generate bad code, only declaring `var a, b`
function rename() {
  return new Promise(function ($return, $error) {
    var a, b;
    return Promise.resolve({ a: 1, b: 2 }).then(function ($await_3) {
      ({ a, b: c } = $await_3);

      console.log(a, c);
      return $return();
    }.$asyncbind(this, $error), $error);
  }.$asyncbind(this));
}
function key() {
  return new Promise(function ($return, $error) {
    var a, undefined;
    return Promise.resolve({ a: 1, b: 2 }).then(function ($await_4) {
      ({ a, ['b']: c } = $await_4);

      console.log(a, c);
      return $return();
    }.$asyncbind(this, $error), $error);
  }.$asyncbind(this));
}
function nestedArray() {
  return new Promise(function ($return, $error) {
    var a, b;
    return Promise.resolve({ a: 1, b: [2, 3] }).then(function ($await_5) {
      ({ a, b: [c, d] } = $await_5);

      console.log(a, c, d);
      return $return();
    }.$asyncbind(this, $error), $error);
  }.$asyncbind(this));
}
function nestedObject() {
  return new Promise(function ($return, $error) {
    var a, b;
    return Promise.resolve({ a: 1, b: { c: 2, d: 3 } }).then(function ($await_6) {
      ({ a, b: { c, d } } = $await_6);

      console.log(a, c, d);
      return $return();
    }.$asyncbind(this, $error), $error);
  }.$asyncbind(this));
}
function indirect() {
  return new Promise(function ($return, $error) {
    var result, a, b;
    return Promise.resolve({ a: 1, b: 2 }).then(function ($await_7) {
      result = $await_7;
      ({ a, b: c } = result);

      console.log(a, c);
      return $return();
    }.$asyncbind(this, $error), $error);
  }.$asyncbind(this));
}

Array rest gives error:

% babel --preset es2015 --plugins syntax-async-functions,fast-async async.js
SyntaxError: async.js: Unexpected token (10:16)
   8 | }
   9 | async function arraySpread() {
> 10 |   const [a, ...b, c] = await Promise.resolve([1, 2, 3, 4]);
     |                 ^
  11 |   console.log(a, b, c);
  12 | }
  13 | async function rename() {

Without fast-async:

% babel --preset es2015 --plugins syntax-async-functions array_rest.js
async function test() {
  const [a, ...b] = [1, 2, 3];
  console.log(a, b);
}

Array elide gives error:

% babel --preset es2015 --plugins syntax-async-functions,fast-async async.js
TypeError: async.js: Cannot read property 'type' of null
    at getDeclNames (/home/simon/code/xxx/node_modules/nodent/lib/arboriculture.js:2010:19)
    at /home/simon/code/xxx/node_modules/nodent/lib/arboriculture.js:2014:70
    at Array.reduce (native)
    at getDeclNames (/home/simon/code/xxx/node_modules/nodent/lib/arboriculture.js:2014:32)
    at /home/simon/code/xxx/node_modules/nodent/lib/arboriculture.js:2061:29
    at treeWalker (/home/simon/code/xxx/node_modules/nodent/lib/parser.js:156:5)
    at goDown (/home/simon/code/xxx/node_modules/nodent/lib/parser.js:122:9)
    at down (/home/simon/code/xxx/node_modules/nodent/lib/parser.js:146:25)
    at Object.base.Function (/home/simon/code/xxx/node_modules/acorn/dist/walk.js:269:4)
    at down (/home/simon/code/xxx/node_modules/nodent/lib/parser.js:133:60)

SyntaxError: Strict mode does not allow function declarations in a lexically nested statement

fast-async compiled code throws SyntaxError: Strict mode does not allow function declarations in a lexically nested statement in IOS 9.x.

.babelrc :

{
  "plugins": [
    [
      "transform-runtime", {
        "polyfill": false,
        "regenerator": false
      }
    ],
    [
      "fast-async", {
        "env": {
          "log": false
        },
        "compiler": {
          "promises": true,
          "generators": false,
          "noRuntime": true
        },
        "runtimePattern": null,
        "useRuntimeModule": true
      }
    ]
  ]
}

source code:

async(ctx, next) => {
  if (ctx.method != 'GET') {
    const request = serializeRequest(ctx);
    if (!requestLimits[request]) {
      await next();
    }
  } else {
    await next();
  }
}

compiled code:

function (ctx, next) {
  return new Promise(function ($return, $error) {
    var request;

    if (ctx.method != 'GET') {
      request = serializeRequest(ctx);
      if (!requestLimits[request]) {
        return next().then(function ($await_5) {
          try {
            return $If_4.call(this);
          } catch ($boundEx) {
            return $error($boundEx);
          }
        }.bind(this), $error);
      }

      function $If_4() { // throws SyntaxError: Strict mode does not allow function declarations in a lexically nested statement
        return $If_3.call(this);
      }

      return $If_4.call(this);
    } else {
      return next().then(function ($await_6) {
        try {
          return $If_3.call(this);
        } catch ($boundEx) {
          return $error($boundEx);
        }
      }.bind(this), $error);
    }

    function $If_3() {
      return $return();
    }
  }.bind(this));
}

Could you fix this? Thanks very much for your hard work.

Error: unknown node of type "Literal" with constructor "Object"

I wanted to give a fast-async a second shot but unfortunately it didn't work. I did nail down the problem to this piece of code though.

let foo = async () => {
  for(let bar of []) {
    await Promise.resolve();
  }
};

Full error:

/code/babel-fast-async-test/node_modules/babel-core/lib/transformation/file/index.js:600
      throw err;
      ^

ReferenceError: /code/babel-fast-async-test/index.js: unknown node of type "Literal" with constructor "Object"
    at Generator.print (/code/babel-fast-async-test/node_modules/babel-generator/lib/printer.js:279:13)
    at Generator.MemberExpression (/code/babel-fast-async-test/node_modules/babel-generator/lib/generators/expressions.js:228:10)
    at /code/babel-fast-async-test/node_modules/babel-generator/lib/printer.js:298:23
    at Buffer.withSource (/code/babel-fast-async-test/node_modules/babel-generator/lib/buffer.js:151:5)
    at Generator.withSource (/code/babel-fast-async-test/node_modules/babel-generator/lib/printer.js:189:15)
    at Generator.print (/code/babel-fast-async-test/node_modules/babel-generator/lib/printer.js:297:10)
    at Generator.AssignmentExpression (/code/babel-fast-async-test/node_modules/babel-generator/lib/generators/expressions.js:189:8)
    at /code/babel-fast-async-test/node_modules/babel-generator/lib/printer.js:298:23
    at Buffer.withSource (/code/babel-fast-async-test/node_modules/babel-generator/lib/buffer.js:151:5)
    at Generator.withSource (/code/babel-fast-async-test/node_modules/babel-generator/lib/printer.js:189:15)

My .babelrc:

{
  "presets": ["es2015-node6"],
  "plugins": ["transform-decorators-legacy", "transform-class-properties", "transform-es2015-modules-commonjs", "transform-strict-mode", "transform-es2015-spread", "transform-es2015-destructuring", "transform-es2015-block-scoping", ["fast-async", {
    "compiler": {
      "sourcemap": true
    }
  }]]
}

To reproduce:

wget http://x.rushbase.net/ad01410a94ea35c0d57d86ddfe4eedd4da29c877/babel-fast-async-test.zip
cd babel-fast-async-test
npm install
node -r babel-register index.js

await on literal value causes error

In such code:

const getSearchCount = () => {
  return await {
    repoCount: 100,
    codeCount: 20
  };
};

fast-async will generate wrong code such as (copied from console):

function getSearchCount(keyword) {
  return new Promise(function ($return, $error) {
    return {
      repoCount: 100,
      codeCount: 20
    }.then($return, $error);
  }.$asyncbind(this));
}

which obviously leads to error (object does not have then method)

"await is a reserved word"

I will get right to the point:

.babelrc:

{
  "presets": [
    ["@babel/env", {
      "targets": {
        "node": "current"
      }
    }]
  ],
  "plugins": [
    "module:fast-async",
    ["babel-plugin-module-resolver", {
      "alias": {
        "BIRD3": "./src"
      }
    }],
    ["@babel/plugin-proposal-class-properties", {
      "loose": true
    }],
    ["@babel/plugin-transform-react-jsx", {
      "pragma": "h",
      "pragmaFrag": "fragment",
      "throwIfNamespace": false
    }]
  ]
}

Error:

{ SyntaxError: /Users/Ingwie/Work/DragonsInn/BIRD3/test2.js: await is a reserved word (8:14)

   6 |   init() {
   7 |     try {
>  8 |       let a = await someFunction();
     |               ^
   9 |       let b = await someFunction();
  10 |       console.log("Math:" + (a+b))
  11 |     } catch(e) throw e;
    at _class.raise (/usr/local/lib/node_modules/@babel/core/node_modules/@babel/parser/lib/index.js:4021:15)
    at _class.checkReservedWord (/usr/local/lib/node_modules/@babel/core/node_modules/@babel/parser/lib/index.js:7146:12)
    at _class.parseIdentifierName (/usr/local/lib/node_modules/@babel/core/node_modules/@babel/parser/lib/index.js:7111:12)
    at _class.parseIdentifier (/usr/local/lib/node_modules/@babel/core/node_modules/@babel/parser/lib/index.js:7103:21)
    at _class.parseExprAtom (/usr/local/lib/node_modules/@babel/core/node_modules/@babel/parser/lib/index.js:6296:25)
    at _class.parseExprAtom (/usr/local/lib/node_modules/@babel/core/node_modules/@babel/parser/lib/index.js:3717:52)
    at _class.parseExprSubscripts (/usr/local/lib/node_modules/@babel/core/node_modules/@babel/parser/lib/index.js:6006:21)
    at _class.parseMaybeUnary (/usr/local/lib/node_modules/@babel/core/node_modules/@babel/parser/lib/index.js:5985:21)
    at _class.parseExprOps (/usr/local/lib/node_modules/@babel/core/node_modules/@babel/parser/lib/index.js:5894:21)
    at _class.parseMaybeConditional (/usr/local/lib/node_modules/@babel/core/node_modules/@babel/parser/lib/index.js:5866:21)
  pos: 94,
  loc: Position { line: 8, column: 14 },
  code: 'BABEL_PARSE_ERROR' }

Versions:

[email protected] ~/W/D/BIRD3 $ babel --version
7.1.5 (@babel/core 7.1.5)
[email protected] ~/W/D/BIRD3 $ cat package.json | grep babel
    "@babel/cli": "^7.1.5",
    "@babel/core": "^7.1.5",
    "@babel/plugin-proposal-class-properties": "^7.1.0",
    "@babel/plugin-transform-object-super": "^7.0.0",
    "@babel/plugin-transform-react-jsx": "^7.0.0",
    "@babel/preset-env": "^7.1.5",
    "babel-loader": "^8.0.2",
    "babel-plugin-module-resolver": "^3.1.1",
[email protected] ~/W/D/BIRD3 $ cat package.json | grep fast-async
    "fast-async": "^7",
[email protected] ~/W/D/BIRD3 $ node --version
v11.1.0

What I am trying to do is, to test various transformer plugins on the CLI before adding them to my WebPack build. I wanted to test fast-async to see if it transforms async and await in the way that I want.

While I am at it: How do I tell the plugin to only include the NoDent runtime once for many files, so it doesn't blow up the whole build in the end?

Well, I tried removing various entries from the .babelrc and even tried without a .babelrc entirely, with the plugin just specified on the CLI, and get the same error each and every time. What am I doing wrong here? :)

Also, the code I am trying to transpile:

async function someFunction() {
  return 1;
}

class Foo {
  init() {
    try {
      let a = await someFunction();
      let b = await someFunction();
      console.log("Math:" + (a+b))
    } catch(e) throw e;
  }
}

new Foo().init();

Crashes if compiler options are missing

There are no defaults for state.opts.compiler

Crash happens here (plugin.js):

Object.keys(state.opts.compiler).forEach(function(k){
    compilerOpts[k] = state.opts.compiler[k] ;
}) ;

Issues with source maps

  • Source maps are not enabled by default
  • The first babel run on the file does not have working source maps

To reproduce the second:

git clone https://github.com/Rush/fasy-async-sourcemaps-test
cd fasy-async-sourcemaps-test
npm install
npm test

You will see both first and second run:

> [email protected] test /code/fasy-async-sourcemaps-test
> rm -f ~/.babel.json && node run-fastasync.js && node run-fastasync.js

Error
    at Foo.$ForStatement_1_loop (/code/fasy-async-sourcemaps-test/test.js:165:31)
    at Function.boundThen [as then] (/code/fasy-async-sourcemaps-test/test.js:132:21)
    at /code/fasy-async-sourcemaps-test/test.js:170:35
    at Foo.<anonymous> (/code/fasy-async-sourcemaps-test/test.js:174:12)
    at boundThen (/code/fasy-async-sourcemaps-test/test.js:132:21)
    at Foo.liveBackup (/code/fasy-async-sourcemaps-test/test.js:149:14)
    at Object.<anonymous> (/code/fasy-async-sourcemaps-test/test.js:216:11)
    at Module._compile (module.js:556:32)
    at loader (/code/fasy-async-sourcemaps-test/node_modules/babel-register/lib/node.js:143:5)
    at Object.require.extensions.(anonymous function) [as .js] (/code/fasy-async-sourcemaps-test/node_modules/babel-register/lib/node.js:153:7)
Error
    at $ForStatement_1_loop (/code/fasy-async-sourcemaps-test/test.js:165:31)
    at Foo.$ForStatement_1_next (/code/fasy-async-sourcemaps-test/test.js:161:26)
    at Foo.<anonymous> (/code/fasy-async-sourcemaps-test/test.js:167:54)
    at then (/code/fasy-async-sourcemaps-test/test.js:125:126)
    at process._tickCallback (internal/process/next_tick.js:103:7)
    at Module.runMain (module.js:592:11)
    at run (bootstrap_node.js:394:7)
    at startup (bootstrap_node.js:149:9)
    at bootstrap_node.js:509:3
Error
    at $ForStatement_1_loop (/code/fasy-async-sourcemaps-test/test.js:165:31)
    at $ForStatement_1_next (/code/fasy-async-sourcemaps-test/test.js:161:26)
    at /code/fasy-async-sourcemaps-test/test.js:167:54
    at then (/code/fasy-async-sourcemaps-test/test.js:125:126)
    at process._tickCallback (internal/process/next_tick.js:103:7)
    at Module.runMain (module.js:592:11)
    at run (bootstrap_node.js:394:7)
    at startup (bootstrap_node.js:149:9)
    at bootstrap_node.js:509:3
foo
Error
    at Foo.$ForStatement_1_loop (/code/fasy-async-sourcemaps-test/test.js:8:17)
    at Function.boundThen [as then] (/code/fasy-async-sourcemaps-test/test.js:132:21)
    at /code/fasy-async-sourcemaps-test/test.js:5:1
    at Foo.<anonymous> (/code/fasy-async-sourcemaps-test/test.js:5:1)
    at boundThen (/code/fasy-async-sourcemaps-test/test.js:132:21)
    at Foo.liveBackup (/code/fasy-async-sourcemaps-test/test.js:5:1)
    at Object.<anonymous> (/code/fasy-async-sourcemaps-test/test.js:18:11)
    at Module._compile (module.js:556:32)
    at loader (/code/fasy-async-sourcemaps-test/node_modules/babel-register/lib/node.js:143:5)
    at Object.require.extensions.(anonymous function) [as .js] (/code/fasy-async-sourcemaps-test/node_modules/babel-register/lib/node.js:153:7)
Error
    at $ForStatement_1_loop (/code/fasy-async-sourcemaps-test/test.js:8:17)
    at Foo.$ForStatement_1_next (/code/fasy-async-sourcemaps-test/test.js:5:1)
    at Foo.<anonymous> (/code/fasy-async-sourcemaps-test/test.js:9:5)
    at then (/code/fasy-async-sourcemaps-test/test.js:125:126)
    at process._tickCallback (internal/process/next_tick.js:103:7)
    at Module.runMain (module.js:592:11)
    at run (bootstrap_node.js:394:7)
    at startup (bootstrap_node.js:149:9)
    at bootstrap_node.js:509:3
Error
    at $ForStatement_1_loop (/code/fasy-async-sourcemaps-test/test.js:8:17)
    at $ForStatement_1_next (/code/fasy-async-sourcemaps-test/test.js:5:1)
    at /code/fasy-async-sourcemaps-test/test.js:9:5
    at then (/code/fasy-async-sourcemaps-test/test.js:125:126)
    at process._tickCallback (internal/process/next_tick.js:103:7)
    at Module.runMain (module.js:592:11)
    at run (bootstrap_node.js:394:7)
    at startup (bootstrap_node.js:149:9)
    at bootstrap_node.js:509:3
foo

In contrast the bluebird version works fine:

node run-bluebird.js

broken interaction with babel modules transform

To reproduce:

// foo.js
export default async function bar() {}
bar.SOMETHING = 3
// .babelrc
{
  "plugins": [
    "transform-es2015-modules-commonjs",
    "fast-async"
  ]
}

And run npm install fast-async babel-cli babel-plugin-transform-es2015-modules-commonjs.

Running ./node_modules/.bin/babel-node foo.js then gives:

bar.SOMETHING = 3;
^

ReferenceError: bar is not defined

Await above for...of causes compilation error

This only occurs in combination with transform-es2015-for-of in loose mode.

This code:

async function run(filePath) {
  const fileContents = await readFileAsync(filePath, 'utf8');
  for (const field of fileContents) {
  }
}

Compiles to:

    Duplicate declaration '_iterator = _isArray ? _iterator : _iterator[Symbol.iterator]()'
import _default from 'nodent-runtime';
function run(languages) {
  return new Promise(function ($return, $error) {
    var fileContents, _iterator, _isArray, _i, _ref, field;

    return readFileAsync(filePath, 'utf8').then(function ($await_1) {
      fileContents = $await_1;

      for ({
        _iterator = fileContents
        _isArray = Array.isArray(_iterator)
        _i = 0
        _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]()
      };;) {
        if (_isArray) {
          if (_i >= _iterator.length) break;
          _ref = _iterator[_i++];
        } else {
          _i = _iterator.next();
          if (_i.done) break;
          _ref = _i.value;
        }

        field = _ref;
      }
      return $return();
    }.$asyncbind(this, $error), $error);
  }.$asyncbind(this));
}

Notice the error in the top line and the very odd for() syntax.

.babelrc:

{
  "plugins": [
    ['transform-es2015-for-of', {loose: true}],
    'syntax-async-functions',
    ['fast-async', {
      useRuntimeModule: 'nodent-runtime'
    }]
  ]
}

ReferenceError: unknown node of type "Literal" with constructor "Object"

Hi!

A user of Neutrino reported an issue with their project when they updated their dependencies (neutrinojs/neutrino#984) that upon creating a reduced testcase, appears to be due to fast-async / nodent-compiler regression.

The exception no longer occurs if nodent-compiler is rolled back to v3.1.8 (eg using yarn's resolutions feature). The first version of nodent-compiler that triggers the exception is v3.2.0.

STR:

  1. Clone https://github.com/edmorley/testcase-fast-async-unknown-node
  2. yarn
  3. yarn babel testcase.js

Expected:

Command completes successfully, or else if the testcase's syntax is invalid, a helpful error message is output.

Actual:

ReferenceError: testcase.js: unknown node of type "Literal" with constructor "Object"
    at Generator.print (...\node_modules\babel-generator\lib\printer.js:279:13)
    at Generator.MemberExpression (...\node_modules\babel-generator\lib\generators\expressions.js:229:10)
    at ...\node_modules\babel-generator\lib\printer.js:298:23
    at Buffer.withSource (...\node_modules\babel-generator\lib\buffer.js:159:28)
    at Generator.withSource (...\node_modules\babel-generator\lib\printer.js:189:15)
    at Generator.print (...\node_modules\babel-generator\lib\printer.js:297:10)
    at Generator.AssignmentExpression (...\node_modules\babel-generator\lib\generators\expressions.js:190:8)
    at ...\node_modules\babel-generator\lib\printer.js:298:23
    at Buffer.withSource (...\node_modules\babel-generator\lib\buffer.js:159:28)
    at Generator.withSource (...\node_modules\babel-generator\lib\printer.js:189:15)

6.1.1: regeneratorRuntime is not defined

I have a 'regeneratorRuntime is not defined' bug with 6.1.1 (everything was fine with previous versions)

My .babelrc is similar to the minimal .babelrc example :

{ "plugins": ["fast-async"] }

errors to console

Hello! Can this plugin output unhandled error to err stream?

async function someFunctionWithUncatchedError(){
    throw new Error(123);  //nothing output from hire to err stream/ silent break function and very hard to debug code
    try {
        throw new Error(123);   //this error will be handled
    }
    catch(er){
        console.error(er)    
    }
}

someFunctionWithUncatchedError();

Promise is undefined

How do I use this for IE9? I have in .babelrc:

      ["fast-async", {
        "compiler": {
          "promises": false
        },
        "useRuntimeModule": true
      }],

and even import nodent-runtime in my main file, but I keep seeing that Promise is undefined in IE. Could you please explain how to use it :(( it's so frustrating -- do I need to update webpack config to provide global Promise?

Cannot append Element node to non-array

Hi, I'm trying to switch from transform-async-to-module-method to fast-async, and I bumped into this error. I reduced the code to this minimal example:

test.js:

export const A = '';

class B {
  async f() {
    await g();
  }
}

.babelrc:

{
  "presets": [
    "es2015",
    "stage-0"
  ],
  "plugins": [
    ["fast-async", {
      "runtimePattern": "main.js"
    }],
  ]
}

And it produces the following error:

Error: test.js: Cannot append Element node to non-array
    at Object.append (/home/diego/repos/brainiac-www/node_modules/nodent/lib/parser.js:87:23)
    at /home/diego/repos/brainiac-www/node_modules/nodent/lib/arboriculture.js:2190:34
    at Array.forEach (native)
    at /home/diego/repos/brainiac-www/node_modules/nodent/lib/arboriculture.js:2189:32
    at Object.treeWalker (/home/diego/repos/brainiac-www/node_modules/nodent/lib/parser.js:156:5)
    at hoistDeclarations (/home/diego/repos/brainiac-www/node_modules/nodent/lib/arboriculture.js:2136:16)
    at asyncTransforms (/home/diego/repos/brainiac-www/node_modules/nodent/lib/arboriculture.js:359:9)
    at asynchronize (/home/diego/repos/brainiac-www/node_modules/nodent/lib/arboriculture.js:352:9)
    at NodentCompiler.asynchronize (/home/diego/repos/brainiac-www/node_modules/nodent/lib/arboriculture.js:2657:20)
    at PluginPass.Program (/home/diego/repos/brainiac-www/node_modules/fast-async/plugin.js:36:14)

Is this a bug in fast-async, or perhaps something wrong in my code?

Thanks!

How to create Bluebird promises from async functions

Given the below code, how to configure fast-async/nodent to return bluebird promises?

import Promise from 'bluebird'; 

async function foo() {
  return 'bar';
}
// where .delay is provided by bluebird
foo().delay(3000).then(() => {

});

Babel v7: Env Preset + nodent breaks in Babel generator

I have another exception I got in a pretty trivial case.

Code:

async function executeTasks(tasks) {
  for (const taskName of tasks) {
    try {
      await executeCommands()
    } catch (error) {
      console.error("Error")
    }
  }
}

Babelrc:

{
  "presets": [
    [ "@babel/env", { "exclude": ["transform-regenerator", "transform-async-to-generator"] } ]
  ],

  "plugins": [
    "module:./src/transformAsyncToPromises.js"
  ]
}

Command Line:

node_modules/.bin/babel --config-file ./.babelrc-test --no-babelrc async-for-of.js

Exception:

TypeError: Cannot read property 'length' of undefined
    at Buffer._append (/Users/swerner/Workspace/open-source/babel-preset-edge/node_modules/@babel/generator/lib/buffer.js:115:26)
    at Buffer.append (/Users/swerner/Workspace/open-source/babel-preset-edge/node_modules/@babel/generator/lib/buffer.js:81:10)
    at Generator._append (/Users/swerner/Workspace/open-source/babel-preset-edge/node_modules/@babel/generator/lib/printer.js:202:52)
    at Generator.word (/Users/swerner/Workspace/open-source/babel-preset-edge/node_modules/@babel/generator/lib/printer.js:126:10)
    at Generator.Identifier (/Users/swerner/Workspace/open-source/babel-preset-edge/node_modules/@babel/generator/lib/generators/types.js:43:8)
    at /Users/swerner/Workspace/open-source/babel-preset-edge/node_modules/@babel/generator/lib/printer.js:315:23
    at Buffer.withSource (/Users/swerner/Workspace/open-source/babel-preset-edge/node_modules/@babel/generator/lib/buffer.js:178:28)
    at Generator.withSource (/Users/swerner/Workspace/open-source/babel-preset-edge/node_modules/@babel/generator/lib/printer.js:182:15)
    at Generator.print (/Users/swerner/Workspace/open-source/babel-preset-edge/node_modules/@babel/generator/lib/printer.js:314:10)
    at Generator.printJoin (/Users/swerner/Workspace/open-source/babel-preset-edge/node_modules/@babel/generator/lib/printer.js:382:12)

I modified the generator a bit to catch this case:

  _proto._append = function _append(str, line, column, identifierName, filename) {
    if (this._map && str[0] !== "\n") {
      this._map.mark(this._position.line, this._position.column, line, column, identifierName, filename);
    }

    // Hot fix
    if (str == null) {
      str = "[XXXXX]"
    }

   ...

Generated output with fix:

"use strict";

function executeTasks(tasks) {
  return new Promise(function ($return, $error) {
    var $Try_1_Finally = function ($Try_1_Exit) {
      return function ($Try_1_Value) {
        try {
          var $Try_3_Finally = function ($Try_3_Exit) {
            return function ($Try_3_Value) {
              try {
                if (_didIteratorError) {
                  throw _iteratorError;
                }

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

          var $Try_3_Catch = function ($exception_4) {
            try {
              throw $exception_4;
            } catch ($boundEx) {
              return $Try_3_Finally($error)($boundEx);
            }
          }.bind(this);

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

            return $Try_3_Finally([XXXXX])();
          } catch ($exception_4) {
            $Try_3_Catch($exception_4)
          }

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

    var _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, taskName;

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

    var $Try_1_Post = function () {
      try {
        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 {
      _iterator = tasks[Symbol.iterator]();
      var $Loop_5_trampoline;

      function $Loop_5_step() {
        _iteratorNormalCompletion = true;
        return $Loop_5;
      }

      function $Loop_5() {
        if (!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) {
          taskName = _step.value;

          var $Try_2_Post = function () {
            try {
              return $Loop_5_step;
            } catch ($boundEx) {
              return $Try_1_Catch($boundEx);
            }
          };

          var $Try_2_Catch = function (error) {
            try {
              console.error("Error");
              return $Try_2_Post();
            } catch ($boundEx) {
              return $Try_1_Catch($boundEx);
            }
          };

          try {
            return Promise.resolve(executeCommands()).then(function ($await_7) {
              try {
                return $Try_2_Post();
              } catch ($boundEx) {
                return $Try_2_Catch($boundEx);
              }
            }, $Try_2_Catch);
          } catch (error) {
            $Try_2_Catch(error)
          }
        } else return [1];
      }

      return ($Loop_5_trampoline = function (q) {
        while (q) {
          if (q.then) return void q.then($Loop_5_trampoline, $Try_1_Catch);

          try {
            if (q.pop) {
              if (q.length) return q.pop() ? $Loop_5_exit.call(this) : q;else q = $Loop_5_step;
            } else q = q.call(this);
          } catch (_exception) {
            return $Try_1_Catch(_exception);
          }
        }
      }.bind(this))($Loop_5);

      function $Loop_5_exit() {
        return $Try_1_Finally($Try_1_Post)();
      }
    } catch (err) {
      $Try_1_Catch(err)
    }
  });
}

The problematic code is at line 35:

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

            return $Try_3_Finally([XXXXX])();
          } catch ($exception_4) {
            $Try_3_Catch($exception_4)
          }

Do you have any idea what's wrong?

incorrect code when this is used in async function

This code:

  public async loadBundle() {
    return new Promise((resolve, reject) => {
      if (this.xhr) {
        this.xhr.abort()
        this.xhr = undefined
      }

      this.xhr = $.ajax({
        url: "some url",

        dataType: "script",

        success: () => {
          resolve()
        },

        error: (jqXHR, textStatus, errorThrown) => {
          reject()
        },
      })
    })
  }

converted to:

    loadBundle(bundleID) {
      return new Promise(function ($return, $error) {
        return $return(new Promise((resolve, reject) => {
          if (this.xhr) {
            this.xhr.abort();
            this.xhr = undefined;
          }

          this.xhr = $.ajax({
            url: "some url",
            dataType: "script",
            success: () => {
              resolve()
            },
            error: (jqXHR, textStatus, errorThrown) => {
              reject()
            }
          });
        }));
      });

and this is always undefined here because return new Promise(function ($return, $error) { steals this.

package.json:

    "@babel/core": "^7.1.6",
    "@babel/plugin-proposal-class-properties": "^7.1.0",
    "@babel/plugin-proposal-object-rest-spread": "^7.0.0",
    "@babel/plugin-transform-react-constant-elements": "^7.0.0",
    "@babel/plugin-transform-react-inline-elements": "^7.0.0",
    "@babel/preset-env": "^7.1.6",
    "@babel/preset-react": "^7.0.0",
    "@babel/preset-typescript": "^7.1.0",
    "fast-async": "^7.0.6",

babel.config.js:

{
  compact: false,
  presets: [
    ['@babel/preset-env', {
      targets: ['Since 2018'],
      exclude: ['transform-regenerator']
    }],
    ['@babel/preset-react', { development: isDev }],
    ['@babel/preset-typescript', { isTSX: true, allExtensions: true }]
  ],
  plugins: [
    '@babel/proposal-class-properties',
    '@babel/proposal-object-rest-spread',
    'module:fast-async',
    'add-module-exports',
    'inline-react-svg',
    'add-react-displayname',
  ]
}

Does not transpile defaults in object destructuring

config

{
    "presets": [
      [
        "env",
        {
          "targets": {
            "node": "6.10"
          },
          "exclude": [
            "transform-regenerator",
            "transform-async-to-generator"
          ]
        }
      ]
    ],
    "plugins": [
      "syntax-async-functions",
      [
        "fast-async",
        {
          "useRuntimeModule":true
        }
      ],
      "add-module-exports",
      [
        "transform-object-rest-spread",
        {
          "useBuiltIns": true
        }
      ]
    ]
}

Input:

const {
  bar = async bar => bar
} = {}

async function test ({
  foo = async foo => foo
}, cb = async foo => foo) {
  console.log(foo, cb)
}

output

"use strict";

var _nodentRuntime = require("nodent-runtime");

var _nodentRuntime2 = _interopRequireDefault(_nodentRuntime);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

const {
  bar = async bar => bar
} = {};

function test({
  foo = async foo => foo
}, cb = foo => new Promise(function ($return, $error) {
  return $return(foo);
}.$asyncbind(this))) {
  return new Promise(function ($return, $error) {
    console.log(foo, cb);
    return $return();
  }.$asyncbind(this));
}

Thanks!

I think fast-async and rest-spread is not incompatible

I think fast-async and rest spread is not incompatible
the error sample :

origin es file

(props) => {
  let { ...others } = props
}

babel options

module.exports = {
  "presets": [ "es2015", "stage-2" ],
  "plugins": [
     [require("fast-async"), { runtimePattern: 'directive' }]
  ]
}

exception stack info

"TypeError: Cannot read property 'name' of undefined
    at fast-async\node_modules\nodent\lib\arboriculture.js:2004:63
    at Array.map (native)
    at getDeclNames (fast-async\node_modules\nodent\lib\arboriculture.js:2004:34)
    at fast-async\node_modules\nodent\lib\arboriculture.js:2050:29
    at treeWalker (fast-async\node_modules\nodent\lib\parser.js:156:5)
    at goDown (fast-async\node_modules\nodent\lib\parser.js:122:9)
    at down (fast-async\node_modules\nodent\lib\parser.js:146:25)
    at Object.__dirname.1.base.Function (fast-async\node_modules\nodent\node_modules\acorn\dist\walk.js:269:4)
    at down (fast-async\node_modules\nodent\lib\parser.js:133:60)
    at Object.__dirname.1.base.FunctionDeclaration (fast-async\node_modules\nodent\node_modules\acorn\dist\walk.js:253:10)"

Losing const

I've noticed we lost const in async functions when we use fast-async.

export async function indexPost ({ id }, opts) {
  const input = { ids: [id] }
  await indexPosts(input, opts)
  return { post: { id } }
}
// bluebird
let indexPost = exports.indexPost = (() => {
  var _ref41 = (0, _bluebird.coroutine)(function* ({ id }, opts) {
    const input = { ids: [id] };
    yield indexPosts(input, opts);
    return { post: { id } };
  });

  return function indexPost(_x22, _x23) {
    return _ref41.apply(this, arguments);
  };
})();
// fast-async
function indexPost({ id }, opts) {
  return new Promise(function ($return, $error) {
    var input;
    input = { ids: [id] };
    return indexPosts(input, opts).then(function ($await_109) {
      return $return({ post: { id } });
    }.$asyncbind(this, $error), $error);
  }.$asyncbind(this));
}

My babel config looks like this

{
  "babel": {
    "presets": [
      [
        "env",
        {
          "targets": {
            "node": "6.10"
          },
          "exclude": [
            "transform-regenerator",
            "transform-async-to-generator"
          ]
        }
      ]
    ],
    "plugins": [
      "syntax-async-functions",
      [
        "fast-async",
        {
          "useRuntimeModule": true
        }
      ],
      "add-module-exports",
      [
        "transform-object-rest-spread",
        {
          "useBuiltIns": true
        }
      ]
    ]
  }
}

[bug] Errors when transforming code with for-of loops

Hi!

Seems that some of the more recent version introduces errors during processing. Either babel-v6 is erroring out with unknown node of type "Literal" with constructor "Object" or there are warnings by nodent-transform: arboriculture.js:2327: Duplicate declaration '_iterator = _isArray ? _iterator : _iterator[Symbol.iterator]()'

Simple async code seems to work while it breaks with for-of-loops (works with "normal" for-in loops) and try-catch blocks. This is my reduced example which throws:

async function executeTasks(tasks) {
  for (const taskName of tasks) {
    try {
      await executeCommands()
    } catch (error) {
      console.error("Error")
    }
  }
}

fast-async not working when awaiting non-promise

Consider this small code. It is working with Babel implementation.

async function returnsFive() {
  var three = 3;
  var threeP = await three;
  return threeP+2;
}

returnsFive().then(k=>console.log(k), e=>console.error("err", e))

See babel repl.

With fast-async, I get

index.js:1362 err TypeError: three.then is not a function

That's not good.

I cannot right now find a formal specification for async/await, so I am not sure which implementation is "correct".

add options to select which parts of the runtime will be included

When I load fast-async as a babel plugin with the following configuration {compiler: {noRuntime: false, promises: true}}, the runtime is included in the output file. Currently that runtime is 286 lines long (before minification) and includes things that I don't use, such as support for lazy thenables and the entire Zousan library. I suspect that only a small part of that is actually needed in my case. Is it possible to make fast-async include only a subset of the runtime?

test failed with latest dependencies

$ npm test

> [email protected] test /Users/undozen/github/fa
> cd tests && npm i && node .

npm WARN package.json [email protected] No repository field.
npm WARN package.json [email protected] No README data
[email protected] node_modules/colors

[email protected] node_modules/fast-async
โ””โ”€โ”€ [email protected] ([email protected], [email protected], [email protected])

[email protected] node_modules/babel-plugin-syntax-async-functions
โ””โ”€โ”€ [email protected] ([email protected])

[email protected] node_modules/babel-core
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected] ([email protected])
โ”œโ”€โ”€ [email protected] ([email protected], [email protected])
โ”œโ”€โ”€ [email protected] ([email protected])
โ”œโ”€โ”€ [email protected] ([email protected], [email protected], [email protected])
โ”œโ”€โ”€ [email protected] ([email protected], [email protected], [email protected], [email protected], [email protected])
โ”œโ”€โ”€ [email protected] ([email protected], [email protected], [email protected], [email protected])
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected] ([email protected], [email protected], [email protected], [email protected])
โ””โ”€โ”€ [email protected] ([email protected])
#### To run the tests you need to npm install babel-core. This additional module is only required for testing, not deployment.

Starting tests...
'npm install babel-plugin-transform-async-to-generator babel-preset-es2015' to compare against babel plugin 'transform-async-to-generator'
'npm install babel-plugin-transform-async-to-module-method babel-preset-es2015 bluebird coroutine' to compare against babel plugin 'transform-async-to-module-method'
Transforming with fast-async
TypeError: unknown: Cannot read property 'end' of undefined
    at /Users/undozen/github/fa/tests/node_modules/babel-core/node_modules/babel-generator/lib/whitespace.js:50:19
    at Whitespace._findToken (/Users/undozen/github/fa/tests/node_modules/babel-core/node_modules/babel-generator/lib/whitespace.js:99:30)
    at Whitespace._findToken (/Users/undozen/github/fa/tests/node_modules/babel-core/node_modules/babel-generator/lib/whitespace.js:101:19)
    at Whitespace._findToken (/Users/undozen/github/fa/tests/node_modules/babel-core/node_modules/babel-generator/lib/whitespace.js:101:19)
    at Whitespace._findToken (/Users/undozen/github/fa/tests/node_modules/babel-core/node_modules/babel-generator/lib/whitespace.js:101:19)
    at Whitespace._findToken (/Users/undozen/github/fa/tests/node_modules/babel-core/node_modules/babel-generator/lib/whitespace.js:101:19)
    at Whitespace._findToken (/Users/undozen/github/fa/tests/node_modules/babel-core/node_modules/babel-generator/lib/whitespace.js:101:19)
    at Whitespace._findToken (/Users/undozen/github/fa/tests/node_modules/babel-core/node_modules/babel-generator/lib/whitespace.js:101:19)
    at Whitespace._findToken (/Users/undozen/github/fa/tests/node_modules/babel-core/node_modules/babel-generator/lib/whitespace.js:101:19)
    at Whitespace.getNewlinesAfter (/Users/undozen/github/fa/tests/node_modules/babel-core/node_modules/babel-generator/lib/whitespace.js:49:22)

[Bug] 6.3.2 - Error: Cannot find module '@babel/helper-module-imports'

@babel/helper-module-imports is being used in plugin.js but is not present in package.json's dependencies.

Error: Cannot find module '@babel/helper-module-imports'
    at Function.Module._resolveFilename (module.js:547:15)
    at Function.Module._load (module.js:474:25)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at module.exports (*****/fast-async/plugin.js:10:25)

[bug] infinite recursion (stack overflow) with $super$N helper

I've got some transpiled ode that looks like this:

        disconnectedCallback() {
            return new Promise(function ($return, $error) {
                if (this.$super$1('disconnectedCallback')) this.$super$1('disconnectedCallback').call(this);

and it looks like $super$1('disconnectedCallback').call(this) calls the exact same disconnectedCallback method in an infinite loop.

I'm not sure if this is a fast-async problem, I think probably not, because $super$1 just calls native super. But it is fast-async output, so thought I'd post just in case.

Gonna investigate...

Use Promise from babel-transform-runtime?

babel-transform-runtime transpiles Promise in source code to _Promise which is ultimately the Promise polyfill from core-js.

Is it possible to make fast-async use transform-runtime promises?

Currently, when I set the fast-async option compiler.promises to true, it result in Promise appearing in the output.

Then, I thought that if I change the ordering of plugins so that fast-async runs before transform-runtime, that transform-runtime would handle these Promises, but this isn't the case. transform-runtime is leaving those in the output unpolyfilled. If I try swapping the order of the two plugins, no luck.

If I set compiler.promises to false, then I see Nodent's Promise polyfill included (which is extra duplication).


A possible workaround could be that I can have a separate Babel step using only fast-async to convert async functions on first pass with promises: true, then the second pass of Babel would catch those Promises. This will obviously take more time, but the output will be better (I think?).

Benchmarks?

I know this isn't an 'issue', but I've been battling against this myself. Here's my scenaro:

  • Code calls a function to lookup value (async)
  • If value is cached, return straight from cache.
  • If value not cached, go fetch (websocket call actual async)

In short, I'm using an async code path that is potentially async in some places - but actually 99% of the time - totally sync. What I've been finding is that Promise.resolve(cachedValue) would bounce off the queue, causing massive slowdown. Your module is a massive improvement I find over the naive Promise based approach.

Been trying to benchmark a scenario where I do 200,000 operations, and finding that I'm not getting a massive uplift from fast-async. I'm wondering if this is a Node 6.4 or Babel improvement, because I only get a material difference when using babel-plugin-transform-bluebird - but even then it's nowhere near as fast as a pure sync solution - there's a serious amount of performance being lost.

  • fast-async / Native promises - 2758msec
  • fast-async / transform-bluebird - 1688msec
  • transform-async-to-generator / native promises - 7257msec
  • transform-async-to-generator / transform-bluebird - 1750msec

In short, async-to-generator with the transform-bluebird seems to achieve most of the same effect, however, if I modify the such that I remove any reference to async/await and only use the sync path I get:

  • no async/await - 763msec

The mysteries I'm facing:

  • Why does using transform-bluebird help at all? I'm not seeing any promises in the generated code with the default parameters.
  • Is there any option to set to reduce the overhead? I'm guessing the time differential of circa 1 - 1.3 seconds is basically the overhead of 200,000 of the method call setups/promise unrolling behaviour. Just looking to confirm I've not missed a setting that might help.

async functions are omitted when called from a regular function

I was experimenting with fast-async and babel and I got the following unexpected behavior: Suppose that you have the following input file:

async function dummy() {
	console.log("test");
}

// execute dummy in the background:
dummy();

If I transpile it with babel, the output is empty. When I change the last line to

dummy().then();

then everything works as expected.

I have configured babel with plugins: ["fast-async", {spec: true}] without any preset.

What babel options to get the promise transformation ?

I'm trying this:

var options = {
    presets: ['es2015','stage-0'],
   plugins: [["fast-async",{compiler:{promises:true}}]]
};

but it somehow doesn't output promises

Edit: Ah I guess I do need to exclude the transform-async-to-generator plugin

Edit2: ok I got it to work by excluding transform-async-to-generator (manually specifying the plugins I need from stage-0)

It seems nodent/fast-async doesn't handle async methods though ?

class A
{
async f()
{
return 5;
}
}

Edit3: well in the end that unhandled method bug was my real problem, letting stage-0 in presets is okay

Await inside for loop does not work

async liveBackup(files) {
  /* some other code here */
  for(let file of files) {
    await execFileAsync('touch', [backupFile(file.fullPath)]);
  }
}
{ TypeError: /code/app/lib/api/machines.js: Duplicate declaration "file" (This is an error on an internal node. Probably an internal error)
    at File.buildCodeFrameError (/code/app/node_modules/babel-core/lib/transformation/file/index.js:431:15)
    at Scope.checkBlockScopedCollisions (/code/app/node_modules/babel-traverse/lib/scope/index.js:397:27)
    at Scope.registerBinding (/code/app/node_modules/babel-traverse/lib/scope/index.js:579:16)
    at Scope.registerDeclaration (/code/app/node_modules/babel-traverse/lib/scope/index.js:483:14)
    at Object.BlockScoped (/code/app/node_modules/babel-traverse/lib/scope/index.js:185:28)

It works fine with babel's async-to-module-method.

Runtime as module

Following the discussion in MatAtBread/nodent#60

FYI, noRuntime is nice, but it is a bit slower, mainly because .bind(this) is slow compared to $asyncbind(this), and the need to wrap async bodies in a try...catch causes de-optimization.

I think it would be nice to have an option to require the runtime as a module. Currently the choices are: directive, everywhere or in some file matching a regexp.

Something like babel-runtime:

const fn = async function(){}

Transforms into

require('nodent-runtime');
var fn = function fn() {
  return new Promise(function ($return, $error) {
    return $return();
  }.$asyncbind(this));
};

And throw if nodent-runtime is not in the package dependencies.

Options not working

I can't get any of the options for this plugin to work...

For example, with this configuration:

{
  "plugins":
    ["fast-async", {
      "runtimePattern": "test-input\\.js"
    }]
}

I get:

Error: Plugin 1 specified in "/www/derby-boilerplate/.babelrc" provided an invalid property of "runtimePattern"

I'm running Babel 6.10.1.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.