@jsenv/core 24.5.6 → 24.6.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.
Files changed (29) hide show
  1. package/dist/build_manifest.js +4 -4
  2. package/dist/compile_proxy/asset-manifest.json +1 -1
  3. package/dist/compile_proxy/{compile_proxy-4d4349b1.html → compile_proxy-a3969633.html} +36 -18
  4. package/dist/compile_proxy/{compile_proxy.html__inline__20-f94f176c.js.map → compile_proxy.html__inline__20-9c92c170.js.map} +10 -8
  5. package/dist/redirector/asset-manifest.json +1 -1
  6. package/dist/redirector/{redirector-b491ae1d.html → redirector-a6b8d640.html} +36 -18
  7. package/dist/redirector/{redirector.html__inline__15-7a0d16d6.js.map → redirector.html__inline__15-58430672.js.map} +10 -8
  8. package/dist/toolbar/asset-manifest.json +1 -1
  9. package/dist/toolbar/{toolbar-9fb7b5af.html → toolbar-84985f43.html} +36 -18
  10. package/dist/toolbar/{toolbar.main-ece8404d.js.map → toolbar.main-7aa01366.js.map} +10 -7
  11. package/dist/toolbar_injector/asset-manifest.json +1 -1
  12. package/dist/toolbar_injector/{toolbar_injector-8d0c0d33.js → toolbar_injector-8edcae04.js} +2 -2
  13. package/dist/toolbar_injector/{toolbar_injector-8d0c0d33.js.map → toolbar_injector-8edcae04.js.map} +2 -2
  14. package/package.json +30 -30
  15. package/readme.md +13 -15
  16. package/src/buildProject.js +1 -2
  17. package/src/executeTestPlan.js +12 -6
  18. package/src/internal/browser_detection/browser_detection.js +2 -0
  19. package/src/internal/browser_detection/detectChrome.js +0 -12
  20. package/src/internal/browser_detection/user_agent_data.js +26 -0
  21. package/src/internal/browser_launcher/executeHtmlFile.js +2 -1
  22. package/src/internal/browser_launcher/from_playwright.js +4 -0
  23. package/src/internal/compiling/js-compilation-service/jsenvTransform.js +3 -0
  24. package/src/internal/executing/createSummaryLog.js +30 -4
  25. package/src/internal/executing/executeConcurrently.js +22 -8
  26. package/src/internal/executing/executePlan.js +12 -6
  27. package/src/internal/executing/executionLogs.js +14 -4
  28. package/src/internal/executing/gc.js +9 -0
  29. package/src/internal/logs/byte.js +10 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "24.5.6",
3
+ "version": "24.6.2",
4
4
  "description": "Tool to develop, test and build js projects",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -45,55 +45,55 @@
45
45
  "playwright": "1.x"
46
46
  },
