Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Plugin dev] AwaitExpression not found since @babel/preset-env@7.7.7 #11940

Closed
cyrilgandon opened this issue Aug 10, 2020 · 3 comments
Closed
Labels
area: plugin ordering i: question outdated A closed issue/PR that is archived due to age. Recommended to make a new issue

Comments

@cyrilgandon
Copy link

cyrilgandon commented Aug 10, 2020

Bug Report

Current behavior

I have a plugin that worked well before, but since I upgraded to @babel/preset-env 7.11.0, it does not work anymore.

The plugin.js:

module.exports = function(babel) {
    console.log('Plugin read...');
    return {
        visitor: {
            AwaitExpression: function() {
                console.log('AwaitExpression');
            }
        }
    };
};

Input Code

    async function myFunctionWithAwait() {
        await myAsyncFunction()
    }
    
    async function myAsyncFunction() {
        return `test`;
    }
    
    myFunctionWithAwait();

Expected behavior

With @babel/preset-env@7.7.6, I got the log AwaitExpression.
With @babel/preset-env@7.7.7+, I have not log.

Babel Configuration

  • Filename: .babelrc
{
        "presets": [
            [
                "@babel/preset-env",
                {
                    "useBuiltIns": "usage",
                    "corejs": 3
                }
            ]
        ],
        "plugins": [
            "./plugin.js"
        ]
    }

I have narrowed down to one release, from 7.7.6 to 7.7.7.
Seeing the changes logs https://github.com/babel/babel/releases/tag/v7.7.7,
maybe it comes from #10839.

What my plugin tries to do is to run before transformations from preset on await call, so it can transform them.

@babel-bot
Copy link
Collaborator

Hey @cyrilgandon! We really appreciate you taking the time to report an issue. The collaborators on this project attempt to help as many people as possible, but we're a limited number of volunteers, so it's possible this won't be addressed swiftly.

If you need any help, or just have general Babel or JavaScript questions, we have a vibrant Slack community that typically always has someone willing to help. You can sign-up here for an invite."

@cyrilgandon cyrilgandon changed the title [Plugin dev] AwaitExpression not found with @babel/preset-env@7.11.0 [Plugin dev] AwaitExpression not found since @babel/preset-env@7.7.7 Aug 10, 2020
@JLHwung
Copy link
Contributor

JLHwung commented Aug 10, 2020

The behaviour is expected. Because @babel/transform-async-to-generator visits the Function[isAsync=true] node and transforms the whole function body, so AwaitExpression is not traversed. James has a clean write-up on Babel's plugin orders: https://jamie.build/babel-plugin-ordering.html

As a workaround, you can initiate a sub-travese from Function node

module.exports = function(babel) {
    console.log('Plugin read...');
    return {
        visitor: {
            Function(path) {
                path.traverse({
                     AwaitExpression: function() {
                         console.log('AwaitExpression');
                     }
                })
            }
        }
    };
};

However, a sub-traverse may introduces significant performance overhead so it is not recommended.

Out of curiosity, what is your use case of transforming AwaitExpression? If you transform AwaitExpression to ES5, you can instruct preset-env to ignore async-to-generators (See https://babeljs.io/docs/en/babel-preset-env#exclude):

["@babel/preset-env", { "exclude": ["@babel/plugin-transform-async-to-generators"] }]

@cyrilgandon
Copy link
Author

cyrilgandon commented Aug 10, 2020

Use case is this plugin: https://github.com/noppa/babel-plugin-angularjs-digest-await
Wrapping every await into a function that trigger a $digest cycle for angularjs.

module.exports = function(babel) {
  var t = babel.types;

  var defaultOptions = {
    helperFunctionName: '$$await'
  };
    
  // Checks if an AwaitExpression path has already been
  // wrapped by this plugin.
  function noWrappingNeeded(path, helperFunctionName) {
    var parent = path.parentPath;
    var isGeneratedExpression =
      !!parent
      && t.isCallExpression(parent)
      && t.isIdentifier(parent.node.callee, { name: helperFunctionName });

    return isGeneratedExpression;
  }

  return {
    visitor: {
      AwaitExpression: function(path, state) {
        var opts = state.opts;
        var helperFunctionName = opts.helperFunctionName || defaultOptions.helperFunctionName;
        if (noWrappingNeeded(path, helperFunctionName)) return;

        var newPath = t.callExpression(
          t.identifier(helperFunctionName),
          [path.node]
        );

        path.replaceWith(newPath);
      }
    }
  };
};

@github-actions github-actions bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label Feb 11, 2024
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 11, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: plugin ordering i: question outdated A closed issue/PR that is archived due to age. Recommended to make a new issue
Projects
None yet
Development

No branches or pull requests

4 participants