@rspack-canary/test-tools 1.6.0-canary-6cd722f4-20251022123039 → 1.6.0-canary-4ad8b49f-20251023175711

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.
Files changed (91) hide show
  1. package/dist/case/builtin.d.ts +3 -2
  2. package/dist/case/builtin.js +1 -1
  3. package/dist/case/cache.d.ts +2 -2
  4. package/dist/case/cache.js +9 -6
  5. package/dist/case/common.d.ts +10 -10
  6. package/dist/case/common.js +33 -30
  7. package/dist/case/compiler.d.ts +9 -8
  8. package/dist/case/compiler.js +5 -6
  9. package/dist/case/config.d.ts +6 -5
  10. package/dist/case/defaults.d.ts +5 -4
  11. package/dist/case/defaults.js +10 -10
  12. package/dist/case/diagnostic.js +4 -5
  13. package/dist/case/error.d.ts +5 -5
  14. package/dist/case/error.js +7 -8
  15. package/dist/case/example.js +2 -2
  16. package/dist/case/hash.d.ts +2 -2
  17. package/dist/case/hash.js +1 -1
  18. package/dist/case/hook.d.ts +4 -3
  19. package/dist/case/hook.js +3 -2
  20. package/dist/case/hot-step.d.ts +2 -2
  21. package/dist/case/hot-step.js +4 -6
  22. package/dist/case/hot.d.ts +5 -4
  23. package/dist/case/hot.js +6 -6
  24. package/dist/case/incremental.d.ts +2 -2
  25. package/dist/case/index.d.ts +0 -1
  26. package/dist/case/index.js +1 -3
  27. package/dist/case/multi-compiler.d.ts +9 -8
  28. package/dist/case/multi-compiler.js +3 -4
  29. package/dist/case/normal.js +1 -1
  30. package/dist/case/runner.d.ts +5 -4
  31. package/dist/case/runner.js +12 -8
  32. package/dist/case/serial.d.ts +2 -2
  33. package/dist/case/stats-api.d.ts +6 -5
  34. package/dist/case/stats-api.js +5 -7
  35. package/dist/case/stats-output.d.ts +3 -2
  36. package/dist/case/stats-output.js +1 -1
  37. package/dist/case/treeshaking.js +1 -1
  38. package/dist/case/watch.d.ts +6 -6
  39. package/dist/case/watch.js +15 -14
  40. package/dist/compiler.d.ts +16 -17
  41. package/dist/compiler.js +116 -16
  42. package/dist/helper/index.d.ts +1 -0
  43. package/dist/helper/index.js +1 -0
  44. package/dist/helper/legacy/checkArrayExpectation.js +1 -1
  45. package/dist/helper/read-config-file.d.ts +3 -2
  46. package/dist/helper/read-config-file.js +7 -0
  47. package/dist/helper/setup-env.js +1 -0
  48. package/dist/helper/stringify-config.d.ts +2 -0
  49. package/dist/helper/stringify-config.js +43 -0
  50. package/dist/index.d.ts +0 -1
  51. package/dist/index.js +0 -1
  52. package/dist/plugin/index.d.ts +0 -3
  53. package/dist/plugin/index.js +0 -3
  54. package/dist/runner/node/index.d.ts +13 -8
  55. package/dist/runner/node/index.js +86 -7
  56. package/dist/runner/web/index.d.ts +6 -5
  57. package/dist/runner/web/index.js +38 -50
  58. package/dist/test/context.d.ts +15 -16
  59. package/dist/test/context.js +44 -59
  60. package/dist/test/creator.d.ts +14 -14
  61. package/dist/test/creator.js +4 -5
  62. package/dist/test/debug.d.ts +15 -0
  63. package/dist/test/debug.js +205 -0
  64. package/dist/test/tester.js +13 -4
  65. package/dist/type.d.ts +37 -50
  66. package/dist/type.js +1 -6
  67. package/package.json +5 -9
  68. package/dist/case/diff.d.ts +0 -19
  69. package/dist/case/diff.js +0 -274
  70. package/dist/compare/comparator.d.ts +0 -17
  71. package/dist/compare/comparator.js +0 -52
  72. package/dist/compare/compare.d.ts +0 -17
  73. package/dist/compare/compare.js +0 -178
  74. package/dist/compare/format-code.d.ts +0 -16
  75. package/dist/compare/format-code.js +0 -244
  76. package/dist/compare/index.d.ts +0 -5
  77. package/dist/compare/index.js +0 -21
  78. package/dist/compare/replace-module-argument.d.ts +0 -1
  79. package/dist/compare/replace-module-argument.js +0 -8
  80. package/dist/compare/replace-runtime-module-name.d.ts +0 -1
  81. package/dist/compare/replace-runtime-module-name.js +0 -71
  82. package/dist/plugin/rspack-diff-config-plugin.d.ts +0 -7
  83. package/dist/plugin/rspack-diff-config-plugin.js +0 -42
  84. package/dist/plugin/webpack-diff-config-plugin.d.ts +0 -7
  85. package/dist/plugin/webpack-diff-config-plugin.js +0 -41
  86. package/dist/plugin/webpack-module-placeholder-plugin.d.ts +0 -3
  87. package/dist/plugin/webpack-module-placeholder-plugin.js +0 -106
  88. package/template/diff.bundle.css +0 -1
  89. package/template/diff.bundle.js +0 -144
  90. package/template/diff.html +0 -14
  91. package/template/editor.worker.js +0 -1
