Skip to content

Commit 2479ed2

Browse files
authored
Enable type checking and support Babel 8 (#1056)
* build babel-loader by Babel 8 beta * enable tscheck on sources
1 parent 242e7d2 commit 2479ed2

File tree

13 files changed

+1442
-1448
lines changed

13 files changed

+1442
-1448
lines changed

.github/workflows/ci.yml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,25 @@ permissions:
77

88
jobs:
99
test:
10-
name: Test - ${{ matrix.os }} - Node ${{ matrix.node-version }}, Webpack ${{ matrix.webpack-version }}
10+
name: Test - ${{ matrix.os }} - Node ${{ matrix.node-version }}, Babel ${{ matrix.babel-version }}, Webpack ${{ matrix.webpack-version }}
1111
strategy:
1212
matrix:
1313
os: [ubuntu-latest, windows-latest]
14-
node-version: [18, 20, 22]
14+
node-version: [20, 22, 24]
15+
babel-version: ["7", "8"]
1516
webpack-version: ["5"]
1617
include:
18+
- node-version: "18"
19+
webpack-version: "5"
20+
babel-version: "7"
21+
os: ubuntu-latest
22+
- node-version: "18"
23+
webpack-version: "5"
24+
babel-version: "7"
25+
os: windows-latest
1726
- node-version: "18.20.0" # The minimum supported node version
1827
webpack-version: "5.61.0" # The minimum supported webpack version
28+
babel-version: "7"
1929
os: ubuntu-latest
2030
runs-on: ${{ matrix.os }}
2131
steps:
@@ -29,6 +39,9 @@ jobs:
2939
run: yarn
3040
- name: Install webpack ${{ matrix.webpack-version }}
3141
run: yarn add -D webpack@${{ matrix.webpack-version }}
42+
- name: Downgrade to Babel 7
43+
if: matrix.babel-version == '7'
44+
run: yarn up @babel/*@^7
3245
- name: Build babel-loader
3346
run: yarn run build
3447
- name: Run tests for webpack version ${{ matrix.webpack-version }}
@@ -50,6 +63,8 @@ jobs:
5063
cache: "yarn"
5164
- name: Install dependencies
5265
run: yarn
66+
- name: Run tsc
67+
run: yarn tsc
5368
- name: Run lint and coverage tests
5469
run: yarn test
5570
- name: Submit coverage data to codecov

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ test/output
99
.pnp.*
1010
.vscode
1111
scripts/test-legacy-source/output
12+
tsconfig.tsbuildinfo

babel.config.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
[
2525
"@babel/preset-env",
2626
{
27-
"bugfixes": true,
2827
"modules": false
2928
}
3029
]

package.json

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313
"find-up": "^5.0.0"
1414
},
1515
"peerDependencies": {
16-
"@babel/core": "^7.12.0",
16+
"@babel/core": "^7.12.0 || ^8.0.0-beta.1",
1717
"webpack": ">=5.61.0"
1818
},
1919
"devDependencies": {
20-
"@babel/cli": "^7.23.0",
21-
"@babel/core": "^7.23.3",
22-
"@babel/eslint-parser": "^7.23.3",
23-
"@babel/preset-env": "^7.23.3",
20+
"@babel/cli": "^8.0.0-beta.1",
21+
"@babel/core": "^8.0.0-beta.1",
22+
"@babel/eslint-parser": "^8.0.0-beta.1",
23+
"@babel/preset-env": "^8.0.0-beta.1",
2424
"c8": "^10.1.2",
2525
"eslint": "^9.6.0",
2626
"eslint-config-prettier": "^9.1.0",
@@ -29,6 +29,7 @@
2929
"husky": "^9.1.5",
3030
"lint-staged": "^15.2.9",
3131
"prettier": "^3.0.0",
32+
"typescript": "^5.8.3",
3233
"webpack": "^5.93.0"
3334
},
3435
"scripts": {
@@ -38,7 +39,7 @@
3839
"lint": "eslint src test",
3940
"precommit": "lint-staged",
4041
"prepublish": "yarn run clean && yarn run build",
41-
"preversion": "yarn run test",
42+
"preversion": "yarn tsc && yarn run test",
4243
"test": "yarn run lint && yarn run build --source-maps && c8 yarn run test-only",
4344
"test-only": "node --test test/**/*.test.js"
4445
},

