@rspack/test-tools 1.2.5 → 1.2.7-alpha.0

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 (39) hide show
  1. package/dist/case/diff.js +27 -49
  2. package/dist/case/new-incremental.js +3 -2
  3. package/dist/case/stats-output.js +1 -0
  4. package/dist/case/watch.js +3 -2
  5. package/dist/compare/compare.d.ts +5 -1
  6. package/dist/compare/compare.js +46 -18
  7. package/dist/compare/format-code.js +4 -1
  8. package/dist/compare/replace-runtime-module-name.d.ts +1 -1
  9. package/dist/compare/replace-runtime-module-name.js +52 -47
  10. package/dist/helper/loaders/hot-update.js +6 -3
  11. package/dist/helper/parse-modules.d.ts +2 -2
  12. package/dist/helper/parse-modules.js +5 -5
  13. package/dist/processor/basic.js +22 -12
  14. package/dist/processor/diff.js +31 -17
  15. package/dist/processor/hash.js +2 -3
  16. package/dist/processor/snapshot.js +14 -3
  17. package/dist/processor/stats.d.ts +2 -0
  18. package/dist/processor/stats.js +5 -2
  19. package/dist/processor/watch.d.ts +4 -2
  20. package/dist/processor/watch.js +63 -19
  21. package/dist/runner/basic.d.ts +2 -1
  22. package/dist/runner/basic.js +18 -5
  23. package/dist/runner/cache.js +2 -1
  24. package/dist/runner/hot-step.js +2 -1
  25. package/dist/runner/hot.js +2 -1
  26. package/dist/runner/multiple.d.ts +1 -1
  27. package/dist/runner/multiple.js +1 -1
  28. package/dist/runner/normal.d.ts +1 -1
  29. package/dist/runner/normal.js +1 -0
  30. package/dist/runner/runner/basic.d.ts +2 -1
  31. package/dist/runner/runner/basic.js +15 -6
  32. package/dist/runner/runner/cjs.js +4 -4
  33. package/dist/runner/runner/watch.d.ts +1 -1
  34. package/dist/runner/runner/watch.js +2 -3
  35. package/dist/runner/runner/web/jsdom.js +0 -1
  36. package/dist/runner/watch.d.ts +2 -1
  37. package/dist/runner/watch.js +23 -0
  38. package/dist/type.d.ts +8 -5
  39. package/package.json +27 -27
package/dist/case/diff.js CHANGED
@@ -32,49 +32,36 @@ function createDiffCase(name, src, dist) {
32
32
  dist,
33
33
  steps: [processor]
34
34
  });
