Skip to content

Commit f143ce6

Browse files
committed
feat(transform): pass config options through to transformer
1 parent 0f09ca4 commit f143ce6

File tree

8 files changed

+62
-37
lines changed

8 files changed

+62
-37
lines changed

docs/CodeTransformation.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,17 @@ interface Transformer<OptionType = unknown> {
3535
getCacheKey?: (
3636
sourceText: string,
3737
sourcePath: string,
38-
options: TransformOptions,
38+
options: TransformOptions<OptionType>,
3939
) => string;
4040

4141
process: (
4242
sourceText: string,
4343
sourcePath: string,
44-
options: TransformOptions,
44+
options: TransformOptions<OptionType>,
4545
) => TransformedSource;
4646
}
4747

48-
interface TransformOptions {
48+
interface TransformOptions<OptionType> {
4949
/**
5050
* If a transformer does module resolution and reads files, it should populate `cacheFS` so that
5151
* Jest avoids reading the same files again, improving performance. `cacheFS` stores entries of
@@ -61,6 +61,8 @@ interface TransformOptions {
6161
supportsExportNamespaceFrom: boolean;
6262
supportsStaticESM: boolean;
6363
supportsTopLevelAwait: boolean;
64+
/** the options passed through Jest's config by the user */
65+
transformerConfig: OptionType;
6466
}
6567

6668
type TransformedSource =

packages/babel-jest/src/index.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ const createTransformer: CreateTransformer = userOptions => {
5050
function loadBabelConfig(
5151
cwd: Config.Path,
5252
filename: Config.Path,
53-
transformOptions?: JestTransformOptions,
53+
transformOptions: JestTransformOptions,
5454
): PartialConfig {
5555
// `cwd` first to allow incoming options to override it
5656
const babelConfig = loadPartialConfig({
@@ -59,16 +59,16 @@ const createTransformer: CreateTransformer = userOptions => {
5959
caller: {
6060
...options.caller,
6161
supportsDynamicImport:
62-
transformOptions?.supportsDynamicImport ??
62+
transformOptions.supportsDynamicImport ??
6363
options.caller.supportsDynamicImport,
6464
supportsExportNamespaceFrom:
65-
transformOptions?.supportsExportNamespaceFrom ??
65+
transformOptions.supportsExportNamespaceFrom ??
6666
options.caller.supportsExportNamespaceFrom,
6767
supportsStaticESM:
68-
transformOptions?.supportsStaticESM ??
68+
transformOptions.supportsStaticESM ??
6969
options.caller.supportsStaticESM,
7070
supportsTopLevelAwait:
71-
transformOptions?.supportsTopLevelAwait ??
71+
transformOptions.supportsTopLevelAwait ??
7272
options.caller.supportsTopLevelAwait,
7373
},
7474
filename,

packages/jest-repl/src/cli/repl.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import type {Transformer} from '@jest/transform';
1515
import type {Config} from '@jest/types';
1616

1717
let transformer: Transformer;
18+
let transformerConfig: unknown;
1819

1920
const evalCommand: repl.REPLEval = (
2021
cmd: string,
@@ -37,6 +38,7 @@ const evalCommand: repl.REPLEval = (
3738
supportsExportNamespaceFrom: false,
3839
supportsStaticESM: false,
3940
supportsTopLevelAwait: false,
41+
transformerConfig,
4042
},
4143
);
4244
cmd =
@@ -69,6 +71,7 @@ if (jestProjectConfig.transform) {
6971
for (let i = 0; i < jestProjectConfig.transform.length; i++) {
7072
if (new RegExp(jestProjectConfig.transform[i][0]).test('foobar.js')) {
7173
transformerPath = jestProjectConfig.transform[i][1];
74+
transformerConfig = jestProjectConfig.transform[i][2];
7275
break;
7376
}
7477
}

packages/jest-transform/src/ScriptTransformer.ts

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@ export default class ScriptTransformer {
6767
private readonly _cache: ProjectCache;
6868
private readonly _cacheFS: StringMap;
6969
private readonly _config: Config.ProjectConfig;
70-
private readonly _transformCache: Map<Config.Path, Transformer>;
70+
private readonly _transformCache: Map<
71+
Config.Path,
72+
{transformer: Transformer; transformerConfig: unknown}
73+
>;
7174
private readonly _transformConfigCache: Map<Config.Path, unknown>;
7275

7376
constructor(
@@ -102,7 +105,8 @@ export default class ScriptTransformer {
102105
options: ReducedTransformOptions,
103106
): string {
104107
const configString = this._cache.configString;
105-
const transformer = this._getTransformer(filename);
108+
const {transformer, transformerConfig = {}} =
109+
this._getTransformer(filename) || {};
106110

107111
if (transformer && typeof transformer.getCacheKey === 'function') {
108112
return createHash('md5')
@@ -112,6 +116,7 @@ export default class ScriptTransformer {
112116
cacheFS: this._cacheFS,
113117
config: this._config,
114118
configString,
119+
transformerConfig,
115120
}),
116121
)
117122
.update(CACHE_VERSION)
@@ -181,28 +186,30 @@ export default class ScriptTransformer {
181186
return null;
182187
}
183188

184-
const transformer = this._transformCache.get(transformPath);
185-
if (transformer) {
186-
return transformer;
189+
const cached = this._transformCache.get(transformPath);
190+
if (cached) {
191+
return cached;
187192
}
188193

189-
let transform: Transformer = require(transformPath);
194+
let transformer: Transformer = require(transformPath);
190195

191-
if (!transform) {
196+
if (!transformer) {
192197
throw new TypeError('Jest: a transform must export something.');
193198
}
194-
const transformerConfig = this._transformConfigCache.get(transformPath);
195-
if (typeof transform.createTransformer === 'function') {
196-
transform = transform.createTransformer(transformerConfig);
199+
const transformerConfig =
200+
this._transformConfigCache.get(transformPath) || {};
201+
if (typeof transformer.createTransformer === 'function') {
202+
transformer = transformer.createTransformer(transformerConfig);
197203
}
198-
if (typeof transform.process !== 'function') {
204+
if (typeof transformer.process !== 'function') {
199205
throw new TypeError(
200206
'Jest: a transform must export a `process` function.',
201207
);
202208
}
203-
this._transformCache.set(transformPath, transform);
209+
const res = {transformer, transformerConfig};
210+
this._transformCache.set(transformPath, res);
204211

205-
return transform;
212+
return res;
206213
}
207214

208215
private _instrumentFile(
@@ -262,18 +269,19 @@ export default class ScriptTransformer {
262269
options: ReducedTransformOptions,
263270
): TransformResult {
264271
const filename = tryRealpath(filepath);
265-
const transform = this._getTransformer(filename);
272+
const {transformer, transformerConfig = {}} =
273+
this._getTransformer(filename) || {};
266274
const cacheFilePath = this._getFileCachePath(filename, content, options);
267275
let sourceMapPath: Config.Path | null = cacheFilePath + '.map';
268276
// Ignore cache if `config.cache` is set (--no-cache)
269277
let code = this._config.cache ? readCodeCacheFile(cacheFilePath) : null;
270278

271-
const shouldCallTransform = transform && this.shouldTransform(filename);
279+
const shouldCallTransform = transformer && this.shouldTransform(filename);
272280

273281
// That means that the transform has a custom instrumentation
274282
// logic and will handle it based on `config.collectCoverage` option
275283
const transformWillInstrument =
276-
shouldCallTransform && transform && transform.canInstrument;
284+
shouldCallTransform && transformer && transformer.canInstrument;
277285

278286
if (code) {
279287
// This is broken: we return the code, and a path for the source map
@@ -292,12 +300,13 @@ export default class ScriptTransformer {
292300
map: null,
293301
};
294302

295-
if (transform && shouldCallTransform) {
296-
const processed = transform.process(content, filename, {
303+
if (transformer && shouldCallTransform) {
304+
const processed = transformer.process(content, filename, {
297305
...options,
298306
cacheFS: this._cacheFS,
299307
config: this._config,
300308
configString: this._cache.configString,
309+
transformerConfig,
301310
});
302311

303312
if (typeof processed === 'string') {
@@ -343,7 +352,7 @@ export default class ScriptTransformer {
343352
*
344353
*/
345354
const shouldEmitSourceMaps =
346-
(transform != null && map != null) || transform == null;
355+
(transformer != null && map != null) || transformer == null;
347356

348357
const instrumented = this._instrumentFile(
349358
filename,

packages/jest-transform/src/__tests__/script_transformer.test.ts renamed to packages/jest-transform/src/__tests__/ScriptTransformer.test.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,10 @@ describe('ScriptTransformer', () => {
663663
});
664664

665665
it('passes expected transform options to getCacheKey', () => {
666-
config = {...config, transform: [['\\.js$', 'test_preprocessor', {}]]};
666+
config = {
667+
...config,
668+
transform: [['\\.js$', 'test_preprocessor', {configKey: 'configValue'}]],
669+
};
667670
const scriptTransformer = new ScriptTransformer(config);
668671

669672
scriptTransformer.transform(
@@ -779,8 +782,8 @@ describe('ScriptTransformer', () => {
779782

780783
scriptTransformer.transform(fileName2, getCoverageOptions());
781784

782-
expect(testPreprocessor.getCacheKey.mock.calls[0][2].cacheFS).toBeDefined()
783-
expect(testPreprocessor.process.mock.calls[0][2].cacheFS).toBeDefined()
785+
expect(testPreprocessor.getCacheKey.mock.calls[0][2].cacheFS).toBeDefined();
786+
expect(testPreprocessor.process.mock.calls[0][2].cacheFS).toBeDefined();
784787
expect(fs.readFileSync).toHaveBeenCalledTimes(1);
785788
expect(fs.readFileSync).toBeCalledWith(fileName1, 'utf8');
786789
});

0 commit comments

Comments
 (0)