src/Error.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1+
// @ts-check
12
const STRIP_FILENAME_RE = /^[^:]+: /;
23

4+
/**
5+
* @typedef { Error & { hideStack?: boolean, codeFrame?: string } } BabelLoaderError
6+
*/
7+
/**
8+
* Format the error for display.
9+
* @param {BabelLoaderError} err
10+
* @returns {BabelLoaderError}
11+
*/
312
const format = err => {
413
if (err instanceof SyntaxError) {
514
err.name = "SyntaxError";
@@ -17,6 +26,9 @@ const format = err => {
1726
};
1827

1928
class LoaderError extends Error {
29+
/**
30+
* @param {BabelLoaderError} err
31+
*/
2032
constructor(err) {
2133
super();
2234

src/cache.js

Lines changed: 84 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// @ts-check
12
/**
23
* Filesystem Cache
34
*
@@ -17,6 +18,27 @@ const { sync: findUpSync } = require("find-up");
1718
const { env } = process;
1819
const transform = require("./transform");
1920
const serialize = require("./serialize");
21+
/**
22+
* @typedef {object} FileSystemInfoEntry
23+
* @property {number} safeTime
24+
* @property {number} timestamp
25+
*/
26+
/**
27+
* @typedef {object} WebpackLogger
28+
* @property {function(string): void} debug
29+
* @property {function(string): void} info
30+
* @property {function(string): void} warn
31+
* @property {function(string): void} error
32+
*/
33+
/**
34+
* @typedef {object} WebpackHash
35+
* @property {(data: string | Buffer, inputEncoding?: string) => WebpackHash} update
36+
* @property {(encoding?: string) => string | Buffer} digest
37+
*/
38+
39+
/**
40+
* @type {string | null}
41+
*/
2042
let defaultCacheDirectory = null;
2143

2244
const gunzip = promisify(zlib.gunzip);
@@ -35,8 +57,8 @@ const findRootPackageJSON = () => {
3557
* Read the contents from the compressed file.
3658
*
3759
* @async
38-
* @params {String} filename
39-
* @params {Boolean} compress
60+
* @param {string} filename
61+
* @param {boolean} compress
4062
*/
4163
const read = async function (filename, compress) {
4264
const data = await readFile(filename + (compress ? ".gz" : ""));
@@ -47,11 +69,10 @@ const read = async function (filename, compress) {
4769

4870
/**
4971
* Write contents into a compressed file.
50-
*
5172
* @async
52-
* @params {String} filename
53-
* @params {Boolean} compress
54-
* @params {String} result
73+
* @param {string} filename
74+
* @param {boolean} compress
75+
* @param {any} result
5576
*/
5677
const write = async function (filename, compress, result) {
5778
const content = JSON.stringify(result);
@@ -62,18 +83,24 @@ const write = async function (filename, compress, result) {
6283

6384
/**
6485
* Build the filename for the cached file
65-
*
66-
* @params {String} source File source code
67-
* @params {Object} options Options used
68-
*
69-
* @return {String}
86+
* @param {string} source File source code
87+
* @param {string} identifier Unique identifier to bust cache
88+
* @param {Object} options Options used
89+
* @param {WebpackHash} hash Hash function returned by `LoaderContext.utils.createHash`
90+
* @return {string}
7091
*/
7192
const filename = function (source, identifier, options, hash) {
7293
hash.update(serialize([options, source, identifier]));
7394

7495
return hash.digest("hex") + ".json";
7596
};
7697

98+
/**
99+
* Add timestamps to external dependencies.
100+
* @async
101+
* @param {import("./transform").TransformResult["externalDependencies"]} externalDependencies
102+
* @param {(filename: string) => Promise<FileSystemInfoEntry>} getFileTimestamp
103+
*/
77104
const addTimestamps = async function (externalDependencies, getFileTimestamp) {
78105
for (const depAndEmptyTimestamp of externalDependencies) {
79106
try {
@@ -86,6 +113,13 @@ const addTimestamps = async function (externalDependencies, getFileTimestamp) {
86113
}
87114
};
88115

116+
/**
117+
* Check if any external dependencies have been modified.
118+
* @async
119+
* @param {import("./transform").TransformResult["externalDependencies"]} externalDepsWithTimestamp
120+
* @param {(filename: string) => Promise<FileSystemInfoEntry>} getFileTimestamp
121+
* @returns {Promise<boolean>}
122+
*/
89123
const areExternalDependenciesModified = async function (
90124
externalDepsWithTimestamp,
91125
getFileTimestamp,
@@ -107,9 +141,18 @@ const areExternalDependenciesModified = async function (
107141

108142
/**
109143
* Handle the cache
110-
*
111-
* @params {String} directory
112-
* @params {Object} params
144+
* @async
145+
* @param {string} directory
146+
* @param {Object} params
147+
* @param {string} params.source The source code to transform.
148+
* @param {import(".").NormalizedOptions} [params.options] Options used for transformation.
149+
* @param {string} params.cacheIdentifier Unique identifier to bust cache.
150+
* @param {string} [params.cacheDirectory] Directory to store cached files.
151+
* @param {boolean} [params.cacheCompression] Whether to compress cached files.
152+
* @param {WebpackHash} params.hash Hash function to use for the cache filename.
153+
* @param {(filename: string) => Promise<FileSystemInfoEntry>} params.getFileTimestamp - Function to get file timestamps.
154+
* @param {WebpackLogger} params.logger
155+
* @returns {Promise<null | import("./transform").TransformResult>}
113156
*/
114157
const handleCache = async function (directory, params) {
115158
const {
@@ -170,6 +213,10 @@ const handleCache = async function (directory, params) {
170213
// return it to the user asap and write it in cache
171214
logger.debug(`applying Babel transform`);
172215
const result = await transform(source, options);
216+
if (!result) {
217+
logger.debug(`no result from Babel transform, skipping cache write`);
218+
return null;
219+
}
173220
await addTimestamps(result.externalDependencies, getFileTimestamp);
174221

175222
try {
@@ -189,14 +236,17 @@ const handleCache = async function (directory, params) {
189236

190237
/**
191238
* Retrieve file from cache, or create a new one for future reads
192-
*
193239
* @async
194-
* @param {Object} params
195-
* @param {String} params.cacheDirectory Directory to store cached files
196-
* @param {String} params.cacheIdentifier Unique identifier to bust cache
197-
* @param {Boolean} params.cacheCompression Whether compressing cached files
198-
* @param {String} params.source Original contents of the file to be cached
199-
* @param {Object} params.options Options to be given to the transform fn
240+
* @param {object} params
241+
* @param {string} params.cacheDirectory Directory to store cached files.
242+
* @param {string} params.cacheIdentifier Unique identifier to bust cache.
243+
* @param {boolean} params.cacheCompression Whether compressing cached files.
244+
* @param {string} params.source Original contents of the file to be cached.
245+
* @param {import(".").NormalizedOptions} params.options Options to be given to the transform function.
246+
* @param {function} params.transform Transform function to apply to the file.
247+
* @param {WebpackHash} params.hash Hash function to use for the cache filename.
248+
* @param {function(string): Promise<FileSystemInfoEntry>} params.getFileTimestamp Function to get file timestamps.
249+
* @param {WebpackLogger} params.logger Logger instance.
200250
*
201251
* @example
202252
*
@@ -212,7 +262,7 @@ const handleCache = async function (directory, params) {
212262
* });
213263
*/
214264

215-
module.exports = async function (params) {
265+
module.exports = async function cache(params) {
216266
let directory;
217267

218268
if (typeof params.cacheDirectory === "string") {
@@ -225,13 +275,23 @@ module.exports = async function (params) {
225275
return await handleCache(directory, params);
226276
};
227277

278+
/**
279+
* Find the cache directory for babel-loader.
280+
* @param {string} name "babel-loader"
281+
* @returns {string}
282+
*/
228283
function findCacheDir(name) {
229284
if (env.CACHE_DIR && !["true", "false", "1", "0"].includes(env.CACHE_DIR)) {
230285
return path.join(env.CACHE_DIR, name);
231286
}
232-
const rootPkgJSONPath = path.dirname(findRootPackageJSON());
287+
const rootPkgJSONPath = findRootPackageJSON();
233288
if (rootPkgJSONPath) {
234-
return path.join(rootPkgJSONPath, "node_modules", ".cache", name);
289+
return path.join(
290+
path.dirname(rootPkgJSONPath),
291+
"node_modules",
292+
".cache",
293+
name,
294+
);
235295
}
236296
return os.tmpdir();
237297
}

0 commit comments

Comments
 (0)