@jsenv/core 27.1.0 → 27.2.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/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 +580 -806
- package/package.json +10 -9
- 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/chromium.js +1 -1
- package/src/execute/runtimes/browsers/firefox.js +1 -1
- package/src/execute/runtimes/browsers/from_playwright.js +13 -8
- package/src/execute/runtimes/browsers/webkit.js +1 -1
- 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
|
|
@@ -26534,20 +26022,23 @@ const evalException = (exceptionSource, {
|
|
|
26534
26022
|
|
|
26535
26023
|
const chromium = createRuntimeFromPlaywright({
|
|
26536
26024
|
browserName: "chromium",
|
|
26537
|
-
browserVersion: "
|
|
26025
|
+
browserVersion: "104.0.5112.20",
|
|
26026
|
+
// to update, check https://github.com/microsoft/playwright/releases
|
|
26538
26027
|
coveragePlaywrightAPIAvailable: true
|
|
26539
26028
|
});
|
|
26540
26029
|
const chromiumIsolatedTab = chromium.isolatedTab;
|
|
26541
26030
|
|
|
26542
26031
|
const firefox = createRuntimeFromPlaywright({
|
|
26543
26032
|
browserName: "firefox",
|
|
26544
|
-
browserVersion: "
|
|
26033
|
+
browserVersion: "100.0.2" // to update, check https://github.com/microsoft/playwright/releases
|
|
26034
|
+
|
|
26545
26035
|
});
|
|
26546
26036
|
const firefoxIsolatedTab = firefox.isolatedTab;
|
|
26547
26037
|
|
|
26548
26038
|
const webkit = createRuntimeFromPlaywright({
|
|
26549
26039
|
browserName: "webkit",
|
|
26550
26040
|
browserVersion: "15.4",
|
|
26041
|
+
// to update, check https://github.com/microsoft/playwright/releases
|
|
26551
26042
|
ignoreErrorHook: error => {
|
|
26552
26043
|
// we catch error during execution but safari throw unhandled rejection
|
|
26553
26044
|
// in a non-deterministic way.
|
|
@@ -26846,13 +26337,24 @@ const killProcessTree = async (processId, {
|
|
|
26846
26337
|
await check();
|
|
26847
26338
|
};
|
|
26848
26339
|
|
|
26849
|
-
|
|
26850
|
-
const
|
|
26851
|
-
|
|
26340
|
+
// https://nodejs.org/api/process.html#process_signal_events
|
|
26341
|
+
const SIGINT_SIGNAL_NUMBER = 2;
|
|
26342
|
+
const SIGABORT_SIGNAL_NUMBER = 6;
|
|
26343
|
+
const SIGTERM_SIGNAL_NUMBER = 15;
|
|
26344
|
+
const EXIT_CODES = {
|
|
26345
|
+
SIGINT: 128 + SIGINT_SIGNAL_NUMBER,
|
|
26346
|
+
SIGABORT: 128 + SIGABORT_SIGNAL_NUMBER,
|
|
26347
|
+
SIGTERM: 128 + SIGTERM_SIGNAL_NUMBER
|
|
26348
|
+
};
|
|
26349
|
+
|
|
26350
|
+
const CONTROLLABLE_CHILD_PROCESS_URL = new URL("./controllable_child_process.mjs", import.meta.url).href;
|
|
26351
|
+
const nodeChildProcess = {
|
|
26352
|
+
type: "node",
|
|
26353
|
+
name: "node_child_process",
|
|
26852
26354
|
version: process.version.slice(1)
|
|
26853
26355
|
};
|
|
26854
26356
|
|
|
26855
|
-
|
|
26357
|
+
nodeChildProcess.run = async ({
|
|
26856
26358
|
signal = new AbortController().signal,
|
|
26857
26359
|
logger,
|
|
26858
26360
|
logProcessCommand = false,
|
|
@@ -26862,13 +26364,14 @@ nodeProcess.run = async ({
|
|
|
26862
26364
|
gracefulStopAllocatedMs = 4000,
|
|
26863
26365
|
stopSignal,
|
|
26864
26366
|
onConsole,
|
|
26865
|
-
|
|
26866
|
-
|
|
26367
|
+
coverageEnabled = false,
|
|
26368
|
+
coverageConfig,
|
|
26369
|
+
coverageMethodForNodeJs,
|
|
26867
26370
|
collectPerformance,
|
|
26371
|
+
env,
|
|
26868
26372
|
debugPort,
|
|
26869
26373
|
debugMode,
|
|
26870
26374
|
debugModeInheritBreak,
|
|
26871
|
-
env,
|
|
26872
26375
|
inheritProcessEnv = true,
|
|
26873
26376
|
commandLineOptions = [],
|
|
26874
26377
|
stdin = "pipe",
|
|
@@ -26880,13 +26383,10 @@ nodeProcess.run = async ({
|
|
|
26880
26383
|
}
|
|
26881
26384
|
|
|
26882
26385
|
env = { ...env,
|
|
26883
|
-
COVERAGE_ENABLED: collectCoverage,
|
|
26884
26386
|
JSENV: true
|
|
26885
26387
|
};
|
|
26886
26388
|
|
|
26887
|
-
if (
|
|
26888
|
-
// if we want to force istanbul, we will set process.env.NODE_V8_COVERAGE = ''
|
|
26889
|
-
// into the child_process
|
|
26389
|
+
if (coverageMethodForNodeJs !== "NODE_V8_COVERAGE") {
|
|
26890
26390
|
env.NODE_V8_COVERAGE = "";
|
|
26891
26391
|
}
|
|
26892
26392
|
|
|
@@ -26911,8 +26411,8 @@ nodeProcess.run = async ({
|
|
|
26911
26411
|
const envForChildProcess = { ...(inheritProcessEnv ? process.env : {}),
|
|
26912
26412
|
...env
|
|
26913
26413
|
};
|
|
26914
|
-
logger[logProcessCommand ? "info" : "debug"](`${process.argv[0]} ${execArgv.join(" ")} ${
|
|
26915
|
-
const childProcess = fork(
|
|
26414
|
+
logger[logProcessCommand ? "info" : "debug"](`${process.argv[0]} ${execArgv.join(" ")} ${fileURLToPath(CONTROLLABLE_CHILD_PROCESS_URL)}`);
|
|
26415
|
+
const childProcess = fork(fileURLToPath(CONTROLLABLE_CHILD_PROCESS_URL), {
|
|
26916
26416
|
execArgv,
|
|
26917
26417
|
// silent: true
|
|
26918
26418
|
stdio: ["pipe", "pipe", "pipe", "ipc"],
|
|
@@ -26936,9 +26436,9 @@ nodeProcess.run = async ({
|
|
|
26936
26436
|
}
|
|
26937
26437
|
|
|
26938
26438
|
const childProcessReadyPromise = new Promise(resolve => {
|
|
26939
|
-
|
|
26439
|
+
onceChildProcessMessage(childProcess, "ready", resolve);
|
|
26940
26440
|
});
|
|
26941
|
-
const removeOutputListener =
|
|
26441
|
+
const removeOutputListener = installChildProcessOutputListener(childProcess, ({
|
|
26942
26442
|
type,
|
|
26943
26443
|
text
|
|
26944
26444
|
}) => {
|
|
@@ -26999,10 +26499,10 @@ nodeProcess.run = async ({
|
|
|
26999
26499
|
// },
|
|
27000
26500
|
// https://nodejs.org/api/child_process.html#child_process_event_error
|
|
27001
26501
|
error: cb => {
|
|
27002
|
-
return
|
|
26502
|
+
return onceChildProcessEvent(childProcess, "error", cb);
|
|
27003
26503
|
},
|
|
27004
26504
|
exit: cb => {
|
|
27005
|
-
return
|
|
26505
|
+
return onceChildProcessEvent(childProcess, "exit", (code, signal) => {
|
|
27006
26506
|
cb({
|
|
27007
26507
|
code,
|
|
27008
26508
|
signal
|
|
@@ -27010,7 +26510,7 @@ nodeProcess.run = async ({
|
|
|
27010
26510
|
});
|
|
27011
26511
|
},
|
|
27012
26512
|
response: cb => {
|
|
27013
|
-
|
|
26513
|
+
return onceChildProcessMessage(childProcess, "action-result", cb);
|
|
27014
26514
|
}
|
|
27015
26515
|
}, resolve);
|
|
27016
26516
|
});
|
|
@@ -27019,11 +26519,19 @@ nodeProcess.run = async ({
|
|
|
27019
26519
|
actionOperation.throwIfAborted();
|
|
27020
26520
|
await childProcessReadyPromise;
|
|
27021
26521
|
actionOperation.throwIfAborted();
|
|
27022
|
-
await
|
|
27023
|
-
|
|
27024
|
-
|
|
27025
|
-
|
|
27026
|
-
|
|
26522
|
+
await sendToChildProcess(childProcess, {
|
|
26523
|
+
type: "action",
|
|
26524
|
+
data: {
|
|
26525
|
+
actionType: "execute-using-dynamic-import",
|
|
26526
|
+
actionParams: {
|
|
26527
|
+
rootDirectoryUrl,
|
|
26528
|
+
fileUrl: new URL(fileRelativeUrl, rootDirectoryUrl).href,
|
|
26529
|
+
collectPerformance,
|
|
26530
|
+
coverageEnabled,
|
|
26531
|
+
coverageConfig,
|
|
26532
|
+
coverageMethodForNodeJs,
|
|
26533
|
+
exitAfterAction: true
|
|
26534
|
+
}
|
|
27027
26535
|
}
|
|
27028
26536
|
});
|
|
27029
26537
|
const winner = await winnerPromise;
|
|
@@ -27056,7 +26564,7 @@ nodeProcess.run = async ({
|
|
|
27056
26564
|
};
|
|
27057
26565
|
}
|
|
27058
26566
|
|
|
27059
|
-
if (code === null || code === 0 || code ===
|
|
26567
|
+
if (code === null || code === 0 || code === EXIT_CODES.SIGINT || code === EXIT_CODES.SIGTERM || code === EXIT_CODES.SIGABORT) {
|
|
27060
26568
|
return {
|
|
27061
26569
|
status: "errored",
|
|
27062
26570
|
error: new Error(`node process exited during execution`)
|
|
@@ -27110,31 +26618,25 @@ nodeProcess.run = async ({
|
|
|
27110
26618
|
|
|
27111
26619
|
await actionOperation.end();
|
|
27112
26620
|
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
|
|
26621
|
+
}; // http://man7.org/linux/man-pages/man7/signal.7.html
|
|
27122
26622
|
// https:// github.com/nodejs/node/blob/1d9511127c419ec116b3ddf5fc7a59e8f0f1c1e4/lib/internal/child_process.js#L472
|
|
27123
26623
|
|
|
26624
|
+
|
|
27124
26625
|
const GRACEFUL_STOP_SIGNAL = "SIGTERM";
|
|
27125
26626
|
const STOP_SIGNAL = "SIGKILL"; // it would be more correct if GRACEFUL_STOP_FAILED_SIGNAL was SIGHUP instead of SIGKILL.
|
|
27126
26627
|
// but I'm not sure and it changes nothing so just use SIGKILL
|
|
27127
26628
|
|
|
27128
26629
|
const GRACEFUL_STOP_FAILED_SIGNAL = "SIGKILL";
|
|
27129
26630
|
|
|
27130
|
-
const
|
|
27131
|
-
|
|
27132
|
-
|
|
27133
|
-
|
|
26631
|
+
const sendToChildProcess = async (childProcess, {
|
|
26632
|
+
type,
|
|
26633
|
+
data
|
|
26634
|
+
}) => {
|
|
27134
26635
|
return new Promise((resolve, reject) => {
|
|
27135
26636
|
childProcess.send({
|
|
26637
|
+
jsenv: true,
|
|
27136
26638
|
type,
|
|
27137
|
-
data
|
|
26639
|
+
data
|
|
27138
26640
|
}, error => {
|
|
27139
26641
|
if (error) {
|
|
27140
26642
|
reject(error);
|
|
@@ -27145,7 +26647,7 @@ const sendToProcess = async (childProcess, type, data) => {
|
|
|
27145
26647
|
});
|
|
27146
26648
|
};
|
|
27147
26649
|
|
|
27148
|
-
const
|
|
26650
|
+
const installChildProcessOutputListener = (childProcess, callback) => {
|
|
27149
26651
|
// beware that we may receive ansi output here, should not be a problem but keep that in mind
|
|
27150
26652
|
const stdoutDataCallback = chunk => {
|
|
27151
26653
|
callback({
|
|
@@ -27170,9 +26672,9 @@ const installProcessOutputListener = (childProcess, callback) => {
|
|
|
27170
26672
|
};
|
|
27171
26673
|
};
|
|
27172
26674
|
|
|
27173
|
-
const
|
|
26675
|
+
const onceChildProcessMessage = (childProcess, type, callback) => {
|
|
27174
26676
|
const onmessage = message => {
|
|
27175
|
-
if (message.type === type) {
|
|
26677
|
+
if (message && message.jsenv && message.type === type) {
|
|
27176
26678
|
childProcess.removeListener("message", onmessage); // eslint-disable-next-line no-eval
|
|
27177
26679
|
|
|
27178
26680
|
callback(message.data ? eval(`(${message.data})`) : "");
|
|
@@ -27185,13 +26687,290 @@ const onceProcessMessage = (childProcess, type, callback) => {
|
|
|
27185
26687
|
};
|
|
27186
26688
|
};
|
|
27187
26689
|
|
|
27188
|
-
const
|
|
26690
|
+
const onceChildProcessEvent = (childProcess, type, callback) => {
|
|
27189
26691
|
childProcess.once(type, callback);
|
|
27190
26692
|
return () => {
|
|
27191
26693
|
childProcess.removeListener(type, callback);
|
|
27192
26694
|
};
|
|
27193
26695
|
};
|
|
27194
26696
|
|
|
26697
|
+
// https://github.com/avajs/ava/blob/576f534b345259055c95fa0c2b33bef10847a2af/lib/fork.js#L23
|
|
26698
|
+
const CONTROLLABLE_WORKER_THREAD_URL = new URL("./controllable_worker_thread.mjs", import.meta.url).href;
|
|
26699
|
+
const nodeWorkerThread = {
|
|
26700
|
+
type: "node",
|
|
26701
|
+
name: "node_worker_thread",
|
|
26702
|
+
version: process.version.slice(1)
|
|
26703
|
+
};
|
|
26704
|
+
|
|
26705
|
+
nodeWorkerThread.run = async ({
|
|
26706
|
+
signal = new AbortController().signal,
|
|
26707
|
+
// logger,
|
|
26708
|
+
rootDirectoryUrl,
|
|
26709
|
+
fileRelativeUrl,
|
|
26710
|
+
keepRunning,
|
|
26711
|
+
stopSignal,
|
|
26712
|
+
onConsole,
|
|
26713
|
+
coverageConfig,
|
|
26714
|
+
coverageMethodForNodeJs,
|
|
26715
|
+
coverageEnabled = false,
|
|
26716
|
+
collectPerformance,
|
|
26717
|
+
env,
|
|
26718
|
+
debugPort,
|
|
26719
|
+
debugMode,
|
|
26720
|
+
debugModeInheritBreak,
|
|
26721
|
+
inheritProcessEnv = true,
|
|
26722
|
+
commandLineOptions = []
|
|
26723
|
+
}) => {
|
|
26724
|
+
if (env !== undefined && typeof env !== "object") {
|
|
26725
|
+
throw new TypeError(`env must be an object, got ${env}`);
|
|
26726
|
+
}
|
|
26727
|
+
|
|
26728
|
+
env = { ...env,
|
|
26729
|
+
JSENV: true
|
|
26730
|
+
};
|
|
26731
|
+
|
|
26732
|
+
if (coverageMethodForNodeJs !== "NODE_V8_COVERAGE") {
|
|
26733
|
+
env.NODE_V8_COVERAGE = "";
|
|
26734
|
+
}
|
|
26735
|
+
|
|
26736
|
+
const workerThreadExecOptions = await createChildExecOptions({
|
|
26737
|
+
signal,
|
|
26738
|
+
debugPort,
|
|
26739
|
+
debugMode,
|
|
26740
|
+
debugModeInheritBreak
|
|
26741
|
+
});
|
|
26742
|
+
const execArgvForWorkerThread = ExecOptions.toExecArgv({ ...workerThreadExecOptions,
|
|
26743
|
+
...ExecOptions.fromExecArgv(commandLineOptions)
|
|
26744
|
+
});
|
|
26745
|
+
const envForWorkerThread = { ...(inheritProcessEnv ? process.env : {}),
|
|
26746
|
+
...env
|
|
26747
|
+
};
|
|
26748
|
+
const cleanupCallbackList = createCallbackListNotifiedOnce();
|
|
26749
|
+
|
|
26750
|
+
const cleanup = async reason => {
|
|
26751
|
+
await cleanupCallbackList.notify({
|
|
26752
|
+
reason
|
|
26753
|
+
});
|
|
26754
|
+
};
|
|
26755
|
+
|
|
26756
|
+
const actionOperation = Abort.startOperation();
|
|
26757
|
+
actionOperation.addAbortSignal(signal); // https://nodejs.org/api/worker_threads.html#new-workerfilename-options
|
|
26758
|
+
|
|
26759
|
+
const workerThread = new Worker(fileURLToPath(CONTROLLABLE_WORKER_THREAD_URL), {
|
|
26760
|
+
env: envForWorkerThread,
|
|
26761
|
+
execArgv: execArgvForWorkerThread,
|
|
26762
|
+
// workerData: { options },
|
|
26763
|
+
// trackUnmanagedFds: true,
|
|
26764
|
+
stdin: true,
|
|
26765
|
+
stdout: true,
|
|
26766
|
+
stderr: true
|
|
26767
|
+
});
|
|
26768
|
+
const removeOutputListener = installWorkerThreadOutputListener(workerThread, ({
|
|
26769
|
+
type,
|
|
26770
|
+
text
|
|
26771
|
+
}) => {
|
|
26772
|
+
onConsole({
|
|
26773
|
+
type,
|
|
26774
|
+
text
|
|
26775
|
+
});
|
|
26776
|
+
});
|
|
26777
|
+
const workerThreadReadyPromise = new Promise(resolve => {
|
|
26778
|
+
onceWorkerThreadMessage(workerThread, "ready", resolve);
|
|
26779
|
+
});
|
|
26780
|
+
const stop = memoize(async () => {
|
|
26781
|
+
await workerThreadReadyPromise;
|
|
26782
|
+
await workerThread.terminate();
|
|
26783
|
+
});
|
|
26784
|
+
const winnerPromise = new Promise(resolve => {
|
|
26785
|
+
raceCallbacks({
|
|
26786
|
+
aborted: cb => {
|
|
26787
|
+
return actionOperation.addAbortCallback(cb);
|
|
26788
|
+
},
|
|
26789
|
+
error: cb => {
|
|
26790
|
+
return onceWorkerThreadEvent(workerThread, "error", cb);
|
|
26791
|
+
},
|
|
26792
|
+
exit: cb => {
|
|
26793
|
+
return onceWorkerThreadEvent(workerThread, "exit", (code, signal) => {
|
|
26794
|
+
cb({
|
|
26795
|
+
code,
|
|
26796
|
+
signal
|
|
26797
|
+
});
|
|
26798
|
+
});
|
|
26799
|
+
},
|
|
26800
|
+
response: cb => {
|
|
26801
|
+
return onceWorkerThreadMessage(workerThread, "action-result", cb);
|
|
26802
|
+
}
|
|
26803
|
+
}, resolve);
|
|
26804
|
+
});
|
|
26805
|
+
|
|
26806
|
+
const getResult = async () => {
|
|
26807
|
+
actionOperation.throwIfAborted();
|
|
26808
|
+
await workerThreadReadyPromise;
|
|
26809
|
+
actionOperation.throwIfAborted();
|
|
26810
|
+
await sendToWorkerThread(workerThread, {
|
|
26811
|
+
type: "action",
|
|
26812
|
+
data: {
|
|
26813
|
+
actionType: "execute-using-dynamic-import",
|
|
26814
|
+
actionParams: {
|
|
26815
|
+
rootDirectoryUrl,
|
|
26816
|
+
fileUrl: new URL(fileRelativeUrl, rootDirectoryUrl).href,
|
|
26817
|
+
collectPerformance,
|
|
26818
|
+
coverageEnabled,
|
|
26819
|
+
coverageConfig,
|
|
26820
|
+
coverageMethodForNodeJs,
|
|
26821
|
+
exitAfterAction: true
|
|
26822
|
+
}
|
|
26823
|
+
}
|
|
26824
|
+
});
|
|
26825
|
+
const winner = await winnerPromise;
|
|
26826
|
+
|
|
26827
|
+
if (winner.name === "aborted") {
|
|
26828
|
+
return {
|
|
26829
|
+
status: "aborted"
|
|
26830
|
+
};
|
|
26831
|
+
}
|
|
26832
|
+
|
|
26833
|
+
if (winner.name === "error") {
|
|
26834
|
+
const error = winner.data;
|
|
26835
|
+
removeOutputListener();
|
|
26836
|
+
return {
|
|
26837
|
+
status: "errored",
|
|
26838
|
+
error
|
|
26839
|
+
};
|
|
26840
|
+
}
|
|
26841
|
+
|
|
26842
|
+
if (winner.name === "exit") {
|
|
26843
|
+
const {
|
|
26844
|
+
code
|
|
26845
|
+
} = winner.data;
|
|
26846
|
+
await cleanup("process exit");
|
|
26847
|
+
|
|
26848
|
+
if (code === 12) {
|
|
26849
|
+
return {
|
|
26850
|
+
status: "errored",
|
|
26851
|
+
error: new Error(`node process exited with 12 (the forked child process wanted to use a non-available port for debug)`)
|
|
26852
|
+
};
|
|
26853
|
+
}
|
|
26854
|
+
|
|
26855
|
+
if (code === null || code === 0 || code === EXIT_CODES.SIGINT || code === EXIT_CODES.SIGTERM || code === EXIT_CODES.SIGABORT) {
|
|
26856
|
+
return {
|
|
26857
|
+
status: "errored",
|
|
26858
|
+
error: new Error(`node worker thread exited during execution`)
|
|
26859
|
+
};
|
|
26860
|
+
} // process.exit(1) in child process or process.exitCode = 1 + process.exit()
|
|
26861
|
+
// means there was an error even if we don't know exactly what.
|
|
26862
|
+
|
|
26863
|
+
|
|
26864
|
+
return {
|
|
26865
|
+
status: "errored",
|
|
26866
|
+
error: new Error(`node worker thread exited with code ${code} during execution`)
|
|
26867
|
+
};
|
|
26868
|
+
}
|
|
26869
|
+
|
|
26870
|
+
const {
|
|
26871
|
+
status,
|
|
26872
|
+
value
|
|
26873
|
+
} = winner.data;
|
|
26874
|
+
|
|
26875
|
+
if (status === "action-failed") {
|
|
26876
|
+
return {
|
|
26877
|
+
status: "errored",
|
|
26878
|
+
error: value
|
|
26879
|
+
};
|
|
26880
|
+
}
|
|
26881
|
+
|
|
26882
|
+
const {
|
|
26883
|
+
namespace,
|
|
26884
|
+
performance,
|
|
26885
|
+
coverage
|
|
26886
|
+
} = value;
|
|
26887
|
+
return {
|
|
26888
|
+
status: "completed",
|
|
26889
|
+
namespace,
|
|
26890
|
+
performance,
|
|
26891
|
+
coverage
|
|
26892
|
+
};
|
|
26893
|
+
};
|
|
26894
|
+
|
|
26895
|
+
let result;
|
|
26896
|
+
|
|
26897
|
+
try {
|
|
26898
|
+
result = await getResult();
|
|
26899
|
+
} catch (e) {
|
|
26900
|
+
result = {
|
|
26901
|
+
status: "errored",
|
|
26902
|
+
error: e
|
|
26903
|
+
};
|
|
26904
|
+
}
|
|
26905
|
+
|
|
26906
|
+
if (keepRunning) {
|
|
26907
|
+
stopSignal.notify = stop;
|
|
26908
|
+
} else {
|
|
26909
|
+
await stop();
|
|
26910
|
+
}
|
|
26911
|
+
|
|
26912
|
+
await actionOperation.end();
|
|
26913
|
+
return result;
|
|
26914
|
+
};
|
|
26915
|
+
|
|
26916
|
+
const installWorkerThreadOutputListener = (workerThread, callback) => {
|
|
26917
|
+
// beware that we may receive ansi output here, should not be a problem but keep that in mind
|
|
26918
|
+
const stdoutDataCallback = chunk => {
|
|
26919
|
+
callback({
|
|
26920
|
+
type: "log",
|
|
26921
|
+
text: String(chunk)
|
|
26922
|
+
});
|
|
26923
|
+
};
|
|
26924
|
+
|
|
26925
|
+
workerThread.stdout.on("data", stdoutDataCallback);
|
|
26926
|
+
|
|
26927
|
+
const stdErrorDataCallback = chunk => {
|
|
26928
|
+
callback({
|
|
26929
|
+
type: "error",
|
|
26930
|
+
text: String(chunk)
|
|
26931
|
+
});
|
|
26932
|
+
};
|
|
26933
|
+
|
|
26934
|
+
workerThread.stderr.on("data", stdErrorDataCallback);
|
|
26935
|
+
return () => {
|
|
26936
|
+
workerThread.stdout.removeListener("data", stdoutDataCallback);
|
|
26937
|
+
workerThread.stderr.removeListener("data", stdoutDataCallback);
|
|
26938
|
+
};
|
|
26939
|
+
};
|
|
26940
|
+
|
|
26941
|
+
const sendToWorkerThread = (worker, {
|
|
26942
|
+
type,
|
|
26943
|
+
data
|
|
26944
|
+
}) => {
|
|
26945
|
+
worker.postMessage({
|
|
26946
|
+
jsenv: true,
|
|
26947
|
+
type,
|
|
26948
|
+
data
|
|
26949
|
+
});
|
|
26950
|
+
};
|
|
26951
|
+
|
|
26952
|
+
const onceWorkerThreadMessage = (workerThread, type, callback) => {
|
|
26953
|
+
const onmessage = message => {
|
|
26954
|
+
if (message && message.jsenv && message.type === type) {
|
|
26955
|
+
workerThread.removeListener("message", onmessage); // eslint-disable-next-line no-eval
|
|
26956
|
+
|
|
26957
|
+
callback(message.data ? eval(`(${message.data})`) : undefined);
|
|
26958
|
+
}
|
|
26959
|
+
};
|
|
26960
|
+
|
|
26961
|
+
workerThread.on("message", onmessage);
|
|
26962
|
+
return () => {
|
|
26963
|
+
workerThread.removeListener("message", onmessage);
|
|
26964
|
+
};
|
|
26965
|
+
};
|
|
26966
|
+
|
|
26967
|
+
const onceWorkerThreadEvent = (worker, type, callback) => {
|
|
26968
|
+
worker.once(type, callback);
|
|
26969
|
+
return () => {
|
|
26970
|
+
worker.removeListener(type, callback);
|
|
26971
|
+
};
|
|
26972
|
+
};
|
|
26973
|
+
|
|
27195
26974
|
const loadUrlGraph = async ({
|
|
27196
26975
|
operation,
|
|
27197
26976
|
urlGraph,
|
|
@@ -27261,7 +27040,6 @@ const loadUrlGraph = async ({
|
|
|
27261
27040
|
type,
|
|
27262
27041
|
specifier
|
|
27263
27042
|
});
|
|
27264
|
-
entryUrlInfo.data.isEntryPoint = true;
|
|
27265
27043
|
cook(entryUrlInfo, {
|
|
27266
27044
|
reference: entryReference
|
|
27267
27045
|
});
|
|
@@ -27635,7 +27413,7 @@ const determineDirectoryPath = ({
|
|
|
27635
27413
|
return parentDirectoryPath;
|
|
27636
27414
|
}
|
|
27637
27415
|
|
|
27638
|
-
if (urlInfo.
|
|
27416
|
+
if (urlInfo.isEntryPoint) {
|
|
27639
27417
|
return "";
|
|
27640
27418
|
}
|
|
27641
27419
|
|
|
@@ -27669,7 +27447,7 @@ const injectGlobalVersionMapping = async ({
|
|
|
27669
27447
|
versionMappings
|
|
27670
27448
|
}) => {
|
|
27671
27449
|
await Promise.all(GRAPH.map(finalGraph, async urlInfo => {
|
|
27672
|
-
if (urlInfo.
|
|
27450
|
+
if (urlInfo.isEntryPoint) {
|
|
27673
27451
|
await injectVersionMappings({
|
|
27674
27452
|
urlInfo,
|
|
27675
27453
|
kitchen: finalGraphKitchen,
|
|
@@ -27705,7 +27483,7 @@ const jsInjector = (urlInfo, {
|
|
|
27705
27483
|
}) => {
|
|
27706
27484
|
const magicSource = createMagicSource(urlInfo.content);
|
|
27707
27485
|
magicSource.prepend(generateClientCodeForVersionMappings(versionMappings, {
|
|
27708
|
-
globalName: urlInfo
|
|
27486
|
+
globalName: isWebWorkerUrlInfo(urlInfo) ? "self" : "window"
|
|
27709
27487
|
}));
|
|
27710
27488
|
return magicSource.toContentAndSourcemap();
|
|
27711
27489
|
};
|
|
@@ -27811,7 +27589,7 @@ const injectServiceWorkerUrls = async ({
|
|
|
27811
27589
|
lineBreakNormalization
|
|
27812
27590
|
}) => {
|
|
27813
27591
|
const serviceWorkerEntryUrlInfos = GRAPH.filter(finalGraph, finalUrlInfo => {
|
|
27814
|
-
return finalUrlInfo.subtype === "service_worker" && finalUrlInfo.
|
|
27592
|
+
return finalUrlInfo.subtype === "service_worker" && finalUrlInfo.isEntryPoint;
|
|
27815
27593
|
});
|
|
27816
27594
|
|
|
27817
27595
|
if (serviceWorkerEntryUrlInfos.length === 0) {
|
|
@@ -28227,7 +28005,7 @@ build ${entryPointKeys.length} entry points`);
|
|
|
28227
28005
|
};
|
|
28228
28006
|
|
|
28229
28007
|
GRAPH.forEach(rawGraph, rawUrlInfo => {
|
|
28230
|
-
if (rawUrlInfo.
|
|
28008
|
+
if (rawUrlInfo.isEntryPoint) {
|
|
28231
28009
|
addToBundlerIfAny(rawUrlInfo);
|
|
28232
28010
|
|
|
28233
28011
|
if (rawUrlInfo.type === "html") {
|
|
@@ -28305,6 +28083,7 @@ build ${entryPointKeys.length} entry points`);
|
|
|
28305
28083
|
const bundleUrlInfo = {
|
|
28306
28084
|
type,
|
|
28307
28085
|
subtype: rawUrlInfo ? rawUrlInfo.subtype : undefined,
|
|
28086
|
+
isEntryPoint: rawUrlInfo ? rawUrlInfo.isEntryPoint : undefined,
|
|
28308
28087
|
filename: rawUrlInfo ? rawUrlInfo.filename : undefined,
|
|
28309
28088
|
originalUrl: rawUrlInfo ? rawUrlInfo.originalUrl : undefined,
|
|
28310
28089
|
originalContent: rawUrlInfo ? rawUrlInfo.originalContent : undefined,
|
|
@@ -28442,9 +28221,8 @@ build ${entryPointKeys.length} entry points`);
|
|
|
28442
28221
|
|
|
28443
28222
|
const buildUrl = buildUrlsGenerator.generate(rawUrl, {
|
|
28444
28223
|
urlInfo: {
|
|
28445
|
-
data:
|
|
28446
|
-
|
|
28447
|
-
},
|
|
28224
|
+
data: reference.data,
|
|
28225
|
+
isEntryPoint: reference.isEntryPoint || isWebWorkerEntryPointReference(reference),
|
|
28448
28226
|
type: reference.expectedType,
|
|
28449
28227
|
subtype: reference.expectedSubtype,
|
|
28450
28228
|
filename: reference.filename
|
|
@@ -28736,7 +28514,7 @@ ${Object.keys(finalGraph.urlInfos).join("\n")}`);
|
|
|
28736
28514
|
// nothing uses this url anymore
|
|
28737
28515
|
// - versioning update inline content
|
|
28738
28516
|
// - file converted for import assertion of js_classic conversion
|
|
28739
|
-
if (!urlInfo.
|
|
28517
|
+
if (!urlInfo.isEntryPoint && urlInfo.type !== "sourcemap" && urlInfo.dependents.size === 0) {
|
|
28740
28518
|
cleanupActions.push(() => {
|
|
28741
28519
|
finalGraph.deleteUrlInfo(urlInfo.url);
|
|
28742
28520
|
});
|
|
@@ -28958,7 +28736,7 @@ const applyUrlVersioning = async ({
|
|
|
28958
28736
|
return;
|
|
28959
28737
|
}
|
|
28960
28738
|
|
|
28961
|
-
if (!urlInfo.
|
|
28739
|
+
if (!urlInfo.isEntryPoint && urlInfo.dependents.size === 0) {
|
|
28962
28740
|
return;
|
|
28963
28741
|
}
|
|
28964
28742
|
|
|
@@ -29204,7 +28982,7 @@ const assertEntryPoints = ({
|
|
|
29204
28982
|
};
|
|
29205
28983
|
|
|
29206
28984
|
const canUseVersionedUrl = urlInfo => {
|
|
29207
|
-
if (urlInfo.
|
|
28985
|
+
if (urlInfo.isEntryPoint) {
|
|
29208
28986
|
return false;
|
|
29209
28987
|
}
|
|
29210
28988
|
|
|
@@ -29212,10 +28990,6 @@ const canUseVersionedUrl = urlInfo => {
|
|
|
29212
28990
|
return false;
|
|
29213
28991
|
}
|
|
29214
28992
|
|
|
29215
|
-
if (urlInfo.subtype === "service_worker") {
|
|
29216
|
-
return !urlInfo.data.isWebWorkerEntryPoint;
|
|
29217
|
-
}
|
|
29218
|
-
|
|
29219
28993
|
return true;
|
|
29220
28994
|
};
|
|
29221
28995
|
|
|
@@ -29677,4 +29451,4 @@ const jsenvPluginInjectGlobals = urlAssociations => {
|
|
|
29677
29451
|
};
|
|
29678
29452
|
};
|
|
29679
29453
|
|
|
29680
|
-
export { build, chromium, chromiumIsolatedTab, execute, executeTestPlan, firefox, firefoxIsolatedTab, jsenvPluginInjectGlobals,
|
|
29454
|
+
export { build, chromium, chromiumIsolatedTab, execute, executeTestPlan, firefox, firefoxIsolatedTab, jsenvPluginInjectGlobals, nodeChildProcess, nodeWorkerThread, startBuildServer, startDevServer, webkit, webkitIsolatedTab };
|