UNPKG

2.91 kBJavaScriptView Raw
1/*
2 * Copyright 2022 The Backstage Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17const fs = require('fs');
18const { default: JestRuntime } = require('jest-runtime');
19
20const fileTransformCache = new Map();
21const scriptTransformCache = new Map();
22
23let runtimeGeneration = 0;
24
25module.exports = class CachingJestRuntime extends JestRuntime {
26 // Each Jest run creates a new runtime, including when rerunning tests in
27 // watch mode. This keeps track of whether we've switched runtime instance.
28 __runtimeGeneration = runtimeGeneration++;
29
30 transformFile(filename, options) {
31 const entry = fileTransformCache.get(filename);
32 if (entry) {
33 // Only check modification time if it's from a different runtime generation
34 if (entry.generation === this.__runtimeGeneration) {
35 return entry.code;
36 }
37
38 // Keep track of the modification time of files so that we can properly
39 // reprocess them in watch mode.
40 const { mtimeMs } = fs.statSync(filename);
41 if (mtimeMs > entry.mtimeMs) {
42 const code = super.transformFile(filename, options);
43 fileTransformCache.set(filename, {
44 code,
45 mtimeMs,
46 generation: this.__runtimeGeneration,
47 });
48 return code;
49 }
50
51 fileTransformCache.set(filename, {
52 ...entry,
53 generation: this.__runtimeGeneration,
54 });
55 return entry.code;
56 }
57
58 const code = super.transformFile(filename, options);
59 fileTransformCache.set(filename, {
60 code,
61 mtimeMs: fs.statSync(filename).mtimeMs,
62 generation: this.__runtimeGeneration,
63 });
64 return code;
65 }
66
67 // This may or may not be a good idea. Theoretically I don't know why this would impact
68 // test correctness and flakiness, but it seems like it may introduce flakiness and strange failures.
69 // It does seem to speed up test execution by a fair amount though.
70 createScriptFromCode(scriptSource, filename) {
71 let script = scriptTransformCache.get(scriptSource);
72 if (!script) {
73 script = super.createScriptFromCode(scriptSource, filename);
74 // Tried to store the script object in a WeakRef here. It starts out at
75 // about 90% hit rate, but eventually drops all the way to 20%, and overall
76 // it seemed to increase memory usage by 20% or so.
77 scriptTransformCache.set(scriptSource, script);
78 }
79 return script;
80 }
81};