cli: simplify Jest ESM support

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2024-12-26 11:31:03 +01:00
parent ce74d76262
commit be9a1f8dc7
2 changed files with 15 additions and 14 deletions
+8 -12
View File
@@ -19,6 +19,11 @@ const { default: JestRuntime } = require('jest-runtime');
const scriptTransformCache = new Map();
module.exports = class CachingJestRuntime extends JestRuntime {
constructor(config, ...restAgs) {
super(config, ...restAgs);
this.allowLoadAsEsm = config.extensionsToTreatAsEsm.includes('.mts');
}
// This may or may not be a good idea. Theoretically I don't know why this would impact
// test correctness and flakiness, but it seems like it may introduce flakiness and strange failures.
// It does seem to speed up test execution by a fair amount though.
@@ -34,19 +39,10 @@ module.exports = class CachingJestRuntime extends JestRuntime {
return script;
}
// Notes(Rugvip): As far as I can tell this is the best we can currently do
// for runtime ESM support in Jest. What the below logic effectively does is
// to only allow packages to be loaded as ESM if all imports of that package
// are done in an ESM compatible way, as in either from ESM code or with a
// dynamic import.
cjsModules = new Set();
_resolveCjsModule(...args) {
const path = super._resolveCjsModule(...args);
this.cjsModules.add(path);
return path;
}
// Unfortunately we need to use this unstable API to make sure that .js files
// are only loaded as modules where ESM is supported, i.e. Node.js packages.
unstable_shouldLoadAsEsm(path, ...restArgs) {
if (this.cjsModules.has(path)) {
if (!this.allowLoadAsEsm) {
return false;
}
return super.unstable_shouldLoadAsEsm(path, ...restArgs);
+7 -2
View File
@@ -18,13 +18,18 @@ const { createTransformer: createSwcTransformer } = require('@swc/jest');
const ESM_REGEX = /\b(?:import|export)\b/;
function createTransformer(config) {
const useModules = Boolean(config?.module);
const swcTransformer = createSwcTransformer({
inputSourceMap: false,
...config,
});
const process = (source, filePath, jestOptions) => {
if (filePath.endsWith('.js') && (useModules || !ESM_REGEX.test(source))) {
// Skip transformation of .js files without ESM syntax, we never transform from CJS to ESM
if (filePath.endsWith('.js') && !ESM_REGEX.test(source)) {
return { code: source };
}
// Skip transformation of .mjs files, they should only be used if ESM support is available
if (filePath.endsWith('.mjs')) {
return { code: source };
}