47
47
  "dependencies": {
48
- "@babel/core": "7.16.0",
48
+ "@babel/core": "7.16.5",
49
49
  "@babel/helper-module-imports": "7.16.0",
50
- "@babel/helpers": "7.16.3",
51
- "@babel/parser": "7.16.4",
52
- "@babel/plugin-proposal-dynamic-import": "7.16.0",
50
+ "@babel/helpers": "7.16.5",
51
+ "@babel/parser": "7.16.6",
52
+ "@babel/plugin-proposal-dynamic-import": "7.16.5",
53
53
  "@babel/plugin-syntax-dynamic-import": "7.8.3",
54
- "@babel/plugin-syntax-import-assertions": "7.16.0",
54
+ "@babel/plugin-syntax-import-assertions": "7.16.5",
55
55
  "@babel/plugin-syntax-import-meta": "7.10.4",
56
56
  "@babel/plugin-syntax-numeric-separator": "7.10.4",
57
- "@babel/plugin-transform-modules-systemjs": "7.16.0",
57
+ "@babel/plugin-transform-modules-systemjs": "7.16.5",
58
58
  "@c88/v8-coverage": "0.1.1",
59
59
  "@jsenv/abort": "4.1.2",
60
- "@jsenv/filesystem": "2.5.1",
60
+ "@jsenv/filesystem": "2.6.0",
61
61
  "@jsenv/importmap": "1.2.0",
62
62
  "@jsenv/log": "1.5.0",
63
63
  "@jsenv/logger": "4.0.1",
64
- "@jsenv/server": "12.2.0",
64
+ "@jsenv/server": "12.2.1",
65
65
  "@jsenv/uneval": "1.6.0",
66
66
  "@rollup/plugin-commonjs": "21.0.1",
67
67
  "@rollup/plugin-json": "4.1.0",
68
- "@rollup/plugin-node-resolve": "13.0.6",
68
+ "@rollup/plugin-node-resolve": "13.1.1",
69
69
  "@rollup/plugin-replace": "3.0.0",
70
70
  "acorn-import-assertions": "1.8.0",
71
71
  "ansi-to-html": "0.7.2",
72
72
  "bytes": "3.1.1",
73
73
  "cjs-module-lexer": "1.2.2",
74
- "construct-style-sheets-polyfill": "3.0.4",
75
- "cssnano": "5.0.11",
76
- "cssnano-preset-default": "5.1.7",
74
+ "construct-style-sheets-polyfill": "3.0.5",
75
+ "cssnano": "5.0.14",
76
+ "cssnano-preset-default": "5.1.9",
77
77
  "cuid": "2.1.8",
78
- "estree-walker": "3.0.0",
78
+ "estree-walker": "3.0.1",
79
79
  "html-minifier": "4.0.0",
80
- "humanize-duration": "3.27.0",
80
+ "humanize-duration": "3.27.1",
81
81
  "is-valid-identifier": "2.0.2",
82
82
  "istanbul-lib-coverage": "3.2.0",
83
83
  "istanbul-lib-instrument": "5.1.0",
84
84
  "istanbul-lib-report": "3.0.0",
85
- "istanbul-reports": "3.0.5",
85
+ "istanbul-reports": "3.1.1",
86
86
  "magic-string": "0.25.7",
87
87
  "parse5": "6.0.1",
88
88
  "pidtree": "0.5.0",
89
- "postcss": "8.3.11",
90
- "postcss-value-parser": "4.1.0",
89
+ "postcss": "8.4.5",
90
+ "postcss-value-parser": "4.2.0",
91
91
  "regenerator-runtime": "0.13.9",
92
92
  "resolve": "1.20.0",
93
- "rollup": "2.60.1",
93
+ "rollup": "2.61.1",
94
94
  "rollup-plugin-node-builtins-brofs": "2.1.3",
95
95
  "rollup-plugin-node-globals": "1.4.0",
96
- "rollup-plugin-polyfill-node": "0.7.0",
96
+ "rollup-plugin-polyfill-node": "0.8.0",
97
97
  "source-map": "0.7.3",
98
98
  "systemjs": "6.11.0",
99
99
  "terser": "5.10.0",
@@ -103,20 +103,20 @@
103
103
  "wrap-ansi": "8.0.1"
104
104
  },
