@jsenv/core 27.0.2 → 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.
Files changed (35) hide show
  1. package/dist/controllable_child_process.mjs +139 -0
  2. package/dist/controllable_worker_thread.mjs +103 -0
  3. package/dist/js/execute_using_dynamic_import.js +169 -0
  4. package/dist/js/v8_coverage.js +539 -0
  5. package/dist/main.js +703 -827
  6. package/package.json +13 -12
  7. package/src/build/build.js +9 -12
  8. package/src/build/build_urls_generator.js +1 -1
  9. package/src/build/inject_global_version_mappings.js +3 -2
  10. package/src/build/inject_service_worker_urls.js +1 -2
  11. package/src/execute/run.js +50 -68
  12. package/src/execute/runtimes/browsers/from_playwright.js +13 -8
  13. package/src/execute/runtimes/node/{controllable_file.mjs → controllable_child_process.mjs} +18 -50
  14. package/src/execute/runtimes/node/controllable_worker_thread.mjs +103 -0
  15. package/src/execute/runtimes/node/execute_using_dynamic_import.js +49 -0
  16. package/src/execute/runtimes/node/exit_codes.js +9 -0
  17. package/src/execute/runtimes/node/{node_process.js → node_child_process.js} +56 -50
  18. package/src/execute/runtimes/node/node_worker_thread.js +268 -25
  19. package/src/execute/runtimes/node/profiler_v8_coverage.js +56 -0
  20. package/src/main.js +3 -1
  21. package/src/omega/kitchen.js +19 -6
  22. package/src/omega/server/file_service.js +2 -2
  23. package/src/omega/url_graph/url_graph_load.js +0 -1
  24. package/src/omega/url_graph/url_info_transformations.js +27 -14
  25. package/src/omega/url_graph.js +2 -0
  26. package/src/plugins/bundling/js_module/bundle_js_module.js +2 -5
  27. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +18 -15
  28. package/src/plugins/url_resolution/jsenv_plugin_url_resolution.js +2 -1
  29. package/src/test/coverage/report_to_coverage.js +16 -19
  30. package/src/test/coverage/v8_coverage.js +26 -0
  31. package/src/test/coverage/{v8_coverage_from_directory.js → v8_coverage_node_directory.js} +22 -26
  32. package/src/test/execute_plan.js +98 -91
  33. package/src/test/execute_test_plan.js +19 -13
  34. package/src/test/logs_file_execution.js +90 -13
  35. 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";
@@ -332,23 +332,27 @@ const canUseUnicode = isUnicodeSupported();
332
332
  const COMMAND_RAW = canUseUnicode ? `❯` : `>`;
333
333
  const OK_RAW = canUseUnicode ? `✔` : `√`;
334
334
  const FAILURE_RAW = canUseUnicode ? `✖` : `×`;
335
+ const DEBUG_RAW = canUseUnicode ? `◆` : `♦`;
335
336
  const INFO_RAW = canUseUnicode ? `ℹ` : `i`;
336
337
  const WARNING_RAW = canUseUnicode ? `⚠` : `‼`;
337
338
  const COMMAND = ANSI.color(COMMAND_RAW, ANSI.GREY); // ANSI_MAGENTA)
338
339
 
339
340
  const OK = ANSI.color(OK_RAW, ANSI.GREEN);
340
341
  const FAILURE = ANSI.color(FAILURE_RAW, ANSI.RED);
342
+ const DEBUG = ANSI.color(DEBUG_RAW, ANSI.GREY);
341
343
  const INFO = ANSI.color(INFO_RAW, ANSI.BLUE);
342
344
  const WARNING = ANSI.color(WARNING_RAW, ANSI.YELLOW);
343
345
  const UNICODE = {
344
346
  COMMAND,
345
347
  OK,
346
348
  FAILURE,
349
+ DEBUG,
347
350
  INFO,
348
351
  WARNING,
349
352
  COMMAND_RAW,
350
353
  OK_RAW,
351
354
  FAILURE_RAW,
355
+ DEBUG_RAW,
352
356
  INFO_RAW,
353
357
  WARNING_RAW,
354
358
  supported: canUseUnicode
@@ -5738,515 +5742,6 @@ const createEventHistory = limit => {
5738
5742
  };
5739
5743
  };
5740
5744
 
