Skip to content

Commit a2bdcf4

Browse files
Test Babel 7 compatibility
1 parent 25d7e60 commit a2bdcf4

4 files changed

Lines changed: 144 additions & 16 deletions

File tree

.github/workflows/ci.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,43 @@ jobs:
7676
- name: Test the esm build
7777
run: yarn test:esm
7878

79+
test-babel7:
80+
name: Test with Babel 7
81+
needs: prepare-yarn-cache
82+
runs-on: ubuntu-latest
83+
steps:
84+
- name: Checkout code
85+
uses: actions/checkout@v3
86+
- name: Use Node.js latest
87+
uses: actions/setup-node@v3
88+
with:
89+
cache: "yarn"
90+
- name: Install
91+
run: yarn install
92+
- name: Build
93+
run: yarn build
94+
env:
95+
BABEL_ENV: production
96+
- name: Downgrade to Babel 7
97+
run: |
98+
node scripts/downgrade-babel-to-v7.mjs
99+
YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn install
100+
- name: Remove Babel 8-specific fixture outputs
101+
run: |
102+
# These fixtures produce different output with Babel 7 due to
103+
# behavioral changes in @babel/helper-compilation-targets and
104+
# @babel/plugin-transform-classes between Babel 7 and 8.
105+
# Removing the output files lets the test runner auto-generate
106+
# them, verifying the transform runs without crashing.
107+
rm packages/babel-plugin-polyfill-corejs3/test/fixtures/regression/usage-pure-in-helpers/output.mjs
108+
rm packages/babel-plugin-polyfill-corejs3/test/fixtures/usage-global/browserslist-config-ignore/output.mjs
109+
rm packages/babel-plugin-polyfill-corejs3/test/fixtures/usage-global/dynamic-import/output.mjs
110+
rm packages/babel-plugin-polyfill-corejs3/test/fixtures/usage-global/dynamic-import-webpack/output.mjs
111+
- name: Test
112+
run: yarn jest --ci --color --maxWorkers=2
113+
- name: Test the esm build
114+
run: yarn test:esm
115+
79116
test-windows:
80117
name: Test on Windows
81118
needs: prepare-yarn-cache

packages/babel-helper-define-polyfill-provider/test/helpers/ast-to-code-serializer.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { types as t } from "@babel/core";
2-
import generator from "@babel/generator";
2+
import _generator from "@babel/generator";
3+
// For compatibility when running tests with Babel 7
4+
const generator = _generator.default || _generator;
35