35
- beforeAll(async () => {
36
- (0, rimraf_1.rimrafSync)(dist);
37
- await tester.prepare();
38
- });
39
- do {
40
- const prefix = node_path_1.default.basename(name);
41
- describe(`${prefix}:build`, () => {
42
- beforeAll(async () => {
43
- await tester.compile();
44
- });
45
- checkBundleFiles("webpack", node_path_1.default.join(dist, "webpack"), caseConfig.files);
46
- checkBundleFiles("rspack", node_path_1.default.join(dist, "rspack"), caseConfig.files);
35
+ (0, rimraf_1.rimrafSync)(dist);
36
+ const buildTask = tester.compile();
37
+ const prefix = node_path_1.default.basename(name);
38
+ describe(`${prefix}:check`, () => {
39
+ beforeAll(async () => {
40
+ await buildTask;
41
+ compareMap.clear();
42
+ await tester.check(env);
47
43
  });
48
- describe(`${prefix}:check`, () => {
49
- beforeAll(async () => {
50
- compareMap.clear();
51
- await tester.check(env);
52
- });
53
- for (const file of caseConfig.files) {
54
- describe(`Comparing "${file}"`, () => {
55
- let moduleResults = [];
56
- let runtimeResults = [];
57
- beforeAll(() => {
58
- const fileResult = compareMap.get(file);
59
- if (!fileResult) {
60
- throw new Error(`File ${file} has no results`);
61
- }
62
- moduleResults = fileResult.modules;
63
- runtimeResults = fileResult.runtimeModules;
64
- });
65
- if (caseConfig.modules) {
66
- checkCompareResults("modules", () => moduleResults);
67
- }
68
- if (caseConfig.runtimeModules) {
69
- checkCompareResults("runtime modules", () => runtimeResults);
44
+ for (const file of caseConfig.files) {
45
+ describe(`Comparing "${file}"`, () => {
46
+ let moduleResults = [];
47
+ let runtimeResults = [];
48
+ beforeAll(() => {
49
+ const fileResult = compareMap.get(file);
50
+ if (!fileResult) {
51
+ throw new Error(`File ${file} has no results`);
70
52
  }
53
+ moduleResults = fileResult.modules;
54
+ runtimeResults = fileResult.runtimeModules;
71
55
  });
72
- }
73
- const env = (0, createLazyTestEnv_1.default)(1000);
74
- });
75
- } while (tester.next());
76
- afterAll(async () => {
77
- await tester.resume();
56
+ if (caseConfig.modules) {
57
+ checkCompareResults("modules", () => moduleResults);
58
+ }
59
+ if (caseConfig.runtimeModules) {
60
+ checkCompareResults("runtime modules", () => runtimeResults);
61
+ }
62
+ });
63
+ }
64
+ const env = (0, createLazyTestEnv_1.default)(1000);
78
65
  });
79
66
  }
80
67
  function createDiffProcessor(config) {
@@ -113,15 +100,6 @@ function createDiffProcessor(config) {
113
100
  });
114
101
  return [processor, fileCompareMap];
115
102
  }
116
- function checkBundleFiles(name, dist, files) {
117
- describe(`Checking ${name} dist files`, () => {
118
- for (const file of files) {
119
- it(`${name}: ${file} should be generated`, () => {
120
- expect(fs_extra_1.default.existsSync(node_path_1.default.join(dist, file))).toBeTruthy();
121
- });
122
- }
123
- });
124
- }
125
103
  function checkCompareResults(name, getResults) {
126
104
  describe(`Comparing ${name}`, () => {
127
105
  it("should not miss any module", () => {
@@ -48,6 +48,7 @@ const watchCreator = new creator_1.BasicCaseCreator({
48
48
  },
49
49
  describe: false,
50
50
  steps: ({ name, src, temp }) => {
51
+ const watchState = {};
51
52
  const runs = node_fs_1.default
52
53
  .readdirSync(src)
53
54
  .sort()
@@ -66,7 +67,7 @@ const watchCreator = new creator_1.BasicCaseCreator({
66
67
  experiments: {
67
68
  incremental: true
68
69
  }
69
- })
70
+ }, watchState)
70
71
  : new watch_1.WatchStepProcessor({
71
72
  name,
72
73
  stepName: run.name,
@@ -74,7 +75,7 @@ const watchCreator = new creator_1.BasicCaseCreator({
74
75
  runable: true,
75
76
  compilerType: type_1.ECompilerType.Rspack,
76
77
  configFiles: ["rspack.config.js", "webpack.config.js"]
77
- }));
78
+ }, watchState));
78
79
  }
79
80
  });
80
81
  function createWatchNewIncrementalCase(name, src, dist, temp) {
@@ -10,6 +10,7 @@ const creator = new creator_1.BasicCaseCreator({
10
10
  steps: ({ name }) => [
11
11
  new stats_1.StatsProcessor({
12
12
  name,
13
+ writeStatsOuptut: false,
13
14
  compilerType: type_1.ECompilerType.Rspack,
14
15
  configFiles: ["rspack.config.js", "webpack.config.js"]
15
16
  })
@@ -20,6 +20,7 @@ const creator = new creator_1.BasicCaseCreator({
20
20
  },
21
21
  describe: false,
22
22
  steps: ({ name, src, temp }) => {
23
+ const watchState = {};
23
24
  const runs = node_fs_1.default
24
25
  .readdirSync(src)
25
26
  .sort()
@@ -35,7 +36,7 @@ const creator = new creator_1.BasicCaseCreator({
35
36
  runable: true,
36
37
  compilerType: type_1.ECompilerType.Rspack,
37
38
  configFiles: ["rspack.config.js", "webpack.config.js"]
38
- })
39
+ }, watchState)
39
40
  : new watch_1.WatchStepProcessor({
40
41
  name,
41
42
  stepName: run.name,
@@ -43,7 +44,7 @@ const creator = new creator_1.BasicCaseCreator({
43
44
  runable: true,
44
45
  compilerType: type_1.ECompilerType.Rspack,
45
46
  configFiles: ["rspack.config.js", "webpack.config.js"]
46
- }));
47
+ }, watchState));
47
48
  }
48
49
  });
49
50
  function createWatchCase(name, src, dist, temp) {
@@ -1,5 +1,8 @@
1
1
  import { type TCompareModules, type TCompareResult, type TFileCompareResult, type TModuleCompareResult } from "../type";
2
2
  import { type IFormatCodeOptions } from "./format-code";
3
+ declare global {
4
+ var updateSnapshot: boolean;
5
+ }
3
6
  export interface ICompareOptions {
4
7
  modules?: TCompareModules;
5
8
  runtimeModules?: TCompareModules;
@@ -7,7 +10,8 @@ export interface ICompareOptions {
7
10
  renameModule?: (name: string) => string;
8
11
  bootstrap?: boolean;
9
12
  detail?: boolean;
13
+ snapshot?: string;
10
14
  }
11
15
  export declare function compareFile(sourceFile: string, distFile: string, compareOptions: ICompareOptions): TFileCompareResult;
12
- export declare function compareModules(modules: string[], sourceModules: Map<string, string>, distModules: Map<string, string>, compareOptions: ICompareOptions): TModuleCompareResult[];
16
+ export declare function compareModules(modules: string[], sourceModules: Record<string, string>, distModules: Record<string, string>, compareOptions: ICompareOptions): TModuleCompareResult[];
13
17
  export declare function compareContent(sourceContent: string | false, distContent: string | false, compareOptions: ICompareOptions): TCompareResult;
@@ -8,10 +8,12 @@ exports.compareModules = compareModules;
8
8
  exports.compareContent = compareContent;
9
9
  const fs_extra_1 = __importDefault(require("fs-extra"));
10
10
  const jest_diff_1 = require("jest-diff");
11
+ const node_path_1 = __importDefault(require("node:path"));
11
12
  const helper_1 = require("../helper");
12
13
  const type_1 = require("../type");
13
14
  const format_code_1 = require("./format-code");
14
15
  const replace_runtime_module_name_1 = require("./replace-runtime-module-name");
16
+ const WORKSPACE = node_path_1.default.resolve(__dirname, "../../../..");
15
17
  function compareFile(sourceFile, distFile, compareOptions) {
16
18
  const result = {
17
19
  type: type_1.ECompareResultType.Same,
@@ -22,7 +24,9 @@ function compareFile(sourceFile, distFile, compareOptions) {
22
24
  modules: {}
23
25
  };
24
26
  const sourceExists = fs_extra_1.default.existsSync(sourceFile);
25
- const distExists = fs_extra_1.default.existsSync(distFile);
27
+ const distExists = compareOptions.snapshot
28
+ ? fs_extra_1.default.existsSync(compareOptions.snapshot)
29
+ : fs_extra_1.default.existsSync(distFile);
26
30
  if (!sourceExists && !distExists) {
27
31
  result.type = type_1.ECompareResultType.Missing;
28
32
  return result;
@@ -35,27 +39,53 @@ function compareFile(sourceFile, distFile, compareOptions) {
35
39
  result.type = type_1.ECompareResultType.OnlySource;
36
40
  return result;
37
41
  }
38
- const sourceContent = (0, replace_runtime_module_name_1.replaceRuntimeModuleName)(fs_extra_1.default.readFileSync(sourceFile, "utf-8"));
39
- const distContent = (0, replace_runtime_module_name_1.replaceRuntimeModuleName)(fs_extra_1.default.readFileSync(distFile, "utf-8"));
40
- // const compareContentResult = compareContent(sourceContent, distContent);
41
- // result.detail = compareContentResult.detail;
42
- // result.lines = compareContentResult.lines;
43
- result.type = type_1.ECompareResultType.Different;
42
+ function formatModules(modules) {
43
+ const res = {};
44
+ for (const [name, content] of Object.entries(modules)) {
45
+ const renamed = name.replaceAll(node_path_1.default.win32.sep, node_path_1.default.posix.sep);
46
+ if (!renamed.includes("node_modules/css-loader/dist")) {
47
+ res[renamed] = (0, format_code_1.formatCode)(renamed, content, compareOptions.format);
48
+ }
49
+ }
50
+ return res;
51
+ }
52
+ const sourceContent = (0, replace_runtime_module_name_1.replaceRuntimeModuleName)(fs_extra_1.default.readFileSync(sourceFile, "utf-8").replaceAll(WORKSPACE, "__WORKSPACE__"));
44
53
  const sourceModules = (0, helper_1.parseModules)(sourceContent, {
45
54
  bootstrap: compareOptions.bootstrap,
46
55
  renameModule: compareOptions.renameModule
47
56
  });
48
- const distModules = (0, helper_1.parseModules)(distContent, {
49
- bootstrap: compareOptions.bootstrap,
50
- renameModule: compareOptions.renameModule
51
- });
57
+ sourceModules.modules = formatModules(sourceModules.modules);
58
+ sourceModules.runtimeModules = formatModules(sourceModules.runtimeModules);
59
+ let distModules = {
60
+ modules: {},
61
+ runtimeModules: {}
62
+ };
63
+ if (!global.updateSnapshot &&
64
+ compareOptions.snapshot &&
65
+ fs_extra_1.default.existsSync(compareOptions.snapshot)) {
66
+ distModules = JSON.parse(fs_extra_1.default.readFileSync(compareOptions.snapshot, "utf-8"));
67
+ }
68
+ else {
69
+ const distContent = (0, replace_runtime_module_name_1.replaceRuntimeModuleName)(fs_extra_1.default.readFileSync(distFile, "utf-8").replaceAll(WORKSPACE, "__WORKSPACE__"));
70
+ distModules = (0, helper_1.parseModules)(distContent, {
71
+ bootstrap: compareOptions.bootstrap,
72
+ renameModule: compareOptions.renameModule
73
+ });
74
+ distModules.modules = formatModules(distModules.modules);
75
+ distModules.runtimeModules = formatModules(distModules.runtimeModules);
76
+ if (compareOptions.snapshot) {
77
+ fs_extra_1.default.ensureDirSync(node_path_1.default.dirname(compareOptions.snapshot));
78
+ fs_extra_1.default.writeFileSync(compareOptions.snapshot, JSON.stringify(distModules, null, 2));
79
+ }
80
+ }
81
+ result.type = type_1.ECompareResultType.Different;
52
82
  for (const type of ["modules", "runtimeModules"]) {
53
83
  const t = type;
54
84
  let moduleList = [];
55
85
  if (compareOptions[t] === true) {
56
86
  moduleList = [
57
- ...sourceModules[t].keys(),
58
- ...distModules[t].keys()
87
+ ...Object.keys(sourceModules[t]),
88
+ ...Object.keys(distModules[t])
59
89
  ].filter((i, idx, arr) => arr.indexOf(i) === idx);
60
90
  }
61
91
  else if (Array.isArray(compareOptions[t])) {
@@ -71,11 +101,9 @@ function compareFile(sourceFile, distFile, compareOptions) {
71
101
  function compareModules(modules, sourceModules, distModules, compareOptions) {
72
102
  const compareResults = [];
73
103
  for (const name of modules) {
74
- const renamed = (0, replace_runtime_module_name_1.replaceRuntimeModuleName)(name);
75
- const sourceContent = sourceModules.has(renamed) &&
76
- (0, format_code_1.formatCode)(name, sourceModules.get(renamed), compareOptions.format);
77
- const distContent = distModules.has(renamed) &&
78
- (0, format_code_1.formatCode)(name, distModules.get(renamed), compareOptions.format);
104
+ const renamed = (0, replace_runtime_module_name_1.replaceRuntimeModuleName)(name).replaceAll(node_path_1.default.win32.sep, node_path_1.default.posix.sep);
105
+ const sourceContent = sourceModules[renamed];
106
+ const distContent = distModules[renamed];
79
107
  compareResults.push({
80
108
  ...compareContent(sourceContent, distContent, compareOptions),
81
109
  name
@@ -45,6 +45,7 @@ const replace_module_argument_1 = require("./replace-module-argument");
45
45
  const SWC_HELPER_PATH_REG = /^_swc_helpers_[a-zA-Z\d_-]+__WEBPACK_IMPORTED_MODULE_xxx__$/;
46
46
  const CSS_FILE_EXT_REG = /(le|sa|c|sc)ss$/;
47
47
  const INVALID_PATH_REG = /[<>:"/\\|?*.]/g;
48
+ const MODULE_ID_REG = /__WEBPACK_IMPORTED_MODULE_\d+__/;
48
49
  function formatCode(name, raw, options) {
49
50
  const ast = (0, parser_1.parse)(raw, {
50
51
  sourceType: "unambiguous"
@@ -73,7 +74,9 @@ function formatCode(name, raw, options) {
73
74
  },
74
75
  Identifier(path) {
75
76
  if (options.ignoreModuleId) {
76
- path.node.name = path.node.name.replace(/__WEBPACK_IMPORTED_MODULE_\d+__/g, "__WEBPACK_IMPORTED_MODULE_xxx__");
77
+ if (MODULE_ID_REG.test(path.node.name)) {
78
+ path.node.name = "__WEBPACK_IMPORTED_MODULE_xxx__";
79
+ }
77
80
  }
78
81
  if (options.ignoreSwcHelpersPath) {
79
82
  if (SWC_HELPER_PATH_REG.test(path.node.name)) {
@@ -1 +1 @@
1
- export declare function replaceRuntimeModuleName(name: string): string;
1
+ export declare function replaceRuntimeModuleName(content: string): string;
@@ -1,49 +1,52 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.replaceRuntimeModuleName = replaceRuntimeModuleName;
4
+ const RUNTIME_MODULE_REGEX = /(webpack\/runtime\/)([a-z_]+)/g;
5
+ const RUNTIME_MODULE_NAME_REPLACER = {
6
+ auto_public_path: "publicPath",
7
+ public_path: "publicPath",
8
+ async_module: "async module",
9
+ base_uri: "base uri",
10
+ chunk_name: "chunkName",
11
+ compat_get_default_export: "compat get default export",
12
+ compat: "compat",
13
+ create_fake_namespace_object: "create fake namespace object",
14
+ create_script_url: "trusted types script url",
15
+ create_script: "trusted types script",
16
+ define_property_getters: "define property getters",
17
+ ensure_chunk: "ensure chunk",
18
+ get_full_hash: "getFullHash",
19
+ get_trusted_types_policy: "trusted types policy",
20
+ global: "global",
21
+ has_own_property: "hasOwnProperty shorthand",
22
+ load_script: "load script",
23
+ make_namespace_object: "make namespace object",
24
+ nonce: "nonce",
25
+ on_chunk_loaded: "chunk loaded",
26
+ relative_url: "relative url",
27
+ runtime_id: "runtimeId",
28
+ startup_chunk_dependencies: "startup chunk dependencies",
29
+ startup_entrypoint: "startup entrypoint",
30
+ system_context: "__system_context__",
31
+ chunk_prefetch_startup: "startup prefetch",
32
+ chunk_prefetch_trigger: "chunk prefetch trigger",
33
+ chunk_preload_trigger: "chunk preload trigger",
34
+ css_loading: "css loading",
35
+ async_wasm_loading: "wasm loading",
36
+ hot_module_replacement: "hot module replacement",
37
+ readfile_chunk_loading: "readFile chunk loading",
38
+ require_chunk_loading: "require chunk loading",
39
+ import_scripts_chunk_loading: "importScripts chunk loading",
40
+ module_chunk_loading: "import chunk loading",
41
+ export_webpack_runtime: "export webpack runtime",
42
+ jsonp_chunk_loading: "jsonp chunk loading",
43
+ remote: "remotes loading",
44
+ share: "sharing",
45
+ consume_shared: "consumes",
46
+ esm_module_decorator: "harmony module decorator",
47
+ node_module_decorator: "node module decorator"
48
+ };
4
49
  const RUNTIME_MODULE_NAME_MAPPING = {
5
- "webpack/runtime/auto_public_path": "webpack/runtime/publicPath",
6
- "webpack/runtime/public_path": "webpack/runtime/publicPath",
7
- "webpack/runtime/async_module": "webpack/runtime/async module",
8
- "webpack/runtime/base_uri": "webpack/runtime/base uri",
9
- "webpack/runtime/chunk_name": "webpack/runtime/chunkName",
10
- "webpack/runtime/compat_get_default_export": "webpack/runtime/compat get default export",
11
- "webpack/runtime/compat": "webpack/runtime/compat",
12
- "webpack/runtime/create_fake_namespace_object": "webpack/runtime/create fake namespace object",
13
- "webpack/runtime/create_script_url": "webpack/runtime/trusted types script url",
14
- "webpack/runtime/create_script": "webpack/runtime/trusted types script",
15
- "webpack/runtime/define_property_getters": "webpack/runtime/define property getters",
16
- "webpack/runtime/ensure_chunk": "webpack/runtime/ensure chunk",
17
- "webpack/runtime/get_full_hash": "webpack/runtime/getFullHash",
18
- "webpack/runtime/get_trusted_types_policy": "webpack/runtime/trusted types policy",
19
- "webpack/runtime/global": "webpack/runtime/global",
20
- "webpack/runtime/has_own_property": "webpack/runtime/hasOwnProperty shorthand",
21
- "webpack/runtime/load_script": "webpack/runtime/load script",
22
- "webpack/runtime/make_namespace_object": "webpack/runtime/make namespace object",
23
- "webpack/runtime/nonce": "webpack/runtime/nonce",
24
- "webpack/runtime/on_chunk_loaded": "webpack/runtime/chunk loaded",
25
- "webpack/runtime/relative_url": "webpack/runtime/relative url",
26
- "webpack/runtime/runtime_id": "webpack/runtime/runtimeId",
27
- "webpack/runtime/startup_chunk_dependencies": "webpack/runtime/startup chunk dependencies",
28
- "webpack/runtime/startup_entrypoint": "webpack/runtime/startup entrypoint",
29
- "webpack/runtime/system_context": "webpack/runtime/__system_context__",
30
- "webpack/runtime/chunk_prefetch_startup": "webpack/runtime/startup prefetch",
31
- "webpack/runtime/chunk_prefetch_trigger": "webpack/runtime/chunk prefetch trigger",
32
- "webpack/runtime/chunk_preload_trigger": "webpack/runtime/chunk preload trigger",
33
- "webpack/runtime/css_loading": "webpack/runtime/css loading",
34
- "webpack/runtime/async_wasm_loading": "webpack/runtime/wasm loading",
35
- "webpack/runtime/hot_module_replacement": "webpack/runtime/hot module replacement",
36
- "webpack/runtime/readfile_chunk_loading": "webpack/runtime/readFile chunk loading",
37
- "webpack/runtime/require_chunk_loading": "webpack/runtime/require chunk loading",
38
- "webpack/runtime/import_scripts_chunk_loading": "webpack/runtime/importScripts chunk loading",
39
- "webpack/runtime/module_chunk_loading": "webpack/runtime/import chunk loading",
40
- "webpack/runtime/export_webpack_runtime": "webpack/runtime/export webpack runtime",
41
- "webpack/runtime/jsonp_chunk_loading": "webpack/runtime/jsonp chunk loading",
42
- "webpack/runtime/remote": "webpack/runtime/remotes loading",
43
- "webpack/runtime/share": "webpack/runtime/sharing",
44
- "webpack/runtime/consume_shared": "webpack/runtime/consumes",
45
- "webpack/runtime/esm_module_decorator": "webpack/runtime/harmony module decorator",
46
- "webpack/runtime/node_module_decorator": "webpack/runtime/node module decorator",
47
50
  // module name with parameters
48
51
  "webpack/runtime/get_chunk_filename": "webpack/runtime/get $1 chunk filename",
49
52
  "webpack/runtime/get_main_filename": "webpack/runtime/get $1 filename",
@@ -54,13 +57,15 @@ const RUNTIME_MODULE_PARAM_REGEX = {
54
57
  "webpack/runtime/get_main_filename": /webpack\/runtime\/get_main_filename\/([\w.\-_\s]+)(\*\/)?/g,
55
58
  "webpack/runtime/chunk_prefetch_function": /webpack\/runtime\/chunk_prefetch_function\/([\w.\-_\s]+)(\*\/)?/g
56
59
  };
57
- function replaceRuntimeModuleName(name) {
58
- return Object.entries(RUNTIME_MODULE_NAME_MAPPING).reduce((name, [rspackName, webpackName]) => {
60
+ function replaceRuntimeModuleName(content) {
61
+ let res = content.replace(RUNTIME_MODULE_REGEX, (_, $1, $2) => `${$1}${RUNTIME_MODULE_NAME_REPLACER[$2] || $2}`);
62
+ res = Object.entries(RUNTIME_MODULE_NAME_MAPPING).reduce((res, [rspackName, webpackName]) => {
59
63
  if (RUNTIME_MODULE_PARAM_REGEX[rspackName]) {
60
- return name.replace(RUNTIME_MODULE_PARAM_REGEX[rspackName], (_, $1, $2) => {
64
+ return res.replace(RUNTIME_MODULE_PARAM_REGEX[rspackName], (_, $1, $2) => {
61
65
  return webpackName.replace("$1", $1.trim()) + ($2 ? " */" : "");
62
66
  });
63
67
  }
64
- return name.split(rspackName).join(webpackName);
65
- }, name);
68
+ return res.replaceAll(rspackName, webpackName);
69
+ }, res);
70
+ return res;
66
71
  }
@@ -7,14 +7,17 @@ function default_1(c) {
7
7
  content = `
8
8
  ${content}
9
9
  let __hmr_children__ = [...module.children];
10
- let __hmr_used_exports__ = __hmr_children__.reduce((res, child) => {
11
- res[child] = __webpack_module_cache__[child].exports;
10
+ let __hmr_used_exports__ = __hmr_children__.reduce((res, child) => {
11
+ if (__webpack_module_cache__[child]) {
12
+ res[child] = __webpack_module_cache__[child].exports;
13
+ }
12
14
  return res;
13
15
  }, {});
14
16
  module.hot.accept(__hmr_children__, () => {
15
17
  __hmr_children__.forEach((child) => {
16
18
  const reexports = __webpack_require__(child);
17
- for (let key in reexports) {
19
+ for (let key in reexports) {
20
+ if (!__hmr_used_exports__[child]) { continue; }
18
21
  Object.defineProperty(__hmr_used_exports__[child], key, {
19
22
  configurable: true,
20
23
  enumerable: true,
@@ -2,6 +2,6 @@ export declare function parseModules(content: string, options?: {
2
2
  bootstrap?: boolean;
3
3
  renameModule?: (name: string) => string;
4
4
  }): {
5
- modules: Map<string, string>;
6
- runtimeModules: Map<string, string>;
5
+ modules: Record<string, string>;
6
+ runtimeModules: Record<string, string>;
7
7
  };
@@ -35,14 +35,14 @@ function isValidModule(name) {
35
35
  return true;
36
36
  }
37
37
  function parseModules(content, options = {}) {
38
- const modules = new Map();
39
- const runtimeModules = new Map();
38
+ const modules = {};
39
+ const runtimeModules = {};
40
40
  let currentPosition = 0;
41
41
  if (options.bootstrap) {
42
42
  // parse bootstrap code
43
43
  const bootstrap = getStringBetween(content, 0, BOOTSTRAP_SPLIT_LINE, BOOTSTRAP_SPLIT_LINE);
44
44
  if (bootstrap.result) {
45
- runtimeModules.set("webpack/runtime/bootstrap", bootstrap.result);
45
+ runtimeModules["webpack/runtime/bootstrap"] = bootstrap.result;
46
46
  }
47
47
  }
48
48
  // parse module & runtime module code
@@ -56,11 +56,11 @@ function parseModules(content, options = {}) {
56
56
  ? options.renameModule(moduleName)
57
57
  : moduleName;
58
58
  if (moduleName.startsWith("webpack/runtime")) {
59
- runtimeModules.set(renamedModuleName, moduleContent.result);
59
+ runtimeModules[renamedModuleName] = moduleContent.result;
60
60
  }
61
61
  else {
62
62
  if (isValidModule(moduleName)) {
63
- modules.set(renamedModuleName, moduleContent.result);
63
+ modules[renamedModuleName] = moduleContent.result;
64
64
  }
65
65
  }
66
66
  currentPosition = moduleContent.remain;
@@ -95,19 +95,29 @@ class BasicProcessor {
95
95
  const compiler = this.getCompiler(context);
96
96
  const stats = compiler.getStats();
97
97
  if (stats) {
98
- node_fs_1.default.writeFileSync(node_path_1.default.join(context.getDist(), "stats.txt"), stats.toString({
99
- preset: "verbose",
100
- colors: false
101
- }), "utf-8");
102
- const jsonStats = stats.toJson({
103
- errorDetails: true
104
- });
105
- node_fs_1.default.writeFileSync(node_path_1.default.join(context.getDist(), "stats.json"), JSON.stringify(jsonStats, null, 2), "utf-8");
106
- if (jsonStats.errors) {
107
- errors.push(...jsonStats.errors);
98
+ if (testConfig.writeStatsOuptut) {
99
+ node_fs_1.default.writeFileSync(node_path_1.default.join(context.getDist(), "stats.txt"), stats.toString({
100
+ preset: "verbose",
101
+ colors: false
102
+ }), "utf-8");
108
103
  }
109
- if (jsonStats.warnings) {
110
- warnings.push(...jsonStats.warnings);
104
+ if (testConfig.writeStatsJson) {
105
+ const jsonStats = stats.toJson({
106
+ errorDetails: true
107
+ });
108
+ node_fs_1.default.writeFileSync(node_path_1.default.join(context.getDist(), "stats.json"), JSON.stringify(jsonStats, null, 2), "utf-8");
109
+ }
110
+ if (node_fs_1.default.existsSync(context.getSource("errors.js")) ||
111
+ node_fs_1.default.existsSync(context.getSource("warnings.js"))) {
112
+ const statsJson = stats.toJson({
113
+ errorDetails: true
114
+ });
115
+ if (statsJson.errors) {
116
+ errors.push(...statsJson.errors);
117
+ }
118
+ if (statsJson.warnings) {
119
+ warnings.push(...statsJson.warnings);
120
+ }
111
121
  }
112
122
  }
113
123
  await (0, checkArrayExpectation_1.default)(context.getSource(), { errors }, "error", "errors", "Error");
@@ -13,13 +13,16 @@ class DiffProcessor {
13
13
  constructor(options) {
14
14
  this.options = options;
15
15
  this.hashes = [];
16
- this.webpack = new basic_1.BasicProcessor({
17
- defaultOptions: context => this.getDefaultOptions(type_1.ECompilerType.Webpack, context.getSource(), node_path_1.default.join(context.getDist(), type_1.ECompilerType.Webpack)),
18
- compilerType: type_1.ECompilerType.Webpack,
19
- name: type_1.ECompilerType.Webpack,
20
- configFiles: ["webpack.config.js", "rspack.config.js"],
21
- runable: false
22
- });
16
+ this.webpack = null;
17
+ if (global.updateSnapshot) {
18
+ this.webpack = new basic_1.BasicProcessor({
19
+ defaultOptions: context => this.getDefaultOptions(type_1.ECompilerType.Webpack, context.getSource(), node_path_1.default.join(context.getDist(), type_1.ECompilerType.Webpack)),
20
+ compilerType: type_1.ECompilerType.Webpack,
21
+ name: type_1.ECompilerType.Webpack,
22
+ configFiles: ["webpack.config.js", "rspack.config.js"],
23
+ runable: false
24
+ });
25
+ }
23
26
  this.rspack = new basic_1.BasicProcessor({
24
27
  defaultOptions: context => this.getDefaultOptions(type_1.ECompilerType.Rspack, context.getSource(), node_path_1.default.join(context.getDist(), type_1.ECompilerType.Rspack)),
25
28
  compilerType: type_1.ECompilerType.Rspack,
@@ -29,24 +32,32 @@ class DiffProcessor {
29
32
  });
30
33
  }
31
34
  async config(context) {
32
- await this.webpack.config(context);
35
+ if (this.webpack) {
36
+ await this.webpack.config(context);
37
+ }
33
38
  await this.rspack.config(context);
34
39
  }
35
40
  async compiler(context) {
36
- await this.webpack.compiler(context);
41
+ if (this.webpack) {
42
+ await this.webpack.compiler(context);
43
+ }
37
44
  await this.rspack.compiler(context);
38
45
  }
39
46
  async build(context) {
40
- await this.webpack.build(context);
47
+ if (this.webpack) {
48
+ await this.webpack.build(context);
49
+ }
41
50
  await this.rspack.build(context);
42
51
  }
43
52
  async check(env, context) {
44
- const webpackCompiler = context.getCompiler(type_1.ECompilerType.Webpack);
45
- const webpackStats = webpackCompiler.getStats();
46
- //TODO: handle chunk hash and content hash
47
- webpackStats?.hash && this.hashes.push(webpackStats?.hash);
48
- if (!this.options.errors) {
49
- env.expect(webpackStats?.hasErrors()).toBe(false);
53
+ if (this.webpack) {
54
+ const webpackCompiler = context.getCompiler(type_1.ECompilerType.Webpack);
55
+ const webpackStats = webpackCompiler.getStats();
56
+ //TODO: handle chunk hash and content hash
57
+ webpackStats?.hash && this.hashes.push(webpackStats?.hash);
58
+ if (!this.options.errors) {
59
+ env.expect(webpackStats?.hasErrors()).toBe(false);
60
+ }
50
61
  }
51
62
  const rspackCompiler = context.getCompiler(type_1.ECompilerType.Rspack);
52
63
  const rspackStats = rspackCompiler.getStats();
@@ -56,16 +67,19 @@ class DiffProcessor {
56
67
  env.expect(rspackStats?.hasErrors()).toBe(false);
57
68
  }
58
69
  const dist = context.getDist();
70
+ const snapshot = context.getSource("__snapshot__");
59
71
  for (const file of this.options.files) {
60
72
  const rspackDist = node_path_1.default.join(dist, type_1.ECompilerType.Rspack, file);
61
73
  const webpackDist = node_path_1.default.join(dist, type_1.ECompilerType.Webpack, file);
74
+ const snapshotDist = node_path_1.default.join(snapshot, file.replace(/\.js$/, ".json"));
62
75
  const result = (0, compare_1.compareFile)(rspackDist, webpackDist, {
63
76
  modules: this.options.modules,
64
77
  runtimeModules: this.options.runtimeModules,
65
78
  format: this.createFormatOptions(),
66
79
  renameModule: this.options.renameModule,
67
80
  bootstrap: this.options.bootstrap,
68
- detail: this.options.detail
81
+ detail: this.options.detail,
82
+ snapshot: snapshotDist
69
83
  });
70
84
  if (typeof this.options.onCompareFile === "function") {
71
85
  this.options.onCompareFile(file, result);
@@ -20,12 +20,11 @@ class HashProcessor extends multi_1.MultiTaskProcessor {
20
20
  env.expect(false);
21
21
  return;
22
22
  }
23
- const statsJson = stats.toJson({ assets: true });
24
23
  if (REG_ERROR_CASE.test(this._options.name)) {
25
- env.expect((statsJson.errors || []).length > 0);
24
+ env.expect(stats.hasErrors());
26
25
  }
27
26
  else {
28
- env.expect((statsJson.errors || []).length === 0);
27
+ env.expect(!stats.hasErrors());
29
28
  }
30
29
  if (typeof testConfig.validate === "function") {
31
30
  testConfig.validate(stats);