@rstest/core 0.6.1 → 0.6.3
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/LICENSE.md +0 -14
- package/dist/0~171.js +4 -6
- package/dist/0~204.js +67 -77
- package/dist/0~263.js +1423 -0
- package/dist/0~350.js +29 -373
- package/dist/0~365.js +92 -0
- package/dist/0~463.js +331 -0
- package/dist/0~470.js +388 -0
- package/dist/0~607.js +119 -0
- package/dist/0~691.js +74 -82
- package/dist/0~711.js +29 -373
- package/dist/0~764.js +13284 -0
- package/dist/0~814.js +900 -0
- package/dist/0~830.js +1130 -0
- package/dist/0~836.js +13 -21
- package/dist/0~971.js +130 -136
- package/dist/597.js +174 -0
- package/dist/603.js +41 -0
- package/dist/808.js +167 -0
- package/dist/857.js +3252 -0
- package/dist/index.js +2394 -5972
- package/dist/rslib-runtime.js +60 -0
- package/dist/worker.js +154 -1393
- package/dist-types/index.d.ts +24 -3
- package/dist-types/worker.d.ts +8 -2
- package/package.json +2 -2
- package/dist/0~33.js +0 -425
- package/dist/0~414.js +0 -16
- package/dist/0~493.js +0 -126
- package/dist/0~603.js +0 -50
- package/dist/0~628.js +0 -1090
- package/dist/0~655.js +0 -11533
- package/dist/0~85.js +0 -1819
- package/dist/0~873.js +0 -1220
- package/dist/0~928.js +0 -1432
- package/dist/0~967.js +0 -99
- /package/dist/{0~928.js.LICENSE.txt → 0~263.js.LICENSE.txt} +0 -0
- /package/dist/{0~655.js.LICENSE.txt → 0~764.js.LICENSE.txt} +0 -0
package/dist/0~814.js
ADDED
|
@@ -0,0 +1,900 @@
|
|
|
1
|
+
import 'module';
|
|
2
|
+
/*#__PURE__*/ import.meta.url;
|
|
3
|
+
import { __webpack_require__ } from "./rslib-runtime.js";
|
|
4
|
+
import node_events from "node:events";
|
|
5
|
+
import { Tinypool } from "tinypool";
|
|
6
|
+
import node_inspector from "node:inspector";
|
|
7
|
+
import { basename, TEMP_RSTEST_OUTPUT_DIR, dirname, posix, resolve as pathe_M_eThtNZ_resolve, serializableConfig, node_process, isBuiltin, castArray, TEMP_RSTEST_OUTPUT_DIR_GLOB, isDebug, ADDITIONAL_NODE_BUILTINS, join, needFlagExperimentalDetectModule } from "./857.js";
|
|
8
|
+
import { node_v8, fileURLToPath, createBirpc } from "./808.js";
|
|
9
|
+
import { logger, createRsbuild } from "./index.js";
|
|
10
|
+
const DefaultMaxHeapSize = 1073741824;
|
|
11
|
+
function memory_isMemorySufficient(options) {
|
|
12
|
+
const { memoryThreshold = 0.7, maxHeapSize = DefaultMaxHeapSize } = options || {};
|
|
13
|
+
if (!node_process?.memoryUsage) return true;
|
|
14
|
+
const memoryUsage = node_process.memoryUsage();
|
|
15
|
+
const heapUsed = memoryUsage.heapUsed;
|
|
16
|
+
const heapTotal = memoryUsage.heapTotal;
|
|
17
|
+
const memoryUsageRatio = heapUsed / heapTotal;
|
|
18
|
+
const isMemorySufficient = memoryUsageRatio < memoryThreshold && heapUsed < maxHeapSize;
|
|
19
|
+
return isMemorySufficient;
|
|
20
|
+
}
|
|
21
|
+
const forks_filename = fileURLToPath(import.meta.url);
|
|
22
|
+
const forks_dirname = dirname(forks_filename);
|
|
23
|
+
function createChannel(rpcMethods) {
|
|
24
|
+
const emitter = new node_events();
|
|
25
|
+
const cleanup = ()=>emitter.removeAllListeners();
|
|
26
|
+
const events = {
|
|
27
|
+
message: 'message',
|
|
28
|
+
response: 'response'
|
|
29
|
+
};
|
|
30
|
+
const channel = {
|
|
31
|
+
onMessage: (callback)=>{
|
|
32
|
+
emitter.on(events.message, callback);
|
|
33
|
+
},
|
|
34
|
+
postMessage: (message)=>{
|
|
35
|
+
emitter.emit(events.response, message);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
createBirpc(rpcMethods, {
|
|
39
|
+
serialize: node_v8.serialize,
|
|
40
|
+
deserialize: (v)=>node_v8.deserialize(Buffer.from(v)),
|
|
41
|
+
post (v) {
|
|
42
|
+
emitter.emit(events.message, v);
|
|
43
|
+
},
|
|
44
|
+
on (fn) {
|
|
45
|
+
emitter.on(events.response, fn);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
return {
|
|
49
|
+
channel,
|
|
50
|
+
cleanup
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const createForksPool = (poolOptions)=>{
|
|
54
|
+
const { maxWorkers: maxThreads, minWorkers: minThreads, env, execArgv = [], isolate = true } = poolOptions;
|
|
55
|
+
const options = {
|
|
56
|
+
runtime: 'child_process',
|
|
57
|
+
filename: pathe_M_eThtNZ_resolve(forks_dirname, './worker.js'),
|
|
58
|
+
env,
|
|
59
|
+
execArgv,
|
|
60
|
+
maxThreads,
|
|
61
|
+
minThreads,
|
|
62
|
+
concurrentTasksPerWorker: 1,
|
|
63
|
+
isolateWorkers: isolate
|
|
64
|
+
};
|
|
65
|
+
const pool = new Tinypool(options);
|
|
66
|
+
return {
|
|
67
|
+
name: 'forks',
|
|
68
|
+
runTest: async ({ options, rpcMethods })=>{
|
|
69
|
+
const { channel, cleanup } = createChannel(rpcMethods);
|
|
70
|
+
try {
|
|
71
|
+
return await pool.run(options, {
|
|
72
|
+
channel
|
|
73
|
+
});
|
|
74
|
+
} finally{
|
|
75
|
+
cleanup();
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
collectTests: async ({ options, rpcMethods })=>{
|
|
79
|
+
const { channel, cleanup } = createChannel(rpcMethods);
|
|
80
|
+
try {
|
|
81
|
+
return await pool.run(options, {
|
|
82
|
+
channel
|
|
83
|
+
});
|
|
84
|
+
} finally{
|
|
85
|
+
cleanup();
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
close: ()=>pool.destroy()
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
const external_node_os_ = __webpack_require__("node:os");
|
|
92
|
+
const getNumCpus = ()=>external_node_os_["default"].availableParallelism?.() ?? external_node_os_["default"].cpus().length;
|
|
93
|
+
const parseWorkers = (maxWorkers)=>{
|
|
94
|
+
const parsed = Number.parseInt(maxWorkers.toString(), 10);
|
|
95
|
+
if ('string' == typeof maxWorkers && maxWorkers.trim().endsWith('%')) {
|
|
96
|
+
const numCpus = getNumCpus();
|
|
97
|
+
const workers = Math.floor(parsed / 100 * numCpus);
|
|
98
|
+
return Math.max(workers, 1);
|
|
99
|
+
}
|
|
100
|
+
return parsed > 0 ? parsed : 1;
|
|
101
|
+
};
|
|
102
|
+
const getRuntimeConfig = (context)=>{
|
|
103
|
+
const { testNamePattern, testTimeout, passWithNoTests, retry, globals, clearMocks, resetMocks, restoreMocks, unstubEnvs, unstubGlobals, maxConcurrency, printConsoleTrace, disableConsoleIntercept, testEnvironment, hookTimeout, isolate, coverage, snapshotFormat, env, logHeapUsage } = context.normalizedConfig;
|
|
104
|
+
return {
|
|
105
|
+
env,
|
|
106
|
+
testNamePattern,
|
|
107
|
+
testTimeout,
|
|
108
|
+
hookTimeout,
|
|
109
|
+
passWithNoTests,
|
|
110
|
+
retry,
|
|
111
|
+
globals,
|
|
112
|
+
clearMocks,
|
|
113
|
+
resetMocks,
|
|
114
|
+
restoreMocks,
|
|
115
|
+
unstubEnvs,
|
|
116
|
+
unstubGlobals,
|
|
117
|
+
maxConcurrency,
|
|
118
|
+
printConsoleTrace,
|
|
119
|
+
disableConsoleIntercept,
|
|
120
|
+
testEnvironment,
|
|
121
|
+
isolate,
|
|
122
|
+
coverage,
|
|
123
|
+
snapshotFormat,
|
|
124
|
+
logHeapUsage
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
const filterAssetsByEntry = async (entryInfo, getAssetFiles, getSourceMaps, setupAssets)=>{
|
|
128
|
+
const assetNames = Array.from(new Set([
|
|
129
|
+
...entryInfo.files,
|
|
130
|
+
...setupAssets
|
|
131
|
+
]));
|
|
132
|
+
const neededFiles = await getAssetFiles(assetNames);
|
|
133
|
+
const neededSourceMaps = await getSourceMaps(assetNames);
|
|
134
|
+
return {
|
|
135
|
+
assetFiles: neededFiles,
|
|
136
|
+
sourceMaps: neededSourceMaps
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
const createPool = async ({ context, recommendWorkerCount = 1 / 0 })=>{
|
|
140
|
+
const execArgv = process.execArgv.filter((execArg)=>execArg.startsWith('--perf') || execArg.startsWith('--cpu-prof') || execArg.startsWith('--heap-prof') || execArg.startsWith('--diagnostic-dir'));
|
|
141
|
+
const numCpus = getNumCpus();
|
|
142
|
+
const { normalizedConfig: { pool: poolOptions, isolate }, reporters } = context;
|
|
143
|
+
const threadsCount = 'watch' === context.command ? Math.max(Math.floor(numCpus / 2), 1) : Math.max(numCpus - 1, 1);
|
|
144
|
+
const recommendCount = 'watch' === context.command ? threadsCount : Math.min(recommendWorkerCount, threadsCount);
|
|
145
|
+
const maxWorkers = poolOptions.maxWorkers ? parseWorkers(poolOptions.maxWorkers) : recommendCount;
|
|
146
|
+
const minWorkers = poolOptions.minWorkers ? parseWorkers(poolOptions.minWorkers) : maxWorkers < recommendCount ? maxWorkers : recommendCount;
|
|
147
|
+
if (maxWorkers < minWorkers) throw `Invalid pool configuration: maxWorkers(${maxWorkers}) cannot be less than minWorkers(${minWorkers}).`;
|
|
148
|
+
const pool = createForksPool({
|
|
149
|
+
...poolOptions,
|
|
150
|
+
isolate,
|
|
151
|
+
maxWorkers,
|
|
152
|
+
minWorkers,
|
|
153
|
+
execArgv: [
|
|
154
|
+
...poolOptions?.execArgv ?? [],
|
|
155
|
+
...execArgv,
|
|
156
|
+
'--experimental-vm-modules',
|
|
157
|
+
'--experimental-import-meta-resolve',
|
|
158
|
+
'--no-warnings',
|
|
159
|
+
needFlagExperimentalDetectModule() ? '--experimental-detect-module' : void 0
|
|
160
|
+
].filter(Boolean),
|
|
161
|
+
env: {
|
|
162
|
+
NODE_ENV: 'test',
|
|
163
|
+
FORCE_COLOR: '1' === process.env.NO_COLOR ? '0' : '1',
|
|
164
|
+
...process.env
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
const rpcMethods = {
|
|
168
|
+
onTestCaseResult: async (result)=>{
|
|
169
|
+
await Promise.all(reporters.map((reporter)=>reporter.onTestCaseResult?.(result)));
|
|
170
|
+
},
|
|
171
|
+
onConsoleLog: async (log)=>{
|
|
172
|
+
await Promise.all(reporters.map((reporter)=>reporter.onUserConsoleLog?.(log)));
|
|
173
|
+
},
|
|
174
|
+
onTestFileStart: async (test)=>{
|
|
175
|
+
await Promise.all(reporters.map((reporter)=>reporter.onTestFileStart?.(test)));
|
|
176
|
+
},
|
|
177
|
+
resolveSnapshotPath: (testPath)=>{
|
|
178
|
+
const snapExtension = '.snap';
|
|
179
|
+
const resolver = context.normalizedConfig.resolveSnapshotPath || (()=>join(dirname(testPath), '__snapshots__', `${basename(testPath)}${snapExtension}`));
|
|
180
|
+
const snapshotPath = resolver(testPath, snapExtension);
|
|
181
|
+
return snapshotPath;
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
return {
|
|
185
|
+
runTests: async ({ entries, getAssetFiles, getSourceMaps, setupEntries, project, updateSnapshot })=>{
|
|
186
|
+
const projectName = context.normalizedConfig.name;
|
|
187
|
+
const runtimeConfig = getRuntimeConfig(project);
|
|
188
|
+
const setupAssets = setupEntries.flatMap((entry)=>entry.files || []);
|
|
189
|
+
const results = await Promise.all(entries.map(async (entryInfo, index)=>{
|
|
190
|
+
const result = await pool.runTest({
|
|
191
|
+
options: {
|
|
192
|
+
entryInfo,
|
|
193
|
+
context: {
|
|
194
|
+
taskId: index + 1,
|
|
195
|
+
project: projectName,
|
|
196
|
+
rootPath: context.rootPath,
|
|
197
|
+
projectRoot: project.rootPath,
|
|
198
|
+
runtimeConfig: serializableConfig(runtimeConfig)
|
|
199
|
+
},
|
|
200
|
+
type: 'run',
|
|
201
|
+
setupEntries,
|
|
202
|
+
updateSnapshot,
|
|
203
|
+
assets: memory_isMemorySufficient() ? await filterAssetsByEntry(entryInfo, getAssetFiles, getSourceMaps, setupAssets) : void 0
|
|
204
|
+
},
|
|
205
|
+
rpcMethods: {
|
|
206
|
+
...rpcMethods,
|
|
207
|
+
getAssetsByEntry: async ()=>filterAssetsByEntry(entryInfo, getAssetFiles, getSourceMaps, setupAssets)
|
|
208
|
+
}
|
|
209
|
+
}).catch((err)=>{
|
|
210
|
+
err.fullStack = true;
|
|
211
|
+
return {
|
|
212
|
+
project: projectName,
|
|
213
|
+
testPath: entryInfo.testPath,
|
|
214
|
+
status: 'fail',
|
|
215
|
+
name: '',
|
|
216
|
+
results: [],
|
|
217
|
+
errors: [
|
|
218
|
+
err
|
|
219
|
+
]
|
|
220
|
+
};
|
|
221
|
+
});
|
|
222
|
+
reporters.map((reporter)=>reporter.onTestFileResult?.(result));
|
|
223
|
+
return result;
|
|
224
|
+
}));
|
|
225
|
+
for (const result of results)if (result.snapshotResult) context.snapshotManager.add(result.snapshotResult);
|
|
226
|
+
const testResults = results.flatMap((r)=>r.results);
|
|
227
|
+
return {
|
|
228
|
+
results,
|
|
229
|
+
testResults,
|
|
230
|
+
project
|
|
231
|
+
};
|
|
232
|
+
},
|
|
233
|
+
collectTests: async ({ entries, getAssetFiles, getSourceMaps, setupEntries, project, updateSnapshot })=>{
|
|
234
|
+
const runtimeConfig = getRuntimeConfig(project);
|
|
235
|
+
const projectName = project.normalizedConfig.name;
|
|
236
|
+
const setupAssets = setupEntries.flatMap((entry)=>entry.files || []);
|
|
237
|
+
return Promise.all(entries.map(async (entryInfo, index)=>pool.collectTests({
|
|
238
|
+
options: {
|
|
239
|
+
entryInfo,
|
|
240
|
+
context: {
|
|
241
|
+
taskId: index + 1,
|
|
242
|
+
project: projectName,
|
|
243
|
+
rootPath: context.rootPath,
|
|
244
|
+
projectRoot: project.rootPath,
|
|
245
|
+
runtimeConfig: serializableConfig(runtimeConfig)
|
|
246
|
+
},
|
|
247
|
+
type: 'collect',
|
|
248
|
+
setupEntries,
|
|
249
|
+
updateSnapshot,
|
|
250
|
+
assets: memory_isMemorySufficient() ? await filterAssetsByEntry(entryInfo, getAssetFiles, getSourceMaps, setupAssets) : void 0
|
|
251
|
+
},
|
|
252
|
+
rpcMethods: {
|
|
253
|
+
...rpcMethods,
|
|
254
|
+
getAssetsByEntry: async ()=>filterAssetsByEntry(entryInfo, getAssetFiles, getSourceMaps, setupAssets)
|
|
255
|
+
}
|
|
256
|
+
}).catch((err)=>{
|
|
257
|
+
err.fullStack = true;
|
|
258
|
+
return {
|
|
259
|
+
project: projectName,
|
|
260
|
+
testPath: entryInfo.testPath,
|
|
261
|
+
tests: [],
|
|
262
|
+
errors: [
|
|
263
|
+
err
|
|
264
|
+
]
|
|
265
|
+
};
|
|
266
|
+
})));
|
|
267
|
+
},
|
|
268
|
+
close: ()=>pool.close()
|
|
269
|
+
};
|
|
270
|
+
};
|
|
271
|
+
const RUNTIME_CHUNK_NAME = 'runtime';
|
|
272
|
+
const pluginBasic = (context)=>({
|
|
273
|
+
name: 'rstest:basic',
|
|
274
|
+
setup: (api)=>{
|
|
275
|
+
api.modifyEnvironmentConfig(async (config, { mergeEnvironmentConfig, name })=>{
|
|
276
|
+
const { normalizedConfig: { resolve, source, output, tools, performance, dev, testEnvironment }, rootPath } = context.projects.find((p)=>p.environmentName === name);
|
|
277
|
+
return mergeEnvironmentConfig(config, {
|
|
278
|
+
performance,
|
|
279
|
+
tools,
|
|
280
|
+
resolve,
|
|
281
|
+
source,
|
|
282
|
+
output,
|
|
283
|
+
dev
|
|
284
|
+
}, {
|
|
285
|
+
source: {
|
|
286
|
+
define: {
|
|
287
|
+
'import.meta.rstest': "global['@rstest/core']",
|
|
288
|
+
'import.meta.env': 'process.env'
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
output: {
|
|
292
|
+
manifest: `${name}-manifest.json`,
|
|
293
|
+
sourceMap: {
|
|
294
|
+
js: 'source-map'
|
|
295
|
+
},
|
|
296
|
+
distPath: {
|
|
297
|
+
root: context.projects.length > 1 ? `${TEMP_RSTEST_OUTPUT_DIR}/${name}` : TEMP_RSTEST_OUTPUT_DIR
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
tools: {
|
|
301
|
+
rspack: (config, { isProd, rspack })=>{
|
|
302
|
+
config.context = rootPath;
|
|
303
|
+
config.mode = isProd ? 'production' : 'development';
|
|
304
|
+
config.output ??= {};
|
|
305
|
+
config.output.iife = false;
|
|
306
|
+
config.output.importFunctionName = '__rstest_dynamic_import__';
|
|
307
|
+
config.output.devtoolModuleFilenameTemplate = '[absolute-resource-path]';
|
|
308
|
+
if (!config.devtool || !config.devtool.includes('inline')) config.devtool = 'nosources-source-map';
|
|
309
|
+
config.plugins.push(new rspack.experiments.RstestPlugin({
|
|
310
|
+
injectModulePathName: true,
|
|
311
|
+
importMetaPathName: true,
|
|
312
|
+
hoistMockModule: true,
|
|
313
|
+
manualMockRoot: posix.resolve(rootPath, '__mocks__')
|
|
314
|
+
}));
|
|
315
|
+
config.module.parser ??= {};
|
|
316
|
+
config.module.parser.javascript = {
|
|
317
|
+
importDynamic: false,
|
|
318
|
+
requireDynamic: false,
|
|
319
|
+
requireAsExpression: false,
|
|
320
|
+
requireResolve: false,
|
|
321
|
+
...config.module.parser.javascript || {}
|
|
322
|
+
};
|
|
323
|
+
config.resolve ??= {};
|
|
324
|
+
config.resolve.extensions ??= [];
|
|
325
|
+
config.resolve.extensions.push('.cjs');
|
|
326
|
+
config.resolve.extensionAlias ??= {};
|
|
327
|
+
config.resolve.extensionAlias['.js'] = [
|
|
328
|
+
'.js',
|
|
329
|
+
'.ts',
|
|
330
|
+
'.tsx'
|
|
331
|
+
];
|
|
332
|
+
config.resolve.extensionAlias['.jsx'] = [
|
|
333
|
+
'.jsx',
|
|
334
|
+
'.tsx'
|
|
335
|
+
];
|
|
336
|
+
if ('node' === testEnvironment) config.resolve.mainFields = config.resolve.mainFields?.filter((filed)=>'module' !== filed) || [
|
|
337
|
+
'main'
|
|
338
|
+
];
|
|
339
|
+
config.resolve.byDependency ??= {};
|
|
340
|
+
config.resolve.byDependency.commonjs ??= {};
|
|
341
|
+
config.resolve.byDependency.commonjs.mainFields = [
|
|
342
|
+
'main',
|
|
343
|
+
'...'
|
|
344
|
+
];
|
|
345
|
+
config.optimization = {
|
|
346
|
+
moduleIds: 'named',
|
|
347
|
+
chunkIds: 'named',
|
|
348
|
+
nodeEnv: false,
|
|
349
|
+
...config.optimization || {},
|
|
350
|
+
runtimeChunk: {
|
|
351
|
+
name: `${name}-${RUNTIME_CHUNK_NAME}`
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
const external_node_path_ = __webpack_require__("node:path");
|
|
361
|
+
const PLUGIN_CSS_FILTER = 'rstest:css-filter';
|
|
362
|
+
const css_filter_dirname = external_node_path_["default"].dirname(fileURLToPath(import.meta.url));
|
|
363
|
+
const pluginCSSFilter = ()=>({
|
|
364
|
+
name: PLUGIN_CSS_FILTER,
|
|
365
|
+
setup (api) {
|
|
366
|
+
api.modifyBundlerChain({
|
|
367
|
+
order: 'post',
|
|
368
|
+
handler: async (chain, { target, CHAIN_ID, environment })=>{
|
|
369
|
+
const emitCss = environment.config.output.emitCss ?? 'web' === target;
|
|
370
|
+
if (!emitCss) {
|
|
371
|
+
const ruleIds = [
|
|
372
|
+
CHAIN_ID.RULE.CSS,
|
|
373
|
+
CHAIN_ID.RULE.SASS,
|
|
374
|
+
CHAIN_ID.RULE.LESS,
|
|
375
|
+
CHAIN_ID.RULE.STYLUS
|
|
376
|
+
];
|
|
377
|
+
for (const ruleId of ruleIds){
|
|
378
|
+
if (!chain.module.rules.has(ruleId)) continue;
|
|
379
|
+
const rule = chain.module.rule(ruleId);
|
|
380
|
+
if (!rule.uses.has(CHAIN_ID.USE.CSS)) continue;
|
|
381
|
+
const cssLoaderOptions = rule.use(CHAIN_ID.USE.CSS).get('options');
|
|
382
|
+
if (cssLoaderOptions.modules && ('object' != typeof cssLoaderOptions.modules || false !== cssLoaderOptions.modules.auto)) rule.use('rstest-css-pre-filter').loader(external_node_path_["default"].join(css_filter_dirname, 'cssFilterLoader.mjs')).options({
|
|
383
|
+
modules: cssLoaderOptions.modules
|
|
384
|
+
}).after(ruleId);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
class TestFileWatchPlugin {
|
|
392
|
+
contextToWatch = null;
|
|
393
|
+
constructor(contextToWatch){
|
|
394
|
+
this.contextToWatch = contextToWatch;
|
|
395
|
+
}
|
|
396
|
+
apply(compiler) {
|
|
397
|
+
compiler.hooks.afterCompile.tap('Rstest:TestFileWatchPlugin', (compilation)=>{
|
|
398
|
+
if (null === this.contextToWatch) return;
|
|
399
|
+
const contextDep = compilation.contextDependencies;
|
|
400
|
+
if (!contextDep.has(this.contextToWatch)) contextDep.add(this.contextToWatch);
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
const pluginEntryWatch = ({ isWatch, globTestSourceEntries, setupFiles, context })=>({
|
|
405
|
+
name: 'rstest:entry-watch',
|
|
406
|
+
setup: (api)=>{
|
|
407
|
+
api.modifyRspackConfig(async (config, { environment })=>{
|
|
408
|
+
if (isWatch) {
|
|
409
|
+
config.plugins.push(new TestFileWatchPlugin(environment.config.root));
|
|
410
|
+
config.entry = async ()=>{
|
|
411
|
+
const sourceEntries = await globTestSourceEntries(environment.name);
|
|
412
|
+
return {
|
|
413
|
+
...sourceEntries,
|
|
414
|
+
...setupFiles[environment.name]
|
|
415
|
+
};
|
|
416
|
+
};
|
|
417
|
+
config.watchOptions ??= {};
|
|
418
|
+
config.watchOptions.ignored = castArray(config.watchOptions.ignored || []);
|
|
419
|
+
if (0 === config.watchOptions.ignored.length) config.watchOptions.ignored.push('**/.git', '**/node_modules');
|
|
420
|
+
config.watchOptions.ignored.push(TEMP_RSTEST_OUTPUT_DIR_GLOB, context.normalizedConfig.coverage.reportsDirectory, '**/*.snap');
|
|
421
|
+
const configFilePath = context.projects.find((project)=>project.environmentName === environment.name)?.configFilePath;
|
|
422
|
+
if (configFilePath) config.watchOptions.ignored.push(configFilePath);
|
|
423
|
+
} else {
|
|
424
|
+
config.watch = false;
|
|
425
|
+
config.watchOptions ??= {};
|
|
426
|
+
config.watchOptions.ignored = '**/**';
|
|
427
|
+
const sourceEntries = await globTestSourceEntries(environment.name);
|
|
428
|
+
config.entry = {
|
|
429
|
+
...setupFiles[environment.name],
|
|
430
|
+
...sourceEntries
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
const autoExternalNodeModules = ({ context, request, dependencyType, getResolve }, callback)=>{
|
|
437
|
+
if (!request) return callback();
|
|
438
|
+
if (request.startsWith('@swc/helpers/')) return callback();
|
|
439
|
+
const doExternal = (externalPath = request)=>{
|
|
440
|
+
callback(void 0, externalPath, 'commonjs' === dependencyType ? 'commonjs' : 'import');
|
|
441
|
+
};
|
|
442
|
+
const resolver = getResolve?.();
|
|
443
|
+
if (!resolver) return callback();
|
|
444
|
+
resolver(context, request, (err, resolvePath)=>{
|
|
445
|
+
if (err) return callback();
|
|
446
|
+
if (resolvePath && /node_modules/.test(resolvePath)) return doExternal(resolvePath);
|
|
447
|
+
return callback();
|
|
448
|
+
});
|
|
449
|
+
};
|
|
450
|
+
function autoExternalNodeBuiltin({ request, dependencyType }, callback) {
|
|
451
|
+
if (!request) return void callback();
|
|
452
|
+
const isNodeBuiltin = isBuiltin(request) || ADDITIONAL_NODE_BUILTINS.some((builtin)=>{
|
|
453
|
+
if ('string' == typeof builtin) return builtin === request;
|
|
454
|
+
return builtin.test(request);
|
|
455
|
+
});
|
|
456
|
+
if (isNodeBuiltin) callback(void 0, request, 'commonjs' === dependencyType ? 'commonjs' : 'module-import');
|
|
457
|
+
else callback();
|
|
458
|
+
}
|
|
459
|
+
const pluginExternal = (context)=>({
|
|
460
|
+
name: 'rstest:external',
|
|
461
|
+
setup: (api)=>{
|
|
462
|
+
api.modifyEnvironmentConfig(async (config, { mergeEnvironmentConfig, name })=>{
|
|
463
|
+
const { normalizedConfig: { testEnvironment } } = context.projects.find((p)=>p.environmentName === name);
|
|
464
|
+
return mergeEnvironmentConfig(config, {
|
|
465
|
+
output: {
|
|
466
|
+
externals: 'node' === testEnvironment ? [
|
|
467
|
+
autoExternalNodeModules
|
|
468
|
+
] : void 0
|
|
469
|
+
},
|
|
470
|
+
tools: {
|
|
471
|
+
rspack: (config)=>{
|
|
472
|
+
config.externals = castArray(config.externals) || [];
|
|
473
|
+
config.externals.unshift({
|
|
474
|
+
'@rstest/core': 'global @rstest/core'
|
|
475
|
+
});
|
|
476
|
+
config.externalsPresets ??= {};
|
|
477
|
+
config.externalsPresets.node = false;
|
|
478
|
+
config.externals.push(autoExternalNodeBuiltin);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
class IgnoreModuleNotFoundErrorPlugin {
|
|
486
|
+
apply(compiler) {
|
|
487
|
+
compiler.hooks.done.tap('Rstest:IgnoreModuleNotFoundPlugin', (stats)=>{
|
|
488
|
+
for(let i = stats.compilation.errors.length - 1; i >= 0; i--)if (/Module not found/.test(stats.compilation.errors[i].message)) stats.compilation.errors.splice(i, 1);
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
const pluginIgnoreResolveError = {
|
|
493
|
+
name: 'rstest:ignore-resolve-error',
|
|
494
|
+
setup: (api)=>{
|
|
495
|
+
api.modifyRspackConfig(async (config)=>{
|
|
496
|
+
config.plugins.push(new IgnoreModuleNotFoundErrorPlugin());
|
|
497
|
+
config.optimization ??= {};
|
|
498
|
+
config.optimization.emitOnErrors = true;
|
|
499
|
+
config.ignoreWarnings ??= [];
|
|
500
|
+
config.ignoreWarnings.push(/Module not found/);
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
const enable = void 0 !== node_inspector.url();
|
|
505
|
+
const pluginInspect = ()=>enable ? {
|
|
506
|
+
name: 'rstest:inspect',
|
|
507
|
+
setup: (api)=>{
|
|
508
|
+
api.modifyRspackConfig(async (config)=>{
|
|
509
|
+
config.devtool = 'inline-nosources-source-map';
|
|
510
|
+
config.optimization ??= {};
|
|
511
|
+
config.optimization.splitChunks = {
|
|
512
|
+
...config.optimization.splitChunks || {},
|
|
513
|
+
maxSize: 1048576,
|
|
514
|
+
chunks: 'all'
|
|
515
|
+
};
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
} : null;
|
|
519
|
+
const external_node_fs_ = __webpack_require__("node:fs");
|
|
520
|
+
const mockRuntime_dirname = external_node_path_["default"].dirname(fileURLToPath(import.meta.url));
|
|
521
|
+
class MockRuntimeRspackPlugin {
|
|
522
|
+
apply(compiler) {
|
|
523
|
+
const { RuntimeModule } = compiler.webpack;
|
|
524
|
+
class RetestImportRuntimeModule extends RuntimeModule {
|
|
525
|
+
constructor(){
|
|
526
|
+
super('rstest runtime');
|
|
527
|
+
}
|
|
528
|
+
generate() {
|
|
529
|
+
const code = external_node_fs_["default"].readFileSync(external_node_path_["default"].join(mockRuntime_dirname, './mockRuntimeCode.js'), 'utf8');
|
|
530
|
+
return code;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
compiler.hooks.compilation.tap('RstestMockPlugin', (compilation)=>{
|
|
534
|
+
compilation.hooks.runtimeModule.tap('RstestMockChunkLoadingRuntimePlugin', (module)=>{
|
|
535
|
+
if ('require_chunk_loading' === module.name) {
|
|
536
|
+
const finalSource = module.source.source.toString('utf-8').replace('for (var moduleId in moreModules) {', "for (var moduleId in moreModules) {\n if (Object.keys(__webpack_require__.rstest_original_modules).includes(moduleId)) continue;");
|
|
537
|
+
module.source.source = Buffer.from(finalSource);
|
|
538
|
+
}
|
|
539
|
+
if ('define_property_getters' === module.name) {
|
|
540
|
+
const finalSource = module.source.source.toString('utf-8').replace('enumerable: true, get:', 'enumerable: true, configurable: true, get:');
|
|
541
|
+
module.source.source = Buffer.from(finalSource);
|
|
542
|
+
}
|
|
543
|
+
});
|
|
544
|
+
});
|
|
545
|
+
compiler.hooks.thisCompilation.tap('RstestMockPlugin', (compilation)=>{
|
|
546
|
+
compilation.hooks.additionalTreeRuntimeRequirements.tap('RstestAddMockRuntimePlugin', (chunk)=>{
|
|
547
|
+
compilation.addRuntimeModule(chunk, new RetestImportRuntimeModule());
|
|
548
|
+
});
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
const pluginMockRuntime = {
|
|
553
|
+
name: 'rstest:mock-runtime',
|
|
554
|
+
setup: (api)=>{
|
|
555
|
+
api.modifyRspackConfig(async (config)=>{
|
|
556
|
+
config.plugins.push(new MockRuntimeRspackPlugin());
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
class RstestCacheControlPlugin {
|
|
561
|
+
apply(compiler) {
|
|
562
|
+
const { RuntimeModule } = compiler.webpack;
|
|
563
|
+
class RetestCacheControlModule extends RuntimeModule {
|
|
564
|
+
constructor(){
|
|
565
|
+
super('rstest_cache_control');
|
|
566
|
+
}
|
|
567
|
+
generate() {
|
|
568
|
+
return `
|
|
569
|
+
global.setupIds = [];
|
|
570
|
+
|
|
571
|
+
function __rstest_clean_core_cache__() {
|
|
572
|
+
if (typeof __webpack_require__ === 'undefined') {
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
delete __webpack_module_cache__['@rstest/core'];
|
|
576
|
+
|
|
577
|
+
global.setupIds.forEach((id) => {
|
|
578
|
+
delete __webpack_module_cache__[id];
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
global.__rstest_clean_core_cache__ = __rstest_clean_core_cache__;
|
|
583
|
+
`;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
compiler.hooks.thisCompilation.tap('RstestCacheControlPlugin', (compilation)=>{
|
|
587
|
+
compilation.hooks.additionalTreeRuntimeRequirements.tap('RstestAddCacheControlRuntimePlugin', (chunk)=>{
|
|
588
|
+
compilation.addRuntimeModule(chunk, new RetestCacheControlModule());
|
|
589
|
+
});
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
const pluginCacheControl = (setupFiles)=>({
|
|
594
|
+
name: 'rstest:cache-control',
|
|
595
|
+
setup: (api)=>{
|
|
596
|
+
api.transform({
|
|
597
|
+
test: setupFiles
|
|
598
|
+
}, ({ code })=>({
|
|
599
|
+
code: `
|
|
600
|
+
${code}
|
|
601
|
+
if (global.setupIds && __webpack_module__.id) {
|
|
602
|
+
global.setupIds.push(__webpack_module__.id);
|
|
603
|
+
}
|
|
604
|
+
`
|
|
605
|
+
}));
|
|
606
|
+
api.modifyRspackConfig(async (config)=>{
|
|
607
|
+
config.plugins.push(new RstestCacheControlPlugin());
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
});
|
|
611
|
+
const rsbuild_dirname = posix.dirname(fileURLToPath(import.meta.url));
|
|
612
|
+
function parseInlineSourceMapStr(code) {
|
|
613
|
+
const inlineSourceMapRegex = /\/\/# sourceMappingURL=data:application\/json(?:;charset=utf-8)?;base64,(.+)\s*$/m;
|
|
614
|
+
const match = code.match(inlineSourceMapRegex);
|
|
615
|
+
if (!match || !match[1]) return null;
|
|
616
|
+
try {
|
|
617
|
+
const base64Data = match[1];
|
|
618
|
+
const decodedStr = Buffer.from(base64Data, 'base64').toString('utf-8');
|
|
619
|
+
return decodedStr;
|
|
620
|
+
} catch (_error) {
|
|
621
|
+
return null;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
const isMultiCompiler = (compiler)=>'compilers' in compiler && Array.isArray(compiler.compilers);
|
|
625
|
+
const prepareRsbuild = async (context, globTestSourceEntries, setupFiles)=>{
|
|
626
|
+
const { command, normalizedConfig: { isolate, dev = {}, coverage } } = context;
|
|
627
|
+
const debugMode = isDebug();
|
|
628
|
+
logger.level = debugMode ? 'verbose' : 'error';
|
|
629
|
+
const writeToDisk = dev.writeToDisk || debugMode;
|
|
630
|
+
const rsbuildInstance = await createRsbuild({
|
|
631
|
+
callerName: 'rstest',
|
|
632
|
+
config: {
|
|
633
|
+
root: context.rootPath,
|
|
634
|
+
server: {
|
|
635
|
+
printUrls: false,
|
|
636
|
+
strictPort: false,
|
|
637
|
+
middlewareMode: true,
|
|
638
|
+
compress: false,
|
|
639
|
+
cors: false,
|
|
640
|
+
publicDir: false
|
|
641
|
+
},
|
|
642
|
+
dev: {
|
|
643
|
+
hmr: false,
|
|
644
|
+
writeToDisk
|
|
645
|
+
},
|
|
646
|
+
environments: Object.fromEntries(context.projects.map((project)=>[
|
|
647
|
+
project.environmentName,
|
|
648
|
+
{
|
|
649
|
+
plugins: project.normalizedConfig.plugins,
|
|
650
|
+
root: project.rootPath,
|
|
651
|
+
output: {
|
|
652
|
+
target: 'node'
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
])),
|
|
656
|
+
plugins: [
|
|
657
|
+
pluginBasic(context),
|
|
658
|
+
pluginIgnoreResolveError,
|
|
659
|
+
pluginMockRuntime,
|
|
660
|
+
pluginCSSFilter(),
|
|
661
|
+
pluginEntryWatch({
|
|
662
|
+
globTestSourceEntries,
|
|
663
|
+
setupFiles,
|
|
664
|
+
context,
|
|
665
|
+
isWatch: 'watch' === command
|
|
666
|
+
}),
|
|
667
|
+
pluginExternal(context),
|
|
668
|
+
!isolate ? pluginCacheControl(Object.values(setupFiles).flatMap((files)=>Object.values(files))) : null,
|
|
669
|
+
pluginInspect()
|
|
670
|
+
].filter(Boolean)
|
|
671
|
+
}
|
|
672
|
+
});
|
|
673
|
+
if (coverage?.enabled && 'list' !== command) {
|
|
674
|
+
const { loadCoverageProvider } = await import("./603.js").then((mod)=>({
|
|
675
|
+
loadCoverageProvider: mod.loadCoverageProvider
|
|
676
|
+
}));
|
|
677
|
+
const { pluginCoverageCore } = await import("./0~836.js").then((mod)=>({
|
|
678
|
+
pluginCoverageCore: mod.pluginCoverageCore
|
|
679
|
+
}));
|
|
680
|
+
const { pluginCoverage } = await loadCoverageProvider(coverage, context.rootPath);
|
|
681
|
+
coverage.exclude.push(...Object.values(setupFiles).flatMap((files)=>Object.values(files)));
|
|
682
|
+
rsbuildInstance.addPlugins([
|
|
683
|
+
pluginCoverage(coverage),
|
|
684
|
+
pluginCoverageCore(coverage)
|
|
685
|
+
]);
|
|
686
|
+
}
|
|
687
|
+
return rsbuildInstance;
|
|
688
|
+
};
|
|
689
|
+
const calcEntriesToRerun = (entries, chunks, buildData, runtimeChunkName)=>{
|
|
690
|
+
const entryToChunkHashesMap = new Map();
|
|
691
|
+
const buildChunkHashes = (entry)=>{
|
|
692
|
+
const validChunks = (entry.chunks || []).filter((chunk)=>chunk !== runtimeChunkName);
|
|
693
|
+
validChunks.forEach((chunkName)=>{
|
|
694
|
+
const chunkInfo = chunks?.find((c)=>c.names?.includes(chunkName));
|
|
695
|
+
if (chunkInfo) {
|
|
696
|
+
const existing = entryToChunkHashesMap.get(entry.testPath) || {};
|
|
697
|
+
existing[chunkName] = chunkInfo.hash ?? '';
|
|
698
|
+
entryToChunkHashesMap.set(entry.testPath, existing);
|
|
699
|
+
}
|
|
700
|
+
});
|
|
701
|
+
};
|
|
702
|
+
(entries || []).forEach(buildChunkHashes);
|
|
703
|
+
const entryToChunkHashes = Array.from(entryToChunkHashesMap.entries()).map(([name, chunks])=>({
|
|
704
|
+
name,
|
|
705
|
+
chunks
|
|
706
|
+
}));
|
|
707
|
+
const affectedTestPaths = new Set();
|
|
708
|
+
const deletedEntries = [];
|
|
709
|
+
if (buildData.entryToChunkHashes) {
|
|
710
|
+
const prevMap = new Map(buildData.entryToChunkHashes.map((e)=>[
|
|
711
|
+
e.name,
|
|
712
|
+
e.chunks
|
|
713
|
+
]));
|
|
714
|
+
const currentNames = new Set(entryToChunkHashesMap.keys());
|
|
715
|
+
deletedEntries.push(...Array.from(prevMap.keys()).filter((name)=>!currentNames.has(name)));
|
|
716
|
+
const findAffectedEntry = (testPath)=>{
|
|
717
|
+
const currentChunks = entryToChunkHashesMap.get(testPath);
|
|
718
|
+
const prevChunks = prevMap.get(testPath);
|
|
719
|
+
if (!currentChunks) return;
|
|
720
|
+
if (!prevChunks) return void affectedTestPaths.add(testPath);
|
|
721
|
+
const hasChanges = Object.entries(currentChunks).some(([chunkName, hash])=>prevChunks[chunkName] !== hash);
|
|
722
|
+
if (hasChanges) affectedTestPaths.add(testPath);
|
|
723
|
+
};
|
|
724
|
+
entryToChunkHashesMap.forEach((_, testPath)=>{
|
|
725
|
+
findAffectedEntry(testPath);
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
buildData.entryToChunkHashes = entryToChunkHashes;
|
|
729
|
+
const affectedEntries = Array.from(affectedTestPaths).map((testPath)=>entries.find((e)=>e.testPath === testPath)).filter((entry)=>void 0 !== entry);
|
|
730
|
+
return {
|
|
731
|
+
affectedEntries,
|
|
732
|
+
deletedEntries
|
|
733
|
+
};
|
|
734
|
+
};
|
|
735
|
+
class AssetsMemorySafeMap extends Map {
|
|
736
|
+
set(key, value) {
|
|
737
|
+
if (this.has(key)) return this;
|
|
738
|
+
if (!memory_isMemorySufficient()) this.clear();
|
|
739
|
+
return super.set(key, value);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
const createRsbuildServer = async ({ globTestSourceEntries, setupFiles, rsbuildInstance, inspectedConfig })=>{
|
|
743
|
+
let rspackCompiler;
|
|
744
|
+
const rstestCompilerPlugin = {
|
|
745
|
+
name: 'rstest:compiler',
|
|
746
|
+
setup: (api)=>{
|
|
747
|
+
api.modifyBundlerChain((chain)=>{
|
|
748
|
+
chain.module.rule('rstest-mock-module-doppelgangers').test(/\.(?:js|jsx|mjs|cjs|ts|tsx|mts|cts)$/).with({
|
|
749
|
+
rstest: 'importActual'
|
|
750
|
+
}).use('import-actual-loader').loader(posix.resolve(rsbuild_dirname, './importActualLoader.mjs')).end();
|
|
751
|
+
});
|
|
752
|
+
api.onAfterCreateCompiler(({ compiler })=>{
|
|
753
|
+
rspackCompiler = compiler;
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
};
|
|
757
|
+
rsbuildInstance.addPlugins([
|
|
758
|
+
rstestCompilerPlugin
|
|
759
|
+
]);
|
|
760
|
+
const devServer = await rsbuildInstance.createDevServer({
|
|
761
|
+
getPortSilently: true
|
|
762
|
+
});
|
|
763
|
+
if (isDebug()) await rsbuildInstance.inspectConfig({
|
|
764
|
+
writeToDisk: true,
|
|
765
|
+
extraConfigs: {
|
|
766
|
+
rstest: inspectedConfig
|
|
767
|
+
}
|
|
768
|
+
});
|
|
769
|
+
if (!rspackCompiler) throw new Error('rspackCompiler was not initialized');
|
|
770
|
+
const outputFileSystem = isMultiCompiler(rspackCompiler) ? rspackCompiler.compilers[0].outputFileSystem : rspackCompiler.outputFileSystem;
|
|
771
|
+
if (!outputFileSystem) throw new Error(`Expect outputFileSystem to be defined, but got ${outputFileSystem}`);
|
|
772
|
+
const readFile = async (fileName)=>new Promise((resolve, reject)=>{
|
|
773
|
+
outputFileSystem.readFile(fileName, (err, data)=>{
|
|
774
|
+
if (err) reject(err);
|
|
775
|
+
resolve('string' == typeof data ? data : data.toString());
|
|
776
|
+
});
|
|
777
|
+
});
|
|
778
|
+
const buildData = {};
|
|
779
|
+
const getEntryFiles = async (manifest, outputPath)=>{
|
|
780
|
+
const entryFiles = {};
|
|
781
|
+
const entries = Object.keys(manifest.entries);
|
|
782
|
+
for (const entry of entries){
|
|
783
|
+
const data = manifest.entries[entry];
|
|
784
|
+
entryFiles[entry] = ((data?.initial?.js || []).concat(data?.async?.js || []) || []).map((file)=>posix.join(outputPath, file));
|
|
785
|
+
}
|
|
786
|
+
return entryFiles;
|
|
787
|
+
};
|
|
788
|
+
const getRsbuildStats = async ({ environmentName, fileFilters })=>{
|
|
789
|
+
const stats = await devServer.environments[environmentName].getStats();
|
|
790
|
+
const enableAssetsCache = memory_isMemorySufficient();
|
|
791
|
+
const manifest = devServer.environments[environmentName].context.manifest;
|
|
792
|
+
const { entrypoints, outputPath, assets, hash, chunks } = stats.toJson({
|
|
793
|
+
all: false,
|
|
794
|
+
hash: true,
|
|
795
|
+
entrypoints: true,
|
|
796
|
+
outputPath: true,
|
|
797
|
+
assets: true,
|
|
798
|
+
relatedAssets: true,
|
|
799
|
+
cachedAssets: true,
|
|
800
|
+
chunks: true,
|
|
801
|
+
timings: true
|
|
802
|
+
});
|
|
803
|
+
const entryFiles = await getEntryFiles(manifest, outputPath);
|
|
804
|
+
const entries = [];
|
|
805
|
+
const setupEntries = [];
|
|
806
|
+
const sourceEntries = await globTestSourceEntries(environmentName);
|
|
807
|
+
for (const entry of Object.keys(entrypoints)){
|
|
808
|
+
const e = entrypoints[entry];
|
|
809
|
+
const distPath = posix.join(outputPath, e.assets[e.assets.length - 1].name);
|
|
810
|
+
if (setupFiles[environmentName][entry]) setupEntries.push({
|
|
811
|
+
distPath,
|
|
812
|
+
testPath: setupFiles[environmentName][entry],
|
|
813
|
+
files: entryFiles[entry],
|
|
814
|
+
chunks: e.chunks || []
|
|
815
|
+
});
|
|
816
|
+
else if (sourceEntries[entry]) {
|
|
817
|
+
if (fileFilters?.length && !fileFilters.includes(sourceEntries[entry])) continue;
|
|
818
|
+
entries.push({
|
|
819
|
+
distPath,
|
|
820
|
+
testPath: sourceEntries[entry],
|
|
821
|
+
files: entryFiles[entry],
|
|
822
|
+
chunks: e.chunks || []
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
const inlineSourceMap = 'inline-source-map' === stats.compilation.options.devtool;
|
|
827
|
+
const sourceMapPaths = Object.fromEntries(assets.map((asset)=>{
|
|
828
|
+
const assetFilePath = posix.join(outputPath, asset.name);
|
|
829
|
+
if (inlineSourceMap) return [
|
|
830
|
+
assetFilePath,
|
|
831
|
+
assetFilePath
|
|
832
|
+
];
|
|
833
|
+
const sourceMapPath = asset?.info.related?.sourceMap?.[0];
|
|
834
|
+
if (sourceMapPath) {
|
|
835
|
+
const filePath = posix.join(outputPath, sourceMapPath);
|
|
836
|
+
return [
|
|
837
|
+
assetFilePath,
|
|
838
|
+
filePath
|
|
839
|
+
];
|
|
840
|
+
}
|
|
841
|
+
return [
|
|
842
|
+
assetFilePath,
|
|
843
|
+
null
|
|
844
|
+
];
|
|
845
|
+
}));
|
|
846
|
+
buildData[environmentName] ??= {};
|
|
847
|
+
const { affectedEntries, deletedEntries } = calcEntriesToRerun(entries, chunks, buildData[environmentName], `${environmentName}-${RUNTIME_CHUNK_NAME}`);
|
|
848
|
+
const cachedAssetFiles = new AssetsMemorySafeMap();
|
|
849
|
+
const cachedSourceMaps = new AssetsMemorySafeMap();
|
|
850
|
+
const readFileWithCache = async (name)=>{
|
|
851
|
+
if (enableAssetsCache && cachedAssetFiles.has(name)) return cachedAssetFiles.get(name);
|
|
852
|
+
const content = await readFile(name);
|
|
853
|
+
enableAssetsCache && cachedAssetFiles.set(name, content);
|
|
854
|
+
return content;
|
|
855
|
+
};
|
|
856
|
+
const getSourceMap = async (name)=>{
|
|
857
|
+
const sourceMapPath = sourceMapPaths[name];
|
|
858
|
+
if (!sourceMapPath) return null;
|
|
859
|
+
if (enableAssetsCache && cachedSourceMaps.has(name)) return cachedSourceMaps.get(name);
|
|
860
|
+
let content = null;
|
|
861
|
+
if (inlineSourceMap) {
|
|
862
|
+
const file = await readFile(sourceMapPath);
|
|
863
|
+
content = parseInlineSourceMapStr(file);
|
|
864
|
+
} else {
|
|
865
|
+
const sourceMap = await readFile(sourceMapPath);
|
|
866
|
+
content = sourceMap;
|
|
867
|
+
}
|
|
868
|
+
enableAssetsCache && content && cachedSourceMaps.set(name, content);
|
|
869
|
+
return content;
|
|
870
|
+
};
|
|
871
|
+
const assetNames = assets.map((asset)=>posix.join(outputPath, asset.name));
|
|
872
|
+
return {
|
|
873
|
+
affectedEntries,
|
|
874
|
+
deletedEntries,
|
|
875
|
+
hash,
|
|
876
|
+
entries,
|
|
877
|
+
setupEntries,
|
|
878
|
+
assetNames,
|
|
879
|
+
getAssetFiles: async (names)=>Object.fromEntries(await Promise.all(names.map(async (name)=>{
|
|
880
|
+
const content = await readFileWithCache(name);
|
|
881
|
+
return [
|
|
882
|
+
name,
|
|
883
|
+
content
|
|
884
|
+
];
|
|
885
|
+
}))),
|
|
886
|
+
getSourceMaps: async (names)=>Object.fromEntries(await Promise.all(names.map(async (name)=>{
|
|
887
|
+
const content = await getSourceMap(name);
|
|
888
|
+
return [
|
|
889
|
+
name,
|
|
890
|
+
content
|
|
891
|
+
];
|
|
892
|
+
})))
|
|
893
|
+
};
|
|
894
|
+
};
|
|
895
|
+
return {
|
|
896
|
+
closeServer: devServer.close,
|
|
897
|
+
getRsbuildStats
|
|
898
|
+
};
|
|
899
|
+
};
|
|
900
|
+
export { createPool, createRsbuildServer, prepareRsbuild };
|