46
export default {
57
test: v => t.isNode(v),

scripts/babel-plugin-compat-core-import.js

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,55 @@
11
// Convert
2-
// import { x as y } from "@babel/core";
2+
// import foo, { x as y } from "@babel/core";
33
// to
4-
// import * as babel from "@babel/core";
5-
// const { x: y } = babel.default || babel;
4+
// import * as _babel_core from "@babel/core";
5+
// const { default: foo, x: y } = _babel_core.default && _babel_core.default.__esModule ? _babel_core.default : _babel_core;
66

77
module.exports = function ({ types: t, template }) {
88
return {
99
visitor: {
1010
ImportDeclaration(path) {
11+
const source = path.node.source.value;
1112
if (
12-
t.isStringLiteral(path.node.source, { value: "@babel/core" }) &&
13-
path.node.specifiers.every(node => t.isImportSpecifier(node))
13+
!source.startsWith("@babel/") ||
14+
source === "@babel/helper-define-polyfill-provider"
1415
) {
15-
const defaultName = path.scope.generateUidIdentifier("babel");
16+
return;
17+
}
1618

17-
const destr = t.objectPattern(
18-
path.node.specifiers.map(spec =>
19-
t.objectProperty(spec.imported, spec.local)
20-
)
21-
);
19+
if (path.node.importKind === "type") return;
20+
const specs = path.node.specifiers.filter(s => s.importKind !== "type");
21+
if (specs.length === 0) return;
22+
23+
const hasDefault = specs.some(s => t.isImportDefaultSpecifier(s));
24+
const namedSpecs = specs.filter(s => t.isImportSpecifier(s));
25+
26+
if (!hasDefault && namedSpecs.length === 0) return;
27+
28+
const nsName = path.scope.generateUidIdentifier(source);
2229

23-
path.replaceWithMultiple(template.statements.ast`
24-
import * as ${defaultName} from "@babel/core";
25-
const ${destr} = ${defaultName}.default || ${defaultName};
26-
`);
30+
// Use __esModule to distinguish CJS (Babel 7) from ESM (Babel 8).
31+
// Cannot use the simpler `_ns.default || _ns` because for ESM
32+
// packages that have a default export (like
33+
// @babel/helper-compilation-targets), `_ns.default` is truthy.
34+
35+
const properties = namedSpecs.map(spec =>
36+
t.objectProperty(spec.imported, spec.local)
37+
);
38+
if (hasDefault) {
39+
// Treat default import as `{ default: local }`
40+
const defaultSpec = specs.find(s => t.isImportDefaultSpecifier(s));
41+
properties.unshift(
42+
t.objectProperty(t.identifier("default"), defaultSpec.local)
43+
);
2744
}
45+
46+
const destr = t.objectPattern(properties);
47+
48+
path.replaceWithMultiple([
49+
template.statement.ast`import * as ${nsName} from "${source}";`,
50+
template.statement
51+
.ast`const ${destr} = ${nsName}.default && ${nsName}.default.__esModule ? ${nsName}.default : ${nsName};`,
52+
]);
2853
},
2954
},
3055
};

scripts/downgrade-babel-to-v7.mjs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { readFileSync, writeFileSync, readdirSync } from "fs";
2+
3+
const root = new URL("../", import.meta.url).pathname;
4+
5+
// Read root package.json
6+
const pkgPath = root + "package.json";
7+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
8+
9+
// Collect all workspace package names to exclude them from resolutions
10+
const workspacePackages = new Set();
11+
for (const dir of readdirSync(root + "packages")) {
12+
try {
13+
const subPkg = JSON.parse(
14+
readFileSync(root + "packages/" + dir + "/package.json", "utf8"),
15+
);
16+
workspacePackages.add(subPkg.name);
17+
} catch {}
18+
}
19+
20+
// Collect all @babel/* package names from the dependency tree
21+
const babelPackages = new Set();
22+
23+
function collectBabelDeps(obj) {
24+
if (!obj) return;
25+
for (const name of Object.keys(obj)) {
26+
if (name.startsWith("@babel/") && !workspacePackages.has(name)) {
27+
babelPackages.add(name);
28+
}
29+
}
30+
}
31+
32+
collectBabelDeps(pkg.devDependencies);
33+
collectBabelDeps(pkg.dependencies);
34+
35+
for (const dir of readdirSync(root + "packages")) {
36+
try {
37+
const subPkg = JSON.parse(
38+
readFileSync(root + "packages/" + dir + "/package.json", "utf8"),
39+
);
40+
collectBabelDeps(subPkg.dependencies);
41+
collectBabelDeps(subPkg.devDependencies);
42+
} catch {}
43+
}
44+
45+
// test/esm
46+
try {
47+
const esmPkg = JSON.parse(
48+
readFileSync(root + "test/esm/package.json", "utf8"),
49+
);
50+
collectBabelDeps(esmPkg.devDependencies);
51+
} catch {}
52+
53+
// Add resolutions to force Babel 7
54+
if (!pkg.resolutions) pkg.resolutions = {};
55+
for (const name of babelPackages) {
56+
pkg.resolutions[name] = "^7.0.0";
57+
}
58+
59+
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
60+
61+
console.log(
62+
"Added Babel 7 resolutions for:",
63+
[...babelPackages].sort().join(", "),
64+
);

0 commit comments

Comments
 (0)