JS Transformer does not correctly polyfill new `core-js` features
🐛 bug report
The JS transformer with swc under the hood allows tranforming core-js imports into the needed polyfills for the targeted browsers. Due to this bug the needed polyfills do not get included correctly resulting in errors for users with older browsers.
I believe this affects anyone trying to polyfill features from core-js that aren't in core-js 3.0.
(I already started a discussion about this but after investigating I was inclined to believe it is a bug)
🎛 Configuration (.babelrc, package.json, cli command)
This is a reproduction example but I think it applies to all newer features polyfilled by core-js. So let's try to polyfill structuredClone, which was added in core-js 3.24 (-ish)
1. Create the following files in an empty directory
.browserslistrc
safari 15.3
package.json
{
"devDependencies": {
"core-js": "^3.37.1",
"parcel": "^2.12.0"
}
}
index.ts
import "core-js/stable/structured-clone";
console.log(structuredClone({}));
2. Install deps and compile
npm i
npx parcel build index.ts --no-optimize
3. Check the output of dist/index.js
(() => {
console.log(structuredClone({}));
})();
//# sourceMappingURL=index.js.map
The polyfill for structuredClone is not added even though it is needed in Safari 15.3 according to can-i-use.
🤔 Expected Behavior
The polyfills for unsupported features for the target browsers should be included in the output compiled by parcel.
😯 Current Behavior
The polyfills for unsupported features for the target browsers are NOT included in the output compiled by parcel.
💁 Possible Solution
This is not a final solution but I believe this is a hint of where the problem lies.
When playing around with the swc playground (since swc is used in the JS transformer) I noticed that the coreJs option is not set.
According to the swc docs it needs to be set with the minor version. Otherwise for example 3 will default to 3.0
It is recommended to specify the minor version (E.g. "3.22") otherwise "3" will be interpreted as "3.0" which may not include polyfills for the latest features.
This swc playground supports this hypothesis. You can see how the polyfill is correctly included in the output,
but when editing the options via the Edit as JSON button and remove or edit the coreJs option from "3.37" to "3", it is no longer included.
When set to "3.37" the polyfill is correctly included.
So the solution could be to make sure that parcel sets the core_js Option on the present_env_config struct to the currently installed Version of core-js including the minor version.
🔦 Context
Finding errors in older but supported browsers for features that should have been polyfilled.
💻 Code Sample
See above and here
🌍 Your Environment
| Software | Version(s) |
|---|---|
| Parcel | 2.12.0 |
| Node | 20 |
| npm/Yarn | npm 10 |
| Operating System | Linux and MacOS |
Additional troubleshooting info
Setup
Run this script which creates a folder with 3 files (.swcrc, package.json, index.ts) setup a test sample for comparing swc and parcel results for expanding core-js imports
mkdir swc-parcel-comparison
cd swc-parcel-comparison
echo '{
"$schema": "https://swc.rs/schema.json",
"env": {
"targets": "safari 15.3",
"mode": "entry",
"coreJs": "3.37.1"
},
"minify": false
}' >.swcrc
echo '{
"name": "swc-parcel-test",
"scripts": {
"swc": "swc index.ts",
"parcel": "parcel build index.ts --no-optimize && cat dist/index.js"
},
"browserslist": "safari 15.3",
"devDependencies": {
"@swc/cli": "^0.3.12",
"@swc/core": "^1.5.29",
"parcel": "^2.12.0"
}
}' >package.json
echo 'import "core-js/stable/object/has-own"
import "core-js/stable/structured-clone"
console.log(42);
' >index.ts
Compare SWC and Parcel output
Now run the following and compare the outputs of swc and parcel. You will find that swc does expand the core-js imports while parcel does not
cd swc-parcel-comparison
npm install
npm run swc
npm run parcel
Issue still persists
Issue still persists