5741
- const assertUrlLike = (value, name = "url") => {
5742
- if (typeof value !== "string") {
5743
- throw new TypeError(`${name} must be a url string, got ${value}`);
5744
- }
5745
-
5746
- if (isWindowsPathnameSpecifier(value)) {
5747
- throw new TypeError(`${name} must be a url but looks like a windows pathname, got ${value}`);
5748
- }
5749
-
5750
- if (!hasScheme$1(value)) {
5751
- throw new TypeError(`${name} must be a url and no scheme found, got ${value}`);
5752
- }
5753
- };
5754
- const isPlainObject = value => {
5755
- if (value === null) {
5756
- return false;
5757
- }
5758
-
5759
- if (typeof value === "object") {
5760
- if (Array.isArray(value)) {
5761
- return false;
5762
- }
5763
-
5764
- return true;
5765
- }
5766
-
5767
- return false;
5768
- };
5769
-
5770
- const isWindowsPathnameSpecifier = specifier => {
5771
- const firstChar = specifier[0];
5772
- if (!/[a-zA-Z]/.test(firstChar)) return false;
5773
- const secondChar = specifier[1];
5774
- if (secondChar !== ":") return false;
5775
- const thirdChar = specifier[2];
5776
- return thirdChar === "/" || thirdChar === "\\";
5777
- };
5778
-
5779
- const hasScheme$1 = specifier => /^[a-zA-Z]+:/.test(specifier);
5780
-
5781
- const resolveAssociations = (associations, baseUrl) => {
5782
- assertUrlLike(baseUrl, "baseUrl");
5783
- const associationsResolved = {};
5784
- Object.keys(associations).forEach(key => {
5785
- const valueMap = associations[key];
5786
- const valueMapResolved = {};
5787
- Object.keys(valueMap).forEach(pattern => {
5788
- const value = valueMap[pattern];
5789
- const patternResolved = normalizeUrlPattern(pattern, baseUrl);
5790
- valueMapResolved[patternResolved] = value;
5791
- });
5792
- associationsResolved[key] = valueMapResolved;
5793
- });
5794
- return associationsResolved;
5795
- };
5796
-
5797
- const normalizeUrlPattern = (urlPattern, baseUrl) => {
5798
- // starts with a scheme
5799
- if (/^[a-zA-Z]{2,}:/.test(urlPattern)) {
5800
- return urlPattern;
5801
- }
5802
-
5803
- return String(new URL(urlPattern, baseUrl));
5804
- };
5805
-
5806
- const asFlatAssociations = associations => {
5807
- if (!isPlainObject(associations)) {
5808
- throw new TypeError(`associations must be a plain object, got ${associations}`);
5809
- }
5810
-
5811
- const flatAssociations = {};
5812
- Object.keys(associations).forEach(key => {
5813
- const valueMap = associations[key];
5814
-
5815
- if (!isPlainObject(valueMap)) {
5816
- throw new TypeError(`all associations value must be objects, found "${key}": ${valueMap}`);
5817
- }
5818
-
5819
- Object.keys(valueMap).forEach(pattern => {
5820
- const value = valueMap[pattern];
5821
- const previousValue = flatAssociations[pattern];
5822
- flatAssociations[pattern] = previousValue ? { ...previousValue,
5823
- [key]: value
5824
- } : {
5825
- [key]: value
5826
- };
5827
- });
5828
- });
5829
- return flatAssociations;
5830
- };
5831
-
5832
- /*
5833
- * Link to things doing pattern matching:
5834
- * https://git-scm.com/docs/gitignore
5835
- * https://github.com/kaelzhang/node-ignore
5836
- */
5837
- /** @module jsenv_url_meta **/
5838
-
5839
- /**
5840
- * An object representing the result of applying a pattern to an url
5841
- * @typedef {Object} MatchResult
5842
- * @property {boolean} matched Indicates if url matched pattern
5843
- * @property {number} patternIndex Index where pattern stopped matching url, otherwise pattern.length
5844
- * @property {number} urlIndex Index where url stopped matching pattern, otherwise url.length
5845
- * @property {Array} matchGroups Array of strings captured during pattern matching
5846
- */
5847
-
5848
- /**
5849
- * Apply a pattern to an url
5850
- * @param {Object} applyPatternMatchingParams
5851
- * @param {string} applyPatternMatchingParams.pattern "*", "**" and trailing slash have special meaning
5852
- * @param {string} applyPatternMatchingParams.url a string representing an url
5853
- * @return {MatchResult}
5854
- */
5855
-
5856
- const applyPatternMatching = ({
5857
- url,
5858
- pattern
5859
- }) => {
5860
- assertUrlLike(pattern, "pattern");
5861
- assertUrlLike(url, "url");
5862
- const {
5863
- matched,
5864
- patternIndex,
5865
- index,
5866
- groups
5867
- } = applyMatching(pattern, url);
5868
- const matchGroups = [];
5869
- let groupIndex = 0;
5870
- groups.forEach(group => {
5871
- if (group.name) {
5872
- matchGroups[group.name] = group.string;
5873
- } else {
5874
- matchGroups[groupIndex] = group.string;
5875
- groupIndex++;
5876
- }
5877
- });
5878
- return {
5879
- matched,
5880
- patternIndex,
5881
- urlIndex: index,
5882
- matchGroups
5883
- };
5884
- };
5885
-
5886
- const applyMatching = (pattern, string) => {
5887
- const groups = [];
5888
- let patternIndex = 0;
5889
- let index = 0;
5890
- let remainingPattern = pattern;
5891
- let remainingString = string;
5892
- let restoreIndexes = true;
5893
-
5894
- const consumePattern = count => {
5895
- const subpattern = remainingPattern.slice(0, count);
5896
- remainingPattern = remainingPattern.slice(count);
5897
- patternIndex += count;
5898
- return subpattern;
5899
- };
5900
-
5901
- const consumeString = count => {
5902
- const substring = remainingString.slice(0, count);
5903
- remainingString = remainingString.slice(count);
5904
- index += count;
5905
- return substring;
5906
- };
5907
-
5908
- const consumeRemainingString = () => {
5909
- return consumeString(remainingString.length);
5910
- };
5911
-
5912
- let matched;
5913
-
5914
- const iterate = () => {
5915
- const patternIndexBefore = patternIndex;
5916
- const indexBefore = index;
5917
- matched = matchOne();
5918
-
5919
- if (matched === undefined) {
5920
- consumePattern(1);
5921
- consumeString(1);
5922
- iterate();
5923
- return;
5924
- }
5925
-
5926
- if (matched === false && restoreIndexes) {
5927
- patternIndex = patternIndexBefore;
5928
- index = indexBefore;
5929
- }
5930
- };
5931
-
5932
- const matchOne = () => {
5933
- // pattern consumed and string consumed
5934
- if (remainingPattern === "" && remainingString === "") {
5935
- return true; // string fully matched pattern
5936
- } // pattern consumed, string not consumed
5937
-
5938
-
5939
- if (remainingPattern === "" && remainingString !== "") {
5940
- return false; // fails because string longer than expected
5941
- } // -- from this point pattern is not consumed --
5942
- // string consumed, pattern not consumed
5943
-
5944
-
5945
- if (remainingString === "") {
5946
- if (remainingPattern === "**") {
5947
- // trailing "**" is optional
5948
- consumePattern(2);
5949
- return true;
5950
- }
5951
-
5952
- if (remainingPattern === "*") {
5953
- groups.push({
5954
- string: ""
5955
- });
5956
- }
5957
-
5958
- return false; // fail because string shorter than expected
5959
- } // -- from this point pattern and string are not consumed --
5960
- // fast path trailing slash
5961
-
5962
-
5963
- if (remainingPattern === "/") {
5964
- if (remainingString[0] === "/") {
5965
- // trailing slash match remaining
5966
- consumePattern(1);
5967
- groups.push({
5968
- string: consumeRemainingString()
5969
- });
5970
- return true;
5971
- }
5972
-
5973
- return false;
5974
- } // fast path trailing '**'
5975
-
5976
-
5977
- if (remainingPattern === "**") {
5978
- consumePattern(2);
5979
- consumeRemainingString();
5980
- return true;
5981
- } // pattern leading **
5982
-
5983
-
5984
- if (remainingPattern.slice(0, 2) === "**") {
5985
- consumePattern(2); // consumes "**"
5986
-
5987
- if (remainingPattern[0] === "/") {
5988
- consumePattern(1); // consumes "/"
5989
- } // pattern ending with ** always match remaining string
5990
-
5991
-
5992
- if (remainingPattern === "") {
5993
- consumeRemainingString();
5994
- return true;
5995
- }
5996
-
5997
- const skipResult = skipUntilMatch({
5998
- pattern: remainingPattern,
5999
- string: remainingString,
6000
- canSkipSlash: true
6001
- });
6002
- groups.push(...skipResult.groups);
6003
- consumePattern(skipResult.patternIndex);
6004
- consumeRemainingString();
6005
- restoreIndexes = false;
6006
- return skipResult.matched;
6007
- }
6008
-
6009
- if (remainingPattern[0] === "*") {
6010
- consumePattern(1); // consumes "*"
6011
-
6012
- if (remainingPattern === "") {
6013
- // matches everything except '/'
6014
- const slashIndex = remainingString.indexOf("/");
6015
-
6016
- if (slashIndex === -1) {
6017
- groups.push({
6018
- string: consumeRemainingString()
6019
- });
6020
- return true;
6021
- }
6022
-
6023
- groups.push({
6024
- string: consumeString(slashIndex)
6025
- });
6026
- return false;
6027
- } // the next char must not the one expected by remainingPattern[0]
6028
- // because * is greedy and expect to skip at least one char
6029
-
6030
-
6031
- if (remainingPattern[0] === remainingString[0]) {
6032
- groups.push({
6033
- string: ""
6034
- });
6035
- patternIndex = patternIndex - 1;
6036
- return false;
6037
- }
6038
-
6039
- const skipResult = skipUntilMatch({
6040
- pattern: remainingPattern,
6041
- string: remainingString,
6042
- canSkipSlash: false
6043
- });
6044
- groups.push(skipResult.group, ...skipResult.groups);
6045
- consumePattern(skipResult.patternIndex);
6046
- consumeString(skipResult.index);
6047
- restoreIndexes = false;
6048
- return skipResult.matched;
6049
- }
6050
-
6051
- if (remainingPattern[0] !== remainingString[0]) {
6052
- return false;
6053
- }
6054
-
6055
- return undefined;
6056
- };
6057
-
6058
- iterate();
6059
- return {
6060
- matched,
6061
- patternIndex,
6062
- index,
6063
- groups
6064
- };
6065
- };
6066
-
6067
- const skipUntilMatch = ({
6068
- pattern,
6069
- string,
6070
- canSkipSlash
6071
- }) => {
6072
- let index = 0;
6073
- let remainingString = string;
6074
- let longestMatchRange = null;
6075
-
6076
- const tryToMatch = () => {
6077
- const matchAttempt = applyMatching(pattern, remainingString);
6078
-
6079
- if (matchAttempt.matched) {
6080
- return {
6081
- matched: true,
6082
- patternIndex: matchAttempt.patternIndex,
6083
- index: index + matchAttempt.index,
6084
- groups: matchAttempt.groups,
6085
- group: {
6086
- string: remainingString === "" ? string : string.slice(0, -remainingString.length)
6087
- }
6088
- };
6089
- }
6090
-
6091
- const matchAttemptIndex = matchAttempt.index;
6092
- const matchRange = {
6093
- patternIndex: matchAttempt.patternIndex,
6094
- index,
6095
- length: matchAttemptIndex,
6096
- groups: matchAttempt.groups
6097
- };
6098
-
6099
- if (!longestMatchRange || longestMatchRange.length < matchRange.length) {
6100
- longestMatchRange = matchRange;
6101
- }
6102
-
6103
- const nextIndex = matchAttemptIndex + 1;
6104
- const canSkip = nextIndex < remainingString.length && (canSkipSlash || remainingString[0] !== "/");
6105
-
6106
- if (canSkip) {
6107
- // search against the next unattempted string
6108
- index += nextIndex;
6109
- remainingString = remainingString.slice(nextIndex);
6110
- return tryToMatch();
6111
- }
6112
-
6113
- return {
6114
- matched: false,
6115
- patternIndex: longestMatchRange.patternIndex,
6116
- index: longestMatchRange.index + longestMatchRange.length,
6117
- groups: longestMatchRange.groups,
6118
- group: {
6119
- string: string.slice(0, longestMatchRange.index)
6120
- }
6121
- };
6122
- };
6123
-
6124
- return tryToMatch();
6125
- };
6126
-
6127
- const applyAssociations = ({
6128
- url,
6129
- associations
6130
- }) => {
6131
- assertUrlLike(url);
6132
- const flatAssociations = asFlatAssociations(associations);
6133
- return Object.keys(flatAssociations).reduce((previousValue, pattern) => {
6134
- const {
6135
- matched
6136
- } = applyPatternMatching({
6137
- pattern,
6138
- url
6139
- });
6140
-
6141
- if (matched) {
6142
- const value = flatAssociations[pattern];
6143
-
6144
- if (isPlainObject(previousValue) && isPlainObject(value)) {
6145
- return { ...previousValue,
6146
- ...value
6147
- };
6148
- }
6149
-
6150
- return value;
6151
- }
6152
-
6153
- return previousValue;
6154
- }, {});
6155
- };
6156
-
6157
- const applyAliases = ({
6158
- url,
6159
- aliases
6160
- }) => {
6161
- let aliasFullMatchResult;
6162
- const aliasMatchingKey = Object.keys(aliases).find(key => {
6163
- const aliasMatchResult = applyPatternMatching({
6164
- pattern: key,
6165
- url
6166
- });
6167
-
6168
- if (aliasMatchResult.matched) {
6169
- aliasFullMatchResult = aliasMatchResult;
6170
- return true;
6171
- }
6172
-
6173
- return false;
6174
- });
6175
-
6176
- if (!aliasMatchingKey) {
6177
- return url;
6178
- }
6179
-
6180
- const {
6181
- matchGroups
6182
- } = aliasFullMatchResult;
6183
- const alias = aliases[aliasMatchingKey];
6184
- const parts = alias.split("*");
6185
- const newUrl = parts.reduce((previous, value, index) => {
6186
- return `${previous}${value}${index === parts.length - 1 ? "" : matchGroups[index]}`;
6187
- }, "");
6188
- return newUrl;
6189
- };
6190
-
6191
- const urlChildMayMatch = ({
6192
- url,
6193
- associations,
6194
- predicate
6195
- }) => {
6196
- assertUrlLike(url, "url"); // the function was meants to be used on url ending with '/'
6197
-
6198
- if (!url.endsWith("/")) {
6199
- throw new Error(`url should end with /, got ${url}`);
6200
- }
6201
-
6202
- if (typeof predicate !== "function") {
6203
- throw new TypeError(`predicate must be a function, got ${predicate}`);
6204
- }
6205
-
6206
- const flatAssociations = asFlatAssociations(associations); // for full match we must create an object to allow pattern to override previous ones
6207
-
6208
- let fullMatchMeta = {};
6209
- let someFullMatch = false; // for partial match, any meta satisfying predicate will be valid because
6210
- // we don't know for sure if pattern will still match for a file inside pathname
6211
-
6212
- const partialMatchMetaArray = [];
6213
- Object.keys(flatAssociations).forEach(pattern => {
6214
- const value = flatAssociations[pattern];
6215
- const matchResult = applyPatternMatching({
6216
- pattern,
6217
- url
6218
- });
6219
-
6220
- if (matchResult.matched) {
6221
- someFullMatch = true;
6222
-
6223
- if (isPlainObject(fullMatchMeta) && isPlainObject(value)) {
6224
- fullMatchMeta = { ...fullMatchMeta,
6225
- ...value
6226
- };
6227
- } else {
6228
- fullMatchMeta = value;
6229
- }
6230
- } else if (someFullMatch === false && matchResult.urlIndex >= url.length) {
6231
- partialMatchMetaArray.push(value);
6232
- }
6233
- });
6234
-
6235
- if (someFullMatch) {
6236
- return Boolean(predicate(fullMatchMeta));
6237
- }
6238
-
6239
- return partialMatchMetaArray.some(partialMatchMeta => predicate(partialMatchMeta));
6240
- };
6241
-
6242
- const URL_META = {
6243
- resolveAssociations,
6244
- applyAssociations,
6245
- urlChildMayMatch,
6246
- applyPatternMatching,
6247
- applyAliases
6248
- };
6249
-
6250
5745
  const pluginRequestWaitingCheck = ({
6251
5746
  requestWaitingMs = 20000,
6252
5747
  requestWaitingCallback = ({
@@ -10067,7 +9562,10 @@ const jsenvPluginUrlResolution = () => {
10067
9562
  name: "jsenv:url_resolution",
10068
9563
  appliesDuring: "*",
10069
9564
  resolveUrl: {
9565
+ "http_request": urlResolver,
9566
+ // during dev
10070
9567
  "entry_point": urlResolver,
9568
+ // during build
10071
9569
  "link_href": urlResolver,
10072
9570
  "script_src": urlResolver,
10073
9571
  "a_href": urlResolver,
@@ -18022,16 +17520,16 @@ const jsenvPluginAsJsClassicConversion = ({
18022
17520
  return null;
18023
17521
  }
18024
17522
 
18025
- const isJsEntryPoint = // in general html files are entry points
18026
- // but during build js can be sepcified as an entry point
18027
- // (meaning there is no html file where we can inject systemjs)
18028
- // in that case we need to inject systemjs in the js file
18029
- originalUrlInfo.data.isEntryPoint || // In thoose case we need to inject systemjs the worker js file
18030
- originalUrlInfo.data.isWebWorkerEntryPoint; // if it's an entry point without dependency (it does not use import)
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)
18031
17530
  // then we can use UMD, otherwise we have to use systemjs
18032
17531
  // because it is imported by systemjs
18033
-
18034
- const jsClassicFormat = isJsEntryPoint && !originalUrlInfo.data.usesImport ? "umd" : "system";
17532
+ !originalUrlInfo.data.usesImport ? "umd" : "system";
18035
17533
  const {
18036
17534
  content,
18037
17535
  sourcemap
@@ -18039,7 +17537,6 @@ const jsenvPluginAsJsClassicConversion = ({
18039
17537
  systemJsInjection,
18040
17538
  systemJsClientFileUrl,
18041
17539
  urlInfo: originalUrlInfo,
18042
- isJsEntryPoint,
18043
17540
  jsClassicFormat
18044
17541
  });
18045
17542
  urlInfo.data.jsClassicFormat = jsClassicFormat;
@@ -18083,7 +17580,6 @@ const convertJsModuleToJsClassic = async ({
18083
17580
  systemJsInjection,
18084
17581
  systemJsClientFileUrl,
18085
17582
  urlInfo,
18086
- isJsEntryPoint,
18087
17583
  jsClassicFormat
18088
17584
  }) => {
18089
17585
  const {
@@ -18102,7 +17598,7 @@ const convertJsModuleToJsClassic = async ({
18102
17598
  let sourcemap = urlInfo.sourcemap;
18103
17599
  sourcemap = await composeTwoSourcemaps(sourcemap, map);
18104
17600
 
18105
- if (systemJsInjection && jsClassicFormat === "system" && isJsEntryPoint) {
17601
+ if (systemJsInjection && jsClassicFormat === "system" && urlInfo.isEntryPoint) {
18106
17602
  const magicSource = createMagicSource(code);
18107
17603
  const systemjsCode = readFileSync(systemJsClientFileUrl, {
18108
17604
  as: "string"
@@ -19796,7 +19292,7 @@ const rollupPluginJsenv = ({
19796
19292
  jsModuleUrlInfos.forEach(jsModuleUrlInfo => {
19797
19293
  const id = jsModuleUrlInfo.url;
19798
19294
 
19799
- if (jsModuleUrlInfo.data.isEntryPoint) {
19295
+ if (jsModuleUrlInfo.isEntryPoint) {
19800
19296
  emitChunk({
19801
19297
  id
19802
19298
  });
@@ -20079,7 +19575,7 @@ const willBeInsideJsDirectory = ({
20079
19575
  return true;
20080
19576
  }
20081
19577
 
20082
- if (!jsModuleUrlInfo.data.isEntryPoint && !jsModuleUrlInfo.data.isWebWorkerEntryPoint) {
19578
+ if (!jsModuleUrlInfo.isEntryPoint) {
20083
19579
  // not an entry point, jsenv will put it inside js/ directory
20084
19580
  return true;
20085
19581
  }
@@ -21439,6 +20935,7 @@ const createUrlInfo = url => {
21439
20935
  originalUrl: undefined,
21440
20936
  generatedUrl: null,
21441
20937
  filename: "",
20938
+ isEntryPoint: false,
21442
20939
  isInline: false,
21443
20940
  inlineUrlSite: null,
21444
20941
  shouldHandle: undefined,
@@ -21446,6 +20943,7 @@ const createUrlInfo = url => {
21446
20943
  content: undefined,
21447
20944
  sourcemap: null,
21448
20945
  sourcemapReference: null,
20946
+ sourcemapIsWrong: false,
21449
20947
  timing: {},
21450
20948
  headers: {}
21451
20949
  };
@@ -21891,7 +21389,8 @@ const createUrlInfoTransformer = ({
21891
21389
  type,
21892
21390
  contentType,
21893
21391
  content,
21894
- sourcemap
21392
+ sourcemap,
21393
+ sourcemapIsWrong
21895
21394
  } = transformations;
21896
21395
 
21897
21396
  if (type) {
@@ -21910,7 +21409,17 @@ const createUrlInfoTransformer = ({
21910
21409
  const sourcemapNormalized = normalizeSourcemap(urlInfo, sourcemap);
21911
21410
  const finalSourcemap = await composeTwoSourcemaps(urlInfo.sourcemap, sourcemapNormalized);
21912
21411
  const finalSourcemapNormalized = normalizeSourcemap(urlInfo, finalSourcemap);
21913
- urlInfo.sourcemap = finalSourcemapNormalized;
21412
+ urlInfo.sourcemap = finalSourcemapNormalized; // A plugin is allowed to modify url content
21413
+ // without returning a sourcemap
21414
+ // This is the case for preact and react plugins.
21415
+ // They are currently generating wrong source mappings
21416
+ // when used.
21417
+ // Generating the correct sourcemap in this situation
21418
+ // is a nightmare no-one could solve in years so
21419
+ // jsenv won't emit a warning and use the following strategy:
21420
+ // "no sourcemap is better than wrong sourcemap"
21421
+
21422
+ urlInfo.sourcemapIsWrong = sourcemapIsWrong;
21914
21423
  }
21915
21424
  };
21916
21425
 
@@ -21939,16 +21448,18 @@ const createUrlInfoTransformer = ({
21939
21448
 
21940
21449
  sourcemapUrlInfo.content = JSON.stringify(sourcemap, null, " ");
21941
21450
 
21942
- if (sourcemaps === "inline") {
21943
- sourcemapReference.generatedSpecifier = generateSourcemapDataUrl(sourcemap);
21944
- }
21451
+ if (!urlInfo.sourcemapIsWrong) {
21452
+ if (sourcemaps === "inline") {
21453
+ sourcemapReference.generatedSpecifier = generateSourcemapDataUrl(sourcemap);
21454
+ }
21945
21455
 
21946
- if (sourcemaps === "file" || sourcemaps === "inline") {
21947
- urlInfo.content = SOURCEMAP.writeComment({
21948
- contentType: urlInfo.contentType,
21949
- content: urlInfo.content,
21950
- specifier: sourcemaps === "file" && sourcemapsRelativeSources ? urlToRelativeUrl(sourcemapReference.url, urlInfo.url) : sourcemapReference.generatedSpecifier
21951
- });
21456
+ if (sourcemaps === "file" || sourcemaps === "inline") {
21457
+ urlInfo.content = SOURCEMAP.writeComment({
21458
+ contentType: urlInfo.contentType,
21459
+ content: urlInfo.content,
21460
+ specifier: sourcemaps === "file" && sourcemapsRelativeSources ? urlToRelativeUrl(sourcemapReference.url, urlInfo.url) : sourcemapReference.generatedSpecifier
21461
+ });
21462
+ }
21952
21463
  }
21953
21464
  } else if (urlInfo.sourcemapReference) {
21954
21465
  // in the end we don't use the sourcemap placeholder
@@ -22356,6 +21867,7 @@ const createKitchen = ({
22356
21867
  baseUrl,
22357
21868
  isOriginalPosition,
22358
21869
  shouldHandle,
21870
+ isEntryPoint = false,
22359
21871
  isInline = false,
22360
21872
  injected = false,
22361
21873
  isRessourceHint = false,
@@ -22393,6 +21905,7 @@ const createKitchen = ({
22393
21905
  baseUrl,
22394
21906
  isOriginalPosition,
22395
21907
  shouldHandle,
21908
+ isEntryPoint,
22396
21909
  isInline,
22397
21910
  injected,
22398
21911
  isRessourceHint,
@@ -22409,7 +21922,7 @@ const createKitchen = ({
22409
21922
  const mutateReference = (reference, newReference) => {
22410
21923
  reference.next = newReference;
22411
21924
  newReference.prev = reference;
22412
- newReference.original = reference.original || reference;
21925
+ newReference.original = reference.original || reference; // newReference.isEntryPoint = reference.isEntryPoint
22413
21926
  };
22414
21927
 
22415
21928
  const resolveReference = reference => {
@@ -22434,11 +21947,16 @@ const createKitchen = ({
22434
21947
  reference.url = normalizedReturnValue;
22435
21948
  mutateReference(previousReference, reference);
22436
21949
  });
22437
- const urlInfo = urlGraph.reuseOrCreateUrlInfo(reference.url);
22438
- applyReferenceEffectsOnUrlInfo(reference, urlInfo, kitchenContext);
22439
21950
  const referenceUrlObject = new URL(reference.url);
22440
21951
  reference.searchParams = referenceUrlObject.searchParams;
22441
- reference.generatedUrl = reference.url; // This hook must touch reference.generatedUrl, NOT 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
22442
21960
  // And this is because this hook inject query params used to:
22443
21961
  // - bypass browser cache (?v)
22444
21962
  // - convey information (?hmr)
@@ -22539,7 +22057,8 @@ const createKitchen = ({
22539
22057
  filename,
22540
22058
  status = 200,
22541
22059
  headers = {},
22542
- body
22060
+ body,
22061
+ isEntryPoint
22543
22062
  } = fetchUrlContentReturnValue;
22544
22063
 
22545
22064
  if (status !== 200) {
@@ -22575,6 +22094,10 @@ const createKitchen = ({
22575
22094
  Object.assign(urlInfo.data, data);
22576
22095
  }
22577
22096
 
22097
+ if (typeof isEntryPoint === "boolean") {
22098
+ urlInfo.isEntryPoint = isEntryPoint;
22099
+ }
22100
+
22578
22101
  if (filename) {
22579
22102
  urlInfo.filename = filename;
22580
22103
  }
@@ -22877,6 +22400,7 @@ const createKitchen = ({
22877
22400
 
22878
22401
  const prepareEntryPoint = params => {
22879
22402
  const entryReference = createReference(params);
22403
+ entryReference.isEntryPoint = true;
22880
22404
  const entryUrlInfo = resolveReference(entryReference);
22881
22405
  return [entryReference, entryUrlInfo];
22882
22406
  };
@@ -22984,6 +22508,11 @@ const applyReferenceEffectsOnUrlInfo = (reference, urlInfo, context) => {
22984
22508
  }
22985
22509
 
22986
22510
  urlInfo.originalUrl = urlInfo.originalUrl || reference.url;
22511
+
22512
+ if (reference.isEntryPoint || isWebWorkerEntryPointReference(reference)) {
22513
+ urlInfo.isEntryPoint = true;
22514
+ }
22515
+
22987
22516
  Object.assign(urlInfo.data, reference.data);
22988
22517
  Object.assign(urlInfo.timing, reference.timing);
22989
22518
 
@@ -23008,10 +22537,6 @@ const applyReferenceEffectsOnUrlInfo = (reference, urlInfo, context) => {
23008
22537
  urlInfo.originalContent = context === "build" ? urlInfo.originalContent === undefined ? reference.content : urlInfo.originalContent : reference.content;
23009
22538
  urlInfo.content = reference.content;
23010
22539
  }
23011
-
23012
- if (isWebWorkerEntryPointReference(reference)) {
23013
- urlInfo.data.isWebWorkerEntryPoint = true;
23014
- }
23015
22540
  };
23016
22541
 
23017
22542
  const adjustUrlSite = (urlInfo, {
@@ -23294,10 +22819,10 @@ const createFileService = ({
23294
22819
  }
23295
22820
 
23296
22821
  if (!reference) {
23297
- const entryPoint = kitchen.prepareEntryPoint({
22822
+ const entryPoint = kitchen.injectReference({
23298
22823
  trace: parentUrl || rootDirectoryUrl,
23299
22824
  parentUrl: parentUrl || rootDirectoryUrl,
23300
- type: "entry_point",
22825
+ type: "http_request",
23301
22826
  specifier: request.ressource
23302
22827
  });
23303
22828
  reference = entryPoint[0];
@@ -24050,23 +23575,31 @@ const babelPluginInstrument = (api, {
24050
23575
  };
24051
23576
  };
24052
23577
 
24053
- const visitNodeV8Directory = async ({
23578
+ const readNodeV8CoverageDirectory = async ({
24054
23579
  logger,
24055
23580
  signal,
24056
- NODE_V8_COVERAGE,
24057
23581
  onV8Coverage,
24058
23582
  maxMsWaitingForNodeToWriteCoverageFile = 2000
24059
23583
  }) => {
23584
+ const NODE_V8_COVERAGE = process.env.NODE_V8_COVERAGE;
24060
23585
  const operation = Abort.startOperation();
24061
23586
  operation.addAbortSignal(signal);
23587
+ let timeSpentTrying = 0;
24062
23588
 
24063
23589
  const tryReadDirectory = async () => {
24064
- const dirContent = await readDirectory(NODE_V8_COVERAGE);
23590
+ const dirContent = readdirSync(NODE_V8_COVERAGE);
24065
23591
 
24066
23592
  if (dirContent.length > 0) {
24067
23593
  return dirContent;
24068
23594
  }
24069
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
+
24070
23603
  logger.warn(`v8 coverage directory is empty at ${NODE_V8_COVERAGE}`);
24071
23604
  return dirContent;
24072
23605
  };
@@ -24078,17 +23611,16 @@ const visitNodeV8Directory = async ({
24078
23611
  await dirContent.reduce(async (previous, dirEntry) => {
24079
23612
  operation.throwIfAborted();
24080
23613
  await previous;
24081
- const dirEntryUrl = resolveUrl$1(dirEntry, coverageDirectoryUrl);
23614
+ const dirEntryUrl = new URL(dirEntry, coverageDirectoryUrl);
24082
23615
 
24083
- const tryReadJsonFile = async (timeSpentTrying = 0) => {
24084
- const fileContent = await readFile(dirEntryUrl, {
24085
- as: "string"
24086
- });
23616
+ const tryReadJsonFile = async () => {
23617
+ const fileContent = String(readFileSync$1(dirEntryUrl));
24087
23618
 
24088
23619
  if (fileContent === "") {
24089
- if (timeSpentTrying < 400) {
23620
+ if (timeSpentTrying < maxMsWaitingForNodeToWriteCoverageFile) {
24090
23621
  await new Promise(resolve => setTimeout(resolve, 200));
24091
- return tryReadJsonFile(timeSpentTrying + 200);
23622
+ timeSpentTrying += 200;
23623
+ return tryReadJsonFile();
24092
23624
  }
24093
23625
 
24094
23626
  console.warn(`Coverage JSON file is empty at ${dirEntryUrl}`);
@@ -24101,7 +23633,8 @@ const visitNodeV8Directory = async ({
24101
23633
  } catch (e) {
24102
23634
  if (timeSpentTrying < maxMsWaitingForNodeToWriteCoverageFile) {
24103
23635
  await new Promise(resolve => setTimeout(resolve, 200));
24104
- return tryReadJsonFile(timeSpentTrying + 200);
23636
+ timeSpentTrying += 200;
23637
+ return tryReadJsonFile();
24105
23638
  }
24106
23639
 
24107
23640
  console.warn(createDetailedMessage$1(`Error while reading coverage file`, {
@@ -24115,21 +23648,13 @@ const visitNodeV8Directory = async ({
24115
23648
  const fileContent = await tryReadJsonFile();
24116
23649
 
24117
23650
  if (fileContent) {
24118
- onV8Coverage(fileContent);
23651
+ await onV8Coverage(fileContent);
24119
23652
  }
24120
23653
  }, Promise.resolve());
24121
23654
  } finally {
24122
23655
  await operation.end();
24123
23656
  }
24124
23657
  };
24125
- const filterV8Coverage = (v8Coverage, {
24126
- urlShouldBeCovered
24127
- }) => {
24128
- const v8CoverageFiltered = { ...v8Coverage,
24129
- result: v8Coverage.result.filter(fileReport => urlShouldBeCovered(fileReport.url))
24130
- };
24131
- return v8CoverageFiltered;
24132
- };
24133
23658
 
24134
23659
  const composeTwoV8Coverages = (firstV8Coverage, secondV8Coverage) => {
24135
23660
  if (secondV8Coverage.result.length === 0) {
@@ -24430,8 +23955,7 @@ const reportToCoverage = async (report, {
24430
23955
  rootDirectoryUrl,
24431
23956
  coverageConfig,
24432
23957
  coverageIncludeMissing,
24433
- urlShouldBeCovered,
24434
- coverageForceIstanbul,
23958
+ coverageMethodForNodeJs,
24435
23959
  coverageV8ConflictWarning
24436
23960
  }) => {
24437
23961
  // collect v8 and istanbul coverage from executions
@@ -24460,20 +23984,20 @@ const reportToCoverage = async (report, {
24460
23984
  // in any scenario we are fine because
24461
23985
  // coverDescription will generate empty coverage for files
24462
23986
  // that were suppose to be coverage but were not.
24463
- if (executionResult.status === "completed" && executionResult.runtimeName !== "node" && !process.env.NODE_V8_COVERAGE) {
24464
- logger.warn(`No execution.coverageFileUrl from execution named "${executionName}" of ${file}`);
23987
+ if (executionResult.status === "completed" && executionResult.type === "node" && coverageMethodForNodeJs !== "NODE_V8_COVERAGE") {
23988
+ logger.warn(`No "coverageFileUrl" from execution named "${executionName}" of ${file}`);
24465
23989
  }
24466
23990
  }
24467
23991
  });
24468
23992
 
24469
- if (!coverageForceIstanbul && process.env.NODE_V8_COVERAGE) {
24470
- await visitNodeV8Directory({
23993
+ if (coverageMethodForNodeJs === "NODE_V8_COVERAGE") {
23994
+ await readNodeV8CoverageDirectory({
24471
23995
  logger,
24472
23996
  signal,
24473
- NODE_V8_COVERAGE: process.env.NODE_V8_COVERAGE,
24474
- onV8Coverage: nodeV8Coverage => {
24475
- const nodeV8CoverageLight = filterV8Coverage(nodeV8Coverage, {
24476
- urlShouldBeCovered
23997
+ onV8Coverage: async nodeV8Coverage => {
23998
+ const nodeV8CoverageLight = await filterV8Coverage(nodeV8Coverage, {
23999
+ rootDirectoryUrl,
24000
+ coverageConfig
24477
24001
  });
24478
24002
  v8Coverage = v8Coverage ? composeTwoV8Coverages(v8Coverage, nodeV8CoverageLight) : nodeV8CoverageLight;
24479
24003
  }
@@ -24552,9 +24076,7 @@ const getCoverageFromReport = async ({
24552
24076
  return;
24553
24077
  }
24554
24078
 
24555
- const executionCoverage = await readFile(coverageFileUrl, {
24556
- as: "json"
24557
- });
24079
+ const executionCoverage = JSON.parse(String(readFileSync$1(new URL(coverageFileUrl))));
24558
24080
 
24559
24081
  if (isV8Coverage(executionCoverage)) {
24560
24082
  v8Coverage = v8Coverage ? composeTwoV8Coverages(v8Coverage, executionCoverage) : executionCoverage;
@@ -24581,21 +24103,20 @@ const run = async ({
24581
24103
  keepRunning = false,
24582
24104
  mirrorConsole = false,
24583
24105
  collectConsole = false,
24584
- collectCoverage = false,
24106
+ coverageEnabled = false,
24585
24107
  coverageTempDirectoryUrl,
24586
24108
  collectPerformance = false,
24587
24109
  runtime,
24588
24110
  runtimeParams
24589
24111
  }) => {
24112
+ let result = {};
24113
+ const callbacks = [];
24590
24114
  const onConsoleRef = {
24591
24115
  current: () => {}
24592
24116
  };
24593
24117
  const stopSignal = {
24594
24118
  notify: () => {}
24595
24119
  };
24596
-
24597
- let resultTransformer = result => result;
24598
-
24599
24120
  const runtimeLabel = `${runtime.name}/${runtime.version}`;
24600
24121
  const runOperation = Abort.startOperation();
24601
24122
  runOperation.addAbortSignal(signal);
@@ -24604,21 +24125,21 @@ const run = async ({
24604
24125
  // when keepRunning is true
24605
24126
  !keepRunning && typeof allocatedMs === "number" && allocatedMs !== Infinity) {
24606
24127
  const timeoutAbortSource = runOperation.timeout(allocatedMs);
24607
- resultTransformer = composeTransformer$1(resultTransformer, result => {
24128
+ callbacks.push(() => {
24608
24129
  if (result.status === "errored" && Abort.isAbortError(result.error) && timeoutAbortSource.signal.aborted) {
24609
- return createTimedoutResult();
24130
+ result = {
24131
+ status: "timedout"
24132
+ };
24610
24133
  }
24611
-
24612
- return result;
24613
24134
  });
24614
24135
  }
24615
24136
 
24616
- resultTransformer = composeTransformer$1(resultTransformer, result => {
24137
+ callbacks.push(() => {
24617
24138
  if (result.status === "errored" && Abort.isAbortError(result.error)) {
24618
- return createAbortedResult();
24139
+ result = {
24140
+ status: "aborted"
24141
+ };
24619
24142
  }
24620
-
24621
- return result;
24622
24143
  });
24623
24144
  const consoleCalls = [];
24624
24145
 
@@ -24643,44 +24164,14 @@ const run = async ({
24643
24164
  };
24644
24165
 
24645
24166
  if (collectConsole) {
24646
- resultTransformer = composeTransformer$1(resultTransformer, result => {
24167
+ callbacks.push(() => {
24647
24168
  result.consoleCalls = consoleCalls;
24648
- return result;
24649
- });
24650
- }
24651
-
24652
- if (collectCoverage) {
24653
- resultTransformer = composeTransformer$1(resultTransformer, async result => {
24654
- // we do not keep coverage in memory, it can grow very big
24655
- // instead we store it on the filesystem
24656
- // and they can be read later at "coverageFileUrl"
24657
- const {
24658
- coverage
24659
- } = result;
24660
-
24661
- if (coverage) {
24662
- const coverageFileUrl = resolveUrl$1(`./${runtime.name}/${cuid()}`, coverageTempDirectoryUrl);
24663
- await writeFile(coverageFileUrl, JSON.stringify(coverage, null, " "));
24664
- result.coverageFileUrl = coverageFileUrl;
24665
- delete result.coverage;
24666
- }
24667
-
24668
- return result;
24669
- });
24670
- } else {
24671
- resultTransformer = composeTransformer$1(resultTransformer, result => {
24672
- // as collectCoverage is disabled
24673
- // executionResult.coverage is undefined or {}
24674
- // we delete it just to have a cleaner object
24675
- delete result.coverage;
24676
- return result;
24677
24169
  });
24678
24170
  }
24679
24171
 
24680
24172
  const startMs = Date.now();
24681
- resultTransformer = composeTransformer$1(resultTransformer, result => {
24173
+ callbacks.push(() => {
24682
24174
  result.duration = Date.now() - startMs;
24683
- return result;
24684
24175
  });
24685
24176
 
24686
24177
  try {
@@ -24696,7 +24187,7 @@ const run = async ({
24696
24187
  },
24697
24188
  runned: async cb => {
24698
24189
  try {
24699
- const result = await runtime.run({
24190
+ const runResult = await runtime.run({
24700
24191
  signal: runOperation.signal,
24701
24192
  logger,
24702
24193
  ...runtimeParams,
@@ -24705,7 +24196,7 @@ const run = async ({
24705
24196
  stopSignal,
24706
24197
  onConsole: log => onConsoleRef.current(log)
24707
24198
  });
24708
- cb(result);
24199
+ cb(runResult);
24709
24200
  } catch (e) {
24710
24201
  cb({
24711
24202
  status: "errored",
@@ -24721,40 +24212,55 @@ const run = async ({
24721
24212
  runOperation.throwIfAborted();
24722
24213
  }
24723
24214
 
24724
- let result = winner.data;
24725
- result = await resultTransformer(result);
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
+ });
24726
24249
  return result;
24727
24250
  } catch (e) {
24728
- let result = {
24251
+ result = {
24729
24252
  status: "errored",
24730
24253
  error: e
24731
24254
  };
24732
- result = await resultTransformer(result);
24255
+ callbacks.forEach(callback => {
24256
+ callback();
24257
+ });
24733
24258
  return result;
24734
24259
  } finally {
24735
24260
  await runOperation.end();
24736
24261
  }
24737
24262
  };
24738
24263
 
24739
- const composeTransformer$1 = (previousTransformer, transformer) => {
24740
- return async value => {
24741
- const transformedValue = await previousTransformer(value);
24742
- return transformer(transformedValue);
24743
- };
24744
- };
24745
-
24746
- const createAbortedResult = () => {
24747
- return {
24748
- status: "aborted"
24749
- };
24750
- };
24751
-
24752
- const createTimedoutResult = () => {
24753
- return {
24754
- status: "timedout"
24755
- };
24756
- };
24757
-
24758
24264
  const ensureGlobalGc = () => {
24759
24265
  if (!global.gc) {
24760
24266
  v8.setFlagsFromString("--expose_gc");
@@ -24839,6 +24345,8 @@ const createExecutionLog = ({
24839
24345
  }, {
24840
24346
  completedExecutionLogAbbreviation,
24841
24347
  counters,
24348
+ logRuntime,
24349
+ logEachDuration,
24842
24350
  timeEllapsed,
24843
24351
  memoryHeap
24844
24352
  }) => {
@@ -24871,8 +24379,12 @@ const createExecutionLog = ({
24871
24379
  label: `${description}${summary}`,
24872
24380
  details: {
24873
24381
  file: fileRelativeUrl,
24874
- runtime: `${runtimeName}/${runtimeVersion}`,
24875
- duration: status === "executing" ? msAsEllapsedTime(Date.now() - startMs) : msAsDuration(endMs - startMs),
24382
+ ...(logRuntime ? {
24383
+ runtime: `${runtimeName}/${runtimeVersion}`
24384
+ } : {}),
24385
+ ...(logEachDuration ? {
24386
+ duration: status === "executing" ? msAsEllapsedTime(Date.now() - startMs) : msAsDuration(endMs - startMs)
24387
+ } : {}),
24876
24388
  ...(error ? {
24877
24389
  error: error.stack || error.message || error
24878
24390
  } : {})
@@ -25026,22 +24538,93 @@ const descriptionFormatters = {
25026
24538
  };
25027
24539
 
25028
24540
  const formatConsoleCalls = consoleCalls => {
25029
- const consoleOutput = consoleCalls.reduce((previous, {
25030
- text
25031
- }) => {
25032
- return `${previous}${text}`;
25033
- }, "");
25034
- const consoleOutputTrimmed = consoleOutput.trim();
25035
-
25036
- if (consoleOutputTrimmed === "") {
24541
+ if (consoleCalls.length === 0) {
25037
24542
  return "";
25038
24543
  }
25039
24544
 
25040
- return `${ANSI.color(`-------- console output --------`, ANSI.GREY)}
25041
- ${consoleOutputTrimmed}
24545
+ const repartition = {
24546
+ debug: 0,
24547
+ info: 0,
24548
+ warning: 0,
24549
+ error: 0,
24550
+ log: 0
24551
+ };
24552
+ let consoleOutput = ``;
24553
+ consoleCalls.forEach(consoleCall => {
24554
+ repartition[consoleCall.type]++;
24555
+ const text = consoleCall.text;
24556
+ const textFormatted = prefixFirstAndIndentRemainingLines({
24557
+ prefix: CONSOLE_ICONS[consoleCall.type],
24558
+ text,
24559
+ trimLastLine: consoleCall === consoleCalls[consoleCalls.length - 1]
24560
+ });
24561
+ consoleOutput += textFormatted;
24562
+ });
24563
+ return `${ANSI.color(`-------- ${formatConsoleSummary(repartition)} --------`, ANSI.GREY)}
24564
+ ${consoleOutput}
25042
24565
  ${ANSI.color(`-------------------------`, ANSI.GREY)}`;
25043
24566
  };
25044
24567
 
24568
+ const CONSOLE_ICONS = {
24569
+ debug: UNICODE.DEBUG,
24570
+ info: UNICODE.INFO,
24571
+ warning: UNICODE.WARNING,
24572
+ error: UNICODE.FAILURE,
24573
+ log: " "
24574
+ };
24575
+
24576
+ const formatConsoleSummary = repartition => {
24577
+ const {
24578
+ debug,
24579
+ info,
24580
+ warning,
24581
+ error
24582
+ } = repartition;
24583
+ const parts = [];
24584
+
24585
+ if (error) {
24586
+ parts.push(`${CONSOLE_ICONS.error} ${error}`);
24587
+ }
24588
+
24589
+ if (warning) {
24590
+ parts.push(`${CONSOLE_ICONS.warning} ${warning}`);
24591
+ }
24592
+
24593
+ if (info) {
24594
+ parts.push(`${CONSOLE_ICONS.info} ${info}`);
24595
+ }
24596
+
24597
+ if (debug) {
24598
+ parts.push(`${CONSOLE_ICONS.debug} ${debug}`);
24599
+ }
24600
+
24601
+ if (parts.length === 0) {
24602
+ return `console`;
24603
+ }
24604
+
24605
+ return `console (${parts.join(" ")})`;
24606
+ };
24607
+
24608
+ const prefixFirstAndIndentRemainingLines = ({
24609
+ prefix,
24610
+ text,
24611
+ trimLastLine
24612
+ }) => {
24613
+ const lines = text.split(/\r?\n/);
24614
+ const firstLine = lines.shift();
24615
+ let result = `${prefix} ${firstLine}`;
24616
+ let i = 0;
24617
+ const indentation = ` `;
24618
+
24619
+ while (i < lines.length) {
24620
+ const line = lines[i].trim();
24621
+ i++;
24622
+ result += line.length ? `\n${indentation}${line}` : trimLastLine && i === lines.length ? "" : `\n`;
24623
+ }
24624
+
24625
+ return result;
24626
+ };
24627
+
25045
24628
  const formatExecution = ({
25046
24629
  label,
25047
24630
  details = {},
@@ -25066,6 +24649,8 @@ const executePlan = async (plan, {
25066
24649
  signal,
25067
24650
  handleSIGINT,
25068
24651
  logger,
24652
+ logRuntime,
24653
+ logEachDuration,
25069
24654
  logSummary,
25070
24655
  logTimeUsage,
25071
24656
  logMemoryHeapUsage,
@@ -25079,10 +24664,11 @@ const executePlan = async (plan, {
25079
24664
  failFast,
25080
24665
  gcBetweenExecutions,
25081
24666
  cooldownBetweenExecutions,
25082
- coverage,
24667
+ coverageEnabled,
25083
24668
  coverageConfig,
25084
24669
  coverageIncludeMissing,
25085
- coverageForceIstanbul,
24670
+ coverageMethodForBrowsers,
24671
+ coverageMethodForNodeJs,
25086
24672
  coverageV8ConflictWarning,
25087
24673
  coverageTempDirectoryRelativeUrl,
25088
24674
  scenario,
@@ -25100,10 +24686,14 @@ const executePlan = async (plan, {
25100
24686
  beforeExecutionCallback = () => {},
25101
24687
  afterExecutionCallback = () => {}
25102
24688
  } = {}) => {
24689
+ const executePlanReturnValue = {};
24690
+ const report = {};
24691
+ const callbacks = [];
25103
24692
  const stopAfterAllSignal = {
25104
24693
  notify: () => {}
25105
24694
  };
25106
24695
  let someNeedsServer = false;
24696
+ let someNodeRuntime = false;
25107
24697
  const runtimes = {};
25108
24698
  Object.keys(plan).forEach(filePattern => {
25109
24699
  const filePlan = plan[filePattern];
@@ -25119,6 +24709,10 @@ const executePlan = async (plan, {
25119
24709
  if (runtime.needsServer) {
25120
24710
  someNeedsServer = true;
25121
24711
  }
24712
+
24713
+ if (runtime.type === "node") {
24714
+ someNodeRuntime = true;
24715
+ }
25122
24716
  }
25123
24717
  });
25124
24718
  });
@@ -25146,10 +24740,67 @@ const executePlan = async (plan, {
25146
24740
  }
25147
24741
 
25148
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
+
25149
24798
  let runtimeParams = {
25150
24799
  rootDirectoryUrl,
25151
- collectCoverage: coverage,
25152
- coverageForceIstanbul,
24800
+ coverageEnabled,
24801
+ coverageConfig,
24802
+ coverageMethodForBrowsers,
24803
+ coverageMethodForNodeJs,
25153
24804
  stopAfterAllSignal
25154
24805
  };
25155
24806
 
@@ -25176,7 +24827,7 @@ const executePlan = async (plan, {
25176
24827
  getCustomBabelPlugins: ({
25177
24828
  clientRuntimeCompat
25178
24829
  }) => {
25179
- if (coverage && Object.keys(clientRuntimeCompat)[0] !== "chrome") {
24830
+ if (coverageEnabled && Object.keys(clientRuntimeCompat)[0] !== "chrome") {
25180
24831
  return {
25181
24832
  "transform-instrument": [babelPluginInstrument, {
25182
24833
  rootDirectoryUrl,
@@ -25232,79 +24883,7 @@ const executePlan = async (plan, {
25232
24883
  // so we enable spinner only when !process.exitCode (no error so far)
25233
24884
  process.exitCode !== 1;
25234
24885
  const startMs = Date.now();
25235
- const report = {};
25236
24886
  let rawOutput = "";
25237
-
25238
- let transformReturnValue = value => value;
25239
-
25240
- if (gcBetweenExecutions) {
25241
- ensureGlobalGc();
25242
- }
25243
-
25244
- const coverageTempDirectoryUrl = new URL(coverageTempDirectoryRelativeUrl, rootDirectoryUrl).href;
25245
-
25246
- if (coverage) {
25247
- const associations = URL_META.resolveAssociations({
25248
- cover: coverageConfig
25249
- }, rootDirectoryUrl);
25250
-
25251
- const urlShouldBeCovered = url => {
25252
- const {
25253
- cover
25254
- } = URL_META.applyAssociations({
25255
- url: new URL(url, rootDirectoryUrl).href,
25256
- associations
25257
- });
25258
- return cover;
25259
- };
25260
-
25261
- runtimeParams.urlShouldBeCovered = urlShouldBeCovered; // in case runned multiple times, we don't want to keep writing lot of files in this directory
25262
-
25263
- if (!process.env.NODE_V8_COVERAGE) {
25264
- await ensureEmptyDirectory(coverageTempDirectoryUrl);
25265
- }
25266
-
25267
- if (runtimes.node) {
25268
- // v8 coverage is written in a directoy and auto propagate to subprocesses
25269
- // through process.env.NODE_V8_COVERAGE.
25270
- if (!coverageForceIstanbul && !process.env.NODE_V8_COVERAGE) {
25271
- const v8CoverageDirectory = new URL(`./node_v8/${cuid()}`, coverageTempDirectoryUrl).href;
25272
- await writeDirectory(v8CoverageDirectory, {
25273
- allowUseless: true
25274
- });
25275
- process.env.NODE_V8_COVERAGE = urlToFileSystemPath(v8CoverageDirectory);
25276
- }
25277
- }
25278
-
25279
- transformReturnValue = async value => {
25280
- if (multipleExecutionsOperation.signal.aborted) {
25281
- // don't try to do the coverage stuff
25282
- return value;
25283
- }
25284
-
25285
- try {
25286
- value.coverage = await reportToCoverage(value.report, {
25287
- signal: multipleExecutionsOperation.signal,
25288
- logger,
25289
- rootDirectoryUrl,
25290
- coverageConfig,
25291
- coverageIncludeMissing,
25292
- coverageForceIstanbul,
25293
- urlShouldBeCovered,
25294
- coverageV8ConflictWarning
25295
- });
25296
- } catch (e) {
25297
- if (Abort.isAbortError(e)) {
25298
- return value;
25299
- }
25300
-
25301
- throw e;
25302
- }
25303
-
25304
- return value;
25305
- };
25306
- }
25307
-
25308
24887
  logger.info("");
25309
24888
  let executionLog = createLog({
25310
24889
  newLine: ""
@@ -25329,6 +24908,7 @@ const executePlan = async (plan, {
25329
24908
  fileRelativeUrl,
25330
24909
  runtime
25331
24910
  } = paramsFromStep;
24911
+ const runtimeType = runtime.type;
25332
24912
  const runtimeName = runtime.name;
25333
24913
  const runtimeVersion = runtime.version;
25334
24914
  const executionParams = {
@@ -25344,6 +24924,7 @@ const executePlan = async (plan, {
25344
24924
  };
25345
24925
  const beforeExecutionInfo = {
25346
24926
  fileRelativeUrl,
24927
+ runtimeType,
25347
24928
  runtimeName,
25348
24929
  runtimeVersion,
25349
24930
  executionIndex,
@@ -25361,6 +24942,8 @@ const executePlan = async (plan, {
25361
24942
  render: () => {
25362
24943
  return createExecutionLog(beforeExecutionInfo, {
25363
24944
  counters,
24945
+ logRuntime,
24946
+ logEachDuration,
25364
24947
  ...(logTimeUsage ? {
25365
24948
  timeEllapsed: Date.now() - startMs
25366
24949
  } : {}),
@@ -25385,7 +24968,7 @@ const executePlan = async (plan, {
25385
24968
  mirrorConsole: false,
25386
24969
  // file are executed in parallel, log would be a mess to read
25387
24970
  collectConsole: executionParams.collectConsole,
25388
- collectCoverage: coverage,
24971
+ coverageEnabled,
25389
24972
  coverageTempDirectoryUrl,
25390
24973
  runtime: executionParams.runtime,
25391
24974
  runtimeParams: { ...runtimeParams,
@@ -25434,6 +25017,8 @@ const executePlan = async (plan, {
25434
25017
  let log = createExecutionLog(afterExecutionInfo, {
25435
25018
  completedExecutionLogAbbreviation,
25436
25019
  counters,
25020
+ logRuntime,
25021
+ logEachDuration,
25437
25022
  ...(logTimeUsage ? {
25438
25023
  timeEllapsed: Date.now() - startMs
25439
25024
  } : {}),
@@ -25501,16 +25086,14 @@ const executePlan = async (plan, {
25501
25086
  logger.info(`-> ${urlToFileSystemPath(logFileUrl)}`);
25502
25087
  }
25503
25088
 
25504
- const result = await transformReturnValue({
25505
- summary,
25506
- report
25507
- });
25508
- return {
25509
- aborted: multipleExecutionsOperation.signal.aborted,
25510
- planSummary: result.summary,
25511
- planReport: result.report,
25512
- planCoverage: result.coverage
25513
- };
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;
25514
25097
  } finally {
25515
25098
  await multipleExecutionsOperation.end();
25516
25099
  }
@@ -25631,7 +25214,7 @@ const executeInParallel = async ({
25631
25214
  * @param {boolean} [testPlanParameters.failFast=false] Fails immediatly when a test execution fails
25632
25215
  * @param {number} [testPlanParameters.cooldownBetweenExecutions=0] Millisecond to wait between each execution
25633
25216
  * @param {boolean} [testPlanParameters.logMemoryHeapUsage=false] Add memory heap usage during logs
25634
- * @param {boolean} [testPlanParameters.coverage=false] Controls if coverage is collected during files executions
25217
+ * @param {boolean} [testPlanParameters.coverageEnabled=false] Controls if coverage is collected during files executions
25635
25218
  * @param {boolean} [testPlanParameters.coverageV8ConflictWarning=true] Warn when coverage from 2 executions cannot be merged
25636
25219
  * @return {Object} An object containing the result of all file executions
25637
25220
  */
@@ -25640,6 +25223,8 @@ const executeTestPlan = async ({
25640
25223
  signal = new AbortController().signal,
25641
25224
  handleSIGINT = true,
25642
25225
  logLevel = "info",
25226
+ logRuntime = true,
25227
+ logEachDuration = true,
25643
25228
  logSummary = true,
25644
25229
  logTimeUsage = false,
25645
25230
  logMemoryHeapUsage = false,
@@ -25660,22 +25245,25 @@ const executeTestPlan = async ({
25660
25245
  keepRunning = false,
25661
25246
  cooldownBetweenExecutions = 0,
25662
25247
  gcBetweenExecutions = logMemoryHeapUsage,
25663
- coverage = process.argv.includes("--cover") || process.argv.includes("--coverage"),
25664
- coverageTempDirectoryRelativeUrl = "./.coverage/tmp/",
25248
+ coverageEnabled = process.argv.includes("--cover") || process.argv.includes("--coverage"),
25665
25249
  coverageConfig = {
25666
25250
  "./src/": true
25667
25251
  },
25668
25252
  coverageIncludeMissing = true,
25669
25253
  coverageAndExecutionAllowed = false,
25670
- coverageForceIstanbul = false,
25254
+ coverageMethodForNodeJs = "NODE_V8_COVERAGE",
25255
+ // "Profiler" also accepted
25256
+ coverageMethodForBrowsers = "playwright_api",
25257
+ // "istanbul" also accepted
25671
25258
  coverageV8ConflictWarning = true,
25672
- coverageReportTextLog = true,
25673
- coverageReportJsonFile = process.env.CI ? null : "./.coverage/coverage.json",
25674
- coverageReportHtmlDirectory = process.env.CI ? "./.coverage/" : null,
25259
+ coverageTempDirectoryRelativeUrl = "./.coverage/tmp/",
25675
25260
  // skip empty means empty files won't appear in the coverage reports (json and html)
25676
25261
  coverageReportSkipEmpty = false,
25677
25262
  // skip full means file with 100% coverage won't appear in coverage reports (json and html)
25678
25263
  coverageReportSkipFull = false,
25264
+ coverageReportTextLog = true,
25265
+ coverageReportJsonFile = process.env.CI ? null : "./.coverage/coverage.json",
25266
+ coverageReportHtmlDirectory = process.env.CI ? "./.coverage/" : null,
25679
25267
  sourcemaps = "inline",
25680
25268
  plugins = [],
25681
25269
  nodeEsmResolution,
@@ -25696,7 +25284,7 @@ const executeTestPlan = async ({
25696
25284
  throw new Error(`testPlan must be an object, got ${testPlan}`);
25697
25285
  }
25698
25286
 
25699
- if (coverage) {
25287
+ if (coverageEnabled) {
25700
25288
  if (typeof coverageConfig !== "object") {
25701
25289
  throw new TypeError(`coverageConfig must be an object, got ${coverageConfig}`);
25702
25290
  }
@@ -25737,6 +25325,8 @@ const executeTestPlan = async ({
25737
25325
  logger,
25738
25326
  logLevel,
25739
25327
  logSummary,
25328
+ logRuntime,
25329
+ logEachDuration,
25740
25330
  logTimeUsage,
25741
25331
  logMemoryHeapUsage,
25742
25332
  logFileRelativeUrl,
@@ -25749,10 +25339,11 @@ const executeTestPlan = async ({
25749
25339
  keepRunning,
25750
25340
  cooldownBetweenExecutions,
25751
25341
  gcBetweenExecutions,
25752
- coverage,
25342
+ coverageEnabled,
25753
25343
  coverageConfig,
25754
25344
  coverageIncludeMissing,
25755
- coverageForceIstanbul,
25345
+ coverageMethodForBrowsers,
25346
+ coverageMethodForNodeJs,
25756
25347
  coverageV8ConflictWarning,
25757
25348
  coverageTempDirectoryRelativeUrl,
25758
25349
  scenario: "test",
@@ -25779,7 +25370,7 @@ const executeTestPlan = async ({
25779
25370
  // and in case coverage json file gets written in the same directory
25780
25371
  // it must be done before
25781
25372
 
25782
- if (coverage && coverageReportHtmlDirectory) {
25373
+ if (coverageEnabled && coverageReportHtmlDirectory) {
25783
25374
  const coverageHtmlDirectoryUrl = resolveDirectoryUrl(coverageReportHtmlDirectory, rootDirectoryUrl);
25784
25375
 
25785
25376
  if (!urlIsInsideOf(coverageHtmlDirectoryUrl, rootDirectoryUrl)) {
@@ -25797,7 +25388,7 @@ const executeTestPlan = async ({
25797
25388
  }));
25798
25389
  }
25799
25390
 
25800
- if (coverage && coverageReportJsonFile) {
25391
+ if (coverageEnabled && coverageReportJsonFile) {
25801
25392
  const coverageJsonFileUrl = new URL(coverageReportJsonFile, rootDirectoryUrl).href;
25802
25393
  promises.push(generateCoverageJsonFile({
25803
25394
  coverage: result.planCoverage,
@@ -25806,7 +25397,7 @@ const executeTestPlan = async ({
25806
25397
  }));
25807
25398
  }
25808
25399
 
25809
- if (coverage && coverageReportTextLog) {
25400
+ if (coverageEnabled && coverageReportTextLog) {
25810
25401
  promises.push(generateCoverageTextLog(result.planCoverage, {
25811
25402
  coverageReportSkipEmpty,
25812
25403
  coverageReportSkipFull
@@ -25881,6 +25472,7 @@ const createRuntimeFromPlaywright = ({
25881
25472
  isolatedTab = false
25882
25473
  }) => {
25883
25474
  const runtime = {
25475
+ type: "browser",
25884
25476
  name: browserName,
25885
25477
  version: browserVersion,
25886
25478
  needsServer: true
@@ -25895,9 +25487,9 @@ const createRuntimeFromPlaywright = ({
25895
25487
  server,
25896
25488
  // measurePerformance,
25897
25489
  collectPerformance,
25898
- collectCoverage = false,
25899
- coverageForceIstanbul,
25900
- urlShouldBeCovered,
25490
+ coverageEnabled = false,
25491
+ coverageConfig,
25492
+ coverageMethodForBrowsers,
25901
25493
  stopAfterAllSignal,
25902
25494
  stopSignal,
25903
25495
  keepRunning,
@@ -25982,8 +25574,8 @@ const createRuntimeFromPlaywright = ({
25982
25574
 
25983
25575
  let resultTransformer = result => result;
25984
25576
 
25985
- if (collectCoverage) {
25986
- if (coveragePlaywrightAPIAvailable && !coverageForceIstanbul) {
25577
+ if (coverageEnabled) {
25578
+ if (coveragePlaywrightAPIAvailable && coverageMethodForBrowsers === "playwright_api") {
25987
25579
  await page.coverage.startJSCoverage({// reportAnonymousScripts: true,
25988
25580
  });
25989
25581
  resultTransformer = composeTransformer(resultTransformer, async result => {
@@ -26001,10 +25593,11 @@ const createRuntimeFromPlaywright = ({
26001
25593
  url: fsUrl
26002
25594
  };
26003
25595
  });
26004
- const coverage = filterV8Coverage({
25596
+ const coverage = await filterV8Coverage({
26005
25597
  result: v8CoveragesWithFsUrls
26006
25598
  }, {
26007
- urlShouldBeCovered
25599
+ rootDirectoryUrl,
25600
+ coverageConfig
26008
25601
  });
26009
25602
  return { ...result,
26010
25603
  coverage
@@ -26741,13 +26334,24 @@ const killProcessTree = async (processId, {
26741
26334
  await check();
26742
26335
  };
26743
26336
 
26744
- const NODE_CONTROLLABLE_FILE_URL = new URL("./js/controllable_file.mjs", import.meta.url).href;
26745
- const nodeProcess = {
26746
- name: "node",
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",
26747
26351
  version: process.version.slice(1)
26748
26352
  };
26749
26353
 
26750
- nodeProcess.run = async ({
26354
+ nodeChildProcess.run = async ({
26751
26355
  signal = new AbortController().signal,
26752
26356
  logger,
26753
26357
  logProcessCommand = false,
@@ -26757,13 +26361,14 @@ nodeProcess.run = async ({
26757
26361
  gracefulStopAllocatedMs = 4000,
26758
26362
  stopSignal,
26759
26363
  onConsole,
26760
- collectCoverage = false,
26761
- coverageForceIstanbul,
26364
+ coverageEnabled = false,
26365
+ coverageConfig,
26366
+ coverageMethodForNodeJs,
26762
26367
  collectPerformance,
26368
+ env,
26763
26369
  debugPort,
26764
26370
  debugMode,
26765
26371
  debugModeInheritBreak,
26766
- env,
26767
26372
  inheritProcessEnv = true,
26768
26373
  commandLineOptions = [],
26769
26374
  stdin = "pipe",
@@ -26775,13 +26380,10 @@ nodeProcess.run = async ({
26775
26380
  }
26776
26381
 
26777
26382
  env = { ...env,
26778
- COVERAGE_ENABLED: collectCoverage,
26779
26383
  JSENV: true
26780
26384
  };
26781
26385
 
26782
- if (coverageForceIstanbul) {
26783
- // if we want to force istanbul, we will set process.env.NODE_V8_COVERAGE = ''
26784
- // into the child_process
26386
+ if (coverageMethodForNodeJs !== "NODE_V8_COVERAGE") {
26785
26387
  env.NODE_V8_COVERAGE = "";
26786
26388
  }
26787
26389
 
@@ -26806,8 +26408,8 @@ nodeProcess.run = async ({
26806
26408
  const envForChildProcess = { ...(inheritProcessEnv ? process.env : {}),
26807
26409
  ...env
26808
26410
  };
26809
- logger[logProcessCommand ? "info" : "debug"](`${process.argv[0]} ${execArgv.join(" ")} ${urlToFileSystemPath(NODE_CONTROLLABLE_FILE_URL)}`);
26810
- const childProcess = fork(urlToFileSystemPath(NODE_CONTROLLABLE_FILE_URL), {
26411
+ logger[logProcessCommand ? "info" : "debug"](`${process.argv[0]} ${execArgv.join(" ")} ${fileURLToPath(CONTROLLABLE_CHILD_PROCESS_URL)}`);
26412
+ const childProcess = fork(fileURLToPath(CONTROLLABLE_CHILD_PROCESS_URL), {
26811
26413
  execArgv,
26812
26414
  // silent: true
26813
26415
  stdio: ["pipe", "pipe", "pipe", "ipc"],
@@ -26831,9 +26433,9 @@ nodeProcess.run = async ({
26831
26433
  }
26832
26434
 
26833
26435
  const childProcessReadyPromise = new Promise(resolve => {
26834
- onceProcessMessage(childProcess, "ready", resolve);
26436
+ onceChildProcessMessage(childProcess, "ready", resolve);
26835
26437
  });
26836
- const removeOutputListener = installProcessOutputListener(childProcess, ({
26438
+ const removeOutputListener = installChildProcessOutputListener(childProcess, ({
26837
26439
  type,
26838
26440
  text
26839
26441
  }) => {
@@ -26894,10 +26496,10 @@ nodeProcess.run = async ({
26894
26496
  // },
26895
26497
  // https://nodejs.org/api/child_process.html#child_process_event_error
26896
26498
  error: cb => {
26897
- return onceProcessEvent(childProcess, "error", cb);
26499
+ return onceChildProcessEvent(childProcess, "error", cb);
26898
26500
  },
26899
26501
  exit: cb => {
26900
- return onceProcessEvent(childProcess, "exit", (code, signal) => {
26502
+ return onceChildProcessEvent(childProcess, "exit", (code, signal) => {
26901
26503
  cb({
26902
26504
  code,
26903
26505
  signal
@@ -26905,7 +26507,7 @@ nodeProcess.run = async ({
26905
26507
  });
26906
26508
  },
26907
26509
  response: cb => {
26908
- onceProcessMessage(childProcess, "action-result", cb);
26510
+ return onceChildProcessMessage(childProcess, "action-result", cb);
26909
26511
  }
26910
26512
  }, resolve);
26911
26513
  });
@@ -26914,11 +26516,19 @@ nodeProcess.run = async ({
26914
26516
  actionOperation.throwIfAborted();
26915
26517
  await childProcessReadyPromise;
26916
26518
  actionOperation.throwIfAborted();
26917
- await sendToProcess(childProcess, "action", {
26918
- actionType: "execute-using-dynamic-import",
26919
- actionParams: {
26920
- fileUrl: new URL(fileRelativeUrl, rootDirectoryUrl).href,
26921
- collectPerformance
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
+ }
26922
26532
  }
26923
26533
  });
26924
26534
  const winner = await winnerPromise;
@@ -26951,7 +26561,7 @@ nodeProcess.run = async ({
26951
26561
  };
26952
26562
  }
26953
26563
 
26954
- if (code === null || code === 0 || code === SIGINT_EXIT_CODE || code === SIGTERM_EXIT_CODE || code === SIGABORT_EXIT_CODE) {
26564
+ if (code === null || code === 0 || code === EXIT_CODES.SIGINT || code === EXIT_CODES.SIGTERM || code === EXIT_CODES.SIGABORT) {
26955
26565
  return {
26956
26566
  status: "errored",
26957
26567
  error: new Error(`node process exited during execution`)
@@ -27005,31 +26615,25 @@ nodeProcess.run = async ({
27005
26615
 
27006
26616
  await actionOperation.end();
27007
26617
  return result;
27008
- }; // https://nodejs.org/api/process.html#process_signal_events
27009
-
27010
-
27011
- const SIGINT_SIGNAL_NUMBER = 2;
27012
- const SIGABORT_SIGNAL_NUMBER = 6;
27013
- const SIGTERM_SIGNAL_NUMBER = 15;
27014
- const SIGINT_EXIT_CODE = 128 + SIGINT_SIGNAL_NUMBER;
27015
- const SIGABORT_EXIT_CODE = 128 + SIGABORT_SIGNAL_NUMBER;
27016
- 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
27017
26619
  // https:// github.com/nodejs/node/blob/1d9511127c419ec116b3ddf5fc7a59e8f0f1c1e4/lib/internal/child_process.js#L472
27018
26620
 
26621
+
27019
26622
  const GRACEFUL_STOP_SIGNAL = "SIGTERM";
27020
26623
  const STOP_SIGNAL = "SIGKILL"; // it would be more correct if GRACEFUL_STOP_FAILED_SIGNAL was SIGHUP instead of SIGKILL.
27021
26624
  // but I'm not sure and it changes nothing so just use SIGKILL
27022
26625
 
27023
26626
  const GRACEFUL_STOP_FAILED_SIGNAL = "SIGKILL";
27024
26627
 
27025
- const sendToProcess = async (childProcess, type, data) => {
27026
- const source = uneval(data, {
27027
- functionAllowed: true
27028
- });
26628
+ const sendToChildProcess = async (childProcess, {
26629
+ type,
26630
+ data
26631
+ }) => {
27029
26632
  return new Promise((resolve, reject) => {
27030
26633
  childProcess.send({
26634
+ jsenv: true,
27031
26635
  type,
27032
- data: source
26636
+ data
27033
26637
  }, error => {
27034
26638
  if (error) {
27035
26639
  reject(error);
@@ -27040,7 +26644,7 @@ const sendToProcess = async (childProcess, type, data) => {
27040
26644
  });
27041
26645
  };
27042
26646
 
27043
- const installProcessOutputListener = (childProcess, callback) => {
26647
+ const installChildProcessOutputListener = (childProcess, callback) => {
27044
26648
  // beware that we may receive ansi output here, should not be a problem but keep that in mind
27045
26649
  const stdoutDataCallback = chunk => {
27046
26650
  callback({
@@ -27065,9 +26669,9 @@ const installProcessOutputListener = (childProcess, callback) => {
27065
26669
  };
27066
26670
  };
27067
26671
 
27068
- const onceProcessMessage = (childProcess, type, callback) => {
26672
+ const onceChildProcessMessage = (childProcess, type, callback) => {
27069
26673
  const onmessage = message => {
27070
- if (message.type === type) {
26674
+ if (message && message.jsenv && message.type === type) {
27071
26675
  childProcess.removeListener("message", onmessage); // eslint-disable-next-line no-eval
27072
26676
 
27073
26677
  callback(message.data ? eval(`(${message.data})`) : "");
@@ -27080,13 +26684,290 @@ const onceProcessMessage = (childProcess, type, callback) => {
27080
26684
  };
27081
26685
  };
27082
26686
 
27083
- const onceProcessEvent = (childProcess, type, callback) => {
26687
+ const onceChildProcessEvent = (childProcess, type, callback) => {
27084
26688
  childProcess.once(type, callback);
27085
26689
  return () => {
27086
26690
  childProcess.removeListener(type, callback);
27087
26691
  };
27088
26692
  };
27089
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
+
27090
26971
  const loadUrlGraph = async ({
27091
26972
  operation,
27092
26973
  urlGraph,
@@ -27156,7 +27037,6 @@ const loadUrlGraph = async ({
27156
27037
  type,
27157
27038
  specifier
27158
27039
  });
27159
- entryUrlInfo.data.isEntryPoint = true;
27160
27040
  cook(entryUrlInfo, {
27161
27041
  reference: entryReference
27162
27042
  });
@@ -27530,7 +27410,7 @@ const determineDirectoryPath = ({
27530
27410
  return parentDirectoryPath;
27531
27411
  }
27532
27412
 
27533
- if (urlInfo.data.isEntryPoint || urlInfo.data.isWebWorkerEntryPoint) {
27413
+ if (urlInfo.isEntryPoint) {
27534
27414
  return "";
27535
27415
  }
27536
27416
 
@@ -27564,7 +27444,7 @@ const injectGlobalVersionMapping = async ({
27564
27444
  versionMappings
27565
27445
  }) => {
27566
27446
  await Promise.all(GRAPH.map(finalGraph, async urlInfo => {
27567
- if (urlInfo.data.isEntryPoint || urlInfo.data.isWebWorkerEntryPoint) {
27447
+ if (urlInfo.isEntryPoint) {
27568
27448
  await injectVersionMappings({
27569
27449
  urlInfo,
27570
27450
  kitchen: finalGraphKitchen,
@@ -27600,7 +27480,7 @@ const jsInjector = (urlInfo, {
27600
27480
  }) => {
27601
27481
  const magicSource = createMagicSource(urlInfo.content);
27602
27482
  magicSource.prepend(generateClientCodeForVersionMappings(versionMappings, {
27603
- globalName: urlInfo.data.isWebWorkerEntryPoint ? "self" : "window"
27483
+ globalName: isWebWorkerUrlInfo(urlInfo) ? "self" : "window"
27604
27484
  }));
27605
27485
  return magicSource.toContentAndSourcemap();
27606
27486
  };
@@ -27706,7 +27586,7 @@ const injectServiceWorkerUrls = async ({
27706
27586
  lineBreakNormalization
27707
27587
  }) => {
27708
27588
  const serviceWorkerEntryUrlInfos = GRAPH.filter(finalGraph, finalUrlInfo => {
27709
- return finalUrlInfo.subtype === "service_worker" && finalUrlInfo.data.isWebWorkerEntryPoint;
27589
+ return finalUrlInfo.subtype === "service_worker" && finalUrlInfo.isEntryPoint;
27710
27590
  });
27711
27591
 
27712
27592
  if (serviceWorkerEntryUrlInfos.length === 0) {
@@ -28122,7 +28002,7 @@ build ${entryPointKeys.length} entry points`);
28122
28002
  };
28123
28003
 
28124
28004
  GRAPH.forEach(rawGraph, rawUrlInfo => {
28125
- if (rawUrlInfo.data.isEntryPoint) {
28005
+ if (rawUrlInfo.isEntryPoint) {
28126
28006
  addToBundlerIfAny(rawUrlInfo);
28127
28007
 
28128
28008
  if (rawUrlInfo.type === "html") {
@@ -28200,6 +28080,7 @@ build ${entryPointKeys.length} entry points`);
28200
28080
  const bundleUrlInfo = {
28201
28081
  type,
28202
28082
  subtype: rawUrlInfo ? rawUrlInfo.subtype : undefined,
28083
+ isEntryPoint: rawUrlInfo ? rawUrlInfo.isEntryPoint : undefined,
28203
28084
  filename: rawUrlInfo ? rawUrlInfo.filename : undefined,
28204
28085
  originalUrl: rawUrlInfo ? rawUrlInfo.originalUrl : undefined,
28205
28086
  originalContent: rawUrlInfo ? rawUrlInfo.originalContent : undefined,
@@ -28337,9 +28218,8 @@ build ${entryPointKeys.length} entry points`);
28337
28218
 
28338
28219
  const buildUrl = buildUrlsGenerator.generate(rawUrl, {
28339
28220
  urlInfo: {
28340
- data: { ...reference.data,
28341
- isWebWorkerEntryPoint: isWebWorkerEntryPointReference(reference)
28342
- },
28221
+ data: reference.data,
28222
+ isEntryPoint: reference.isEntryPoint || isWebWorkerEntryPointReference(reference),
28343
28223
  type: reference.expectedType,
28344
28224
  subtype: reference.expectedSubtype,
28345
28225
  filename: reference.filename
@@ -28631,7 +28511,7 @@ ${Object.keys(finalGraph.urlInfos).join("\n")}`);
28631
28511
  // nothing uses this url anymore
28632
28512
  // - versioning update inline content
28633
28513
  // - file converted for import assertion of js_classic conversion
28634
- if (!urlInfo.data.isEntryPoint && urlInfo.type !== "sourcemap" && urlInfo.dependents.size === 0) {
28514
+ if (!urlInfo.isEntryPoint && urlInfo.type !== "sourcemap" && urlInfo.dependents.size === 0) {
28635
28515
  cleanupActions.push(() => {
28636
28516
  finalGraph.deleteUrlInfo(urlInfo.url);
28637
28517
  });
@@ -28853,7 +28733,7 @@ const applyUrlVersioning = async ({
28853
28733
  return;
28854
28734
  }
28855
28735
 
28856
- if (!urlInfo.data.isEntryPoint && urlInfo.dependents.size === 0) {
28736
+ if (!urlInfo.isEntryPoint && urlInfo.dependents.size === 0) {
28857
28737
  return;
28858
28738
  }
28859
28739
 
@@ -29099,7 +28979,7 @@ const assertEntryPoints = ({
29099
28979
  };
29100
28980
 
29101
28981
  const canUseVersionedUrl = urlInfo => {
29102
- if (urlInfo.data.isEntryPoint) {
28982
+ if (urlInfo.isEntryPoint) {
29103
28983
  return false;
29104
28984
  }
29105
28985
 
@@ -29107,10 +28987,6 @@ const canUseVersionedUrl = urlInfo => {
29107
28987
  return false;
29108
28988
  }
29109
28989
 
29110
- if (urlInfo.subtype === "service_worker") {
29111
- return !urlInfo.data.isWebWorkerEntryPoint;
29112
- }
29113
-
29114
28990
  return true;
29115
28991
  };
29116
28992
 
@@ -29572,4 +29448,4 @@ const jsenvPluginInjectGlobals = urlAssociations => {
29572
29448
  };
29573
29449
  };
29574
29450
 
29575
- export { build, chromium, chromiumIsolatedTab, execute, executeTestPlan, firefox, firefoxIsolatedTab, jsenvPluginInjectGlobals, nodeProcess, startBuildServer, startDevServer, webkit, webkitIsolatedTab };
29451
+ export { build, chromium, chromiumIsolatedTab, execute, executeTestPlan, firefox, firefoxIsolatedTab, jsenvPluginInjectGlobals, nodeChildProcess, nodeWorkerThread, startBuildServer, startDevServer, webkit, webkitIsolatedTab };