@jsenv/test 2.1.3 → 3.0.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.
- package/README.md +2 -1
- package/dist/js/exception.js +908 -0
- package/dist/js/execute_using_dynamic_import.js +76 -167
- package/dist/js/v8_coverage.js +4 -482
- package/dist/jsenv_test.js +4608 -2917
- package/dist/node_child_process_controlled.mjs +95 -76
- package/dist/node_worker_thread_controlled.mjs +72 -54
- package/package.json +23 -14
- package/src/coverage/generate_coverage.js +186 -0
- package/src/coverage/list_files_not_covered.js +2 -2
- package/src/coverage/missing_coverage.js +2 -2
- package/src/coverage/report_coverage_as_html.js +45 -0
- package/src/coverage/report_coverage_as_json.js +20 -0
- package/src/coverage/{coverage_reporter_text_log.js → report_coverage_in_console.js} +13 -7
- package/src/coverage/v8_and_istanbul.js +4 -4
- package/src/coverage/v8_coverage.js +2 -2
- package/src/execution/exception.js +151 -68
- package/src/execution/execute.js +24 -11
- package/src/execution/execute_test_plan.js +834 -750
- package/src/execution/format_error_for_terminal.js +187 -0
- package/src/execution/github_annotation_from_error.js +3 -3
- package/src/execution/junit_xml_file/report_as_junit_xml.js +149 -0
- package/src/execution/junit_xml_file/xml_generator.js +141 -0
- package/src/execution/reporters/reporter_list.js +687 -0
- package/src/execution/run.js +92 -30
- package/src/execution/web_server/start_using_command.js +2 -2
- package/src/execution/web_server_param.js +5 -5
- package/src/helpers/cpu_usage.js +142 -0
- package/src/helpers/cpu_usage.test_manual.js +7 -0
- package/src/main.js +8 -0
- package/src/runtime_browsers/chromium.js +1 -3
- package/src/runtime_browsers/firefox.js +0 -3
- package/src/runtime_browsers/middleware_istanbul.js +2 -2
- package/src/runtime_browsers/using_playwright.js +296 -220
- package/src/runtime_browsers/webkit.js +0 -3
- package/src/runtime_node/execute_using_dynamic_import.js +75 -28
- package/src/runtime_node/node_child_process.js +250 -139
- package/src/runtime_node/node_child_process_controlled.mjs +94 -75
- package/src/runtime_node/node_worker_thread.js +206 -120
- package/src/runtime_node/node_worker_thread_controlled.mjs +70 -53
- package/src/coverage/coverage_reporter_html_directory.js +0 -32
- package/src/coverage/coverage_reporter_json_file.js +0 -17
- package/src/coverage/report_to_coverage.js +0 -198
- package/src/execution/execution_colors.js +0 -10
- package/src/execution/execution_steps.js +0 -65
- package/src/execution/logs_file_execution.js +0 -495
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { urlToRelativeUrl } from "@jsenv/urls";
|
|
4
|
+
import { ensureEmptyDirectorySync } from "@jsenv/filesystem";
|
|
5
|
+
|
|
6
|
+
import { importWithRequire } from "../helpers/import_with_require.js";
|
|
7
|
+
import { istanbulCoverageMapFromCoverage } from "./istanbul_coverage_map_from_coverage.js";
|
|
8
|
+
|
|
9
|
+
export const reportCoverageAsHtml = (
|
|
10
|
+
testPlanResult,
|
|
11
|
+
directoryUrl,
|
|
12
|
+
{ skipEmpty, skipFull } = {},
|
|
13
|
+
) => {
|
|
14
|
+
if (testPlanResult.aborted) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const testPlanCoverage = testPlanResult.coverage;
|
|
18
|
+
if (!testPlanCoverage) {
|
|
19
|
+
// TODO
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const { rootDirectoryUrl } = testPlanResult;
|
|
23
|
+
ensureEmptyDirectorySync(directoryUrl);
|
|
24
|
+
const coverageHtmlDirectoryRelativeUrl = urlToRelativeUrl(
|
|
25
|
+
directoryUrl,
|
|
26
|
+
rootDirectoryUrl,
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const libReport = importWithRequire("istanbul-lib-report");
|
|
30
|
+
const reports = importWithRequire("istanbul-reports");
|
|
31
|
+
const context = libReport.createContext({
|
|
32
|
+
dir: fileURLToPath(rootDirectoryUrl),
|
|
33
|
+
coverageMap: istanbulCoverageMapFromCoverage(testPlanCoverage),
|
|
34
|
+
sourceFinder: (path) =>
|
|
35
|
+
readFileSync(new URL(path, rootDirectoryUrl), "utf8"),
|
|
36
|
+
});
|
|
37
|
+
const report = reports.create("html", {
|
|
38
|
+
skipEmpty,
|
|
39
|
+
skipFull,
|
|
40
|
+
subdir: coverageHtmlDirectoryRelativeUrl,
|
|
41
|
+
});
|
|
42
|
+
report.execute(context);
|
|
43
|
+
// const htmlCoverageDirectoryIndexFileUrl = `${directoryUrl}index.html`;
|
|
44
|
+
// console.log(`-> ${urlToFileSystemPath(htmlCoverageDirectoryIndexFileUrl)}`);
|
|
45
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { urlToFileSystemPath } from "@jsenv/urls";
|
|
2
|
+
import { writeFileSync } from "@jsenv/filesystem";
|
|
3
|
+
import { inspectFileSize } from "@jsenv/inspect";
|
|
4
|
+
|
|
5
|
+
export const reportCoverageAsJson = (testPlanResult, fileUrl) => {
|
|
6
|
+
if (testPlanResult.aborted) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
const testPlanCoverage = testPlanResult.coverage;
|
|
10
|
+
if (!testPlanCoverage) {
|
|
11
|
+
// TODO
|
|
12
|
+
}
|
|
13
|
+
const coverageAsText = JSON.stringify(testPlanCoverage, null, " ");
|
|
14
|
+
writeFileSync(fileUrl, coverageAsText);
|
|
15
|
+
console.log(
|
|
16
|
+
`-> ${urlToFileSystemPath(fileUrl)} (${inspectFileSize(
|
|
17
|
+
Buffer.byteLength(coverageAsText),
|
|
18
|
+
)})`,
|
|
19
|
+
);
|
|
20
|
+
};
|
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
import { importWithRequire } from "../helpers/import_with_require.js";
|
|
2
2
|
import { istanbulCoverageMapFromCoverage } from "./istanbul_coverage_map_from_coverage.js";
|
|
3
3
|
|
|
4
|
-
export const
|
|
5
|
-
|
|
6
|
-
{
|
|
4
|
+
export const reportCoverageInConsole = (
|
|
5
|
+
testPlanResult,
|
|
6
|
+
{ skipEmpty, skipFull } = {},
|
|
7
7
|
) => {
|
|
8
|
+
if (testPlanResult.aborted) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const testPlanCoverage = testPlanResult.coverage;
|
|
12
|
+
if (!testPlanCoverage) {
|
|
13
|
+
// TODO
|
|
14
|
+
}
|
|
8
15
|
const libReport = importWithRequire("istanbul-lib-report");
|
|
9
16
|
const reports = importWithRequire("istanbul-reports");
|
|
10
|
-
|
|
11
17
|
const context = libReport.createContext({
|
|
12
|
-
coverageMap: istanbulCoverageMapFromCoverage(
|
|
18
|
+
coverageMap: istanbulCoverageMapFromCoverage(testPlanCoverage),
|
|
13
19
|
});
|
|
14
20
|
const report = reports.create("text", {
|
|
15
|
-
skipEmpty
|
|
16
|
-
skipFull
|
|
21
|
+
skipEmpty,
|
|
22
|
+
skipFull,
|
|
17
23
|
});
|
|
18
24
|
report.execute(context);
|
|
19
25
|
};
|
|
@@ -3,7 +3,7 @@ import { createDetailedMessage } from "@jsenv/log";
|
|
|
3
3
|
export const composeV8AndIstanbul = (
|
|
4
4
|
v8FileByFileCoverage,
|
|
5
5
|
istanbulFileByFileCoverage,
|
|
6
|
-
{
|
|
6
|
+
{ v8ConflictWarning },
|
|
7
7
|
) => {
|
|
8
8
|
const fileByFileCoverage = {};
|
|
9
9
|
const v8Files = Object.keys(v8FileByFileCoverage);
|
|
@@ -15,15 +15,15 @@ export const composeV8AndIstanbul = (
|
|
|
15
15
|
istanbulFiles.forEach((key) => {
|
|
16
16
|
const v8Coverage = v8FileByFileCoverage[key];
|
|
17
17
|
if (v8Coverage) {
|
|
18
|
-
if (
|
|
18
|
+
if (v8ConflictWarning) {
|
|
19
19
|
console.warn(
|
|
20
20
|
createDetailedMessage(
|
|
21
21
|
`Coverage conflict on "${key}", found two coverage that cannot be merged together: v8 and istanbul. The istanbul coverage will be ignored.`,
|
|
22
22
|
{
|
|
23
23
|
"details": `This happens when a file is executed on a runtime using v8 coverage (node or chromium) and on runtime using istanbul coverage (firefox or webkit)`,
|
|
24
24
|
"suggestion":
|
|
25
|
-
"disable this warning with
|
|
26
|
-
"suggestion 2": `force coverage using istanbul with
|
|
25
|
+
"disable this warning with coverage.v8ConflictWarning: false",
|
|
26
|
+
"suggestion 2": `force coverage using istanbul with coverage.methodForBrowsers: "istanbul"`,
|
|
27
27
|
},
|
|
28
28
|
),
|
|
29
29
|
);
|
|
@@ -2,10 +2,10 @@ import { URL_META } from "@jsenv/url-meta";
|
|
|
2
2
|
|
|
3
3
|
export const filterV8Coverage = async (
|
|
4
4
|
v8Coverage,
|
|
5
|
-
{ rootDirectoryUrl,
|
|
5
|
+
{ rootDirectoryUrl, coverageInclude },
|
|
6
6
|
) => {
|
|
7
7
|
const associations = URL_META.resolveAssociations(
|
|
8
|
-
{ cover:
|
|
8
|
+
{ cover: coverageInclude },
|
|
9
9
|
rootDirectoryUrl,
|
|
10
10
|
);
|
|
11
11
|
const urlShouldBeCovered = (url) => {
|
|
@@ -17,7 +17,15 @@
|
|
|
17
17
|
* The browser part can be found in "supervisor.js"
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
// https://github.com/marvinhagemeister/errorstacks/tree/main
|
|
21
|
+
// https://cdn.jsdelivr.net/npm/errorstacks@latest/dist/esm/index.mjs
|
|
22
|
+
import { parseStackTrace } from "errorstacks";
|
|
23
|
+
import { URL_META } from "@jsenv/url-meta";
|
|
24
|
+
|
|
25
|
+
const isDev = process.execArgv.includes("--conditions=development");
|
|
26
|
+
const jsenvCoreDirectoryUrl = new URL("../../../../../", import.meta.url);
|
|
27
|
+
|
|
28
|
+
export const createException = (reason, { rootDirectoryUrl } = {}) => {
|
|
21
29
|
const exception = {
|
|
22
30
|
isException: true,
|
|
23
31
|
isError: false,
|
|
@@ -25,6 +33,7 @@ export const createException = (reason) => {
|
|
|
25
33
|
message: "",
|
|
26
34
|
stack: "",
|
|
27
35
|
stackTrace: "",
|
|
36
|
+
stackFrames: undefined,
|
|
28
37
|
site: null,
|
|
29
38
|
};
|
|
30
39
|
|
|
@@ -32,88 +41,162 @@ export const createException = (reason) => {
|
|
|
32
41
|
exception.message = "undefined";
|
|
33
42
|
return exception;
|
|
34
43
|
}
|
|
35
|
-
if (reason ===
|
|
36
|
-
exception.message = "
|
|
44
|
+
if (reason === null) {
|
|
45
|
+
exception.message = "null";
|
|
37
46
|
return exception;
|
|
38
47
|
}
|
|
39
48
|
if (typeof reason === "string") {
|
|
40
49
|
exception.message = reason;
|
|
41
50
|
return exception;
|
|
42
51
|
}
|
|
43
|
-
if (reason
|
|
44
|
-
exception.
|
|
45
|
-
exception.name = reason.name;
|
|
46
|
-
exception.message = reason.message;
|
|
47
|
-
const stackInfo = getStackInfo(reason);
|
|
48
|
-
if (stackInfo) {
|
|
49
|
-
const { stackTrace, stackObject } = stackInfo;
|
|
50
|
-
exception.stackTrace = stackTrace;
|
|
51
|
-
const [firstCallSite] = stackObject;
|
|
52
|
-
writePropertiesFromCallSite(exception, firstCallSite);
|
|
53
|
-
}
|
|
54
|
-
exception.stack = reason.stack;
|
|
55
|
-
return exception;
|
|
56
|
-
}
|
|
57
|
-
if (typeof reason === "object") {
|
|
58
|
-
exception.code = reason.code;
|
|
59
|
-
exception.message = reason.message;
|
|
60
|
-
exception.stack = reason.stack;
|
|
52
|
+
if (typeof reason !== "object") {
|
|
53
|
+
exception.message = JSON.stringify(reason);
|
|
61
54
|
return exception;
|
|
62
55
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
};
|
|
56
|
+
if (reason.stackFrames === undefined && "stack" in reason) {
|
|
57
|
+
let stackFrames;
|
|
66
58
|
|
|
67
|
-
const getStackInfo = (reason) => {
|
|
68
|
-
if (reason instanceof Error) {
|
|
69
59
|
const { prepareStackTrace } = Error;
|
|
70
|
-
|
|
71
|
-
let stackObject;
|
|
72
|
-
Error.prepareStackTrace = (e, secondArg) => {
|
|
60
|
+
Error.prepareStackTrace = (e, callSites) => {
|
|
73
61
|
Error.prepareStackTrace = prepareStackTrace;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
62
|
+
|
|
63
|
+
stackFrames = [];
|
|
64
|
+
for (const callSite of callSites) {
|
|
65
|
+
const stackFrame = {
|
|
66
|
+
raw: ` at ${String(callSite)}`,
|
|
67
|
+
url: callSite.getFileName() || callSite.getScriptNameOrSourceURL(),
|
|
68
|
+
line: callSite.getLineNumber(),
|
|
69
|
+
column: callSite.getColumnNumber(),
|
|
70
|
+
functionName: callSite.getFunctionName(),
|
|
71
|
+
isNative: callSite.isNative(),
|
|
72
|
+
isEval: callSite.isEval(),
|
|
73
|
+
isConstructor: callSite.isConstructor(),
|
|
74
|
+
isAsync: callSite.isAsync(),
|
|
75
|
+
evalSite: null,
|
|
76
|
+
};
|
|
77
|
+
if (stackFrame.isEval) {
|
|
78
|
+
const evalOrigin = stackFrame.getEvalOrigin();
|
|
79
|
+
if (evalOrigin) {
|
|
80
|
+
stackFrame.evalSite = getPropertiesFromEvalOrigin(evalOrigin);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
stackFrames.push(stackFrame);
|
|
81
84
|
}
|
|
82
|
-
return
|
|
85
|
+
return "";
|
|
83
86
|
};
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
exception.stack = reason.stack;
|
|
88
|
+
if (stackFrames === undefined) {
|
|
89
|
+
// Error.prepareStackTrace not trigerred
|
|
90
|
+
// - reason is not an error
|
|
91
|
+
// - reason.stack already get
|
|
92
|
+
Error.prepareStackTrace = prepareStackTrace;
|
|
93
|
+
|
|
94
|
+
const calls = parseStackTrace(reason.stack);
|
|
95
|
+
stackFrames = [];
|
|
96
|
+
for (const call of calls) {
|
|
97
|
+
if (call.fileName === "") {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
stackFrames.push({
|
|
101
|
+
raw: call.raw,
|
|
102
|
+
functionName: call.name,
|
|
103
|
+
url: call.fileName,
|
|
104
|
+
line: call.line,
|
|
105
|
+
column: call.column,
|
|
106
|
+
native: call.type === "native",
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const stackFramesNonNative = [];
|
|
112
|
+
for (const stackFrame of stackFrames) {
|
|
113
|
+
if (stackFrame.url.startsWith("node:")) {
|
|
114
|
+
stackFrame.native = "node";
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (stackFrame.url.startsWith("file:")) {
|
|
118
|
+
if (rootDirectoryUrl && stackFrame.url.startsWith(rootDirectoryUrl)) {
|
|
119
|
+
stackFramesNonNative.push(stackFrame);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (isDev) {
|
|
124
|
+
// while developing jsenv itself we want to exclude any
|
|
125
|
+
// - src/*
|
|
126
|
+
// - packages/**/src/
|
|
127
|
+
// for the users of jsenv it's easier, we want to exclude
|
|
128
|
+
// - **/node_modules/@jsenv/**
|
|
129
|
+
if (
|
|
130
|
+
URL_META.matches(stackFrame.url, {
|
|
131
|
+
[`${jsenvCoreDirectoryUrl}src/`]: true,
|
|
132
|
+
[`${jsenvCoreDirectoryUrl}packages/**/src/`]: true,
|
|
133
|
+
})
|
|
134
|
+
) {
|
|
135
|
+
stackFrame.native = "jsenv";
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
} else if (
|
|
139
|
+
URL_META.matches(stackFrame.url, {
|
|
140
|
+
"file:///**/node_modules/@jsenv/core/": true,
|
|
141
|
+
})
|
|
142
|
+
) {
|
|
143
|
+
stackFrame.native = "jsenv";
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
stackFramesNonNative.push(stackFrame);
|
|
148
|
+
}
|
|
149
|
+
if (stackFramesNonNative.length) {
|
|
150
|
+
stackFrames = stackFramesNonNative;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
reason.stackFrames = stackFrames;
|
|
154
|
+
|
|
155
|
+
let stackTrace = "";
|
|
156
|
+
for (const stackFrame of stackFrames) {
|
|
157
|
+
if (stackTrace) stackTrace += "\n";
|
|
158
|
+
stackTrace += stackFrame.raw;
|
|
159
|
+
}
|
|
160
|
+
reason.stackTrace = stackTrace;
|
|
161
|
+
let stack = "";
|
|
162
|
+
const name = reason.name || "Error";
|
|
163
|
+
const message = reason.message || "";
|
|
164
|
+
stack += `${name}: ${message}`;
|
|
165
|
+
if (stackTrace) {
|
|
166
|
+
stack += `\n${stackTrace}`;
|
|
167
|
+
}
|
|
168
|
+
reason.stack = stack;
|
|
169
|
+
|
|
170
|
+
const [firstCallFrame] = stackFrames;
|
|
171
|
+
if (firstCallFrame && (!reason.site || !reason.site.isInline)) {
|
|
172
|
+
reason.site = firstCallFrame.url
|
|
173
|
+
? {
|
|
174
|
+
url: firstCallFrame.url,
|
|
175
|
+
line: firstCallFrame.line,
|
|
176
|
+
column: firstCallFrame.column,
|
|
177
|
+
}
|
|
178
|
+
: firstCallFrame.evalSite;
|
|
88
179
|
}
|
|
89
|
-
return {
|
|
90
|
-
stackTrace,
|
|
91
|
-
stackObject,
|
|
92
|
-
};
|
|
93
180
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const column = callSite.getColumnNumber() - 1;
|
|
101
|
-
exception.site = {
|
|
102
|
-
url: source,
|
|
103
|
-
line,
|
|
104
|
-
column,
|
|
105
|
-
};
|
|
106
|
-
return;
|
|
181
|
+
// getOwnPropertyNames to catch non enumerable properties on reason
|
|
182
|
+
// (happens mostly when reason is instanceof Error)
|
|
183
|
+
// like .stack, .message
|
|
184
|
+
// some properties are even on the prototype like .name
|
|
185
|
+
for (const ownPropertyName of Object.getOwnPropertyNames(reason)) {
|
|
186
|
+
exception[ownPropertyName] = reason[ownPropertyName];
|
|
107
187
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
188
|
+
const isError = reason instanceof Error;
|
|
189
|
+
exception.isError = isError;
|
|
190
|
+
if (isError) {
|
|
191
|
+
// getOwnPropertyNames is not enough to copy .name and .message
|
|
192
|
+
// on error instances
|
|
193
|
+
exception.name = reason.name;
|
|
194
|
+
exception.message = reason.message;
|
|
114
195
|
}
|
|
196
|
+
return exception;
|
|
115
197
|
};
|
|
116
|
-
|
|
198
|
+
|
|
199
|
+
const getPropertiesFromEvalOrigin = (origin) => {
|
|
117
200
|
// Most eval() calls are in this format
|
|
118
201
|
const topLevelEvalMatch = /^eval at ([^(]+) \((.+):(\d+):(\d+)\)$/.exec(
|
|
119
202
|
origin,
|
|
@@ -122,16 +205,16 @@ const writePropertiesFromEvalOrigin = (exception, origin) => {
|
|
|
122
205
|
const source = topLevelEvalMatch[2];
|
|
123
206
|
const line = Number(topLevelEvalMatch[3]);
|
|
124
207
|
const column = topLevelEvalMatch[4] - 1;
|
|
125
|
-
|
|
208
|
+
return {
|
|
126
209
|
url: source,
|
|
127
210
|
line,
|
|
128
211
|
column,
|
|
129
212
|
};
|
|
130
|
-
return;
|
|
131
213
|
}
|
|
132
214
|
// Parse nested eval() calls using recursion
|
|
133
215
|
const nestedEvalMatch = /^eval at ([^(]+) \((.+)\)$/.exec(origin);
|
|
134
216
|
if (nestedEvalMatch) {
|
|
135
|
-
|
|
217
|
+
return getPropertiesFromEvalOrigin(nestedEvalMatch[2]);
|
|
136
218
|
}
|
|
219
|
+
return null;
|
|
137
220
|
};
|
package/src/execution/execute.js
CHANGED
|
@@ -14,13 +14,14 @@ import { Abort, raceProcessTeardownEvents } from "@jsenv/abort";
|
|
|
14
14
|
import { assertAndNormalizeDirectoryUrl } from "@jsenv/filesystem";
|
|
15
15
|
import { createLogger } from "@jsenv/log";
|
|
16
16
|
|
|
17
|
-
import { createTeardown } from "../helpers/teardown.js";
|
|
18
17
|
import { assertAndNormalizeWebServer } from "./web_server_param.js";
|
|
19
18
|
import { run } from "./run.js";
|
|
20
19
|
|
|
21
20
|
export const execute = async ({
|
|
22
21
|
signal = new AbortController().signal,
|
|
23
22
|
handleSIGINT = true,
|
|
23
|
+
handleSIGUP = true,
|
|
24
|
+
handleSIGTERM = true,
|
|
24
25
|
logLevel,
|
|
25
26
|
rootDirectoryUrl,
|
|
26
27
|
webServer,
|
|
@@ -31,10 +32,12 @@ export const execute = async ({
|
|
|
31
32
|
mirrorConsole = true,
|
|
32
33
|
keepRunning = false,
|
|
33
34
|
|
|
34
|
-
collectConsole,
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
collectConsole = false,
|
|
36
|
+
measureMemoryUsage = false,
|
|
37
|
+
onMeasureMemoryAvailable,
|
|
37
38
|
collectPerformance = false,
|
|
39
|
+
collectCoverage = false,
|
|
40
|
+
coverageTempDirectoryUrl,
|
|
38
41
|
runtime,
|
|
39
42
|
runtimeParams,
|
|
40
43
|
|
|
@@ -45,14 +48,16 @@ export const execute = async ({
|
|
|
45
48
|
rootDirectoryUrl,
|
|
46
49
|
"rootDirectoryUrl",
|
|
47
50
|
);
|
|
48
|
-
const
|
|
51
|
+
const teardownCallbackSet = new Set();
|
|
49
52
|
const executeOperation = Abort.startOperation();
|
|
50
53
|
executeOperation.addAbortSignal(signal);
|
|
51
|
-
if (handleSIGINT) {
|
|
54
|
+
if (handleSIGINT || handleSIGUP || handleSIGTERM) {
|
|
52
55
|
executeOperation.addAbortSource((abort) => {
|
|
53
56
|
return raceProcessTeardownEvents(
|
|
54
57
|
{
|
|
55
|
-
SIGINT:
|
|
58
|
+
SIGINT: handleSIGINT,
|
|
59
|
+
SIGHUP: handleSIGUP,
|
|
60
|
+
SIGTERM: handleSIGTERM,
|
|
56
61
|
},
|
|
57
62
|
abort,
|
|
58
63
|
);
|
|
@@ -60,7 +65,11 @@ export const execute = async ({
|
|
|
60
65
|
}
|
|
61
66
|
|
|
62
67
|
if (runtime.type === "browser") {
|
|
63
|
-
await assertAndNormalizeWebServer(webServer, {
|
|
68
|
+
await assertAndNormalizeWebServer(webServer, {
|
|
69
|
+
signal,
|
|
70
|
+
teardownCallbackSet,
|
|
71
|
+
logger,
|
|
72
|
+
});
|
|
64
73
|
}
|
|
65
74
|
|
|
66
75
|
let resultTransformer = (result) => result;
|
|
@@ -69,7 +78,7 @@ export const execute = async ({
|
|
|
69
78
|
webServer,
|
|
70
79
|
fileRelativeUrl,
|
|
71
80
|
importMap,
|
|
72
|
-
|
|
81
|
+
teardownCallbackSet,
|
|
73
82
|
...runtimeParams,
|
|
74
83
|
};
|
|
75
84
|
|
|
@@ -80,9 +89,11 @@ export const execute = async ({
|
|
|
80
89
|
keepRunning,
|
|
81
90
|
mirrorConsole,
|
|
82
91
|
collectConsole,
|
|
92
|
+
measureMemoryUsage,
|
|
93
|
+
onMeasureMemoryAvailable,
|
|
94
|
+
collectPerformance,
|
|
83
95
|
collectCoverage,
|
|
84
96
|
coverageTempDirectoryUrl,
|
|
85
|
-
collectPerformance,
|
|
86
97
|
runtime,
|
|
87
98
|
runtimeParams,
|
|
88
99
|
});
|
|
@@ -109,7 +120,9 @@ export const execute = async ({
|
|
|
109
120
|
}
|
|
110
121
|
return result;
|
|
111
122
|
} finally {
|
|
112
|
-
|
|
123
|
+
for (const teardownCallback of teardownCallbackSet) {
|
|
124
|
+
await teardownCallback();
|
|
125
|
+
}
|
|
113
126
|
await executeOperation.end();
|
|
114
127
|
}
|
|
115
128
|
};
|