@jsenv/core 27.1.0 → 27.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/controllable_child_process.mjs +139 -0
- package/dist/controllable_worker_thread.mjs +103 -0
- package/dist/js/execute_using_dynamic_import.js +169 -0
- package/dist/js/v8_coverage.js +539 -0
- package/dist/main.js +575 -804
- package/package.json +8 -7
- package/src/build/build.js +9 -12
- package/src/build/build_urls_generator.js +1 -1
- package/src/build/inject_global_version_mappings.js +3 -2
- package/src/build/inject_service_worker_urls.js +1 -2
- package/src/execute/run.js +50 -68
- package/src/execute/runtimes/browsers/from_playwright.js +13 -8
- package/src/execute/runtimes/node/{controllable_file.mjs → controllable_child_process.mjs} +18 -50
- package/src/execute/runtimes/node/controllable_worker_thread.mjs +103 -0
- package/src/execute/runtimes/node/execute_using_dynamic_import.js +49 -0
- package/src/execute/runtimes/node/exit_codes.js +9 -0
- package/src/execute/runtimes/node/{node_process.js → node_child_process.js} +56 -50
- package/src/execute/runtimes/node/node_worker_thread.js +268 -25
- package/src/execute/runtimes/node/profiler_v8_coverage.js +56 -0
- package/src/main.js +3 -1
- package/src/omega/kitchen.js +19 -6
- package/src/omega/server/file_service.js +2 -2
- package/src/omega/url_graph/url_graph_load.js +0 -1
- package/src/omega/url_graph.js +1 -0
- package/src/plugins/bundling/js_module/bundle_js_module.js +2 -5
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +18 -15
- package/src/plugins/url_resolution/jsenv_plugin_url_resolution.js +2 -1
- package/src/test/coverage/report_to_coverage.js +16 -19
- package/src/test/coverage/v8_coverage.js +26 -0
- package/src/test/coverage/{v8_coverage_from_directory.js → v8_coverage_node_directory.js} +22 -26
- package/src/test/execute_plan.js +92 -91
- package/src/test/execute_test_plan.js +15 -13
- package/dist/js/controllable_file.mjs +0 -227
package/dist/main.js
CHANGED
|
@@ -13,17 +13,17 @@ import { performance } from "node:perf_hooks";
|
|
|
13
13
|
import { extname, dirname, basename } from "node:path";
|
|
14
14
|
import { pathToFileURL, fileURLToPath } from "node:url";
|
|
15
15
|
import crypto, { createHash } from "node:crypto";
|
|
16
|
+
import { U as URL_META, f as filterV8Coverage } from "./js/v8_coverage.js";
|
|
16
17
|
import { parseHtmlString, stringifyHtmlAst, visitHtmlNodes, getHtmlNodeAttribute, setHtmlNodeAttributes, parseSrcSet, getHtmlNodePosition, getHtmlNodeAttributePosition, applyPostCss, postCssPluginUrlVisitor, parseJsUrls, findHtmlNode, getHtmlNodeText, removeHtmlNode, setHtmlNodeText, analyzeScriptNode, applyBabelPlugins, injectScriptNodeAsEarlyAsPossible, createHtmlNode, removeHtmlNodeText, transpileWithParcel, injectJsImport, minifyWithParcel, analyzeLinkNode } from "@jsenv/ast";
|
|
17
18
|
import { createMagicSource, composeTwoSourcemaps, sourcemapConverter, SOURCEMAP, generateSourcemapFileUrl, generateSourcemapDataUrl } from "@jsenv/sourcemap";
|
|
18
19
|
import { createRequire } from "node:module";
|
|
19
20
|
import babelParser from "@babel/parser";
|
|
21
|
+
import v8, { takeCoverage } from "node:v8";
|
|
20
22
|
import wrapAnsi from "wrap-ansi";
|
|
21
23
|
import stripAnsi from "strip-ansi";
|
|
22
24
|
import cuid from "cuid";
|
|
23
|
-
import v8 from "node:v8";
|
|
24
25
|
import { runInNewContext, Script } from "node:vm";
|
|
25
26
|
import { fork } from "node:child_process";
|
|
26
|
-
import { u as uneval } from "./js/uneval.js";
|
|
27
27
|
|
|
28
28
|
const LOG_LEVEL_OFF = "off";
|
|
29
29
|
const LOG_LEVEL_DEBUG = "debug";
|
|
@@ -5742,515 +5742,6 @@ const createEventHistory = limit => {
|
|
|
5742
5742
|
};
|
|
5743
5743
|
};
|
|
5744
5744
|
|
|
5745
|
-
const assertUrlLike = (value, name = "url") => {
|
|
5746
|
-
if (typeof value !== "string") {
|
|
5747
|
-
throw new TypeError(`${name} must be a url string, got ${value}`);
|
|
5748
|
-
}
|
|
5749
|
-
|
|
5750
|
-
if (isWindowsPathnameSpecifier(value)) {
|
|
5751
|
-
throw new TypeError(`${name} must be a url but looks like a windows pathname, got ${value}`);
|
|
5752
|
-
}
|
|
5753
|
-
|
|
5754
|
-
if (!hasScheme$1(value)) {
|
|
5755
|
-
throw new TypeError(`${name} must be a url and no scheme found, got ${value}`);
|
|
5756
|
-
}
|
|
5757
|
-
};
|
|
5758
|
-
const isPlainObject = value => {
|
|
5759
|
-
if (value === null) {
|
|
5760
|
-
return false;
|
|
5761
|
-
}
|
|
5762
|
-
|
|
5763
|
-
if (typeof value === "object") {
|
|
5764
|
-
if (Array.isArray(value)) {
|
|
5765
|
-
return false;
|
|
5766
|
-
}
|
|
5767
|
-
|
|
5768
|
-
return true;
|
|
5769
|
-
}
|
|
5770
|
-
|
|
5771
|
-
return false;
|
|
5772
|
-
};
|
|
5773
|
-
|
|
5774
|
-
const isWindowsPathnameSpecifier = specifier => {
|
|
5775
|
-
const firstChar = specifier[0];
|
|
5776
|
-
if (!/[a-zA-Z]/.test(firstChar)) return false;
|
|
5777
|
-
const secondChar = specifier[1];
|
|
5778
|
-
if (secondChar !== ":") return false;
|
|
5779
|
-
const thirdChar = specifier[2];
|
|
5780
|
-
return thirdChar === "/" || thirdChar === "\\";
|
|
5781
|
-
};
|
|
5782
|
-
|
|
5783
|
-
const hasScheme$1 = specifier => /^[a-zA-Z]+:/.test(specifier);
|
|
5784
|
-
|
|
5785
|
-
const resolveAssociations = (associations, baseUrl) => {
|
|
5786
|
-
assertUrlLike(baseUrl, "baseUrl");
|
|
5787
|
-
const associationsResolved = {};
|
|
5788
|
-
Object.keys(associations).forEach(key => {
|
|
5789
|
-
const valueMap = associations[key];
|
|
5790
|
-
const valueMapResolved = {};
|
|
5791
|
-
Object.keys(valueMap).forEach(pattern => {
|
|
5792
|
-
const value = valueMap[pattern];
|
|
5793
|
-
const patternResolved = normalizeUrlPattern(pattern, baseUrl);
|
|
5794
|
-
valueMapResolved[patternResolved] = value;
|
|
5795
|
-
});
|
|
5796
|
-
associationsResolved[key] = valueMapResolved;
|
|
5797
|
-
});
|
|
5798
|
-
return associationsResolved;
|
|
5799
|
-
};
|
|
5800
|
-
|
|
5801
|
-
const normalizeUrlPattern = (urlPattern, baseUrl) => {
|
|
5802
|
-
// starts with a scheme
|
|
5803
|
-
if (/^[a-zA-Z]{2,}:/.test(urlPattern)) {
|
|
5804
|
-
return urlPattern;
|
|
5805
|
-
}
|
|
5806
|
-
|
|
5807
|
-
return String(new URL(urlPattern, baseUrl));
|
|
5808
|
-
};
|
|
5809
|
-
|
|
5810
|
-
const asFlatAssociations = associations => {
|
|
5811
|
-
if (!isPlainObject(associations)) {
|
|
5812
|
-
throw new TypeError(`associations must be a plain object, got ${associations}`);
|
|
5813
|
-
}
|
|
5814
|
-
|
|
5815
|
-
const flatAssociations = {};
|
|
5816
|
-
Object.keys(associations).forEach(key => {
|
|
5817
|
-
const valueMap = associations[key];
|
|
5818
|
-
|
|
5819
|
-
if (!isPlainObject(valueMap)) {
|
|
5820
|
-
throw new TypeError(`all associations value must be objects, found "${key}": ${valueMap}`);
|
|
5821
|
-
}
|
|
5822
|
-
|
|
5823
|
-
Object.keys(valueMap).forEach(pattern => {
|
|
5824
|
-
const value = valueMap[pattern];
|
|
5825
|
-
const previousValue = flatAssociations[pattern];
|
|
5826
|
-
flatAssociations[pattern] = previousValue ? { ...previousValue,
|
|
5827
|
-
[key]: value
|
|
5828
|
-
} : {
|
|
5829
|
-
[key]: value
|
|
5830
|
-
};
|
|
5831
|
-
});
|
|
5832
|
-
});
|
|
5833
|
-
return flatAssociations;
|
|
5834
|
-
};
|
|
5835
|
-
|
|
5836
|
-
/*
|
|
5837
|
-
* Link to things doing pattern matching:
|
|
5838
|
-
* https://git-scm.com/docs/gitignore
|
|
5839
|
-
* https://github.com/kaelzhang/node-ignore
|
|
5840
|
-
*/
|
|
5841
|
-
/** @module jsenv_url_meta **/
|
|
5842
|
-
|
|
5843
|
-
/**
|
|
5844
|
-
* An object representing the result of applying a pattern to an url
|
|
5845
|
-
* @typedef {Object} MatchResult
|
|
5846
|
-
* @property {boolean} matched Indicates if url matched pattern
|
|
5847
|
-
* @property {number} patternIndex Index where pattern stopped matching url, otherwise pattern.length
|
|
5848
|
-
* @property {number} urlIndex Index where url stopped matching pattern, otherwise url.length
|
|
5849
|
-
* @property {Array} matchGroups Array of strings captured during pattern matching
|
|
5850
|
-
*/
|
|
5851
|
-
|
|
5852
|
-
/**
|
|
5853
|
-
* Apply a pattern to an url
|
|
5854
|
-
* @param {Object} applyPatternMatchingParams
|
|
5855
|
-
* @param {string} applyPatternMatchingParams.pattern "*", "**" and trailing slash have special meaning
|
|
5856
|
-
* @param {string} applyPatternMatchingParams.url a string representing an url
|
|
5857
|
-
* @return {MatchResult}
|
|
5858
|
-
*/
|
|
5859
|
-
|
|
5860
|
-
const applyPatternMatching = ({
|
|
5861
|
-
url,
|
|
5862
|
-
pattern
|
|
5863
|
-
}) => {
|
|
5864
|
-
assertUrlLike(pattern, "pattern");
|
|
5865
|
-
assertUrlLike(url, "url");
|
|
5866
|
-
const {
|
|
5867
|
-
matched,
|
|
5868
|
-
patternIndex,
|
|
5869
|
-
index,
|
|
5870
|
-
groups
|
|
5871
|
-
} = applyMatching(pattern, url);
|
|
5872
|
-
const matchGroups = [];
|
|
5873
|
-
let groupIndex = 0;
|
|
5874
|
-
groups.forEach(group => {
|
|
5875
|
-
if (group.name) {
|
|
5876
|
-
matchGroups[group.name] = group.string;
|
|
5877
|
-
} else {
|
|
5878
|
-
matchGroups[groupIndex] = group.string;
|
|
5879
|
-
groupIndex++;
|
|
5880
|
-
}
|
|
5881
|
-
});
|
|
5882
|
-
return {
|
|
5883
|
-
matched,
|
|
5884
|
-
patternIndex,
|
|
5885
|
-
urlIndex: index,
|
|
5886
|
-
matchGroups
|
|
5887
|
-
};
|
|
5888
|
-
};
|
|
5889
|
-
|
|
5890
|
-
const applyMatching = (pattern, string) => {
|
|
5891
|
-
const groups = [];
|
|
5892
|
-
let patternIndex = 0;
|
|
5893
|
-
let index = 0;
|
|
5894
|
-
let remainingPattern = pattern;
|
|
5895
|
-
let remainingString = string;
|
|
5896
|
-
let restoreIndexes = true;
|
|
5897
|
-
|
|
5898
|
-
const consumePattern = count => {
|
|
5899
|
-
const subpattern = remainingPattern.slice(0, count);
|
|
5900
|
-
remainingPattern = remainingPattern.slice(count);
|
|
5901
|
-
patternIndex += count;
|
|
5902
|
-
return subpattern;
|
|
5903
|
-
};
|
|
5904
|
-
|
|
5905
|
-
const consumeString = count => {
|
|
5906
|
-
const substring = remainingString.slice(0, count);
|
|
5907
|
-
remainingString = remainingString.slice(count);
|
|
5908
|
-
index += count;
|
|
5909
|
-
return substring;
|
|
5910
|
-
};
|
|
5911
|
-
|
|
5912
|
-
const consumeRemainingString = () => {
|
|
5913
|
-
return consumeString(remainingString.length);
|
|
5914
|
-
};
|
|
5915
|
-
|
|
5916
|
-
let matched;
|
|
5917
|
-
|
|
5918
|
-
const iterate = () => {
|
|
5919
|
-
const patternIndexBefore = patternIndex;
|
|
5920
|
-
const indexBefore = index;
|
|
5921
|
-
matched = matchOne();
|
|
5922
|
-
|
|
5923
|
-
if (matched === undefined) {
|
|
5924
|
-
consumePattern(1);
|
|
5925
|
-
consumeString(1);
|
|
5926
|
-
iterate();
|
|
5927
|
-
return;
|
|
5928
|
-
}
|
|
5929
|
-
|
|
5930
|
-
if (matched === false && restoreIndexes) {
|
|
5931
|
-
patternIndex = patternIndexBefore;
|
|
5932
|
-
index = indexBefore;
|
|
5933
|
-
}
|
|
5934
|
-
};
|
|
5935
|
-
|
|
5936
|
-
const matchOne = () => {
|
|
5937
|
-
// pattern consumed and string consumed
|
|
5938
|
-
if (remainingPattern === "" && remainingString === "") {
|
|
5939
|
-
return true; // string fully matched pattern
|
|
5940
|
-
} // pattern consumed, string not consumed
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
if (remainingPattern === "" && remainingString !== "") {
|
|
5944
|
-
return false; // fails because string longer than expected
|
|
5945
|
-
} // -- from this point pattern is not consumed --
|
|
5946
|
-
// string consumed, pattern not consumed
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
if (remainingString === "") {
|
|
5950
|
-
if (remainingPattern === "**") {
|
|
5951
|
-
// trailing "**" is optional
|
|
5952
|
-
consumePattern(2);
|
|
5953
|
-
return true;
|
|
5954
|
-
}
|
|
5955
|
-
|
|
5956
|
-
if (remainingPattern === "*") {
|
|
5957
|
-
groups.push({
|
|
5958
|
-
string: ""
|
|
5959
|
-
});
|
|
5960
|
-
}
|
|
5961
|
-
|
|
5962
|
-
return false; // fail because string shorter than expected
|
|
5963
|
-
} // -- from this point pattern and string are not consumed --
|
|
5964
|
-
// fast path trailing slash
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
if (remainingPattern === "/") {
|
|
5968
|
-
if (remainingString[0] === "/") {
|
|
5969
|
-
// trailing slash match remaining
|
|
5970
|
-
consumePattern(1);
|
|
5971
|
-
groups.push({
|
|
5972
|
-
string: consumeRemainingString()
|
|
5973
|
-
});
|
|
5974
|
-
return true;
|
|
5975
|
-
}
|
|
5976
|
-
|
|
5977
|
-
return false;
|
|
5978
|
-
} // fast path trailing '**'
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
if (remainingPattern === "**") {
|
|
5982
|
-
consumePattern(2);
|
|
5983
|
-
consumeRemainingString();
|
|
5984
|
-
return true;
|
|
5985
|
-
} // pattern leading **
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
if (remainingPattern.slice(0, 2) === "**") {
|
|
5989
|
-
consumePattern(2); // consumes "**"
|
|
5990
|
-
|
|
5991
|
-
if (remainingPattern[0] === "/") {
|
|
5992
|
-
consumePattern(1); // consumes "/"
|
|
5993
|
-
} // pattern ending with ** always match remaining string
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
if (remainingPattern === "") {
|
|
5997
|
-
consumeRemainingString();
|
|
5998
|
-
return true;
|
|
5999
|
-
}
|
|
6000
|
-
|
|
6001
|
-
const skipResult = skipUntilMatch({
|
|
6002
|
-
pattern: remainingPattern,
|
|
6003
|
-
string: remainingString,
|
|
6004
|
-
canSkipSlash: true
|
|
6005
|
-
});
|
|
6006
|
-
groups.push(...skipResult.groups);
|
|
6007
|
-
consumePattern(skipResult.patternIndex);
|
|
6008
|
-
consumeRemainingString();
|
|
6009
|
-
restoreIndexes = false;
|
|
6010
|
-
return skipResult.matched;
|
|
6011
|
-
}
|
|
6012
|
-
|
|
6013
|
-
if (remainingPattern[0] === "*") {
|
|
6014
|
-
consumePattern(1); // consumes "*"
|
|
6015
|
-
|
|
6016
|
-
if (remainingPattern === "") {
|
|
6017
|
-
// matches everything except '/'
|
|
6018
|
-
const slashIndex = remainingString.indexOf("/");
|
|
6019
|
-
|
|
6020
|
-
if (slashIndex === -1) {
|
|
6021
|
-
groups.push({
|
|
6022
|
-
string: consumeRemainingString()
|
|
6023
|
-
});
|
|
6024
|
-
return true;
|
|
6025
|
-
}
|
|
6026
|
-
|
|
6027
|
-
groups.push({
|
|
6028
|
-
string: consumeString(slashIndex)
|
|
6029
|
-
});
|
|
6030
|
-
return false;
|
|
6031
|
-
} // the next char must not the one expected by remainingPattern[0]
|
|
6032
|
-
// because * is greedy and expect to skip at least one char
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
if (remainingPattern[0] === remainingString[0]) {
|
|
6036
|
-
groups.push({
|
|
6037
|
-
string: ""
|
|
6038
|
-
});
|
|
6039
|
-
patternIndex = patternIndex - 1;
|
|
6040
|
-
return false;
|
|
6041
|
-
}
|
|
6042
|
-
|
|
6043
|
-
const skipResult = skipUntilMatch({
|
|
6044
|
-
pattern: remainingPattern,
|
|
6045
|
-
string: remainingString,
|
|
6046
|
-
canSkipSlash: false
|
|
6047
|
-
});
|
|
6048
|
-
groups.push(skipResult.group, ...skipResult.groups);
|
|
6049
|
-
consumePattern(skipResult.patternIndex);
|
|
6050
|
-
consumeString(skipResult.index);
|
|
6051
|
-
restoreIndexes = false;
|
|
6052
|
-
return skipResult.matched;
|
|
6053
|
-
}
|
|
6054
|
-
|
|
6055
|
-
if (remainingPattern[0] !== remainingString[0]) {
|
|
6056
|
-
return false;
|
|
6057
|
-
}
|
|
6058
|
-
|
|
6059
|
-
return undefined;
|
|
6060
|
-
};
|
|
6061
|
-
|
|
6062
|
-
iterate();
|
|
6063
|
-
return {
|
|
6064
|
-
matched,
|
|
6065
|
-
patternIndex,
|
|
6066
|
-
index,
|
|
6067
|
-
groups
|
|
6068
|
-
};
|
|
6069
|
-
};
|
|
6070
|
-
|
|
6071
|
-
const skipUntilMatch = ({
|
|
6072
|
-
pattern,
|
|
6073
|
-
string,
|
|
6074
|
-
canSkipSlash
|
|
6075
|
-
}) => {
|
|
6076
|
-
let index = 0;
|
|
6077
|
-
let remainingString = string;
|
|
6078
|
-
let longestMatchRange = null;
|
|
6079
|
-
|
|
6080
|
-
const tryToMatch = () => {
|
|
6081
|
-
const matchAttempt = applyMatching(pattern, remainingString);
|
|
6082
|
-
|
|
6083
|
-
if (matchAttempt.matched) {
|
|
6084
|
-
return {
|
|
6085
|
-
matched: true,
|
|
6086
|
-
patternIndex: matchAttempt.patternIndex,
|
|
6087
|
-
index: index + matchAttempt.index,
|
|
6088
|
-
groups: matchAttempt.groups,
|
|
6089
|
-
group: {
|
|
6090
|
-
string: remainingString === "" ? string : string.slice(0, -remainingString.length)
|
|
6091
|
-
}
|
|
6092
|
-
};
|
|
6093
|
-
}
|
|
6094
|
-
|
|
6095
|
-
const matchAttemptIndex = matchAttempt.index;
|
|
6096
|
-
const matchRange = {
|
|
6097
|
-
patternIndex: matchAttempt.patternIndex,
|
|
6098
|
-
index,
|
|
6099
|
-
length: matchAttemptIndex,
|
|
6100
|
-
groups: matchAttempt.groups
|
|
6101
|
-
};
|
|
6102
|
-
|
|
6103
|
-
if (!longestMatchRange || longestMatchRange.length < matchRange.length) {
|
|
6104
|
-
longestMatchRange = matchRange;
|
|
6105
|
-
}
|
|
6106
|
-
|
|
6107
|
-
const nextIndex = matchAttemptIndex + 1;
|
|
6108
|
-
const canSkip = nextIndex < remainingString.length && (canSkipSlash || remainingString[0] !== "/");
|
|
6109
|
-
|
|
6110
|
-
if (canSkip) {
|
|
6111
|
-
// search against the next unattempted string
|
|
6112
|
-
index += nextIndex;
|
|
6113
|
-
remainingString = remainingString.slice(nextIndex);
|
|
6114
|
-
return tryToMatch();
|
|
6115
|
-
}
|
|
6116
|
-
|
|
6117
|
-
return {
|
|
6118
|
-
matched: false,
|
|
6119
|
-
patternIndex: longestMatchRange.patternIndex,
|
|
6120
|
-
index: longestMatchRange.index + longestMatchRange.length,
|
|
6121
|
-
groups: longestMatchRange.groups,
|
|
6122
|
-
group: {
|
|
6123
|
-
string: string.slice(0, longestMatchRange.index)
|
|
6124
|
-
}
|
|
6125
|
-
};
|
|
6126
|
-
};
|
|
6127
|
-
|
|
6128
|
-
return tryToMatch();
|
|
6129
|
-
};
|
|
6130
|
-
|
|
6131
|
-
const applyAssociations = ({
|
|
6132
|
-
url,
|
|
6133
|
-
associations
|
|
6134
|
-
}) => {
|
|
6135
|
-
assertUrlLike(url);
|
|
6136
|
-
const flatAssociations = asFlatAssociations(associations);
|
|
6137
|
-
return Object.keys(flatAssociations).reduce((previousValue, pattern) => {
|
|
6138
|
-
const {
|
|
6139
|
-
matched
|
|
6140
|
-
} = applyPatternMatching({
|
|
6141
|
-
pattern,
|
|
6142
|
-
url
|
|
6143
|
-
});
|
|
6144
|
-
|
|
6145
|
-
if (matched) {
|
|
6146
|
-
const value = flatAssociations[pattern];
|
|
6147
|
-
|
|
6148
|
-
if (isPlainObject(previousValue) && isPlainObject(value)) {
|
|
6149
|
-
return { ...previousValue,
|
|
6150
|
-
...value
|
|
6151
|
-
};
|
|
6152
|
-
}
|
|
6153
|
-
|
|
6154
|
-
return value;
|
|
6155
|
-
}
|
|
6156
|
-
|
|
6157
|
-
return previousValue;
|
|
6158
|
-
}, {});
|
|
6159
|
-
};
|
|
6160
|
-
|
|
6161
|
-
const applyAliases = ({
|
|
6162
|
-
url,
|
|
6163
|
-
aliases
|
|
6164
|
-
}) => {
|
|
6165
|
-
let aliasFullMatchResult;
|
|
6166
|
-
const aliasMatchingKey = Object.keys(aliases).find(key => {
|
|
6167
|
-
const aliasMatchResult = applyPatternMatching({
|
|
6168
|
-
pattern: key,
|
|
6169
|
-
url
|
|
6170
|
-
});
|
|
6171
|
-
|
|
6172
|
-
if (aliasMatchResult.matched) {
|
|
6173
|
-
aliasFullMatchResult = aliasMatchResult;
|
|
6174
|
-
return true;
|
|
6175
|
-
}
|
|
6176
|
-
|
|
6177
|
-
return false;
|
|
6178
|
-
});
|
|
6179
|
-
|
|
6180
|
-
if (!aliasMatchingKey) {
|
|
6181
|
-
return url;
|
|
6182
|
-
}
|
|
6183
|
-
|
|
6184
|
-
const {
|
|
6185
|
-
matchGroups
|
|
6186
|
-
} = aliasFullMatchResult;
|
|
6187
|
-
const alias = aliases[aliasMatchingKey];
|
|
6188
|
-
const parts = alias.split("*");
|
|
6189
|
-
const newUrl = parts.reduce((previous, value, index) => {
|
|
6190
|
-
return `${previous}${value}${index === parts.length - 1 ? "" : matchGroups[index]}`;
|
|
6191
|
-
}, "");
|
|
6192
|
-
return newUrl;
|
|
6193
|
-
};
|
|
6194
|
-
|
|
6195
|
-
const urlChildMayMatch = ({
|
|
6196
|
-
url,
|
|
6197
|
-
associations,
|
|
6198
|
-
predicate
|
|
6199
|
-
}) => {
|
|
6200
|
-
assertUrlLike(url, "url"); // the function was meants to be used on url ending with '/'
|
|
6201
|
-
|
|
6202
|
-
if (!url.endsWith("/")) {
|
|
6203
|
-
throw new Error(`url should end with /, got ${url}`);
|
|
6204
|
-
}
|
|
6205
|
-
|
|
6206
|
-
if (typeof predicate !== "function") {
|
|
6207
|
-
throw new TypeError(`predicate must be a function, got ${predicate}`);
|
|
6208
|
-
}
|
|
6209
|
-
|
|
6210
|
-
const flatAssociations = asFlatAssociations(associations); // for full match we must create an object to allow pattern to override previous ones
|
|
6211
|
-
|
|
6212
|
-
let fullMatchMeta = {};
|
|
6213
|
-
let someFullMatch = false; // for partial match, any meta satisfying predicate will be valid because
|
|
6214
|
-
// we don't know for sure if pattern will still match for a file inside pathname
|
|
6215
|
-
|
|
6216
|
-
const partialMatchMetaArray = [];
|
|
6217
|
-
Object.keys(flatAssociations).forEach(pattern => {
|
|
6218
|
-
const value = flatAssociations[pattern];
|
|
6219
|
-
const matchResult = applyPatternMatching({
|
|
6220
|
-
pattern,
|
|
6221
|
-
url
|
|
6222
|
-
});
|
|
6223
|
-
|
|
6224
|
-
if (matchResult.matched) {
|
|
6225
|
-
someFullMatch = true;
|
|
6226
|
-
|
|
6227
|
-
if (isPlainObject(fullMatchMeta) && isPlainObject(value)) {
|
|
6228
|
-
fullMatchMeta = { ...fullMatchMeta,
|
|
6229
|
-
...value
|
|
6230
|
-
};
|
|
6231
|
-
} else {
|
|
6232
|
-
fullMatchMeta = value;
|
|
6233
|
-
}
|
|
6234
|
-
} else if (someFullMatch === false && matchResult.urlIndex >= url.length) {
|
|
6235
|
-
partialMatchMetaArray.push(value);
|
|
6236
|
-
}
|
|
6237
|
-
});
|
|
6238
|
-
|
|
6239
|
-
if (someFullMatch) {
|
|
6240
|
-
return Boolean(predicate(fullMatchMeta));
|
|
6241
|
-
}
|
|
6242
|
-
|
|
6243
|
-
return partialMatchMetaArray.some(partialMatchMeta => predicate(partialMatchMeta));
|
|
6244
|
-
};
|
|
6245
|
-
|
|
6246
|
-
const URL_META = {
|
|
6247
|
-
resolveAssociations,
|
|
6248
|
-
applyAssociations,
|
|
6249
|
-
urlChildMayMatch,
|
|
6250
|
-
applyPatternMatching,
|
|
6251
|
-
applyAliases
|
|
6252
|
-
};
|
|
6253
|
-
|
|
6254
5745
|
const pluginRequestWaitingCheck = ({
|
|
6255
5746
|
requestWaitingMs = 20000,
|
|
6256
5747
|
requestWaitingCallback = ({
|
|
@@ -10071,7 +9562,10 @@ const jsenvPluginUrlResolution = () => {
|
|
|
10071
9562
|
name: "jsenv:url_resolution",
|
|
10072
9563
|
appliesDuring: "*",
|
|
10073
9564
|
resolveUrl: {
|
|
9565
|
+
"http_request": urlResolver,
|
|
9566
|
+
// during dev
|
|
10074
9567
|
"entry_point": urlResolver,
|
|
9568
|
+
// during build
|
|
10075
9569
|
"link_href": urlResolver,
|
|
10076
9570
|
"script_src": urlResolver,
|
|
10077
9571
|
"a_href": urlResolver,
|
|
@@ -18026,16 +17520,16 @@ const jsenvPluginAsJsClassicConversion = ({
|
|
|
18026
17520
|
return null;
|
|
18027
17521
|
}
|
|
18028
17522
|
|
|
18029
|
-
const
|
|
18030
|
-
//
|
|
18031
|
-
//
|
|
18032
|
-
//
|
|
18033
|
-
|
|
18034
|
-
|
|
17523
|
+
const jsClassicFormat = // in general html file are entry points, but js can be entry point when:
|
|
17524
|
+
// - passed in entryPoints to build
|
|
17525
|
+
// - is used by web worker
|
|
17526
|
+
// - the reference contains ?entry_point
|
|
17527
|
+
// When js is entry point there can be no HTML to inject systemjs
|
|
17528
|
+
// and systemjs must be injected into the js file
|
|
17529
|
+
originalUrlInfo.isEntryPoint && // if it's an entry point without dependency (it does not use import)
|
|
18035
17530
|
// then we can use UMD, otherwise we have to use systemjs
|
|
18036
17531
|
// because it is imported by systemjs
|
|
18037
|
-
|
|
18038
|
-
const jsClassicFormat = isJsEntryPoint && !originalUrlInfo.data.usesImport ? "umd" : "system";
|
|
17532
|
+
!originalUrlInfo.data.usesImport ? "umd" : "system";
|
|
18039
17533
|
const {
|
|
18040
17534
|
content,
|
|
18041
17535
|
sourcemap
|
|
@@ -18043,7 +17537,6 @@ const jsenvPluginAsJsClassicConversion = ({
|
|
|
18043
17537
|
systemJsInjection,
|
|
18044
17538
|
systemJsClientFileUrl,
|
|
18045
17539
|
urlInfo: originalUrlInfo,
|
|
18046
|
-
isJsEntryPoint,
|
|
18047
17540
|
jsClassicFormat
|
|
18048
17541
|
});
|
|
18049
17542
|
urlInfo.data.jsClassicFormat = jsClassicFormat;
|
|
@@ -18087,7 +17580,6 @@ const convertJsModuleToJsClassic = async ({
|
|
|
18087
17580
|
systemJsInjection,
|
|
18088
17581
|
systemJsClientFileUrl,
|
|
18089
17582
|
urlInfo,
|
|
18090
|
-
isJsEntryPoint,
|
|
18091
17583
|
jsClassicFormat
|
|
18092
17584
|
}) => {
|
|
18093
17585
|
const {
|
|
@@ -18106,7 +17598,7 @@ const convertJsModuleToJsClassic = async ({
|
|
|
18106
17598
|
let sourcemap = urlInfo.sourcemap;
|
|
18107
17599
|
sourcemap = await composeTwoSourcemaps(sourcemap, map);
|
|
18108
17600
|
|
|
18109
|
-
if (systemJsInjection && jsClassicFormat === "system" &&
|
|
17601
|
+
if (systemJsInjection && jsClassicFormat === "system" && urlInfo.isEntryPoint) {
|
|
18110
17602
|
const magicSource = createMagicSource(code);
|
|
18111
17603
|
const systemjsCode = readFileSync(systemJsClientFileUrl, {
|
|
18112
17604
|
as: "string"
|
|
@@ -19800,7 +19292,7 @@ const rollupPluginJsenv = ({
|
|
|
19800
19292
|
jsModuleUrlInfos.forEach(jsModuleUrlInfo => {
|
|
19801
19293
|
const id = jsModuleUrlInfo.url;
|
|
19802
19294
|
|
|
19803
|
-
if (jsModuleUrlInfo.
|
|
19295
|
+
if (jsModuleUrlInfo.isEntryPoint) {
|
|
19804
19296
|
emitChunk({
|
|
19805
19297
|
id
|
|
19806
19298
|
});
|
|
@@ -20083,7 +19575,7 @@ const willBeInsideJsDirectory = ({
|
|
|
20083
19575
|
return true;
|
|
20084
19576
|
}
|
|
20085
19577
|
|
|
20086
|
-
if (!jsModuleUrlInfo.
|
|
19578
|
+
if (!jsModuleUrlInfo.isEntryPoint) {
|
|
20087
19579
|
// not an entry point, jsenv will put it inside js/ directory
|
|
20088
19580
|
return true;
|
|
20089
19581
|
}
|
|
@@ -21443,6 +20935,7 @@ const createUrlInfo = url => {
|
|
|
21443
20935
|
originalUrl: undefined,
|
|
21444
20936
|
generatedUrl: null,
|
|
21445
20937
|
filename: "",
|
|
20938
|
+
isEntryPoint: false,
|
|
21446
20939
|
isInline: false,
|
|
21447
20940
|
inlineUrlSite: null,
|
|
21448
20941
|
shouldHandle: undefined,
|
|
@@ -22374,6 +21867,7 @@ const createKitchen = ({
|
|
|
22374
21867
|
baseUrl,
|
|
22375
21868
|
isOriginalPosition,
|
|
22376
21869
|
shouldHandle,
|
|
21870
|
+
isEntryPoint = false,
|
|
22377
21871
|
isInline = false,
|
|
22378
21872
|
injected = false,
|
|
22379
21873
|
isRessourceHint = false,
|
|
@@ -22411,6 +21905,7 @@ const createKitchen = ({
|
|
|
22411
21905
|
baseUrl,
|
|
22412
21906
|
isOriginalPosition,
|
|
22413
21907
|
shouldHandle,
|
|
21908
|
+
isEntryPoint,
|
|
22414
21909
|
isInline,
|
|
22415
21910
|
injected,
|
|
22416
21911
|
isRessourceHint,
|
|
@@ -22427,7 +21922,7 @@ const createKitchen = ({
|
|
|
22427
21922
|
const mutateReference = (reference, newReference) => {
|
|
22428
21923
|
reference.next = newReference;
|
|
22429
21924
|
newReference.prev = reference;
|
|
22430
|
-
newReference.original = reference.original || reference;
|
|
21925
|
+
newReference.original = reference.original || reference; // newReference.isEntryPoint = reference.isEntryPoint
|
|
22431
21926
|
};
|
|
22432
21927
|
|
|
22433
21928
|
const resolveReference = reference => {
|
|
@@ -22452,11 +21947,16 @@ const createKitchen = ({
|
|
|
22452
21947
|
reference.url = normalizedReturnValue;
|
|
22453
21948
|
mutateReference(previousReference, reference);
|
|
22454
21949
|
});
|
|
22455
|
-
const urlInfo = urlGraph.reuseOrCreateUrlInfo(reference.url);
|
|
22456
|
-
applyReferenceEffectsOnUrlInfo(reference, urlInfo, kitchenContext);
|
|
22457
21950
|
const referenceUrlObject = new URL(reference.url);
|
|
22458
21951
|
reference.searchParams = referenceUrlObject.searchParams;
|
|
22459
|
-
reference.generatedUrl = reference.url;
|
|
21952
|
+
reference.generatedUrl = reference.url;
|
|
21953
|
+
|
|
21954
|
+
if (reference.searchParams.has("entry_point")) {
|
|
21955
|
+
reference.isEntryPoint = true;
|
|
21956
|
+
}
|
|
21957
|
+
|
|
21958
|
+
const urlInfo = urlGraph.reuseOrCreateUrlInfo(reference.url);
|
|
21959
|
+
applyReferenceEffectsOnUrlInfo(reference, urlInfo, kitchenContext); // This hook must touch reference.generatedUrl, NOT reference.url
|
|
22460
21960
|
// And this is because this hook inject query params used to:
|
|
22461
21961
|
// - bypass browser cache (?v)
|
|
22462
21962
|
// - convey information (?hmr)
|
|
@@ -22557,7 +22057,8 @@ const createKitchen = ({
|
|
|
22557
22057
|
filename,
|
|
22558
22058
|
status = 200,
|
|
22559
22059
|
headers = {},
|
|
22560
|
-
body
|
|
22060
|
+
body,
|
|
22061
|
+
isEntryPoint
|
|
22561
22062
|
} = fetchUrlContentReturnValue;
|
|
22562
22063
|
|
|
22563
22064
|
if (status !== 200) {
|
|
@@ -22593,6 +22094,10 @@ const createKitchen = ({
|
|
|
22593
22094
|
Object.assign(urlInfo.data, data);
|
|
22594
22095
|
}
|
|
22595
22096
|
|
|
22097
|
+
if (typeof isEntryPoint === "boolean") {
|
|
22098
|
+
urlInfo.isEntryPoint = isEntryPoint;
|
|
22099
|
+
}
|
|
22100
|
+
|
|
22596
22101
|
if (filename) {
|
|
22597
22102
|
urlInfo.filename = filename;
|
|
22598
22103
|
}
|
|
@@ -22895,6 +22400,7 @@ const createKitchen = ({
|
|
|
22895
22400
|
|
|
22896
22401
|
const prepareEntryPoint = params => {
|
|
22897
22402
|
const entryReference = createReference(params);
|
|
22403
|
+
entryReference.isEntryPoint = true;
|
|
22898
22404
|
const entryUrlInfo = resolveReference(entryReference);
|
|
22899
22405
|
return [entryReference, entryUrlInfo];
|
|
22900
22406
|
};
|
|
@@ -23002,6 +22508,11 @@ const applyReferenceEffectsOnUrlInfo = (reference, urlInfo, context) => {
|
|
|
23002
22508
|
}
|
|
23003
22509
|
|
|
23004
22510
|
urlInfo.originalUrl = urlInfo.originalUrl || reference.url;
|
|
22511
|
+
|
|
22512
|
+
if (reference.isEntryPoint || isWebWorkerEntryPointReference(reference)) {
|
|
22513
|
+
urlInfo.isEntryPoint = true;
|
|
22514
|
+
}
|
|
22515
|
+
|
|
23005
22516
|
Object.assign(urlInfo.data, reference.data);
|
|
23006
22517
|
Object.assign(urlInfo.timing, reference.timing);
|
|
23007
22518
|
|
|
@@ -23026,10 +22537,6 @@ const applyReferenceEffectsOnUrlInfo = (reference, urlInfo, context) => {
|
|
|
23026
22537
|
urlInfo.originalContent = context === "build" ? urlInfo.originalContent === undefined ? reference.content : urlInfo.originalContent : reference.content;
|
|
23027
22538
|
urlInfo.content = reference.content;
|
|
23028
22539
|
}
|
|
23029
|
-
|
|
23030
|
-
if (isWebWorkerEntryPointReference(reference)) {
|
|
23031
|
-
urlInfo.data.isWebWorkerEntryPoint = true;
|
|
23032
|
-
}
|
|
23033
22540
|
};
|
|
23034
22541
|
|
|
23035
22542
|
const adjustUrlSite = (urlInfo, {
|
|
@@ -23312,10 +22819,10 @@ const createFileService = ({
|
|
|
23312
22819
|
}
|
|
23313
22820
|
|
|
23314
22821
|
if (!reference) {
|
|
23315
|
-
const entryPoint = kitchen.
|
|
22822
|
+
const entryPoint = kitchen.injectReference({
|
|
23316
22823
|
trace: parentUrl || rootDirectoryUrl,
|
|
23317
22824
|
parentUrl: parentUrl || rootDirectoryUrl,
|
|
23318
|
-
type: "
|
|
22825
|
+
type: "http_request",
|
|
23319
22826
|
specifier: request.ressource
|
|
23320
22827
|
});
|
|
23321
22828
|
reference = entryPoint[0];
|
|
@@ -24068,23 +23575,31 @@ const babelPluginInstrument = (api, {
|
|
|
24068
23575
|
};
|
|
24069
23576
|
};
|
|
24070
23577
|
|
|
24071
|
-
const
|
|
23578
|
+
const readNodeV8CoverageDirectory = async ({
|
|
24072
23579
|
logger,
|
|
24073
23580
|
signal,
|
|
24074
|
-
NODE_V8_COVERAGE,
|
|
24075
23581
|
onV8Coverage,
|
|
24076
23582
|
maxMsWaitingForNodeToWriteCoverageFile = 2000
|
|
24077
23583
|
}) => {
|
|
23584
|
+
const NODE_V8_COVERAGE = process.env.NODE_V8_COVERAGE;
|
|
24078
23585
|
const operation = Abort.startOperation();
|
|
24079
23586
|
operation.addAbortSignal(signal);
|
|
23587
|
+
let timeSpentTrying = 0;
|
|
24080
23588
|
|
|
24081
23589
|
const tryReadDirectory = async () => {
|
|
24082
|
-
const dirContent =
|
|
23590
|
+
const dirContent = readdirSync(NODE_V8_COVERAGE);
|
|
24083
23591
|
|
|
24084
23592
|
if (dirContent.length > 0) {
|
|
24085
23593
|
return dirContent;
|
|
24086
23594
|
}
|
|
24087
23595
|
|
|
23596
|
+
if (timeSpentTrying < maxMsWaitingForNodeToWriteCoverageFile) {
|
|
23597
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
23598
|
+
timeSpentTrying += 200;
|
|
23599
|
+
logger.debug("retry to read coverage directory");
|
|
23600
|
+
return tryReadDirectory();
|
|
23601
|
+
}
|
|
23602
|
+
|
|
24088
23603
|
logger.warn(`v8 coverage directory is empty at ${NODE_V8_COVERAGE}`);
|
|
24089
23604
|
return dirContent;
|
|
24090
23605
|
};
|
|
@@ -24096,17 +23611,16 @@ const visitNodeV8Directory = async ({
|
|
|
24096
23611
|
await dirContent.reduce(async (previous, dirEntry) => {
|
|
24097
23612
|
operation.throwIfAborted();
|
|
24098
23613
|
await previous;
|
|
24099
|
-
const dirEntryUrl =
|
|
23614
|
+
const dirEntryUrl = new URL(dirEntry, coverageDirectoryUrl);
|
|
24100
23615
|
|
|
24101
|
-
const tryReadJsonFile = async (
|
|
24102
|
-
const fileContent =
|
|
24103
|
-
as: "string"
|
|
24104
|
-
});
|
|
23616
|
+
const tryReadJsonFile = async () => {
|
|
23617
|
+
const fileContent = String(readFileSync$1(dirEntryUrl));
|
|
24105
23618
|
|
|
24106
23619
|
if (fileContent === "") {
|
|
24107
|
-
if (timeSpentTrying <
|
|
23620
|
+
if (timeSpentTrying < maxMsWaitingForNodeToWriteCoverageFile) {
|
|
24108
23621
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
24109
|
-
|
|
23622
|
+
timeSpentTrying += 200;
|
|
23623
|
+
return tryReadJsonFile();
|
|
24110
23624
|
}
|
|
24111
23625
|
|
|
24112
23626
|
console.warn(`Coverage JSON file is empty at ${dirEntryUrl}`);
|
|
@@ -24119,7 +23633,8 @@ const visitNodeV8Directory = async ({
|
|
|
24119
23633
|
} catch (e) {
|
|
24120
23634
|
if (timeSpentTrying < maxMsWaitingForNodeToWriteCoverageFile) {
|
|
24121
23635
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
24122
|
-
|
|
23636
|
+
timeSpentTrying += 200;
|
|
23637
|
+
return tryReadJsonFile();
|
|
24123
23638
|
}
|
|
24124
23639
|
|
|
24125
23640
|
console.warn(createDetailedMessage$1(`Error while reading coverage file`, {
|
|
@@ -24133,21 +23648,13 @@ const visitNodeV8Directory = async ({
|
|
|
24133
23648
|
const fileContent = await tryReadJsonFile();
|
|
24134
23649
|
|
|
24135
23650
|
if (fileContent) {
|
|
24136
|
-
onV8Coverage(fileContent);
|
|
23651
|
+
await onV8Coverage(fileContent);
|
|
24137
23652
|
}
|
|
24138
23653
|
}, Promise.resolve());
|
|
24139
23654
|
} finally {
|
|
24140
23655
|
await operation.end();
|
|
24141
23656
|
}
|
|
24142
23657
|
};
|
|
24143
|
-
const filterV8Coverage = (v8Coverage, {
|
|
24144
|
-
urlShouldBeCovered
|
|
24145
|
-
}) => {
|
|
24146
|
-
const v8CoverageFiltered = { ...v8Coverage,
|
|
24147
|
-
result: v8Coverage.result.filter(fileReport => urlShouldBeCovered(fileReport.url))
|
|
24148
|
-
};
|
|
24149
|
-
return v8CoverageFiltered;
|
|
24150
|
-
};
|
|
24151
23658
|
|
|
24152
23659
|
const composeTwoV8Coverages = (firstV8Coverage, secondV8Coverage) => {
|
|
24153
23660
|
if (secondV8Coverage.result.length === 0) {
|
|
@@ -24448,8 +23955,7 @@ const reportToCoverage = async (report, {
|
|
|
24448
23955
|
rootDirectoryUrl,
|
|
24449
23956
|
coverageConfig,
|
|
24450
23957
|
coverageIncludeMissing,
|
|
24451
|
-
|
|
24452
|
-
coverageForceIstanbul,
|
|
23958
|
+
coverageMethodForNodeJs,
|
|
24453
23959
|
coverageV8ConflictWarning
|
|
24454
23960
|
}) => {
|
|
24455
23961
|
// collect v8 and istanbul coverage from executions
|
|
@@ -24478,20 +23984,20 @@ const reportToCoverage = async (report, {
|
|
|
24478
23984
|
// in any scenario we are fine because
|
|
24479
23985
|
// coverDescription will generate empty coverage for files
|
|
24480
23986
|
// that were suppose to be coverage but were not.
|
|
24481
|
-
if (executionResult.status === "completed" && executionResult.
|
|
24482
|
-
logger.warn(`No
|
|
23987
|
+
if (executionResult.status === "completed" && executionResult.type === "node" && coverageMethodForNodeJs !== "NODE_V8_COVERAGE") {
|
|
23988
|
+
logger.warn(`No "coverageFileUrl" from execution named "${executionName}" of ${file}`);
|
|
24483
23989
|
}
|
|
24484
23990
|
}
|
|
24485
23991
|
});
|
|
24486
23992
|
|
|
24487
|
-
if (
|
|
24488
|
-
await
|
|
23993
|
+
if (coverageMethodForNodeJs === "NODE_V8_COVERAGE") {
|
|
23994
|
+
await readNodeV8CoverageDirectory({
|
|
24489
23995
|
logger,
|
|
24490
23996
|
signal,
|
|
24491
|
-
|
|
24492
|
-
|
|
24493
|
-
|
|
24494
|
-
|
|
23997
|
+
onV8Coverage: async nodeV8Coverage => {
|
|
23998
|
+
const nodeV8CoverageLight = await filterV8Coverage(nodeV8Coverage, {
|
|
23999
|
+
rootDirectoryUrl,
|
|
24000
|
+
coverageConfig
|
|
24495
24001
|
});
|
|
24496
24002
|
v8Coverage = v8Coverage ? composeTwoV8Coverages(v8Coverage, nodeV8CoverageLight) : nodeV8CoverageLight;
|
|
24497
24003
|
}
|
|
@@ -24570,9 +24076,7 @@ const getCoverageFromReport = async ({
|
|
|
24570
24076
|
return;
|
|
24571
24077
|
}
|
|
24572
24078
|
|
|
24573
|
-
const executionCoverage =
|
|
24574
|
-
as: "json"
|
|
24575
|
-
});
|
|
24079
|
+
const executionCoverage = JSON.parse(String(readFileSync$1(new URL(coverageFileUrl))));
|
|
24576
24080
|
|
|
24577
24081
|
if (isV8Coverage(executionCoverage)) {
|
|
24578
24082
|
v8Coverage = v8Coverage ? composeTwoV8Coverages(v8Coverage, executionCoverage) : executionCoverage;
|
|
@@ -24599,21 +24103,20 @@ const run = async ({
|
|
|
24599
24103
|
keepRunning = false,
|
|
24600
24104
|
mirrorConsole = false,
|
|
24601
24105
|
collectConsole = false,
|
|
24602
|
-
|
|
24106
|
+
coverageEnabled = false,
|
|
24603
24107
|
coverageTempDirectoryUrl,
|
|
24604
24108
|
collectPerformance = false,
|
|
24605
24109
|
runtime,
|
|
24606
24110
|
runtimeParams
|
|
24607
24111
|
}) => {
|
|
24112
|
+
let result = {};
|
|
24113
|
+
const callbacks = [];
|
|
24608
24114
|
const onConsoleRef = {
|
|
24609
24115
|
current: () => {}
|
|
24610
24116
|
};
|
|
24611
24117
|
const stopSignal = {
|
|
24612
24118
|
notify: () => {}
|
|
24613
24119
|
};
|
|
24614
|
-
|
|
24615
|
-
let resultTransformer = result => result;
|
|
24616
|
-
|
|
24617
24120
|
const runtimeLabel = `${runtime.name}/${runtime.version}`;
|
|
24618
24121
|
const runOperation = Abort.startOperation();
|
|
24619
24122
|
runOperation.addAbortSignal(signal);
|
|
@@ -24622,21 +24125,21 @@ const run = async ({
|
|
|
24622
24125
|
// when keepRunning is true
|
|
24623
24126
|
!keepRunning && typeof allocatedMs === "number" && allocatedMs !== Infinity) {
|
|
24624
24127
|
const timeoutAbortSource = runOperation.timeout(allocatedMs);
|
|
24625
|
-
|
|
24128
|
+
callbacks.push(() => {
|
|
24626
24129
|
if (result.status === "errored" && Abort.isAbortError(result.error) && timeoutAbortSource.signal.aborted) {
|
|
24627
|
-
|
|
24130
|
+
result = {
|
|
24131
|
+
status: "timedout"
|
|
24132
|
+
};
|
|
24628
24133
|
}
|
|
24629
|
-
|
|
24630
|
-
return result;
|
|
24631
24134
|
});
|
|
24632
24135
|
}
|
|
24633
24136
|
|
|
24634
|
-
|
|
24137
|
+
callbacks.push(() => {
|
|
24635
24138
|
if (result.status === "errored" && Abort.isAbortError(result.error)) {
|
|
24636
|
-
|
|
24139
|
+
result = {
|
|
24140
|
+
status: "aborted"
|
|
24141
|
+
};
|
|
24637
24142
|
}
|
|
24638
|
-
|
|
24639
|
-
return result;
|
|
24640
24143
|
});
|
|
24641
24144
|
const consoleCalls = [];
|
|
24642
24145
|
|
|
@@ -24661,44 +24164,14 @@ const run = async ({
|
|
|
24661
24164
|
};
|
|
24662
24165
|
|
|
24663
24166
|
if (collectConsole) {
|
|
24664
|
-
|
|
24167
|
+
callbacks.push(() => {
|
|
24665
24168
|
result.consoleCalls = consoleCalls;
|
|
24666
|
-
return result;
|
|
24667
|
-
});
|
|
24668
|
-
}
|
|
24669
|
-
|
|
24670
|
-
if (collectCoverage) {
|
|
24671
|
-
resultTransformer = composeTransformer$1(resultTransformer, async result => {
|
|
24672
|
-
// we do not keep coverage in memory, it can grow very big
|
|
24673
|
-
// instead we store it on the filesystem
|
|
24674
|
-
// and they can be read later at "coverageFileUrl"
|
|
24675
|
-
const {
|
|
24676
|
-
coverage
|
|
24677
|
-
} = result;
|
|
24678
|
-
|
|
24679
|
-
if (coverage) {
|
|
24680
|
-
const coverageFileUrl = resolveUrl$1(`./${runtime.name}/${cuid()}`, coverageTempDirectoryUrl);
|
|
24681
|
-
await writeFile(coverageFileUrl, JSON.stringify(coverage, null, " "));
|
|
24682
|
-
result.coverageFileUrl = coverageFileUrl;
|
|
24683
|
-
delete result.coverage;
|
|
24684
|
-
}
|
|
24685
|
-
|
|
24686
|
-
return result;
|
|
24687
|
-
});
|
|
24688
|
-
} else {
|
|
24689
|
-
resultTransformer = composeTransformer$1(resultTransformer, result => {
|
|
24690
|
-
// as collectCoverage is disabled
|
|
24691
|
-
// executionResult.coverage is undefined or {}
|
|
24692
|
-
// we delete it just to have a cleaner object
|
|
24693
|
-
delete result.coverage;
|
|
24694
|
-
return result;
|
|
24695
24169
|
});
|
|
24696
24170
|
}
|
|
24697
24171
|
|
|
24698
24172
|
const startMs = Date.now();
|
|
24699
|
-
|
|
24173
|
+
callbacks.push(() => {
|
|
24700
24174
|
result.duration = Date.now() - startMs;
|
|
24701
|
-
return result;
|
|
24702
24175
|
});
|
|
24703
24176
|
|
|
24704
24177
|
try {
|
|
@@ -24714,7 +24187,7 @@ const run = async ({
|
|
|
24714
24187
|
},
|
|
24715
24188
|
runned: async cb => {
|
|
24716
24189
|
try {
|
|
24717
|
-
const
|
|
24190
|
+
const runResult = await runtime.run({
|
|
24718
24191
|
signal: runOperation.signal,
|
|
24719
24192
|
logger,
|
|
24720
24193
|
...runtimeParams,
|
|
@@ -24723,7 +24196,7 @@ const run = async ({
|
|
|
24723
24196
|
stopSignal,
|
|
24724
24197
|
onConsole: log => onConsoleRef.current(log)
|
|
24725
24198
|
});
|
|
24726
|
-
cb(
|
|
24199
|
+
cb(runResult);
|
|
24727
24200
|
} catch (e) {
|
|
24728
24201
|
cb({
|
|
24729
24202
|
status: "errored",
|
|
@@ -24739,40 +24212,55 @@ const run = async ({
|
|
|
24739
24212
|
runOperation.throwIfAborted();
|
|
24740
24213
|
}
|
|
24741
24214
|
|
|
24742
|
-
|
|
24743
|
-
|
|
24215
|
+
const {
|
|
24216
|
+
status,
|
|
24217
|
+
namespace,
|
|
24218
|
+
error,
|
|
24219
|
+
performance,
|
|
24220
|
+
coverage
|
|
24221
|
+
} = winner.data;
|
|
24222
|
+
result.status = status;
|
|
24223
|
+
|
|
24224
|
+
if (status === "errored") {
|
|
24225
|
+
result.error = error;
|
|
24226
|
+
} else {
|
|
24227
|
+
result.namespace = namespace;
|
|
24228
|
+
}
|
|
24229
|
+
|
|
24230
|
+
if (collectPerformance) {
|
|
24231
|
+
result.performance = performance;
|
|
24232
|
+
}
|
|
24233
|
+
|
|
24234
|
+
if (coverageEnabled) {
|
|
24235
|
+
if (coverage) {
|
|
24236
|
+
// we do not keep coverage in memory, it can grow very big
|
|
24237
|
+
// instead we store it on the filesystem
|
|
24238
|
+
// and they can be read later at "coverageFileUrl"
|
|
24239
|
+
const coverageFileUrl = new URL(`./${runtime.name}/${cuid()}.json`, coverageTempDirectoryUrl);
|
|
24240
|
+
writeFileSync(coverageFileUrl, JSON.stringify(coverage, null, " "));
|
|
24241
|
+
result.coverageFileUrl = coverageFileUrl.href;
|
|
24242
|
+
} else {// will eventually log a warning in report_to_coverage.js
|
|
24243
|
+
}
|
|
24244
|
+
}
|
|
24245
|
+
|
|
24246
|
+
callbacks.forEach(callback => {
|
|
24247
|
+
callback();
|
|
24248
|
+
});
|
|
24744
24249
|
return result;
|
|
24745
24250
|
} catch (e) {
|
|
24746
|
-
|
|
24251
|
+
result = {
|
|
24747
24252
|
status: "errored",
|
|
24748
24253
|
error: e
|
|
24749
24254
|
};
|
|
24750
|
-
|
|
24255
|
+
callbacks.forEach(callback => {
|
|
24256
|
+
callback();
|
|
24257
|
+
});
|
|
24751
24258
|
return result;
|
|
24752
24259
|
} finally {
|
|
24753
24260
|
await runOperation.end();
|
|
24754
24261
|
}
|
|
24755
24262
|
};
|
|
24756
24263
|
|
|
24757
|
-
const composeTransformer$1 = (previousTransformer, transformer) => {
|
|
24758
|
-
return async value => {
|
|
24759
|
-
const transformedValue = await previousTransformer(value);
|
|
24760
|
-
return transformer(transformedValue);
|
|
24761
|
-
};
|
|
24762
|
-
};
|
|
24763
|
-
|
|
24764
|
-
const createAbortedResult = () => {
|
|
24765
|
-
return {
|
|
24766
|
-
status: "aborted"
|
|
24767
|
-
};
|
|
24768
|
-
};
|
|
24769
|
-
|
|
24770
|
-
const createTimedoutResult = () => {
|
|
24771
|
-
return {
|
|
24772
|
-
status: "timedout"
|
|
24773
|
-
};
|
|
24774
|
-
};
|
|
24775
|
-
|
|
24776
24264
|
const ensureGlobalGc = () => {
|
|
24777
24265
|
if (!global.gc) {
|
|
24778
24266
|
v8.setFlagsFromString("--expose_gc");
|
|
@@ -25176,10 +24664,11 @@ const executePlan = async (plan, {
|
|
|
25176
24664
|
failFast,
|
|
25177
24665
|
gcBetweenExecutions,
|
|
25178
24666
|
cooldownBetweenExecutions,
|
|
25179
|
-
|
|
24667
|
+
coverageEnabled,
|
|
25180
24668
|
coverageConfig,
|
|
25181
24669
|
coverageIncludeMissing,
|
|
25182
|
-
|
|
24670
|
+
coverageMethodForBrowsers,
|
|
24671
|
+
coverageMethodForNodeJs,
|
|
25183
24672
|
coverageV8ConflictWarning,
|
|
25184
24673
|
coverageTempDirectoryRelativeUrl,
|
|
25185
24674
|
scenario,
|
|
@@ -25197,10 +24686,14 @@ const executePlan = async (plan, {
|
|
|
25197
24686
|
beforeExecutionCallback = () => {},
|
|
25198
24687
|
afterExecutionCallback = () => {}
|
|
25199
24688
|
} = {}) => {
|
|
24689
|
+
const executePlanReturnValue = {};
|
|
24690
|
+
const report = {};
|
|
24691
|
+
const callbacks = [];
|
|
25200
24692
|
const stopAfterAllSignal = {
|
|
25201
24693
|
notify: () => {}
|
|
25202
24694
|
};
|
|
25203
24695
|
let someNeedsServer = false;
|
|
24696
|
+
let someNodeRuntime = false;
|
|
25204
24697
|
const runtimes = {};
|
|
25205
24698
|
Object.keys(plan).forEach(filePattern => {
|
|
25206
24699
|
const filePlan = plan[filePattern];
|
|
@@ -25216,6 +24709,10 @@ const executePlan = async (plan, {
|
|
|
25216
24709
|
if (runtime.needsServer) {
|
|
25217
24710
|
someNeedsServer = true;
|
|
25218
24711
|
}
|
|
24712
|
+
|
|
24713
|
+
if (runtime.type === "node") {
|
|
24714
|
+
someNodeRuntime = true;
|
|
24715
|
+
}
|
|
25219
24716
|
}
|
|
25220
24717
|
});
|
|
25221
24718
|
});
|
|
@@ -25243,10 +24740,67 @@ const executePlan = async (plan, {
|
|
|
25243
24740
|
}
|
|
25244
24741
|
|
|
25245
24742
|
try {
|
|
24743
|
+
const coverageTempDirectoryUrl = new URL(coverageTempDirectoryRelativeUrl, rootDirectoryUrl).href;
|
|
24744
|
+
|
|
24745
|
+
if (someNodeRuntime && coverageEnabled && coverageMethodForNodeJs === "NODE_V8_COVERAGE") {
|
|
24746
|
+
if (process.env.NODE_V8_COVERAGE) {
|
|
24747
|
+
// when runned multiple times, we don't want to keep previous files in this directory
|
|
24748
|
+
await ensureEmptyDirectory(process.env.NODE_V8_COVERAGE);
|
|
24749
|
+
} else {
|
|
24750
|
+
coverageMethodForNodeJs = "Profiler";
|
|
24751
|
+
logger.warn(createDetailedMessage$1(`process.env.NODE_V8_COVERAGE is required to generate coverage for Node.js subprocesses`, {
|
|
24752
|
+
"suggestion": `Preprend NODE_V8_COVERAGE=.coverage/node to the command executing this process`,
|
|
24753
|
+
"suggestion 2": `use coverageMethodForNodeJs: "Profiler". But it means coverage for child_process and worker_thread cannot be collected`
|
|
24754
|
+
}));
|
|
24755
|
+
}
|
|
24756
|
+
}
|
|
24757
|
+
|
|
24758
|
+
if (gcBetweenExecutions) {
|
|
24759
|
+
ensureGlobalGc();
|
|
24760
|
+
}
|
|
24761
|
+
|
|
24762
|
+
if (coverageEnabled) {
|
|
24763
|
+
// when runned multiple times, we don't want to keep previous files in this directory
|
|
24764
|
+
await ensureEmptyDirectory(coverageTempDirectoryUrl);
|
|
24765
|
+
callbacks.push(async () => {
|
|
24766
|
+
if (multipleExecutionsOperation.signal.aborted) {
|
|
24767
|
+
// don't try to do the coverage stuff
|
|
24768
|
+
return;
|
|
24769
|
+
}
|
|
24770
|
+
|
|
24771
|
+
try {
|
|
24772
|
+
if (coverageMethodForNodeJs === "NODE_V8_COVERAGE") {
|
|
24773
|
+
takeCoverage(); // conceptually we don't need coverage anymore so it would be
|
|
24774
|
+
// good to call v8.stopCoverage()
|
|
24775
|
+
// but it logs a strange message about "result is not an object"
|
|
24776
|
+
}
|
|
24777
|
+
|
|
24778
|
+
const planCoverage = await reportToCoverage(report, {
|
|
24779
|
+
signal: multipleExecutionsOperation.signal,
|
|
24780
|
+
logger,
|
|
24781
|
+
rootDirectoryUrl,
|
|
24782
|
+
coverageConfig,
|
|
24783
|
+
coverageIncludeMissing,
|
|
24784
|
+
coverageMethodForBrowsers,
|
|
24785
|
+
coverageV8ConflictWarning
|
|
24786
|
+
});
|
|
24787
|
+
executePlanReturnValue.planCoverage = planCoverage;
|
|
24788
|
+
} catch (e) {
|
|
24789
|
+
if (Abort.isAbortError(e)) {
|
|
24790
|
+
return;
|
|
24791
|
+
}
|
|
24792
|
+
|
|
24793
|
+
throw e;
|
|
24794
|
+
}
|
|
24795
|
+
});
|
|
24796
|
+
}
|
|
24797
|
+
|
|
25246
24798
|
let runtimeParams = {
|
|
25247
24799
|
rootDirectoryUrl,
|
|
25248
|
-
|
|
25249
|
-
|
|
24800
|
+
coverageEnabled,
|
|
24801
|
+
coverageConfig,
|
|
24802
|
+
coverageMethodForBrowsers,
|
|
24803
|
+
coverageMethodForNodeJs,
|
|
25250
24804
|
stopAfterAllSignal
|
|
25251
24805
|
};
|
|
25252
24806
|
|
|
@@ -25273,7 +24827,7 @@ const executePlan = async (plan, {
|
|
|
25273
24827
|
getCustomBabelPlugins: ({
|
|
25274
24828
|
clientRuntimeCompat
|
|
25275
24829
|
}) => {
|
|
25276
|
-
if (
|
|
24830
|
+
if (coverageEnabled && Object.keys(clientRuntimeCompat)[0] !== "chrome") {
|
|
25277
24831
|
return {
|
|
25278
24832
|
"transform-instrument": [babelPluginInstrument, {
|
|
25279
24833
|
rootDirectoryUrl,
|
|
@@ -25329,79 +24883,7 @@ const executePlan = async (plan, {
|
|
|
25329
24883
|
// so we enable spinner only when !process.exitCode (no error so far)
|
|
25330
24884
|
process.exitCode !== 1;
|
|
25331
24885
|
const startMs = Date.now();
|
|
25332
|
-
const report = {};
|
|
25333
24886
|
let rawOutput = "";
|
|
25334
|
-
|
|
25335
|
-
let transformReturnValue = value => value;
|
|
25336
|
-
|
|
25337
|
-
if (gcBetweenExecutions) {
|
|
25338
|
-
ensureGlobalGc();
|
|
25339
|
-
}
|
|
25340
|
-
|
|
25341
|
-
const coverageTempDirectoryUrl = new URL(coverageTempDirectoryRelativeUrl, rootDirectoryUrl).href;
|
|
25342
|
-
|
|
25343
|
-
if (coverage) {
|
|
25344
|
-
const associations = URL_META.resolveAssociations({
|
|
25345
|
-
cover: coverageConfig
|
|
25346
|
-
}, rootDirectoryUrl);
|
|
25347
|
-
|
|
25348
|
-
const urlShouldBeCovered = url => {
|
|
25349
|
-
const {
|
|
25350
|
-
cover
|
|
25351
|
-
} = URL_META.applyAssociations({
|
|
25352
|
-
url: new URL(url, rootDirectoryUrl).href,
|
|
25353
|
-
associations
|
|
25354
|
-
});
|
|
25355
|
-
return cover;
|
|
25356
|
-
};
|
|
25357
|
-
|
|
25358
|
-
runtimeParams.urlShouldBeCovered = urlShouldBeCovered; // in case runned multiple times, we don't want to keep writing lot of files in this directory
|
|
25359
|
-
|
|
25360
|
-
if (!process.env.NODE_V8_COVERAGE) {
|
|
25361
|
-
await ensureEmptyDirectory(coverageTempDirectoryUrl);
|
|
25362
|
-
}
|
|
25363
|
-
|
|
25364
|
-
if (runtimes.node) {
|
|
25365
|
-
// v8 coverage is written in a directoy and auto propagate to subprocesses
|
|
25366
|
-
// through process.env.NODE_V8_COVERAGE.
|
|
25367
|
-
if (!coverageForceIstanbul && !process.env.NODE_V8_COVERAGE) {
|
|
25368
|
-
const v8CoverageDirectory = new URL(`./node_v8/${cuid()}`, coverageTempDirectoryUrl).href;
|
|
25369
|
-
await writeDirectory(v8CoverageDirectory, {
|
|
25370
|
-
allowUseless: true
|
|
25371
|
-
});
|
|
25372
|
-
process.env.NODE_V8_COVERAGE = urlToFileSystemPath(v8CoverageDirectory);
|
|
25373
|
-
}
|
|
25374
|
-
}
|
|
25375
|
-
|
|
25376
|
-
transformReturnValue = async value => {
|
|
25377
|
-
if (multipleExecutionsOperation.signal.aborted) {
|
|
25378
|
-
// don't try to do the coverage stuff
|
|
25379
|
-
return value;
|
|
25380
|
-
}
|
|
25381
|
-
|
|
25382
|
-
try {
|
|
25383
|
-
value.coverage = await reportToCoverage(value.report, {
|
|
25384
|
-
signal: multipleExecutionsOperation.signal,
|
|
25385
|
-
logger,
|
|
25386
|
-
rootDirectoryUrl,
|
|
25387
|
-
coverageConfig,
|
|
25388
|
-
coverageIncludeMissing,
|
|
25389
|
-
coverageForceIstanbul,
|
|
25390
|
-
urlShouldBeCovered,
|
|
25391
|
-
coverageV8ConflictWarning
|
|
25392
|
-
});
|
|
25393
|
-
} catch (e) {
|
|
25394
|
-
if (Abort.isAbortError(e)) {
|
|
25395
|
-
return value;
|
|
25396
|
-
}
|
|
25397
|
-
|
|
25398
|
-
throw e;
|
|
25399
|
-
}
|
|
25400
|
-
|
|
25401
|
-
return value;
|
|
25402
|
-
};
|
|
25403
|
-
}
|
|
25404
|
-
|
|
25405
24887
|
logger.info("");
|
|
25406
24888
|
let executionLog = createLog({
|
|
25407
24889
|
newLine: ""
|
|
@@ -25426,6 +24908,7 @@ const executePlan = async (plan, {
|
|
|
25426
24908
|
fileRelativeUrl,
|
|
25427
24909
|
runtime
|
|
25428
24910
|
} = paramsFromStep;
|
|
24911
|
+
const runtimeType = runtime.type;
|
|
25429
24912
|
const runtimeName = runtime.name;
|
|
25430
24913
|
const runtimeVersion = runtime.version;
|
|
25431
24914
|
const executionParams = {
|
|
@@ -25441,6 +24924,7 @@ const executePlan = async (plan, {
|
|
|
25441
24924
|
};
|
|
25442
24925
|
const beforeExecutionInfo = {
|
|
25443
24926
|
fileRelativeUrl,
|
|
24927
|
+
runtimeType,
|
|
25444
24928
|
runtimeName,
|
|
25445
24929
|
runtimeVersion,
|
|
25446
24930
|
executionIndex,
|
|
@@ -25484,7 +24968,7 @@ const executePlan = async (plan, {
|
|
|
25484
24968
|
mirrorConsole: false,
|
|
25485
24969
|
// file are executed in parallel, log would be a mess to read
|
|
25486
24970
|
collectConsole: executionParams.collectConsole,
|
|
25487
|
-
|
|
24971
|
+
coverageEnabled,
|
|
25488
24972
|
coverageTempDirectoryUrl,
|
|
25489
24973
|
runtime: executionParams.runtime,
|
|
25490
24974
|
runtimeParams: { ...runtimeParams,
|
|
@@ -25602,16 +25086,14 @@ const executePlan = async (plan, {
|
|
|
25602
25086
|
logger.info(`-> ${urlToFileSystemPath(logFileUrl)}`);
|
|
25603
25087
|
}
|
|
25604
25088
|
|
|
25605
|
-
|
|
25606
|
-
|
|
25607
|
-
|
|
25608
|
-
|
|
25609
|
-
|
|
25610
|
-
|
|
25611
|
-
|
|
25612
|
-
|
|
25613
|
-
planCoverage: result.coverage
|
|
25614
|
-
};
|
|
25089
|
+
executePlanReturnValue.aborted = multipleExecutionsOperation.signal.aborted;
|
|
25090
|
+
executePlanReturnValue.planSummary = summary;
|
|
25091
|
+
executePlanReturnValue.planReport = report;
|
|
25092
|
+
await callbacks.reduce(async (previous, callback) => {
|
|
25093
|
+
await previous;
|
|
25094
|
+
await callback();
|
|
25095
|
+
}, Promise.resolve());
|
|
25096
|
+
return executePlanReturnValue;
|
|
25615
25097
|
} finally {
|
|
25616
25098
|
await multipleExecutionsOperation.end();
|
|
25617
25099
|
}
|
|
@@ -25732,7 +25214,7 @@ const executeInParallel = async ({
|
|
|
25732
25214
|
* @param {boolean} [testPlanParameters.failFast=false] Fails immediatly when a test execution fails
|
|
25733
25215
|
* @param {number} [testPlanParameters.cooldownBetweenExecutions=0] Millisecond to wait between each execution
|
|
25734
25216
|
* @param {boolean} [testPlanParameters.logMemoryHeapUsage=false] Add memory heap usage during logs
|
|
25735
|
-
* @param {boolean} [testPlanParameters.
|
|
25217
|
+
* @param {boolean} [testPlanParameters.coverageEnabled=false] Controls if coverage is collected during files executions
|
|
25736
25218
|
* @param {boolean} [testPlanParameters.coverageV8ConflictWarning=true] Warn when coverage from 2 executions cannot be merged
|
|
25737
25219
|
* @return {Object} An object containing the result of all file executions
|
|
25738
25220
|
*/
|
|
@@ -25763,22 +25245,25 @@ const executeTestPlan = async ({
|
|
|
25763
25245
|
keepRunning = false,
|
|
25764
25246
|
cooldownBetweenExecutions = 0,
|
|
25765
25247
|
gcBetweenExecutions = logMemoryHeapUsage,
|
|
25766
|
-
|
|
25767
|
-
coverageTempDirectoryRelativeUrl = "./.coverage/tmp/",
|
|
25248
|
+
coverageEnabled = process.argv.includes("--cover") || process.argv.includes("--coverage"),
|
|
25768
25249
|
coverageConfig = {
|
|
25769
25250
|
"./src/": true
|
|
25770
25251
|
},
|
|
25771
25252
|
coverageIncludeMissing = true,
|
|
25772
25253
|
coverageAndExecutionAllowed = false,
|
|
25773
|
-
|
|
25254
|
+
coverageMethodForNodeJs = "NODE_V8_COVERAGE",
|
|
25255
|
+
// "Profiler" also accepted
|
|
25256
|
+
coverageMethodForBrowsers = "playwright_api",
|
|
25257
|
+
// "istanbul" also accepted
|
|
25774
25258
|
coverageV8ConflictWarning = true,
|
|
25775
|
-
|
|
25776
|
-
coverageReportJsonFile = process.env.CI ? null : "./.coverage/coverage.json",
|
|
25777
|
-
coverageReportHtmlDirectory = process.env.CI ? "./.coverage/" : null,
|
|
25259
|
+
coverageTempDirectoryRelativeUrl = "./.coverage/tmp/",
|
|
25778
25260
|
// skip empty means empty files won't appear in the coverage reports (json and html)
|
|
25779
25261
|
coverageReportSkipEmpty = false,
|
|
25780
25262
|
// skip full means file with 100% coverage won't appear in coverage reports (json and html)
|
|
25781
25263
|
coverageReportSkipFull = false,
|
|
25264
|
+
coverageReportTextLog = true,
|
|
25265
|
+
coverageReportJsonFile = process.env.CI ? null : "./.coverage/coverage.json",
|
|
25266
|
+
coverageReportHtmlDirectory = process.env.CI ? "./.coverage/" : null,
|
|
25782
25267
|
sourcemaps = "inline",
|
|
25783
25268
|
plugins = [],
|
|
25784
25269
|
nodeEsmResolution,
|
|
@@ -25799,7 +25284,7 @@ const executeTestPlan = async ({
|
|
|
25799
25284
|
throw new Error(`testPlan must be an object, got ${testPlan}`);
|
|
25800
25285
|
}
|
|
25801
25286
|
|
|
25802
|
-
if (
|
|
25287
|
+
if (coverageEnabled) {
|
|
25803
25288
|
if (typeof coverageConfig !== "object") {
|
|
25804
25289
|
throw new TypeError(`coverageConfig must be an object, got ${coverageConfig}`);
|
|
25805
25290
|
}
|
|
@@ -25854,10 +25339,11 @@ const executeTestPlan = async ({
|
|
|
25854
25339
|
keepRunning,
|
|
25855
25340
|
cooldownBetweenExecutions,
|
|
25856
25341
|
gcBetweenExecutions,
|
|
25857
|
-
|
|
25342
|
+
coverageEnabled,
|
|
25858
25343
|
coverageConfig,
|
|
25859
25344
|
coverageIncludeMissing,
|
|
25860
|
-
|
|
25345
|
+
coverageMethodForBrowsers,
|
|
25346
|
+
coverageMethodForNodeJs,
|
|
25861
25347
|
coverageV8ConflictWarning,
|
|
25862
25348
|
coverageTempDirectoryRelativeUrl,
|
|
25863
25349
|
scenario: "test",
|
|
@@ -25884,7 +25370,7 @@ const executeTestPlan = async ({
|
|
|
25884
25370
|
// and in case coverage json file gets written in the same directory
|
|
25885
25371
|
// it must be done before
|
|
25886
25372
|
|
|
25887
|
-
if (
|
|
25373
|
+
if (coverageEnabled && coverageReportHtmlDirectory) {
|
|
25888
25374
|
const coverageHtmlDirectoryUrl = resolveDirectoryUrl(coverageReportHtmlDirectory, rootDirectoryUrl);
|
|
25889
25375
|
|
|
25890
25376
|
if (!urlIsInsideOf(coverageHtmlDirectoryUrl, rootDirectoryUrl)) {
|
|
@@ -25902,7 +25388,7 @@ const executeTestPlan = async ({
|
|
|
25902
25388
|
}));
|
|
25903
25389
|
}
|
|
25904
25390
|
|
|
25905
|
-
if (
|
|
25391
|
+
if (coverageEnabled && coverageReportJsonFile) {
|
|
25906
25392
|
const coverageJsonFileUrl = new URL(coverageReportJsonFile, rootDirectoryUrl).href;
|
|
25907
25393
|
promises.push(generateCoverageJsonFile({
|
|
25908
25394
|
coverage: result.planCoverage,
|
|
@@ -25911,7 +25397,7 @@ const executeTestPlan = async ({
|
|
|
25911
25397
|
}));
|
|
25912
25398
|
}
|
|
25913
25399
|
|
|
25914
|
-
if (
|
|
25400
|
+
if (coverageEnabled && coverageReportTextLog) {
|
|
25915
25401
|
promises.push(generateCoverageTextLog(result.planCoverage, {
|
|
25916
25402
|
coverageReportSkipEmpty,
|
|
25917
25403
|
coverageReportSkipFull
|
|
@@ -25986,6 +25472,7 @@ const createRuntimeFromPlaywright = ({
|
|
|
25986
25472
|
isolatedTab = false
|
|
25987
25473
|
}) => {
|
|
25988
25474
|
const runtime = {
|
|
25475
|
+
type: "browser",
|
|
25989
25476
|
name: browserName,
|
|
25990
25477
|
version: browserVersion,
|
|
25991
25478
|
needsServer: true
|
|
@@ -26000,9 +25487,9 @@ const createRuntimeFromPlaywright = ({
|
|
|
26000
25487
|
server,
|
|
26001
25488
|
// measurePerformance,
|
|
26002
25489
|
collectPerformance,
|
|
26003
|
-
|
|
26004
|
-
|
|
26005
|
-
|
|
25490
|
+
coverageEnabled = false,
|
|
25491
|
+
coverageConfig,
|
|
25492
|
+
coverageMethodForBrowsers,
|
|
26006
25493
|
stopAfterAllSignal,
|
|
26007
25494
|
stopSignal,
|
|
26008
25495
|
keepRunning,
|
|
@@ -26087,8 +25574,8 @@ const createRuntimeFromPlaywright = ({
|
|
|
26087
25574
|
|
|
26088
25575
|
let resultTransformer = result => result;
|
|
26089
25576
|
|
|
26090
|
-
if (
|
|
26091
|
-
if (coveragePlaywrightAPIAvailable &&
|
|
25577
|
+
if (coverageEnabled) {
|
|
25578
|
+
if (coveragePlaywrightAPIAvailable && coverageMethodForBrowsers === "playwright_api") {
|
|
26092
25579
|
await page.coverage.startJSCoverage({// reportAnonymousScripts: true,
|
|
26093
25580
|
});
|
|
26094
25581
|
resultTransformer = composeTransformer(resultTransformer, async result => {
|
|
@@ -26106,10 +25593,11 @@ const createRuntimeFromPlaywright = ({
|
|
|
26106
25593
|
url: fsUrl
|
|
26107
25594
|
};
|
|
26108
25595
|
});
|
|
26109
|
-
const coverage = filterV8Coverage({
|
|
25596
|
+
const coverage = await filterV8Coverage({
|
|
26110
25597
|
result: v8CoveragesWithFsUrls
|
|
26111
25598
|
}, {
|
|
26112
|
-
|
|
25599
|
+
rootDirectoryUrl,
|
|
25600
|
+
coverageConfig
|
|
26113
25601
|
});
|
|
26114
25602
|
return { ...result,
|
|
26115
25603
|
coverage
|
|
@@ -26846,13 +26334,24 @@ const killProcessTree = async (processId, {
|
|
|
26846
26334
|
await check();
|
|
26847
26335
|
};
|
|
26848
26336
|
|
|
26849
|
-
|
|
26850
|
-
const
|
|
26851
|
-
|
|
26337
|
+
// https://nodejs.org/api/process.html#process_signal_events
|
|
26338
|
+
const SIGINT_SIGNAL_NUMBER = 2;
|
|
26339
|
+
const SIGABORT_SIGNAL_NUMBER = 6;
|
|
26340
|
+
const SIGTERM_SIGNAL_NUMBER = 15;
|
|
26341
|
+
const EXIT_CODES = {
|
|
26342
|
+
SIGINT: 128 + SIGINT_SIGNAL_NUMBER,
|
|
26343
|
+
SIGABORT: 128 + SIGABORT_SIGNAL_NUMBER,
|
|
26344
|
+
SIGTERM: 128 + SIGTERM_SIGNAL_NUMBER
|
|
26345
|
+
};
|
|
26346
|
+
|
|
26347
|
+
const CONTROLLABLE_CHILD_PROCESS_URL = new URL("./controllable_child_process.mjs", import.meta.url).href;
|
|
26348
|
+
const nodeChildProcess = {
|
|
26349
|
+
type: "node",
|
|
26350
|
+
name: "node_child_process",
|
|
26852
26351
|
version: process.version.slice(1)
|
|
26853
26352
|
};
|
|
26854
26353
|
|
|
26855
|
-
|
|
26354
|
+
nodeChildProcess.run = async ({
|
|
26856
26355
|
signal = new AbortController().signal,
|
|
26857
26356
|
logger,
|
|
26858
26357
|
logProcessCommand = false,
|
|
@@ -26862,13 +26361,14 @@ nodeProcess.run = async ({
|
|
|
26862
26361
|
gracefulStopAllocatedMs = 4000,
|
|
26863
26362
|
stopSignal,
|
|
26864
26363
|
onConsole,
|
|
26865
|
-
|
|
26866
|
-
|
|
26364
|
+
coverageEnabled = false,
|
|
26365
|
+
coverageConfig,
|
|
26366
|
+
coverageMethodForNodeJs,
|
|
26867
26367
|
collectPerformance,
|
|
26368
|
+
env,
|
|
26868
26369
|
debugPort,
|
|
26869
26370
|
debugMode,
|
|
26870
26371
|
debugModeInheritBreak,
|
|
26871
|
-
env,
|
|
26872
26372
|
inheritProcessEnv = true,
|
|
26873
26373
|
commandLineOptions = [],
|
|
26874
26374
|
stdin = "pipe",
|
|
@@ -26880,13 +26380,10 @@ nodeProcess.run = async ({
|
|
|
26880
26380
|
}
|
|
26881
26381
|
|
|
26882
26382
|
env = { ...env,
|
|
26883
|
-
COVERAGE_ENABLED: collectCoverage,
|
|
26884
26383
|
JSENV: true
|
|
26885
26384
|
};
|
|
26886
26385
|
|
|
26887
|
-
if (
|
|
26888
|
-
// if we want to force istanbul, we will set process.env.NODE_V8_COVERAGE = ''
|
|
26889
|
-
// into the child_process
|
|
26386
|
+
if (coverageMethodForNodeJs !== "NODE_V8_COVERAGE") {
|
|
26890
26387
|
env.NODE_V8_COVERAGE = "";
|
|
26891
26388
|
}
|
|
26892
26389
|
|
|
@@ -26911,8 +26408,8 @@ nodeProcess.run = async ({
|
|
|
26911
26408
|
const envForChildProcess = { ...(inheritProcessEnv ? process.env : {}),
|
|
26912
26409
|
...env
|
|
26913
26410
|
};
|
|
26914
|
-
logger[logProcessCommand ? "info" : "debug"](`${process.argv[0]} ${execArgv.join(" ")} ${
|
|
26915
|
-
const childProcess = fork(
|
|
26411
|
+
logger[logProcessCommand ? "info" : "debug"](`${process.argv[0]} ${execArgv.join(" ")} ${fileURLToPath(CONTROLLABLE_CHILD_PROCESS_URL)}`);
|
|
26412
|
+
const childProcess = fork(fileURLToPath(CONTROLLABLE_CHILD_PROCESS_URL), {
|
|
26916
26413
|
execArgv,
|
|
26917
26414
|
// silent: true
|
|
26918
26415
|
stdio: ["pipe", "pipe", "pipe", "ipc"],
|
|
@@ -26936,9 +26433,9 @@ nodeProcess.run = async ({
|
|
|
26936
26433
|
}
|
|
26937
26434
|
|
|
26938
26435
|
const childProcessReadyPromise = new Promise(resolve => {
|
|
26939
|
-
|
|
26436
|
+
onceChildProcessMessage(childProcess, "ready", resolve);
|
|
26940
26437
|
});
|
|
26941
|
-
const removeOutputListener =
|
|
26438
|
+
const removeOutputListener = installChildProcessOutputListener(childProcess, ({
|
|
26942
26439
|
type,
|
|
26943
26440
|
text
|
|
26944
26441
|
}) => {
|
|
@@ -26999,10 +26496,10 @@ nodeProcess.run = async ({
|
|
|
26999
26496
|
// },
|
|
27000
26497
|
// https://nodejs.org/api/child_process.html#child_process_event_error
|
|
27001
26498
|
error: cb => {
|
|
27002
|
-
return
|
|
26499
|
+
return onceChildProcessEvent(childProcess, "error", cb);
|
|
27003
26500
|
},
|
|
27004
26501
|
exit: cb => {
|
|
27005
|
-
return
|
|
26502
|
+
return onceChildProcessEvent(childProcess, "exit", (code, signal) => {
|
|
27006
26503
|
cb({
|
|
27007
26504
|
code,
|
|
27008
26505
|
signal
|
|
@@ -27010,7 +26507,7 @@ nodeProcess.run = async ({
|
|
|
27010
26507
|
});
|
|
27011
26508
|
},
|
|
27012
26509
|
response: cb => {
|
|
27013
|
-
|
|
26510
|
+
return onceChildProcessMessage(childProcess, "action-result", cb);
|
|
27014
26511
|
}
|
|
27015
26512
|
}, resolve);
|
|
27016
26513
|
});
|
|
@@ -27019,11 +26516,19 @@ nodeProcess.run = async ({
|
|
|
27019
26516
|
actionOperation.throwIfAborted();
|
|
27020
26517
|
await childProcessReadyPromise;
|
|
27021
26518
|
actionOperation.throwIfAborted();
|
|
27022
|
-
await
|
|
27023
|
-
|
|
27024
|
-
|
|
27025
|
-
|
|
27026
|
-
|
|
26519
|
+
await sendToChildProcess(childProcess, {
|
|
26520
|
+
type: "action",
|
|
26521
|
+
data: {
|
|
26522
|
+
actionType: "execute-using-dynamic-import",
|
|
26523
|
+
actionParams: {
|
|
26524
|
+
rootDirectoryUrl,
|
|
26525
|
+
fileUrl: new URL(fileRelativeUrl, rootDirectoryUrl).href,
|
|
26526
|
+
collectPerformance,
|
|
26527
|
+
coverageEnabled,
|
|
26528
|
+
coverageConfig,
|
|
26529
|
+
coverageMethodForNodeJs,
|
|
26530
|
+
exitAfterAction: true
|
|
26531
|
+
}
|
|
27027
26532
|
}
|
|
27028
26533
|
});
|
|
27029
26534
|
const winner = await winnerPromise;
|
|
@@ -27056,7 +26561,7 @@ nodeProcess.run = async ({
|
|
|
27056
26561
|
};
|
|
27057
26562
|
}
|
|
27058
26563
|
|
|
27059
|
-
if (code === null || code === 0 || code ===
|
|
26564
|
+
if (code === null || code === 0 || code === EXIT_CODES.SIGINT || code === EXIT_CODES.SIGTERM || code === EXIT_CODES.SIGABORT) {
|
|
27060
26565
|
return {
|
|
27061
26566
|
status: "errored",
|
|
27062
26567
|
error: new Error(`node process exited during execution`)
|
|
@@ -27110,31 +26615,25 @@ nodeProcess.run = async ({
|
|
|
27110
26615
|
|
|
27111
26616
|
await actionOperation.end();
|
|
27112
26617
|
return result;
|
|
27113
|
-
}; //
|
|
27114
|
-
|
|
27115
|
-
|
|
27116
|
-
const SIGINT_SIGNAL_NUMBER = 2;
|
|
27117
|
-
const SIGABORT_SIGNAL_NUMBER = 6;
|
|
27118
|
-
const SIGTERM_SIGNAL_NUMBER = 15;
|
|
27119
|
-
const SIGINT_EXIT_CODE = 128 + SIGINT_SIGNAL_NUMBER;
|
|
27120
|
-
const SIGABORT_EXIT_CODE = 128 + SIGABORT_SIGNAL_NUMBER;
|
|
27121
|
-
const SIGTERM_EXIT_CODE = 128 + SIGTERM_SIGNAL_NUMBER; // http://man7.org/linux/man-pages/man7/signal.7.html
|
|
26618
|
+
}; // http://man7.org/linux/man-pages/man7/signal.7.html
|
|
27122
26619
|
// https:// github.com/nodejs/node/blob/1d9511127c419ec116b3ddf5fc7a59e8f0f1c1e4/lib/internal/child_process.js#L472
|
|
27123
26620
|
|
|
26621
|
+
|
|
27124
26622
|
const GRACEFUL_STOP_SIGNAL = "SIGTERM";
|
|
27125
26623
|
const STOP_SIGNAL = "SIGKILL"; // it would be more correct if GRACEFUL_STOP_FAILED_SIGNAL was SIGHUP instead of SIGKILL.
|
|
27126
26624
|
// but I'm not sure and it changes nothing so just use SIGKILL
|
|
27127
26625
|
|
|
27128
26626
|
const GRACEFUL_STOP_FAILED_SIGNAL = "SIGKILL";
|
|
27129
26627
|
|
|
27130
|
-
const
|
|
27131
|
-
|
|
27132
|
-
|
|
27133
|
-
|
|
26628
|
+
const sendToChildProcess = async (childProcess, {
|
|
26629
|
+
type,
|
|
26630
|
+
data
|
|
26631
|
+
}) => {
|
|
27134
26632
|
return new Promise((resolve, reject) => {
|
|
27135
26633
|
childProcess.send({
|
|
26634
|
+
jsenv: true,
|
|
27136
26635
|
type,
|
|
27137
|
-
data
|
|
26636
|
+
data
|
|
27138
26637
|
}, error => {
|
|
27139
26638
|
if (error) {
|
|
27140
26639
|
reject(error);
|
|
@@ -27145,7 +26644,7 @@ const sendToProcess = async (childProcess, type, data) => {
|
|
|
27145
26644
|
});
|
|
27146
26645
|
};
|
|
27147
26646
|
|
|
27148
|
-
const
|
|
26647
|
+
const installChildProcessOutputListener = (childProcess, callback) => {
|
|
27149
26648
|
// beware that we may receive ansi output here, should not be a problem but keep that in mind
|
|
27150
26649
|
const stdoutDataCallback = chunk => {
|
|
27151
26650
|
callback({
|
|
@@ -27170,9 +26669,9 @@ const installProcessOutputListener = (childProcess, callback) => {
|
|
|
27170
26669
|
};
|
|
27171
26670
|
};
|
|
27172
26671
|
|
|
27173
|
-
const
|
|
26672
|
+
const onceChildProcessMessage = (childProcess, type, callback) => {
|
|
27174
26673
|
const onmessage = message => {
|
|
27175
|
-
if (message.type === type) {
|
|
26674
|
+
if (message && message.jsenv && message.type === type) {
|
|
27176
26675
|
childProcess.removeListener("message", onmessage); // eslint-disable-next-line no-eval
|
|
27177
26676
|
|
|
27178
26677
|
callback(message.data ? eval(`(${message.data})`) : "");
|
|
@@ -27185,13 +26684,290 @@ const onceProcessMessage = (childProcess, type, callback) => {
|
|
|
27185
26684
|
};
|
|
27186
26685
|
};
|
|
27187
26686
|
|
|
27188
|
-
const
|
|
26687
|
+
const onceChildProcessEvent = (childProcess, type, callback) => {
|
|
27189
26688
|
childProcess.once(type, callback);
|
|
27190
26689
|
return () => {
|
|
27191
26690
|
childProcess.removeListener(type, callback);
|
|
27192
26691
|
};
|
|
27193
26692
|
};
|
|
27194
26693
|
|
|
26694
|
+
// https://github.com/avajs/ava/blob/576f534b345259055c95fa0c2b33bef10847a2af/lib/fork.js#L23
|
|
26695
|
+
const CONTROLLABLE_WORKER_THREAD_URL = new URL("./controllable_worker_thread.mjs", import.meta.url).href;
|
|
26696
|
+
const nodeWorkerThread = {
|
|
26697
|
+
type: "node",
|
|
26698
|
+
name: "node_worker_thread",
|
|
26699
|
+
version: process.version.slice(1)
|
|
26700
|
+
};
|
|
26701
|
+
|
|
26702
|
+
nodeWorkerThread.run = async ({
|
|
26703
|
+
signal = new AbortController().signal,
|
|
26704
|
+
// logger,
|
|
26705
|
+
rootDirectoryUrl,
|
|
26706
|
+
fileRelativeUrl,
|
|
26707
|
+
keepRunning,
|
|
26708
|
+
stopSignal,
|
|
26709
|
+
onConsole,
|
|
26710
|
+
coverageConfig,
|
|
26711
|
+
coverageMethodForNodeJs,
|
|
26712
|
+
coverageEnabled = false,
|
|
26713
|
+
collectPerformance,
|
|
26714
|
+
env,
|
|
26715
|
+
debugPort,
|
|
26716
|
+
debugMode,
|
|
26717
|
+
debugModeInheritBreak,
|
|
26718
|
+
inheritProcessEnv = true,
|
|
26719
|
+
commandLineOptions = []
|
|
26720
|
+
}) => {
|
|
26721
|
+
if (env !== undefined && typeof env !== "object") {
|
|
26722
|
+
throw new TypeError(`env must be an object, got ${env}`);
|
|
26723
|
+
}
|
|
26724
|
+
|
|
26725
|
+
env = { ...env,
|
|
26726
|
+
JSENV: true
|
|
26727
|
+
};
|
|
26728
|
+
|
|
26729
|
+
if (coverageMethodForNodeJs !== "NODE_V8_COVERAGE") {
|
|
26730
|
+
env.NODE_V8_COVERAGE = "";
|
|
26731
|
+
}
|
|
26732
|
+
|
|
26733
|
+
const workerThreadExecOptions = await createChildExecOptions({
|
|
26734
|
+
signal,
|
|
26735
|
+
debugPort,
|
|
26736
|
+
debugMode,
|
|
26737
|
+
debugModeInheritBreak
|
|
26738
|
+
});
|
|
26739
|
+
const execArgvForWorkerThread = ExecOptions.toExecArgv({ ...workerThreadExecOptions,
|
|
26740
|
+
...ExecOptions.fromExecArgv(commandLineOptions)
|
|
26741
|
+
});
|
|
26742
|
+
const envForWorkerThread = { ...(inheritProcessEnv ? process.env : {}),
|
|
26743
|
+
...env
|
|
26744
|
+
};
|
|
26745
|
+
const cleanupCallbackList = createCallbackListNotifiedOnce();
|
|
26746
|
+
|
|
26747
|
+
const cleanup = async reason => {
|
|
26748
|
+
await cleanupCallbackList.notify({
|
|
26749
|
+
reason
|
|
26750
|
+
});
|
|
26751
|
+
};
|
|
26752
|
+
|
|
26753
|
+
const actionOperation = Abort.startOperation();
|
|
26754
|
+
actionOperation.addAbortSignal(signal); // https://nodejs.org/api/worker_threads.html#new-workerfilename-options
|
|
26755
|
+
|
|
26756
|
+
const workerThread = new Worker(fileURLToPath(CONTROLLABLE_WORKER_THREAD_URL), {
|
|
26757
|
+
env: envForWorkerThread,
|
|
26758
|
+
execArgv: execArgvForWorkerThread,
|
|
26759
|
+
// workerData: { options },
|
|
26760
|
+
// trackUnmanagedFds: true,
|
|
26761
|
+
stdin: true,
|
|
26762
|
+
stdout: true,
|
|
26763
|
+
stderr: true
|
|
26764
|
+
});
|
|
26765
|
+
const removeOutputListener = installWorkerThreadOutputListener(workerThread, ({
|
|
26766
|
+
type,
|
|
26767
|
+
text
|
|
26768
|
+
}) => {
|
|
26769
|
+
onConsole({
|
|
26770
|
+
type,
|
|
26771
|
+
text
|
|
26772
|
+
});
|
|
26773
|
+
});
|
|
26774
|
+
const workerThreadReadyPromise = new Promise(resolve => {
|
|
26775
|
+
onceWorkerThreadMessage(workerThread, "ready", resolve);
|
|
26776
|
+
});
|
|
26777
|
+
const stop = memoize(async () => {
|
|
26778
|
+
await workerThreadReadyPromise;
|
|
26779
|
+
await workerThread.terminate();
|
|
26780
|
+
});
|
|
26781
|
+
const winnerPromise = new Promise(resolve => {
|
|
26782
|
+
raceCallbacks({
|
|
26783
|
+
aborted: cb => {
|
|
26784
|
+
return actionOperation.addAbortCallback(cb);
|
|
26785
|
+
},
|
|
26786
|
+
error: cb => {
|
|
26787
|
+
return onceWorkerThreadEvent(workerThread, "error", cb);
|
|
26788
|
+
},
|
|
26789
|
+
exit: cb => {
|
|
26790
|
+
return onceWorkerThreadEvent(workerThread, "exit", (code, signal) => {
|
|
26791
|
+
cb({
|
|
26792
|
+
code,
|
|
26793
|
+
signal
|
|
26794
|
+
});
|
|
26795
|
+
});
|
|
26796
|
+
},
|
|
26797
|
+
response: cb => {
|
|
26798
|
+
return onceWorkerThreadMessage(workerThread, "action-result", cb);
|
|
26799
|
+
}
|
|
26800
|
+
}, resolve);
|
|
26801
|
+
});
|
|
26802
|
+
|
|
26803
|
+
const getResult = async () => {
|
|
26804
|
+
actionOperation.throwIfAborted();
|
|
26805
|
+
await workerThreadReadyPromise;
|
|
26806
|
+
actionOperation.throwIfAborted();
|
|
26807
|
+
await sendToWorkerThread(workerThread, {
|
|
26808
|
+
type: "action",
|
|
26809
|
+
data: {
|
|
26810
|
+
actionType: "execute-using-dynamic-import",
|
|
26811
|
+
actionParams: {
|
|
26812
|
+
rootDirectoryUrl,
|
|
26813
|
+
fileUrl: new URL(fileRelativeUrl, rootDirectoryUrl).href,
|
|
26814
|
+
collectPerformance,
|
|
26815
|
+
coverageEnabled,
|
|
26816
|
+
coverageConfig,
|
|
26817
|
+
coverageMethodForNodeJs,
|
|
26818
|
+
exitAfterAction: true
|
|
26819
|
+
}
|
|
26820
|
+
}
|
|
26821
|
+
});
|
|
26822
|
+
const winner = await winnerPromise;
|
|
26823
|
+
|
|
26824
|
+
if (winner.name === "aborted") {
|
|
26825
|
+
return {
|
|
26826
|
+
status: "aborted"
|
|
26827
|
+
};
|
|
26828
|
+
}
|
|
26829
|
+
|
|
26830
|
+
if (winner.name === "error") {
|
|
26831
|
+
const error = winner.data;
|
|
26832
|
+
removeOutputListener();
|
|
26833
|
+
return {
|
|
26834
|
+
status: "errored",
|
|
26835
|
+
error
|
|
26836
|
+
};
|
|
26837
|
+
}
|
|
26838
|
+
|
|
26839
|
+
if (winner.name === "exit") {
|
|
26840
|
+
const {
|
|
26841
|
+
code
|
|
26842
|
+
} = winner.data;
|
|
26843
|
+
await cleanup("process exit");
|
|
26844
|
+
|
|
26845
|
+
if (code === 12) {
|
|
26846
|
+
return {
|
|
26847
|
+
status: "errored",
|
|
26848
|
+
error: new Error(`node process exited with 12 (the forked child process wanted to use a non-available port for debug)`)
|
|
26849
|
+
};
|
|
26850
|
+
}
|
|
26851
|
+
|
|
26852
|
+
if (code === null || code === 0 || code === EXIT_CODES.SIGINT || code === EXIT_CODES.SIGTERM || code === EXIT_CODES.SIGABORT) {
|
|
26853
|
+
return {
|
|
26854
|
+
status: "errored",
|
|
26855
|
+
error: new Error(`node worker thread exited during execution`)
|
|
26856
|
+
};
|
|
26857
|
+
} // process.exit(1) in child process or process.exitCode = 1 + process.exit()
|
|
26858
|
+
// means there was an error even if we don't know exactly what.
|
|
26859
|
+
|
|
26860
|
+
|
|
26861
|
+
return {
|
|
26862
|
+
status: "errored",
|
|
26863
|
+
error: new Error(`node worker thread exited with code ${code} during execution`)
|
|
26864
|
+
};
|
|
26865
|
+
}
|
|
26866
|
+
|
|
26867
|
+
const {
|
|
26868
|
+
status,
|
|
26869
|
+
value
|
|
26870
|
+
} = winner.data;
|
|
26871
|
+
|
|
26872
|
+
if (status === "action-failed") {
|
|
26873
|
+
return {
|
|
26874
|
+
status: "errored",
|
|
26875
|
+
error: value
|
|
26876
|
+
};
|
|
26877
|
+
}
|
|
26878
|
+
|
|
26879
|
+
const {
|
|
26880
|
+
namespace,
|
|
26881
|
+
performance,
|
|
26882
|
+
coverage
|
|
26883
|
+
} = value;
|
|
26884
|
+
return {
|
|
26885
|
+
status: "completed",
|
|
26886
|
+
namespace,
|
|
26887
|
+
performance,
|
|
26888
|
+
coverage
|
|
26889
|
+
};
|
|
26890
|
+
};
|
|
26891
|
+
|
|
26892
|
+
let result;
|
|
26893
|
+
|
|
26894
|
+
try {
|
|
26895
|
+
result = await getResult();
|
|
26896
|
+
} catch (e) {
|
|
26897
|
+
result = {
|
|
26898
|
+
status: "errored",
|
|
26899
|
+
error: e
|
|
26900
|
+
};
|
|
26901
|
+
}
|
|
26902
|
+
|
|
26903
|
+
if (keepRunning) {
|
|
26904
|
+
stopSignal.notify = stop;
|
|
26905
|
+
} else {
|
|
26906
|
+
await stop();
|
|
26907
|
+
}
|
|
26908
|
+
|
|
26909
|
+
await actionOperation.end();
|
|
26910
|
+
return result;
|
|
26911
|
+
};
|
|
26912
|
+
|
|
26913
|
+
const installWorkerThreadOutputListener = (workerThread, callback) => {
|
|
26914
|
+
// beware that we may receive ansi output here, should not be a problem but keep that in mind
|
|
26915
|
+
const stdoutDataCallback = chunk => {
|
|
26916
|
+
callback({
|
|
26917
|
+
type: "log",
|
|
26918
|
+
text: String(chunk)
|
|
26919
|
+
});
|
|
26920
|
+
};
|
|
26921
|
+
|
|
26922
|
+
workerThread.stdout.on("data", stdoutDataCallback);
|
|
26923
|
+
|
|
26924
|
+
const stdErrorDataCallback = chunk => {
|
|
26925
|
+
callback({
|
|
26926
|
+
type: "error",
|
|
26927
|
+
text: String(chunk)
|
|
26928
|
+
});
|
|
26929
|
+
};
|
|
26930
|
+
|
|
26931
|
+
workerThread.stderr.on("data", stdErrorDataCallback);
|
|
26932
|
+
return () => {
|
|
26933
|
+
workerThread.stdout.removeListener("data", stdoutDataCallback);
|
|
26934
|
+
workerThread.stderr.removeListener("data", stdoutDataCallback);
|
|
26935
|
+
};
|
|
26936
|
+
};
|
|
26937
|
+
|
|
26938
|
+
const sendToWorkerThread = (worker, {
|
|
26939
|
+
type,
|
|
26940
|
+
data
|
|
26941
|
+
}) => {
|
|
26942
|
+
worker.postMessage({
|
|
26943
|
+
jsenv: true,
|
|
26944
|
+
type,
|
|
26945
|
+
data
|
|
26946
|
+
});
|
|
26947
|
+
};
|
|
26948
|
+
|
|
26949
|
+
const onceWorkerThreadMessage = (workerThread, type, callback) => {
|
|
26950
|
+
const onmessage = message => {
|
|
26951
|
+
if (message && message.jsenv && message.type === type) {
|
|
26952
|
+
workerThread.removeListener("message", onmessage); // eslint-disable-next-line no-eval
|
|
26953
|
+
|
|
26954
|
+
callback(message.data ? eval(`(${message.data})`) : undefined);
|
|
26955
|
+
}
|
|
26956
|
+
};
|
|
26957
|
+
|
|
26958
|
+
workerThread.on("message", onmessage);
|
|
26959
|
+
return () => {
|
|
26960
|
+
workerThread.removeListener("message", onmessage);
|
|
26961
|
+
};
|
|
26962
|
+
};
|
|
26963
|
+
|
|
26964
|
+
const onceWorkerThreadEvent = (worker, type, callback) => {
|
|
26965
|
+
worker.once(type, callback);
|
|
26966
|
+
return () => {
|
|
26967
|
+
worker.removeListener(type, callback);
|
|
26968
|
+
};
|
|
26969
|
+
};
|
|
26970
|
+
|
|
27195
26971
|
const loadUrlGraph = async ({
|
|
27196
26972
|
operation,
|
|
27197
26973
|
urlGraph,
|
|
@@ -27261,7 +27037,6 @@ const loadUrlGraph = async ({
|
|
|
27261
27037
|
type,
|
|
27262
27038
|
specifier
|
|
27263
27039
|
});
|
|
27264
|
-
entryUrlInfo.data.isEntryPoint = true;
|
|
27265
27040
|
cook(entryUrlInfo, {
|
|
27266
27041
|
reference: entryReference
|
|
27267
27042
|
});
|
|
@@ -27635,7 +27410,7 @@ const determineDirectoryPath = ({
|
|
|
27635
27410
|
return parentDirectoryPath;
|
|
27636
27411
|
}
|
|
27637
27412
|
|
|
27638
|
-
if (urlInfo.
|
|
27413
|
+
if (urlInfo.isEntryPoint) {
|
|
27639
27414
|
return "";
|
|
27640
27415
|
}
|
|
27641
27416
|
|
|
@@ -27669,7 +27444,7 @@ const injectGlobalVersionMapping = async ({
|
|
|
27669
27444
|
versionMappings
|
|
27670
27445
|
}) => {
|
|
27671
27446
|
await Promise.all(GRAPH.map(finalGraph, async urlInfo => {
|
|
27672
|
-
if (urlInfo.
|
|
27447
|
+
if (urlInfo.isEntryPoint) {
|
|
27673
27448
|
await injectVersionMappings({
|
|
27674
27449
|
urlInfo,
|
|
27675
27450
|
kitchen: finalGraphKitchen,
|
|
@@ -27705,7 +27480,7 @@ const jsInjector = (urlInfo, {
|
|
|
27705
27480
|
}) => {
|
|
27706
27481
|
const magicSource = createMagicSource(urlInfo.content);
|
|
27707
27482
|
magicSource.prepend(generateClientCodeForVersionMappings(versionMappings, {
|
|
27708
|
-
globalName: urlInfo
|
|
27483
|
+
globalName: isWebWorkerUrlInfo(urlInfo) ? "self" : "window"
|
|
27709
27484
|
}));
|
|
27710
27485
|
return magicSource.toContentAndSourcemap();
|
|
27711
27486
|
};
|
|
@@ -27811,7 +27586,7 @@ const injectServiceWorkerUrls = async ({
|
|
|
27811
27586
|
lineBreakNormalization
|
|
27812
27587
|
}) => {
|
|
27813
27588
|
const serviceWorkerEntryUrlInfos = GRAPH.filter(finalGraph, finalUrlInfo => {
|
|
27814
|
-
return finalUrlInfo.subtype === "service_worker" && finalUrlInfo.
|
|
27589
|
+
return finalUrlInfo.subtype === "service_worker" && finalUrlInfo.isEntryPoint;
|
|
27815
27590
|
});
|
|
27816
27591
|
|
|
27817
27592
|
if (serviceWorkerEntryUrlInfos.length === 0) {
|
|
@@ -28227,7 +28002,7 @@ build ${entryPointKeys.length} entry points`);
|
|
|
28227
28002
|
};
|
|
28228
28003
|
|
|
28229
28004
|
GRAPH.forEach(rawGraph, rawUrlInfo => {
|
|
28230
|
-
if (rawUrlInfo.
|
|
28005
|
+
if (rawUrlInfo.isEntryPoint) {
|
|
28231
28006
|
addToBundlerIfAny(rawUrlInfo);
|
|
28232
28007
|
|
|
28233
28008
|
if (rawUrlInfo.type === "html") {
|
|
@@ -28305,6 +28080,7 @@ build ${entryPointKeys.length} entry points`);
|
|
|
28305
28080
|
const bundleUrlInfo = {
|
|
28306
28081
|
type,
|
|
28307
28082
|
subtype: rawUrlInfo ? rawUrlInfo.subtype : undefined,
|
|
28083
|
+
isEntryPoint: rawUrlInfo ? rawUrlInfo.isEntryPoint : undefined,
|
|
28308
28084
|
filename: rawUrlInfo ? rawUrlInfo.filename : undefined,
|
|
28309
28085
|
originalUrl: rawUrlInfo ? rawUrlInfo.originalUrl : undefined,
|
|
28310
28086
|
originalContent: rawUrlInfo ? rawUrlInfo.originalContent : undefined,
|
|
@@ -28442,9 +28218,8 @@ build ${entryPointKeys.length} entry points`);
|
|
|
28442
28218
|
|
|
28443
28219
|
const buildUrl = buildUrlsGenerator.generate(rawUrl, {
|
|
28444
28220
|
urlInfo: {
|
|
28445
|
-
data:
|
|
28446
|
-
|
|
28447
|
-
},
|
|
28221
|
+
data: reference.data,
|
|
28222
|
+
isEntryPoint: reference.isEntryPoint || isWebWorkerEntryPointReference(reference),
|
|
28448
28223
|
type: reference.expectedType,
|
|
28449
28224
|
subtype: reference.expectedSubtype,
|
|
28450
28225
|
filename: reference.filename
|
|
@@ -28736,7 +28511,7 @@ ${Object.keys(finalGraph.urlInfos).join("\n")}`);
|
|
|
28736
28511
|
// nothing uses this url anymore
|
|
28737
28512
|
// - versioning update inline content
|
|
28738
28513
|
// - file converted for import assertion of js_classic conversion
|
|
28739
|
-
if (!urlInfo.
|
|
28514
|
+
if (!urlInfo.isEntryPoint && urlInfo.type !== "sourcemap" && urlInfo.dependents.size === 0) {
|
|
28740
28515
|
cleanupActions.push(() => {
|
|
28741
28516
|
finalGraph.deleteUrlInfo(urlInfo.url);
|
|
28742
28517
|
});
|
|
@@ -28958,7 +28733,7 @@ const applyUrlVersioning = async ({
|
|
|
28958
28733
|
return;
|
|
28959
28734
|
}
|
|
28960
28735
|
|
|
28961
|
-
if (!urlInfo.
|
|
28736
|
+
if (!urlInfo.isEntryPoint && urlInfo.dependents.size === 0) {
|
|
28962
28737
|
return;
|
|
28963
28738
|
}
|
|
28964
28739
|
|
|
@@ -29204,7 +28979,7 @@ const assertEntryPoints = ({
|
|
|
29204
28979
|
};
|
|
29205
28980
|
|
|
29206
28981
|
const canUseVersionedUrl = urlInfo => {
|
|
29207
|
-
if (urlInfo.
|
|
28982
|
+
if (urlInfo.isEntryPoint) {
|
|
29208
28983
|
return false;
|
|
29209
28984
|
}
|
|
29210
28985
|
|
|
@@ -29212,10 +28987,6 @@ const canUseVersionedUrl = urlInfo => {
|
|
|
29212
28987
|
return false;
|
|
29213
28988
|
}
|
|
29214
28989
|
|
|
29215
|
-
if (urlInfo.subtype === "service_worker") {
|
|
29216
|
-
return !urlInfo.data.isWebWorkerEntryPoint;
|
|
29217
|
-
}
|
|
29218
|
-
|
|
29219
28990
|
return true;
|
|
29220
28991
|
};
|
|
29221
28992
|
|
|
@@ -29677,4 +29448,4 @@ const jsenvPluginInjectGlobals = urlAssociations => {
|
|
|
29677
29448
|
};
|
|
29678
29449
|
};
|
|
29679
29450
|
|
|
29680
|
-
export { build, chromium, chromiumIsolatedTab, execute, executeTestPlan, firefox, firefoxIsolatedTab, jsenvPluginInjectGlobals,
|
|
29451
|
+
export { build, chromium, chromiumIsolatedTab, execute, executeTestPlan, firefox, firefoxIsolatedTab, jsenvPluginInjectGlobals, nodeChildProcess, nodeWorkerThread, startBuildServer, startDevServer, webkit, webkitIsolatedTab };
|