package/dist/compiler.js CHANGED
@@ -3,10 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.TestCompilerManager = exports.COMPILER_FACTORIES = exports.ECompilerEvent = void 0;
6
+ exports.TestCompilerManager = exports.ECompilerEvent = void 0;
7
7
  const node_events_1 = __importDefault(require("node:events"));
8
+ const core_1 = require("@rspack/core");
8
9
  const webpack_merge_1 = __importDefault(require("webpack-merge"));
9
- const type_1 = require("./type");
10
+ const debug_1 = require("./test/debug");
10
11
  var ECompilerEvent;
11
12
  (function (ECompilerEvent) {
12
13
  ECompilerEvent["Build"] = "build";
@@ -14,14 +15,9 @@ var ECompilerEvent;
14
15
  ECompilerEvent["Create"] = "create";
15
16
  ECompilerEvent["Close"] = "close";
16
17
  })(ECompilerEvent || (exports.ECompilerEvent = ECompilerEvent = {}));
17
- exports.COMPILER_FACTORIES = {
18
- [type_1.ECompilerType.Rspack]: ((options, callback) => require("@rspack/core")(options, callback)),
19
- [type_1.ECompilerType.Webpack]: ((options, callback) => require("webpack")(options, callback))
20
- };
21
18
  class TestCompilerManager {
22
- constructor(type, factories = exports.COMPILER_FACTORIES) {
23
- this.type = type;
24
- this.factories = factories;
19
+ constructor(context) {
20
+ this.context = context;
25
21
  this.compilerOptions = {};
26
22
  this.compilerInstance = null;
27
23
  this.compilerStats = null;
@@ -44,12 +40,58 @@ class TestCompilerManager {
44
40
  return this.compilerInstance;
45
41
  }
46
42
  createCompiler() {
47
- this.compilerInstance = this.factories[this.type](this.compilerOptions);
43
+ this.compilerInstance = require("@rspack/core")(this.compilerOptions);
44
+ if (__DEBUG__) {
45
+ const context = this.context;
46
+ this.compilerInstance = new Proxy(this.compilerInstance, {
47
+ get(target, p, receiver) {
48
+ const value = Reflect.get(target, p, receiver);
49
+ if (typeof value === "function" &&
50
+ core_1.Compiler.prototype.hasOwnProperty(p)) {
51
+ return value.bind(target);
52
+ }
53
+ return value;
54
+ },
55
+ set(target, p, value, receiver) {
56
+ const debugSetProperties = context.getValue(debug_1.DEBUG_SCOPES.CreateCompilerSetProperties) || [];
57
+ debugSetProperties.push(`${p} ${new Error().stack?.split("\n")[2]?.trim()}`);
58
+ context.setValue(debug_1.DEBUG_SCOPES.CreateCompilerSetProperties, debugSetProperties);
59
+ return Reflect.set(target, p, value, receiver);
60
+ }
61
+ });
62
+ this.context.setValue(debug_1.DEBUG_SCOPES.CreateCompilerInstance, {
63
+ path: require.resolve("@rspack/core"),
64
+ mode: "no-callback"
65
+ });
66
+ }
48
67
  this.emitter.emit(ECompilerEvent.Create, this.compilerInstance);
49
68
  return this.compilerInstance;
50
69
  }
51
70
  createCompilerWithCallback(callback) {
52
- this.compilerInstance = this.factories[this.type](this.compilerOptions, callback);
71
+ this.compilerInstance = require("@rspack/core")(this.compilerOptions, callback);
72
+ if (__DEBUG__) {
73
+ const context = this.context;
74
+ this.compilerInstance = new Proxy(this.compilerInstance, {
75
+ get(target, p, receiver) {
76
+ const value = Reflect.get(target, p, receiver);
77
+ if (typeof value === "function" &&
78
+ core_1.Compiler.prototype.hasOwnProperty(p)) {
79
+ return value.bind(target);
80
+ }
81
+ return value;
82
+ },
83
+ set(target, p, value, receiver) {
84
+ const debugSetProperties = context.getValue(debug_1.DEBUG_SCOPES.CreateCompilerSetProperties) || [];
85
+ debugSetProperties.push(`${p} ${new Error().stack?.split("\n")[2]?.trim()}`);
86
+ context.setValue(debug_1.DEBUG_SCOPES.CreateCompilerSetProperties, debugSetProperties);
87
+ return Reflect.set(target, p, value, receiver);
88
+ }
89
+ });
90
+ this.context.setValue(debug_1.DEBUG_SCOPES.CreateCompilerInstance, {
91
+ path: require.resolve("@rspack/core"),
92
+ mode: "callback"
93
+ });
94
+ }
53
95
  this.emitter.emit(ECompilerEvent.Create, this.compilerInstance);
54
96
  return this.compilerInstance;
55
97
  }
@@ -58,11 +100,39 @@ class TestCompilerManager {
58
100
  throw new Error("Compiler should be created before build");
59
101
  return new Promise((resolve, reject) => {
60
102
  try {
103
+ const context = this.context;
104
+ if (__DEBUG__) {
105
+ context.setValue(debug_1.DEBUG_SCOPES.BuildMethod, {
106
+ method: "run"
107
+ });
108
+ }
61
109
  this.compilerInstance.run((error, newStats) => {
62
110
  this.emitter.emit(ECompilerEvent.Build, error, newStats);
63
- if (error)
111
+ if (error) {
112
+ if (__DEBUG__) {
113
+ context.setValue(debug_1.DEBUG_SCOPES.BuildError, {
114
+ type: "fatal",
115
+ errors: [error]
116
+ });
117
+ }
64
118
  return reject(error);
119
+ }
65
120
  this.compilerStats = newStats;
121
+ if (__DEBUG__) {
122
+ if (newStats?.hasErrors()) {
123
+ context.setValue(debug_1.DEBUG_SCOPES.BuildError, {
124
+ type: "stats",
125
+ errors: newStats.toJson({
126
+ errors: true
127
+ }).errors || []
128
+ });
129
+ }
130
+ if (newStats?.hasWarnings()) {
131
+ context.setValue(debug_1.DEBUG_SCOPES.BuildWarning, newStats.toJson({
132
+ warnings: true
133
+ }).warnings || []);
134
+ }
135
+ }
66
136
  resolve(newStats);
67
137
  });
68
138
  }
@@ -74,7 +144,8 @@ class TestCompilerManager {
74
144
  watch(timeout = 1000) {
75
145
  if (!this.compilerInstance)
76
146
  throw new Error("Compiler should be created before watch");
77
- this.compilerInstance.watch({
147
+ const context = this.context;
148
+ const watchOptions = {
78
149
  // IMPORTANT:
79
150
  // This is a workaround for the issue that watchpack cannot detect the file change in time
80
151
  // so we set the poll to 300ms to make it more sensitive to the file change
@@ -83,11 +154,40 @@ class TestCompilerManager {
83
154
  // want to watch all files, which aligns with webpack's default behavior
84
155
  ignored: [],
85
156
  aggregateTimeout: timeout
86
- }, (error, newStats) => {
157
+ };
158
+ if (__DEBUG__) {
159
+ context.setValue(debug_1.DEBUG_SCOPES.BuildMethod, {
160
+ method: "watch",
161
+ options: watchOptions
162
+ });
163
+ }
164
+ this.compilerInstance.watch(watchOptions, (error, newStats) => {
87
165
  this.emitter.emit(ECompilerEvent.Build, error, newStats);
88
- if (error)
89
- return error;
166
+ if (__DEBUG__) {
167
+ if (error) {
168
+ context.setValue(debug_1.DEBUG_SCOPES.BuildError, {
169
+ type: "fatal",
170
+ errors: [error]
171
+ });
172
+ return error;
173
+ }
174
+ }
90
175
  if (newStats) {
176
+ if (__DEBUG__) {
177
+ if (newStats.hasErrors()) {
178
+ context.setValue(debug_1.DEBUG_SCOPES.BuildError, {
179
+ type: "stats",
180
+ errors: newStats.toJson({
181
+ errors: true
182
+ }).errors || []
183
+ });
184
+ }
185
+ if (newStats.hasWarnings()) {
186
+ context.setValue(debug_1.DEBUG_SCOPES.BuildWarning, newStats.toJson({
187
+ warnings: true
188
+ }).warnings || []);
189
+ }
190
+ }
91
191
  this.compilerStats = newStats;
92
192
  }
93
193
  return newStats;
@@ -2,6 +2,7 @@ export * from "./directory";
2
2
  export * from "./is";
3
3
  export * from "./parse-modules";
4
4
  export * from "./read-config-file";
5
+ export * from "./stringify-config";
5
6
  export * from "./update-snapshot";
6
7
  export * from "./util/checkStats";
7
8
  export * from "./win";
@@ -18,6 +18,7 @@ __exportStar(require("./directory"), exports);
18
18
  __exportStar(require("./is"), exports);
19
19
  __exportStar(require("./parse-modules"), exports);
20
20
  __exportStar(require("./read-config-file"), exports);
21
+ __exportStar(require("./stringify-config"), exports);
21
22
  __exportStar(require("./update-snapshot"), exports);
22
23
  __exportStar(require("./util/checkStats"), exports);
23
24
  __exportStar(require("./win"), exports);
@@ -1,6 +1,6 @@
1
1
  // @ts-nocheck
2
2
  "use strict";
3
- const fs = require("graceful-fs");
3
+ const fs = require("fs-extra");
4
4
  const path = require("node:path");
5
5
  const check = (expected, actual) => {
6
6
  if (expected instanceof RegExp) {
@@ -1,2 +1,3 @@
1
- import type { ECompilerType, ITestContext, TCompilerOptions } from "../type";
2
- export declare function readConfigFile<T extends ECompilerType>(files: string[], context: ITestContext, prevOption?: TCompilerOptions<T>, functionApply?: (config: (TCompilerOptions<T> | ((...args: unknown[]) => TCompilerOptions<T>))[]) => TCompilerOptions<T>[]): TCompilerOptions<T>[];
1
+ import type { RspackOptions } from "@rspack/core";
2
+ import type { ITestContext } from "../type";
3
+ export declare function readConfigFile(files: string[], context: ITestContext, prevOption?: RspackOptions, functionApply?: (config: (RspackOptions | ((...args: unknown[]) => RspackOptions))[]) => RspackOptions[]): RspackOptions[];
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.readConfigFile = readConfigFile;
7
7
  const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const debug_1 = require("../test/debug");
8
9
  function readConfigFile(files, context, prevOption, functionApply) {
9
10
  const existsFile = files.find(i => fs_extra_1.default.existsSync(i));
10
11
  let fileConfig = existsFile ? require(existsFile) : {};
@@ -12,5 +13,11 @@ function readConfigFile(files, context, prevOption, functionApply) {
12
13
  fileConfig = fileConfig({ config: prevOption }, { testPath: context.getDist(), tempPath: context.getTemp() });
13
14
  }
14
15
  const configArr = Array.isArray(fileConfig) ? fileConfig : [fileConfig];
16
+ if (existsFile) {
17
+ context.setValue(debug_1.DEBUG_SCOPES.CompilerOptionsReadConfigFile, {
18
+ file: existsFile,
19
+ config: fileConfig
20
+ });
21
+ }
15
22
  return functionApply ? functionApply(configArr) : configArr;
16
23
  }
@@ -16,6 +16,7 @@ if (process.env.RSTEST) {
16
16
  global.__ROOT_PATH__ ??= process.env.__ROOT_PATH__;
17
17
  global.__RSPACK_PATH__ ??= process.env.__RSPACK_PATH__;
18
18
  global.__RSPACK_TEST_TOOLS_PATH__ ??= process.env.__RSPACK_TEST_TOOLS_PATH__;
19
+ global.__DEBUG__ ??= process.env.DEBUG === "test";
19
20
  }
20
21
  else {
21
22
  // Compatible with wasm tests (lazyTestEnv)
@@ -0,0 +1,2 @@
1
+ import type { RspackOptions } from "@rspack/core";
2
+ export default function stringifyConfig(config: RspackOptions, verbose?: boolean): string | undefined;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = stringifyConfig;
4
+ const javascript_stringify_1 = require("javascript-stringify");
5
+ function stringifyConfig(config, verbose = false) {
6
+ return (0, javascript_stringify_1.stringify)(config, (value, indent, stringify) => {
7
+ // improve plugin output
8
+ if (value?.__pluginName) {
9
+ const prefix = `/* config.${value.__pluginType}('${value.__pluginName}') */\n`;
10
+ const constructorExpression = value.__pluginPath
11
+ ? // The path is stringified to ensure special characters are escaped
12
+ // (such as the backslashes in Windows-style paths).
13
+ `(require(${stringify(value.__pluginPath)}))`
14
+ : value.__pluginConstructorName;
15
+ if (constructorExpression) {
16
+ // get correct indentation for args by stringifying the args array and
17
+ // discarding the square brackets.
18
+ const args = stringify(value.__pluginArgs)?.slice(1, -1);
19
+ return `${prefix}new ${constructorExpression}(${args})`;
20
+ }
21
+ return (prefix +
22
+ stringify(value.__pluginArgs?.length ? { args: value.__pluginArgs } : {}));
23
+ }
24
+ // improve rule/use output
25
+ if (value?.__ruleNames) {
26
+ const ruleTypes = value.__ruleTypes;
27
+ const prefix = `/* config.module${value.__ruleNames
28
+ .map((r, index) => `.${ruleTypes ? ruleTypes[index] : "rule"}('${r}')`)
29
+ .join("")}${value.__useName ? `.use('${value.__useName}')` : ``} */\n`;
30
+ return prefix + stringify(value);
31
+ }
32
+ if (value?.__expression) {
33
+ return value.__expression;
34
+ }
35
+ // shorten long functions
36
+ if (typeof value === "function") {
37
+ if (!verbose && value.toString().length > 100) {
38
+ return `function () { /* omitted long function */ }`;
39
+ }
40
+ }
41
+ return stringify(value);
42
+ }, 2);
43
+ }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  export * from "./case";
2
- export * from "./compare";
3
2
  export * from "./helper";
4
3
  export * from "./plugin";
5
4
  export * from "./runner";
package/dist/index.js CHANGED
@@ -15,7 +15,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./case"), exports);
18
- __exportStar(require("./compare"), exports);
19
18
  __exportStar(require("./helper"), exports);
20
19
  __exportStar(require("./plugin"), exports);
21
20
  __exportStar(require("./runner"), exports);
@@ -1,4 +1 @@
1
1
  export * from "./lazy-compilation-test-plugin";
2
- export * from "./rspack-diff-config-plugin";
3
- export * from "./webpack-diff-config-plugin";
4
- export * from "./webpack-module-placeholder-plugin";
@@ -15,6 +15,3 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./lazy-compilation-test-plugin"), exports);
18
- __exportStar(require("./rspack-diff-config-plugin"), exports);
19
- __exportStar(require("./webpack-diff-config-plugin"), exports);
20
- __exportStar(require("./webpack-module-placeholder-plugin"), exports);
@@ -1,25 +1,29 @@
1
- import { type ECompilerType, type IGlobalContext, type IModuleScope, type ITestEnv, type ITestRunner, type TCompilerOptions, type TCompilerStatsCompilation, type TModuleObject, type TRunnerFile, type TRunnerRequirer, type TTestConfig } from "../../type";
1
+ import type { RspackOptions, StatsCompilation } from "@rspack/core";
2
+ import { type IGlobalContext, type IModuleScope, type ITestEnv, type ITestRunner, type TModuleObject, type TRunnerFile, type TRunnerRequirer, type TTestConfig } from "../../type";
2
3
  declare global {
3
4
  var printLogger: boolean;
4
5
  }
5
- export interface INodeRunnerOptions<T extends ECompilerType> {
6
+ export interface INodeRunnerOptions {
6
7
  env: ITestEnv;
7
- stats?: () => TCompilerStatsCompilation<T>;
8
+ stats?: () => StatsCompilation;
8
9
  name: string;
9
10
  runInNewContext?: boolean;
10
- testConfig: TTestConfig<T>;
11
+ testConfig: TTestConfig;
11
12
  source: string;
12
13
  dist: string;
13
- compilerOptions: TCompilerOptions<T>;
14
+ compilerOptions: RspackOptions;
14
15
  cachable?: boolean;
16
+ logs?: string[];
17
+ errors?: Error[];
15
18
  }
16
- export declare class NodeRunner<T extends ECompilerType = ECompilerType.Rspack> implements ITestRunner {
17
- protected _options: INodeRunnerOptions<T>;
19
+ export declare class NodeRunner implements ITestRunner {
20
+ protected _options: INodeRunnerOptions;
18
21
  protected requireCache: any;
19
22
  protected globalContext: IGlobalContext | null;
20
23
  protected baseModuleScope: IModuleScope | null;
21
24
  protected requirers: Map<string, TRunnerRequirer>;
22
- constructor(_options: INodeRunnerOptions<T>);
25
+ constructor(_options: INodeRunnerOptions);
26
+ protected log(message: string): void;
23
27
  run(file: string): Promise<unknown>;
24
28
  getRequire(): TRunnerRequirer;
25
29
  getGlobal(name: string): unknown;
@@ -35,3 +39,4 @@ export declare class NodeRunner<T extends ECompilerType = ECompilerType.Rspack>
35
39
  protected createCjsRequirer(): TRunnerRequirer;
36
40
  protected createEsmRequirer(): TRunnerRequirer;
37
41
  }
42
+ export declare const createLocatedError: (collectedErrors: Error[], offset: number) => (e: Error, file: TRunnerFile) => Error;
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.NodeRunner = void 0;
39
+ exports.createLocatedError = exports.NodeRunner = void 0;
40
40
  const node_fs_1 = __importDefault(require("node:fs"));
41
41
  const node_path_1 = __importDefault(require("node:path"));
42
42
  const node_url_1 = require("node:url");
@@ -45,6 +45,7 @@ const asModule_1 = __importDefault(require("../../helper/legacy/asModule"));
45
45
  const createFakeWorker_1 = __importDefault(require("../../helper/legacy/createFakeWorker"));
46
46
  const urlToRelativePath_1 = __importDefault(require("../../helper/legacy/urlToRelativePath"));
47
47
  const type_1 = require("../../type");
48
+ const EVAL_LOCATION_REGEX = /<anonymous>:(\d+)/;
48
49
  const isRelativePath = (p) => /^\.\.?\//.test(p);
49
50
  const getSubPath = (p) => {
50
51
  const lastSlash = p.lastIndexOf("/");
@@ -72,6 +73,9 @@ class NodeRunner {
72
73
  this.baseModuleScope = null;
73
74
  this.requirers = new Map();
74
75
  }
76
+ log(message) {
77
+ this._options.logs?.push(`[NodeRunner] ${message}`);
78
+ }
75
79
  run(file) {
76
80
  if (!this.globalContext) {
77
81
  this.globalContext = this.createGlobalContext();
@@ -81,7 +85,9 @@ class NodeRunner {
81
85
  this._options.testConfig.moduleScope(this.baseModuleScope, this._options.stats, this._options.compilerOptions);
82
86
  }
83
87
  this.createRunner();
84
- const res = this.getRequire()(this._options.dist, file.startsWith("./") || file.startsWith("https://test.cases/")
88
+ const res = this.getRequire()(node_path_1.default.isAbsolute(file) ? node_path_1.default.dirname(file) : this._options.dist, file.startsWith("./") ||
89
+ file.startsWith("https://test.cases/") ||
90
+ node_path_1.default.isAbsolute(file)
85
91
  ? file
86
92
  : `./${file}`);
87
93
  if (typeof res === "object" && "then" in res) {
@@ -91,7 +97,15 @@ class NodeRunner {
91
97
  }
92
98
  getRequire() {
93
99
  const entryRequire = this.requirers.get("entry");
94
- return (currentDirectory, modulePath, context = {}) => {
100
+ const runner = this;
101
+ return function (currentDirectory, modulePath, context = {}) {
102
+ const from = this?.from;
103
+ if (from) {
104
+ runner.log(`require: ${modulePath} from ${from}`);
105
+ }
106
+ else {
107
+ runner.log(`require: ${modulePath}`);
108
+ }
95
109
  const p = Array.isArray(modulePath)
96
110
  ? modulePath
97
111
  : modulePath.split("?")[0];
@@ -175,7 +189,10 @@ class NodeRunner {
175
189
  return baseModuleScope;
176
190
  }
177
191
  createModuleScope(requireFn, m, file) {
178
- const requirer = requireFn.bind(null, node_path_1.default.dirname(file.path));
192
+ const requirer = requireFn.bind({
193
+ from: file.path,
194
+ module: m
195
+ }, node_path_1.default.dirname(file.path));
179
196
  requirer.webpackTestSuiteRequire = true;
180
197
  return {
181
198
  ...this.baseModuleScope,
@@ -244,6 +261,7 @@ class NodeRunner {
244
261
  this.requirers.set("json", this.createJsonRequirer());
245
262
  this.requirers.set("entry", (currentDirectory, modulePath, context) => {
246
263
  const file = this.getFile(modulePath, currentDirectory);
264
+ this.log(`entry: ${modulePath} -> ${file?.path}`);
247
265
  if (!file) {
248
266
  return this.requirers.get("miss")(currentDirectory, modulePath);
249
267
  }
@@ -268,11 +286,14 @@ class NodeRunner {
268
286
  }
269
287
  createMissRequirer() {
270
288
  return (currentDirectory, modulePath, context = {}) => {
289
+ this.log(`missing: ${modulePath}`);
271
290
  const modulePathStr = modulePath;
272
291
  const modules = this._options.testConfig.modules;
273
292
  if (modules && modulePathStr in modules) {
293
+ this.log(`mock module: ${modulePathStr}`);
274
294
  return modules[modulePathStr];
275
295
  }
296
+ this.log(`native require: ${modulePathStr}`);
276
297
  return require(modulePathStr.startsWith("node:")
277
298
  ? modulePathStr.slice(5)
278
299
  : modulePathStr);
@@ -284,6 +305,7 @@ class NodeRunner {
284
305
  throw new Error("Array module path is not supported in hot cases");
285
306
  }
286
307
  const file = context.file || this.getFile(modulePath, currentDirectory);
308
+ this.log(`json: ${modulePath} -> ${file?.path}`);
287
309
  if (!file) {
288
310
  return this.requirers.get("miss")(currentDirectory, modulePath);
289
311
  }
@@ -296,10 +318,12 @@ class NodeRunner {
296
318
  return require("@rspack/test-tools");
297
319
  }
298
320
  const file = context.file || this.getFile(modulePath, currentDirectory);
321
+ this.log(`cjs: ${modulePath} -> ${file?.path}`);
299
322
  if (!file) {
300
323
  return this.requirers.get("miss")(currentDirectory, modulePath);
301
324
  }
302
325
  if (file.path in this.requireCache) {
326
+ this.log(`cjs cache hit: ${file.path}`);
303
327
  return this.requireCache[file.path].exports;
304
328
  }
305
329
  const m = {
@@ -323,19 +347,45 @@ class NodeRunner {
323
347
  currentModuleScope.__STATS_I__ = statsIndex;
324
348
  }
325
349
  }
350
+ const createNodeLocatedError = (0, exports.createLocatedError)(this._options.errors || [], 2);
351
+ const originIt = currentModuleScope.it;
352
+ currentModuleScope.it = (description, fn) => {
353
+ originIt(description, async () => {
354
+ try {
355
+ await fn();
356
+ }
357
+ catch (err) {
358
+ throw createNodeLocatedError(err, file);
359
+ }
360
+ });
361
+ };
362
+ currentModuleScope.__CREATE_LOCATED_ERROR__ = createNodeLocatedError;
363
+ currentModuleScope.__FILE__ = file;
326
364
  const args = Object.keys(currentModuleScope);
327
365
  const argValues = args.map(arg => currentModuleScope[arg]);
328
366
  const code = `(function(${args.join(", ")}) {
329
- ${file.content}
367
+ try {
368
+ ${file.content}
369
+ } catch(err) {
370
+ throw __CREATE_LOCATED_ERROR__(err, __FILE__);
371
+ }
330
372
  })`;
331
373
  this.preExecute(code, file);
374
+ this.log(`run mode: ${this._options.runInNewContext ? "new context" : "this context"}`);
332
375
  const fn = this._options.runInNewContext
333
- ? node_vm_1.default.runInNewContext(code, this.globalContext, file.path)
334
- : node_vm_1.default.runInThisContext(code, file.path);
376
+ ? node_vm_1.default.runInNewContext(code, this.globalContext, {
377
+ filename: file.path,
378
+ lineOffset: 1
379
+ })
380
+ : node_vm_1.default.runInThisContext(code, {
381
+ filename: file.path,
382
+ lineOffset: 1
383
+ });
335
384
  fn.call(this._options.testConfig.nonEsmThis
336
385
  ? this._options.testConfig.nonEsmThis(modulePath)
337
386
  : m.exports, ...argValues);
338
387
  this.postExecute(m, file);
388
+ this.log(`end cjs: ${modulePath}`);
339
389
  return m.exports;
340
390
  };
341
391
  }
@@ -351,6 +401,7 @@ class NodeRunner {
351
401
  }
352
402
  const _require = this.getRequire();
353
403
  const file = context.file || this.getFile(modulePath, currentDirectory);
404
+ this.log(`esm: ${modulePath} -> ${file?.path}`);
354
405
  if (!file) {
355
406
  return this.requirers.get("miss")(currentDirectory, modulePath);
356
407
  }
@@ -376,6 +427,7 @@ class NodeRunner {
376
427
  meta.filename = file.path;
377
428
  },
378
429
  importModuleDynamically: async (specifier, module) => {
430
+ this.log(`import: ${specifier} from ${file?.path}`);
379
431
  const result = await _require(node_path_1.default.dirname(file.path), specifier, {
380
432
  esmMode: type_1.EEsmMode.Evaluated
381
433
  });
@@ -401,9 +453,36 @@ class NodeRunner {
401
453
  return esm;
402
454
  }
403
455
  const ns = esm.namespace;
456
+ this.log(`end esm: ${modulePath}`);
404
457
  return ns.default && ns.default instanceof Promise ? ns.default : ns;
405
458
  })();
406
459
  };
407
460
  }
408
461
  }
409
462
  exports.NodeRunner = NodeRunner;
463
+ const createLocatedError = (collectedErrors, offset) => {
464
+ return (e, file) => {
465
+ const match = (e.stack || e.message).match(EVAL_LOCATION_REGEX);
466
+ if (match) {
467
+ const [, line] = match;
468
+ const realLine = Number(line) - offset;
469
+ const codeLines = file.content.split("\n");
470
+ const lineContents = [
471
+ ...codeLines
472
+ .slice(Math.max(0, realLine - 3), Math.max(0, realLine - 1))
473
+ .map(line => `│ ${line}`),
474
+ `│> ${codeLines[realLine - 1]}`,
475
+ ...codeLines.slice(realLine, realLine + 2).map(line => `│ ${line}`)
476
+ ];
477
+ const message = `Error in JSDOM when running file '${file.path}' at line ${realLine}: ${e.message}\n${lineContents.join("\n")}`;
478
+ const finalError = new Error(message);
479
+ finalError.stack = undefined;
480
+ collectedErrors.push(finalError);
481
+ return finalError;
482
+ }
483
+ else {
484
+ return e;
485
+ }
486
+ };
487
+ };
488
+ exports.createLocatedError = createLocatedError;
@@ -1,14 +1,15 @@
1
- import type { ECompilerType, TRunnerFile, TRunnerRequirer } from "../../type";
1
+ import type { TRunnerFile, TRunnerRequirer } from "../../type";
2
2
  import { type INodeRunnerOptions, NodeRunner } from "../node";
3
- export interface IWebRunnerOptions<T extends ECompilerType = ECompilerType.Rspack> extends INodeRunnerOptions<T> {
3
+ export interface IWebRunnerOptions extends INodeRunnerOptions {
4
4
  location: string;
5
5
  }
6
- export declare class WebRunner<T extends ECompilerType = ECompilerType.Rspack> extends NodeRunner<T> {
7
- protected _webOptions: IWebRunnerOptions<T>;
6
+ export declare class WebRunner extends NodeRunner {
7
+ protected _webOptions: IWebRunnerOptions;
8
8
  private dom;
9
- constructor(_webOptions: IWebRunnerOptions<T>);
9
+ constructor(_webOptions: IWebRunnerOptions);
10
10
  run(file: string): Promise<unknown>;
11
11
  getGlobal(name: string): unknown;
12
+ protected log(message: string): void;
12
13
  protected createResourceLoader(): {
13
14
  fetch(url: string, _: {
14
15
  element: HTMLScriptElement;