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

Support transforming async generators like @babel/plugin-proposal-async-generator-functions does #2780

Closed
segevfiner opened this issue Dec 29, 2022 · 21 comments · Fixed by #3194

Comments

@segevfiner
Copy link

It would be nice to be able to have esbuild transform async generators like the babel plugin @babel/plugin-proposal-async-generator-functions does when native async support is disabled, that is:

   esbuild: {
     supported: {
       "async-await": false,
     }
  }

Currently using async generator functions with async await disabled results in an error.

This is used as a stopgap by Angular's Zone.JS so they can track async generator functions as they have no way to track native async await in the browser ATM, so they rely on down transpiling them to generators.

See: https://github.com/angular/angular-cli/blob/67ffa8b40be04b0e671429063810fe5f52b2043a/packages/angular_devkit/build_angular/src/babel/presets/application.ts#L232-L239

If esbuild supported this natively, babel wouldn't be needed here.

@evanw
Copy link
Owner

evanw commented Dec 29, 2022

It's interesting to hear that someone actually uses this feature for something. This JavaScript feature is so obscure that I haven't yet found any code that uses it, which is why I haven't implemented this transform yet.

I tried bundling the npm package zone.js with a target of es6 but it works fine, as that package doesn't appear to contain any async generator functions.

What is your use case for this feature? Can you provide an example of real published code that makes use of this feature?

@segevfiner
Copy link
Author

The idea is that the zone will propagate across the async generator call, zone.js can't handle native async await because that's hard coded to use the native browser promise and it can't be monkey patched by it.

@evanw
Copy link
Owner

evanw commented Dec 29, 2022

Is this just a hypothetical concern? Can you provide an example of production code that uses this language feature?

@segevfiner
Copy link
Author

segevfiner commented Dec 29, 2022

You can see an MWE of this here, checkout the main.ts file and the vite config.

@evanw
Copy link
Owner

evanw commented Dec 29, 2022

You can see an MWE of this here, checkout the main.ts file and the vite config.

Did you mean to post a link? I'm not sure where "here" is, sorry.

@segevfiner
Copy link
Author

segevfiner commented Dec 29, 2022

You can see an MWE of this here, checkout the main.ts file and the vite config.

Did you mean to post a link? I'm not sure where "here" is, sorry.

Oops. Yeah, here is the link: https://stackblitz.com/edit/vitejs-vite-k5ghhm?file=src/main.ts

@segevfiner
Copy link
Author

@evanw
Copy link
Owner

evanw commented Dec 29, 2022

It looks like you posted a link to some code you just wrote to demonstrate the feature instead of posting a link to real code. So I'm guessing that means that this is just a hypothetical concern. I can try to implement this at some point, but I should also say that the priority of this still seems low given the information in this thread.

@segevfiner
Copy link
Author

segevfiner commented Dec 29, 2022

Some real code would be Angular projects, the link I posted shows where angular-cli had to use Babel instead of just esbuild due to this.

The real code I tried using Zone.js in, is properitery, which is why I posted a MWE to show the issue instead.

I have actually been trying to use Zone.js to propagate async context for logging outside of Angular, with Vite & Vue instead, which is where I stumbled upon this issue. And Zone.js appears to be rather heavyweight so I'm not sure we will actually end up using it in the end. Priority is really up to you, this is just a feature request and there is a workaround using Babel.

Thanks for looking into this anyhow 👍

@hiebj
Copy link

hiebj commented Jan 4, 2023

For what it's worth, I just arrived here from a real-world use case. I was trying to switch from ts-loader to esbuild-loader to speed up my webpack build, but I use an async generator to create an asynchronous stream of progress outputs culminating in a response body during a file upload operation using XMLHttpRequest.

In many apps something like this would be achieved with the local Observable implementation, but this project does not currently use or need Observable for anything else, and async generators are a native language feature which accomplishes the same thing when combined with my view engine's reactive state in this case. I am generally resistant to library bloat and prefer to use language features as much as possible.

@axelthat
Copy link

axelthat commented Jan 22, 2023

withastro/astro#5870

I wanted to target older browser for my Astro project. Esbuild fails while trying to transform the generator functions @evanw.

@segevfiner
Copy link
Author

Workaround for Vite users:

    // https://github.com/evanw/esbuild/issues/2780
    {
      ...babel({
        babelConfig: {
          babelrc: false,
          configFile: false,
          plugins: [
            "@babel/plugin-transform-async-to-generator",
            "@babel/plugin-proposal-async-generator-functions"
          ]
        },
        filter: /\.(?:jsx?|tsx?|vue)$/,
      }),
      enforce: "post",
    },

@fijiwebdesign
Copy link

I'm trying to bundle https://www.npmjs.com/package/streamx with a build.

esbuild errors on https://github.com/mafintosh/streamx/blob/49bf57d5b9833736b72a733e92958e0e41225f42/test/async-iterator.js#L84

bypass transforming async iterators?

@talentlessguy
Copy link

I'm using aegir to test ipfs-utils and it has this function:

export default async function * globSource (cwd, pattern, options) {
  // ...
}

it doesn't export it at all, all other functions work properly, so I suppose async default generator function can't work

@pilotmoon
Copy link

pilotmoon commented May 18, 2023

FWIW here's an example of some real code (mine) using an async generator. The generator itself:
https://github.com/pilotmoon/PopClip-Extensions/blob/master/lib/%40popclip/helpers/generator.ts
and the code that calls it:
https://github.com/pilotmoon/PopClip-Extensions/blob/master/source/Bitly.popclipext/bitly.ts

It would be great to be able to use esbuild on my project without refactoring my code to remove the use of this language feature.

@airhorns
Copy link

airhorns commented Jun 5, 2023

The reasonably popular urql GraphQL client also uses async generators internally to model GraphQL subscriptions that can yield multiple values over time as well -- see https://github.com/urql-graphql/urql/blob/30b628ecfae2ed70c02aaed73a5293fc5b65ac78/packages/core/src/internal/fetchSource.ts#L18 and the underlying wonka library.

Would be great to get support for lowering them!

@itrcz
Copy link

itrcz commented Jun 17, 2023

gpt-tokenizer also fails when building via esbuild

@dandv
Copy link

dandv commented Mar 14, 2024

[mistaken comment; TL;DR forgot to set the target to es2017]

@pilotmoon
Copy link

pilotmoon commented Mar 14, 2024

@dandv It's closed because it was implemented -- #3194

@evanw
Copy link
Owner

evanw commented Mar 14, 2024

You're asking why this issue was closed, but that's something that GitHub already tells you. For future reference, you can see it right above what you just posted:

@evanw closed this as completed in #3194 on Jun 24, 2023

@dandv
Copy link

dandv commented Mar 15, 2024

My bad, I overlooked the close reason, and neglected to set the target environment, so I ended up with the untranspiled async iterator and thought the issue was closed due to lack of use cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants