What do we need to make `usage-global` injection work with `@babel/runtime`?
- Dominant language
- TypeScript
- Stars
- 44k
- Forks
- 6k
- Avg merge
- 5d 15h
- Merged PRs (30d)
- 23
Description
### 💻
- [ ] Would you like to work on this feature?
### What problem are you trying to solve?
@nyngwang has been going around a bit checking how our polyfill injection works (thank you very much!), and after going through their comments I realized that our injection story for `usage-global` is pretty bad when it comes to helpers.
If you have this config:
```json
{
"plugins": [
"@babel/transform-runtime"
]
}
```
Babel will inject imports for helpers like `import _typeof from "@babel/runtime/helpers/typeof"`.
Then you decide that you want to inject global polyfills through `core-js`, so you update your config to this:
```json
{
"plugins": [
"@babel/transform-runtime",
["babel-plugin-polyfill-corejs3", { "method": "usage-global" }]
]
}
```
now Babel will inject imports like `import "core-js/modules/es.array.flat.js";`, but suddently your imports for helpers will become `import "@babel/runtime-corejs3/helpers/typeof"` (which depends on `core-js-pure`). This is to make sure that the helpers are also polyfilled, but:
- you asked for global-modifying polyfills, and now in your dependencies you have both `core-js` and `core-js-pure`
- injecting global polyfills forced you to change one of your dependencies.
If you still want to use `@babel/runtime` (because `@babel/runtime-corejs3` includes polyfills down to ES5), you have to instead use this config:
```json
{
"plugins": [
["@babel/transform-runtime", { "moduleName": "@babel/runtime" }],
["babel-plugin-polyfill-corejs3", { "method": "usage-global" }]
]
}
```
> NOTE: I think this behavior is good when it comes to `usage-pure`, because we are just changing the `@babel/runtime` imports to a different package that uses exactly the _pure_ polyfill the user asked for.
### Describe the solution you'd like
What if for each helper we maintained the list of built-ins that it relies on, and when injecting a `import "@babel/runtime/typeof/helpers"` we called the polyfill provider saying "hey, we included a helper that uses `Symbol` and `Array.prototype.flat`: if needed for the configured target, consider injecting imports to these polyfills".
Then, when compiling `typeof foo` and using `["babel-plugin-polyfill-corejs3", { "method": "usage-global" }]`, we would generate some code like
```js
import "core-js/modules/es.symbol.js";
import _typeof from "@babel/runtime/helpers/typeof";
_typeof(foo);
```
rather than
```js
import _typeof from "@babel/runtime-corejs3/helpers/typeof";
_typeof(foo);
```
This list would probably need to be manually-maintained by us for each helper, and:
- we could try linting using our existing polyfill provider infrastructure, to make sure that we aren't missing any builtin in our list
- even if we change the helper to not rely on X anymore, we still need to include X in the list of features for compatibility with older `@babel/runtime` versions
### Describe alternatives you've considered
Do nothing
### Documentation, Adoption, Migration Strategy
_No response_
Contributor guide
Research direction
Start by reproducing the two plugin configurations with the `typeof` helper and compare their generated imports. Read the existing polyfill provider infrastructure and helper behavior described in the issue; done means `usage-global` keeps `@babel/runtime` imports while injecting required global `core-js` modules, without switching to `@babel/runtime-corejs3`.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- compilers, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100