Skip to content

Commit

Permalink
feat: tell Babel about Jest's ESM support
Browse files Browse the repository at this point in the history
  • Loading branch information
SimenB committed Oct 31, 2020
1 parent 1a06c2c commit 62dcfad
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 4 deletions.
16 changes: 16 additions & 0 deletions packages/babel-jest/src/index.ts
Expand Up @@ -40,6 +40,14 @@ interface BabelJestTransformOptions extends TransformOptions {
sourceMaps: 'both';
}

// https://github.com/DefinitelyTyped/DefinitelyTyped/pull/49267
declare module '@babel/core' {
interface TransformCaller {
supportsExportNamespaceFrom?: boolean;
supportsTopLevelAwait?: boolean;
}
}

const createTransformer = (
userOptions?: TransformOptions | null,
): BabelJestTransformer => {
Expand All @@ -49,7 +57,9 @@ const createTransformer = (
caller: {
name: 'babel-jest',
supportsDynamicImport: false,
supportsExportNamespaceFrom: false,
supportsStaticESM: false,
supportsTopLevelAwait: false,
...inputOptions.caller,
},
compact: false,
Expand All @@ -72,9 +82,15 @@ const createTransformer = (
supportsDynamicImport:
transformOptions?.supportsDynamicImport ??
options.caller.supportsDynamicImport,
supportsExportNamespaceFrom:
transformOptions?.supportsExportNamespaceFrom ??
options.caller.supportsExportNamespaceFrom,
supportsStaticESM:
transformOptions?.supportsStaticESM ??
options.caller.supportsStaticESM,
supportsTopLevelAwait:
transformOptions?.supportsTopLevelAwait ??
options.caller.supportsTopLevelAwait,
},
filename,
});
Expand Down
2 changes: 2 additions & 0 deletions packages/jest-runtime/package.json
Expand Up @@ -34,6 +34,7 @@
"jest-snapshot": "^26.6.1",
"jest-util": "^26.6.1",
"jest-validate": "^26.6.1",
"semver": "^7.3.2",
"slash": "^3.0.0",
"strip-bom": "^4.0.0",
"yargs": "^15.4.1"
Expand All @@ -44,6 +45,7 @@
"@types/glob": "^7.1.1",
"@types/graceful-fs": "^4.1.2",
"@types/node": "^14.0.27",
"@types/semver": "^7.3.4",
"execa": "^4.0.0",
"jest-environment-node": "^26.6.1",
"jest-snapshot-serializer-raw": "^1.1.0"
Expand Down
11 changes: 11 additions & 0 deletions packages/jest-runtime/src/index.ts
Expand Up @@ -18,6 +18,7 @@ import {
Module as VMModule,
} from 'vm';
import * as nativeModule from 'module';
import * as semver from 'semver';
// @ts-expect-error
import parseCjs = require('cjs-module-lexer');
import type {Config, Global} from '@jest/types';
Expand Down Expand Up @@ -78,15 +79,21 @@ type HasteMapOptions = {
type InternalModuleOptions = {
isInternalModule: boolean;
supportsDynamicImport: boolean;
supportsExportNamespaceFrom: boolean;
supportsStaticESM: boolean;
supportsTopLevelAwait: boolean;
};

const defaultTransformOptions: InternalModuleOptions = {
isInternalModule: false,
supportsDynamicImport: esmIsAvailable,
supportsExportNamespaceFrom: false,
supportsStaticESM: false,
supportsTopLevelAwait: false,
};

const nodeVersionSupportsTla = semver.satisfies(process.version, '>=14.3.0');

type InitialModule = Omit<Module, 'require' | 'parent' | 'paths'>;
type ModuleRegistry = Map<string, InitialModule | Module>;

Expand Down Expand Up @@ -378,7 +385,9 @@ class Runtime {
const transformedCode = this.transformFile(modulePath, {
isInternalModule: false,
supportsDynamicImport: true,
supportsExportNamespaceFrom: false,
supportsStaticESM: true,
supportsTopLevelAwait: nodeVersionSupportsTla,
});

const module = new SourceTextModule(transformedCode, {
Expand Down Expand Up @@ -608,7 +617,9 @@ class Runtime {
return this.requireModule<T>(from, to, {
isInternalModule: true,
supportsDynamicImport: esmIsAvailable,
supportsExportNamespaceFrom: false,
supportsStaticESM: false,
supportsTopLevelAwait: false,
});
}

Expand Down
29 changes: 27 additions & 2 deletions packages/jest-transform/src/ScriptTransformer.ts
Expand Up @@ -62,6 +62,14 @@ async function waitForPromiseWithCleanup(
}
}

// https://github.com/DefinitelyTyped/DefinitelyTyped/pull/49267
declare module '@babel/core' {
interface TransformCaller {
supportsExportNamespaceFrom?: boolean;
supportsTopLevelAwait?: boolean;
}
}

export default class ScriptTransformer {
private _cache: ProjectCache;
private _config: Config.ProjectConfig;
Expand Down Expand Up @@ -96,6 +104,7 @@ export default class ScriptTransformer {
instrument: boolean,
supportsDynamicImport: boolean,
supportsStaticESM: boolean,
supportsTopLevelAwait: boolean,
): string {
const configString = this._cache.configString;
const transformer = this._getTransformer(filename);
Expand All @@ -108,7 +117,9 @@ export default class ScriptTransformer {
instrument,
rootDir: this._config.rootDir,
supportsDynamicImport,
supportsExportNamespaceFrom: false,
supportsStaticESM,
supportsTopLevelAwait,
}),
)
.update(CACHE_VERSION)
Expand All @@ -130,6 +141,7 @@ export default class ScriptTransformer {
instrument: boolean,
supportsDynamicImport: boolean,
supportsStaticESM: boolean,
supportsTopLevelAwait: boolean,
): Config.Path {
const baseCacheDir = HasteMap.getCacheFilePath(
this._config.cacheDirectory,
Expand All @@ -142,6 +154,7 @@ export default class ScriptTransformer {
instrument,
supportsDynamicImport,
supportsStaticESM,
supportsTopLevelAwait,
);
// Create sub folders based on the cacheKey to avoid creating one
// directory with many files.
Expand Down Expand Up @@ -216,6 +229,7 @@ export default class ScriptTransformer {
supportsDynamicImport: boolean,
supportsStaticESM: boolean,
canMapToInput: boolean,
supportsTopLevelAwait: boolean,
): TransformedSource {
const inputCode = typeof input === 'string' ? input : input.code;
const inputMap = typeof input === 'string' ? null : input.map;
Expand All @@ -226,7 +240,9 @@ export default class ScriptTransformer {
caller: {
name: '@jest/transform',
supportsDynamicImport,
supportsExportNamespaceFrom: false,
supportsStaticESM,
supportsTopLevelAwait,
},
configFile: false,
filename,
Expand Down Expand Up @@ -267,6 +283,7 @@ export default class ScriptTransformer {
instrument: boolean,
supportsDynamicImport = false,
supportsStaticESM = false,
supportsTopLevelAwait = false,
): TransformResult {
const filename = tryRealpath(filepath);
const transform = this._getTransformer(filename);
Expand All @@ -276,6 +293,7 @@ export default class ScriptTransformer {
instrument,
supportsDynamicImport,
supportsStaticESM,
supportsTopLevelAwait,
);
let sourceMapPath: Config.Path | null = cacheFilePath + '.map';
// Ignore cache if `config.cache` is set (--no-cache)
Expand Down Expand Up @@ -309,7 +327,9 @@ export default class ScriptTransformer {
const processed = transform.process(content, filename, this._config, {
instrument,
supportsDynamicImport,
supportsExportNamespaceFrom: false,
supportsStaticESM,
supportsTopLevelAwait,
});

if (typeof processed === 'string') {
Expand Down Expand Up @@ -363,6 +383,7 @@ export default class ScriptTransformer {
supportsDynamicImport,
supportsStaticESM,
shouldEmitSourceMaps,
supportsTopLevelAwait,
);

code =
Expand Down Expand Up @@ -400,6 +421,7 @@ export default class ScriptTransformer {
isInternalModule,
supportsDynamicImport,
supportsStaticESM,
supportsTopLevelAwait,
} = options;
const content = stripShebang(
fileSource || fs.readFileSync(filename, 'utf8'),
Expand All @@ -421,6 +443,7 @@ export default class ScriptTransformer {
instrument,
supportsDynamicImport,
supportsStaticESM,
supportsTopLevelAwait,
);

code = transformedSource.code;
Expand Down Expand Up @@ -480,6 +503,7 @@ export default class ScriptTransformer {
isInternalModule,
supportsDynamicImport,
supportsStaticESM,
supportsTopLevelAwait,
} = options;
const willTransform =
!isInternalModule && !isCoreModule && this.shouldTransform(filename);
Expand All @@ -491,6 +515,7 @@ export default class ScriptTransformer {
false,
supportsDynamicImport,
supportsStaticESM,
supportsTopLevelAwait,
);
return transformedJsonSource;
}
Expand Down Expand Up @@ -521,8 +546,8 @@ export default class ScriptTransformer {
transforming = true;
return (
// we might wanna do `supportsDynamicImport` at some point
this.transformSource(filename, code, false, false, false).code ||
code
this.transformSource(filename, code, false, false, false, false)
.code || code
);
} finally {
transforming = false;
Expand Down
6 changes: 5 additions & 1 deletion packages/jest-transform/src/types.ts
Expand Up @@ -24,7 +24,9 @@ export type Options = ShouldInstrumentOptions &
isCoreModule: boolean;
isInternalModule: boolean;
supportsDynamicImport: boolean;
supportsExportNamespaceFrom: boolean;
supportsStaticESM: boolean;
supportsTopLevelAwait: boolean;
}>;

// This is fixed in source-map@0.7.x, but we can't upgrade yet since it's async
Expand All @@ -41,9 +43,11 @@ export type TransformResult = TransformTypes.TransformResult;

export interface TransformOptions {
instrument: boolean;
// names are copied from babel
// names are copied from babel: https://babeljs.io/docs/en/options#caller
supportsDynamicImport?: boolean;
supportsExportNamespaceFrom?: boolean;
supportsStaticESM?: boolean;
supportsTopLevelAwait?: boolean;
}

// TODO: For Jest 26 we should combine these into one options shape
Expand Down
4 changes: 3 additions & 1 deletion yarn.lock
Expand Up @@ -3747,7 +3747,7 @@ __metadata:
languageName: node
linkType: hard

"@types/semver@npm:^7.1.0":
"@types/semver@npm:^7.1.0, @types/semver@npm:^7.3.4":
version: 7.3.4
resolution: "@types/semver@npm:7.3.4"
checksum: 7e8588aa55ecb344eda6954674b83a3c568d97d478e70e4617bd3ab22902590ac416ccf2cea48b58fb2f0fbd80f9ad1896332c9b3c3189ffd24e4350ff22094a
Expand Down Expand Up @@ -11957,6 +11957,7 @@ fsevents@^1.2.7:
"@types/glob": ^7.1.1
"@types/graceful-fs": ^4.1.2
"@types/node": ^14.0.27
"@types/semver": ^7.3.4
"@types/yargs": ^15.0.0
chalk: ^4.0.0
cjs-module-lexer: ^0.4.2
Expand All @@ -11976,6 +11977,7 @@ fsevents@^1.2.7:
jest-snapshot-serializer-raw: ^1.1.0
jest-util: ^26.6.1
jest-validate: ^26.6.1
semver: ^7.3.2
slash: ^3.0.0
strip-bom: ^4.0.0
yargs: ^15.4.1
Expand Down

0 comments on commit 62dcfad

Please sign in to comment.