@jsenv/core 27.0.0-alpha.81 → 27.0.0-alpha.84
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/babel_helpers/applyDecs/applyDecs.js +756 -0
- package/dist/babel_helpers/construct/construct.js +1 -1
- package/dist/babel_helpers/extends/extends.js +1 -1
- package/dist/babel_helpers/get/get.js +1 -1
- package/dist/babel_helpers/getPrototypeOf/getPrototypeOf.js +1 -1
- package/dist/babel_helpers/identity/identity.js +3 -0
- package/dist/babel_helpers/setPrototypeOf/setPrototypeOf.js +2 -2
- package/dist/js/event_source_client.js +206 -2
- package/dist/main.js +934 -90
- package/dist/s.js.map +2 -1
- package/package.json +9 -9
- package/src/build/build.js +5 -5
- package/src/build/build_urls_generator.js +1 -2
- package/src/build/inject_global_version_mappings.js +2 -2
- package/src/build/inject_service_worker_urls.js +2 -2
- package/src/build/resync_ressource_hints.js +1 -1
- package/src/build/start_build_server.js +33 -26
- package/src/dev/plugins/explorer/jsenv_plugin_explorer.js +1 -2
- package/src/dev/plugins/toolbar/client/util/fetching.js +1 -1
- package/src/dev/plugins/toolbar/jsenv_plugin_toolbar.js +1 -1
- package/src/dev/start_dev_server.js +38 -30
- package/src/execute/runtimes/browsers/from_playwright.js +5 -4
- package/src/execute/runtimes/node/node_process.js +2 -2
- package/src/helpers/command/command.js +73 -0
- package/src/helpers/event_source/event_source.js +197 -0
- package/src/helpers/event_source/sse_service.js +53 -0
- package/src/helpers/worker_reload.js +57 -0
- package/src/omega/compat/runtime_compat.js +2 -1
- package/src/omega/kitchen.js +2 -1
- package/src/omega/server/user_agent.js +2 -1
- package/src/omega/url_graph/sort_by_dependencies.js +27 -0
- package/src/omega/url_graph/url_info_transformations.js +24 -14
- package/src/plugins/autoreload/dev_sse/client/event_source_client.js +1 -1
- package/src/plugins/autoreload/dev_sse/client/reload.js +1 -1
- package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_client.js +1 -1
- package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js +1 -1
- package/src/plugins/bundling/css/bundle_css.js +5 -4
- package/src/plugins/bundling/js_module/bundle_js_module.js +2 -2
- package/src/plugins/commonjs_globals/jsenv_plugin_commonjs_globals.js +2 -2
- package/src/plugins/file_urls/jsenv_plugin_file_urls.js +1 -2
- package/src/plugins/html_supervisor/jsenv_plugin_html_supervisor.js +1 -1
- package/src/plugins/import_meta_hot/html_hot_dependencies.js +2 -2
- package/src/plugins/import_meta_hot/jsenv_plugin_import_meta_hot.js +4 -3
- package/src/plugins/import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js +2 -2
- package/src/plugins/importmap/jsenv_plugin_importmap.js +2 -3
- package/src/plugins/inject_globals/inject_globals.js +2 -2
- package/src/plugins/inline/jsenv_plugin_data_urls.js +1 -1
- package/src/plugins/inline/jsenv_plugin_html_inline_content.js +3 -3
- package/src/plugins/inline/jsenv_plugin_js_inline_content.js +4 -4
- package/src/plugins/minification/css/minify_css.js +1 -1
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +2 -4
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_html.js +5 -5
- package/src/plugins/transpilation/babel/global_this/babel_plugin_global_this_as_jsenv_import.js +1 -1
- package/src/plugins/transpilation/babel/helpers/babel_plugin_babel_helpers_as_jsenv_imports.js +2 -3
- package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +1 -1
- package/src/plugins/transpilation/babel/new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js +1 -2
- package/src/plugins/transpilation/babel/regenerator_runtime/babel_plugin_regenerator_runtime_as_jsenv_import.js +1 -2
- package/src/plugins/transpilation/css_parcel/jsenv_plugin_css_parcel.js +1 -1
- package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +1 -1
- package/src/plugins/transpilation/jsenv_plugin_top_level_await.js +2 -1
- package/src/plugins/url_analysis/css/css_urls.js +3 -3
- package/src/plugins/url_analysis/html/html_urls.js +2 -2
- package/src/plugins/url_analysis/js/js_urls.js +3 -2
- package/src/test/coverage/babel_plugin_instrument.js +82 -0
- package/src/test/coverage/coverage_reporter_html_directory.js +36 -0
- package/src/test/coverage/coverage_reporter_json_file.js +22 -0
- package/src/test/coverage/coverage_reporter_text_log.js +19 -0
- package/src/test/coverage/empty_coverage_factory.js +52 -0
- package/src/test/coverage/file_by_file_coverage.js +25 -0
- package/src/test/coverage/istanbul_coverage_composition.js +28 -0
- package/src/test/coverage/istanbul_coverage_map_from_coverage.js +16 -0
- package/src/test/coverage/list_files_not_covered.js +15 -0
- package/src/test/coverage/missing_coverage.js +41 -0
- package/src/test/coverage/report_to_coverage.js +196 -0
- package/src/test/coverage/v8_and_istanbul.js +37 -0
- package/src/test/coverage/v8_coverage_composition.js +24 -0
- package/src/test/coverage/v8_coverage_from_directory.js +87 -0
- package/src/test/coverage/v8_coverage_to_istanbul.js +99 -0
- package/src/test/execute_plan.js +2 -2
- package/src/test/execute_test_plan.js +3 -3
- package/dist/babel_helpers/readme.md +0 -8
package/dist/main.js
CHANGED
|
@@ -1,56 +1,97 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { registerFileLifecycle, readFileSync as readFileSync$1, bufferToEtag, writeFileSync, ensureWindowsDriveLetter, collectFiles, assertAndNormalizeDirectoryUrl, registerDirectoryLifecycle, writeFile, ensureEmptyDirectory, writeDirectory } from "@jsenv/filesystem";
|
|
3
|
-
import {
|
|
1
|
+
import { createSSERoom, timeStart, fetchFileSystem, composeTwoResponses, serveDirectory, startServer, pluginCORS, jsenvAccessControlAllowedHeaders, pluginServerTiming, pluginRequestWaitingCheck, composeServices, findFreePort } from "@jsenv/server";
|
|
2
|
+
import { registerFileLifecycle, readFileSync as readFileSync$1, bufferToEtag, writeFileSync, ensureWindowsDriveLetter, collectFiles, assertAndNormalizeDirectoryUrl, registerDirectoryLifecycle, writeFile, readFile, readDirectory, ensureEmptyDirectory, writeDirectory } from "@jsenv/filesystem";
|
|
3
|
+
import { createCallbackListNotifiedOnce, createCallbackList, Abort, raceProcessTeardownEvents, raceCallbacks } from "@jsenv/abort";
|
|
4
|
+
import { createDetailedMessage, createLogger, createTaskLog, loggerToLevels, byteAsFileSize, ANSI, msAsDuration, msAsEllapsedTime, byteAsMemoryUsage, UNICODE, createLog, startSpinner, distributePercentages } from "@jsenv/log";
|
|
4
5
|
import { urlToRelativeUrl, generateInlineContentUrl, ensurePathnameTrailingSlash, urlIsInsideOf, urlToFilename, DATA_URL, injectQueryParams, injectQueryParamsIntoSpecifier, fileSystemPathToUrl, urlToFileSystemPath, isFileSystemPath, normalizeUrl, stringifyUrlSite, setUrlFilename, moveUrl, getCallerPosition, resolveUrl, resolveDirectoryUrl, asUrlWithoutSearch, asUrlUntilPathname, urlToBasename, urlToExtension } from "@jsenv/urls";
|
|
5
|
-
import {
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
7
|
+
import { workerData, Worker } from "node:worker_threads";
|
|
6
8
|
import { URL_META } from "@jsenv/url-meta";
|
|
7
|
-
import { parseHtmlString, stringifyHtmlAst, visitHtmlAst, getHtmlNodeAttributeByName, htmlNodePosition, findNode, getHtmlNodeTextNode, removeHtmlNode, setHtmlNodeGeneratedText, removeHtmlNodeAttributeByName, parseScriptNode, injectScriptAsEarlyAsPossible, createHtmlNode, removeHtmlNodeText, assignHtmlNodeAttributes, parseLinkNode } from "@jsenv/utils/html_ast/html_ast.js";
|
|
8
|
-
import { htmlAttributeSrcSet } from "@jsenv/utils/html_ast/html_attribute_src_set.js";
|
|
9
|
-
import { createMagicSource } from "@jsenv/
|
|
10
|
-
import { applyPostCss } from "@jsenv/utils/css_ast/apply_post_css.js";
|
|
11
|
-
import { postCssPluginUrlVisitor } from "@jsenv/utils/css_ast/postcss_plugin_url_visitor.js";
|
|
12
|
-
import { parseJsUrls } from "@jsenv/utils/js_ast/parse_js_urls.js";
|
|
9
|
+
import { parseHtmlString, stringifyHtmlAst, visitHtmlAst, getHtmlNodeAttributeByName, htmlNodePosition, findNode, getHtmlNodeTextNode, removeHtmlNode, setHtmlNodeGeneratedText, removeHtmlNodeAttributeByName, parseScriptNode, injectScriptAsEarlyAsPossible, createHtmlNode, removeHtmlNodeText, assignHtmlNodeAttributes, parseLinkNode } from "@jsenv/utils/src/html_ast/html_ast.js";
|
|
10
|
+
import { htmlAttributeSrcSet } from "@jsenv/utils/src/html_ast/html_attribute_src_set.js";
|
|
11
|
+
import { createMagicSource, composeTwoSourcemaps, sourcemapConverter, SOURCEMAP, generateSourcemapFileUrl, generateSourcemapDataUrl } from "@jsenv/sourcemap";
|
|
12
|
+
import { applyPostCss } from "@jsenv/utils/src/css_ast/apply_post_css.js";
|
|
13
|
+
import { postCssPluginUrlVisitor } from "@jsenv/utils/src/css_ast/postcss_plugin_url_visitor.js";
|
|
14
|
+
import { parseJsUrls } from "@jsenv/utils/src/js_ast/parse_js_urls.js";
|
|
13
15
|
import { resolveImport, normalizeImportMap, composeTwoImportMaps } from "@jsenv/importmap";
|
|
14
16
|
import { applyNodeEsmResolution, defaultLookupPackageScope, defaultReadPackageJson, readCustomConditionsFromProcessArgs, applyFileSystemMagicResolution, getExtensionsToTry } from "@jsenv/node-esm-resolution";
|
|
15
17
|
import { statSync, realpathSync, readdirSync, readFileSync, existsSync } from "node:fs";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import { transpileWithParcel, minifyWithParcel } from "@jsenv/utils/css_ast/parcel_css.js";
|
|
18
|
+
import { CONTENT_TYPE } from "@jsenv/utils/src/content_type/content_type.js";
|
|
19
|
+
import { JS_QUOTES } from "@jsenv/utils/src/string/js_quotes.js";
|
|
20
|
+
import { applyBabelPlugins } from "@jsenv/utils/src/js_ast/apply_babel_plugins.js";
|
|
21
|
+
import { transpileWithParcel, minifyWithParcel } from "@jsenv/utils/src/css_ast/parcel_css.js";
|
|
21
22
|
import { createRequire } from "node:module";
|
|
22
|
-
import { composeTwoSourcemaps } from "@jsenv/utils/sourcemap/sourcemap_composition_v3.js";
|
|
23
23
|
import babelParser from "@babel/parser";
|
|
24
|
-
import { findHighestVersion } from "@jsenv/utils/semantic_versioning/highest_version.js";
|
|
25
|
-
import { injectImport } from "@jsenv/utils/js_ast/babel_utils.js";
|
|
26
|
-
import {
|
|
27
|
-
import { applyRollupPlugins } from "@jsenv/utils/js_ast/apply_rollup_plugins.js";
|
|
28
|
-
import { sourcemapConverter } from "@jsenv/utils/sourcemap/sourcemap_converter.js";
|
|
29
|
-
import { createCallbackList, createCallbackListNotifiedOnce, Abort, raceCallbacks, raceProcessTeardownEvents } from "@jsenv/abort";
|
|
30
|
-
import { createSSEService } from "@jsenv/utils/event_source/sse_service.js";
|
|
31
|
-
import { timeStart, fetchFileSystem, composeTwoResponses, serveDirectory, startServer, pluginCORS, jsenvAccessControlAllowedHeaders, pluginServerTiming, pluginRequestWaitingCheck, composeServices, findFreePort } from "@jsenv/server";
|
|
32
|
-
import { SOURCEMAP, generateSourcemapUrl, sourcemapToBase64Url } from "@jsenv/utils/sourcemap/sourcemap_utils.js";
|
|
24
|
+
import { findHighestVersion } from "@jsenv/utils/src/semantic_versioning/highest_version.js";
|
|
25
|
+
import { injectImport } from "@jsenv/utils/src/js_ast/babel_utils.js";
|
|
26
|
+
import { applyRollupPlugins } from "@jsenv/utils/src/js_ast/apply_rollup_plugins.js";
|
|
33
27
|
import { validateResponseIntegrity } from "@jsenv/integrity";
|
|
34
28
|
import { convertFileSystemErrorToResponseProperties } from "@jsenv/server/src/internal/convertFileSystemErrorToResponseProperties.js";
|
|
35
|
-
import { memoizeByFirstArgument } from "@jsenv/utils/memoize/memoize_by_first_argument.js";
|
|
36
|
-
import { generateCoverageJsonFile } from "@jsenv/utils/coverage/coverage_reporter_json_file.js";
|
|
37
|
-
import { generateCoverageHtmlDirectory } from "@jsenv/utils/coverage/coverage_reporter_html_directory.js";
|
|
38
|
-
import { generateCoverageTextLog } from "@jsenv/utils/coverage/coverage_reporter_text_log.js";
|
|
29
|
+
import { memoizeByFirstArgument } from "@jsenv/utils/src/memoize/memoize_by_first_argument.js";
|
|
39
30
|
import { memoryUsage } from "node:process";
|
|
40
31
|
import wrapAnsi from "wrap-ansi";
|
|
41
32
|
import stripAnsi from "strip-ansi";
|
|
42
33
|
import cuid from "cuid";
|
|
43
|
-
import { babelPluginInstrument } from "@jsenv/utils/coverage/babel_plugin_instrument.js";
|
|
44
|
-
import { reportToCoverage } from "@jsenv/utils/coverage/report_to_coverage.js";
|
|
45
34
|
import v8 from "node:v8";
|
|
46
35
|
import { runInNewContext, Script } from "node:vm";
|
|
47
|
-
import { memoize } from "@jsenv/utils/memoize/memoize.js";
|
|
48
|
-
import {
|
|
49
|
-
import { composeTwoFileByFileIstanbulCoverages } from "@jsenv/utils/coverage/istanbul_coverage_composition.js";
|
|
50
|
-
import { escapeRegexpSpecialChars } from "@jsenv/utils/string/escape_regexp_special_chars.js";
|
|
36
|
+
import { memoize } from "@jsenv/utils/src/memoize/memoize.js";
|
|
37
|
+
import { escapeRegexpSpecialChars } from "@jsenv/utils/src/string/escape_regexp_special_chars.js";
|
|
51
38
|
import { fork } from "node:child_process";
|
|
52
39
|
import { uneval } from "@jsenv/uneval";
|
|
53
|
-
import { createVersionGenerator } from "@jsenv/utils/versioning/version_generator.js";
|
|
40
|
+
import { createVersionGenerator } from "@jsenv/utils/src/versioning/version_generator.js";
|
|
41
|
+
|
|
42
|
+
const createReloadableWorker = (workerFileUrl, options = {}) => {
|
|
43
|
+
const workerFilePath = fileURLToPath(workerFileUrl);
|
|
44
|
+
const isPrimary = !workerData || workerData.workerFilePath !== workerFilePath;
|
|
45
|
+
let worker;
|
|
46
|
+
|
|
47
|
+
const terminate = async () => {
|
|
48
|
+
if (worker) {
|
|
49
|
+
let _worker = worker;
|
|
50
|
+
worker = null;
|
|
51
|
+
const exitPromise = new Promise(resolve => {
|
|
52
|
+
_worker.once("exit", resolve);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
_worker.terminate();
|
|
56
|
+
|
|
57
|
+
await exitPromise;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const load = async () => {
|
|
62
|
+
if (!isPrimary) {
|
|
63
|
+
throw new Error(`worker can be loaded from primary file only`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
worker = new Worker(workerFilePath, { ...options,
|
|
67
|
+
workerData: { ...options.workerData,
|
|
68
|
+
workerFilePath
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
worker.once("error", error => {
|
|
72
|
+
console.error(error);
|
|
73
|
+
});
|
|
74
|
+
await new Promise(resolve => {
|
|
75
|
+
worker.once("online", resolve);
|
|
76
|
+
});
|
|
77
|
+
worker.once("exit", () => {
|
|
78
|
+
worker = null;
|
|
79
|
+
});
|
|
80
|
+
return worker;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const reload = async () => {
|
|
84
|
+
await terminate();
|
|
85
|
+
await load();
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
isPrimary,
|
|
90
|
+
load,
|
|
91
|
+
reload,
|
|
92
|
+
terminate
|
|
93
|
+
};
|
|
94
|
+
};
|
|
54
95
|
|
|
55
96
|
const parseAndTransformHtmlUrls = async (urlInfo, context) => {
|
|
56
97
|
const url = urlInfo.originalUrl;
|
|
@@ -3386,9 +3427,13 @@ const getFeatureCompat = feature => {
|
|
|
3386
3427
|
return feature;
|
|
3387
3428
|
};
|
|
3388
3429
|
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3430
|
+
/*
|
|
3431
|
+
* Generated helpers
|
|
3432
|
+
* - https://github.com/babel/babel/commits/main/packages/babel-helpers/src/helpers.ts
|
|
3433
|
+
* File helpers
|
|
3434
|
+
* - https://github.com/babel/babel/tree/main/packages/babel-helpers/src/helpers
|
|
3435
|
+
*
|
|
3436
|
+
*/
|
|
3392
3437
|
const babelHelperClientDirectoryUrl = new URL("./babel_helpers/", import.meta.url).href; // we cannot use "@jsenv/core/src/*" because babel helper might be injected
|
|
3393
3438
|
// into node_modules not depending on "@jsenv/core"
|
|
3394
3439
|
|
|
@@ -4455,6 +4500,39 @@ const jsenvPluginNodeRuntime = ({
|
|
|
4455
4500
|
};
|
|
4456
4501
|
};
|
|
4457
4502
|
|
|
4503
|
+
const sortByDependencies = nodes => {
|
|
4504
|
+
const visited = [];
|
|
4505
|
+
const sorted = [];
|
|
4506
|
+
const circular = [];
|
|
4507
|
+
|
|
4508
|
+
const visit = url => {
|
|
4509
|
+
const isSorted = sorted.includes(url);
|
|
4510
|
+
|
|
4511
|
+
if (isSorted) {
|
|
4512
|
+
return;
|
|
4513
|
+
}
|
|
4514
|
+
|
|
4515
|
+
const isVisited = visited.includes(url);
|
|
4516
|
+
|
|
4517
|
+
if (isVisited) {
|
|
4518
|
+
circular.push(url);
|
|
4519
|
+
sorted.push(url);
|
|
4520
|
+
} else {
|
|
4521
|
+
visited.push(url);
|
|
4522
|
+
nodes[url].dependencies.forEach(dependencyUrl => {
|
|
4523
|
+
visit(dependencyUrl);
|
|
4524
|
+
});
|
|
4525
|
+
sorted.push(url);
|
|
4526
|
+
}
|
|
4527
|
+
};
|
|
4528
|
+
|
|
4529
|
+
Object.keys(nodes).forEach(url => {
|
|
4530
|
+
visit(url);
|
|
4531
|
+
});
|
|
4532
|
+
sorted.circular = circular;
|
|
4533
|
+
return sorted;
|
|
4534
|
+
};
|
|
4535
|
+
|
|
4458
4536
|
/*
|
|
4459
4537
|
* Each @import found in css is replaced by the file content
|
|
4460
4538
|
* - There is no need to worry about urls (such as background-image: url())
|
|
@@ -5633,6 +5711,60 @@ const jsenvPluginDevSSEClient = () => {
|
|
|
5633
5711
|
};
|
|
5634
5712
|
};
|
|
5635
5713
|
|
|
5714
|
+
const createSSEService = ({
|
|
5715
|
+
serverEventCallbackList
|
|
5716
|
+
}) => {
|
|
5717
|
+
const destroyCallbackList = createCallbackListNotifiedOnce();
|
|
5718
|
+
const cache = [];
|
|
5719
|
+
const sseRoomLimit = 100;
|
|
5720
|
+
|
|
5721
|
+
const getOrCreateSSERoom = request => {
|
|
5722
|
+
const htmlFileRelativeUrl = request.ressource.slice(1);
|
|
5723
|
+
const cacheEntry = cache.find(cacheEntryCandidate => cacheEntryCandidate.htmlFileRelativeUrl === htmlFileRelativeUrl);
|
|
5724
|
+
|
|
5725
|
+
if (cacheEntry) {
|
|
5726
|
+
return cacheEntry.sseRoom;
|
|
5727
|
+
}
|
|
5728
|
+
|
|
5729
|
+
const sseRoom = createSSERoom({
|
|
5730
|
+
retryDuration: 2000,
|
|
5731
|
+
historyLength: 100,
|
|
5732
|
+
welcomeEventEnabled: true,
|
|
5733
|
+
effect: () => {
|
|
5734
|
+
return serverEventCallbackList.add(event => {
|
|
5735
|
+
sseRoom.sendEvent(event);
|
|
5736
|
+
});
|
|
5737
|
+
}
|
|
5738
|
+
});
|
|
5739
|
+
const removeSSECleanupCallback = destroyCallbackList.add(() => {
|
|
5740
|
+
removeSSECleanupCallback();
|
|
5741
|
+
sseRoom.close();
|
|
5742
|
+
});
|
|
5743
|
+
cache.push({
|
|
5744
|
+
htmlFileRelativeUrl,
|
|
5745
|
+
sseRoom,
|
|
5746
|
+
cleanup: () => {
|
|
5747
|
+
removeSSECleanupCallback();
|
|
5748
|
+
sseRoom.close();
|
|
5749
|
+
}
|
|
5750
|
+
});
|
|
5751
|
+
|
|
5752
|
+
if (cache.length >= sseRoomLimit) {
|
|
5753
|
+
const firstCacheEntry = cache.shift();
|
|
5754
|
+
firstCacheEntry.cleanup();
|
|
5755
|
+
}
|
|
5756
|
+
|
|
5757
|
+
return sseRoom;
|
|
5758
|
+
};
|
|
5759
|
+
|
|
5760
|
+
return {
|
|
5761
|
+
getOrCreateSSERoom,
|
|
5762
|
+
destroy: () => {
|
|
5763
|
+
destroyCallbackList.notify();
|
|
5764
|
+
}
|
|
5765
|
+
};
|
|
5766
|
+
};
|
|
5767
|
+
|
|
5636
5768
|
const jsenvPluginDevSSEServer = ({
|
|
5637
5769
|
rootDirectoryUrl,
|
|
5638
5770
|
urlGraph,
|
|
@@ -6604,13 +6736,27 @@ const createUrlInfoTransformer = ({
|
|
|
6604
6736
|
const sourcemapsEnabled = sourcemaps === "inline" || sourcemaps === "file" || sourcemaps === "programmatic";
|
|
6605
6737
|
|
|
6606
6738
|
const normalizeSourcemap = (urlInfo, sourcemap) => {
|
|
6739
|
+
let {
|
|
6740
|
+
sources
|
|
6741
|
+
} = sourcemap;
|
|
6742
|
+
|
|
6743
|
+
if (sources) {
|
|
6744
|
+
sources = sources.map(source => {
|
|
6745
|
+
if (source && isFileSystemPath(source)) {
|
|
6746
|
+
return String(pathToFileURL(source));
|
|
6747
|
+
}
|
|
6748
|
+
|
|
6749
|
+
return source;
|
|
6750
|
+
});
|
|
6751
|
+
}
|
|
6752
|
+
|
|
6607
6753
|
const wantSourcesContent = // for inline content (<script> insdide html)
|
|
6608
6754
|
// chrome won't be able to fetch the file as it does not exists
|
|
6609
6755
|
// so sourcemap must contain sources
|
|
6610
|
-
sourcemapsSourcesContent || urlInfo.isInline ||
|
|
6756
|
+
sourcemapsSourcesContent || urlInfo.isInline || sources && sources.some(source => !source || !source.startsWith("file:"));
|
|
6611
6757
|
|
|
6612
|
-
if (
|
|
6613
|
-
sourcemap.sources =
|
|
6758
|
+
if (sources && sources.length > 1) {
|
|
6759
|
+
sourcemap.sources = sources.map(source => new URL(source, urlInfo.originalUrl).href);
|
|
6614
6760
|
|
|
6615
6761
|
if (!wantSourcesContent) {
|
|
6616
6762
|
sourcemap.sourcesContent = undefined;
|
|
@@ -6646,7 +6792,7 @@ const createUrlInfoTransformer = ({
|
|
|
6646
6792
|
// but otherwise it's generatedUrl to be inside .jsenv/ directory
|
|
6647
6793
|
|
|
6648
6794
|
|
|
6649
|
-
urlInfo.sourcemapGeneratedUrl =
|
|
6795
|
+
urlInfo.sourcemapGeneratedUrl = generateSourcemapFileUrl(urlInfo.generatedUrl);
|
|
6650
6796
|
const [sourcemapReference, sourcemapUrlInfo] = injectSourcemapPlaceholder({
|
|
6651
6797
|
urlInfo,
|
|
6652
6798
|
specifier: urlInfo.sourcemapGeneratedUrl
|
|
@@ -6752,7 +6898,7 @@ const createUrlInfoTransformer = ({
|
|
|
6752
6898
|
sourcemapUrlInfo.content = JSON.stringify(sourcemap, null, " ");
|
|
6753
6899
|
|
|
6754
6900
|
if (sourcemaps === "inline") {
|
|
6755
|
-
sourcemapReference.generatedSpecifier =
|
|
6901
|
+
sourcemapReference.generatedSpecifier = generateSourcemapDataUrl(sourcemap);
|
|
6756
6902
|
}
|
|
6757
6903
|
|
|
6758
6904
|
if (sourcemaps === "file" || sourcemaps === "inline") {
|
|
@@ -8291,7 +8437,7 @@ const jsenvPluginExplorer = ({
|
|
|
8291
8437
|
|
|
8292
8438
|
const startDevServer = async ({
|
|
8293
8439
|
signal = new AbortController().signal,
|
|
8294
|
-
handleSIGINT,
|
|
8440
|
+
handleSIGINT = true,
|
|
8295
8441
|
logLevel = "info",
|
|
8296
8442
|
omegaServerLogLevel = "warn",
|
|
8297
8443
|
port = 3456,
|
|
@@ -8311,9 +8457,9 @@ const startDevServer = async ({
|
|
|
8311
8457
|
devServerMainFile = getCallerPosition().url,
|
|
8312
8458
|
// force disable server autoreload when this code is executed:
|
|
8313
8459
|
// - inside a forked child process
|
|
8314
|
-
// -
|
|
8315
|
-
//
|
|
8316
|
-
devServerAutoreload = typeof process.send !== "function" && !
|
|
8460
|
+
// - debugged by vscode
|
|
8461
|
+
// otherwise we get net:ERR_CONNECTION_REFUSED
|
|
8462
|
+
devServerAutoreload = typeof process.send !== "function" && !process.env.VSCODE_INSPECTOR_OPTIONS,
|
|
8317
8463
|
clientFiles = {
|
|
8318
8464
|
"./src/": true,
|
|
8319
8465
|
"./test/": true
|
|
@@ -8353,32 +8499,36 @@ const startDevServer = async ({
|
|
|
8353
8499
|
logLevel
|
|
8354
8500
|
});
|
|
8355
8501
|
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl);
|
|
8356
|
-
const
|
|
8357
|
-
|
|
8358
|
-
handleSIGINT,
|
|
8359
|
-
...(devServerAutoreload ? {
|
|
8360
|
-
enabled: true,
|
|
8361
|
-
logLevel: "warn",
|
|
8362
|
-
fileToRestart: devServerMainFile
|
|
8363
|
-
} : {
|
|
8364
|
-
enabled: false
|
|
8365
|
-
})
|
|
8366
|
-
});
|
|
8502
|
+
const operation = Abort.startOperation();
|
|
8503
|
+
operation.addAbortSignal(signal);
|
|
8367
8504
|
|
|
8368
|
-
if (
|
|
8505
|
+
if (handleSIGINT) {
|
|
8506
|
+
operation.addAbortSource(abort => {
|
|
8507
|
+
return raceProcessTeardownEvents({
|
|
8508
|
+
SIGINT: true
|
|
8509
|
+
}, abort);
|
|
8510
|
+
});
|
|
8511
|
+
}
|
|
8512
|
+
|
|
8513
|
+
if (port === 0) {
|
|
8514
|
+
port = await findFreePort(port, {
|
|
8515
|
+
signal: operation.signal
|
|
8516
|
+
});
|
|
8517
|
+
}
|
|
8518
|
+
|
|
8519
|
+
const reloadableWorker = createReloadableWorker(devServerMainFile);
|
|
8520
|
+
|
|
8521
|
+
if (devServerAutoreload && reloadableWorker.isPrimary) {
|
|
8369
8522
|
const devServerFileChangeCallback = ({
|
|
8370
8523
|
relativeUrl,
|
|
8371
8524
|
event
|
|
8372
8525
|
}) => {
|
|
8373
8526
|
const url = new URL(relativeUrl, rootDirectoryUrl).href;
|
|
8374
|
-
|
|
8375
|
-
|
|
8376
|
-
logger.info(`file ${event} ${url} -> restarting server...`);
|
|
8377
|
-
reloadableProcess.reload();
|
|
8378
|
-
}
|
|
8527
|
+
logger.info(`file ${event} ${url} -> restarting server...`);
|
|
8528
|
+
reloadableWorker.reload();
|
|
8379
8529
|
};
|
|
8380
8530
|
|
|
8381
|
-
const
|
|
8531
|
+
const stopWatchingDevServerFiles = registerDirectoryLifecycle(rootDirectoryUrl, {
|
|
8382
8532
|
watchPatterns: {
|
|
8383
8533
|
[devServerMainFile]: true,
|
|
8384
8534
|
...devServerFiles
|
|
@@ -8411,14 +8561,21 @@ const startDevServer = async ({
|
|
|
8411
8561
|
});
|
|
8412
8562
|
}
|
|
8413
8563
|
});
|
|
8414
|
-
|
|
8415
|
-
|
|
8564
|
+
operation.addAbortCallback(() => {
|
|
8565
|
+
stopWatchingDevServerFiles();
|
|
8566
|
+
reloadableWorker.terminate();
|
|
8416
8567
|
});
|
|
8568
|
+
const worker = await reloadableWorker.load();
|
|
8569
|
+
|
|
8570
|
+
if (!keepProcessAlive) {
|
|
8571
|
+
worker.unref();
|
|
8572
|
+
}
|
|
8573
|
+
|
|
8417
8574
|
return {
|
|
8418
8575
|
origin: `${protocol}://127.0.0.1:${port}`,
|
|
8419
8576
|
stop: () => {
|
|
8420
|
-
|
|
8421
|
-
|
|
8577
|
+
stopWatchingDevServerFiles();
|
|
8578
|
+
reloadableWorker.terminate();
|
|
8422
8579
|
}
|
|
8423
8580
|
};
|
|
8424
8581
|
}
|
|
@@ -8537,6 +8694,679 @@ const startDevServer = async ({
|
|
|
8537
8694
|
};
|
|
8538
8695
|
};
|
|
8539
8696
|
|
|
8697
|
+
const generateCoverageJsonFile = async ({
|
|
8698
|
+
coverage,
|
|
8699
|
+
coverageJsonFileUrl,
|
|
8700
|
+
coverageJsonFileLog,
|
|
8701
|
+
logger
|
|
8702
|
+
}) => {
|
|
8703
|
+
const coverageAsText = JSON.stringify(coverage, null, " ");
|
|
8704
|
+
|
|
8705
|
+
if (coverageJsonFileLog) {
|
|
8706
|
+
logger.info(`-> ${urlToFileSystemPath(coverageJsonFileUrl)} (${byteAsFileSize(Buffer.byteLength(coverageAsText))})`);
|
|
8707
|
+
}
|
|
8708
|
+
|
|
8709
|
+
await writeFile(coverageJsonFileUrl, coverageAsText);
|
|
8710
|
+
};
|
|
8711
|
+
|
|
8712
|
+
const istanbulCoverageMapFromCoverage = coverage => {
|
|
8713
|
+
const {
|
|
8714
|
+
createCoverageMap
|
|
8715
|
+
} = requireFromJsenv("istanbul-lib-coverage");
|
|
8716
|
+
const coverageAdjusted = {};
|
|
8717
|
+
Object.keys(coverage).forEach(key => {
|
|
8718
|
+
coverageAdjusted[key.slice(2)] = { ...coverage[key],
|
|
8719
|
+
path: key.slice(2)
|
|
8720
|
+
};
|
|
8721
|
+
});
|
|
8722
|
+
const coverageMap = createCoverageMap(coverageAdjusted);
|
|
8723
|
+
return coverageMap;
|
|
8724
|
+
};
|
|
8725
|
+
|
|
8726
|
+
const generateCoverageHtmlDirectory = async (coverage, {
|
|
8727
|
+
rootDirectoryUrl,
|
|
8728
|
+
coverageHtmlDirectoryRelativeUrl,
|
|
8729
|
+
coverageSkipEmpty,
|
|
8730
|
+
coverageSkipFull
|
|
8731
|
+
}) => {
|
|
8732
|
+
const libReport = requireFromJsenv("istanbul-lib-report");
|
|
8733
|
+
const reports = requireFromJsenv("istanbul-reports");
|
|
8734
|
+
const context = libReport.createContext({
|
|
8735
|
+
dir: urlToFileSystemPath(rootDirectoryUrl),
|
|
8736
|
+
coverageMap: istanbulCoverageMapFromCoverage(coverage),
|
|
8737
|
+
sourceFinder: path => {
|
|
8738
|
+
return readFileSync(urlToFileSystemPath(resolveUrl(path, rootDirectoryUrl)), "utf8");
|
|
8739
|
+
}
|
|
8740
|
+
});
|
|
8741
|
+
const report = reports.create("html", {
|
|
8742
|
+
skipEmpty: coverageSkipEmpty,
|
|
8743
|
+
skipFull: coverageSkipFull,
|
|
8744
|
+
subdir: coverageHtmlDirectoryRelativeUrl
|
|
8745
|
+
});
|
|
8746
|
+
report.execute(context);
|
|
8747
|
+
};
|
|
8748
|
+
|
|
8749
|
+
const generateCoverageTextLog = (coverage, {
|
|
8750
|
+
coverageSkipEmpty,
|
|
8751
|
+
coverageSkipFull
|
|
8752
|
+
}) => {
|
|
8753
|
+
const libReport = requireFromJsenv("istanbul-lib-report");
|
|
8754
|
+
const reports = requireFromJsenv("istanbul-reports");
|
|
8755
|
+
const context = libReport.createContext({
|
|
8756
|
+
coverageMap: istanbulCoverageMapFromCoverage(coverage)
|
|
8757
|
+
});
|
|
8758
|
+
const report = reports.create("text", {
|
|
8759
|
+
skipEmpty: coverageSkipEmpty,
|
|
8760
|
+
skipFull: coverageSkipFull
|
|
8761
|
+
});
|
|
8762
|
+
report.execute(context);
|
|
8763
|
+
};
|
|
8764
|
+
|
|
8765
|
+
const babelPluginInstrument = (api, {
|
|
8766
|
+
rootDirectoryUrl,
|
|
8767
|
+
useInlineSourceMaps = false,
|
|
8768
|
+
coverageConfig = {
|
|
8769
|
+
"./**/*": true
|
|
8770
|
+
}
|
|
8771
|
+
}) => {
|
|
8772
|
+
const {
|
|
8773
|
+
programVisitor
|
|
8774
|
+
} = requireFromJsenv("istanbul-lib-instrument");
|
|
8775
|
+
const {
|
|
8776
|
+
types
|
|
8777
|
+
} = api;
|
|
8778
|
+
const associations = URL_META.resolveAssociations({
|
|
8779
|
+
cover: coverageConfig
|
|
8780
|
+
}, rootDirectoryUrl);
|
|
8781
|
+
|
|
8782
|
+
const shouldInstrument = url => {
|
|
8783
|
+
return URL_META.applyAssociations({
|
|
8784
|
+
url,
|
|
8785
|
+
associations
|
|
8786
|
+
}).cover;
|
|
8787
|
+
};
|
|
8788
|
+
|
|
8789
|
+
return {
|
|
8790
|
+
name: "transform-instrument",
|
|
8791
|
+
visitor: {
|
|
8792
|
+
Program: {
|
|
8793
|
+
enter(path) {
|
|
8794
|
+
const {
|
|
8795
|
+
file
|
|
8796
|
+
} = this;
|
|
8797
|
+
const {
|
|
8798
|
+
opts
|
|
8799
|
+
} = file;
|
|
8800
|
+
|
|
8801
|
+
if (!opts.sourceFileName) {
|
|
8802
|
+
console.warn(`cannot instrument file when "sourceFileName" option is not set`);
|
|
8803
|
+
return;
|
|
8804
|
+
}
|
|
8805
|
+
|
|
8806
|
+
const fileUrl = fileSystemPathToUrl(opts.sourceFileName);
|
|
8807
|
+
|
|
8808
|
+
if (!shouldInstrument(fileUrl)) {
|
|
8809
|
+
return;
|
|
8810
|
+
}
|
|
8811
|
+
|
|
8812
|
+
this.__dv__ = null;
|
|
8813
|
+
let inputSourceMap;
|
|
8814
|
+
|
|
8815
|
+
if (useInlineSourceMaps) {
|
|
8816
|
+
// https://github.com/istanbuljs/babel-plugin-istanbul/commit/a9e15643d249a2985e4387e4308022053b2cd0ad#diff-1fdf421c05c1140f6d71444ea2b27638R65
|
|
8817
|
+
inputSourceMap = opts.inputSourceMap || file.inputMap ? file.inputMap.sourcemap : null;
|
|
8818
|
+
} else {
|
|
8819
|
+
inputSourceMap = opts.inputSourceMap;
|
|
8820
|
+
}
|
|
8821
|
+
|
|
8822
|
+
this.__dv__ = programVisitor(types, opts.filenameRelative || opts.filename, {
|
|
8823
|
+
coverageVariable: "__coverage__",
|
|
8824
|
+
inputSourceMap
|
|
8825
|
+
});
|
|
8826
|
+
|
|
8827
|
+
this.__dv__.enter(path);
|
|
8828
|
+
},
|
|
8829
|
+
|
|
8830
|
+
exit(path) {
|
|
8831
|
+
if (!this.__dv__) {
|
|
8832
|
+
return;
|
|
8833
|
+
}
|
|
8834
|
+
|
|
8835
|
+
const object = this.__dv__.exit(path); // object got two properties: fileCoverage and sourceMappingURL
|
|
8836
|
+
|
|
8837
|
+
|
|
8838
|
+
this.file.metadata.coverage = object.fileCoverage;
|
|
8839
|
+
}
|
|
8840
|
+
|
|
8841
|
+
}
|
|
8842
|
+
}
|
|
8843
|
+
};
|
|
8844
|
+
};
|
|
8845
|
+
|
|
8846
|
+
const visitNodeV8Directory = async ({
|
|
8847
|
+
logger,
|
|
8848
|
+
signal,
|
|
8849
|
+
NODE_V8_COVERAGE,
|
|
8850
|
+
onV8Coverage,
|
|
8851
|
+
maxMsWaitingForNodeToWriteCoverageFile = 2000
|
|
8852
|
+
}) => {
|
|
8853
|
+
const operation = Abort.startOperation();
|
|
8854
|
+
operation.addAbortSignal(signal);
|
|
8855
|
+
|
|
8856
|
+
const tryReadDirectory = async () => {
|
|
8857
|
+
const dirContent = await readDirectory(NODE_V8_COVERAGE);
|
|
8858
|
+
|
|
8859
|
+
if (dirContent.length > 0) {
|
|
8860
|
+
return dirContent;
|
|
8861
|
+
}
|
|
8862
|
+
|
|
8863
|
+
logger.warn(`v8 coverage directory is empty at ${NODE_V8_COVERAGE}`);
|
|
8864
|
+
return dirContent;
|
|
8865
|
+
};
|
|
8866
|
+
|
|
8867
|
+
try {
|
|
8868
|
+
operation.throwIfAborted();
|
|
8869
|
+
const dirContent = await tryReadDirectory();
|
|
8870
|
+
const coverageDirectoryUrl = assertAndNormalizeDirectoryUrl(NODE_V8_COVERAGE);
|
|
8871
|
+
await dirContent.reduce(async (previous, dirEntry) => {
|
|
8872
|
+
operation.throwIfAborted();
|
|
8873
|
+
await previous;
|
|
8874
|
+
const dirEntryUrl = resolveUrl(dirEntry, coverageDirectoryUrl);
|
|
8875
|
+
|
|
8876
|
+
const tryReadJsonFile = async (timeSpentTrying = 0) => {
|
|
8877
|
+
const fileContent = await readFile(dirEntryUrl, {
|
|
8878
|
+
as: "string"
|
|
8879
|
+
});
|
|
8880
|
+
|
|
8881
|
+
if (fileContent === "") {
|
|
8882
|
+
if (timeSpentTrying < 400) {
|
|
8883
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
8884
|
+
return tryReadJsonFile(timeSpentTrying + 200);
|
|
8885
|
+
}
|
|
8886
|
+
|
|
8887
|
+
console.warn(`Coverage JSON file is empty at ${dirEntryUrl}`);
|
|
8888
|
+
return null;
|
|
8889
|
+
}
|
|
8890
|
+
|
|
8891
|
+
try {
|
|
8892
|
+
const fileAsJson = JSON.parse(fileContent);
|
|
8893
|
+
return fileAsJson;
|
|
8894
|
+
} catch (e) {
|
|
8895
|
+
if (timeSpentTrying < maxMsWaitingForNodeToWriteCoverageFile) {
|
|
8896
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
8897
|
+
return tryReadJsonFile(timeSpentTrying + 200);
|
|
8898
|
+
}
|
|
8899
|
+
|
|
8900
|
+
console.warn(createDetailedMessage(`Error while reading coverage file`, {
|
|
8901
|
+
"error stack": e.stack,
|
|
8902
|
+
"file": dirEntryUrl
|
|
8903
|
+
}));
|
|
8904
|
+
return null;
|
|
8905
|
+
}
|
|
8906
|
+
};
|
|
8907
|
+
|
|
8908
|
+
const fileContent = await tryReadJsonFile();
|
|
8909
|
+
|
|
8910
|
+
if (fileContent) {
|
|
8911
|
+
onV8Coverage(fileContent);
|
|
8912
|
+
}
|
|
8913
|
+
}, Promise.resolve());
|
|
8914
|
+
} finally {
|
|
8915
|
+
await operation.end();
|
|
8916
|
+
}
|
|
8917
|
+
};
|
|
8918
|
+
const filterV8Coverage = (v8Coverage, {
|
|
8919
|
+
urlShouldBeCovered
|
|
8920
|
+
}) => {
|
|
8921
|
+
const v8CoverageFiltered = { ...v8Coverage,
|
|
8922
|
+
result: v8Coverage.result.filter(fileReport => urlShouldBeCovered(fileReport.url))
|
|
8923
|
+
};
|
|
8924
|
+
return v8CoverageFiltered;
|
|
8925
|
+
};
|
|
8926
|
+
|
|
8927
|
+
const composeTwoV8Coverages = (firstV8Coverage, secondV8Coverage) => {
|
|
8928
|
+
if (secondV8Coverage.result.length === 0) {
|
|
8929
|
+
return firstV8Coverage;
|
|
8930
|
+
} // eslint-disable-next-line import/no-unresolved
|
|
8931
|
+
|
|
8932
|
+
|
|
8933
|
+
const {
|
|
8934
|
+
mergeProcessCovs
|
|
8935
|
+
} = requireFromJsenv("@c88/v8-coverage"); // "mergeProcessCovs" do not preserves source-map-cache during the merge
|
|
8936
|
+
// so we store sourcemap cache now
|
|
8937
|
+
|
|
8938
|
+
const sourceMapCache = {};
|
|
8939
|
+
|
|
8940
|
+
const visit = coverageReport => {
|
|
8941
|
+
if (coverageReport["source-map-cache"]) {
|
|
8942
|
+
Object.assign(sourceMapCache, coverageReport["source-map-cache"]);
|
|
8943
|
+
}
|
|
8944
|
+
};
|
|
8945
|
+
|
|
8946
|
+
visit(firstV8Coverage);
|
|
8947
|
+
visit(secondV8Coverage);
|
|
8948
|
+
const v8Coverage = mergeProcessCovs([firstV8Coverage, secondV8Coverage]);
|
|
8949
|
+
v8Coverage["source-map-cache"] = sourceMapCache;
|
|
8950
|
+
return v8Coverage;
|
|
8951
|
+
};
|
|
8952
|
+
|
|
8953
|
+
const composeTwoFileByFileIstanbulCoverages = (firstFileByFileIstanbulCoverage, secondFileByFileIstanbulCoverage) => {
|
|
8954
|
+
const fileByFileIstanbulCoverage = {};
|
|
8955
|
+
Object.keys(firstFileByFileIstanbulCoverage).forEach(key => {
|
|
8956
|
+
fileByFileIstanbulCoverage[key] = firstFileByFileIstanbulCoverage[key];
|
|
8957
|
+
});
|
|
8958
|
+
Object.keys(secondFileByFileIstanbulCoverage).forEach(key => {
|
|
8959
|
+
const firstCoverage = firstFileByFileIstanbulCoverage[key];
|
|
8960
|
+
const secondCoverage = secondFileByFileIstanbulCoverage[key];
|
|
8961
|
+
fileByFileIstanbulCoverage[key] = firstCoverage ? merge(firstCoverage, secondCoverage) : secondCoverage;
|
|
8962
|
+
});
|
|
8963
|
+
return fileByFileIstanbulCoverage;
|
|
8964
|
+
};
|
|
8965
|
+
|
|
8966
|
+
const merge = (firstIstanbulCoverage, secondIstanbulCoverage) => {
|
|
8967
|
+
const {
|
|
8968
|
+
createFileCoverage
|
|
8969
|
+
} = requireFromJsenv("istanbul-lib-coverage");
|
|
8970
|
+
const istanbulFileCoverageObject = createFileCoverage(firstIstanbulCoverage);
|
|
8971
|
+
istanbulFileCoverageObject.merge(secondIstanbulCoverage);
|
|
8972
|
+
const istanbulCoverage = istanbulFileCoverageObject.toJSON();
|
|
8973
|
+
return istanbulCoverage;
|
|
8974
|
+
};
|
|
8975
|
+
|
|
8976
|
+
const v8CoverageToIstanbul = async (v8Coverage, {
|
|
8977
|
+
signal
|
|
8978
|
+
}) => {
|
|
8979
|
+
const operation = Abort.startOperation();
|
|
8980
|
+
operation.addAbortSignal(signal);
|
|
8981
|
+
|
|
8982
|
+
try {
|
|
8983
|
+
const v8ToIstanbul = requireFromJsenv("v8-to-istanbul");
|
|
8984
|
+
const sourcemapCache = v8Coverage["source-map-cache"];
|
|
8985
|
+
let istanbulCoverageComposed = null;
|
|
8986
|
+
await v8Coverage.result.reduce(async (previous, fileV8Coverage) => {
|
|
8987
|
+
operation.throwIfAborted();
|
|
8988
|
+
await previous;
|
|
8989
|
+
const {
|
|
8990
|
+
source
|
|
8991
|
+
} = fileV8Coverage;
|
|
8992
|
+
let sources; // when v8 coverage comes from playwright (chromium) v8Coverage.source is set
|
|
8993
|
+
|
|
8994
|
+
if (typeof source === "string") {
|
|
8995
|
+
sources = {
|
|
8996
|
+
source
|
|
8997
|
+
};
|
|
8998
|
+
} // when v8 coverage comes from Node.js, the source can be read from sourcemapCache
|
|
8999
|
+
else if (sourcemapCache) {
|
|
9000
|
+
sources = sourcesFromSourceMapCache(fileV8Coverage.url, sourcemapCache);
|
|
9001
|
+
}
|
|
9002
|
+
|
|
9003
|
+
const path = urlToFileSystemPath(fileV8Coverage.url);
|
|
9004
|
+
const converter = v8ToIstanbul(path, // wrapperLength is undefined we don't need it
|
|
9005
|
+
// https://github.com/istanbuljs/v8-to-istanbul/blob/2b54bc97c5edf8a37b39a171ec29134ba9bfd532/lib/v8-to-istanbul.js#L27
|
|
9006
|
+
undefined, sources);
|
|
9007
|
+
await converter.load();
|
|
9008
|
+
converter.applyCoverage(fileV8Coverage.functions);
|
|
9009
|
+
const istanbulCoverage = converter.toIstanbul();
|
|
9010
|
+
istanbulCoverageComposed = istanbulCoverageComposed ? composeTwoFileByFileIstanbulCoverages(istanbulCoverageComposed, istanbulCoverage) : istanbulCoverage;
|
|
9011
|
+
}, Promise.resolve());
|
|
9012
|
+
|
|
9013
|
+
if (!istanbulCoverageComposed) {
|
|
9014
|
+
return {};
|
|
9015
|
+
}
|
|
9016
|
+
|
|
9017
|
+
istanbulCoverageComposed = markAsConvertedFromV8(istanbulCoverageComposed);
|
|
9018
|
+
return istanbulCoverageComposed;
|
|
9019
|
+
} finally {
|
|
9020
|
+
await operation.end();
|
|
9021
|
+
}
|
|
9022
|
+
};
|
|
9023
|
+
|
|
9024
|
+
const markAsConvertedFromV8 = fileByFileCoverage => {
|
|
9025
|
+
const fileByFileMarked = {};
|
|
9026
|
+
Object.keys(fileByFileCoverage).forEach(key => {
|
|
9027
|
+
const fileCoverage = fileByFileCoverage[key];
|
|
9028
|
+
fileByFileMarked[key] = { ...fileCoverage,
|
|
9029
|
+
fromV8: true
|
|
9030
|
+
};
|
|
9031
|
+
});
|
|
9032
|
+
return fileByFileMarked;
|
|
9033
|
+
};
|
|
9034
|
+
|
|
9035
|
+
const sourcesFromSourceMapCache = (url, sourceMapCache) => {
|
|
9036
|
+
const sourceMapAndLineLengths = sourceMapCache[url];
|
|
9037
|
+
|
|
9038
|
+
if (!sourceMapAndLineLengths) {
|
|
9039
|
+
return {};
|
|
9040
|
+
}
|
|
9041
|
+
|
|
9042
|
+
const {
|
|
9043
|
+
data,
|
|
9044
|
+
lineLengths
|
|
9045
|
+
} = sourceMapAndLineLengths; // See: https://github.com/nodejs/node/pull/34305
|
|
9046
|
+
|
|
9047
|
+
if (!data) {
|
|
9048
|
+
return undefined;
|
|
9049
|
+
}
|
|
9050
|
+
|
|
9051
|
+
const sources = {
|
|
9052
|
+
sourcemap: data,
|
|
9053
|
+
...(lineLengths ? {
|
|
9054
|
+
source: sourcesFromLineLengths(lineLengths)
|
|
9055
|
+
} : {})
|
|
9056
|
+
};
|
|
9057
|
+
return sources;
|
|
9058
|
+
};
|
|
9059
|
+
|
|
9060
|
+
const sourcesFromLineLengths = lineLengths => {
|
|
9061
|
+
let source = "";
|
|
9062
|
+
lineLengths.forEach(length => {
|
|
9063
|
+
source += `${"".padEnd(length, ".")}\n`;
|
|
9064
|
+
});
|
|
9065
|
+
return source;
|
|
9066
|
+
};
|
|
9067
|
+
|
|
9068
|
+
const composeV8AndIstanbul = (v8FileByFileCoverage, istanbulFileByFileCoverage, {
|
|
9069
|
+
coverageV8ConflictWarning
|
|
9070
|
+
}) => {
|
|
9071
|
+
const fileByFileCoverage = {};
|
|
9072
|
+
const v8Files = Object.keys(v8FileByFileCoverage);
|
|
9073
|
+
const istanbulFiles = Object.keys(istanbulFileByFileCoverage);
|
|
9074
|
+
v8Files.forEach(key => {
|
|
9075
|
+
fileByFileCoverage[key] = v8FileByFileCoverage[key];
|
|
9076
|
+
});
|
|
9077
|
+
istanbulFiles.forEach(key => {
|
|
9078
|
+
const v8Coverage = v8FileByFileCoverage[key];
|
|
9079
|
+
|
|
9080
|
+
if (v8Coverage) {
|
|
9081
|
+
if (coverageV8ConflictWarning) {
|
|
9082
|
+
console.warn(createDetailedMessage(`Coverage conflict on "${key}", found two coverage that cannot be merged together: v8 and istanbul. The istanbul coverage will be ignored.`, {
|
|
9083
|
+
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)`,
|
|
9084
|
+
suggestion: "You can disable this warning with coverageV8ConflictWarning: false"
|
|
9085
|
+
}));
|
|
9086
|
+
}
|
|
9087
|
+
|
|
9088
|
+
fileByFileCoverage[key] = v8Coverage;
|
|
9089
|
+
} else {
|
|
9090
|
+
fileByFileCoverage[key] = istanbulFileByFileCoverage[key];
|
|
9091
|
+
}
|
|
9092
|
+
});
|
|
9093
|
+
return fileByFileCoverage;
|
|
9094
|
+
};
|
|
9095
|
+
|
|
9096
|
+
const normalizeFileByFileCoveragePaths = (fileByFileCoverage, rootDirectoryUrl) => {
|
|
9097
|
+
const fileByFileNormalized = {};
|
|
9098
|
+
Object.keys(fileByFileCoverage).forEach(key => {
|
|
9099
|
+
const fileCoverage = fileByFileCoverage[key];
|
|
9100
|
+
const {
|
|
9101
|
+
path
|
|
9102
|
+
} = fileCoverage;
|
|
9103
|
+
const url = isFileSystemPath(path) ? fileSystemPathToUrl(path) : new URL(path, rootDirectoryUrl).href;
|
|
9104
|
+
const relativeUrl = urlToRelativeUrl(url, rootDirectoryUrl);
|
|
9105
|
+
fileByFileNormalized[`./${relativeUrl}`] = { ...fileCoverage,
|
|
9106
|
+
path: `./${relativeUrl}`
|
|
9107
|
+
};
|
|
9108
|
+
});
|
|
9109
|
+
return fileByFileNormalized;
|
|
9110
|
+
};
|
|
9111
|
+
|
|
9112
|
+
const listRelativeFileUrlToCover = async ({
|
|
9113
|
+
signal,
|
|
9114
|
+
rootDirectoryUrl,
|
|
9115
|
+
coverageConfig
|
|
9116
|
+
}) => {
|
|
9117
|
+
const matchingFileResultArray = await collectFiles({
|
|
9118
|
+
signal,
|
|
9119
|
+
directoryUrl: rootDirectoryUrl,
|
|
9120
|
+
associations: {
|
|
9121
|
+
cover: coverageConfig
|
|
9122
|
+
},
|
|
9123
|
+
predicate: ({
|
|
9124
|
+
cover
|
|
9125
|
+
}) => cover
|
|
9126
|
+
});
|
|
9127
|
+
return matchingFileResultArray.map(({
|
|
9128
|
+
relativeUrl
|
|
9129
|
+
}) => relativeUrl);
|
|
9130
|
+
};
|
|
9131
|
+
|
|
9132
|
+
const relativeUrlToEmptyCoverage = async (relativeUrl, {
|
|
9133
|
+
signal,
|
|
9134
|
+
rootDirectoryUrl
|
|
9135
|
+
}) => {
|
|
9136
|
+
const operation = Abort.startOperation();
|
|
9137
|
+
operation.addAbortSignal(signal);
|
|
9138
|
+
|
|
9139
|
+
try {
|
|
9140
|
+
const fileUrl = resolveUrl(relativeUrl, rootDirectoryUrl);
|
|
9141
|
+
const content = await readFile(fileUrl, {
|
|
9142
|
+
as: "string"
|
|
9143
|
+
});
|
|
9144
|
+
operation.throwIfAborted();
|
|
9145
|
+
const {
|
|
9146
|
+
metadata
|
|
9147
|
+
} = await applyBabelPlugins({
|
|
9148
|
+
babelPlugins: [[babelPluginInstrument, {
|
|
9149
|
+
rootDirectoryUrl
|
|
9150
|
+
}]],
|
|
9151
|
+
urlInfo: {
|
|
9152
|
+
originalUrl: fileUrl,
|
|
9153
|
+
content
|
|
9154
|
+
}
|
|
9155
|
+
});
|
|
9156
|
+
const {
|
|
9157
|
+
coverage
|
|
9158
|
+
} = metadata;
|
|
9159
|
+
|
|
9160
|
+
if (!coverage) {
|
|
9161
|
+
throw new Error(`missing coverage for file`);
|
|
9162
|
+
} // https://github.com/gotwarlost/istanbul/blob/bc84c315271a5dd4d39bcefc5925cfb61a3d174a/lib/command/common/run-with-cover.js#L229
|
|
9163
|
+
|
|
9164
|
+
|
|
9165
|
+
Object.keys(coverage.s).forEach(function (key) {
|
|
9166
|
+
coverage.s[key] = 0;
|
|
9167
|
+
});
|
|
9168
|
+
return coverage;
|
|
9169
|
+
} catch (e) {
|
|
9170
|
+
if (e && e.code === "PARSE_ERROR") {
|
|
9171
|
+
// return an empty coverage for that file when
|
|
9172
|
+
// it contains a syntax error
|
|
9173
|
+
return createEmptyCoverage(relativeUrl);
|
|
9174
|
+
}
|
|
9175
|
+
|
|
9176
|
+
throw e;
|
|
9177
|
+
} finally {
|
|
9178
|
+
await operation.end();
|
|
9179
|
+
}
|
|
9180
|
+
};
|
|
9181
|
+
|
|
9182
|
+
const createEmptyCoverage = relativeUrl => {
|
|
9183
|
+
const {
|
|
9184
|
+
createFileCoverage
|
|
9185
|
+
} = requireFromJsenv("istanbul-lib-coverage");
|
|
9186
|
+
return createFileCoverage(relativeUrl).toJSON();
|
|
9187
|
+
};
|
|
9188
|
+
|
|
9189
|
+
const getMissingFileByFileCoverage = async ({
|
|
9190
|
+
signal,
|
|
9191
|
+
rootDirectoryUrl,
|
|
9192
|
+
coverageConfig,
|
|
9193
|
+
fileByFileCoverage
|
|
9194
|
+
}) => {
|
|
9195
|
+
const relativeUrlsToCover = await listRelativeFileUrlToCover({
|
|
9196
|
+
signal,
|
|
9197
|
+
rootDirectoryUrl,
|
|
9198
|
+
coverageConfig
|
|
9199
|
+
});
|
|
9200
|
+
const relativeUrlsMissing = relativeUrlsToCover.filter(relativeUrlToCover => Object.keys(fileByFileCoverage).every(key => {
|
|
9201
|
+
return key !== `./${relativeUrlToCover}`;
|
|
9202
|
+
}));
|
|
9203
|
+
const operation = Abort.startOperation();
|
|
9204
|
+
operation.addAbortSignal(signal);
|
|
9205
|
+
const missingFileByFileCoverage = {};
|
|
9206
|
+
await relativeUrlsMissing.reduce(async (previous, relativeUrlMissing) => {
|
|
9207
|
+
operation.throwIfAborted();
|
|
9208
|
+
await previous;
|
|
9209
|
+
await operation.withSignal(async signal => {
|
|
9210
|
+
const emptyCoverage = await relativeUrlToEmptyCoverage(relativeUrlMissing, {
|
|
9211
|
+
signal,
|
|
9212
|
+
rootDirectoryUrl
|
|
9213
|
+
});
|
|
9214
|
+
missingFileByFileCoverage[`./${relativeUrlMissing}`] = emptyCoverage;
|
|
9215
|
+
});
|
|
9216
|
+
}, Promise.resolve());
|
|
9217
|
+
return missingFileByFileCoverage;
|
|
9218
|
+
};
|
|
9219
|
+
|
|
9220
|
+
const reportToCoverage = async (report, {
|
|
9221
|
+
signal,
|
|
9222
|
+
logger,
|
|
9223
|
+
rootDirectoryUrl,
|
|
9224
|
+
coverageConfig,
|
|
9225
|
+
coverageIncludeMissing,
|
|
9226
|
+
urlShouldBeCovered,
|
|
9227
|
+
coverageForceIstanbul,
|
|
9228
|
+
coverageV8ConflictWarning
|
|
9229
|
+
}) => {
|
|
9230
|
+
// collect v8 and istanbul coverage from executions
|
|
9231
|
+
let {
|
|
9232
|
+
v8Coverage,
|
|
9233
|
+
fileByFileIstanbulCoverage
|
|
9234
|
+
} = await getCoverageFromReport({
|
|
9235
|
+
signal,
|
|
9236
|
+
report,
|
|
9237
|
+
onMissing: ({
|
|
9238
|
+
file,
|
|
9239
|
+
executionResult,
|
|
9240
|
+
executionName
|
|
9241
|
+
}) => {
|
|
9242
|
+
// several reasons not to have coverage here:
|
|
9243
|
+
// 1. the file we executed did not import an instrumented file.
|
|
9244
|
+
// - a test file without import
|
|
9245
|
+
// - a test file importing only file excluded from coverage
|
|
9246
|
+
// - a coverDescription badly configured so that we don't realize
|
|
9247
|
+
// a file should be covered
|
|
9248
|
+
// 2. the file we wanted to executed timedout
|
|
9249
|
+
// - infinite loop
|
|
9250
|
+
// - too extensive operation
|
|
9251
|
+
// - a badly configured or too low allocatedMs for that execution.
|
|
9252
|
+
// 3. the file we wanted to execute contains syntax-error
|
|
9253
|
+
// in any scenario we are fine because
|
|
9254
|
+
// coverDescription will generate empty coverage for files
|
|
9255
|
+
// that were suppose to be coverage but were not.
|
|
9256
|
+
if (executionResult.status === "completed" && executionResult.runtimeName !== "node" && !process.env.NODE_V8_COVERAGE) {
|
|
9257
|
+
logger.warn(`No execution.coverageFileUrl from execution named "${executionName}" of ${file}`);
|
|
9258
|
+
}
|
|
9259
|
+
}
|
|
9260
|
+
});
|
|
9261
|
+
|
|
9262
|
+
if (!coverageForceIstanbul && process.env.NODE_V8_COVERAGE) {
|
|
9263
|
+
await visitNodeV8Directory({
|
|
9264
|
+
logger,
|
|
9265
|
+
signal,
|
|
9266
|
+
NODE_V8_COVERAGE: process.env.NODE_V8_COVERAGE,
|
|
9267
|
+
onV8Coverage: nodeV8Coverage => {
|
|
9268
|
+
const nodeV8CoverageLight = filterV8Coverage(nodeV8Coverage, {
|
|
9269
|
+
urlShouldBeCovered
|
|
9270
|
+
});
|
|
9271
|
+
v8Coverage = v8Coverage ? composeTwoV8Coverages(v8Coverage, nodeV8CoverageLight) : nodeV8CoverageLight;
|
|
9272
|
+
}
|
|
9273
|
+
});
|
|
9274
|
+
} // try to merge v8 with istanbul, if any
|
|
9275
|
+
|
|
9276
|
+
|
|
9277
|
+
let fileByFileCoverage;
|
|
9278
|
+
|
|
9279
|
+
if (v8Coverage) {
|
|
9280
|
+
let v8FileByFileCoverage = await v8CoverageToIstanbul(v8Coverage, {
|
|
9281
|
+
signal
|
|
9282
|
+
});
|
|
9283
|
+
v8FileByFileCoverage = normalizeFileByFileCoveragePaths(v8FileByFileCoverage, rootDirectoryUrl);
|
|
9284
|
+
|
|
9285
|
+
if (fileByFileIstanbulCoverage) {
|
|
9286
|
+
fileByFileIstanbulCoverage = normalizeFileByFileCoveragePaths(fileByFileIstanbulCoverage, rootDirectoryUrl);
|
|
9287
|
+
fileByFileCoverage = composeV8AndIstanbul(v8FileByFileCoverage, fileByFileIstanbulCoverage, {
|
|
9288
|
+
coverageV8ConflictWarning
|
|
9289
|
+
});
|
|
9290
|
+
} else {
|
|
9291
|
+
fileByFileCoverage = v8FileByFileCoverage;
|
|
9292
|
+
}
|
|
9293
|
+
} // get istanbul only
|
|
9294
|
+
else if (fileByFileIstanbulCoverage) {
|
|
9295
|
+
fileByFileCoverage = normalizeFileByFileCoveragePaths(fileByFileIstanbulCoverage, rootDirectoryUrl);
|
|
9296
|
+
} // no coverage found in execution (or zero file where executed)
|
|
9297
|
+
else {
|
|
9298
|
+
fileByFileCoverage = {};
|
|
9299
|
+
} // now add coverage for file not covered
|
|
9300
|
+
|
|
9301
|
+
|
|
9302
|
+
if (coverageIncludeMissing) {
|
|
9303
|
+
const missingFileByFileCoverage = await getMissingFileByFileCoverage({
|
|
9304
|
+
signal,
|
|
9305
|
+
rootDirectoryUrl,
|
|
9306
|
+
coverageConfig,
|
|
9307
|
+
fileByFileCoverage
|
|
9308
|
+
});
|
|
9309
|
+
Object.assign(fileByFileCoverage, normalizeFileByFileCoveragePaths(missingFileByFileCoverage, rootDirectoryUrl));
|
|
9310
|
+
}
|
|
9311
|
+
|
|
9312
|
+
return fileByFileCoverage;
|
|
9313
|
+
};
|
|
9314
|
+
|
|
9315
|
+
const getCoverageFromReport = async ({
|
|
9316
|
+
signal,
|
|
9317
|
+
report,
|
|
9318
|
+
onMissing
|
|
9319
|
+
}) => {
|
|
9320
|
+
const operation = Abort.startOperation();
|
|
9321
|
+
operation.addAbortSignal(signal);
|
|
9322
|
+
|
|
9323
|
+
try {
|
|
9324
|
+
let v8Coverage;
|
|
9325
|
+
let fileByFileIstanbulCoverage; // collect v8 and istanbul coverage from executions
|
|
9326
|
+
|
|
9327
|
+
await Object.keys(report).reduce(async (previous, file) => {
|
|
9328
|
+
operation.throwIfAborted();
|
|
9329
|
+
await previous;
|
|
9330
|
+
const executionResultForFile = report[file];
|
|
9331
|
+
await Object.keys(executionResultForFile).reduce(async (previous, executionName) => {
|
|
9332
|
+
operation.throwIfAborted();
|
|
9333
|
+
await previous;
|
|
9334
|
+
const executionResultForFileOnRuntime = executionResultForFile[executionName];
|
|
9335
|
+
const {
|
|
9336
|
+
coverageFileUrl
|
|
9337
|
+
} = executionResultForFileOnRuntime;
|
|
9338
|
+
|
|
9339
|
+
if (!coverageFileUrl) {
|
|
9340
|
+
onMissing({
|
|
9341
|
+
executionName,
|
|
9342
|
+
file,
|
|
9343
|
+
executionResult: executionResultForFileOnRuntime
|
|
9344
|
+
});
|
|
9345
|
+
return;
|
|
9346
|
+
}
|
|
9347
|
+
|
|
9348
|
+
const executionCoverage = await readFile(coverageFileUrl, {
|
|
9349
|
+
as: "json"
|
|
9350
|
+
});
|
|
9351
|
+
|
|
9352
|
+
if (isV8Coverage(executionCoverage)) {
|
|
9353
|
+
v8Coverage = v8Coverage ? composeTwoV8Coverages(v8Coverage, executionCoverage) : executionCoverage;
|
|
9354
|
+
} else {
|
|
9355
|
+
fileByFileIstanbulCoverage = fileByFileIstanbulCoverage ? composeTwoFileByFileIstanbulCoverages(fileByFileIstanbulCoverage, executionCoverage) : executionCoverage;
|
|
9356
|
+
}
|
|
9357
|
+
}, Promise.resolve());
|
|
9358
|
+
}, Promise.resolve());
|
|
9359
|
+
return {
|
|
9360
|
+
v8Coverage,
|
|
9361
|
+
fileByFileIstanbulCoverage
|
|
9362
|
+
};
|
|
9363
|
+
} finally {
|
|
9364
|
+
await operation.end();
|
|
9365
|
+
}
|
|
9366
|
+
};
|
|
9367
|
+
|
|
9368
|
+
const isV8Coverage = coverage => Boolean(coverage.result);
|
|
9369
|
+
|
|
8540
9370
|
const run = async ({
|
|
8541
9371
|
signal = new AbortController().signal,
|
|
8542
9372
|
logger,
|
|
@@ -12296,7 +13126,7 @@ build ${entryPointKeys.length} entry points`);
|
|
|
12296
13126
|
|
|
12297
13127
|
if (reference.type === "sourcemap_comment") {
|
|
12298
13128
|
// inherit parent build url
|
|
12299
|
-
return
|
|
13129
|
+
return generateSourcemapFileUrl(reference.parentUrl);
|
|
12300
13130
|
} // files generated during the final graph:
|
|
12301
13131
|
// - sourcemaps
|
|
12302
13132
|
// const finalUrlInfo = finalGraph.getUrlInfo(url)
|
|
@@ -13022,6 +13852,7 @@ const startBuildServer = async ({
|
|
|
13022
13852
|
ip,
|
|
13023
13853
|
port = 9779,
|
|
13024
13854
|
services = {},
|
|
13855
|
+
keepProcessAlive = true,
|
|
13025
13856
|
rootDirectoryUrl,
|
|
13026
13857
|
buildDirectoryUrl,
|
|
13027
13858
|
mainBuildFileUrl = "/index.html",
|
|
@@ -13032,9 +13863,9 @@ const startBuildServer = async ({
|
|
|
13032
13863
|
buildServerMainFile = getCallerPosition().url,
|
|
13033
13864
|
// force disable server autoreload when this code is executed:
|
|
13034
13865
|
// - inside a forked child process
|
|
13035
|
-
// -
|
|
13036
|
-
//
|
|
13037
|
-
buildServerAutoreload = typeof process.send !== "function" && !
|
|
13866
|
+
// - debugged by vscode
|
|
13867
|
+
// otherwise we get net:ERR_CONNECTION_REFUSED
|
|
13868
|
+
buildServerAutoreload = typeof process.send !== "function" && !process.env.VSCODE_INSPECTOR_OPTIONS,
|
|
13038
13869
|
cooldownBetweenFileEvents
|
|
13039
13870
|
}) => {
|
|
13040
13871
|
const logger = createLogger({
|
|
@@ -13042,19 +13873,26 @@ const startBuildServer = async ({
|
|
|
13042
13873
|
});
|
|
13043
13874
|
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl);
|
|
13044
13875
|
buildDirectoryUrl = assertAndNormalizeDirectoryUrl(buildDirectoryUrl);
|
|
13045
|
-
const
|
|
13046
|
-
|
|
13047
|
-
handleSIGINT,
|
|
13048
|
-
...(buildServerAutoreload ? {
|
|
13049
|
-
enabled: true,
|
|
13050
|
-
logLevel: "info",
|
|
13051
|
-
fileToRestart: buildServerMainFile
|
|
13052
|
-
} : {
|
|
13053
|
-
enabled: false
|
|
13054
|
-
})
|
|
13055
|
-
});
|
|
13876
|
+
const operation = Abort.startOperation();
|
|
13877
|
+
operation.addAbortSignal(signal);
|
|
13056
13878
|
|
|
13057
|
-
if (
|
|
13879
|
+
if (handleSIGINT) {
|
|
13880
|
+
operation.addAbortSource(abort => {
|
|
13881
|
+
return raceProcessTeardownEvents({
|
|
13882
|
+
SIGINT: true
|
|
13883
|
+
}, abort);
|
|
13884
|
+
});
|
|
13885
|
+
}
|
|
13886
|
+
|
|
13887
|
+
if (port === 0) {
|
|
13888
|
+
port = await findFreePort(port, {
|
|
13889
|
+
signal: operation.signal
|
|
13890
|
+
});
|
|
13891
|
+
}
|
|
13892
|
+
|
|
13893
|
+
const reloadableWorker = createReloadableWorker(buildServerMainFile);
|
|
13894
|
+
|
|
13895
|
+
if (buildServerAutoreload && reloadableWorker.isPrimary) {
|
|
13058
13896
|
const buildServerFileChangeCallback = ({
|
|
13059
13897
|
relativeUrl,
|
|
13060
13898
|
event
|
|
@@ -13063,7 +13901,7 @@ const startBuildServer = async ({
|
|
|
13063
13901
|
|
|
13064
13902
|
if (buildServerAutoreload) {
|
|
13065
13903
|
logger.info(`file ${event} ${url} -> restarting server...`);
|
|
13066
|
-
|
|
13904
|
+
reloadableWorker.reload();
|
|
13067
13905
|
}
|
|
13068
13906
|
};
|
|
13069
13907
|
|
|
@@ -13100,19 +13938,25 @@ const startBuildServer = async ({
|
|
|
13100
13938
|
});
|
|
13101
13939
|
}
|
|
13102
13940
|
});
|
|
13103
|
-
|
|
13941
|
+
operation.addAbortCallback(() => {
|
|
13104
13942
|
stopWatchingBuildServerFiles();
|
|
13943
|
+
reloadableWorker.terminate();
|
|
13105
13944
|
});
|
|
13945
|
+
const worker = await reloadableWorker.load();
|
|
13946
|
+
|
|
13947
|
+
if (!keepProcessAlive) {
|
|
13948
|
+
worker.unref();
|
|
13949
|
+
}
|
|
13950
|
+
|
|
13106
13951
|
return {
|
|
13107
13952
|
origin: `${protocol}://127.0.0.1:${port}`,
|
|
13108
13953
|
stop: () => {
|
|
13109
13954
|
stopWatchingBuildServerFiles();
|
|
13110
|
-
|
|
13955
|
+
reloadableWorker.terminate();
|
|
13111
13956
|
}
|
|
13112
13957
|
};
|
|
13113
13958
|
}
|
|
13114
13959
|
|
|
13115
|
-
signal = reloadableProcess.signal;
|
|
13116
13960
|
const startBuildServerTask = createTaskLog("start build server", {
|
|
13117
13961
|
disabled: !loggerToLevels(logger).info
|
|
13118
13962
|
});
|