@jsenv/core 27.8.1 → 28.0.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/js/autoreload.js +2 -2
- package/dist/js/html_supervisor_installer.js +3 -3
- package/dist/js/{wrapper.mjs → ws.js} +0 -0
- package/dist/main.js +540 -481
- package/package.json +2 -2
- package/readme.md +1 -1
- package/src/build/build.js +8 -8
- package/src/build/{resync_ressource_hints.js → resync_resource_hints.js} +10 -12
- package/src/build/start_build_server.js +6 -9
- package/src/dev/start_dev_server.js +2 -2
- package/src/execute/execute.js +14 -52
- package/src/execute/runtimes/browsers/from_playwright.js +19 -8
- package/src/main.js +3 -0
- package/src/omega/kitchen.js +21 -5
- package/src/omega/omega_server.js +2 -2
- package/src/omega/server/file_service.js +3 -3
- package/src/omega/url_graph/url_graph_load.js +4 -4
- package/src/omega/url_graph.js +3 -3
- package/src/ping_server.js +30 -0
- package/src/plugins/autoreload/client/reload.js +2 -2
- package/src/plugins/autoreload/jsenv_plugin_autoreload_client.js +1 -1
- package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +3 -3
- package/src/plugins/autoreload/jsenv_plugin_hmr.js +1 -1
- package/src/plugins/explorer/jsenv_plugin_explorer.js +1 -1
- package/src/plugins/html_supervisor/client/error_formatter.js +3 -3
- package/src/plugins/html_supervisor/jsenv_plugin_html_supervisor.js +5 -5
- package/src/plugins/import_meta_hot/html_hot_dependencies.js +4 -4
- package/src/plugins/import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js +1 -9
- package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +2 -13
- package/src/plugins/plugin_controller.js +2 -2
- package/src/plugins/toolbar/jsenv_plugin_toolbar.js +1 -1
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +2 -2
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_html.js +3 -3
- package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +13 -0
- package/src/plugins/url_analysis/html/html_urls.js +2 -2
- package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +1 -1
- package/src/test/execute_plan.js +15 -68
- package/src/test/execute_test_plan.js +4 -26
package/dist/main.js
CHANGED
|
@@ -12,10 +12,10 @@ import { createMagicSource, composeTwoSourcemaps, getOriginalPosition, sourcemap
|
|
|
12
12
|
import { parseHtmlString, stringifyHtmlAst, visitHtmlNodes, getHtmlNodeAttribute, analyzeScriptNode, setHtmlNodeAttributes, parseSrcSet, getHtmlNodePosition, getHtmlNodeAttributePosition, applyPostCss, postCssPluginUrlVisitor, parseJsUrls, getHtmlNodeText, setHtmlNodeText, applyBabelPlugins, injectScriptNodeAsEarlyAsPossible, createHtmlNode, findHtmlNode, removeHtmlNode, removeHtmlNodeText, transpileWithParcel, injectJsImport, minifyWithParcel, analyzeLinkNode } from "@jsenv/ast";
|
|
13
13
|
import { createRequire } from "node:module";
|
|
14
14
|
import babelParser from "@babel/parser";
|
|
15
|
+
import net, { createServer, isIP } from "node:net";
|
|
15
16
|
import http from "node:http";
|
|
16
17
|
import cluster from "node:cluster";
|
|
17
18
|
import { performance as performance$1 } from "node:perf_hooks";
|
|
18
|
-
import net, { createServer } from "node:net";
|
|
19
19
|
import { Readable, Stream, Writable } from "node:stream";
|
|
20
20
|
import { Http2ServerResponse } from "node:http2";
|
|
21
21
|
import { lookup } from "node:dns";
|
|
@@ -94,7 +94,7 @@ const urlToScheme$1 = url => {
|
|
|
94
94
|
return scheme;
|
|
95
95
|
};
|
|
96
96
|
|
|
97
|
-
const
|
|
97
|
+
const urlToResource = url => {
|
|
98
98
|
const scheme = urlToScheme$1(url);
|
|
99
99
|
|
|
100
100
|
if (scheme === "file") {
|
|
@@ -115,25 +115,25 @@ const urlToRessource$1 = url => {
|
|
|
115
115
|
};
|
|
116
116
|
|
|
117
117
|
const urlToPathname$1 = url => {
|
|
118
|
-
const
|
|
119
|
-
const pathname =
|
|
118
|
+
const resource = urlToResource(url);
|
|
119
|
+
const pathname = resourceToPathname(resource);
|
|
120
120
|
return pathname;
|
|
121
121
|
};
|
|
122
122
|
|
|
123
|
-
const
|
|
124
|
-
const searchSeparatorIndex =
|
|
123
|
+
const resourceToPathname = resource => {
|
|
124
|
+
const searchSeparatorIndex = resource.indexOf("?");
|
|
125
125
|
|
|
126
126
|
if (searchSeparatorIndex > -1) {
|
|
127
|
-
return
|
|
127
|
+
return resource.slice(0, searchSeparatorIndex);
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
const hashIndex =
|
|
130
|
+
const hashIndex = resource.indexOf("#");
|
|
131
131
|
|
|
132
132
|
if (hashIndex > -1) {
|
|
133
|
-
return
|
|
133
|
+
return resource.slice(0, hashIndex);
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
return
|
|
136
|
+
return resource;
|
|
137
137
|
};
|
|
138
138
|
|
|
139
139
|
const urlToFilename$1 = url => {
|
|
@@ -616,8 +616,8 @@ const urlToRelativeUrl = (url, baseUrl) => {
|
|
|
616
616
|
} = urlObject;
|
|
617
617
|
|
|
618
618
|
if (pathname === "/") {
|
|
619
|
-
const
|
|
620
|
-
return
|
|
619
|
+
const baseUrlResourceWithoutLeadingSlash = baseUrlObject.pathname.slice(1);
|
|
620
|
+
return baseUrlResourceWithoutLeadingSlash;
|
|
621
621
|
}
|
|
622
622
|
|
|
623
623
|
const basePathname = baseUrlObject.pathname;
|
|
@@ -2006,10 +2006,10 @@ const ensureWindowsDriveLetter = (url, baseUrl) => {
|
|
|
2006
2006
|
return `file:///${driveLetter}:${afterProtocol}`;
|
|
2007
2007
|
};
|
|
2008
2008
|
|
|
2009
|
-
const extractDriveLetter =
|
|
2009
|
+
const extractDriveLetter = resource => {
|
|
2010
2010
|
// we still have the windows drive letter
|
|
2011
|
-
if (/[a-zA-Z]/.test(
|
|
2012
|
-
return
|
|
2011
|
+
if (/[a-zA-Z]/.test(resource[1]) && resource[2] === ":") {
|
|
2012
|
+
return resource[1];
|
|
2013
2013
|
}
|
|
2014
2014
|
|
|
2015
2015
|
return null;
|
|
@@ -2136,7 +2136,7 @@ const createWatcher = (sourcePath, options) => {
|
|
|
2136
2136
|
return watcher;
|
|
2137
2137
|
};
|
|
2138
2138
|
|
|
2139
|
-
const
|
|
2139
|
+
const trackResources = () => {
|
|
2140
2140
|
const callbackArray = [];
|
|
2141
2141
|
|
|
2142
2142
|
const registerCleanupCallback = callback => {
|
|
@@ -2244,7 +2244,7 @@ const registerDirectoryLifecycle = (source, {
|
|
|
2244
2244
|
return watch;
|
|
2245
2245
|
};
|
|
2246
2246
|
|
|
2247
|
-
const tracker =
|
|
2247
|
+
const tracker = trackResources();
|
|
2248
2248
|
const infoMap = new Map();
|
|
2249
2249
|
|
|
2250
2250
|
const readEntryInfo = url => {
|
|
@@ -2380,7 +2380,7 @@ const registerDirectoryLifecycle = (source, {
|
|
|
2380
2380
|
|
|
2381
2381
|
if (entryInfo.type !== previousInfo.type) {
|
|
2382
2382
|
// it existed and was replaced by something else
|
|
2383
|
-
// we don't handle this as an update. We rather say the
|
|
2383
|
+
// we don't handle this as an update. We rather say the resource
|
|
2384
2384
|
// is lost and something else is found (call removed() then added())
|
|
2385
2385
|
handleEntryLost(previousInfo);
|
|
2386
2386
|
handleEntryFound(entryInfo);
|
|
@@ -2591,7 +2591,7 @@ const registerFileLifecycle = (source, {
|
|
|
2591
2591
|
}
|
|
2592
2592
|
}
|
|
2593
2593
|
|
|
2594
|
-
const tracker =
|
|
2594
|
+
const tracker = trackResources();
|
|
2595
2595
|
|
|
2596
2596
|
const handleFileFound = ({
|
|
2597
2597
|
existent
|
|
@@ -4014,10 +4014,10 @@ const createUrlGraph = ({
|
|
|
4014
4014
|
}
|
|
4015
4015
|
|
|
4016
4016
|
references.forEach(reference => {
|
|
4017
|
-
if (reference.
|
|
4018
|
-
//
|
|
4017
|
+
if (reference.isResourceHint) {
|
|
4018
|
+
// resource hint are a special kind of reference.
|
|
4019
4019
|
// They are a sort of weak reference to an url.
|
|
4020
|
-
// We ignore them so that url referenced only by
|
|
4020
|
+
// We ignore them so that url referenced only by resource hints
|
|
4021
4021
|
// have url.dependents.size === 0 and can be considered as not used
|
|
4022
4022
|
// It means html won't consider url referenced solely
|
|
4023
4023
|
// by <link> as dependency and it's fine
|
|
@@ -4243,7 +4243,7 @@ const parseAndTransformHtmlUrls = async (urlInfo, context) => {
|
|
|
4243
4243
|
crossorigin,
|
|
4244
4244
|
integrity
|
|
4245
4245
|
} = readFetchMetas(node);
|
|
4246
|
-
const
|
|
4246
|
+
const isResourceHint = ["preconnect", "dns-prefetch", "prefetch", "preload", "modulepreload"].includes(subtype);
|
|
4247
4247
|
const [reference] = referenceUtils.found({
|
|
4248
4248
|
type,
|
|
4249
4249
|
expectedType,
|
|
@@ -4252,7 +4252,7 @@ const parseAndTransformHtmlUrls = async (urlInfo, context) => {
|
|
|
4252
4252
|
specifier,
|
|
4253
4253
|
specifierLine: line,
|
|
4254
4254
|
specifierColumn: column,
|
|
4255
|
-
|
|
4255
|
+
isResourceHint,
|
|
4256
4256
|
crossorigin,
|
|
4257
4257
|
integrity
|
|
4258
4258
|
});
|
|
@@ -4669,7 +4669,7 @@ const jsenvPluginUrlAnalysis = ({
|
|
|
4669
4669
|
return;
|
|
4670
4670
|
}
|
|
4671
4671
|
|
|
4672
|
-
if (reference.specifier[0] === "#" && // For Html, css and in general "#" refer to a
|
|
4672
|
+
if (reference.specifier[0] === "#" && // For Html, css and in general "#" refer to a resource in the page
|
|
4673
4673
|
// so that urls must be kept intact
|
|
4674
4674
|
// However for js import specifiers they have a different meaning and we want
|
|
4675
4675
|
// to resolve them (https://nodejs.org/api/packages.html#imports for instance)
|
|
@@ -5825,10 +5825,10 @@ const jsenvPluginAsJsClassicHtml = ({
|
|
|
5825
5825
|
const convertedUrls = [];
|
|
5826
5826
|
|
|
5827
5827
|
const getReferenceAsJsClassic = async (reference, {
|
|
5828
|
-
// we don't cook
|
|
5829
|
-
// because they might refer to
|
|
5828
|
+
// we don't cook resource hints
|
|
5829
|
+
// because they might refer to resource that will be modified during build
|
|
5830
5830
|
// It also means something else HAVE to reference that url in order to cook it
|
|
5831
|
-
// so that the preload is deleted by "
|
|
5831
|
+
// so that the preload is deleted by "resync_resource_hints.js" otherwise
|
|
5832
5832
|
cookIt = false
|
|
5833
5833
|
} = {}) => {
|
|
5834
5834
|
const newReferenceProps = {
|
|
@@ -10451,7 +10451,7 @@ const jsenvPluginAsJsClassicConversion = ({
|
|
|
10451
10451
|
// - import specifier (static/dynamic import + re-export)
|
|
10452
10452
|
// - url specifier when inside System.register/_context.import()
|
|
10453
10453
|
// (because it's the transpiled equivalent of static and dynamic imports)
|
|
10454
|
-
// And not other references otherwise we could try to transform inline
|
|
10454
|
+
// And not other references otherwise we could try to transform inline resources
|
|
10455
10455
|
// or specifiers inside new URL()...
|
|
10456
10456
|
js_import_export: propagateJsClassicSearchParam,
|
|
10457
10457
|
js_url_specifier: (reference, context) => {
|
|
@@ -10468,7 +10468,7 @@ const jsenvPluginAsJsClassicConversion = ({
|
|
|
10468
10468
|
context,
|
|
10469
10469
|
searchParam: "as_js_classic",
|
|
10470
10470
|
// override the expectedType to "js_module"
|
|
10471
|
-
// because when there is ?as_js_classic it means the underlying
|
|
10471
|
+
// because when there is ?as_js_classic it means the underlying resource
|
|
10472
10472
|
// is a js_module
|
|
10473
10473
|
expectedType: "js_module"
|
|
10474
10474
|
});
|
|
@@ -11531,26 +11531,26 @@ const getParentUrl = url => {
|
|
|
11531
11531
|
if (url.startsWith("file://")) {
|
|
11532
11532
|
// With node.js new URL('../', 'file:///C:/').href
|
|
11533
11533
|
// returns "file:///C:/" instead of "file:///"
|
|
11534
|
-
const
|
|
11535
|
-
const slashLastIndex =
|
|
11534
|
+
const resource = url.slice("file://".length);
|
|
11535
|
+
const slashLastIndex = resource.lastIndexOf("/");
|
|
11536
11536
|
|
|
11537
11537
|
if (slashLastIndex === -1) {
|
|
11538
11538
|
return url;
|
|
11539
11539
|
}
|
|
11540
11540
|
|
|
11541
|
-
const lastCharIndex =
|
|
11541
|
+
const lastCharIndex = resource.length - 1;
|
|
11542
11542
|
|
|
11543
11543
|
if (slashLastIndex === lastCharIndex) {
|
|
11544
|
-
const slashBeforeLastIndex =
|
|
11544
|
+
const slashBeforeLastIndex = resource.lastIndexOf("/", slashLastIndex - 1);
|
|
11545
11545
|
|
|
11546
11546
|
if (slashBeforeLastIndex === -1) {
|
|
11547
11547
|
return url;
|
|
11548
11548
|
}
|
|
11549
11549
|
|
|
11550
|
-
return `file://${
|
|
11550
|
+
return `file://${resource.slice(0, slashBeforeLastIndex + 1)}`;
|
|
11551
11551
|
}
|
|
11552
11552
|
|
|
11553
|
-
return `file://${
|
|
11553
|
+
return `file://${resource.slice(0, slashLastIndex + 1)}`;
|
|
11554
11554
|
}
|
|
11555
11555
|
|
|
11556
11556
|
return new URL(url.endsWith("/") ? "../" : "./", url).href;
|
|
@@ -12862,7 +12862,7 @@ const jsenvPluginNodeEsmResolution = ({
|
|
|
12862
12862
|
}
|
|
12863
12863
|
},
|
|
12864
12864
|
resolveUrl: {
|
|
12865
|
-
js_import_export:
|
|
12865
|
+
js_import_export: reference => {
|
|
12866
12866
|
const {
|
|
12867
12867
|
parentUrl,
|
|
12868
12868
|
specifier
|
|
@@ -12882,16 +12882,7 @@ const jsenvPluginNodeEsmResolution = ({
|
|
|
12882
12882
|
// changes
|
|
12883
12883
|
|
|
12884
12884
|
const dependsOnPackageJson = type !== "relative_specifier" && type !== "absolute_specifier" && type !== "node_builtin_specifier";
|
|
12885
|
-
|
|
12886
|
-
relatedUrlInfos.forEach(relatedUrlInfo => {
|
|
12887
|
-
if (relatedUrlInfo.dependsOnPackageJson) {
|
|
12888
|
-
// the url may depend due to an other reference
|
|
12889
|
-
// in that case keep dependsOnPackageJson to true
|
|
12890
|
-
return;
|
|
12891
|
-
}
|
|
12892
|
-
|
|
12893
|
-
relatedUrlInfo.dependsOnPackageJson = dependsOnPackageJson;
|
|
12894
|
-
});
|
|
12885
|
+
reference.dependsOnPackageJson = dependsOnPackageJson;
|
|
12895
12886
|
return url;
|
|
12896
12887
|
}
|
|
12897
12888
|
},
|
|
@@ -13190,7 +13181,7 @@ const jsenvPluginHtmlSupervisor = ({
|
|
|
13190
13181
|
name: "jsenv:html_supervisor",
|
|
13191
13182
|
appliesDuring: "dev",
|
|
13192
13183
|
serve: async (request, context) => {
|
|
13193
|
-
if (request.
|
|
13184
|
+
if (request.pathname.startsWith("/__get_code_frame__/")) {
|
|
13194
13185
|
const {
|
|
13195
13186
|
pathname,
|
|
13196
13187
|
searchParams
|
|
@@ -13249,8 +13240,8 @@ const jsenvPluginHtmlSupervisor = ({
|
|
|
13249
13240
|
};
|
|
13250
13241
|
}
|
|
13251
13242
|
|
|
13252
|
-
if (request.
|
|
13253
|
-
const file = request.
|
|
13243
|
+
if (request.pathname.startsWith("/__get_error_cause__/")) {
|
|
13244
|
+
const file = request.pathname.slice("/__get_error_cause__/".length);
|
|
13254
13245
|
|
|
13255
13246
|
if (!file) {
|
|
13256
13247
|
return {
|
|
@@ -13309,8 +13300,8 @@ const jsenvPluginHtmlSupervisor = ({
|
|
|
13309
13300
|
};
|
|
13310
13301
|
}
|
|
13311
13302
|
|
|
13312
|
-
if (request.
|
|
13313
|
-
const file = request.
|
|
13303
|
+
if (request.pathname.startsWith("/__open_in_editor__/")) {
|
|
13304
|
+
const file = request.pathname.slice("/__open_in_editor__/".length);
|
|
13314
13305
|
|
|
13315
13306
|
if (!file) {
|
|
13316
13307
|
return {
|
|
@@ -13742,7 +13733,6 @@ const jsenvPluginImportMetaScenarios = () => {
|
|
|
13742
13733
|
});
|
|
13743
13734
|
const {
|
|
13744
13735
|
dev = [],
|
|
13745
|
-
test = [],
|
|
13746
13736
|
build = []
|
|
13747
13737
|
} = metadata.importMetaScenarios;
|
|
13748
13738
|
const replacements = [];
|
|
@@ -13759,9 +13749,6 @@ const jsenvPluginImportMetaScenarios = () => {
|
|
|
13759
13749
|
dev.forEach(path => {
|
|
13760
13750
|
replace(path, "undefined");
|
|
13761
13751
|
});
|
|
13762
|
-
test.forEach(path => {
|
|
13763
|
-
replace(path, context.scenarios.test ? "true" : "undefined");
|
|
13764
|
-
});
|
|
13765
13752
|
build.forEach(path => {
|
|
13766
13753
|
replace(path, "true");
|
|
13767
13754
|
});
|
|
@@ -13773,12 +13760,6 @@ const jsenvPluginImportMetaScenarios = () => {
|
|
|
13773
13760
|
dev.forEach(path => {
|
|
13774
13761
|
replace(path, "true");
|
|
13775
13762
|
});
|
|
13776
|
-
|
|
13777
|
-
if (context.scenarios.test) {
|
|
13778
|
-
test.forEach(path => {
|
|
13779
|
-
replace(path, "true");
|
|
13780
|
-
});
|
|
13781
|
-
}
|
|
13782
13763
|
}
|
|
13783
13764
|
|
|
13784
13765
|
const magicSource = createMagicSource(urlInfo.content);
|
|
@@ -14062,6 +14043,87 @@ export default inlineContent.text`,
|
|
|
14062
14043
|
return [asJsonModule, asCssModule, asTextModule];
|
|
14063
14044
|
};
|
|
14064
14045
|
|
|
14046
|
+
const babelPluginInstrument = (api, {
|
|
14047
|
+
rootDirectoryUrl,
|
|
14048
|
+
useInlineSourceMaps = false,
|
|
14049
|
+
coverageConfig = {
|
|
14050
|
+
"./**/*": true
|
|
14051
|
+
}
|
|
14052
|
+
}) => {
|
|
14053
|
+
const {
|
|
14054
|
+
programVisitor
|
|
14055
|
+
} = requireFromJsenv("istanbul-lib-instrument");
|
|
14056
|
+
const {
|
|
14057
|
+
types
|
|
14058
|
+
} = api;
|
|
14059
|
+
const associations = URL_META.resolveAssociations({
|
|
14060
|
+
cover: coverageConfig
|
|
14061
|
+
}, rootDirectoryUrl);
|
|
14062
|
+
|
|
14063
|
+
const shouldInstrument = url => {
|
|
14064
|
+
return URL_META.applyAssociations({
|
|
14065
|
+
url,
|
|
14066
|
+
associations
|
|
14067
|
+
}).cover;
|
|
14068
|
+
};
|
|
14069
|
+
|
|
14070
|
+
return {
|
|
14071
|
+
name: "transform-instrument",
|
|
14072
|
+
visitor: {
|
|
14073
|
+
Program: {
|
|
14074
|
+
enter(path) {
|
|
14075
|
+
const {
|
|
14076
|
+
file
|
|
14077
|
+
} = this;
|
|
14078
|
+
const {
|
|
14079
|
+
opts
|
|
14080
|
+
} = file;
|
|
14081
|
+
|
|
14082
|
+
if (!opts.sourceFileName) {
|
|
14083
|
+
console.warn(`cannot instrument file when "sourceFileName" option is not set`);
|
|
14084
|
+
return;
|
|
14085
|
+
}
|
|
14086
|
+
|
|
14087
|
+
const fileUrl = fileSystemPathToUrl$1(opts.sourceFileName);
|
|
14088
|
+
|
|
14089
|
+
if (!shouldInstrument(fileUrl)) {
|
|
14090
|
+
return;
|
|
14091
|
+
}
|
|
14092
|
+
|
|
14093
|
+
this.__dv__ = null;
|
|
14094
|
+
let inputSourceMap;
|
|
14095
|
+
|
|
14096
|
+
if (useInlineSourceMaps) {
|
|
14097
|
+
// https://github.com/istanbuljs/babel-plugin-istanbul/commit/a9e15643d249a2985e4387e4308022053b2cd0ad#diff-1fdf421c05c1140f6d71444ea2b27638R65
|
|
14098
|
+
inputSourceMap = opts.inputSourceMap || file.inputMap ? file.inputMap.sourcemap : null;
|
|
14099
|
+
} else {
|
|
14100
|
+
inputSourceMap = opts.inputSourceMap;
|
|
14101
|
+
}
|
|
14102
|
+
|
|
14103
|
+
this.__dv__ = programVisitor(types, opts.filenameRelative || opts.filename, {
|
|
14104
|
+
coverageVariable: "__coverage__",
|
|
14105
|
+
inputSourceMap
|
|
14106
|
+
});
|
|
14107
|
+
|
|
14108
|
+
this.__dv__.enter(path);
|
|
14109
|
+
},
|
|
14110
|
+
|
|
14111
|
+
exit(path) {
|
|
14112
|
+
if (!this.__dv__) {
|
|
14113
|
+
return;
|
|
14114
|
+
}
|
|
14115
|
+
|
|
14116
|
+
const object = this.__dv__.exit(path); // object got two properties: fileCoverage and sourceMappingURL
|
|
14117
|
+
|
|
14118
|
+
|
|
14119
|
+
this.file.metadata.coverage = object.fileCoverage;
|
|
14120
|
+
}
|
|
14121
|
+
|
|
14122
|
+
}
|
|
14123
|
+
}
|
|
14124
|
+
};
|
|
14125
|
+
};
|
|
14126
|
+
|
|
14065
14127
|
const versionFromValue = value => {
|
|
14066
14128
|
if (typeof value === "number") {
|
|
14067
14129
|
return numberToVersion(value);
|
|
@@ -15243,6 +15305,17 @@ const jsenvPluginBabel = ({
|
|
|
15243
15305
|
getImportSpecifier
|
|
15244
15306
|
});
|
|
15245
15307
|
|
|
15308
|
+
if (context.scenarios.dev) {
|
|
15309
|
+
const requestHeaders = context.request.headers;
|
|
15310
|
+
|
|
15311
|
+
if (requestHeaders["x-coverage-instanbul"]) {
|
|
15312
|
+
babelPluginStructure["transform-instrument"] = [babelPluginInstrument, {
|
|
15313
|
+
rootDirectoryUrl: context.rootDirectoryUrl,
|
|
15314
|
+
coverageConfig: JSON.parse(requestHeaders["x-coverage-instanbul"])
|
|
15315
|
+
}];
|
|
15316
|
+
}
|
|
15317
|
+
}
|
|
15318
|
+
|
|
15246
15319
|
if (getCustomBabelPlugins) {
|
|
15247
15320
|
Object.assign(babelPluginStructure, getCustomBabelPlugins(context));
|
|
15248
15321
|
}
|
|
@@ -16315,7 +16388,7 @@ const htmlNodeCanHotReload = node => {
|
|
|
16315
16388
|
if (node.nodeName === "link") {
|
|
16316
16389
|
const {
|
|
16317
16390
|
isStylesheet,
|
|
16318
|
-
|
|
16391
|
+
isResourceHint,
|
|
16319
16392
|
rel
|
|
16320
16393
|
} = analyzeLinkNode(node);
|
|
16321
16394
|
|
|
@@ -16324,9 +16397,9 @@ const htmlNodeCanHotReload = node => {
|
|
|
16324
16397
|
return true;
|
|
16325
16398
|
}
|
|
16326
16399
|
|
|
16327
|
-
if (
|
|
16328
|
-
// for
|
|
16329
|
-
// but we won't do anything (if the
|
|
16400
|
+
if (isResourceHint) {
|
|
16401
|
+
// for resource hints html will be notified the underlying resource has changed
|
|
16402
|
+
// but we won't do anything (if the resource is deleted we should?)
|
|
16330
16403
|
return true;
|
|
16331
16404
|
}
|
|
16332
16405
|
|
|
@@ -16561,10 +16634,7 @@ import.meta.hot = createImportMetaHot(import.meta.url)
|
|
|
16561
16634
|
const jsenvPluginHmr = () => {
|
|
16562
16635
|
return {
|
|
16563
16636
|
name: "jsenv:hmr",
|
|
16564
|
-
appliesDuring:
|
|
16565
|
-
dev: true,
|
|
16566
|
-
test: false
|
|
16567
|
-
},
|
|
16637
|
+
appliesDuring: "dev",
|
|
16568
16638
|
redirectUrl: reference => {
|
|
16569
16639
|
const urlObject = new URL(reference.url);
|
|
16570
16640
|
|
|
@@ -16607,10 +16677,7 @@ const jsenvPluginAutoreloadClient = () => {
|
|
|
16607
16677
|
const autoreloadClientFileUrl = new URL("./js/autoreload.js", import.meta.url).href;
|
|
16608
16678
|
return {
|
|
16609
16679
|
name: "jsenv:autoreload_client",
|
|
16610
|
-
appliesDuring:
|
|
16611
|
-
dev: true,
|
|
16612
|
-
test: false
|
|
16613
|
-
},
|
|
16680
|
+
appliesDuring: "dev",
|
|
16614
16681
|
transformUrlContent: {
|
|
16615
16682
|
html: (htmlUrlInfo, context) => {
|
|
16616
16683
|
const htmlAst = parseHtmlString(htmlUrlInfo.content);
|
|
@@ -16640,10 +16707,7 @@ const jsenvPluginAutoreloadServer = ({
|
|
|
16640
16707
|
}) => {
|
|
16641
16708
|
return {
|
|
16642
16709
|
name: "jsenv:autoreload_server",
|
|
16643
|
-
appliesDuring:
|
|
16644
|
-
dev: true,
|
|
16645
|
-
test: false
|
|
16646
|
-
},
|
|
16710
|
+
appliesDuring: "dev",
|
|
16647
16711
|
serverEvents: {
|
|
16648
16712
|
reload: ({
|
|
16649
16713
|
sendServerEvent,
|
|
@@ -16805,7 +16869,7 @@ const jsenvPluginAutoreloadServer = ({
|
|
|
16805
16869
|
firstUrlInfo
|
|
16806
16870
|
}) => {
|
|
16807
16871
|
const mainHotUpdate = propagateUpdate(firstUrlInfo);
|
|
16808
|
-
const cause = `following files are no longer referenced: ${prunedUrlInfos.map(prunedUrlInfo => formatUrlForClient(prunedUrlInfo.url))}`; // now check if we can hot update the main
|
|
16872
|
+
const cause = `following files are no longer referenced: ${prunedUrlInfos.map(prunedUrlInfo => formatUrlForClient(prunedUrlInfo.url))}`; // now check if we can hot update the main resource
|
|
16809
16873
|
// then if we can hot update all dependencies
|
|
16810
16874
|
|
|
16811
16875
|
if (mainHotUpdate.declined) {
|
|
@@ -16852,7 +16916,7 @@ const jsenvPluginAutoreloadServer = ({
|
|
|
16852
16916
|
rootDirectoryUrl,
|
|
16853
16917
|
urlGraph
|
|
16854
16918
|
}) => {
|
|
16855
|
-
if (request.
|
|
16919
|
+
if (request.pathname === "/__graph__") {
|
|
16856
16920
|
const graphJson = JSON.stringify(urlGraph.toJSON(rootDirectoryUrl));
|
|
16857
16921
|
return {
|
|
16858
16922
|
status: 200,
|
|
@@ -16922,7 +16986,7 @@ const jsenvPluginExplorer = ({
|
|
|
16922
16986
|
serve: async (request, {
|
|
16923
16987
|
rootDirectoryUrl
|
|
16924
16988
|
}) => {
|
|
16925
|
-
if (request.
|
|
16989
|
+
if (request.pathname !== "/") {
|
|
16926
16990
|
return null;
|
|
16927
16991
|
}
|
|
16928
16992
|
|
|
@@ -17896,7 +17960,7 @@ const nodeStreamToObservable = nodeStream => {
|
|
|
17896
17960
|
// safe measure, ensure the readable stream gets
|
|
17897
17961
|
// used in the next ${readableStreamLifetimeInSeconds} otherwise destroys it
|
|
17898
17962
|
const timeout = setTimeout(() => {
|
|
17899
|
-
process.emitWarning(`Readable stream not used after ${readableStreamLifetimeInSeconds} seconds. It will be destroyed to release
|
|
17963
|
+
process.emitWarning(`Readable stream not used after ${readableStreamLifetimeInSeconds} seconds. It will be destroyed to release resources`, {
|
|
17900
17964
|
CODE: "READABLE_STREAM_TIMEOUT",
|
|
17901
17965
|
// url is for http client request
|
|
17902
17966
|
detail: `path: ${nodeStream.path}, fd: ${nodeStream.fd}, url: ${nodeStream.url}`
|
|
@@ -17976,8 +18040,8 @@ const fromNodeRequest = (nodeRequest, {
|
|
|
17976
18040
|
signal,
|
|
17977
18041
|
http2: Boolean(nodeRequest.stream),
|
|
17978
18042
|
origin: requestOrigin,
|
|
17979
|
-
...
|
|
17980
|
-
|
|
18043
|
+
...getPropertiesFromResource({
|
|
18044
|
+
resource: nodeRequest.url,
|
|
17981
18045
|
baseUrl: requestOrigin
|
|
17982
18046
|
}),
|
|
17983
18047
|
method: nodeRequest.method,
|
|
@@ -17986,13 +18050,13 @@ const fromNodeRequest = (nodeRequest, {
|
|
|
17986
18050
|
});
|
|
17987
18051
|
};
|
|
17988
18052
|
const applyRedirectionToRequest = (request, {
|
|
17989
|
-
|
|
18053
|
+
resource,
|
|
17990
18054
|
pathname,
|
|
17991
18055
|
...rest
|
|
17992
18056
|
}) => {
|
|
17993
18057
|
return { ...request,
|
|
17994
|
-
...(
|
|
17995
|
-
|
|
18058
|
+
...(resource ? getPropertiesFromResource({
|
|
18059
|
+
resource,
|
|
17996
18060
|
baseUrl: request.url
|
|
17997
18061
|
}) : pathname ? getPropertiesFromPathname({
|
|
17998
18062
|
pathname,
|
|
@@ -18002,16 +18066,16 @@ const applyRedirectionToRequest = (request, {
|
|
|
18002
18066
|
};
|
|
18003
18067
|
};
|
|
18004
18068
|
|
|
18005
|
-
const
|
|
18006
|
-
|
|
18069
|
+
const getPropertiesFromResource = ({
|
|
18070
|
+
resource,
|
|
18007
18071
|
baseUrl
|
|
18008
18072
|
}) => {
|
|
18009
|
-
const urlObject = new URL(
|
|
18073
|
+
const urlObject = new URL(resource, baseUrl);
|
|
18010
18074
|
let pathname = urlObject.pathname;
|
|
18011
18075
|
return {
|
|
18012
18076
|
url: String(urlObject),
|
|
18013
18077
|
pathname,
|
|
18014
|
-
|
|
18078
|
+
resource
|
|
18015
18079
|
};
|
|
18016
18080
|
};
|
|
18017
18081
|
|
|
@@ -18019,8 +18083,8 @@ const getPropertiesFromPathname = ({
|
|
|
18019
18083
|
pathname,
|
|
18020
18084
|
baseUrl
|
|
18021
18085
|
}) => {
|
|
18022
|
-
return
|
|
18023
|
-
|
|
18086
|
+
return getPropertiesFromResource({
|
|
18087
|
+
resource: `${pathname}${new URL(baseUrl).search}`,
|
|
18024
18088
|
baseUrl
|
|
18025
18089
|
});
|
|
18026
18090
|
};
|
|
@@ -18048,11 +18112,11 @@ const createPushRequest = (request, {
|
|
|
18048
18112
|
const getHeadersInheritedByPushRequest = request => {
|
|
18049
18113
|
const headersInherited = { ...request.headers
|
|
18050
18114
|
}; // mtime sent by the client in request headers concerns the main request
|
|
18051
|
-
// Time remains valid for request to other
|
|
18115
|
+
// Time remains valid for request to other resources so we keep it
|
|
18052
18116
|
// in child requests
|
|
18053
18117
|
// delete childHeaders["if-modified-since"]
|
|
18054
18118
|
// eTag sent by the client in request headers concerns the main request
|
|
18055
|
-
// A request made to an other
|
|
18119
|
+
// A request made to an other resource must not inherit the eTag
|
|
18056
18120
|
|
|
18057
18121
|
delete headersInherited["if-none-match"];
|
|
18058
18122
|
return headersInherited;
|
|
@@ -18367,101 +18431,12 @@ const statusIsClientError = status => status >= 400 && status < 500;
|
|
|
18367
18431
|
|
|
18368
18432
|
const statusIsServerError = status => status >= 500 && status < 600;
|
|
18369
18433
|
|
|
18370
|
-
const applyDnsResolution = async (hostname, {
|
|
18371
|
-
verbatim = false
|
|
18372
|
-
} = {}) => {
|
|
18373
|
-
const dnsResolution = await new Promise((resolve, reject) => {
|
|
18374
|
-
lookup(hostname, {
|
|
18375
|
-
verbatim
|
|
18376
|
-
}, (error, address, family) => {
|
|
18377
|
-
if (error) {
|
|
18378
|
-
reject(error);
|
|
18379
|
-
} else {
|
|
18380
|
-
resolve({
|
|
18381
|
-
address,
|
|
18382
|
-
family
|
|
18383
|
-
});
|
|
18384
|
-
}
|
|
18385
|
-
});
|
|
18386
|
-
});
|
|
18387
|
-
return dnsResolution;
|
|
18388
|
-
};
|
|
18389
|
-
|
|
18390
|
-
const getServerOrigins = async ({
|
|
18391
|
-
protocol,
|
|
18392
|
-
host,
|
|
18393
|
-
port
|
|
18394
|
-
}) => {
|
|
18395
|
-
const isLocal = LOOPBACK_HOSTNAMES.includes(host);
|
|
18396
|
-
const localhostDnsResolution = await applyDnsResolution("localhost");
|
|
18397
|
-
const localOrigin = createServerOrigin({
|
|
18398
|
-
protocol,
|
|
18399
|
-
hostname: localhostDnsResolution.address === "127.0.0.1" ? "localhost" : "127.0.0.1",
|
|
18400
|
-
port
|
|
18401
|
-
});
|
|
18402
|
-
|
|
18403
|
-
if (isLocal) {
|
|
18404
|
-
return {
|
|
18405
|
-
local: localOrigin
|
|
18406
|
-
};
|
|
18407
|
-
}
|
|
18408
|
-
|
|
18409
|
-
const isAnyIp = WILDCARD_HOSTNAMES.includes(host);
|
|
18410
|
-
const networkOrigin = createServerOrigin({
|
|
18411
|
-
protocol,
|
|
18412
|
-
hostname: isAnyIp ? getExternalIp() : host,
|
|
18413
|
-
port
|
|
18414
|
-
});
|
|
18415
|
-
return {
|
|
18416
|
-
local: localOrigin,
|
|
18417
|
-
network: networkOrigin
|
|
18418
|
-
};
|
|
18419
|
-
};
|
|
18420
|
-
const LOOPBACK_HOSTNAMES = ["localhost", "127.0.0.1", "::1", "0000:0000:0000:0000:0000:0000:0000:0001"];
|
|
18421
|
-
const WILDCARD_HOSTNAMES = [undefined, "0.0.0.0", "::", "0000:0000:0000:0000:0000:0000:0000:0000"];
|
|
18422
|
-
|
|
18423
|
-
const createServerOrigin = ({
|
|
18424
|
-
protocol,
|
|
18425
|
-
hostname,
|
|
18426
|
-
port
|
|
18427
|
-
}) => {
|
|
18428
|
-
const url = new URL("https://127.0.0.1:80");
|
|
18429
|
-
url.protocol = protocol;
|
|
18430
|
-
url.hostname = hostname;
|
|
18431
|
-
url.port = port;
|
|
18432
|
-
return url.origin;
|
|
18433
|
-
};
|
|
18434
|
-
|
|
18435
|
-
const getExternalIp = () => {
|
|
18436
|
-
const networkInterfaceMap = networkInterfaces();
|
|
18437
|
-
let internalIPV4NetworkAddress;
|
|
18438
|
-
Object.keys(networkInterfaceMap).find(key => {
|
|
18439
|
-
const networkAddressArray = networkInterfaceMap[key];
|
|
18440
|
-
return networkAddressArray.find(networkAddress => {
|
|
18441
|
-
if (networkAddress.internal) return false;
|
|
18442
|
-
if (!isIpV4(networkAddress)) return false;
|
|
18443
|
-
internalIPV4NetworkAddress = networkAddress;
|
|
18444
|
-
return true;
|
|
18445
|
-
});
|
|
18446
|
-
});
|
|
18447
|
-
return internalIPV4NetworkAddress ? internalIPV4NetworkAddress.address : null;
|
|
18448
|
-
};
|
|
18449
|
-
|
|
18450
|
-
const isIpV4 = networkAddress => {
|
|
18451
|
-
// node 18+
|
|
18452
|
-
if (typeof networkAddress.family === "number") {
|
|
18453
|
-
return networkAddress.family === 4;
|
|
18454
|
-
}
|
|
18455
|
-
|
|
18456
|
-
return networkAddress.family === "IPv4";
|
|
18457
|
-
};
|
|
18458
|
-
|
|
18459
18434
|
const listen = async ({
|
|
18460
18435
|
signal = new AbortController().signal,
|
|
18461
18436
|
server,
|
|
18462
18437
|
port,
|
|
18463
18438
|
portHint,
|
|
18464
|
-
|
|
18439
|
+
hostname
|
|
18465
18440
|
}) => {
|
|
18466
18441
|
const listeningOperation = Abort.startOperation();
|
|
18467
18442
|
|
|
@@ -18472,7 +18447,7 @@ const listen = async ({
|
|
|
18472
18447
|
listeningOperation.throwIfAborted();
|
|
18473
18448
|
port = await findFreePort(portHint, {
|
|
18474
18449
|
signal: listeningOperation.signal,
|
|
18475
|
-
|
|
18450
|
+
hostname
|
|
18476
18451
|
});
|
|
18477
18452
|
}
|
|
18478
18453
|
|
|
@@ -18480,7 +18455,7 @@ const listen = async ({
|
|
|
18480
18455
|
port = await startListening({
|
|
18481
18456
|
server,
|
|
18482
18457
|
port,
|
|
18483
|
-
|
|
18458
|
+
hostname
|
|
18484
18459
|
});
|
|
18485
18460
|
listeningOperation.addAbortCallback(() => stopListening(server));
|
|
18486
18461
|
listeningOperation.throwIfAborted();
|
|
@@ -18492,7 +18467,7 @@ const listen = async ({
|
|
|
18492
18467
|
|
|
18493
18468
|
const findFreePort = async (initialPort = 1, {
|
|
18494
18469
|
signal = new AbortController().signal,
|
|
18495
|
-
|
|
18470
|
+
hostname = "127.0.0.1",
|
|
18496
18471
|
min = 1,
|
|
18497
18472
|
max = 65534,
|
|
18498
18473
|
next = port => port + 1
|
|
@@ -18514,27 +18489,27 @@ const findFreePort = async (initialPort = 1, {
|
|
|
18514
18489
|
const nextPort = next(port);
|
|
18515
18490
|
|
|
18516
18491
|
if (nextPort > max) {
|
|
18517
|
-
throw new Error(`${
|
|
18492
|
+
throw new Error(`${hostname} has no available port between ${min} and ${max}`);
|
|
18518
18493
|
}
|
|
18519
18494
|
|
|
18520
|
-
return testUntil(nextPort,
|
|
18495
|
+
return testUntil(nextPort, hostname);
|
|
18521
18496
|
};
|
|
18522
18497
|
|
|
18523
|
-
const freePort = await testUntil(initialPort,
|
|
18498
|
+
const freePort = await testUntil(initialPort, hostname);
|
|
18524
18499
|
return freePort;
|
|
18525
18500
|
} finally {
|
|
18526
18501
|
await findFreePortOperation.end();
|
|
18527
18502
|
}
|
|
18528
18503
|
};
|
|
18529
18504
|
|
|
18530
|
-
const portIsFree = async (port,
|
|
18505
|
+
const portIsFree = async (port, hostname) => {
|
|
18531
18506
|
const server = createServer();
|
|
18532
18507
|
|
|
18533
18508
|
try {
|
|
18534
18509
|
await startListening({
|
|
18535
18510
|
server,
|
|
18536
18511
|
port,
|
|
18537
|
-
|
|
18512
|
+
hostname
|
|
18538
18513
|
});
|
|
18539
18514
|
} catch (error) {
|
|
18540
18515
|
if (error && error.code === "EADDRINUSE") {
|
|
@@ -18555,7 +18530,7 @@ const portIsFree = async (port, host) => {
|
|
|
18555
18530
|
const startListening = ({
|
|
18556
18531
|
server,
|
|
18557
18532
|
port,
|
|
18558
|
-
|
|
18533
|
+
hostname
|
|
18559
18534
|
}) => {
|
|
18560
18535
|
return new Promise((resolve, reject) => {
|
|
18561
18536
|
server.on("error", reject);
|
|
@@ -18564,7 +18539,7 @@ const startListening = ({
|
|
|
18564
18539
|
// https://nodejs.org/api/net.html#net_server_listen_port_host_backlog_callback
|
|
18565
18540
|
resolve(server.address().port);
|
|
18566
18541
|
});
|
|
18567
|
-
server.listen(port,
|
|
18542
|
+
server.listen(port, hostname);
|
|
18568
18543
|
});
|
|
18569
18544
|
};
|
|
18570
18545
|
|
|
@@ -18803,6 +18778,134 @@ const STOP_REASON_PROCESS_BEFORE_EXIT = createReason("process before exit");
|
|
|
18803
18778
|
const STOP_REASON_PROCESS_EXIT = createReason("process exit");
|
|
18804
18779
|
const STOP_REASON_NOT_SPECIFIED = createReason("not specified");
|
|
18805
18780
|
|
|
18781
|
+
const createIpGetters = () => {
|
|
18782
|
+
const networkAddresses = [];
|
|
18783
|
+
const networkInterfaceMap = networkInterfaces();
|
|
18784
|
+
|
|
18785
|
+
for (const key of Object.keys(networkInterfaceMap)) {
|
|
18786
|
+
for (const networkAddress of networkInterfaceMap[key]) {
|
|
18787
|
+
networkAddresses.push(networkAddress);
|
|
18788
|
+
}
|
|
18789
|
+
}
|
|
18790
|
+
|
|
18791
|
+
return {
|
|
18792
|
+
getFirstInternalIp: ({
|
|
18793
|
+
preferIpv6
|
|
18794
|
+
}) => {
|
|
18795
|
+
const isPref = preferIpv6 ? isIpV6 : isIpV4;
|
|
18796
|
+
let firstInternalIp;
|
|
18797
|
+
|
|
18798
|
+
for (const networkAddress of networkAddresses) {
|
|
18799
|
+
if (networkAddress.internal) {
|
|
18800
|
+
firstInternalIp = networkAddress.address;
|
|
18801
|
+
|
|
18802
|
+
if (isPref(networkAddress)) {
|
|
18803
|
+
break;
|
|
18804
|
+
}
|
|
18805
|
+
}
|
|
18806
|
+
}
|
|
18807
|
+
|
|
18808
|
+
return firstInternalIp;
|
|
18809
|
+
},
|
|
18810
|
+
getFirstExternalIp: ({
|
|
18811
|
+
preferIpv6
|
|
18812
|
+
}) => {
|
|
18813
|
+
const isPref = preferIpv6 ? isIpV6 : isIpV4;
|
|
18814
|
+
let firstExternalIp;
|
|
18815
|
+
|
|
18816
|
+
for (const networkAddress of networkAddresses) {
|
|
18817
|
+
if (!networkAddress.internal) {
|
|
18818
|
+
firstExternalIp = networkAddress.address;
|
|
18819
|
+
|
|
18820
|
+
if (isPref(networkAddress)) {
|
|
18821
|
+
break;
|
|
18822
|
+
}
|
|
18823
|
+
}
|
|
18824
|
+
}
|
|
18825
|
+
|
|
18826
|
+
return firstExternalIp;
|
|
18827
|
+
}
|
|
18828
|
+
};
|
|
18829
|
+
};
|
|
18830
|
+
|
|
18831
|
+
const isIpV4 = networkAddress => {
|
|
18832
|
+
// node 18.5
|
|
18833
|
+
if (typeof networkAddress.family === "number") {
|
|
18834
|
+
return networkAddress.family === 4;
|
|
18835
|
+
}
|
|
18836
|
+
|
|
18837
|
+
return networkAddress.family === "IPv4";
|
|
18838
|
+
};
|
|
18839
|
+
|
|
18840
|
+
const isIpV6 = networkAddress => !isIpV4(networkAddress);
|
|
18841
|
+
|
|
18842
|
+
const parseHostname = hostname => {
|
|
18843
|
+
if (hostname === "0.0.0.0") {
|
|
18844
|
+
return {
|
|
18845
|
+
type: "ip",
|
|
18846
|
+
label: "unspecified",
|
|
18847
|
+
version: 4
|
|
18848
|
+
};
|
|
18849
|
+
}
|
|
18850
|
+
|
|
18851
|
+
if (hostname === "::" || hostname === "0000:0000:0000:0000:0000:0000:0000:0000") {
|
|
18852
|
+
return {
|
|
18853
|
+
type: "ip",
|
|
18854
|
+
label: "unspecified",
|
|
18855
|
+
version: 6
|
|
18856
|
+
};
|
|
18857
|
+
}
|
|
18858
|
+
|
|
18859
|
+
if (hostname === "127.0.0.1") {
|
|
18860
|
+
return {
|
|
18861
|
+
type: "ip",
|
|
18862
|
+
label: "loopback",
|
|
18863
|
+
version: 4
|
|
18864
|
+
};
|
|
18865
|
+
}
|
|
18866
|
+
|
|
18867
|
+
if (hostname === "::1" || hostname === "0000:0000:0000:0000:0000:0000:0000:0001") {
|
|
18868
|
+
return {
|
|
18869
|
+
type: "ip",
|
|
18870
|
+
label: "loopback",
|
|
18871
|
+
version: 6
|
|
18872
|
+
};
|
|
18873
|
+
}
|
|
18874
|
+
|
|
18875
|
+
const ipVersion = isIP(hostname);
|
|
18876
|
+
|
|
18877
|
+
if (ipVersion === 0) {
|
|
18878
|
+
return {
|
|
18879
|
+
type: "hostname"
|
|
18880
|
+
};
|
|
18881
|
+
}
|
|
18882
|
+
|
|
18883
|
+
return {
|
|
18884
|
+
type: "ip",
|
|
18885
|
+
version: ipVersion
|
|
18886
|
+
};
|
|
18887
|
+
};
|
|
18888
|
+
|
|
18889
|
+
const applyDnsResolution = async (hostname, {
|
|
18890
|
+
verbatim = false
|
|
18891
|
+
} = {}) => {
|
|
18892
|
+
const dnsResolution = await new Promise((resolve, reject) => {
|
|
18893
|
+
lookup(hostname, {
|
|
18894
|
+
verbatim
|
|
18895
|
+
}, (error, address, family) => {
|
|
18896
|
+
if (error) {
|
|
18897
|
+
reject(error);
|
|
18898
|
+
} else {
|
|
18899
|
+
resolve({
|
|
18900
|
+
address,
|
|
18901
|
+
family
|
|
18902
|
+
});
|
|
18903
|
+
}
|
|
18904
|
+
});
|
|
18905
|
+
});
|
|
18906
|
+
return dnsResolution;
|
|
18907
|
+
};
|
|
18908
|
+
|
|
18806
18909
|
const startServer = async ({
|
|
18807
18910
|
signal = new AbortController().signal,
|
|
18808
18911
|
logLevel,
|
|
@@ -18814,7 +18917,8 @@ const startServer = async ({
|
|
|
18814
18917
|
redirectHttpToHttps,
|
|
18815
18918
|
allowHttpRequestOnHttps = false,
|
|
18816
18919
|
acceptAnyIp = false,
|
|
18817
|
-
|
|
18920
|
+
preferIpv6,
|
|
18921
|
+
hostname = "localhost",
|
|
18818
18922
|
port = 0,
|
|
18819
18923
|
// assign a random available port
|
|
18820
18924
|
portHint,
|
|
@@ -18839,11 +18943,15 @@ const startServer = async ({
|
|
|
18839
18943
|
requestWaitingMs
|
|
18840
18944
|
}) => {
|
|
18841
18945
|
warn(createDetailedMessage$1(`still no response found for request after ${requestWaitingMs} ms`, {
|
|
18842
|
-
"request url":
|
|
18946
|
+
"request url": request.url,
|
|
18843
18947
|
"request headers": JSON.stringify(request.headers, null, " ")
|
|
18844
18948
|
}));
|
|
18845
18949
|
}
|
|
18846
18950
|
} = {}) => {
|
|
18951
|
+
const logger = createLogger({
|
|
18952
|
+
logLevel
|
|
18953
|
+
});
|
|
18954
|
+
|
|
18847
18955
|
if (protocol !== "http" && protocol !== "https") {
|
|
18848
18956
|
throw new Error(`protocol must be http or https, got ${protocol}`);
|
|
18849
18957
|
}
|
|
@@ -18862,10 +18970,6 @@ const startServer = async ({
|
|
|
18862
18970
|
throw new Error(`http2 needs "https" but protocol is "${protocol}"`);
|
|
18863
18971
|
}
|
|
18864
18972
|
|
|
18865
|
-
const logger = createLogger({
|
|
18866
|
-
logLevel
|
|
18867
|
-
});
|
|
18868
|
-
|
|
18869
18973
|
if (redirectHttpToHttps === undefined && protocol === "https" && !allowHttpRequestOnHttps) {
|
|
18870
18974
|
redirectHttpToHttps = true;
|
|
18871
18975
|
}
|
|
@@ -18898,6 +19002,10 @@ const startServer = async ({
|
|
|
18898
19002
|
let nodeServer;
|
|
18899
19003
|
const startServerOperation = Abort.startOperation();
|
|
18900
19004
|
const stopCallbackList = createCallbackListNotifiedOnce();
|
|
19005
|
+
const serverOrigins = {
|
|
19006
|
+
local: "" // favors hostname when possible
|
|
19007
|
+
|
|
19008
|
+
};
|
|
18901
19009
|
|
|
18902
19010
|
try {
|
|
18903
19011
|
startServerOperation.addAbortSignal(signal);
|
|
@@ -18925,12 +19033,85 @@ const startServer = async ({
|
|
|
18925
19033
|
nodeServer.unref();
|
|
18926
19034
|
}
|
|
18927
19035
|
|
|
19036
|
+
const createOrigin = hostname => {
|
|
19037
|
+
if (isIP(hostname) === 6) {
|
|
19038
|
+
return `${protocol}://[${hostname}]`;
|
|
19039
|
+
}
|
|
19040
|
+
|
|
19041
|
+
return `${protocol}://${hostname}`;
|
|
19042
|
+
};
|
|
19043
|
+
|
|
19044
|
+
const ipGetters = createIpGetters();
|
|
19045
|
+
let hostnameToListen;
|
|
19046
|
+
|
|
19047
|
+
if (acceptAnyIp) {
|
|
19048
|
+
const firstInternalIp = ipGetters.getFirstInternalIp({
|
|
19049
|
+
preferIpv6
|
|
19050
|
+
});
|
|
19051
|
+
serverOrigins.local = createOrigin(firstInternalIp);
|
|
19052
|
+
serverOrigins.localip = createOrigin(firstInternalIp);
|
|
19053
|
+
const firstExternalIp = ipGetters.getFirstExternalIp({
|
|
19054
|
+
preferIpv6
|
|
19055
|
+
});
|
|
19056
|
+
serverOrigins.externalip = createOrigin(firstExternalIp);
|
|
19057
|
+
hostnameToListen = preferIpv6 ? "::" : "0.0.0.0";
|
|
19058
|
+
} else {
|
|
19059
|
+
hostnameToListen = hostname;
|
|
19060
|
+
}
|
|
19061
|
+
|
|
19062
|
+
const hostnameInfo = parseHostname(hostname);
|
|
19063
|
+
|
|
19064
|
+
if (hostnameInfo.type === "ip") {
|
|
19065
|
+
if (acceptAnyIp) {
|
|
19066
|
+
throw new Error(`hostname cannot be an ip when acceptAnyIp is enabled, got ${hostname}`);
|
|
19067
|
+
}
|
|
19068
|
+
|
|
19069
|
+
preferIpv6 = hostnameInfo.version === 6;
|
|
19070
|
+
const firstInternalIp = ipGetters.getFirstInternalIp({
|
|
19071
|
+
preferIpv6
|
|
19072
|
+
});
|
|
19073
|
+
serverOrigins.local = createOrigin(firstInternalIp);
|
|
19074
|
+
serverOrigins.localip = createOrigin(firstInternalIp);
|
|
19075
|
+
|
|
19076
|
+
if (hostnameInfo.label === "unspecified") {
|
|
19077
|
+
const firstExternalIp = ipGetters.getFirstExternalIp({
|
|
19078
|
+
preferIpv6
|
|
19079
|
+
});
|
|
19080
|
+
serverOrigins.externalip = createOrigin(firstExternalIp);
|
|
19081
|
+
} else if (hostnameInfo.label === "loopback") {} else {
|
|
19082
|
+
serverOrigins.local = createOrigin(hostname);
|
|
19083
|
+
}
|
|
19084
|
+
} else {
|
|
19085
|
+
const hostnameDnsResolution = await applyDnsResolution(hostname, {
|
|
19086
|
+
verbatim: true
|
|
19087
|
+
});
|
|
19088
|
+
|
|
19089
|
+
if (hostnameDnsResolution) {
|
|
19090
|
+
const hostnameIp = hostnameDnsResolution.address;
|
|
19091
|
+
serverOrigins.localip = createOrigin(hostnameIp);
|
|
19092
|
+
serverOrigins.local = createOrigin(hostname);
|
|
19093
|
+
} else {
|
|
19094
|
+
const firstInternalIp = ipGetters.getFirstInternalIp({
|
|
19095
|
+
preferIpv6
|
|
19096
|
+
}); // fallback to internal ip because there is no ip
|
|
19097
|
+
// associated to this hostname on operating system (in hosts file)
|
|
19098
|
+
|
|
19099
|
+
hostname = firstInternalIp;
|
|
19100
|
+
hostnameToListen = firstInternalIp;
|
|
19101
|
+
serverOrigins.local = createOrigin(firstInternalIp);
|
|
19102
|
+
}
|
|
19103
|
+
}
|
|
19104
|
+
|
|
18928
19105
|
port = await listen({
|
|
18929
19106
|
signal: startServerOperation.signal,
|
|
18930
19107
|
server: nodeServer,
|
|
18931
19108
|
port,
|
|
18932
19109
|
portHint,
|
|
18933
|
-
|
|
19110
|
+
hostname: hostnameToListen
|
|
19111
|
+
}); // normalize origins (remove :80 when port is 80 for instance)
|
|
19112
|
+
|
|
19113
|
+
Object.keys(serverOrigins).forEach(key => {
|
|
19114
|
+
serverOrigins[key] = new URL(`${serverOrigins[key]}:${port}`).origin;
|
|
18934
19115
|
});
|
|
18935
19116
|
serviceController.callHooks("serverListening", {
|
|
18936
19117
|
port
|
|
@@ -18941,12 +19122,23 @@ const startServer = async ({
|
|
|
18941
19122
|
startServerOperation.throwIfAborted();
|
|
18942
19123
|
} finally {
|
|
18943
19124
|
await startServerOperation.end();
|
|
18944
|
-
} //
|
|
19125
|
+
} // the main server origin
|
|
19126
|
+
// - when protocol is http
|
|
19127
|
+
// node-fetch do not apply local dns resolution to map localhost back to 127.0.0.1
|
|
19128
|
+
// despites localhost being mapped so we prefer to use the internal ip
|
|
19129
|
+
// (127.0.0.1)
|
|
19130
|
+
// - when protocol is https
|
|
19131
|
+
// using the hostname becomes important because the certificate is generated
|
|
19132
|
+
// for hostnames, not for ips
|
|
19133
|
+
// so we prefer https://locahost or https://local_hostname
|
|
19134
|
+
// over the ip
|
|
19135
|
+
|
|
19136
|
+
|
|
19137
|
+
const serverOrigin = serverOrigins.local; // now the server is started (listening) it cannot be aborted anymore
|
|
18945
19138
|
// (otherwise an AbortError is thrown to the code calling "startServer")
|
|
18946
19139
|
// we can proceed to create a stop function to stop it gacefully
|
|
18947
19140
|
// and add a request handler
|
|
18948
19141
|
|
|
18949
|
-
|
|
18950
19142
|
stopCallbackList.add(({
|
|
18951
19143
|
reason
|
|
18952
19144
|
}) => {
|
|
@@ -18984,12 +19176,6 @@ const startServer = async ({
|
|
|
18984
19176
|
};
|
|
18985
19177
|
|
|
18986
19178
|
status = "opened";
|
|
18987
|
-
const serverOrigins = await getServerOrigins({
|
|
18988
|
-
protocol,
|
|
18989
|
-
host,
|
|
18990
|
-
port
|
|
18991
|
-
});
|
|
18992
|
-
const serverOrigin = serverOrigins.local;
|
|
18993
19179
|
const removeConnectionErrorListener = listenServerConnectionError(nodeServer, onError);
|
|
18994
19180
|
stopCallbackList.add(removeConnectionErrorListener);
|
|
18995
19181
|
const connectionsTracker = trackServerPendingConnections(nodeServer, {
|
|
@@ -19181,7 +19367,7 @@ const startServer = async ({
|
|
|
19181
19367
|
const onPushStreamError = e => {
|
|
19182
19368
|
addRequestLog(requestNode, {
|
|
19183
19369
|
type: "error",
|
|
19184
|
-
value: createDetailedMessage$1(`An error occured while pushing a stream to the response for ${request.
|
|
19370
|
+
value: createDetailedMessage$1(`An error occured while pushing a stream to the response for ${request.resource}`, {
|
|
19185
19371
|
"error stack": e.stack
|
|
19186
19372
|
})
|
|
19187
19373
|
});
|
|
@@ -19285,7 +19471,7 @@ const startServer = async ({
|
|
|
19285
19471
|
|
|
19286
19472
|
addRequestLog(requestNode, {
|
|
19287
19473
|
type: "info",
|
|
19288
|
-
value: request.parent ? `Push ${request.
|
|
19474
|
+
value: request.parent ? `Push ${request.resource}` : `${request.method} ${request.url}`
|
|
19289
19475
|
});
|
|
19290
19476
|
|
|
19291
19477
|
const warn = value => {
|
|
@@ -19605,11 +19791,11 @@ const startServer = async ({
|
|
|
19605
19791
|
const websocketClients = new Set();
|
|
19606
19792
|
const {
|
|
19607
19793
|
WebSocketServer
|
|
19608
|
-
} = await import("./js/
|
|
19794
|
+
} = await import("./js/ws.js");
|
|
19609
19795
|
let websocketServer = new WebSocketServer({
|
|
19610
19796
|
noServer: true
|
|
19611
19797
|
});
|
|
19612
|
-
const websocketOrigin = protocol === "https" ? `wss://${
|
|
19798
|
+
const websocketOrigin = protocol === "https" ? `wss://${hostname}:${port}` : `ws://${hostname}:${port}`;
|
|
19613
19799
|
server.websocketOrigin = websocketOrigin;
|
|
19614
19800
|
|
|
19615
19801
|
const upgradeCallback = (nodeRequest, socket, head) => {
|
|
@@ -19650,6 +19836,7 @@ const startServer = async ({
|
|
|
19650
19836
|
Object.assign(server, {
|
|
19651
19837
|
getStatus: () => status,
|
|
19652
19838
|
port,
|
|
19839
|
+
hostname,
|
|
19653
19840
|
origin: serverOrigin,
|
|
19654
19841
|
origins: serverOrigins,
|
|
19655
19842
|
nodeServer,
|
|
@@ -20102,7 +20289,7 @@ const fetchFileSystem = async (filesystemUrl, {
|
|
|
20102
20289
|
|
|
20103
20290
|
rootDirectoryUrl = rootDirectoryUrlString;
|
|
20104
20291
|
} // here you might be tempted to add || cacheControl === 'no-cache'
|
|
20105
|
-
// but no-cache means
|
|
20292
|
+
// but no-cache means resource can be cache but must be revalidated (yeah naming is strange)
|
|
20106
20293
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Cacheability
|
|
20107
20294
|
|
|
20108
20295
|
|
|
@@ -20243,7 +20430,7 @@ const getClientCacheResponse = async ({
|
|
|
20243
20430
|
sourceUrl
|
|
20244
20431
|
}) => {
|
|
20245
20432
|
// here you might be tempted to add || headers["cache-control"] === "no-cache"
|
|
20246
|
-
// but no-cache means
|
|
20433
|
+
// but no-cache means resource can be cache but must be revalidated (yeah naming is strange)
|
|
20247
20434
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Cacheability
|
|
20248
20435
|
if (headers["cache-control"] === "no-store" || // let's disable it on no-cache too
|
|
20249
20436
|
headers["cache-control"] === "no-cache") {
|
|
@@ -20951,8 +21138,8 @@ const flattenAndFilterPlugins = (plugins, {
|
|
|
20951
21138
|
}
|
|
20952
21139
|
|
|
20953
21140
|
if (typeof appliesDuring === "string") {
|
|
20954
|
-
if (!["dev", "
|
|
20955
|
-
throw new Error(`"appliesDuring" must be "dev"
|
|
21141
|
+
if (!["dev", "build"].includes(appliesDuring)) {
|
|
21142
|
+
throw new Error(`"appliesDuring" must be "dev" or "build", got ${appliesDuring}`);
|
|
20956
21143
|
}
|
|
20957
21144
|
|
|
20958
21145
|
if (scenarios[appliesDuring]) {
|
|
@@ -21644,7 +21831,7 @@ const validateResponseIntegrity = ({
|
|
|
21644
21831
|
return true;
|
|
21645
21832
|
}
|
|
21646
21833
|
|
|
21647
|
-
const error = new Error(`Integrity validation failed for
|
|
21834
|
+
const error = new Error(`Integrity validation failed for resource "${url}". The integrity found for this resource is "${strongestAlgo}-${actualBase64Value}"`);
|
|
21648
21835
|
error.code = "EINTEGRITY";
|
|
21649
21836
|
error.algorithm = strongestAlgo;
|
|
21650
21837
|
error.found = actualBase64Value;
|
|
@@ -21756,7 +21943,8 @@ const createKitchen = ({
|
|
|
21756
21943
|
isEntryPoint = false,
|
|
21757
21944
|
isInline = false,
|
|
21758
21945
|
injected = false,
|
|
21759
|
-
|
|
21946
|
+
isResourceHint = false,
|
|
21947
|
+
dependsOnPackageJson,
|
|
21760
21948
|
content,
|
|
21761
21949
|
contentType,
|
|
21762
21950
|
assert,
|
|
@@ -21794,8 +21982,9 @@ const createKitchen = ({
|
|
|
21794
21982
|
isEntryPoint,
|
|
21795
21983
|
isInline,
|
|
21796
21984
|
injected,
|
|
21797
|
-
|
|
21798
|
-
|
|
21985
|
+
isResourceHint,
|
|
21986
|
+
dependsOnPackageJson,
|
|
21987
|
+
// for inline resources the reference contains the content
|
|
21799
21988
|
content,
|
|
21800
21989
|
contentType,
|
|
21801
21990
|
timing: {},
|
|
@@ -21846,8 +22035,8 @@ const createKitchen = ({
|
|
|
21846
22035
|
// And this is because this hook inject query params used to:
|
|
21847
22036
|
// - bypass browser cache (?v)
|
|
21848
22037
|
// - convey information (?hmr)
|
|
21849
|
-
// But do not represent an other
|
|
21850
|
-
// the same
|
|
22038
|
+
// But do not represent an other resource, it is considered as
|
|
22039
|
+
// the same resource under the hood
|
|
21851
22040
|
|
|
21852
22041
|
pluginController.callHooks("transformUrlSearchParams", reference, kitchenContext, returnValue => {
|
|
21853
22042
|
Object.keys(returnValue).forEach(key => {
|
|
@@ -22427,6 +22616,21 @@ const applyReferenceEffectsOnUrlInfo = (reference, urlInfo, context) => {
|
|
|
22427
22616
|
urlInfo.originalContent = context.scenarios.build ? urlInfo.originalContent === undefined ? reference.content : urlInfo.originalContent : reference.content;
|
|
22428
22617
|
urlInfo.content = reference.content;
|
|
22429
22618
|
}
|
|
22619
|
+
|
|
22620
|
+
const {
|
|
22621
|
+
dependsOnPackageJson
|
|
22622
|
+
} = reference;
|
|
22623
|
+
urlInfo.dependsOnPackageJson = dependsOnPackageJson;
|
|
22624
|
+
const relatedUrlInfos = context.urlGraph.getRelatedUrlInfos(reference.parentUrl);
|
|
22625
|
+
relatedUrlInfos.forEach(relatedUrlInfo => {
|
|
22626
|
+
if (relatedUrlInfo.dependsOnPackageJson) {
|
|
22627
|
+
// the url may depend due to an other reference
|
|
22628
|
+
// in that case keep dependsOnPackageJson to true
|
|
22629
|
+
return;
|
|
22630
|
+
}
|
|
22631
|
+
|
|
22632
|
+
relatedUrlInfo.dependsOnPackageJson = dependsOnPackageJson;
|
|
22633
|
+
});
|
|
22430
22634
|
};
|
|
22431
22635
|
|
|
22432
22636
|
const adjustUrlSite = (urlInfo, {
|
|
@@ -22656,11 +22860,11 @@ const loadUrlGraph = async ({
|
|
|
22656
22860
|
references
|
|
22657
22861
|
} = urlInfo;
|
|
22658
22862
|
references.forEach(reference => {
|
|
22659
|
-
// we don't cook
|
|
22660
|
-
// because they might refer to
|
|
22863
|
+
// we don't cook resource hints
|
|
22864
|
+
// because they might refer to resource that will be modified during build
|
|
22661
22865
|
// It also means something else have to reference that url in order to cook it
|
|
22662
|
-
// so that the preload is deleted by "
|
|
22663
|
-
if (reference.
|
|
22866
|
+
// so that the preload is deleted by "resync_resource_hints.js" otherwise
|
|
22867
|
+
if (reference.isResourceHint) {
|
|
22664
22868
|
return;
|
|
22665
22869
|
} // we use reference.generatedUrl to mimic what a browser would do:
|
|
22666
22870
|
// do a fetch to the specifier as found in the file
|
|
@@ -23325,23 +23529,23 @@ self.serviceWorkerUrls = ${JSON.stringify(serviceWorkerUrls, null, " ")};
|
|
|
23325
23529
|
/*
|
|
23326
23530
|
* Update <link rel="preload"> and friends after build (once we know everything)
|
|
23327
23531
|
*
|
|
23328
|
-
* - Used to remove
|
|
23532
|
+
* - Used to remove resource hint targeting an url that is no longer used:
|
|
23329
23533
|
* - Happens because of import assertions transpilation (file is inlined into JS)
|
|
23330
23534
|
*/
|
|
23331
|
-
const
|
|
23535
|
+
const resyncResourceHints = async ({
|
|
23332
23536
|
logger,
|
|
23333
23537
|
finalGraphKitchen,
|
|
23334
23538
|
finalGraph,
|
|
23335
23539
|
rawUrls,
|
|
23336
23540
|
postBuildRedirections
|
|
23337
23541
|
}) => {
|
|
23338
|
-
const
|
|
23542
|
+
const resourceHintActions = [];
|
|
23339
23543
|
GRAPH.forEach(finalGraph, urlInfo => {
|
|
23340
23544
|
if (urlInfo.type !== "html") {
|
|
23341
23545
|
return;
|
|
23342
23546
|
}
|
|
23343
23547
|
|
|
23344
|
-
|
|
23548
|
+
resourceHintActions.push(async () => {
|
|
23345
23549
|
const htmlAst = parseHtmlString(urlInfo.content, {
|
|
23346
23550
|
storeOriginalPositions: false
|
|
23347
23551
|
});
|
|
@@ -23353,9 +23557,9 @@ const resyncRessourceHints = async ({
|
|
|
23353
23557
|
}
|
|
23354
23558
|
|
|
23355
23559
|
const rel = getHtmlNodeAttribute(linkNode, "rel");
|
|
23356
|
-
const
|
|
23560
|
+
const isresourceHint = ["preconnect", "dns-prefetch", "prefetch", "preload", "modulepreload"].includes(rel);
|
|
23357
23561
|
|
|
23358
|
-
if (!
|
|
23562
|
+
if (!isresourceHint) {
|
|
23359
23563
|
return;
|
|
23360
23564
|
}
|
|
23361
23565
|
|
|
@@ -23369,7 +23573,7 @@ const resyncRessourceHints = async ({
|
|
|
23369
23573
|
}
|
|
23370
23574
|
|
|
23371
23575
|
if (!buildUrl) {
|
|
23372
|
-
logger.warn(`remove
|
|
23576
|
+
logger.warn(`remove resource hint because cannot find "${href}"`);
|
|
23373
23577
|
actions.push(() => {
|
|
23374
23578
|
removeHtmlNode(linkNode);
|
|
23375
23579
|
});
|
|
@@ -23380,7 +23584,7 @@ const resyncRessourceHints = async ({
|
|
|
23380
23584
|
const urlInfo = finalGraph.getUrlInfo(buildUrl);
|
|
23381
23585
|
|
|
23382
23586
|
if (!urlInfo) {
|
|
23383
|
-
logger.warn(`remove
|
|
23587
|
+
logger.warn(`remove resource hint because cannot find "${buildUrl}" in the graph`);
|
|
23384
23588
|
actions.push(() => {
|
|
23385
23589
|
removeHtmlNode(linkNode);
|
|
23386
23590
|
});
|
|
@@ -23388,7 +23592,7 @@ const resyncRessourceHints = async ({
|
|
|
23388
23592
|
}
|
|
23389
23593
|
|
|
23390
23594
|
if (urlInfo.dependents.size === 0) {
|
|
23391
|
-
logger.info(`remove
|
|
23595
|
+
logger.info(`remove resource hint because "${href}" not used anymore`);
|
|
23392
23596
|
actions.push(() => {
|
|
23393
23597
|
removeHtmlNode(linkNode);
|
|
23394
23598
|
});
|
|
@@ -23420,7 +23624,7 @@ const resyncRessourceHints = async ({
|
|
|
23420
23624
|
}
|
|
23421
23625
|
});
|
|
23422
23626
|
});
|
|
23423
|
-
await Promise.all(
|
|
23627
|
+
await Promise.all(resourceHintActions.map(resourceHintAction => resourceHintAction()));
|
|
23424
23628
|
};
|
|
23425
23629
|
|
|
23426
23630
|
/*
|
|
@@ -23701,10 +23905,10 @@ build ${entryPointKeys.length} entry points`);
|
|
|
23701
23905
|
addToBundlerIfAny(dependencyUrlInfo);
|
|
23702
23906
|
});
|
|
23703
23907
|
rawUrlInfo.references.forEach(reference => {
|
|
23704
|
-
if (reference.
|
|
23908
|
+
if (reference.isResourceHint && reference.expectedType === "js_module") {
|
|
23705
23909
|
const referencedUrlInfo = rawGraph.getUrlInfo(reference.url);
|
|
23706
23910
|
|
|
23707
|
-
if (referencedUrlInfo && // something else than the
|
|
23911
|
+
if (referencedUrlInfo && // something else than the resource hint is using this url
|
|
23708
23912
|
referencedUrlInfo.dependents.size > 0) {
|
|
23709
23913
|
addToBundlerIfAny(referencedUrlInfo);
|
|
23710
23914
|
}
|
|
@@ -23997,7 +24201,7 @@ build ${entryPointKeys.length} entry points`);
|
|
|
23997
24201
|
throw new Error(`urls should be inside build directory at this stage, found "${reference.url}"`);
|
|
23998
24202
|
}
|
|
23999
24203
|
|
|
24000
|
-
if (reference.
|
|
24204
|
+
if (reference.isResourceHint) {
|
|
24001
24205
|
// return the raw url, we will resync at the end
|
|
24002
24206
|
return rawUrls[reference.url];
|
|
24003
24207
|
} // remove eventual search params and hash
|
|
@@ -24101,7 +24305,7 @@ build ${entryPointKeys.length} entry points`);
|
|
|
24101
24305
|
kitchen: finalGraphKitchen,
|
|
24102
24306
|
outDirectoryUrl: new URL(".jsenv/postbuild/", rootDirectoryUrl),
|
|
24103
24307
|
writeGeneratedFiles,
|
|
24104
|
-
|
|
24308
|
+
skipResourceHint: true,
|
|
24105
24309
|
startLoading: cookEntryFile => {
|
|
24106
24310
|
entryUrls.forEach(entryUrl => {
|
|
24107
24311
|
const [, postBuildEntryUrlInfo] = cookEntryFile({
|
|
@@ -24173,7 +24377,7 @@ ${Array.from(finalGraph.urlInfoMap.keys()).join("\n")}`);
|
|
|
24173
24377
|
urlInfo.data.buildUrlIsVersioned = useVersionedUrl;
|
|
24174
24378
|
urlInfo.data.buildUrlSpecifier = buildUrlSpecifier;
|
|
24175
24379
|
});
|
|
24176
|
-
await
|
|
24380
|
+
await resyncResourceHints({
|
|
24177
24381
|
logger,
|
|
24178
24382
|
finalGraphKitchen,
|
|
24179
24383
|
finalGraph,
|
|
@@ -24517,7 +24721,7 @@ const applyUrlVersioning = async ({
|
|
|
24517
24721
|
return null;
|
|
24518
24722
|
}
|
|
24519
24723
|
|
|
24520
|
-
if (reference.
|
|
24724
|
+
if (reference.isResourceHint) {
|
|
24521
24725
|
return null;
|
|
24522
24726
|
} // specifier comes from "normalize" hook done a bit earlier in this file
|
|
24523
24727
|
// we want to get back their build url to access their infos
|
|
@@ -24578,7 +24782,7 @@ const applyUrlVersioning = async ({
|
|
|
24578
24782
|
operation: buildOperation,
|
|
24579
24783
|
urlGraph: finalGraph,
|
|
24580
24784
|
kitchen: versioningKitchen,
|
|
24581
|
-
|
|
24785
|
+
skipResourceHint: true,
|
|
24582
24786
|
writeGeneratedFiles,
|
|
24583
24787
|
startLoading: cookEntryFile => {
|
|
24584
24788
|
postBuildEntryUrls.forEach(postBuildEntryUrl => {
|
|
@@ -25060,7 +25264,7 @@ const createFileService = ({
|
|
|
25060
25264
|
|
|
25061
25265
|
return async request => {
|
|
25062
25266
|
// serve file inside ".jsenv" directory
|
|
25063
|
-
const requestFileUrl = new URL(request.
|
|
25267
|
+
const requestFileUrl = new URL(request.resource.slice(1), rootDirectoryUrl).href;
|
|
25064
25268
|
|
|
25065
25269
|
if (urlIsInsideOf(requestFileUrl, jsenvDirectoryUrl)) {
|
|
25066
25270
|
return fetchFileSystem(requestFileUrl, {
|
|
@@ -25084,7 +25288,7 @@ const createFileService = ({
|
|
|
25084
25288
|
const parentUrl = inferParentFromRequest(request, rootDirectoryUrl);
|
|
25085
25289
|
|
|
25086
25290
|
if (parentUrl) {
|
|
25087
|
-
reference = urlGraph.inferReference(request.
|
|
25291
|
+
reference = urlGraph.inferReference(request.resource, parentUrl);
|
|
25088
25292
|
}
|
|
25089
25293
|
|
|
25090
25294
|
if (!reference) {
|
|
@@ -25094,7 +25298,7 @@ const createFileService = ({
|
|
|
25094
25298
|
},
|
|
25095
25299
|
parentUrl: parentUrl || rootDirectoryUrl,
|
|
25096
25300
|
type: "http_request",
|
|
25097
|
-
specifier: request.
|
|
25301
|
+
specifier: request.resource
|
|
25098
25302
|
});
|
|
25099
25303
|
reference = entryPoint[0];
|
|
25100
25304
|
}
|
|
@@ -25261,7 +25465,7 @@ const startOmegaServer = async ({
|
|
|
25261
25465
|
privateKey,
|
|
25262
25466
|
certificate,
|
|
25263
25467
|
acceptAnyIp,
|
|
25264
|
-
|
|
25468
|
+
hostname,
|
|
25265
25469
|
port = 0,
|
|
25266
25470
|
keepProcessAlive = false,
|
|
25267
25471
|
onStop = () => {},
|
|
@@ -25302,7 +25506,7 @@ const startOmegaServer = async ({
|
|
|
25302
25506
|
certificate,
|
|
25303
25507
|
privateKey,
|
|
25304
25508
|
acceptAnyIp,
|
|
25305
|
-
|
|
25509
|
+
hostname,
|
|
25306
25510
|
port,
|
|
25307
25511
|
requestWaitingMs: 60_1000,
|
|
25308
25512
|
services: [jsenvServiceCORS({
|
|
@@ -25408,7 +25612,7 @@ const startDevServer = async ({
|
|
|
25408
25612
|
http2 = false,
|
|
25409
25613
|
certificate,
|
|
25410
25614
|
privateKey,
|
|
25411
|
-
|
|
25615
|
+
hostname,
|
|
25412
25616
|
port = 3456,
|
|
25413
25617
|
acceptAnyIp,
|
|
25414
25618
|
keepProcessAlive = true,
|
|
@@ -25548,7 +25752,7 @@ const startDevServer = async ({
|
|
|
25548
25752
|
http2,
|
|
25549
25753
|
certificate,
|
|
25550
25754
|
privateKey,
|
|
25551
|
-
|
|
25755
|
+
hostname,
|
|
25552
25756
|
port,
|
|
25553
25757
|
services,
|
|
25554
25758
|
rootDirectoryUrl,
|
|
@@ -25651,87 +25855,6 @@ const generateCoverageTextLog = (coverage, {
|
|
|
25651
25855
|
report.execute(context);
|
|
25652
25856
|
};
|
|
25653
25857
|
|
|
25654
|
-
const babelPluginInstrument = (api, {
|
|
25655
|
-
rootDirectoryUrl,
|
|
25656
|
-
useInlineSourceMaps = false,
|
|
25657
|
-
coverageConfig = {
|
|
25658
|
-
"./**/*": true
|
|
25659
|
-
}
|
|
25660
|
-
}) => {
|
|
25661
|
-
const {
|
|
25662
|
-
programVisitor
|
|
25663
|
-
} = requireFromJsenv("istanbul-lib-instrument");
|
|
25664
|
-
const {
|
|
25665
|
-
types
|
|
25666
|
-
} = api;
|
|
25667
|
-
const associations = URL_META.resolveAssociations({
|
|
25668
|
-
cover: coverageConfig
|
|
25669
|
-
}, rootDirectoryUrl);
|
|
25670
|
-
|
|
25671
|
-
const shouldInstrument = url => {
|
|
25672
|
-
return URL_META.applyAssociations({
|
|
25673
|
-
url,
|
|
25674
|
-
associations
|
|
25675
|
-
}).cover;
|
|
25676
|
-
};
|
|
25677
|
-
|
|
25678
|
-
return {
|
|
25679
|
-
name: "transform-instrument",
|
|
25680
|
-
visitor: {
|
|
25681
|
-
Program: {
|
|
25682
|
-
enter(path) {
|
|
25683
|
-
const {
|
|
25684
|
-
file
|
|
25685
|
-
} = this;
|
|
25686
|
-
const {
|
|
25687
|
-
opts
|
|
25688
|
-
} = file;
|
|
25689
|
-
|
|
25690
|
-
if (!opts.sourceFileName) {
|
|
25691
|
-
console.warn(`cannot instrument file when "sourceFileName" option is not set`);
|
|
25692
|
-
return;
|
|
25693
|
-
}
|
|
25694
|
-
|
|
25695
|
-
const fileUrl = fileSystemPathToUrl$1(opts.sourceFileName);
|
|
25696
|
-
|
|
25697
|
-
if (!shouldInstrument(fileUrl)) {
|
|
25698
|
-
return;
|
|
25699
|
-
}
|
|
25700
|
-
|
|
25701
|
-
this.__dv__ = null;
|
|
25702
|
-
let inputSourceMap;
|
|
25703
|
-
|
|
25704
|
-
if (useInlineSourceMaps) {
|
|
25705
|
-
// https://github.com/istanbuljs/babel-plugin-istanbul/commit/a9e15643d249a2985e4387e4308022053b2cd0ad#diff-1fdf421c05c1140f6d71444ea2b27638R65
|
|
25706
|
-
inputSourceMap = opts.inputSourceMap || file.inputMap ? file.inputMap.sourcemap : null;
|
|
25707
|
-
} else {
|
|
25708
|
-
inputSourceMap = opts.inputSourceMap;
|
|
25709
|
-
}
|
|
25710
|
-
|
|
25711
|
-
this.__dv__ = programVisitor(types, opts.filenameRelative || opts.filename, {
|
|
25712
|
-
coverageVariable: "__coverage__",
|
|
25713
|
-
inputSourceMap
|
|
25714
|
-
});
|
|
25715
|
-
|
|
25716
|
-
this.__dv__.enter(path);
|
|
25717
|
-
},
|
|
25718
|
-
|
|
25719
|
-
exit(path) {
|
|
25720
|
-
if (!this.__dv__) {
|
|
25721
|
-
return;
|
|
25722
|
-
}
|
|
25723
|
-
|
|
25724
|
-
const object = this.__dv__.exit(path); // object got two properties: fileCoverage and sourceMappingURL
|
|
25725
|
-
|
|
25726
|
-
|
|
25727
|
-
this.file.metadata.coverage = object.fileCoverage;
|
|
25728
|
-
}
|
|
25729
|
-
|
|
25730
|
-
}
|
|
25731
|
-
}
|
|
25732
|
-
};
|
|
25733
|
-
};
|
|
25734
|
-
|
|
25735
25858
|
const readNodeV8CoverageDirectory = async ({
|
|
25736
25859
|
logger,
|
|
25737
25860
|
signal,
|
|
@@ -26424,6 +26547,41 @@ const run = async ({
|
|
|
26424
26547
|
}
|
|
26425
26548
|
};
|
|
26426
26549
|
|
|
26550
|
+
const pingServer = async url => {
|
|
26551
|
+
const server = createServer();
|
|
26552
|
+
const {
|
|
26553
|
+
hostname,
|
|
26554
|
+
port
|
|
26555
|
+
} = new URL(url);
|
|
26556
|
+
|
|
26557
|
+
try {
|
|
26558
|
+
await new Promise((resolve, reject) => {
|
|
26559
|
+
server.on("error", reject);
|
|
26560
|
+
server.on("listening", () => {
|
|
26561
|
+
resolve();
|
|
26562
|
+
});
|
|
26563
|
+
server.listen(port, hostname);
|
|
26564
|
+
});
|
|
26565
|
+
} catch (error) {
|
|
26566
|
+
if (error && error.code === "EADDRINUSE") {
|
|
26567
|
+
return true;
|
|
26568
|
+
}
|
|
26569
|
+
|
|
26570
|
+
if (error && error.code === "EACCES") {
|
|
26571
|
+
return true;
|
|
26572
|
+
}
|
|
26573
|
+
|
|
26574
|
+
throw error;
|
|
26575
|
+
}
|
|
26576
|
+
|
|
26577
|
+
await new Promise((resolve, reject) => {
|
|
26578
|
+
server.on("error", reject);
|
|
26579
|
+
server.on("close", resolve);
|
|
26580
|
+
server.close();
|
|
26581
|
+
});
|
|
26582
|
+
return false;
|
|
26583
|
+
};
|
|
26584
|
+
|
|
26427
26585
|
const ensureGlobalGc = () => {
|
|
26428
26586
|
if (!global.gc) {
|
|
26429
26587
|
v8.setFlagsFromString("--expose_gc");
|
|
@@ -26859,8 +27017,8 @@ const executePlan = async (plan, {
|
|
|
26859
27017
|
completedExecutionLogMerging,
|
|
26860
27018
|
completedExecutionLogAbbreviation,
|
|
26861
27019
|
rootDirectoryUrl,
|
|
27020
|
+
devServerOrigin,
|
|
26862
27021
|
keepRunning,
|
|
26863
|
-
services,
|
|
26864
27022
|
defaultMsAllocatedPerExecution,
|
|
26865
27023
|
maxExecutionsInParallel,
|
|
26866
27024
|
failFast,
|
|
@@ -26873,18 +27031,6 @@ const executePlan = async (plan, {
|
|
|
26873
27031
|
coverageMethodForNodeJs,
|
|
26874
27032
|
coverageV8ConflictWarning,
|
|
26875
27033
|
coverageTempDirectoryRelativeUrl,
|
|
26876
|
-
scenarios,
|
|
26877
|
-
sourcemaps,
|
|
26878
|
-
plugins,
|
|
26879
|
-
nodeEsmResolution,
|
|
26880
|
-
fileSystemMagicResolution,
|
|
26881
|
-
transpilation,
|
|
26882
|
-
writeGeneratedFiles,
|
|
26883
|
-
protocol,
|
|
26884
|
-
privateKey,
|
|
26885
|
-
certificate,
|
|
26886
|
-
host,
|
|
26887
|
-
port,
|
|
26888
27034
|
beforeExecutionCallback = () => {},
|
|
26889
27035
|
afterExecutionCallback = () => {}
|
|
26890
27036
|
} = {}) => {
|
|
@@ -26908,7 +27054,7 @@ const executePlan = async (plan, {
|
|
|
26908
27054
|
if (runtime) {
|
|
26909
27055
|
runtimes[runtime.name] = runtime.version;
|
|
26910
27056
|
|
|
26911
|
-
if (runtime.
|
|
27057
|
+
if (runtime.type === "browser") {
|
|
26912
27058
|
someNeedsServer = true;
|
|
26913
27059
|
}
|
|
26914
27060
|
|
|
@@ -26999,6 +27145,7 @@ const executePlan = async (plan, {
|
|
|
26999
27145
|
|
|
27000
27146
|
let runtimeParams = {
|
|
27001
27147
|
rootDirectoryUrl,
|
|
27148
|
+
devServerOrigin,
|
|
27002
27149
|
coverageEnabled,
|
|
27003
27150
|
coverageConfig,
|
|
27004
27151
|
coverageMethodForBrowsers,
|
|
@@ -27007,48 +27154,15 @@ const executePlan = async (plan, {
|
|
|
27007
27154
|
};
|
|
27008
27155
|
|
|
27009
27156
|
if (someNeedsServer) {
|
|
27010
|
-
|
|
27011
|
-
|
|
27012
|
-
|
|
27013
|
-
keepProcessAlive: false,
|
|
27014
|
-
port,
|
|
27015
|
-
host,
|
|
27016
|
-
protocol,
|
|
27017
|
-
certificate,
|
|
27018
|
-
privateKey,
|
|
27019
|
-
services,
|
|
27020
|
-
rootDirectoryUrl,
|
|
27021
|
-
scenarios,
|
|
27022
|
-
runtimeCompat: runtimes,
|
|
27023
|
-
plugins,
|
|
27024
|
-
htmlSupervisor: true,
|
|
27025
|
-
nodeEsmResolution,
|
|
27026
|
-
fileSystemMagicResolution,
|
|
27027
|
-
transpilation: { ...transpilation,
|
|
27028
|
-
getCustomBabelPlugins: ({
|
|
27029
|
-
clientRuntimeCompat
|
|
27030
|
-
}) => {
|
|
27031
|
-
if (coverageEnabled && (coverageMethodForBrowsers !== "playwright_api" || Object.keys(clientRuntimeCompat)[0] !== "chrome")) {
|
|
27032
|
-
return {
|
|
27033
|
-
"transform-instrument": [babelPluginInstrument, {
|
|
27034
|
-
rootDirectoryUrl,
|
|
27035
|
-
coverageConfig
|
|
27036
|
-
}]
|
|
27037
|
-
};
|
|
27038
|
-
}
|
|
27157
|
+
if (!devServerOrigin) {
|
|
27158
|
+
throw new TypeError(`devServerOrigin is required when running tests on browser(s)`);
|
|
27159
|
+
}
|
|
27039
27160
|
|
|
27040
|
-
|
|
27041
|
-
|
|
27042
|
-
|
|
27043
|
-
|
|
27044
|
-
|
|
27045
|
-
});
|
|
27046
|
-
multipleExecutionsOperation.addEndCallback(async () => {
|
|
27047
|
-
await server.stop();
|
|
27048
|
-
});
|
|
27049
|
-
runtimeParams = { ...runtimeParams,
|
|
27050
|
-
server
|
|
27051
|
-
};
|
|
27161
|
+
const devServerStarted = await pingServer(devServerOrigin);
|
|
27162
|
+
|
|
27163
|
+
if (!devServerStarted) {
|
|
27164
|
+
throw new Error(`dev server not started at ${devServerOrigin}. It is required to run tests`);
|
|
27165
|
+
}
|
|
27052
27166
|
}
|
|
27053
27167
|
|
|
27054
27168
|
logger.debug(`Generate executions`);
|
|
@@ -27391,9 +27505,10 @@ const executeInParallel = async ({
|
|
|
27391
27505
|
};
|
|
27392
27506
|
|
|
27393
27507
|
/**
|
|
27394
|
-
* Execute a list of files and log how it goes
|
|
27508
|
+
* Execute a list of files and log how it goes.
|
|
27395
27509
|
* @param {Object} testPlanParameters
|
|
27396
27510
|
* @param {string|url} testPlanParameters.rootDirectoryUrl Root directory of the project
|
|
27511
|
+
* @param {string|url} [testPlanParameters.serverOrigin=undefined] Jsenv dev server origin; required when executing test on browsers
|
|
27397
27512
|
* @param {Object} testPlanParameters.testPlan Object associating patterns leading to files to runtimes where they should be executed
|
|
27398
27513
|
* @param {boolean} [testPlanParameters.completedExecutionLogAbbreviation=false] Abbreviate completed execution information to shorten terminal output
|
|
27399
27514
|
* @param {boolean} [testPlanParameters.completedExecutionLogMerging=false] Merge completed execution logs to shorten terminal output
|
|
@@ -27420,6 +27535,7 @@ const executeTestPlan = async ({
|
|
|
27420
27535
|
completedExecutionLogAbbreviation = false,
|
|
27421
27536
|
completedExecutionLogMerging = false,
|
|
27422
27537
|
rootDirectoryUrl,
|
|
27538
|
+
devServerOrigin,
|
|
27423
27539
|
testPlan,
|
|
27424
27540
|
updateProcessExitCode = true,
|
|
27425
27541
|
maxExecutionsInParallel = 1,
|
|
@@ -27450,17 +27566,7 @@ const executeTestPlan = async ({
|
|
|
27450
27566
|
coverageReportSkipFull = false,
|
|
27451
27567
|
coverageReportTextLog = true,
|
|
27452
27568
|
coverageReportJsonFile = process.env.CI ? null : "./.coverage/coverage.json",
|
|
27453
|
-
coverageReportHtmlDirectory = process.env.CI ? "./.coverage/" : null
|
|
27454
|
-
sourcemaps = "inline",
|
|
27455
|
-
plugins = [],
|
|
27456
|
-
nodeEsmResolution,
|
|
27457
|
-
fileSystemMagicResolution,
|
|
27458
|
-
writeGeneratedFiles = false,
|
|
27459
|
-
protocol,
|
|
27460
|
-
privateKey,
|
|
27461
|
-
certificate,
|
|
27462
|
-
host,
|
|
27463
|
-
port
|
|
27569
|
+
coverageReportHtmlDirectory = process.env.CI ? "./.coverage/" : null
|
|
27464
27570
|
}) => {
|
|
27465
27571
|
const logger = createLogger({
|
|
27466
27572
|
logLevel
|
|
@@ -27520,6 +27626,7 @@ const executeTestPlan = async ({
|
|
|
27520
27626
|
completedExecutionLogMerging,
|
|
27521
27627
|
completedExecutionLogAbbreviation,
|
|
27522
27628
|
rootDirectoryUrl,
|
|
27629
|
+
devServerOrigin,
|
|
27523
27630
|
maxExecutionsInParallel,
|
|
27524
27631
|
defaultMsAllocatedPerExecution,
|
|
27525
27632
|
failFast,
|
|
@@ -27532,21 +27639,7 @@ const executeTestPlan = async ({
|
|
|
27532
27639
|
coverageMethodForBrowsers,
|
|
27533
27640
|
coverageMethodForNodeJs,
|
|
27534
27641
|
coverageV8ConflictWarning,
|
|
27535
|
-
coverageTempDirectoryRelativeUrl
|
|
27536
|
-
scenarios: {
|
|
27537
|
-
dev: true,
|
|
27538
|
-
test: true
|
|
27539
|
-
},
|
|
27540
|
-
sourcemaps,
|
|
27541
|
-
plugins,
|
|
27542
|
-
nodeEsmResolution,
|
|
27543
|
-
fileSystemMagicResolution,
|
|
27544
|
-
writeGeneratedFiles,
|
|
27545
|
-
protocol,
|
|
27546
|
-
privateKey,
|
|
27547
|
-
certificate,
|
|
27548
|
-
host,
|
|
27549
|
-
port
|
|
27642
|
+
coverageTempDirectoryRelativeUrl
|
|
27550
27643
|
});
|
|
27551
27644
|
|
|
27552
27645
|
if (updateProcessExitCode && result.planSummary.counters.total !== result.planSummary.counters.completed) {
|
|
@@ -27664,8 +27757,7 @@ const createRuntimeFromPlaywright = ({
|
|
|
27664
27757
|
const runtime = {
|
|
27665
27758
|
type: "browser",
|
|
27666
27759
|
name: browserName,
|
|
27667
|
-
version: browserVersion
|
|
27668
|
-
needsServer: true
|
|
27760
|
+
version: browserVersion
|
|
27669
27761
|
};
|
|
27670
27762
|
let browserAndContextPromise;
|
|
27671
27763
|
|
|
@@ -27674,7 +27766,7 @@ const createRuntimeFromPlaywright = ({
|
|
|
27674
27766
|
logger,
|
|
27675
27767
|
rootDirectoryUrl,
|
|
27676
27768
|
fileRelativeUrl,
|
|
27677
|
-
|
|
27769
|
+
devServerOrigin,
|
|
27678
27770
|
// measurePerformance,
|
|
27679
27771
|
collectPerformance,
|
|
27680
27772
|
coverageEnabled = false,
|
|
@@ -27749,7 +27841,13 @@ const createRuntimeFromPlaywright = ({
|
|
|
27749
27841
|
await disconnected;
|
|
27750
27842
|
};
|
|
27751
27843
|
|
|
27752
|
-
const
|
|
27844
|
+
const coverageInHeaders = coverageEnabled && (!coveragePlaywrightAPIAvailable || coverageMethodForBrowsers !== "playwright_api");
|
|
27845
|
+
const page = await browserContext.newPage({
|
|
27846
|
+
extraHTTPHeaders: { ...(coverageInHeaders ? {
|
|
27847
|
+
"x-coverage-istanbul": JSON.stringify(coverageConfig)
|
|
27848
|
+
} : {})
|
|
27849
|
+
}
|
|
27850
|
+
});
|
|
27753
27851
|
|
|
27754
27852
|
const closePage = async () => {
|
|
27755
27853
|
try {
|
|
@@ -27777,7 +27875,7 @@ const createRuntimeFromPlaywright = ({
|
|
|
27777
27875
|
const v8CoveragesWithFsUrls = v8CoveragesWithWebUrls.map(v8CoveragesWithWebUrl => {
|
|
27778
27876
|
const fsUrl = moveUrl({
|
|
27779
27877
|
url: v8CoveragesWithWebUrl.url,
|
|
27780
|
-
from: `${
|
|
27878
|
+
from: `${devServerOrigin}/`,
|
|
27781
27879
|
to: rootDirectoryUrl,
|
|
27782
27880
|
preferAbsolute: true
|
|
27783
27881
|
});
|
|
@@ -27848,7 +27946,7 @@ const createRuntimeFromPlaywright = ({
|
|
|
27848
27946
|
});
|
|
27849
27947
|
}
|
|
27850
27948
|
|
|
27851
|
-
const fileClientUrl = new URL(fileRelativeUrl, `${
|
|
27949
|
+
const fileClientUrl = new URL(fileRelativeUrl, `${devServerOrigin}/`).href; // https://github.com/GoogleChrome/puppeteer/blob/v1.4.0/docs/api.md#event-console
|
|
27852
27950
|
|
|
27853
27951
|
const removeConsoleListener = registerEvent({
|
|
27854
27952
|
object: page,
|
|
@@ -27962,7 +28060,7 @@ const createRuntimeFromPlaywright = ({
|
|
|
27962
28060
|
} = returnValue;
|
|
27963
28061
|
const error = evalException(exceptionSource, {
|
|
27964
28062
|
rootDirectoryUrl,
|
|
27965
|
-
|
|
28063
|
+
devServerOrigin,
|
|
27966
28064
|
transformErrorHook
|
|
27967
28065
|
});
|
|
27968
28066
|
cb({
|
|
@@ -28198,7 +28296,7 @@ const registerEvent = ({
|
|
|
28198
28296
|
|
|
28199
28297
|
const evalException = (exceptionSource, {
|
|
28200
28298
|
rootDirectoryUrl,
|
|
28201
|
-
|
|
28299
|
+
devServerOrigin,
|
|
28202
28300
|
transformErrorHook
|
|
28203
28301
|
}) => {
|
|
28204
28302
|
const script = new Script(exceptionSource, {
|
|
@@ -28207,7 +28305,7 @@ const evalException = (exceptionSource, {
|
|
|
28207
28305
|
const error = script.runInThisContext();
|
|
28208
28306
|
|
|
28209
28307
|
if (error && error instanceof Error) {
|
|
28210
|
-
const remoteRootRegexp = new RegExp(escapeRegexpSpecialChars(`${
|
|
28308
|
+
const remoteRootRegexp = new RegExp(escapeRegexpSpecialChars(`${devServerOrigin}/`), "g");
|
|
28211
28309
|
error.stack = error.stack.replace(remoteRootRegexp, rootDirectoryUrl);
|
|
28212
28310
|
error.message = error.message.replace(remoteRootRegexp, rootDirectoryUrl);
|
|
28213
28311
|
}
|
|
@@ -29205,7 +29303,7 @@ const startBuildServer = async ({
|
|
|
29205
29303
|
certificate,
|
|
29206
29304
|
privateKey,
|
|
29207
29305
|
acceptAnyIp,
|
|
29208
|
-
|
|
29306
|
+
hostname,
|
|
29209
29307
|
port = 9779,
|
|
29210
29308
|
services = [],
|
|
29211
29309
|
keepProcessAlive = true,
|
|
@@ -29342,7 +29440,7 @@ const startBuildServer = async ({
|
|
|
29342
29440
|
certificate,
|
|
29343
29441
|
privateKey,
|
|
29344
29442
|
acceptAnyIp,
|
|
29345
|
-
|
|
29443
|
+
hostname,
|
|
29346
29444
|
port,
|
|
29347
29445
|
serverTiming: true,
|
|
29348
29446
|
requestWaitingMs: 60_000,
|
|
@@ -29387,15 +29485,15 @@ const createBuildFilesService = ({
|
|
|
29387
29485
|
buildIndexPath
|
|
29388
29486
|
}) => {
|
|
29389
29487
|
return request => {
|
|
29390
|
-
const urlIsVersioned = new URL(request.
|
|
29488
|
+
const urlIsVersioned = new URL(request.url).searchParams.has("v");
|
|
29391
29489
|
|
|
29392
|
-
if (buildIndexPath && request.
|
|
29490
|
+
if (buildIndexPath && request.resource === "/") {
|
|
29393
29491
|
request = { ...request,
|
|
29394
|
-
|
|
29492
|
+
resource: `/${buildIndexPath}`
|
|
29395
29493
|
};
|
|
29396
29494
|
}
|
|
29397
29495
|
|
|
29398
|
-
return fetchFileSystem(new URL(request.
|
|
29496
|
+
return fetchFileSystem(new URL(request.resource.slice(1), buildDirectoryUrl), {
|
|
29399
29497
|
headers: request.headers,
|
|
29400
29498
|
cacheControl: urlIsVersioned ? `private,max-age=${SECONDS_IN_30_DAYS},immutable` : "private,max-age=0,must-revalidate",
|
|
29401
29499
|
etagEnabled: true,
|
|
@@ -29413,32 +29511,17 @@ const execute = async ({
|
|
|
29413
29511
|
handleSIGINT = true,
|
|
29414
29512
|
logLevel,
|
|
29415
29513
|
rootDirectoryUrl,
|
|
29514
|
+
devServerOrigin,
|
|
29416
29515
|
fileRelativeUrl,
|
|
29417
29516
|
allocatedMs,
|
|
29418
29517
|
mirrorConsole = true,
|
|
29419
29518
|
keepRunning = false,
|
|
29420
|
-
services,
|
|
29421
29519
|
collectConsole,
|
|
29422
29520
|
collectCoverage,
|
|
29423
29521
|
coverageTempDirectoryUrl,
|
|
29424
29522
|
collectPerformance = false,
|
|
29425
29523
|
runtime,
|
|
29426
29524
|
runtimeParams,
|
|
29427
|
-
scenarios = {
|
|
29428
|
-
dev: true
|
|
29429
|
-
},
|
|
29430
|
-
plugins = [],
|
|
29431
|
-
nodeEsmResolution,
|
|
29432
|
-
fileSystemMagicResolution,
|
|
29433
|
-
transpilation,
|
|
29434
|
-
htmlSupervisor = true,
|
|
29435
|
-
sourcemaps = "inline",
|
|
29436
|
-
writeGeneratedFiles = false,
|
|
29437
|
-
port,
|
|
29438
|
-
protocol,
|
|
29439
|
-
http2,
|
|
29440
|
-
certificate,
|
|
29441
|
-
privateKey,
|
|
29442
29525
|
ignoreError = false
|
|
29443
29526
|
}) => {
|
|
29444
29527
|
const logger = createLogger({
|
|
@@ -29460,45 +29543,21 @@ const execute = async ({
|
|
|
29460
29543
|
|
|
29461
29544
|
runtimeParams = {
|
|
29462
29545
|
rootDirectoryUrl,
|
|
29546
|
+
devServerOrigin,
|
|
29463
29547
|
fileRelativeUrl,
|
|
29464
29548
|
...runtimeParams
|
|
29465
29549
|
};
|
|
29466
29550
|
|
|
29467
|
-
if (runtime.
|
|
29468
|
-
|
|
29469
|
-
|
|
29470
|
-
|
|
29471
|
-
keepProcessAlive: false,
|
|
29472
|
-
services,
|
|
29473
|
-
port,
|
|
29474
|
-
protocol,
|
|
29475
|
-
http2,
|
|
29476
|
-
certificate,
|
|
29477
|
-
privateKey,
|
|
29478
|
-
rootDirectoryUrl,
|
|
29479
|
-
scenarios,
|
|
29480
|
-
runtimeCompat: {
|
|
29481
|
-
[runtime.name]: runtime.version
|
|
29482
|
-
},
|
|
29483
|
-
plugins,
|
|
29484
|
-
htmlSupervisor,
|
|
29485
|
-
nodeEsmResolution,
|
|
29486
|
-
fileSystemMagicResolution,
|
|
29487
|
-
transpilation,
|
|
29488
|
-
sourcemaps,
|
|
29489
|
-
writeGeneratedFiles
|
|
29490
|
-
});
|
|
29491
|
-
executeOperation.addEndCallback(async () => {
|
|
29492
|
-
await server.stop("execution done");
|
|
29493
|
-
});
|
|
29494
|
-
runtimeParams = { ...runtimeParams,
|
|
29495
|
-
server
|
|
29496
|
-
};
|
|
29551
|
+
if (runtime.type === "browser") {
|
|
29552
|
+
if (!devServerOrigin) {
|
|
29553
|
+
throw new TypeError(`devServerOrigin is required when running tests on browser(s)`);
|
|
29554
|
+
}
|
|
29497
29555
|
|
|
29498
|
-
|
|
29499
|
-
|
|
29500
|
-
|
|
29501
|
-
|
|
29556
|
+
const devServerStarted = await pingServer(devServerOrigin);
|
|
29557
|
+
|
|
29558
|
+
if (!devServerStarted) {
|
|
29559
|
+
throw new Error(`dev server not started at ${devServerOrigin}. It is required to run tests`);
|
|
29560
|
+
}
|
|
29502
29561
|
}
|
|
29503
29562
|
|
|
29504
29563
|
let result = await run({
|
|
@@ -29620,4 +29679,4 @@ const jsenvPluginInjectGlobals = urlAssociations => {
|
|
|
29620
29679
|
};
|
|
29621
29680
|
};
|
|
29622
29681
|
|
|
29623
|
-
export { build, chromium, chromiumIsolatedTab, execute, executeTestPlan, firefox, firefoxIsolatedTab, jsenvPluginInjectGlobals, nodeChildProcess, nodeWorkerThread, startBuildServer, startDevServer, webkit, webkitIsolatedTab };
|
|
29682
|
+
export { build, chromium, chromiumIsolatedTab, execute, executeTestPlan, firefox, firefoxIsolatedTab, jsenvPluginInjectGlobals, nodeChildProcess, nodeWorkerThread, pingServer, startBuildServer, startDevServer, webkit, webkitIsolatedTab };
|