@jsenv/core 27.0.0-alpha.61 → 27.0.0-alpha.64

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 (43) hide show
  1. package/dist/event_source_client.js +3 -3
  2. package/dist/event_source_client.js.map +7 -8
  3. package/dist/html_supervisor_installer.js +1 -1
  4. package/dist/html_supervisor_installer.js.map +2 -2
  5. package/dist/s.js +626 -0
  6. package/dist/s.js.map +207 -0
  7. package/main.js +1 -0
  8. package/package.json +8 -8
  9. package/src/build/build.js +23 -8
  10. package/src/build/inject_global_version_mappings.js +18 -5
  11. package/src/build/start_build_server.js +49 -32
  12. package/src/dev/start_dev_server.js +11 -3
  13. package/src/execute/runtimes/browsers/from_playwright.js +10 -0
  14. package/src/execute/runtimes/node/node_process.js +8 -0
  15. package/src/omega/kitchen.js +57 -150
  16. package/src/omega/server/file_service.js +34 -17
  17. package/src/omega/url_graph/url_graph_load.js +10 -17
  18. package/src/omega/url_graph/url_info_transformations.js +1 -4
  19. package/src/omega/url_graph.js +6 -2
  20. package/src/omega/url_specifier_encoding.js +59 -0
  21. package/src/plugins/autoreload/dev_sse/client/event_source_client.js +7 -3
  22. package/src/plugins/commonjs_globals/jsenv_plugin_commonjs_globals.js +1 -1
  23. package/src/plugins/html_supervisor/client/html_supervisor_installer.js +1 -1
  24. package/src/plugins/importmap/jsenv_plugin_importmap.js +2 -4
  25. package/src/plugins/inject_globals/jsenv_plugin_inject_globals.js +51 -42
  26. package/src/plugins/inline/jsenv_plugin_data_urls.js +1 -4
  27. package/src/plugins/inline/jsenv_plugin_html_inline_content.js +3 -5
  28. package/src/plugins/inline/jsenv_plugin_inline_query_param.js +1 -4
  29. package/src/plugins/inline/jsenv_plugin_js_inline_content.js +1 -4
  30. package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +4 -0
  31. package/src/plugins/plugins.js +4 -1
  32. package/src/plugins/transpilation/as_js_classic/client/s.js +362 -807
  33. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +28 -12
  34. package/src/plugins/transpilation/as_js_classic/{jsenv_plugin_workers_type_module_as_classic.js → jsenv_plugin_as_js_classic_workers.js} +2 -2
  35. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_script_type_module_as_classic.js +165 -133
  36. package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +5 -2
  37. package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +1 -2
  38. package/src/plugins/transpilation/jsenv_plugin_transpilation.js +4 -1
  39. package/src/test/execute_plan.js +39 -14
  40. package/src/test/execute_test_plan.js +2 -0
  41. package/src/test/logs_file_execution.js +47 -38
  42. package/src/plugins/transpilation/as_js_classic/client/s.js.md +0 -1
  43. package/src/plugins/transpilation/fetch_original_url_info.js +0 -30
@@ -12,38 +12,55 @@
12
12
  */
13
13
 
14
14
  import { createRequire } from "node:module"
15
- import { readFileSync, urlToFilename } from "@jsenv/filesystem"
15
+ import { readFileSync, urlToFilename, urlIsInsideOf } from "@jsenv/filesystem"
16
16
 
17
17
  import { requireBabelPlugin } from "@jsenv/babel-plugins"
18
18
  import { applyBabelPlugins } from "@jsenv/utils/js_ast/apply_babel_plugins.js"
19
19
  import { injectQueryParams } from "@jsenv/utils/urls/url_utils.js"
20
20
  import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
21
21
  import { composeTwoSourcemaps } from "@jsenv/utils/sourcemap/sourcemap_composition_v3.js"
22
+ import { fetchOriginalUrlInfo } from "@jsenv/utils/graph/fetch_original_url_info.js"
22
23
 
23
- import { fetchOriginalUrlInfo } from "../fetch_original_url_info.js"
24
+ import { jsenvRootDirectoryUrl } from "@jsenv/core/src/jsenv_root_directory_url.js"
24
25
  import { babelPluginTransformImportMetaUrl } from "./helpers/babel_plugin_transform_import_meta_url.js"
