@jsenv/test 1.6.0 → 1.6.2
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/dist/jsenv_test.js
CHANGED
|
@@ -8,9 +8,8 @@ import os from "node:os";
|
|
|
8
8
|
import tty from "node:tty";
|
|
9
9
|
import stringWidth from "string-width";
|
|
10
10
|
import { createRequire } from "node:module";
|
|
11
|
-
import { Worker } from "node:worker_threads";
|
|
12
|
-
import { createServer } from "node:net";
|
|
13
11
|
import { spawn, spawnSync, fork } from "node:child_process";
|
|
12
|
+
import { createServer } from "node:net";
|
|
14
13
|
import v8, { takeCoverage } from "node:v8";
|
|
15
14
|
import stripAnsi from "strip-ansi";
|
|
16
15
|
import { applyBabelPlugins } from "@jsenv/ast";
|
|
@@ -20,6 +19,7 @@ import wrapAnsi from "wrap-ansi";
|
|
|
20
19
|
import { injectSupervisorIntoHTML, supervisorFileUrl } from "@jsenv/plugin-supervisor";
|
|
21
20
|
import { SOURCEMAP, generateSourcemapDataUrl } from "@jsenv/sourcemap";
|
|
22
21
|
import { findFreePort } from "@jsenv/server";
|
|
22
|
+
import { Worker } from "node:worker_threads";
|
|
23
23
|
|
|
24
24
|
/*
|
|
25
25
|
* See callback_race.md
|
|
@@ -2828,89 +2828,6 @@ const pingServer = async (url) => {
|
|
|
2828
2828
|
return false;
|
|
2829
2829
|
};
|
|
2830
2830
|
|
|
2831
|
-
const startServerUsingModuleUrl = async (
|
|
2832
|
-
webServer,
|
|
2833
|
-
{ signal, teardown, logger, allocatedMs },
|
|
2834
|
-
) => {
|
|
2835
|
-
if (!existsSync(new URL(webServer.moduleUrl))) {
|
|
2836
|
-
throw new Error(
|
|
2837
|
-
`webServer.moduleUrl does not lead to a file at "${webServer.moduleUrl}"`,
|
|
2838
|
-
);
|
|
2839
|
-
}
|
|
2840
|
-
const worker = new Worker(
|
|
2841
|
-
new URL(
|
|
2842
|
-
"./worker_importing_module_starting_web_server.mjs",
|
|
2843
|
-
import.meta.url,
|
|
2844
|
-
),
|
|
2845
|
-
{
|
|
2846
|
-
workerData: {
|
|
2847
|
-
url: String(webServer.moduleUrl),
|
|
2848
|
-
},
|
|
2849
|
-
env: {
|
|
2850
|
-
IMPORTED_BY_TEST_PLAN: "1",
|
|
2851
|
-
},
|
|
2852
|
-
stdin: true,
|
|
2853
|
-
stdout: true,
|
|
2854
|
-
},
|
|
2855
|
-
);
|
|
2856
|
-
let errorReceived = false;
|
|
2857
|
-
const errorPromise = new Promise((resolve, reject) => {
|
|
2858
|
-
worker.on("error", (e) => {
|
|
2859
|
-
errorReceived = true;
|
|
2860
|
-
reject(e);
|
|
2861
|
-
});
|
|
2862
|
-
});
|
|
2863
|
-
|
|
2864
|
-
const killWorker = async () => {
|
|
2865
|
-
await worker.terminate();
|
|
2866
|
-
};
|
|
2867
|
-
|
|
2868
|
-
const startOperation = Abort.startOperation();
|
|
2869
|
-
startOperation.addAbortSignal(signal);
|
|
2870
|
-
const timeoutAbortSource = startOperation.timeout(allocatedMs);
|
|
2871
|
-
startOperation.addAbortCallback(killWorker);
|
|
2872
|
-
teardown.addCallback(killWorker);
|
|
2873
|
-
|
|
2874
|
-
const startedPromise = (async () => {
|
|
2875
|
-
const logScale = [100, 250, 500];
|
|
2876
|
-
// eslint-disable-next-line no-constant-condition
|
|
2877
|
-
while (true) {
|
|
2878
|
-
if (errorReceived) {
|
|
2879
|
-
break;
|
|
2880
|
-
}
|
|
2881
|
-
const connected = await pingServer(webServer.origin);
|
|
2882
|
-
if (connected) {
|
|
2883
|
-
break;
|
|
2884
|
-
}
|
|
2885
|
-
|
|
2886
|
-
startOperation.throwIfAborted();
|
|
2887
|
-
const delay = logScale.shift() || 1000;
|
|
2888
|
-
logger.debug(`Waiting ${delay}ms`);
|
|
2889
|
-
await new Promise((x) => setTimeout(x, delay));
|
|
2890
|
-
}
|
|
2891
|
-
})();
|
|
2892
|
-
|
|
2893
|
-
try {
|
|
2894
|
-
await Promise.race([errorPromise, startedPromise]);
|
|
2895
|
-
} catch (e) {
|
|
2896
|
-
if (Abort.isAbortError(e)) {
|
|
2897
|
-
if (timeoutAbortSource.signal.aborted) {
|
|
2898
|
-
// aborted by timeout
|
|
2899
|
-
throw new Error(
|
|
2900
|
-
`"${webServer.moduleUrl}" did not start a server in less than ${allocatedMs}ms (webServer.moduleUrl)`,
|
|
2901
|
-
);
|
|
2902
|
-
}
|
|
2903
|
-
if (signal.aborted) {
|
|
2904
|
-
// aborted from outside
|
|
2905
|
-
return;
|
|
2906
|
-
}
|
|
2907
|
-
}
|
|
2908
|
-
throw e;
|
|
2909
|
-
} finally {
|
|
2910
|
-
await startOperation.end();
|
|
2911
|
-
}
|
|
2912
|
-
};
|
|
2913
|
-
|
|
2914
2831
|
const startServerUsingCommand = async (
|
|
2915
2832
|
webServer,
|
|
2916
2833
|
{ signal, allocatedMs, logger, teardown },
|
|
@@ -2951,7 +2868,7 @@ const startServerUsingCommand = async (
|
|
|
2951
2868
|
let processClosed = false;
|
|
2952
2869
|
const closedPromise = new Promise((resolve) => {
|
|
2953
2870
|
spawnedProcess.once("exit", (exitCode, signal) => {
|
|
2954
|
-
logger.
|
|
2871
|
+
logger.debug(
|
|
2955
2872
|
`[pid=${spawnedProcess.pid}] <process did exit: exitCode=${exitCode}, signal=${signal}>`,
|
|
2956
2873
|
);
|
|
2957
2874
|
processClosed = true;
|
|
@@ -2959,14 +2876,14 @@ const startServerUsingCommand = async (
|
|
|
2959
2876
|
});
|
|
2960
2877
|
});
|
|
2961
2878
|
const killProcess = async () => {
|
|
2962
|
-
logger.
|
|
2879
|
+
logger.debug(`[pid=${spawnedProcess.pid}] <kill>`);
|
|
2963
2880
|
if (!spawnedProcess.pid || spawnedProcess.killed || processClosed) {
|
|
2964
|
-
logger.
|
|
2881
|
+
logger.debug(
|
|
2965
2882
|
`[pid=${spawnedProcess.pid}] <skipped force kill spawnedProcess.killed=${spawnedProcess.killed} processClosed=${processClosed}>`,
|
|
2966
2883
|
);
|
|
2967
2884
|
return;
|
|
2968
2885
|
}
|
|
2969
|
-
logger.
|
|
2886
|
+
logger.debug(`[pid=${spawnedProcess.pid}] <will force kill>`);
|
|
2970
2887
|
// Force kill the browser.
|
|
2971
2888
|
try {
|
|
2972
2889
|
if (process.platform === "win32") {
|
|
@@ -2979,7 +2896,9 @@ const startServerUsingCommand = async (
|
|
|
2979
2896
|
taskkillProcess.stderr.toString(),
|
|
2980
2897
|
];
|
|
2981
2898
|
if (stdout)
|
|
2982
|
-
logger.
|
|
2899
|
+
logger.debug(
|
|
2900
|
+
`[pid=${spawnedProcess.pid}] taskkill stdout: ${stdout}`,
|
|
2901
|
+
);
|
|
2983
2902
|
if (stderr)
|
|
2984
2903
|
logger.info(`[pid=${spawnedProcess.pid}] taskkill stderr: ${stderr}`);
|
|
2985
2904
|
} else {
|
|
@@ -3025,7 +2944,7 @@ const startServerUsingCommand = async (
|
|
|
3025
2944
|
if (timeoutAbortSource.signal.aborted) {
|
|
3026
2945
|
// aborted by timeout
|
|
3027
2946
|
throw new Error(
|
|
3028
|
-
`"${webServer.command}" command did not start a server in less than ${allocatedMs}ms
|
|
2947
|
+
`"${webServer.command}" command did not start a server in less than ${allocatedMs}ms`,
|
|
3029
2948
|
);
|
|
3030
2949
|
}
|
|
3031
2950
|
if (signal.aborted) {
|
|
@@ -3039,6 +2958,19 @@ const startServerUsingCommand = async (
|
|
|
3039
2958
|
}
|
|
3040
2959
|
};
|
|
3041
2960
|
|
|
2961
|
+
const startServerUsingModuleUrl = async (webServer, params) => {
|
|
2962
|
+
if (!existsSync(new URL(webServer.moduleUrl))) {
|
|
2963
|
+
throw new Error(`"${webServer.moduleUrl}" does not lead to a file`);
|
|
2964
|
+
}
|
|
2965
|
+
return startServerUsingCommand(
|
|
2966
|
+
{
|
|
2967
|
+
...webServer,
|
|
2968
|
+
command: `node ${fileURLToPath(webServer.moduleUrl)}`,
|
|
2969
|
+
},
|
|
2970
|
+
params,
|
|
2971
|
+
);
|
|
2972
|
+
};
|
|
2973
|
+
|
|
3042
2974
|
const basicFetch = async (
|
|
3043
2975
|
url,
|
|
3044
2976
|
{ rejectUnauthorized = true, method = "GET", headers = {} } = {},
|
package/package.json
CHANGED
|
@@ -43,7 +43,7 @@ export const startServerUsingCommand = async (
|
|
|
43
43
|
let processClosed = false;
|
|
44
44
|
const closedPromise = new Promise((resolve) => {
|
|
45
45
|
spawnedProcess.once("exit", (exitCode, signal) => {
|
|
46
|
-
logger.
|
|
46
|
+
logger.debug(
|
|
47
47
|
`[pid=${spawnedProcess.pid}] <process did exit: exitCode=${exitCode}, signal=${signal}>`,
|
|
48
48
|
);
|
|
49
49
|
processClosed = true;
|
|
@@ -51,14 +51,14 @@ export const startServerUsingCommand = async (
|
|
|
51
51
|
});
|
|
52
52
|
});
|
|
53
53
|
const killProcess = async () => {
|
|
54
|
-
logger.
|
|
54
|
+
logger.debug(`[pid=${spawnedProcess.pid}] <kill>`);
|
|
55
55
|
if (!spawnedProcess.pid || spawnedProcess.killed || processClosed) {
|
|
56
|
-
logger.
|
|
56
|
+
logger.debug(
|
|
57
57
|
`[pid=${spawnedProcess.pid}] <skipped force kill spawnedProcess.killed=${spawnedProcess.killed} processClosed=${processClosed}>`,
|
|
58
58
|
);
|
|
59
59
|
return;
|
|
60
60
|
}
|
|
61
|
-
logger.
|
|
61
|
+
logger.debug(`[pid=${spawnedProcess.pid}] <will force kill>`);
|
|
62
62
|
// Force kill the browser.
|
|
63
63
|
try {
|
|
64
64
|
if (process.platform === "win32") {
|
|
@@ -71,7 +71,9 @@ export const startServerUsingCommand = async (
|
|
|
71
71
|
taskkillProcess.stderr.toString(),
|
|
72
72
|
];
|
|
73
73
|
if (stdout)
|
|
74
|
-
logger.
|
|
74
|
+
logger.debug(
|
|
75
|
+
`[pid=${spawnedProcess.pid}] taskkill stdout: ${stdout}`,
|
|
76
|
+
);
|
|
75
77
|
if (stderr)
|
|
76
78
|
logger.info(`[pid=${spawnedProcess.pid}] taskkill stderr: ${stderr}`);
|
|
77
79
|
} else {
|
|
@@ -117,7 +119,7 @@ export const startServerUsingCommand = async (
|
|
|
117
119
|
if (timeoutAbortSource.signal.aborted) {
|
|
118
120
|
// aborted by timeout
|
|
119
121
|
throw new Error(
|
|
120
|
-
`"${webServer.command}" command did not start a server in less than ${allocatedMs}ms
|
|
122
|
+
`"${webServer.command}" command did not start a server in less than ${allocatedMs}ms`,
|
|
121
123
|
);
|
|
122
124
|
}
|
|
123
125
|
if (signal.aborted) {
|
|
@@ -1,88 +1,17 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
-
import {
|
|
3
|
-
import { Abort } from "@jsenv/abort";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
4
3
|
|
|
5
|
-
import {
|
|
4
|
+
import { startServerUsingCommand } from "./start_using_command.js";
|
|
6
5
|
|
|
7
|
-
export const startServerUsingModuleUrl = async (
|
|
8
|
-
webServer,
|
|
9
|
-
{ signal, teardown, logger, allocatedMs },
|
|
10
|
-
) => {
|
|
6
|
+
export const startServerUsingModuleUrl = async (webServer, params) => {
|
|
11
7
|
if (!existsSync(new URL(webServer.moduleUrl))) {
|
|
12
|
-
throw new Error(
|
|
13
|
-
`webServer.moduleUrl does not lead to a file at "${webServer.moduleUrl}"`,
|
|
14
|
-
);
|
|
8
|
+
throw new Error(`"${webServer.moduleUrl}" does not lead to a file`);
|
|
15
9
|
}
|
|
16
|
-
|
|
17
|
-
new URL(
|
|
18
|
-
"./worker_importing_module_starting_web_server.mjs",
|
|
19
|
-
import.meta.url,
|
|
20
|
-
),
|
|
10
|
+
return startServerUsingCommand(
|
|
21
11
|
{
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
},
|
|
25
|
-
env: {
|
|
26
|
-
IMPORTED_BY_TEST_PLAN: "1",
|
|
27
|
-
},
|
|
28
|
-
stdin: true,
|
|
29
|
-
stdout: true,
|
|
12
|
+
...webServer,
|
|
13
|
+
command: `node ${fileURLToPath(webServer.moduleUrl)}`,
|
|
30
14
|
},
|
|
15
|
+
params,
|
|
31
16
|
);
|
|
32
|
-
let errorReceived = false;
|
|
33
|
-
const errorPromise = new Promise((resolve, reject) => {
|
|
34
|
-
worker.on("error", (e) => {
|
|
35
|
-
errorReceived = true;
|
|
36
|
-
reject(e);
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
const killWorker = async () => {
|
|
41
|
-
await worker.terminate();
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const startOperation = Abort.startOperation();
|
|
45
|
-
startOperation.addAbortSignal(signal);
|
|
46
|
-
const timeoutAbortSource = startOperation.timeout(allocatedMs);
|
|
47
|
-
startOperation.addAbortCallback(killWorker);
|
|
48
|
-
teardown.addCallback(killWorker);
|
|
49
|
-
|
|
50
|
-
const startedPromise = (async () => {
|
|
51
|
-
const logScale = [100, 250, 500];
|
|
52
|
-
// eslint-disable-next-line no-constant-condition
|
|
53
|
-
while (true) {
|
|
54
|
-
if (errorReceived) {
|
|
55
|
-
break;
|
|
56
|
-
}
|
|
57
|
-
const connected = await pingServer(webServer.origin);
|
|
58
|
-
if (connected) {
|
|
59
|
-
break;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
startOperation.throwIfAborted();
|
|
63
|
-
const delay = logScale.shift() || 1000;
|
|
64
|
-
logger.debug(`Waiting ${delay}ms`);
|
|
65
|
-
await new Promise((x) => setTimeout(x, delay));
|
|
66
|
-
}
|
|
67
|
-
})();
|
|
68
|
-
|
|
69
|
-
try {
|
|
70
|
-
await Promise.race([errorPromise, startedPromise]);
|
|
71
|
-
} catch (e) {
|
|
72
|
-
if (Abort.isAbortError(e)) {
|
|
73
|
-
if (timeoutAbortSource.signal.aborted) {
|
|
74
|
-
// aborted by timeout
|
|
75
|
-
throw new Error(
|
|
76
|
-
`"${webServer.moduleUrl}" did not start a server in less than ${allocatedMs}ms (webServer.moduleUrl)`,
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
if (signal.aborted) {
|
|
80
|
-
// aborted from outside
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
throw e;
|
|
85
|
-
} finally {
|
|
86
|
-
await startOperation.end();
|
|
87
|
-
}
|
|
88
17
|
};
|