105
105
  "devDependencies": {
106
- "@babel/eslint-parser": "7.16.3",
107
- "@babel/plugin-syntax-jsx": "7.16.0",
108
- "@babel/plugin-transform-block-scoping": "7.16.0",
109
- "@babel/plugin-transform-react-jsx": "7.16.0",
106
+ "@babel/eslint-parser": "7.16.5",
107
+ "@babel/plugin-syntax-jsx": "7.16.5",
108
+ "@babel/plugin-transform-block-scoping": "7.16.5",
109
+ "@babel/plugin-transform-react-jsx": "7.16.5",
110
110
  "@babel/plugin-transform-typescript": "7.16.1",
111
- "@babel/preset-env": "7.16.4",
112
- "@jsenv/assert": "2.3.2",
111
+ "@babel/preset-env": "7.16.5",
112
+ "@jsenv/assert": "2.4.0",
113
113
  "@jsenv/babel-preset": "./packages/jsenv-babel-preset",
114
114
  "@jsenv/eslint-config": "16.0.9",
115
115
  "@jsenv/file-size-impact": "12.1.1",
116
116
  "@jsenv/github-release-package": "1.2.3",
117
117
  "@jsenv/https-local": "1.0.3",
118
118
  "@jsenv/importmap-eslint-resolver": "5.2.1",
119
- "@jsenv/importmap-node-module": "2.8.0",
119
+ "@jsenv/importmap-node-module": "5.0.0",
120
120
  "@jsenv/package-publish": "1.6.2",
121
121
  "@jsenv/performance-impact": "2.2.1",
122
122
  "@jsenv/pwa": "4.0.0",
@@ -126,10 +126,10 @@
126
126
  "eslint-plugin-import": "2.25.3",
127
127
  "eslint-plugin-react": "7.27.1",
128
128
  "node-notifier": "10.0.0",
129
- "playwright": "1.16.3",
129
+ "playwright": "1.17.1",
130
130
  "postcss-import": "14.0.2",
131
- "preact": "10.5.15",
132
- "prettier": "2.4.1",
131
+ "preact": "10.6.4",
132
+ "prettier": "2.5.1",
133
133
  "react": "17.0.2",
134
134
  "react-dom": "17.0.2",
135
135
  "redux": "4.1.2",
package/readme.md CHANGED
@@ -61,7 +61,7 @@ export const countDogs = (animals) => {
61
61
  </html>
62
62
  ```
63
63
 
64
- 2 - Create _execute_test_plan.mjs_
64
+ 2 - Create _test.mjs_
65
65
 
66
66
  ```js
67
67
  import {
@@ -70,7 +70,7 @@ import {
70
70
  firefoxTabRuntime,
71
71
  } from "@jsenv/core"
72
72
 
73
- executeTestPlan({
73
+ await executeTestPlan({
74
74
  projectDirectoryUrl: new URL("./", import.meta.url),
75
75
  testPlan: {
76
76
  "./animals.test.html": {
@@ -94,24 +94,24 @@ npx playwright install-deps
94
94
  npx playwright install
95
95
  ```
96
96
 
97
- 4 - Run _execute_test_plan.mjs_ with Node.js
97
+ 4 - Run _test.mjs_ with Node.js
98
98
 
99
99
  ```console
100
- > node ./execute_test_plan.mjs
100
+ > node ./test.mjs
101
101
 
102
102
  ✔ execution 1 of 2 completed (all completed)
103
103
  file: animals.test.html
104
- runtime: chromium/82.0.4057.0
105
- duration: 1.2 seconds
104
+ runtime: chromium/97.0.4666.0
105
+ duration: 0.45 seconds
106
106
 
107
107
  ✔ execution 2 of 2 completed (all completed)
108
108
  file: animals.test.html
109
- runtime: firefox/73.0b13
110
- duration: 2.4 seconds
109
+ runtime: firefox/93.0
110
+ duration: 0.81 seconds
111
111
 
112
112
  -------------- summary -----------------
113
113
  2 executions: all completed
114
- total duration: 3.6 seconds
114
+ total duration: 1.2 seconds
115
115
  ----------------------------------------
116
116
  ```
117
117
 
@@ -119,7 +119,7 @@ To read more about testing in jsenv, check [jsenv test runner documentation](./d
119
119
 
120
120
  # Dev server overview
121
121
 
122
- You have an html file that you want to open in a browser on your machine.
122
+ You want to execute the following _main.html_ file in a browser.
123
123
 
124
124
  ```html
125
125
  <!DOCTYPE html>
@@ -145,11 +145,11 @@ npm install --save-dev @jsenv/core
145
145
  ```js
146
146
  import { startDevServer } from "@jsenv/core"
147
147
 
148
- startDevServer({
148
+ await startDevServer({
149
149
  projectDirectoryUrl: new URL("./", import.meta.url),
150
150
  explorableConfig: {
151
151
  source: {
152
- "**/*.html": true,
152
+ "./*.html": true,
153
153
  },
154
154
  },
155
155
  port: 3456,
@@ -336,9 +336,7 @@ Jsenv configuration is done in [jsenv.config.mjs](#jsenvconfigmjs) and [babel.co
336
336
 
337
337
  ## jsenv.config.mjs
338
338
 
339
- Jsenv codebase usually puts configuration in a top level file named _jsenv.config.mjs_.
340
-
341
- It's recommended to use the following _jsenv.config.mjs_
339
+ We recommend to put configuration in a top level file named _jsenv.config.mjs_ like the one below:
342
340
 
343
341
  ```js
344
342
  /*
@@ -159,9 +159,8 @@ export const buildProject = async ({
159
159
  jsenvDirectoryRelativeUrl,
160
160
  jsenvDirectoryClean,
161
161
  // build compiled files are written into a different directory
162
- // than exploring-server. This is because here we compile for rollup
162
+ // than dev-server. This is because here we compile for rollup
163
163
  // that is expecting esmodule format, not systemjs
164
- // + some more differences like import.meta.dev
165
164
  outDirectoryName: "build",
166
165
  importDefaultExtension,
167
166
  moduleOutFormat: "esmodule", // rollup or jsenv rollup plugin will transform into the right format
@@ -32,20 +32,23 @@ export const executeTestPlan = async ({
32
32
  importDefaultExtension,
33
33
 
34
34
  testPlan,
35
- defaultMsAllocatedPerExecution,
36
- cooldownBetweenExecutions,
37
35
 
38
- maxExecutionsInParallel,
36
+ logMemoryHeapUsage = false,
39
37
  completedExecutionLogAbbreviation = false,
40
38
  completedExecutionLogMerging = false,
41
39
  logSummary = true,
42
40
  updateProcessExitCode = true,
41
+
42
+ maxExecutionsInParallel = 1,
43
+ defaultMsAllocatedPerExecution = 30000,
43
44
  // stopAfterExecute: true to ensure runtime is stopped once executed
44
45
  // because we have what we wants: execution is completed and
45
46
  // we have associated coverage and capturedConsole
46
47
  // passsing false means all node process and browsers launched stays opened
47
48
  // (can eventually be used for debug)
48
49
  stopAfterExecute = true,
50
+ cooldownBetweenExecutions = 0,
51
+ gcBetweenExecutions = logMemoryHeapUsage,
49
52
 
50
53
  coverage = process.argv.includes("--cover") ||
51
54
  process.argv.includes("--coverage"),
@@ -148,13 +151,16 @@ export const executeTestPlan = async ({
148
151
  importResolutionMethod,
149
152
  importDefaultExtension,
150
153
 
154
+ logMemoryHeapUsage,
155
+ completedExecutionLogMerging,
156
+ completedExecutionLogAbbreviation,
157
+ logSummary,
158
+
151
159
  defaultMsAllocatedPerExecution,
152
160
  maxExecutionsInParallel,
153
161
  stopAfterExecute,
154
162
  cooldownBetweenExecutions,
155
- completedExecutionLogMerging,
156
- completedExecutionLogAbbreviation,
157
- logSummary,
163
+ gcBetweenExecutions,
158
164
 
159
165
  coverage,
160
166
  coverageConfig,
@@ -1,6 +1,7 @@
1
1
  // https://github.com/Ahmdrza/detect-browser/blob/26254f85cf92795655a983bfd759d85f3de850c6/detect-browser.js#L1
2
2
  // https://github.com/lancedikson/bowser/blob/master/src/parser-browsers.js#L1
3
3
 
4
+ import { detectFromUserAgentData } from "./user_agent_data.js"
4
5
  import { detectAndroid } from "./detectAndroid.js"
5
6
  import { detectInternetExplorer } from "./detectInternetExplorer.js"
6
7
  import { detectOpera } from "./detectOpera.js"
@@ -25,6 +26,7 @@ const detectorCompose = (detectors) => () => {
25
26
  }
26
27
 
27
28
  const detector = detectorCompose([
29
+ detectFromUserAgentData, // keep this first
28
30
  detectOpera,
29
31
  detectInternetExplorer,
30
32
  detectEdge,
@@ -1,18 +1,6 @@
1
1
  import { userAgentToVersion, firstMatch } from "./util.js"
2
2
 
3
3
  export const detectChrome = () => {
4
- const { userAgentData } = window.navigator
5
- if (userAgentData) {
6
- const brand = userAgentData.brands.some((brand) => {
7
- return brand.brand === "chromium" || brand.brand === "Google Chrome"
8
- })
9
- if (brand) {
10
- return {
11
- name: "chrome",
12
- version: brand.version,
13
- }
14
- }
15
- }
16
4
  return userAgentToBrowser(window.navigator.userAgent)
17
5
  }
18
6
 
@@ -0,0 +1,26 @@
1
+ /*
2
+ * Prefer window.navigator.userAgentData before resorting to
3
+ * window.navigator.userAgent because of
4
+ * https://blog.chromium.org/2021/09/user-agent-reduction-origin-trial-and-dates.html
5
+ */
6
+
7
+ export const detectFromUserAgentData = () => {
8
+ const { userAgentData } = window.navigator
9
+ if (!userAgentData) {
10
+ return null
11
+ }
12
+
13
+ const { brands } = userAgentData
14
+ let i = 0
15
+ while (i < brands.length) {
16
+ const { brand, version } = brands[i]
17
+ i++
18
+ if (brand === "chromium" || brand === "Google Chrome") {
19
+ return {
20
+ name: "chrome",
21
+ version,
22
+ }
23
+ }
24
+ }
25
+ return null
26
+ }
@@ -30,6 +30,7 @@ export const executeHtmlFile = async (
30
30
  coverageForceIstanbul,
31
31
  coveragePlaywrightAPIAvailable,
32
32
  transformErrorHook,
33
+ forceCompilation,
33
34
  },
34
35
  ) => {
35
36
  const fileUrl = resolveUrl(fileRelativeUrl, projectDirectoryUrl)
@@ -66,7 +67,7 @@ export const executeHtmlFile = async (
66
67
  let executionResult
67
68
  const { canAvoidCompilation, compileId } = browserRuntimeFeaturesReport
68
69
  executeOperation.throwIfAborted()
69
- if (canAvoidCompilation) {
70
+ if (canAvoidCompilation && !forceCompilation) {
70
71
  executionResult = await executeSource({
71
72
  projectDirectoryUrl,
72
73
  compileServerOrigin,
@@ -45,6 +45,7 @@ export const createRuntimeFromPlaywright = ({
45
45
  stopOnExit = true,
46
46
  ignoreHTTPSErrors = true,
47
47
  stopAfterAllExecutionCallbackList,
48
+ forceCompilation,
48
49
  }) => {
49
50
  const stopCallbackList = createCallbackListNotifiedOnce()
50
51
  const stoppedCallbackList = createCallbackListNotifiedOnce()
@@ -139,6 +140,7 @@ export const createRuntimeFromPlaywright = ({
139
140
 
140
141
  coveragePlaywrightAPIAvailable,
141
142
  transformErrorHook,
143
+ forceCompilation,
142
144
  })
143
145
 
144
146
  return {
@@ -272,6 +274,7 @@ const createExecuteHook = ({
272
274
 
273
275
  coveragePlaywrightAPIAvailable,
274
276
  transformErrorHook,
277
+ forceCompilation,
275
278
  }) => {
276
279
  const execute = async ({ signal, fileRelativeUrl }) => {
277
280
  const executeOperation = Abort.startOperation()
@@ -294,6 +297,7 @@ const createExecuteHook = ({
294
297
  coveragePlaywrightAPIAvailable,
295
298
  coverageIgnorePredicate,
296
299
  transformErrorHook,
300
+ forceCompilation,
297
301
  })
298
302
  return result
299
303
  }
@@ -52,6 +52,9 @@ export const jsenvTransform = async ({
52
52
  parserOpts: {
53
53
  allowAwaitOutsideFunction: allowTopLevelAwait,
54
54
  },
55
+ generatorOpts: {
56
+ compact: false,
57
+ },
55
58
  }
56
59
 
57
60
  const babelHelperName = filePathToBabelHelperName(inputPath)
@@ -1,16 +1,17 @@
1
1
  import { ANSI } from "@jsenv/log"
2
2
 
3
3
  import { msAsDuration } from "../logs/msAsDuration.js"
4
+ import { formatByte } from "../logs/byte.js"
4
5
  import { EXECUTION_COLORS } from "./execution_colors.js"
5
6
 
6
7
  export const createSummaryLog = (
7
8
  summary,
8
9
  ) => `-------------- summary -----------------
9
- ${createSummaryMessage(summary)}
10
+ ${createAllExecutionsSummary(summary)}
10
11
  total duration: ${msAsDuration(summary.duration)}
11
12
  ----------------------------------------`
12
13
 
13
- const createSummaryMessage = ({
14
+ const createAllExecutionsSummary = ({
14
15
  executionCount,
15
16
  abortedCount,
16
17
  timedoutCount,
@@ -24,7 +25,7 @@ const createSummaryMessage = ({
24
25
 
25
26
  const executionLabel =
26
27
  executionCount === 1 ? `1 execution` : `${executionCount} executions`
27
- return `${executionLabel}: ${createSummaryDetails({
28
+ return `${executionLabel}: ${createStatusSummary({
28
29
  executionCount,
29
30
  abortedCount,
30
31
  timedoutCount,
@@ -34,7 +35,32 @@ const createSummaryMessage = ({
34
35
  })}`
35
36
  }
36
37
 
37
- export const createSummaryDetails = ({
38
+ export const createIntermediateSummary = ({
39
+ executionCount,
40
+ abortedCount,
41
+ timedoutCount,
42
+ erroredCount,
43
+ completedCount,
44
+ cancelledCount,
45
+ memoryHeap,
46
+ }) => {
47
+ let intermediateSummary = createStatusSummary({
48
+ executionCount,
49
+ abortedCount,
50
+ timedoutCount,
51
+ erroredCount,
52
+ completedCount,
53
+ cancelledCount,
54
+ })
55
+
56
+ if (memoryHeap) {
57
+ intermediateSummary += ` / memory heap: ${formatByte(memoryHeap)}`
58
+ }
59
+
60
+ return intermediateSummary
61
+ }
62
+
63
+ const createStatusSummary = ({
38
64
  executionCount,
39
65
  abortedCount,
40
66
  timedoutCount,
@@ -1,4 +1,5 @@
1
1
  import { existsSync } from "node:fs"
2
+ import { memoryUsage } from "node:process"
2
3
  import wrapAnsi from "wrap-ansi"
3
4
  import cuid from "cuid"
4
5
  import { loggerToLevels } from "@jsenv/logger"
@@ -17,6 +18,7 @@ import { launchAndExecute } from "../executing/launchAndExecute.js"
17
18
  import { reportToCoverage } from "./coverage/reportToCoverage.js"
18
19
  import { formatExecuting, formatExecutionResult } from "./executionLogs.js"
19
20
  import { createSummaryLog } from "./createSummaryLog.js"
21
+ import { ensureGlobalGc } from "./gc.js"
20
22
 
21
23
  export const executeConcurrently = async (
22
24
  executionSteps,
@@ -28,16 +30,19 @@ export const executeConcurrently = async (
28
30
 
29
31
  projectDirectoryUrl,
30
32
  compileServer,
31
-
32
33
  babelPluginMap,
33
34
 
34
- defaultMsAllocatedPerExecution = 30000,
35
- cooldownBetweenExecutions = 0,
36
- maxExecutionsInParallel = 1,
37
- stopAfterExecute,
35
+ logSummary,
36
+ logMemoryHeapUsage,
38
37
  completedExecutionLogMerging,
39
38
  completedExecutionLogAbbreviation,
40
39
 
40
+ maxExecutionsInParallel,
41
+ defaultMsAllocatedPerExecution,
42
+ stopAfterExecute,
43
+ cooldownBetweenExecutions,
44
+ gcBetweenExecutions,
45
+
41
46
  coverage,
42
47
  coverageConfig,
43
48
  coverageIncludeMissing,
@@ -48,8 +53,6 @@ export const executeConcurrently = async (
48
53
 
49
54
  beforeExecutionCallback = () => {},
50
55
  afterExecutionCallback = () => {},
51
-
52
- logSummary,
53
56
  },
54
57
  ) => {
55
58
  if (completedExecutionLogMerging && !process.stdout.isTTY) {
@@ -62,12 +65,15 @@ export const executeConcurrently = async (
62
65
  const executionSpinner = executionLogsEnabled && process.stdout.isTTY
63
66
 
64
67
  const startMs = Date.now()
65
-
66
68
  const report = {}
67
69
  const executionCount = executionSteps.length
68
70
 
69
71
  let transformReturnValue = (value) => value
70
72
 
73
+ if (gcBetweenExecutions) {
74
+ ensureGlobalGc()
75
+ }
76
+
71
77
  const coverageTempDirectoryUrl = resolveUrl(
72
78
  coverageTempDirectoryRelativeUrl,
73
79
  projectDirectoryUrl,
@@ -185,6 +191,9 @@ export const executeConcurrently = async (
185
191
  timedoutCount,
186
192
  erroredCount,
187
193
  completedCount,
194
+ ...(logMemoryHeapUsage
195
+ ? { memoryHeap: memoryUsage().heapUsed }
196
+ : {}),
188
197
  }),
189
198
  })
190
199
  }
@@ -249,6 +258,10 @@ export const executeConcurrently = async (
249
258
  completedCount++
250
259
  }
251
260
 
261
+ if (gcBetweenExecutions) {
262
+ global.gc()
263
+ }
264
+
252
265
  if (executionLogsEnabled) {
253
266
  let log = formatExecutionResult(afterExecutionInfo, {
254
267
  completedExecutionLogAbbreviation,
@@ -257,6 +270,7 @@ export const executeConcurrently = async (
257
270
  timedoutCount,
258
271
  erroredCount,
259
272
  completedCount,
273
+ ...(logMemoryHeapUsage ? { memoryHeap: memoryUsage().heapUsed } : {}),
260
274
  })
261
275
  log = `${log}
262
276
 
@@ -24,13 +24,16 @@ export const executePlan = async (
24
24
  importResolutionMethod,
25
25
  importDefaultExtension,
26
26
 
27
+ logSummary,
28
+ logMemoryHeapUsage,
29
+ completedExecutionLogMerging,
30
+ completedExecutionLogAbbreviation,
31
+
27
32
  defaultMsAllocatedPerExecution,
28
33
  maxExecutionsInParallel,
34
+ gcBetweenExecutions,
29
35
  stopAfterExecute,
30
36
  cooldownBetweenExecutions,
31
- completedExecutionLogMerging,
32
- completedExecutionLogAbbreviation,
33
- logSummary,
34
37
 
35
38
  coverage,
36
39
  coverageConfig,
@@ -169,13 +172,16 @@ export const executePlan = async (
169
172
 
170
173
  babelPluginMap: compileServer.babelPluginMap,
171
174
 
175
+ logSummary,
176
+ logMemoryHeapUsage,
177
+ completedExecutionLogMerging,
178
+ completedExecutionLogAbbreviation,
179
+
172
180
  defaultMsAllocatedPerExecution,
173
181
  maxExecutionsInParallel,
174
182
  stopAfterExecute,
183
+ gcBetweenExecutions,
175
184
  cooldownBetweenExecutions,
176
- completedExecutionLogMerging,
177
- completedExecutionLogAbbreviation,
178
- logSummary,
179
185
 
180
186
  coverage,
181
187
  coverageConfig,
@@ -2,11 +2,18 @@ import { ANSI, UNICODE } from "@jsenv/log"
2
2
 
3
3
  import { msAsDuration } from "../logs/msAsDuration.js"
4
4
  import { EXECUTION_COLORS } from "./execution_colors.js"
5
- import { createSummaryDetails } from "./createSummaryLog.js"
5
+ import { createIntermediateSummary } from "./createSummaryLog.js"
6
6
 
7
7
  export const formatExecuting = (
8
8
  { executionIndex },
9
- { executionCount, abortedCount, timedoutCount, erroredCount, completedCount },
9
+ {
10
+ executionCount,
11
+ abortedCount,
12
+ timedoutCount,
13
+ erroredCount,
14
+ completedCount,
15
+ memoryHeap,
16
+ },
10
17
  ) => {
11
18
  const executionNumber = executionIndex + 1
12
19
  const description = ANSI.color(
@@ -16,12 +23,13 @@ export const formatExecuting = (
16
23
  const summary =
17
24
  executionIndex === 0
18
25
  ? ""
19
- : `(${createSummaryDetails({
26
+ : `(${createIntermediateSummary({
20
27
  executionCount: executionIndex,
21
28
  abortedCount,
22
29
  timedoutCount,
23
30
  erroredCount,
24
31
  completedCount,
32
+ memoryHeap,
25
33
  })})`
26
34
 
27
35
  return formatExecution({
@@ -45,6 +53,7 @@ export const formatExecutionResult = (
45
53
  timedoutCount,
46
54
  erroredCount,
47
55
  completedCount,
56
+ memoryHeap,
48
57
  },
49
58
  ) => {
50
59
  const executionNumber = executionIndex + 1
@@ -57,12 +66,13 @@ export const formatExecutionResult = (
57
66
  allocatedMs,
58
67
  })
59
68
 
60
- const summary = `(${createSummaryDetails({
69
+ const summary = `(${createIntermediateSummary({
61
70
  executionCount: executionNumber,
62
71
  abortedCount,
63
72
  timedoutCount,
64
73
  erroredCount,
65
74
  completedCount,
75
+ memoryHeap,
66
76
  })})`
67
77
 
68
78
  if (completedExecutionLogAbbreviation && status === "completed") {
@@ -0,0 +1,9 @@
1
+ import v8 from "node:v8"
2
+ import { runInNewContext } from "node:vm"
3
+
4
+ export const ensureGlobalGc = () => {
5
+ if (!global.gc) {
6
+ v8.setFlagsFromString("--expose_gc")
7
+ global.gc = runInNewContext("gc")
8
+ }
9
+ }
@@ -0,0 +1,10 @@
1
+ import { createRequire } from "module"
2
+
3
+ const require = createRequire(import.meta.url)
4
+
5
+ // https://github.com/visionmedia/bytes.js/
6
+ const bytes = require("bytes")
7
+
8
+ export const formatByte = (metricValue) => {
9
+ return bytes(metricValue, { decimalPlaces: 2, unitSeparator: " " })
10
+ }