ts-jest 29.4.9 → 29.4.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.ts-jest-digest CHANGED
@@ -1 +1 @@
1
- 58edfe49f3f9192570efa8fa26d9cbc324d1324e
1
+ 19e702f0a49983ce6d92683fb1199ea2acf8e36a
package/CHANGELOG.md CHANGED
@@ -1,3 +1,34 @@
1
+ ## [29.4.10](https://github.com/kulshekhar/ts-jest/compare/v29.4.9...v29.4.10) (2026-05-18)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * pass `resolutionMode` to `ts.resolveModuleName` for hybrid module support ([b557a85](https://github.com/kulshekhar/ts-jest/commit/b557a85f85c3fd34523ec3a15293afbdc9dea83c))
7
+ * rebuild `Program` when consecutive compiles need different module kinds ([a82a2b3](https://github.com/kulshekhar/ts-jest/commit/a82a2b32c4987a5249fd5284283117dd2fa3be47)), closes [#4774](https://github.com/kulshekhar/ts-jest/issues/4774)
8
+ * respect tsconfig `moduleResolution` instead of forcing `Node10` ([1bffffc](https://github.com/kulshekhar/ts-jest/commit/1bffffc667557c173ae0c1f93dd436920775dac4))
9
+ * **transformer:** transpile `mjs` files from `node_modules` for CJS mode ([96d025d](https://github.com/kulshekhar/ts-jest/commit/96d025dd912ea2bceb18b67d2d509ada7a756d9d))
10
+ * **transformer:** use a consistent comparator in hoist-jest sortStatements ([8a8fd2f](https://github.com/kulshekhar/ts-jest/commit/8a8fd2fb8446655bba18367db9306a1089490e62))
11
+
12
+
13
+
14
+ ## [29.4.9](https://github.com/kulshekhar/ts-jest/compare/v29.4.8...v29.4.9) (2026-04-01)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * use correct registry for npm OIDC trusted publishing ([f8a9cc9](https://github.com/kulshekhar/ts-jest/commit/f8a9cc9892))
20
+
21
+
22
+
23
+ ## [29.4.8](https://github.com/kulshekhar/ts-jest/compare/v29.4.7...v29.4.8) (2026-04-01)
24
+
25
+
26
+ ### Bug Fixes
27
+
28
+ * wrong published assets
29
+
30
+
31
+
1
32
  ## [29.4.7](https://github.com/kulshekhar/ts-jest/compare/v29.4.6...v29.4.7) (2026-04-01)
2
33
 
3
34
 
@@ -5,6 +36,8 @@
5
36
 
6
37
  * support TypeScript v6 ([eda517d](https://github.com/kulshekhar/ts-jest/commit/eda517d226389317d99572887d3c1aa93c81be87))
7
38
 
39
+
40
+
8
41
  ## [29.4.6](https://github.com/kulshekhar/ts-jest/compare/v29.4.5...v29.4.6) (2025-12-01)
9
42
 
10
43
 
@@ -20,7 +20,109 @@ export declare class TsCompiler implements TsCompilerInstance {
20
20
  program: Program | undefined;
21
21
  constructor(configSet: ConfigSet, runtimeCacheFS: StringMap);
22
22
  getResolvedModules(fileContent: string, fileName: string, runtimeCacheFS: StringMap): string[];
23
+ /**
24
+ * Apply ts-jest's runtime fixups on top of the user's compiler options before
25
+ * handing them to the language service or transpiler.
26
+ *
27
+ * Two compiler-options now flow through dedicated helpers so the produced
28
+ * options are always a TypeScript-valid combination:
29
+ *
30
+ * - `moduleResolution` is delegated to `resolveCompatibleModuleResolution`,
31
+ * which preserves the user's value when it is valid alongside the
32
+ * `module` ts-jest forces at runtime (CommonJS on the CJS path, or
33
+ * ESNext / the user's original `module` on the ESM path) and otherwise
34
+ * substitutes a TypeScript-valid alternative. When the user has not set
35
+ * a value the historical Node10 default is kept, so unchanged tsconfigs
36
+ * see the exact same resolved options as before.
37
+ *
38
+ * - `customConditions` is delegated to `preserveCustomConditionsIfCompatible`,
39
+ * which keeps the user's value only when the resolved
40
+ * `moduleResolution` supports it (`Bundler` / `Node16` / `NodeNext`)
41
+ * and clears it otherwise. The pre-#4198 code unconditionally cleared
42
+ * this option because the hardcoded `Node10` override always made it
43
+ * incompatible; that is no longer true.
44
+ *
45
+ * @see https://github.com/kulshekhar/ts-jest/issues/4198
46
+ */
23
47
  private fixupCompilerOptionsForModuleKind;
48
+ /**
49
+ * Pick a `moduleResolution` value that is valid alongside the `module` ts-jest
50
+ * forces at runtime. Closes #4198: previously this was hardcoded to Node10 and
51
+ * silently overrode whatever the user set in tsconfig, even when the user value
52
+ * would have been valid (e.g. Bundler with module: ESNext, Classic with CommonJS).
53
+ *
54
+ * Substitution rules — each tied to a specific TypeScript diagnostic that the
55
+ * resulting combination would otherwise raise. The "Bundler-compatible" set is
56
+ * the one defined by `isBundlerCompatibleModuleKind` (ES2015 / ES2020 / ES2022
57
+ * / ESNext / Preserve); everything else (CommonJS / AMD / UMD / System / None)
58
+ * is treated as Bundler-incompatible across the full supported TS range.
59
+ *
60
+ * - Node16 / NodeNext require `module: Node16` or `module: NodeNext` (TS5110).
61
+ * ts-jest never emits those module kinds, so these user-supplied values are
62
+ * substituted: to Bundler when the forced module is in the
63
+ * Bundler-compatible set, or to Node10 otherwise. (Pairing Bundler with a
64
+ * non-ES module raises TS5095, and Node10 is the only kind that has been
65
+ * valid with non-ES modules across every TypeScript version ts-jest
66
+ * supports.)
67
+ *
68
+ * - User-supplied Bundler with a non-Bundler-compatible forced module is
69
+ * also TS5095 on the supported TS range — substitute Node10. (TypeScript
70
+ * 6 relaxed this for `module: CommonJS` specifically; that relaxation is
71
+ * deliberately not encoded here so behavior stays consistent across the
72
+ * full peerDependency range. See `isBundlerCompatibleModuleKind` for the
73
+ * follow-up pointer.)
74
+ *
75
+ * - Anything else (Node10 / Classic / unset) passes through or falls back
76
+ * to Node10. These pairings are valid with every forced module kind.
77
+ *
78
+ * Compatibility: `ModuleResolutionKind.Bundler` was introduced in
79
+ * TypeScript 5.0. ts-jest declares `peerDependencies: { typescript: ">=4.3 <7" }`,
80
+ * so the Bundler member is `undefined` at runtime on TypeScript 4.3 - 4.9.
81
+ * The Node16/NodeNext substitution falls back to Node10 in that case
82
+ * (`bundlerResolution` below) to keep the function deterministic across the
83
+ * full supported range. Users on TypeScript < 5 can never have set Bundler in
84
+ * tsconfig (the parser rejects it), so the user-supplied-Bundler branch is
85
+ * unreachable there and needs no separate guard.
86
+ */
87
+ private resolveCompatibleModuleResolution;
88
+ /**
89
+ * TypeScript pairs `moduleResolution: bundler` only with ES-module module
90
+ * kinds (`ES2015` / `ES2020` / `ES2022` / `ESNext`) or `Preserve` (added in
91
+ * TypeScript 5.4). Pairing `bundler` with `CommonJS`, `AMD`, `UMD`, `System`,
92
+ * or `None` raises TS5095. Used by `resolveCompatibleModuleResolution` to
93
+ * gate the `Node16` / `NodeNext` → `Bundler` substitution and the
94
+ * user-supplied-`Bundler` pass-through, so neither path emits an invalid
95
+ * pair when the user has selected a non-ES `module`.
96
+ *
97
+ * Note: TypeScript 6.0 relaxed this restriction for `module: CommonJS`
98
+ * specifically (`CommonJS` + `Bundler` is now a valid pair on TS ≥ 6); the
99
+ * other non-ES module kinds (`AMD` / `UMD` / `System` / `None`) remain
100
+ * Bundler-incompatible on every TypeScript version. The TS 6 relaxation is
101
+ * intentionally not encoded here to keep behavior consistent across the full
102
+ * peerDependency range (`>=4.3 <7`); honoring it can ride in as a follow-up
103
+ * once the TS 6 baseline lands.
104
+ *
105
+ * @see https://www.typescriptlang.org/tsconfig/#moduleResolution
106
+ */
107
+ private isBundlerCompatibleModuleKind;
108
+ /**
109
+ * Pass `customConditions` through unchanged when the resolved
110
+ * `moduleResolution` is one of the kinds that supports it (`Bundler`,
111
+ * `Node16`, `NodeNext`); strip it otherwise. TypeScript raises TS5098
112
+ * when `customConditions` is paired with any other resolution kind
113
+ * (verified empirically against TypeScript 5.9.3 with `tsc -p`).
114
+ *
115
+ * Before #4198 the surrounding `fixupCompilerOptionsForModuleKind`
116
+ * unconditionally cleared `customConditions` because the hardcoded
117
+ * `Node10` override always made it incompatible. After #4198 the
118
+ * resolved `moduleResolution` can be `Bundler` (e.g. when the user
119
+ * has `Node16`/`NodeNext` paired with an ES-family `module`), so we
120
+ * need to preserve the user's `customConditions` in that case rather
121
+ * than silently dropping it.
122
+ *
123
+ * @see https://www.typescriptlang.org/tsconfig/#customConditions
124
+ */
125
+ private preserveCustomConditionsIfCompatible;
24
126
  getCompiledOutput(fileContent: string, fileName: string, options: TsJestCompileOptions): CompiledOutput;
25
127
  protected _transpileOutput(fileContent: string, fileName: string): TranspileOutput;
26
128
  protected _makeTransformers(customTransformers: TsJestAstTransformer): CustomTransformers;
@@ -49,6 +49,10 @@ class TsCompiler {
49
49
  * @internal
50
50
  */
51
51
  _projectVersion = 1;
52
+ /**
53
+ * @internal
54
+ */
55
+ _previousCompiledModuleKind;
52
56
  /**
53
57
  * @internal
54
58
  */
@@ -107,17 +111,38 @@ class TsCompiler {
107
111
  });
108
112
  return importedModulePaths;
109
113
  }
114
+ /**
115
+ * Apply ts-jest's runtime fixups on top of the user's compiler options before
116
+ * handing them to the language service or transpiler.
117
+ *
118
+ * Two compiler-options now flow through dedicated helpers so the produced
119
+ * options are always a TypeScript-valid combination:
120
+ *
121
+ * - `moduleResolution` is delegated to `resolveCompatibleModuleResolution`,
122
+ * which preserves the user's value when it is valid alongside the
123
+ * `module` ts-jest forces at runtime (CommonJS on the CJS path, or
124
+ * ESNext / the user's original `module` on the ESM path) and otherwise
125
+ * substitutes a TypeScript-valid alternative. When the user has not set
126
+ * a value the historical Node10 default is kept, so unchanged tsconfigs
127
+ * see the exact same resolved options as before.
128
+ *
129
+ * - `customConditions` is delegated to `preserveCustomConditionsIfCompatible`,
130
+ * which keeps the user's value only when the resolved
131
+ * `moduleResolution` supports it (`Bundler` / `Node16` / `NodeNext`)
132
+ * and clears it otherwise. The pre-#4198 code unconditionally cleared
133
+ * this option because the hardcoded `Node10` override always made it
134
+ * incompatible; that is no longer true.
135
+ *
136
+ * @see https://github.com/kulshekhar/ts-jest/issues/4198
137
+ */
110
138
  fixupCompilerOptionsForModuleKind(compilerOptions, isEsm) {
111
- const moduleResolution = this._ts.ModuleResolutionKind.Node10 ?? this._ts.ModuleResolutionKind.NodeJs;
112
139
  if (!isEsm) {
140
+ const moduleResolution = this.resolveCompatibleModuleResolution(this._ts.ModuleKind.CommonJS, compilerOptions.moduleResolution);
113
141
  return {
114
142
  ...compilerOptions,
115
143
  module: this._ts.ModuleKind.CommonJS,
116
144
  moduleResolution,
117
- /**
118
- * This option is only supported in `Node16`/`NodeNext` and `Bundler` module, see https://www.typescriptlang.org/tsconfig/#customConditions
119
- */
120
- customConditions: undefined,
145
+ customConditions: this.preserveCustomConditionsIfCompatible(moduleResolution, compilerOptions.customConditions),
121
146
  };
122
147
  }
123
148
  let moduleKind = compilerOptions.module ?? this._ts.ModuleKind.ESNext;
@@ -126,22 +151,134 @@ class TsCompiler {
126
151
  esModuleInterop = true;
127
152
  moduleKind = this._ts.ModuleKind.ESNext;
128
153
  }
154
+ const moduleResolution = this.resolveCompatibleModuleResolution(moduleKind, compilerOptions.moduleResolution);
129
155
  return {
130
156
  ...compilerOptions,
131
157
  module: moduleKind,
132
158
  esModuleInterop,
133
159
  moduleResolution,
134
- /**
135
- * This option is only supported in `Node16`/`NodeNext` and `Bundler` module, see https://www.typescriptlang.org/tsconfig/#customConditions
136
- */
137
- customConditions: undefined,
160
+ customConditions: this.preserveCustomConditionsIfCompatible(moduleResolution, compilerOptions.customConditions),
138
161
  };
139
162
  }
163
+ /**
164
+ * Pick a `moduleResolution` value that is valid alongside the `module` ts-jest
165
+ * forces at runtime. Closes #4198: previously this was hardcoded to Node10 and
166
+ * silently overrode whatever the user set in tsconfig, even when the user value
167
+ * would have been valid (e.g. Bundler with module: ESNext, Classic with CommonJS).
168
+ *
169
+ * Substitution rules — each tied to a specific TypeScript diagnostic that the
170
+ * resulting combination would otherwise raise. The "Bundler-compatible" set is
171
+ * the one defined by `isBundlerCompatibleModuleKind` (ES2015 / ES2020 / ES2022
172
+ * / ESNext / Preserve); everything else (CommonJS / AMD / UMD / System / None)
173
+ * is treated as Bundler-incompatible across the full supported TS range.
174
+ *
175
+ * - Node16 / NodeNext require `module: Node16` or `module: NodeNext` (TS5110).
176
+ * ts-jest never emits those module kinds, so these user-supplied values are
177
+ * substituted: to Bundler when the forced module is in the
178
+ * Bundler-compatible set, or to Node10 otherwise. (Pairing Bundler with a
179
+ * non-ES module raises TS5095, and Node10 is the only kind that has been
180
+ * valid with non-ES modules across every TypeScript version ts-jest
181
+ * supports.)
182
+ *
183
+ * - User-supplied Bundler with a non-Bundler-compatible forced module is
184
+ * also TS5095 on the supported TS range — substitute Node10. (TypeScript
185
+ * 6 relaxed this for `module: CommonJS` specifically; that relaxation is
186
+ * deliberately not encoded here so behavior stays consistent across the
187
+ * full peerDependency range. See `isBundlerCompatibleModuleKind` for the
188
+ * follow-up pointer.)
189
+ *
190
+ * - Anything else (Node10 / Classic / unset) passes through or falls back
191
+ * to Node10. These pairings are valid with every forced module kind.
192
+ *
193
+ * Compatibility: `ModuleResolutionKind.Bundler` was introduced in
194
+ * TypeScript 5.0. ts-jest declares `peerDependencies: { typescript: ">=4.3 <7" }`,
195
+ * so the Bundler member is `undefined` at runtime on TypeScript 4.3 - 4.9.
196
+ * The Node16/NodeNext substitution falls back to Node10 in that case
197
+ * (`bundlerResolution` below) to keep the function deterministic across the
198
+ * full supported range. Users on TypeScript < 5 can never have set Bundler in
199
+ * tsconfig (the parser rejects it), so the user-supplied-Bundler branch is
200
+ * unreachable there and needs no separate guard.
201
+ */
202
+ resolveCompatibleModuleResolution(forcedModule, userResolution) {
203
+ const node10Default = this._ts.ModuleResolutionKind.Node10 ?? this._ts.ModuleResolutionKind.NodeJs;
204
+ if (userResolution === undefined) {
205
+ return node10Default;
206
+ }
207
+ const { Node16, NodeNext, Bundler } = this._ts.ModuleResolutionKind;
208
+ const bundlerResolution = Bundler ?? node10Default;
209
+ const canUseBundler = this.isBundlerCompatibleModuleKind(forcedModule);
210
+ if (userResolution === Node16 || userResolution === NodeNext) {
211
+ return canUseBundler ? bundlerResolution : node10Default;
212
+ }
213
+ if (userResolution === Bundler && !canUseBundler) {
214
+ return node10Default;
215
+ }
216
+ return userResolution;
217
+ }
218
+ /**
219
+ * TypeScript pairs `moduleResolution: bundler` only with ES-module module
220
+ * kinds (`ES2015` / `ES2020` / `ES2022` / `ESNext`) or `Preserve` (added in
221
+ * TypeScript 5.4). Pairing `bundler` with `CommonJS`, `AMD`, `UMD`, `System`,
222
+ * or `None` raises TS5095. Used by `resolveCompatibleModuleResolution` to
223
+ * gate the `Node16` / `NodeNext` → `Bundler` substitution and the
224
+ * user-supplied-`Bundler` pass-through, so neither path emits an invalid
225
+ * pair when the user has selected a non-ES `module`.
226
+ *
227
+ * Note: TypeScript 6.0 relaxed this restriction for `module: CommonJS`
228
+ * specifically (`CommonJS` + `Bundler` is now a valid pair on TS ≥ 6); the
229
+ * other non-ES module kinds (`AMD` / `UMD` / `System` / `None`) remain
230
+ * Bundler-incompatible on every TypeScript version. The TS 6 relaxation is
231
+ * intentionally not encoded here to keep behavior consistent across the full
232
+ * peerDependency range (`>=4.3 <7`); honoring it can ride in as a follow-up
233
+ * once the TS 6 baseline lands.
234
+ *
235
+ * @see https://www.typescriptlang.org/tsconfig/#moduleResolution
236
+ */
237
+ isBundlerCompatibleModuleKind(moduleKind) {
238
+ const M = this._ts.ModuleKind;
239
+ if (moduleKind === M.ESNext || moduleKind === M.ES2015 || moduleKind === M.ES2020 || moduleKind === M.ES2022) {
240
+ return true;
241
+ }
242
+ // `ModuleKind.Preserve` was introduced in TypeScript 5.4; on older
243
+ // TypeScript versions the property is `undefined` at runtime.
244
+ if (M.Preserve !== undefined && moduleKind === M.Preserve) {
245
+ return true;
246
+ }
247
+ return false;
248
+ }
249
+ /**
250
+ * Pass `customConditions` through unchanged when the resolved
251
+ * `moduleResolution` is one of the kinds that supports it (`Bundler`,
252
+ * `Node16`, `NodeNext`); strip it otherwise. TypeScript raises TS5098
253
+ * when `customConditions` is paired with any other resolution kind
254
+ * (verified empirically against TypeScript 5.9.3 with `tsc -p`).
255
+ *
256
+ * Before #4198 the surrounding `fixupCompilerOptionsForModuleKind`
257
+ * unconditionally cleared `customConditions` because the hardcoded
258
+ * `Node10` override always made it incompatible. After #4198 the
259
+ * resolved `moduleResolution` can be `Bundler` (e.g. when the user
260
+ * has `Node16`/`NodeNext` paired with an ES-family `module`), so we
261
+ * need to preserve the user's `customConditions` in that case rather
262
+ * than silently dropping it.
263
+ *
264
+ * @see https://www.typescriptlang.org/tsconfig/#customConditions
265
+ */
266
+ preserveCustomConditionsIfCompatible(resolvedModuleResolution, userCustomConditions) {
267
+ const R = this._ts.ModuleResolutionKind;
268
+ const supportsCustomConditions = resolvedModuleResolution === R.Bundler ||
269
+ resolvedModuleResolution === R.Node16 ||
270
+ resolvedModuleResolution === R.NodeNext;
271
+ return supportsCustomConditions ? userCustomConditions : undefined;
272
+ }
140
273
  getCompiledOutput(fileContent, fileName, options) {
141
274
  const isEsmMode = this.configSet.useESM && options.supportsStaticESM;
142
275
  this._compilerOptions = this.fixupCompilerOptionsForModuleKind(this._initialCompilerOptions, isEsmMode);
143
276
  const moduleKind = this._initialCompilerOptions.module;
144
277
  const currentModuleKind = this._compilerOptions.module;
278
+ // Without this, a Program rebuilt for one compile's module kind would be
279
+ // reused on the next compile when that compile expects a different kind.
280
+ const moduleKindChangedSinceLastCompile = this._previousCompiledModuleKind !== undefined && this._previousCompiledModuleKind !== currentModuleKind;
281
+ this._previousCompiledModuleKind = currentModuleKind;
145
282
  if (this._languageService) {
146
283
  if (constants_1.JS_JSX_REGEX.test(fileName) && !this._compilerOptions.allowJs) {
147
284
  this._logger.warn({ fileName: fileName }, (0, messages_1.interpolate)("Got a `.js` file to compile while `allowJs` option is not set to `true` (file: {{path}}). To fix this:\n - if you want TypeScript to process JS files, set `allowJs` to `true` in your TypeScript config (usually tsconfig.json)\n - if you do not want TypeScript to process your `.js` files, in your Jest config change the `transform` key which value is `ts-jest` so that it does not match `.js` files anymore" /* Errors.GotJsFileButAllowJsFalse */, { path: fileName }));
@@ -151,7 +288,7 @@ class TsCompiler {
151
288
  }
152
289
  this._logger.debug({ fileName }, 'getCompiledOutput(): compiling using language service');
153
290
  // Must set memory cache before attempting to compile
154
- this._updateMemoryCache(fileContent, fileName, currentModuleKind === moduleKind);
291
+ this._updateMemoryCache(fileContent, fileName, currentModuleKind === moduleKind && !moduleKindChangedSinceLastCompile);
155
292
  const output = this._languageService.getEmitOutput(fileName);
156
293
  const diagnostics = this.getDiagnostics(fileName);
157
294
  if ((0, transpile_module_1.isModernNodeModuleKind)(this._initialCompilerOptions.module)) {
@@ -360,11 +497,17 @@ class TsCompiler {
360
497
  * @internal
361
498
  */
362
499
  _resolveModuleName(moduleNameToResolve, containingFile) {
500
+ const getImpliedNodeFormat = this._ts.getImpliedNodeFormatForFile;
501
+ const resolutionMode = typeof getImpliedNodeFormat === 'function'
502
+ ? getImpliedNodeFormat(containingFile, undefined,
503
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
504
+ this._moduleResolutionHost, this._compilerOptions)
505
+ : undefined;
363
506
  return this._ts.resolveModuleName(moduleNameToResolve, containingFile, this._compilerOptions,
364
507
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
365
508
  this._moduleResolutionHost,
366
509
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
367
- this._moduleResolutionCache);
510
+ this._moduleResolutionCache, undefined, resolutionMode);
368
511
  }
369
512
  /**
370
513
  * @internal
@@ -189,11 +189,14 @@ class TsJestTransformer {
189
189
  const transpiledResult = typescript_1.default.transpileModule(sourceText, {
190
190
  compilerOptions: {
191
191
  ...configs.parsedTsConfig.options,
192
- module: transformOptions.supportsStaticESM && transformOptions.transformerConfig.useESM
192
+ module: transformOptions.supportsStaticESM && transformOptions.transformerConfig?.useESM
193
193
  ? typescript_1.default.ModuleKind.ESNext
194
194
  : typescript_1.default.ModuleKind.CommonJS,
195
195
  },
196
- fileName: sourcePath,
196
+ // .mjs fileName causes ts.transpileModule to preserve ESM syntax even with module: CommonJS
197
+ fileName: transformOptions.supportsStaticESM && transformOptions.transformerConfig?.useESM
198
+ ? sourcePath
199
+ : sourcePath.replace(/\.mjs$/, '.js'),
197
200
  });
198
201
  result = {
199
202
  code: (0, compiler_utils_1.updateOutput)(transpiledResult.outputText, sourcePath, transpiledResult.sourceMapText),
@@ -62,10 +62,17 @@ function factory({ configSet }) {
62
62
  if (statements.length <= 1) {
63
63
  return statements;
64
64
  }
65
- return statements.sort((stmtA, stmtB) => isJestGlobalImport(stmtA) ||
66
- (isHoistableStatement(stmtA) && !isHoistableStatement(stmtB) && !isJestGlobalImport(stmtB))
67
- ? -1
68
- : 1);
65
+ // Return 0 for same-category statements so stable sort preserves source
66
+ // order, the previous `-1 | 1`-only comparator violated ECMA's consistent
67
+ // comparison contract and let V8 reorder same-category pairs.
68
+ const priority = (stmt) => {
69
+ if (isJestGlobalImport(stmt))
70
+ return 0;
71
+ if (isHoistableStatement(stmt))
72
+ return 1;
73
+ return 2;
74
+ };
75
+ return statements.sort((a, b) => priority(a) - priority(b));
69
76
  };
70
77
  const createVisitor = (ctx, _) => {
71
78
  const visitor = (node) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-jest",
3
- "version": "29.4.9",
3
+ "version": "29.4.10",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "commonjs",
@@ -57,7 +57,7 @@
57
57
  "json5": "^2.2.3",
58
58
  "lodash.memoize": "^4.1.2",
59
59
  "make-error": "^1.3.6",
60
- "semver": "^7.7.4",
60
+ "semver": "^7.8.0",
61
61
  "type-fest": "^4.41.0",
62
62
  "yargs-parser": "^21.1.1"
63
63
  },
@@ -96,9 +96,9 @@
96
96
  "@eslint/compat": "^1.4.1",
97
97
  "@eslint/eslintrc": "^3.3.5",
98
98
  "@eslint/js": "^9.39.4",
99
- "@jest/globals": "^30.3.0",
100
- "@jest/transform": "^30.3.0",
101
- "@jest/types": "^30.3.0",
99
+ "@jest/globals": "^30.4.1",
100
+ "@jest/transform": "^30.4.1",
101
+ "@jest/types": "^30.4.1",
102
102
  "@types/babel__core": "^7.20.5",
103
103
  "@types/fs-extra": "^11.0.4",
104
104
  "@types/jest": "^29.5.14",
@@ -107,16 +107,16 @@
107
107
  "@types/lodash.memoize": "^4.1.9",
108
108
  "@types/lodash.set": "^4.3.9",
109
109
  "@types/micromatch": "^4.0.10",
110
- "@types/node": "20.19.37",
110
+ "@types/node": "20.19.41",
111
111
  "@types/semver": "^7.7.1",
112
112
  "@types/yargs": "^17.0.35",
113
113
  "@types/yargs-parser": "21.0.3",
114
- "@typescript-eslint/eslint-plugin": "^8.57.2",
115
- "@typescript-eslint/parser": "^8.57.2",
116
- "babel-jest": "^30.3.0",
117
- "conventional-changelog-angular": "^8.3.0",
114
+ "@typescript-eslint/eslint-plugin": "^8.59.3",
115
+ "@typescript-eslint/parser": "^8.59.3",
116
+ "babel-jest": "^30.4.1",
117
+ "conventional-changelog-angular": "^8.3.1",
118
118
  "conventional-changelog": "^7.2.0",
119
- "esbuild": "~0.27.4",
119
+ "esbuild": "~0.28.0",
120
120
  "eslint": "^9.39.4",
121
121
  "eslint-config-prettier": "^10.1.8",
122
122
  "eslint-plugin-import": "^2.32.0",
@@ -125,18 +125,18 @@
125
125
  "eslint-plugin-prettier": "^4.2.5",
126
126
  "execa": "5.1.1",
127
127
  "fast-glob": "^3.3.3",
128
- "fs-extra": "^11.3.4",
128
+ "fs-extra": "^11.3.5",
129
129
  "globals": "^16.5.0",
130
130
  "husky": "^9.1.7",
131
- "jest": "^30.3.0",
131
+ "jest": "^30.4.2",
132
132
  "js-yaml": "^4.1.1",
133
133
  "lint-staged": "^15.5.2",
134
- "memfs": "^4.57.1",
134
+ "memfs": "^4.57.2",
135
135
  "prettier": "^2.8.8",
136
136
  "rimraf": "^5.0.10",
137
137
  "ts-node": "^10.9.2",
138
138
  "typescript": "~5.9.3",
139
- "typescript-eslint": "^8.57.2"
139
+ "typescript-eslint": "^8.59.3"
140
140
  },
141
141
  "engines": {
142
142
  "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0"