25
- import { jsenvPluginScriptTypeModuleAsClassic } from "./jsenv_plugin_script_type_module_as_classic.js"
26
- import { jsenvPluginWorkersTypeModuleAsClassic } from "./jsenv_plugin_workers_type_module_as_classic.js"
26
+ import { jsenvPluginAsJsClassicHtml } from "./jsenv_plugin_script_type_module_as_classic.js"
27
+ import { jsenvPluginAsJsClassicWorkers } from "./jsenv_plugin_as_js_classic_workers.js"
27
28
 
28
29
  const require = createRequire(import.meta.url)
29
30
 
30
- export const jsenvPluginAsJsClassic = ({ systemJsInjection }) => {
31
- const systemJsClientFileUrl = new URL("./client/s.js", import.meta.url).href
31
+ export const jsenvPluginAsJsClassic = ({
32
+ rootDirectoryUrl,
33
+ systemJsInjection,
34
+ }) => {
35
+ const preferSourceFiles =
36
+ rootDirectoryUrl === jsenvRootDirectoryUrl ||
37
+ urlIsInsideOf(rootDirectoryUrl, jsenvRootDirectoryUrl)
38
+ const systemJsClientFileUrl = preferSourceFiles
39
+ ? new URL("./client/s.js", import.meta.url).href
40
+ : new URL("./dist/s.js", import.meta.url).href
32
41
 
33
42
  return [
34
- asJsClassic({ systemJsInjection, systemJsClientFileUrl }),
35
- jsenvPluginScriptTypeModuleAsClassic({
43
+ jsenvPluginAsJsClassicConversion({
44
+ systemJsInjection,
45
+ systemJsClientFileUrl,
46
+ }),
47
+ jsenvPluginAsJsClassicHtml({
36
48
  systemJsInjection,
37
49
  systemJsClientFileUrl,
38
50
  generateJsClassicFilename,
39
51
  }),
40
- jsenvPluginWorkersTypeModuleAsClassic({
52
+ jsenvPluginAsJsClassicWorkers({
41
53
  generateJsClassicFilename,
42
54
  }),
43
55
  ]
44
56
  }
45
57
 
46
- const asJsClassic = ({ systemJsInjection, systemJsClientFileUrl }) => {
58
+ // propagate ?as_js_classic to referenced urls
59
+ // and perform the conversion during fetchUrlContent
60
+ const jsenvPluginAsJsClassicConversion = ({
61
+ systemJsInjection,
62
+ systemJsClientFileUrl,
63
+ }) => {
47
64
  const propagateJsClassicSearchParam = (reference, context) => {
48
65
  const parentUrlInfo = context.urlGraph.getUrlInfo(reference.parentUrl)
49
66
  if (
@@ -60,9 +77,8 @@ const asJsClassic = ({ systemJsInjection, systemJsClientFileUrl }) => {
60
77
  }
61
78
 
62
79
  return {
63
- name: "jsenv:as_js_classic",
80
+ name: "jsenv:as_js_classic_conversion",
64
81
  appliesDuring: "*",
65
- // forward ?as_js_classic to referenced urls
66
82
  redirectUrl: {
67
83
  // We want to propagate transformation of js module to js classic to:
68
84
  // - import specifier (static/dynamic import + re-export)
@@ -1,6 +1,6 @@
1
1
  import { injectQueryParams } from "@jsenv/utils/urls/url_utils.js"
2
2
 
3
- export const jsenvPluginWorkersTypeModuleAsClassic = ({
3
+ export const jsenvPluginAsJsClassicWorkers = ({
4
4
  generateJsClassicFilename,
5
5
  }) => {
6
6
  const updateReference = (reference) => {
@@ -19,7 +19,7 @@ export const jsenvPluginWorkersTypeModuleAsClassic = ({
19
19
  }
20
20
 
21
21
  return {
22
- name: "jsenv:workers_type_module_as_classic",
22
+ name: "jsenv:as_js_classic_workers",
23
23
  appliesDuring: "*",
24
24
  redirectUrl: {
25
25
  js_url_specifier: (reference, context) => {
@@ -14,22 +14,19 @@ import {
14
14
  import { generateInlineContentUrl } from "@jsenv/utils/urls/inline_content_url_generator.js"
15
15
  import { injectQueryParamsIntoSpecifier } from "@jsenv/utils/urls/url_utils.js"
16
16
 
17
- export const jsenvPluginScriptTypeModuleAsClassic = ({
17
+ export const jsenvPluginAsJsClassicHtml = ({
18
18
  systemJsInjection,
19
19
  systemJsClientFileUrl,
20
20
  generateJsClassicFilename,
21
21
  }) => {
22
22
  return {
23
- name: "jsenv:script_type_module_as_classic",
23
+ name: "jsenv:as_js_classic_html",
24
24
  appliesDuring: "*",
25
25
  transformUrlContent: {
26
26
  html: async (urlInfo, context) => {
27
- if (
28
- context.isSupportedOnCurrentClients("script_type_module") &&
29
- context.isSupportedOnCurrentClients("import_dynamic")
30
- ) {
31
- return null
32
- }
27
+ const shouldTransformScriptTypeModule =
28
+ !context.isSupportedOnCurrentClients("script_type_module") ||
29
+ !context.isSupportedOnCurrentClients("import_dynamic")
33
30
  const htmlAst = parseHtmlString(urlInfo.content)
34
31
  const preloadAsScriptNodes = []
35
32
  const modulePreloadNodes = []
@@ -47,8 +44,8 @@ export const jsenvPluginScriptTypeModuleAsClassic = ({
47
44
  }
48
45
  if (rel === "preload") {
49
46
  const asAttribute = getHtmlNodeAttributeByName(node, "as")
50
- const as = asAttribute ? asAttribute.value : undefined
51
- if (as === "script") {
47
+ const asValue = asAttribute ? asAttribute.value : undefined
48
+ if (asValue === "script") {
52
49
  preloadAsScriptNodes.push(node)
53
50
  }
54
51
  return
@@ -74,30 +71,9 @@ export const jsenvPluginScriptTypeModuleAsClassic = ({
74
71
  visitScriptNodes(node)
75
72
  })
76
73
 
77
- const classicScriptUrls = []
78
- const moduleScriptUrls = []
79
- classicScriptNodes.forEach((classicScriptNode) => {
80
- const srcAttribute = getHtmlNodeAttributeByName(
81
- classicScriptNode,
82
- "src",
83
- )
84
- if (srcAttribute) {
85
- const url = new URL(srcAttribute.value, urlInfo.url).href
86
- classicScriptUrls.push(url)
87
- }
88
- })
89
- moduleScriptNodes.forEach((moduleScriptNode) => {
90
- const srcAttribute = getHtmlNodeAttributeByName(
91
- moduleScriptNode,
92
- "src",
93
- )
94
- if (srcAttribute) {
95
- const url = new URL(srcAttribute.value, urlInfo.url).href
96
- moduleScriptUrls.push(url)
97
- }
98
- })
99
-
74
+ const actions = []
100
75
  const jsModuleUrls = []
76
+ const convertedUrls = []
101
77
  const getReferenceAsJsClassic = async (
102
78
  reference,
103
79
  {
@@ -108,19 +84,20 @@ export const jsenvPluginScriptTypeModuleAsClassic = ({
108
84
  cookIt = false,
109
85
  } = {},
110
86
  ) => {
87
+ const newReferenceProps = {
88
+ expectedType: "js_classic",
89
+ specifier: injectQueryParamsIntoSpecifier(reference.specifier, {
90
+ as_js_classic: "",
91
+ }),
92
+ filename: generateJsClassicFilename(reference.url),
93
+ }
111
94
  const [newReference, newUrlInfo] = context.referenceUtils.update(
112
95
  reference,
113
- {
114
- expectedType: "js_classic",
115
- specifier: injectQueryParamsIntoSpecifier(reference.specifier, {
116
- as_js_classic: "",
117
- }),
118
- filename: generateJsClassicFilename(reference.url),
119
- },
96
+ newReferenceProps,
120
97
  )
121
- const jsModuleUrl = newUrlInfo.url
122
- if (!jsModuleUrls.includes(jsModuleUrl)) {
123
- jsModuleUrls.push(newUrlInfo.url)
98
+ const convertedUrl = newUrlInfo.url
99
+ if (!convertedUrls.includes(convertedUrl)) {
100
+ convertedUrls.push(convertedUrl)
124
101
  }
125
102
  if (cookIt) {
126
103
  // during dev it means js modules will be cooked before server sends the HTML
@@ -128,123 +105,178 @@ export const jsenvPluginScriptTypeModuleAsClassic = ({
128
105
  // - during dev script_type_module are supported (dev use a recent browser)
129
106
  // - even if browser is not supported it still works it's jus a bit slower
130
107
  // because it needs to decide if systemjs will be injected or not
131
- await context.cook({
132
- reference: newReference,
133
- urlInfo: newUrlInfo,
134
- })
108
+ await context.cook(newUrlInfo, { reference: newReference })
135
109
  }
136
110
  return [newReference, newUrlInfo]
137
111
  }
138
- const actions = []
139
- preloadAsScriptNodes.forEach((preloadAsScriptNode) => {
140
- const hrefAttribute = getHtmlNodeAttributeByName(
141
- preloadAsScriptNode,
142
- "href",
112
+
113
+ classicScriptNodes.forEach((classicScriptNode) => {
114
+ const srcAttribute = getHtmlNodeAttributeByName(
115
+ classicScriptNode,
116
+ "src",
143
117
  )
144
- const href = hrefAttribute.value
145
- const url = new URL(href, urlInfo.url).href
146
- const expectedScriptType = moduleScriptUrls.includes(url)
147
- ? "module"
148
- : "classic"
149
- // keep in mind:
150
- // when the url is not referenced by a <script type="module">
151
- // we assume we want to preload "classic" but it might not be the case
152
- // but it's unlikely to happen and people should use "modulepreload" in that case anyway
153
- if (expectedScriptType === "module") {
154
- actions.push(async () => {
155
- const reference =
156
- context.referenceUtils.findByGeneratedSpecifier(href)
157
- const [newReference] = await getReferenceAsJsClassic(reference)
158
- assignHtmlNodeAttributes(preloadAsScriptNode, {
159
- href: newReference.generatedSpecifier,
118
+ if (srcAttribute) {
119
+ const reference = urlInfo.references.find(
120
+ (ref) =>
121
+ ref.generatedSpecifier === srcAttribute.value &&
122
+ ref.type === "script_src",
123
+ )
124
+ const urlObject = new URL(reference.url)
125
+ if (urlObject.searchParams.has("as_js_classic")) {
126
+ const convertedUrl = urlObject.href
127
+ convertedUrls.push(convertedUrl)
128
+ urlObject.searchParams.delete("as_js_classic")
129
+ const jsModuleUrl = urlObject.href
130
+ jsModuleUrls.push(jsModuleUrl)
131
+ actions.push(async () => {
132
+ const urlInfo = context.urlGraph.getUrlInfo(convertedUrl)
133
+ await context.cook(urlInfo, { reference })
160
134
  })
161
- removeHtmlNodeAttributeByName(preloadAsScriptNode, "crossorigin")
162
- })
135
+ }
163
136
  }
164
137
  })
165
- modulePreloadNodes.forEach((modulePreloadNode) => {
166
- const hrefAttribute = getHtmlNodeAttributeByName(
167
- modulePreloadNode,
168
- "href",
169
- )
170
- const href = hrefAttribute.value
171
- actions.push(async () => {
172
- const reference =
173
- context.referenceUtils.findByGeneratedSpecifier(href)
174
- const [newReference] = await getReferenceAsJsClassic(reference)
175
- assignHtmlNodeAttributes(modulePreloadNode, {
176
- rel: "preload",
177
- as: "script",
178
- href: newReference.generatedSpecifier,
179
- })
180
- })
181
- })
182
138
  moduleScriptNodes.forEach((moduleScriptNode) => {
183
139
  const srcAttribute = getHtmlNodeAttributeByName(
184
140
  moduleScriptNode,
185
141
  "src",
186
142
  )
187
143
  if (srcAttribute) {
144
+ const reference = urlInfo.references.find(
145
+ (ref) =>
146
+ ref.generatedSpecifier === srcAttribute.value &&
147
+ ref.type === "script_src" &&
148
+ ref.expectedType === "js_module",
149
+ )
150
+ jsModuleUrls.push(reference.url)
151
+ if (shouldTransformScriptTypeModule) {
152
+ actions.push(async () => {
153
+ const [newReference] = await getReferenceAsJsClassic(
154
+ reference,
155
+ {
156
+ cookIt: true,
157
+ },
158
+ )
159
+ removeHtmlNodeAttributeByName(moduleScriptNode, "type")
160
+ srcAttribute.value = newReference.generatedSpecifier
161
+ })
162
+ }
163
+ return
164
+ }
165
+ if (shouldTransformScriptTypeModule) {
166
+ const textNode = getHtmlNodeTextNode(moduleScriptNode)
188
167
  actions.push(async () => {
189
- const specifier = srcAttribute.value
190
- const reference =
191
- context.referenceUtils.findByGeneratedSpecifier(specifier)
192
- const [newReference] = await getReferenceAsJsClassic(reference, {
193
- cookIt: true,
168
+ const { line, column, lineEnd, columnEnd, isOriginal } =
169
+ htmlNodePosition.readNodePosition(moduleScriptNode, {
170
+ preferOriginal: true,
171
+ })
172
+ let inlineScriptUrl = generateInlineContentUrl({
173
+ url: urlInfo.url,
174
+ extension: ".js",
175
+ line,
176
+ column,
177
+ lineEnd,
178
+ columnEnd,
194
179
  })
180
+ const [inlineReference] = context.referenceUtils.foundInline({
181
+ node: moduleScriptNode,
182
+ type: "script_src",
183
+ expectedType: "js_module",
184
+ isOriginalPosition: isOriginal,
185
+ // we remove 1 to the line because imagine the following html:
186
+ // <script>console.log('ok')</script>
187
+ // -> content starts same line as <script>
188
+ specifierLine: line - 1,
189
+ specifierColumn: column,
190
+ specifier: inlineScriptUrl,
191
+ contentType: "application/javascript",
192
+ content: textNode.value,
193
+ })
194
+ const [, newUrlInfo] = await getReferenceAsJsClassic(
195
+ inlineReference,
196
+ { cookIt: true },
197
+ )
195
198
  removeHtmlNodeAttributeByName(moduleScriptNode, "type")
196
- srcAttribute.value = newReference.generatedSpecifier
199
+ setHtmlNodeGeneratedText(moduleScriptNode, {
200
+ generatedText: newUrlInfo.content,
201
+ generatedBy: "jsenv:as_js_classic_html",
202
+ })
197
203
  })
198
- return
199
204
  }
200
- const textNode = getHtmlNodeTextNode(moduleScriptNode)
201
- actions.push(async () => {
202
- const { line, column, lineEnd, columnEnd, isOriginal } =
203
- htmlNodePosition.readNodePosition(moduleScriptNode, {
204
- preferOriginal: true,
205
+ })
206
+ if (shouldTransformScriptTypeModule) {
207
+ preloadAsScriptNodes.forEach((preloadAsScriptNode) => {
208
+ const hrefAttribute = getHtmlNodeAttributeByName(
209
+ preloadAsScriptNode,
210
+ "href",
211
+ )
212
+ const href = hrefAttribute.value
213
+ const reference = urlInfo.references.find(
214
+ (ref) =>
215
+ ref.generatedSpecifier === href &&
216
+ ref.type === "link_href" &&
217
+ ref.expectedType === undefined,
218
+ )
219
+ const expectedScriptType = jsModuleUrls.includes(reference.url)
220
+ ? "module"
221
+ : "classic"
222
+ if (expectedScriptType === "module") {
223
+ actions.push(async () => {
224
+ // reference modified by <script type="module"> conversion
225
+ let newReference
226
+ if (reference.next) {
227
+ newReference = reference.next
228
+ } else {
229
+ // when the url is not referenced by a <script type="module">
230
+ // we assume we want to preload "classic" but it might not be the case
231
+ // but it's unlikely to happen and people should use "modulepreload" in that case anyway
232
+ ;[newReference] = await getReferenceAsJsClassic(reference)
233
+ }
234
+ assignHtmlNodeAttributes(preloadAsScriptNode, {
235
+ href: newReference.generatedSpecifier,
236
+ })
237
+ removeHtmlNodeAttributeByName(
238
+ preloadAsScriptNode,
239
+ "crossorigin",
240
+ )
205
241
  })
206
- let inlineScriptUrl = generateInlineContentUrl({
207
- url: urlInfo.url,
208
- extension: ".js",
209
- line,
210
- column,
211
- lineEnd,
212
- columnEnd,
213
- })
214
- const [inlineReference] = context.referenceUtils.foundInline({
215
- node: moduleScriptNode,
216
- type: "script_src",
217
- expectedType: "js_module",
218
- isOriginalPosition: isOriginal,
219
- // we remove 1 to the line because imagine the following html:
220
- // <script>console.log('ok')</script>
221
- // -> content starts same line as <script>
222
- specifierLine: line - 1,
223
- specifierColumn: column,
224
- specifier: inlineScriptUrl,
225
- contentType: "application/javascript",
226
- content: textNode.value,
227
- })
228
- const [, newUrlInfo] = await getReferenceAsJsClassic(
229
- inlineReference,
230
- { cookIt: true },
242
+ }
243
+ })
244
+ modulePreloadNodes.forEach((modulePreloadNode) => {
245
+ const hrefAttribute = getHtmlNodeAttributeByName(
246
+ modulePreloadNode,
247
+ "href",
248
+ )
249
+ const href = hrefAttribute.value
250
+ const reference = urlInfo.references.find(
251
+ (ref) =>
252
+ ref.generatedSpecifier === href &&
253
+ ref.type === "link_href" &&
254
+ ref.expectedType === "js_module",
231
255
  )
232
- removeHtmlNodeAttributeByName(moduleScriptNode, "type")
233
- setHtmlNodeGeneratedText(moduleScriptNode, {
234
- generatedText: newUrlInfo.content,
235
- generatedBy: "jsenv:script_type_module_as_classic",
256
+ actions.push(async () => {
257
+ let newReference
258
+ if (reference.next) {
259
+ newReference = reference.next
260
+ } else {
261
+ ;[newReference] = await getReferenceAsJsClassic(reference)
262
+ }
263
+ assignHtmlNodeAttributes(modulePreloadNode, {
264
+ rel: "preload",
265
+ as: "script",
266
+ href: newReference.generatedSpecifier,
267
+ })
236
268
  })
237
269
  })
238
- })
270
+ }
239
271
 
240
272
  if (actions.length === 0) {
241
273
  return null
242
274
  }
243
275
  await Promise.all(actions.map((action) => action()))
244
276
  if (systemJsInjection) {
245
- const needsSystemJs = jsModuleUrls.some(
246
- (jsModuleUrl) =>
247
- context.urlGraph.getUrlInfo(jsModuleUrl).data.jsClassicFormat ===
277
+ const needsSystemJs = convertedUrls.some(
278
+ (convertedUrl) =>
279
+ context.urlGraph.getUrlInfo(convertedUrl).data.jsClassicFormat ===
248
280
  "system",
249
281
  )
250
282
  if (needsSystemJs) {
@@ -258,7 +290,7 @@ export const jsenvPluginScriptTypeModuleAsClassic = ({
258
290
  createHtmlNode({
259
291
  "tagName": "script",
260
292
  "src": systemJsReference.generatedSpecifier,
261
- "injected-by": "jsenv:script_type_module_as_classic",
293
+ "injected-by": "jsenv:as_js_classic_html",
262
294
  }),
263
295
  )
264
296
  }
@@ -7,7 +7,10 @@ import { babelPluginNewStylesheetAsJsenvImport } from "./new_stylesheet/babel_pl
7
7
  import { babelPluginGlobalThisAsJsenvImport } from "./global_this/babel_plugin_global_this_as_jsenv_import.js"
8
8
  import { babelPluginRegeneratorRuntimeAsJsenvImport } from "./regenerator_runtime/babel_plugin_regenerator_runtime_as_jsenv_import.js"
9
9
 
10
- export const jsenvPluginBabel = ({ getCustomBabelPlugins } = {}) => {
10
+ export const jsenvPluginBabel = ({
11
+ getCustomBabelPlugins,
12
+ babelHelpersAsImport = true,
13
+ } = {}) => {
11
14
  const transformWithBabel = async (urlInfo, context) => {
12
15
  const isJsModule = urlInfo.type === "js_module"
13
16
  const isWorker = urlInfo.subtype === "worker"
@@ -55,7 +58,7 @@ export const jsenvPluginBabel = ({ getCustomBabelPlugins } = {}) => {
55
58
  Object.assign(babelPluginStructure, getCustomBabelPlugins(context))
56
59
  }
57
60
 
58
- if (isJsModule) {
61
+ if (isJsModule && babelHelpersAsImport) {
59
62
  if (!isSupported("global_this")) {
60
63
  babelPluginStructure["global-this-as-jsenv-import"] = [
61
64
  babelPluginGlobalThisAsJsenvImport,
@@ -14,8 +14,7 @@ import { urlToFilename } from "@jsenv/filesystem"
14
14
 
15
15
  import { injectQueryParams } from "@jsenv/utils/urls/url_utils.js"
16
16
  import { JS_QUOTES } from "@jsenv/utils/string/js_quotes.js"
17
-
18
- import { fetchOriginalUrlInfo } from "../fetch_original_url_info.js"
17
+ import { fetchOriginalUrlInfo } from "@jsenv/utils/graph/fetch_original_url_info.js"
19
18
 
20
19
  export const jsenvPluginImportAssertions = () => {
21
20
  const updateReference = (reference, searchParam) => {
@@ -14,11 +14,13 @@ import { jsenvPluginBabel } from "./babel/jsenv_plugin_babel.js"
14
14
  import { jsenvPluginTopLevelAwait } from "./jsenv_plugin_top_level_await.js"
15
15
 
16
16
  export const jsenvPluginTranspilation = ({
17
+ rootDirectoryUrl,
17
18
  importAssertions = true,
18
19
  css = true,
19
20
  jsModuleAsJsClassic = true,
20
21
  systemJsInjection = true,
21
22
  topLevelAwait = true,
23
+ babelHelpersAsImport = true,
22
24
  getCustomBabelPlugins,
23
25
  }) => {
24
26
  return [
@@ -28,13 +30,14 @@ export const jsenvPluginTranspilation = ({
28
30
  jsenvPluginBabel({
29
31
  topLevelAwait,
30
32
  getCustomBabelPlugins,
33
+ babelHelpersAsImport,
31
34
  }),
32
35
  // but the conversion from js_module to js_classic
33
36
  // we want to do it after bundling
34
37
  // so the build function will disable jsModuleAsJsClassic during build
35
38
  // and enable it manually during postbuild
36
39
  ...(jsModuleAsJsClassic
37
- ? [jsenvPluginAsJsClassic({ systemJsInjection })]
40
+ ? [jsenvPluginAsJsClassic({ rootDirectoryUrl, systemJsInjection })]
38
41
  : []),
39
42
  // topLevelAwait must come after js_module_as_js_classic because it's related to the module format
40
43
  // so we want to wait to know the module format before transforming things related to top level await
@@ -25,11 +25,7 @@ import { run } from "@jsenv/core/src/execute/run.js"
25
25
 
26
26
  import { ensureGlobalGc } from "./gc.js"
27
27
  import { generateExecutionSteps } from "./execution_steps.js"
28
- import {
29
- formatExecuting,
30
- formatExecutionResult,
31
- createSummaryLog,
32
- } from "./logs_file_execution.js"
28
+ import { createExecutionLog, createSummaryLog } from "./logs_file_execution.js"
33
29
 
34
30
  export const executePlan = async (
35
31
  plan,
@@ -38,6 +34,7 @@ export const executePlan = async (
38
34
  handleSIGINT,
39
35
  logger,
40
36
  logSummary,
37
+ logTimeUsage,
41
38
  logMemoryHeapUsage,
42
39
  logFileRelativeUrl,
43
40
  completedExecutionLogMerging,
@@ -209,7 +206,13 @@ export const executePlan = async (
209
206
  const debugLogsEnabled = loggerToLevels(logger).debug
210
207
  const executionLogsEnabled = loggerToLevels(logger).info
211
208
  const executionSpinner =
212
- !debugLogsEnabled && executionLogsEnabled && process.stdout.isTTY
209
+ !debugLogsEnabled &&
210
+ executionLogsEnabled &&
211
+ process.stdout.isTTY &&
212
+ // if there is an error during execution npm will mess up the output
213
+ // (happens when npm runs several command in a workspace)
214
+ // so we enable spinner only when !process.exitCode (no error so far)
215
+ !process.exitCode
213
216
 
214
217
  const startMs = Date.now()
215
218
  const report = {}
@@ -320,17 +323,29 @@ export const executePlan = async (
320
323
  runtimeVersion,
321
324
  executionIndex,
322
325
  executionParams,
326
+ startMs: Date.now(),
327
+ executionResult: {
328
+ status: "executing",
329
+ },
323
330
  }
324
331
  let spinner
325
332
  if (executionSpinner) {
326
- spinner = startSpinner({
327
- log: executionLog,
328
- text: formatExecuting(beforeExecutionInfo, {
333
+ const renderSpinnerText = () =>
334
+ createExecutionLog(beforeExecutionInfo, {
329
335
  counters,
336
+ ...(logTimeUsage
337
+ ? {
338
+ timeEllapsed: Date.now() - startMs,
339
+ }
340
+ : {}),
330
341
  ...(logMemoryHeapUsage
331
342
  ? { memoryHeap: memoryUsage().heapUsed }
332
343
  : {}),
333
- }),
344
+ })
345
+ spinner = startSpinner({
346
+ log: executionLog,
347
+ text: renderSpinnerText(),
348
+ update: renderSpinnerText,
334
349
  })
335
350
  }
336
351
  beforeExecutionCallback(beforeExecutionInfo)
@@ -362,10 +377,15 @@ export const executePlan = async (
362
377
  }
363
378
  }
364
379
  counters.done++
365
- if (fileRelativeUrl in report === false) {
366
- report[fileRelativeUrl] = {}
380
+ const fileReport = report[fileRelativeUrl]
381
+ if (fileReport) {
382
+ fileReport[executionName] = executionResult
383
+ } else {
384
+ report[fileRelativeUrl] = {
385
+ [executionName]: executionResult,
386
+ }
367
387
  }
368
- report[fileRelativeUrl][executionName] = executionResult
388
+
369
389
  const afterExecutionInfo = {
370
390
  ...beforeExecutionInfo,
371
391
  endMs: Date.now(),
@@ -386,9 +406,14 @@ export const executePlan = async (
386
406
  global.gc()
387
407
  }
388
408
  if (executionLogsEnabled) {
389
- let log = formatExecutionResult(afterExecutionInfo, {
409
+ let log = createExecutionLog(afterExecutionInfo, {
390
410
  completedExecutionLogAbbreviation,
391
411
  counters,
412
+ ...(logTimeUsage
413
+ ? {
414
+ timeEllapsed: Date.now() - startMs,
415
+ }
416
+ : {}),
392
417
  ...(logMemoryHeapUsage
393
418
  ? { memoryHeap: memoryUsage().heapUsed }
394
419
  : {}),
@@ -42,6 +42,7 @@ export const executeTestPlan = async ({
42
42
  handleSIGINT = true,
43
43
  logLevel = "info",
44
44
  logSummary = true,
45
+ logTimeUsage = false,
45
46
  logMemoryHeapUsage = false,
46
47
  logFileRelativeUrl = ".jsenv/test_plan_debug.txt",
47
48
  completedExecutionLogAbbreviation = false,
@@ -148,6 +149,7 @@ export const executeTestPlan = async ({
148
149
  logger,
149
150
  logLevel,
150
151
  logSummary,
152
+ logTimeUsage,
151
153
  logMemoryHeapUsage,
152
154
  logFileRelativeUrl,
153
155
  completedExecutionLogMerging,