@jsenv/core 23.2.2 → 23.4.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/{license → LICENSE} +0 -0
- package/package.json +13 -14
- package/readme.md +4 -4
- package/src/buildProject.js +12 -13
- package/src/execute.js +92 -93
- package/src/executeTestPlan.js +9 -8
- package/src/internal/browser-launcher/executeHtmlFile.js +26 -23
- package/src/internal/building/buildUsingRollup.js +3 -4
- package/src/internal/building/build_logs.js +7 -6
- package/src/internal/building/createJsenvRollupPlugin.js +9 -14
- package/src/internal/building/url_trace.js +3 -4
- package/src/internal/compiling/createCompiledFileService.js +21 -6
- package/src/internal/compiling/startCompileServer.js +55 -46
- package/src/internal/executing/coverage/babel_plugin_instrument.js +1 -0
- package/src/internal/executing/coverage/reportToCoverage.js +147 -120
- package/src/internal/executing/{coverage → coverage_empty}/createEmptyCoverage.js +0 -0
- package/src/internal/executing/coverage_empty/list_files_not_covered.js +20 -0
- package/src/internal/executing/{coverage → coverage_empty}/relativeUrlToEmptyCoverage.js +3 -4
- package/src/internal/executing/{coverage/generateCoverageHtmlDirectory.js → coverage_reporter/coverage_reporter_html_directory.js} +11 -4
- package/src/internal/executing/{coverage/generateCoverageJsonFile.js → coverage_reporter/coverage_reporter_json_file.js} +0 -0
- package/src/internal/executing/{coverage/generateCoverageTextLog.js → coverage_reporter/coverage_reporter_text_log.js} +4 -2
- package/src/internal/executing/{coverage → coverage_reporter}/istanbulCoverageMapFromCoverage.js +0 -0
- package/src/internal/executing/{coverage/normalizeIstanbulCoverage.js → coverage_utils/file_by_file_coverage.js} +9 -7
- package/src/internal/executing/coverage_utils/istanbul_coverage_composition.js +28 -0
- package/src/internal/executing/coverage_utils/v8_and_istanbul.js +38 -0
- package/src/internal/executing/coverage_utils/v8_coverage_composition.js +23 -0
- package/src/internal/executing/coverage_utils/v8_coverage_from_directory.js +65 -0
- package/src/internal/executing/coverage_utils/v8_coverage_to_istanbul.js +90 -0
- package/src/internal/executing/createSummaryLog.js +15 -15
- package/src/internal/executing/executeConcurrently.js +92 -32
- package/src/internal/executing/executePlan.js +84 -81
- package/src/internal/executing/executionLogs.js +14 -18
- package/src/internal/executing/execution_colors.js +6 -12
- package/src/internal/executing/launchAndExecute.js +172 -169
- package/src/internal/node-launcher/createControllableNodeProcess.js +26 -23
- package/src/launchBrowser.js +72 -69
- package/src/launchNode.js +11 -99
- package/src/startExploring.js +2 -17
- package/src/abort/abortable.js +0 -172
- package/src/abort/callback_list.js +0 -64
- package/src/abort/callback_race.js +0 -34
- package/src/abort/cleaner.js +0 -22
- package/src/abort/main.js +0 -32
- package/src/abort/process_teardown_events.js +0 -59
- package/src/internal/createCallbackList.js +0 -21
- package/src/internal/executing/coverage/composeIstanbulCoverages.js +0 -108
- package/src/internal/executing/coverage/composeV8Coverages.js +0 -20
- package/src/internal/executing/coverage/istanbulCoverageFromCoverages.js +0 -43
- package/src/internal/executing/coverage/istanbulCoverageFromV8Coverage.js +0 -79
- package/src/internal/executing/coverage/v8CoverageFromAllV8Coverages.js +0 -40
- package/src/internal/executing/coverage/v8CoverageFromNodeV8Directory.js +0 -67
- package/src/internal/executing/logUtils.js +0 -30
- package/src/internal/executing/writeLog.js +0 -106
- package/src/internal/executing/writeLog.test-manual.js +0 -62
- package/src/internal/logs/log_style.js +0 -40
- package/src/signal/signal.js +0 -65
package/src/launchBrowser.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
// https://github.com/microsoft/playwright/blob/master/docs/api.md
|
|
2
2
|
|
|
3
3
|
import { createDetailedMessage } from "@jsenv/logger"
|
|
4
|
-
|
|
5
4
|
import {
|
|
6
|
-
|
|
5
|
+
Abort,
|
|
6
|
+
createCallbackListNotifiedOnce,
|
|
7
|
+
createCallbackList,
|
|
7
8
|
raceProcessTeardownEvents,
|
|
8
|
-
} from "@jsenv/
|
|
9
|
-
import {
|
|
9
|
+
} from "@jsenv/abort"
|
|
10
|
+
import { memoize } from "@jsenv/filesystem"
|
|
11
|
+
|
|
10
12
|
import { fetchUrl } from "./internal/fetchUrl.js"
|
|
11
13
|
import { validateResponse } from "./internal/response_validation.js"
|
|
12
14
|
import { trackPageToNotify } from "./internal/browser-launcher/trackPageToNotify.js"
|
|
@@ -35,7 +37,7 @@ chromiumRuntime.launch = async ({
|
|
|
35
37
|
collectPerformance,
|
|
36
38
|
measurePerformance,
|
|
37
39
|
collectCoverage,
|
|
38
|
-
|
|
40
|
+
coverageIgnorePredicate,
|
|
39
41
|
coverageForceIstanbul,
|
|
40
42
|
|
|
41
43
|
headless = true,
|
|
@@ -45,7 +47,9 @@ chromiumRuntime.launch = async ({
|
|
|
45
47
|
stopOnExit = true,
|
|
46
48
|
share = false,
|
|
47
49
|
}) => {
|
|
48
|
-
const launchBrowserOperation =
|
|
50
|
+
const launchBrowserOperation = Abort.startOperation()
|
|
51
|
+
launchBrowserOperation.addAbortSignal(signal)
|
|
52
|
+
|
|
49
53
|
const sharingToken = share
|
|
50
54
|
? chromiumSharing.getSharingToken({
|
|
51
55
|
chromiumExecutablePath,
|
|
@@ -54,9 +58,7 @@ chromiumRuntime.launch = async ({
|
|
|
54
58
|
debugPort,
|
|
55
59
|
})
|
|
56
60
|
: chromiumSharing.getUniqueSharingToken()
|
|
57
|
-
|
|
58
61
|
if (!sharingToken.isUsed()) {
|
|
59
|
-
Abortable.throwIfAborted(launchBrowserOperation)
|
|
60
62
|
const { chromium } = await import("playwright")
|
|
61
63
|
const launchOperation = launchBrowser("chromium", {
|
|
62
64
|
browserClass: chromium,
|
|
@@ -77,10 +79,9 @@ chromiumRuntime.launch = async ({
|
|
|
77
79
|
sharingToken.setSharedValue(launchOperation)
|
|
78
80
|
}
|
|
79
81
|
|
|
80
|
-
const [
|
|
81
|
-
launchBrowserOperation.
|
|
82
|
-
|
|
83
|
-
const browser = await launchOperation
|
|
82
|
+
const [browserPromise, stopUsingBrowser] = sharingToken.useSharedValue()
|
|
83
|
+
launchBrowserOperation.addEndCallback(stopUsingBrowser)
|
|
84
|
+
const browser = await browserPromise
|
|
84
85
|
|
|
85
86
|
if (debug) {
|
|
86
87
|
// https://github.com/puppeteer/puppeteer/blob/v2.0.0/docs/api.md#browserwsendpoint
|
|
@@ -105,7 +106,6 @@ chromiumRuntime.launch = async ({
|
|
|
105
106
|
}
|
|
106
107
|
|
|
107
108
|
const browserHooks = browserToRuntimeHooks(browser, {
|
|
108
|
-
launchBrowserOperation,
|
|
109
109
|
browserServerLogLevel,
|
|
110
110
|
|
|
111
111
|
projectDirectoryUrl,
|
|
@@ -115,7 +115,7 @@ chromiumRuntime.launch = async ({
|
|
|
115
115
|
collectPerformance,
|
|
116
116
|
measurePerformance,
|
|
117
117
|
collectCoverage,
|
|
118
|
-
|
|
118
|
+
coverageIgnorePredicate,
|
|
119
119
|
coverageForceIstanbul,
|
|
120
120
|
coveragePlaywrightAPIAvailable: true,
|
|
121
121
|
})
|
|
@@ -151,20 +151,20 @@ firefoxRuntime.launch = async ({
|
|
|
151
151
|
collectPerformance,
|
|
152
152
|
measurePerformance,
|
|
153
153
|
collectCoverage,
|
|
154
|
-
|
|
154
|
+
coverageIgnorePredicate,
|
|
155
155
|
coverageForceIstanbul,
|
|
156
156
|
|
|
157
157
|
headless = true,
|
|
158
158
|
stopOnExit = true,
|
|
159
159
|
share = false,
|
|
160
160
|
}) => {
|
|
161
|
-
const launchBrowserOperation =
|
|
161
|
+
const launchBrowserOperation = Abort.startOperation()
|
|
162
|
+
launchBrowserOperation.addAbortSignal(signal)
|
|
163
|
+
|
|
162
164
|
const sharingToken = share
|
|
163
165
|
? firefoxSharing.getSharingToken({ firefoxExecutablePath, headless })
|
|
164
166
|
: firefoxSharing.getUniqueSharingToken()
|
|
165
|
-
|
|
166
167
|
if (!sharingToken.isUsed()) {
|
|
167
|
-
Abortable.throwIfAborted(launchBrowserOperation)
|
|
168
168
|
const { firefox } = await import("playwright")
|
|
169
169
|
const launchOperation = launchBrowser("firefox", {
|
|
170
170
|
browserClass: firefox,
|
|
@@ -179,10 +179,9 @@ firefoxRuntime.launch = async ({
|
|
|
179
179
|
sharingToken.setSharedValue(launchOperation)
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
const [
|
|
183
|
-
launchBrowserOperation.
|
|
184
|
-
|
|
185
|
-
const browser = await launchOperation
|
|
182
|
+
const [browserPromise, stopUsingBrowser] = sharingToken.useSharedValue()
|
|
183
|
+
launchBrowserOperation.addEndCallback(stopUsingBrowser)
|
|
184
|
+
const browser = await browserPromise
|
|
186
185
|
|
|
187
186
|
const browserHooks = browserToRuntimeHooks(browser, {
|
|
188
187
|
launchBrowserOperation,
|
|
@@ -195,7 +194,7 @@ firefoxRuntime.launch = async ({
|
|
|
195
194
|
collectPerformance,
|
|
196
195
|
measurePerformance,
|
|
197
196
|
collectCoverage,
|
|
198
|
-
|
|
197
|
+
coverageIgnorePredicate,
|
|
199
198
|
coverageForceIstanbul,
|
|
200
199
|
})
|
|
201
200
|
|
|
@@ -230,20 +229,21 @@ webkitRuntime.launch = async ({
|
|
|
230
229
|
collectPerformance,
|
|
231
230
|
measurePerformance,
|
|
232
231
|
collectCoverage,
|
|
233
|
-
|
|
232
|
+
coverageIgnorePredicate,
|
|
234
233
|
coverageForceIstanbul,
|
|
235
234
|
|
|
236
235
|
headless = true,
|
|
237
236
|
stopOnExit = true,
|
|
238
237
|
share = false,
|
|
239
238
|
}) => {
|
|
240
|
-
const launchBrowserOperation =
|
|
239
|
+
const launchBrowserOperation = Abort.startOperation()
|
|
240
|
+
launchBrowserOperation.addAbortSignal(signal)
|
|
241
|
+
|
|
241
242
|
const sharingToken = share
|
|
242
243
|
? webkitSharing.getSharingToken({ webkitExecutablePath, headless })
|
|
243
244
|
: webkitSharing.getUniqueSharingToken()
|
|
244
245
|
|
|
245
246
|
if (!sharingToken.isUsed()) {
|
|
246
|
-
Abortable.throwIfAborted(launchBrowserOperation)
|
|
247
247
|
const { webkit } = await import("playwright")
|
|
248
248
|
const launchOperation = launchBrowser("webkit", {
|
|
249
249
|
browserClass: webkit,
|
|
@@ -257,10 +257,9 @@ webkitRuntime.launch = async ({
|
|
|
257
257
|
sharingToken.setSharedValue(launchOperation)
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
-
const [
|
|
261
|
-
launchBrowserOperation.
|
|
262
|
-
|
|
263
|
-
const browser = await launchOperation
|
|
260
|
+
const [browserPromise, stopUsingBrowser] = sharingToken.useSharedValue()
|
|
261
|
+
launchBrowserOperation.addEndCallback(stopUsingBrowser)
|
|
262
|
+
const browser = await browserPromise
|
|
264
263
|
|
|
265
264
|
const browserHooks = browserToRuntimeHooks(browser, {
|
|
266
265
|
launchBrowserOperation,
|
|
@@ -273,7 +272,7 @@ webkitRuntime.launch = async ({
|
|
|
273
272
|
collectPerformance,
|
|
274
273
|
measurePerformance,
|
|
275
274
|
collectCoverage,
|
|
276
|
-
|
|
275
|
+
coverageIgnorePredicate,
|
|
277
276
|
coverageForceIstanbul,
|
|
278
277
|
ignoreErrorHook: (error) => {
|
|
279
278
|
// we catch error during execution but safari throw unhandled rejection
|
|
@@ -314,8 +313,8 @@ const launchBrowser = async (
|
|
|
314
313
|
{ launchBrowserOperation, browserClass, options, stopOnExit },
|
|
315
314
|
) => {
|
|
316
315
|
if (stopOnExit) {
|
|
317
|
-
|
|
318
|
-
raceProcessTeardownEvents(
|
|
316
|
+
launchBrowserOperation.addAbortSource((abort) => {
|
|
317
|
+
return raceProcessTeardownEvents(
|
|
319
318
|
{
|
|
320
319
|
SIGHUP: true,
|
|
321
320
|
SIGTERM: true,
|
|
@@ -323,9 +322,9 @@ const launchBrowser = async (
|
|
|
323
322
|
beforeExit: true,
|
|
324
323
|
exit: true,
|
|
325
324
|
},
|
|
326
|
-
|
|
327
|
-
)
|
|
328
|
-
)
|
|
325
|
+
abort,
|
|
326
|
+
)
|
|
327
|
+
})
|
|
329
328
|
}
|
|
330
329
|
|
|
331
330
|
try {
|
|
@@ -337,19 +336,16 @@ const launchBrowser = async (
|
|
|
337
336
|
handleSIGTERM: false,
|
|
338
337
|
handleSIGHUP: false,
|
|
339
338
|
})
|
|
340
|
-
launchBrowserOperation.
|
|
341
|
-
await stopBrowser(browser)
|
|
342
|
-
})
|
|
343
|
-
if (launchBrowserOperation.signal.aborted) {
|
|
344
|
-
await launchBrowserOperation.cleaner.clean()
|
|
345
|
-
Abortable.throwIfAborted(launchBrowserOperation)
|
|
346
|
-
}
|
|
339
|
+
launchBrowserOperation.throwIfAborted()
|
|
347
340
|
return browser
|
|
348
341
|
} catch (e) {
|
|
349
342
|
if (launchBrowserOperation.signal.aborted && isTargetClosedError(e)) {
|
|
350
|
-
|
|
343
|
+
// rethrow the abort error
|
|
344
|
+
launchBrowserOperation.throwIfAborted()
|
|
351
345
|
}
|
|
352
346
|
throw e
|
|
347
|
+
} finally {
|
|
348
|
+
await launchBrowserOperation.end()
|
|
353
349
|
}
|
|
354
350
|
}
|
|
355
351
|
|
|
@@ -375,8 +371,6 @@ const stopBrowser = async (browser) => {
|
|
|
375
371
|
const browserToRuntimeHooks = (
|
|
376
372
|
browser,
|
|
377
373
|
{
|
|
378
|
-
launchBrowserOperation,
|
|
379
|
-
|
|
380
374
|
projectDirectoryUrl,
|
|
381
375
|
compileServerOrigin,
|
|
382
376
|
outDirectoryRelativeUrl,
|
|
@@ -384,33 +378,47 @@ const browserToRuntimeHooks = (
|
|
|
384
378
|
collectPerformance,
|
|
385
379
|
measurePerformance,
|
|
386
380
|
collectCoverage,
|
|
387
|
-
|
|
381
|
+
coverageIgnorePredicate,
|
|
388
382
|
coverageForceIstanbul,
|
|
389
383
|
coveragePlaywrightAPIAvailable = false,
|
|
390
384
|
ignoreErrorHook = () => false,
|
|
391
385
|
transformErrorHook = (error) => error,
|
|
392
386
|
},
|
|
393
387
|
) => {
|
|
394
|
-
const
|
|
388
|
+
const stopCallbackList = createCallbackListNotifiedOnce()
|
|
389
|
+
const stoppedCallbackList = createCallbackListNotifiedOnce()
|
|
390
|
+
const stop = memoize(async (reason) => {
|
|
391
|
+
await stopCallbackList.notify({ reason })
|
|
392
|
+
stoppedCallbackList.notify({ reason })
|
|
393
|
+
return { graceful: false }
|
|
394
|
+
})
|
|
395
|
+
|
|
395
396
|
// https://github.com/GoogleChrome/puppeteer/blob/v1.4.0/docs/api.md#event-disconnected
|
|
396
|
-
browser.on("disconnected",
|
|
397
|
+
browser.on("disconnected", () => {
|
|
398
|
+
stop()
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
stopCallbackList.add(async () => {
|
|
402
|
+
await stopBrowser(browser)
|
|
403
|
+
})
|
|
397
404
|
|
|
398
|
-
const
|
|
405
|
+
const errorCallbackList = createCallbackList()
|
|
399
406
|
|
|
400
|
-
const
|
|
407
|
+
const outputCallbackList = createCallbackList()
|
|
401
408
|
|
|
402
409
|
const execute = async ({
|
|
403
410
|
signal,
|
|
404
411
|
fileRelativeUrl,
|
|
405
412
|
ignoreHTTPSErrors = true, // we mostly use self signed certificates during tests
|
|
406
413
|
}) => {
|
|
407
|
-
const executeOperation =
|
|
408
|
-
|
|
414
|
+
const executeOperation = Abort.startOperation()
|
|
415
|
+
executeOperation.addAbortSignal(signal)
|
|
416
|
+
executeOperation.throwIfAborted()
|
|
409
417
|
// open a tab to execute to the file
|
|
410
418
|
const browserContext = await browser.newContext({ ignoreHTTPSErrors })
|
|
411
|
-
|
|
419
|
+
executeOperation.throwIfAborted()
|
|
412
420
|
const page = await browserContext.newPage()
|
|
413
|
-
|
|
421
|
+
executeOperation.addEndCallback(async () => {
|
|
414
422
|
try {
|
|
415
423
|
await browserContext.close()
|
|
416
424
|
} catch (e) {
|
|
@@ -425,15 +433,15 @@ const browserToRuntimeHooks = (
|
|
|
425
433
|
onError: (error) => {
|
|
426
434
|
error = transformErrorHook(error)
|
|
427
435
|
if (!ignoreErrorHook(error)) {
|
|
428
|
-
|
|
436
|
+
errorCallbackList.notify(error)
|
|
429
437
|
}
|
|
430
438
|
},
|
|
431
|
-
onConsole:
|
|
439
|
+
onConsole: outputCallbackList.notify,
|
|
432
440
|
})
|
|
433
|
-
|
|
441
|
+
stoppedCallbackList.add(stopTrackingToNotify)
|
|
434
442
|
|
|
435
443
|
const result = await executeHtmlFile(fileRelativeUrl, {
|
|
436
|
-
|
|
444
|
+
executeOperation,
|
|
437
445
|
|
|
438
446
|
projectDirectoryUrl,
|
|
439
447
|
compileServerOrigin,
|
|
@@ -443,25 +451,20 @@ const browserToRuntimeHooks = (
|
|
|
443
451
|
measurePerformance,
|
|
444
452
|
collectPerformance,
|
|
445
453
|
collectCoverage,
|
|
446
|
-
coverageConfig,
|
|
447
454
|
coverageForceIstanbul,
|
|
448
455
|
coveragePlaywrightAPIAvailable,
|
|
456
|
+
coverageIgnorePredicate,
|
|
449
457
|
transformErrorHook,
|
|
450
458
|
})
|
|
451
459
|
return result
|
|
452
460
|
}
|
|
453
461
|
|
|
454
|
-
Abortable.cleanOnAbort(launchBrowserOperation)
|
|
455
|
-
|
|
456
462
|
return {
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
463
|
+
stoppedCallbackList,
|
|
464
|
+
errorCallbackList,
|
|
465
|
+
outputCallbackList,
|
|
460
466
|
execute,
|
|
461
|
-
stop
|
|
462
|
-
await launchBrowserOperation.cleaner.clean(reason)
|
|
463
|
-
return { graceful: false }
|
|
464
|
-
},
|
|
467
|
+
stop,
|
|
465
468
|
}
|
|
466
469
|
}
|
|
467
470
|
|
package/src/launchNode.js
CHANGED
|
@@ -1,18 +1,9 @@
|
|
|
1
1
|
import { Script } from "node:vm"
|
|
2
|
-
import cuid from "cuid"
|
|
3
2
|
import { loggerToLogLevel } from "@jsenv/logger"
|
|
4
|
-
import {
|
|
5
|
-
writeDirectory,
|
|
6
|
-
resolveUrl,
|
|
7
|
-
urlToFileSystemPath,
|
|
8
|
-
removeFileSystemNode,
|
|
9
|
-
moveDirectoryContent,
|
|
10
|
-
} from "@jsenv/filesystem"
|
|
11
3
|
|
|
12
4
|
import { jsenvCoreDirectoryUrl } from "@jsenv/core/src/internal/jsenvCoreDirectoryUrl.js"
|
|
13
5
|
import { escapeRegexpSpecialCharacters } from "./internal/escapeRegexpSpecialCharacters.js"
|
|
14
6
|
import { createControllableNodeProcess } from "./internal/node-launcher/createControllableNodeProcess.js"
|
|
15
|
-
import { v8CoverageFromNodeV8Directory } from "./internal/executing/coverage/v8CoverageFromNodeV8Directory.js"
|
|
16
7
|
|
|
17
8
|
export const nodeRuntime = {
|
|
18
9
|
name: "node",
|
|
@@ -30,8 +21,8 @@ nodeRuntime.launch = async ({
|
|
|
30
21
|
measurePerformance,
|
|
31
22
|
collectPerformance,
|
|
32
23
|
collectCoverage = false,
|
|
33
|
-
coverageConfig,
|
|
34
24
|
coverageForceIstanbul,
|
|
25
|
+
coverageConfig,
|
|
35
26
|
|
|
36
27
|
debugPort,
|
|
37
28
|
debugMode,
|
|
@@ -69,59 +60,10 @@ nodeRuntime.launch = async ({
|
|
|
69
60
|
JSENV: true,
|
|
70
61
|
}
|
|
71
62
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// through process.env.NODE_V8_COVERAGE.
|
|
77
|
-
|
|
78
|
-
if (coverageForceIstanbul) {
|
|
79
|
-
// if we want to force istanbul, we will set process.env.NODE_V8_COVERAGE = ''
|
|
80
|
-
// into the child_process
|
|
81
|
-
env.NODE_V8_COVERAGE = ""
|
|
82
|
-
}
|
|
83
|
-
// } else if (process.env.NODE_V8_COVERAGE) {
|
|
84
|
-
// // The V8_COVERAGE was already set by a parent process or command line.
|
|
85
|
-
// // It's the caller that is interested into coverage, it's not anymore this script
|
|
86
|
-
// // responsability to set process.env.NODE_V8_COVERAGE nor to read
|
|
87
|
-
// // coverage files in the v8 directory.
|
|
88
|
-
// }
|
|
89
|
-
// In fact it is so that it's possible to go coverageception:
|
|
90
|
-
// jsenv collect coverage for tests
|
|
91
|
-
// which are testing that coverage can be collected for tests
|
|
92
|
-
// this is possible because we overriding the child process NODE_V8_COVERAGE
|
|
93
|
-
else {
|
|
94
|
-
const NODE_V8_COVERAGE = await getNodeV8CoverageDir({
|
|
95
|
-
projectDirectoryUrl,
|
|
96
|
-
})
|
|
97
|
-
env.NODE_V8_COVERAGE = NODE_V8_COVERAGE
|
|
98
|
-
|
|
99
|
-
// the v8 coverage directory is available once the child process is disconnected
|
|
100
|
-
finalizeExecutionResult = async (executionResult) => {
|
|
101
|
-
if (
|
|
102
|
-
executionResult.status === "timedout" ||
|
|
103
|
-
executionResult.status === "aborted"
|
|
104
|
-
) {
|
|
105
|
-
return executionResult
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const coverage = await ensureV8CoverageDirClean(async () => {
|
|
109
|
-
// prefer istanbul if available
|
|
110
|
-
if (executionResult.coverage) {
|
|
111
|
-
return executionResult.coverage
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const v8Coverage = await v8CoverageFromNodeV8Directory({
|
|
115
|
-
projectDirectoryUrl,
|
|
116
|
-
NODE_V8_COVERAGE,
|
|
117
|
-
coverageConfig,
|
|
118
|
-
})
|
|
119
|
-
return v8Coverage
|
|
120
|
-
}, NODE_V8_COVERAGE)
|
|
121
|
-
executionResult.coverage = coverage
|
|
122
|
-
return executionResult
|
|
123
|
-
}
|
|
124
|
-
}
|
|
63
|
+
if (coverageForceIstanbul) {
|
|
64
|
+
// if we want to force istanbul, we will set process.env.NODE_V8_COVERAGE = ''
|
|
65
|
+
// into the child_process
|
|
66
|
+
env.NODE_V8_COVERAGE = ""
|
|
125
67
|
}
|
|
126
68
|
|
|
127
69
|
commandLineOptions = [
|
|
@@ -132,9 +74,9 @@ nodeRuntime.launch = async ({
|
|
|
132
74
|
const logLevel = loggerToLogLevel(logger)
|
|
133
75
|
const {
|
|
134
76
|
execArgv,
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
77
|
+
stoppedCallbackList,
|
|
78
|
+
errorCallbackList,
|
|
79
|
+
outputCallbackList,
|
|
138
80
|
stop,
|
|
139
81
|
requestActionOnChildProcess,
|
|
140
82
|
} = await createControllableNodeProcess({
|
|
@@ -193,44 +135,14 @@ nodeRuntime.launch = async ({
|
|
|
193
135
|
// because process.env is very big
|
|
194
136
|
// env,
|
|
195
137
|
},
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
138
|
+
stoppedCallbackList,
|
|
139
|
+
errorCallbackList,
|
|
140
|
+
outputCallbackList,
|
|
199
141
|
stop,
|
|
200
142
|
execute,
|
|
201
|
-
finalizeExecutionResult,
|
|
202
143
|
}
|
|
203
144
|
}
|
|
204
145
|
|
|
205
|
-
const ensureV8CoverageDirClean = async (fn, NODE_V8_COVERAGE) => {
|
|
206
|
-
try {
|
|
207
|
-
return await fn()
|
|
208
|
-
} finally {
|
|
209
|
-
if (process.env.NODE_V8_COVERAGE === NODE_V8_COVERAGE) {
|
|
210
|
-
// do not try to remove or copy coverage
|
|
211
|
-
} else if (process.env.NODE_V8_COVERAGE) {
|
|
212
|
-
await moveDirectoryContent({
|
|
213
|
-
from: NODE_V8_COVERAGE,
|
|
214
|
-
to: process.env.NODE_V8_COVERAGE,
|
|
215
|
-
})
|
|
216
|
-
await removeFileSystemNode(NODE_V8_COVERAGE, {})
|
|
217
|
-
} else {
|
|
218
|
-
await removeFileSystemNode(NODE_V8_COVERAGE, {
|
|
219
|
-
recursive: true,
|
|
220
|
-
})
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const getNodeV8CoverageDir = async ({ projectDirectoryUrl }) => {
|
|
226
|
-
const v8CoverageDirectory = resolveUrl(
|
|
227
|
-
`./coverage-v8/${cuid()}`,
|
|
228
|
-
projectDirectoryUrl,
|
|
229
|
-
)
|
|
230
|
-
await writeDirectory(v8CoverageDirectory, { allowUseless: true })
|
|
231
|
-
return urlToFileSystemPath(v8CoverageDirectory)
|
|
232
|
-
}
|
|
233
|
-
|
|
234
146
|
const transformExecutionResult = (
|
|
235
147
|
executionResult,
|
|
236
148
|
{ compileServerOrigin, projectDirectoryUrl },
|
package/src/startExploring.js
CHANGED
|
@@ -4,10 +4,6 @@ import {
|
|
|
4
4
|
urlToRelativeUrl,
|
|
5
5
|
} from "@jsenv/filesystem"
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
Abortable,
|
|
9
|
-
raceProcessTeardownEvents,
|
|
10
|
-
} from "@jsenv/core/src/abort/main.js"
|
|
11
7
|
import { jsenvCoreDirectoryUrl } from "./internal/jsenvCoreDirectoryUrl.js"
|
|
12
8
|
import {
|
|
13
9
|
assertProjectDirectoryUrl,
|
|
@@ -60,18 +56,6 @@ export const startExploring = async ({
|
|
|
60
56
|
projectDirectoryUrl = assertProjectDirectoryUrl({ projectDirectoryUrl })
|
|
61
57
|
await assertProjectDirectoryExists({ projectDirectoryUrl })
|
|
62
58
|
|
|
63
|
-
const exploringServerOperation = Abortable.fromSignal(signal)
|
|
64
|
-
if (handleSIGINT) {
|
|
65
|
-
Abortable.effect(exploringServerOperation, (cb) =>
|
|
66
|
-
raceProcessTeardownEvents(
|
|
67
|
-
{
|
|
68
|
-
SIGINT: true,
|
|
69
|
-
},
|
|
70
|
-
cb,
|
|
71
|
-
),
|
|
72
|
-
)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
59
|
const outDirectoryRelativeUrl = computeOutDirectoryRelativeUrl({
|
|
76
60
|
projectDirectoryUrl,
|
|
77
61
|
jsenvDirectoryRelativeUrl,
|
|
@@ -95,7 +79,8 @@ export const startExploring = async ({
|
|
|
95
79
|
})
|
|
96
80
|
|
|
97
81
|
const compileServer = await startCompileServer({
|
|
98
|
-
signal
|
|
82
|
+
signal,
|
|
83
|
+
handleSIGINT,
|
|
99
84
|
keepProcessAlive,
|
|
100
85
|
|
|
101
86
|
projectDirectoryUrl,
|
package/src/abort/abortable.js
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* https://github.com/whatwg/dom/issues/920
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { createCleaner } from "./cleaner.js"
|
|
6
|
-
import { raceCallbacks } from "./callback_race.js"
|
|
7
|
-
import { createCallbackList } from "./callback_list.js"
|
|
8
|
-
|
|
9
|
-
export const Abortable = {
|
|
10
|
-
throwIfAborted: (operation) => {
|
|
11
|
-
if (operation.signal.aborted) {
|
|
12
|
-
const error = new Error(`The operation was aborted`)
|
|
13
|
-
error.name = "AbortError"
|
|
14
|
-
error.type = "aborted"
|
|
15
|
-
throw error
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
|
|
19
|
-
isAbortError: (error) => {
|
|
20
|
-
return error.name === "AbortError"
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
start: () => {
|
|
24
|
-
const abortController = new AbortController()
|
|
25
|
-
const abort = (value) => abortController.abort(value)
|
|
26
|
-
const signal = abortController.signal
|
|
27
|
-
const cleaner = createCleaner()
|
|
28
|
-
|
|
29
|
-
// abortCallbackList is used to ignore the max listeners warning from Node.js
|
|
30
|
-
// this warning is useful but becomes problematic when it's expected
|
|
31
|
-
// (a function doing 20 http call in parallel)
|
|
32
|
-
// To be 100% sure we don't have memory leak, only Abortable.asyncCallback
|
|
33
|
-
// uses abortCallbackList to know when something is aborted
|
|
34
|
-
const abortCallbackList = createCallbackList()
|
|
35
|
-
signal.onabort = () => {
|
|
36
|
-
const callbacks = abortCallbackList.copy()
|
|
37
|
-
abortCallbackList.clear()
|
|
38
|
-
callbacks.forEach((callback) => {
|
|
39
|
-
callback()
|
|
40
|
-
})
|
|
41
|
-
}
|
|
42
|
-
cleaner.addCallback(() => {
|
|
43
|
-
abortCallbackList.clear()
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
const operation = {
|
|
47
|
-
abort,
|
|
48
|
-
signal,
|
|
49
|
-
abortCallbackList,
|
|
50
|
-
cleaner,
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return operation
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
fromSignal: (signal) => {
|
|
57
|
-
const operation = Abortable.start()
|
|
58
|
-
Abortable.followSignal(operation, signal)
|
|
59
|
-
return operation
|
|
60
|
-
},
|
|
61
|
-
|
|
62
|
-
followSignal: (operation, signal, cleanup = cleanupNoop) => {
|
|
63
|
-
if (operation.signal.aborted) {
|
|
64
|
-
return () => {}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (signal.aborted) {
|
|
68
|
-
operation.abort()
|
|
69
|
-
return () => {}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return raceCallbacks(
|
|
73
|
-
{
|
|
74
|
-
parent_abort: (cb) => {
|
|
75
|
-
return operation.abortCallbackList.add(cb)
|
|
76
|
-
},
|
|
77
|
-
child_abort: (cb) => {
|
|
78
|
-
return addEventListener(signal, "abort", cb)
|
|
79
|
-
},
|
|
80
|
-
cleaned: (cb) => {
|
|
81
|
-
return operation.cleaner.addCallback(cb)
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
(winner) => {
|
|
85
|
-
const raceEffects = {
|
|
86
|
-
parent_abort: () => {
|
|
87
|
-
// Nothing to do, exists to remove
|
|
88
|
-
// - "abort" event listener on parent
|
|
89
|
-
// - "abort" event listener on child
|
|
90
|
-
cleanup()
|
|
91
|
-
},
|
|
92
|
-
child_abort: () => {
|
|
93
|
-
operation.abort()
|
|
94
|
-
},
|
|
95
|
-
cleaned: () => {
|
|
96
|
-
// Nothing to do, exists to remove
|
|
97
|
-
// - "abort" event listener on parent
|
|
98
|
-
// - "abort" event listener on child
|
|
99
|
-
cleanup()
|
|
100
|
-
},
|
|
101
|
-
}
|
|
102
|
-
raceEffects[winner.name](winner.value)
|
|
103
|
-
},
|
|
104
|
-
)
|
|
105
|
-
},
|
|
106
|
-
|
|
107
|
-
effect: (operation, effect) => {
|
|
108
|
-
const abortController = new AbortController()
|
|
109
|
-
const returnValue = effect((value) => abortController.abort(value))
|
|
110
|
-
const cleanup =
|
|
111
|
-
typeof returnValue === "function" ? returnValue : cleanupNoop
|
|
112
|
-
const signal = abortController.signal
|
|
113
|
-
|
|
114
|
-
Abortable.followSignal(operation, signal, cleanup)
|
|
115
|
-
return {
|
|
116
|
-
signal,
|
|
117
|
-
cleanup,
|
|
118
|
-
}
|
|
119
|
-
},
|
|
120
|
-
|
|
121
|
-
timeout: (operation, ms) => {
|
|
122
|
-
return Abortable.effect(operation, (abort) => {
|
|
123
|
-
const timeoutId = setTimeout(abort, ms)
|
|
124
|
-
return () => {
|
|
125
|
-
clearTimeout(timeoutId)
|
|
126
|
-
}
|
|
127
|
-
})
|
|
128
|
-
},
|
|
129
|
-
|
|
130
|
-
cleanOnAbort: (operation) => {
|
|
131
|
-
const removeAbortEventListener = addEventListener(
|
|
132
|
-
operation.signal,
|
|
133
|
-
"abort",
|
|
134
|
-
() => {
|
|
135
|
-
removeAbortEventListener()
|
|
136
|
-
operation.cleaner.clean("operation aborted")
|
|
137
|
-
},
|
|
138
|
-
)
|
|
139
|
-
return removeAbortEventListener
|
|
140
|
-
},
|
|
141
|
-
|
|
142
|
-
// Provide a signal to the callback
|
|
143
|
-
// this signal won't inherit the current signal max listeners
|
|
144
|
-
asyncCallback: async (operation, asyncFunction) => {
|
|
145
|
-
Abortable.throwIfAborted(operation)
|
|
146
|
-
|
|
147
|
-
const abortController = new AbortController()
|
|
148
|
-
const signal = abortController.signal
|
|
149
|
-
|
|
150
|
-
const removeOperationAbortCallback = operation.abortCallbackList.add(() => {
|
|
151
|
-
abortController.abort()
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
try {
|
|
155
|
-
const value = await asyncFunction(signal)
|
|
156
|
-
removeOperationAbortCallback()
|
|
157
|
-
return value
|
|
158
|
-
} catch (e) {
|
|
159
|
-
removeOperationAbortCallback()
|
|
160
|
-
throw e
|
|
161
|
-
}
|
|
162
|
-
},
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const cleanupNoop = () => {}
|
|
166
|
-
|
|
167
|
-
const addEventListener = (target, eventName, cb) => {
|
|
168
|
-
target.addEventListener(eventName, cb)
|
|
169
|
-
return () => {
|
|
170
|
-
target.removeEventListener(eventName, cb)
|
|
171
|
-
}
|
|
172
|
-
}
|