@jsenv/core 25.3.0-alpha.0 → 25.4.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 (107) hide show
  1. package/dist/browser_runtime/asset-manifest.json +2 -2
  2. package/dist/browser_runtime/{browser_runtime_91c5a3b8.js → browser_runtime_0e3396a1.js} +15 -16
  3. package/dist/browser_runtime/{browser_runtime_91c5a3b8.js.map → browser_runtime_0e3396a1.js.map} +13 -13
  4. package/dist/build_manifest.js +5 -5
  5. package/dist/compile_proxy/asset-manifest.json +2 -2
  6. package/dist/compile_proxy/compile_proxy.html__inline__20_f4285042.js.map +343 -0
  7. package/dist/compile_proxy/{compile_proxy_8dfaee51.html → compile_proxy_ab528227.html} +358 -397
  8. package/dist/redirector/asset-manifest.json +2 -2
  9. package/dist/redirector/redirector.html__inline__12_404b8295.js.map +349 -0
  10. package/dist/redirector/{redirector_3e9a97b9.html → redirector_6df2620a.html} +369 -407
  11. package/dist/toolbar/asset-manifest.json +2 -2
  12. package/dist/toolbar/toolbar.main_279b3a68.js.map +764 -0
  13. package/dist/toolbar/{toolbar_361afb84.html → toolbar_0a91ca3b.html} +1509 -1583
  14. package/dist/toolbar_injector/asset-manifest.json +2 -2
  15. package/dist/toolbar_injector/{toolbar_injector_fac1e995.js → toolbar_injector_34f6ad8e.js} +18 -15
  16. package/dist/toolbar_injector/{toolbar_injector_fac1e995.js.map → toolbar_injector_34f6ad8e.js.map} +15 -15
  17. package/package.json +10 -10
  18. package/src/buildProject.js +31 -26
  19. package/src/dev_server.js +111 -92
  20. package/src/execute.js +3 -8
  21. package/src/importUsingChildProcess.js +1 -0
  22. package/src/internal/browser_launcher/{browser_runtime_report.js → browser_runtime_profile.js} +21 -15
  23. package/src/internal/browser_launcher/executeHtmlFile.js +22 -14
  24. package/src/internal/browser_launcher/from_playwright.js +6 -4
  25. package/src/internal/browser_runtime/browser_runtime.js +12 -14
  26. package/src/internal/browser_runtime/createBrowserRuntime.js +7 -6
  27. package/src/internal/browser_utils/fetchAndEvalUsingFetch.js +1 -1
  28. package/src/internal/browser_utils/fetchJson.js +1 -1
  29. package/src/internal/browser_utils/{fetch-browser.js → fetch_browser.js} +0 -2
  30. package/src/internal/building/buildUsingRollup.js +41 -57
  31. package/src/internal/building/rollup_plugin_jsenv.js +28 -8
  32. package/src/internal/compiling/babel_parse_error.js +9 -0
  33. package/src/internal/{babel_plugin_transform_import_meta.js → compiling/babel_plugin_transform_import_meta.js} +53 -36
  34. package/src/internal/compiling/compileFile.js +2 -2
  35. package/src/internal/compiling/compileHtml.js +1 -1
  36. package/src/internal/compiling/createCompiledFileService.js +25 -74
  37. package/src/internal/compiling/js-compilation-service/transformJs.js +151 -23
  38. package/src/internal/compiling/jsenvCompilerForHtml.js +29 -32
  39. package/src/internal/compiling/jsenvCompilerForImportmap.js +2 -2
  40. package/src/internal/compiling/jsenvCompilerForJavaScript.js +2 -4
  41. package/src/internal/compiling/jsenv_directory/comparison_utils.js +24 -0
  42. package/src/internal/compiling/{compile-directory/compile-asset.js → jsenv_directory/compile_asset.js} +0 -0
  43. package/src/internal/compiling/jsenv_directory/compile_context.js +68 -0
  44. package/src/internal/compiling/jsenv_directory/compile_profile.js +218 -0
  45. package/src/internal/compiling/{compile-directory/createLockRegistry.js → jsenv_directory/file_lock_registry.js} +0 -0
  46. package/src/internal/compiling/{compile-directory/createLockRegistry.test.js → jsenv_directory/file_lock_registry.test.js} +2 -1
  47. package/src/internal/compiling/{compile-directory → jsenv_directory}/fs-optimized-for-cache.js +0 -0
  48. package/src/internal/compiling/{compile-directory → jsenv_directory}/getOrGenerateCompiledFile.js +2 -2
  49. package/src/internal/compiling/jsenv_directory/jsenv_directory.js +174 -0
  50. package/src/internal/compiling/{compile-directory → jsenv_directory}/updateMeta.js +1 -1
  51. package/src/internal/compiling/{compile-directory → jsenv_directory}/validateCache.js +0 -0
  52. package/src/internal/compiling/sse_service/sse_service.js +369 -0
  53. package/src/internal/compiling/startCompileServer.js +157 -804
  54. package/src/internal/compiling/transformResultToCompilationResult.js +2 -2
  55. package/src/internal/dev_server/exploring/exploring.js +10 -8
  56. package/src/internal/dev_server/toolbar/compilation/toolbar.compilation.js +92 -78
  57. package/src/internal/dev_server/toolbar/settings/toolbar.settings.js +13 -0
  58. package/src/internal/dev_server/toolbar/toolbar.html +46 -16
  59. package/src/internal/dev_server/toolbar/toolbar.injector.js +17 -15
  60. package/src/internal/dev_server/toolbar/toolbar.main.js +12 -16
  61. package/src/internal/executing/executeConcurrently.js +1 -1
  62. package/src/internal/executing/executePlan.js +2 -3
  63. package/src/internal/{generateGroupMap → features}/babel_plugins_compatibility.js +8 -8
  64. package/src/internal/features/browser_feature_detection/browser_feature_detect_dynamic_import.js +20 -0
  65. package/src/internal/features/browser_feature_detection/browser_feature_detect_import_assertions_css.js +23 -0
  66. package/src/internal/features/browser_feature_detection/browser_feature_detect_import_assertions_json.js +25 -0
  67. package/src/internal/features/browser_feature_detection/browser_feature_detect_importmap.js +37 -0
  68. package/src/internal/features/browser_feature_detection/browser_feature_detect_new_stylesheet.js +9 -0
  69. package/src/internal/features/browser_feature_detection/browser_feature_detect_top_level_await.js +14 -0
  70. package/src/internal/features/browser_feature_detection/browser_feature_detection.js +89 -0
  71. package/src/internal/{browser_feature_detection → features/browser_feature_detection}/compile_proxy.html +1 -1
  72. package/src/internal/features/browser_feature_detection/execute_with_script_module.js +24 -0
  73. package/src/internal/features/features_compat_from_runtime.js +38 -0
  74. package/src/internal/features/features_compat_from_runtime_support.js +31 -0
  75. package/src/internal/{generateGroupMap → features}/features_compatibility.js +3 -3
  76. package/src/internal/{node_feature_detection → features/node_feature_detection}/feature_detect_dynamic_import.mjs +0 -0
  77. package/src/internal/{node_feature_detection → features/node_feature_detection}/feature_detect_top_level_await.mjs +0 -0
  78. package/src/internal/{node_feature_detection/nodeSupportsDynamicImport.js → features/node_feature_detection/node_feature_detect_dynamic_import.js} +0 -0
  79. package/src/internal/{node_feature_detection/nodeSupportsTopLevelAwait.js → features/node_feature_detection/node_feature_detect_top_level_await.js} +0 -0
  80. package/src/internal/features/node_feature_detection/node_feature_detection.js +66 -0
  81. package/src/internal/node_launcher/createControllableNodeProcess.js +4 -6
  82. package/src/internal/node_launcher/node_runtime_report.js +15 -9
  83. package/src/internal/node_runtime/fetchSource.js +2 -4
  84. package/src/internal/node_runtime/nodeControllableFile.mjs +1 -5
  85. package/src/internal/node_runtime/node_execution_systemjs.js +2 -5
  86. package/src/internal/redirector/redirector.html +40 -0
  87. package/src/internal/{generateGroupMap/jsenvRuntimeSupport.js → runtime_support/jsenv_runtime_support.js} +0 -0
  88. package/src/internal/{generateGroupMap → runtime_support}/runtime_support.js +0 -0
  89. package/src/internal/url_conversion.js +12 -17
  90. package/src/launchNode.js +29 -41
  91. package/dist/compile_proxy/compile_proxy.html__inline__20_809f35f7.js.map +0 -392
  92. package/dist/redirector/redirector.html__inline__15_e391410e.js.map +0 -397
  93. package/dist/toolbar/toolbar.main_6c1b3d82.js.map +0 -802
  94. package/src/internal/CONSTANTS.js +0 -11
  95. package/src/internal/browser_feature_detection/browser_feature_detection.js +0 -274
  96. package/src/internal/compiling/js-compilation-service/jsenvTransform.js +0 -242
  97. package/src/internal/dev_server/redirector/redirector.html +0 -48
  98. package/src/internal/generateGroupMap/generateGroupMap.js +0 -65
  99. package/src/internal/generateGroupMap/one_runtime_compat.js +0 -38
  100. package/src/internal/generateGroupMap/runtime_compat.js +0 -34
  101. package/src/internal/generateGroupMap/runtime_compat_composition.js +0 -76
  102. package/src/internal/generateGroupMap/shake_babel_plugin_map.js +0 -21
  103. package/src/internal/node_feature_detection/node_feature_detection.js +0 -117
  104. package/src/internal/node_runtime/detectNode.js +0 -3
  105. package/src/internal/runtime/computeCompileIdFromGroupId.js +0 -30
  106. package/src/internal/runtime/resolveGroup.js +0 -13
  107. package/src/internal/runtime/resolveRuntimeGroup.js +0 -11
@@ -0,0 +1,20 @@
1
+ import {
2
+ asBase64Url,
3
+ executeWithScriptModuleInjection,
4
+ } from "./execute_with_script_module.js"
5
+
6
+ export const supportsDynamicImport = async () => {
7
+ const moduleSource = asBase64Url(`export default 42`)
8
+ try {
9
+ await executeWithScriptModuleInjection(
10
+ `window.__jsenv_runtime_test_dynamic_import__ = import(${JSON.stringify(
11
+ moduleSource,
12
+ )})`,
13
+ )
14
+ const namespace = await window.__jsenv_runtime_test_dynamic_import__
15
+ delete window.__jsenv_runtime_test_dynamic_import__
16
+ return namespace.default === 42
17
+ } catch (e) {
18
+ return false
19
+ }
20
+ }
@@ -0,0 +1,23 @@
1
+ import {
2
+ asBase64Url,
3
+ executeWithScriptModuleInjection,
4
+ } from "./execute_with_script_module.js"
5
+
6
+ export const supportsCssImportAssertions = async () => {
7
+ const cssBase64Url = asBase64Url("p { color: red; }", "text/css")
8
+ const moduleSource = asBase64Url(
9
+ `import css from "${cssBase64Url}" assert { type: "css" }
10
+ export default css`,
11
+ )
12
+ try {
13
+ await executeWithScriptModuleInjection(
14
+ `window.__jsenv_runtime_test_css_import_assertion__ = import(${JSON.stringify(
15
+ moduleSource,
16
+ )})`,
17
+ )
18
+ const namespace = await window.__jsenv_runtime_test_css_import_assertion__
19
+ return namespace.default instanceof CSSStyleSheet
20
+ } catch (e) {
21
+ return false
22
+ }
23
+ }
@@ -0,0 +1,25 @@
1
+ import {
2
+ asBase64Url,
3
+ executeWithScriptModuleInjection,
4
+ } from "./execute_with_script_module.js"
5
+
6
+ export const supportsJsonImportAssertions = async () => {
7
+ const jsonBase64Url = asBase64Url("42", "application/json")
8
+ const moduleSource = asBase64Url(
9
+ `import data from "${jsonBase64Url}" assert { type: "json" }
10
+ export default data`,
11
+ )
12
+ try {
13
+ await executeWithScriptModuleInjection(
14
+ `window.__jsenv_runtime_test_json_import_assertion__ = import(${JSON.stringify(
15
+ moduleSource,
16
+ )})`,
17
+ )
18
+ const namespace = await window.__jsenv_runtime_test_json_import_assertion__
19
+ const supported = namespace.default === 42
20
+ delete window.__jsenv_runtime_test_json_import_assertion__
21
+ return supported
22
+ } catch (e) {
23
+ return false
24
+ }
25
+ }
@@ -0,0 +1,37 @@
1
+ import {
2
+ asBase64Url,
3
+ executeWithScriptModuleInjection,
4
+ } from "./execute_with_script_module.js"
5
+
6
+ export const supportsImportmap = async ({ remote = true } = {}) => {
7
+ const specifier = asBase64Url(`export default false`)
8
+ const importMap = {
9
+ imports: {
10
+ [specifier]: asBase64Url(`export default true`),
11
+ },
12
+ }
13
+ const importmapScript = document.createElement("script")
14
+ const importmapString = JSON.stringify(importMap, null, " ")
15
+ importmapScript.type = "importmap"
16
+ if (remote) {
17
+ importmapScript.src = `data:application/json;base64,${window.btoa(
18
+ importmapString,
19
+ )}`
20
+ } else {
21
+ importmapScript.textContent = importmapString
22
+ }
23
+ document.body.appendChild(importmapScript)
24
+
25
+ try {
26
+ await executeWithScriptModuleInjection(
27
+ `import supported from "${specifier}"; window.__jsenv_runtime_test_importmap__ = supported`,
28
+ )
29
+ document.body.removeChild(importmapScript)
30
+ const supported = window.__jsenv_runtime_test_importmap__
31
+ delete window.__jsenv_runtime_test_importmap__
32
+ return supported
33
+ } catch (e) {
34
+ document.body.removeChild(importmapScript)
35
+ return false
36
+ }
37
+ }
@@ -0,0 +1,9 @@
1
+ export const supportsNewStylesheet = () => {
2
+ try {
3
+ // eslint-disable-next-line no-new
4
+ new CSSStyleSheet()
5
+ return true
6
+ } catch (e) {
7
+ return false
8
+ }
9
+ }
@@ -0,0 +1,14 @@
1
+ import { executeWithScriptModuleInjection } from "./execute_with_script_module.js"
2
+
3
+ export const supportsTopLevelAwait = async () => {
4
+ try {
5
+ await executeWithScriptModuleInjection(
6
+ `window.__jsenv_runtime_test_top_level_await__ = await Promise.resolve(42)`,
7
+ )
8
+ const supported = window.__jsenv_runtime_test_top_level_await__ === 42
9
+ delete window.__jsenv_runtime_test_top_level_await__
10
+ return supported
11
+ } catch (e) {
12
+ return false
13
+ }
14
+ }
@@ -0,0 +1,89 @@
1
+ import { fetchJson } from "../../browser_utils/fetchJson.js"
2
+ import { detectBrowser } from "../../browser_detection/browser_detection.js"
3
+
4
+ import { supportsImportmap } from "./browser_feature_detect_importmap.js"
5
+ import { supportsDynamicImport } from "./browser_feature_detect_dynamic_import.js"
6
+ import { supportsTopLevelAwait } from "./browser_feature_detect_top_level_await.js"
7
+ import { supportsJsonImportAssertions } from "./browser_feature_detect_import_assertions_json.js"
8
+ import { supportsCssImportAssertions } from "./browser_feature_detect_import_assertions_css.js"
9
+ import { supportsNewStylesheet } from "./browser_feature_detect_new_stylesheet.js"
10
+
11
+ export const scanBrowserRuntimeFeatures = async ({
12
+ coverageHandledFromOutside = false,
13
+ forceCompilation = false,
14
+ forceSource = false,
15
+ } = {}) => {
16
+ const jsenvCompileProfileUrl = "/__jsenv_compile_profile__"
17
+ const {
18
+ jsenvDirectoryRelativeUrl,
19
+ inlineImportMapIntoHTML,
20
+ availableCompileIds,
21
+ } = await fetchJson(jsenvCompileProfileUrl)
22
+ const { name, version } = detectBrowser()
23
+ const featuresReport = await detectSupportedFeatures({
24
+ coverageHandledFromOutside,
25
+ inlineImportMapIntoHTML,
26
+ })
27
+ const runtimeReport = {
28
+ env: { browser: true },
29
+ name,
30
+ version,
31
+ featuresReport,
32
+ forceSource,
33
+ forceCompilation,
34
+ }
35
+ const { compileProfile, compileId } = await fetchJson(
36
+ jsenvCompileProfileUrl,
37
+ {
38
+ method: "POST",
39
+ headers: {
40
+ "content-type": "application/json",
41
+ },
42
+ body: JSON.stringify(runtimeReport),
43
+ },
44
+ )
45
+ return {
46
+ jsenvDirectoryRelativeUrl,
47
+ inlineImportMapIntoHTML,
48
+ availableCompileIds,
49
+ runtimeReport,
50
+ compileProfile,
51
+ compileId,
52
+ }
53
+ }
54
+
55
+ const detectSupportedFeatures = async ({
56
+ coverageHandledFromOutside,
57
+ inlineImportMapIntoHTML,
58
+ }) => {
59
+ const featuresReport = {}
60
+ featuresReport["import_http"] = true
61
+ featuresReport["coverage_js"] = coverageHandledFromOutside
62
+ // new CSSStyleSheet
63
+ featuresReport["new_stylesheet"] = supportsNewStylesheet()
64
+ // importmap
65
+ // start testing importmap support first and not in paralell
66
+ // so that there is not module script loaded beore importmap is injected
67
+ // it would log an error in chrome console and return undefined
68
+ featuresReport.importmap = await supportsImportmap({
69
+ // chrome supports inline but not remote importmap
70
+ // https://github.com/WICG/import-maps/issues/235
71
+ // at this stage we won't know if the html file will use
72
+ // an importmap or not and if that importmap is inline or specified with an src
73
+ // so we should test if browser support local and remote importmap.
74
+ // But there exploring server can inline importmap by transforming html
75
+ // and in that case we can test only the local importmap support
76
+ // so we test importmap support and the remote one
77
+ remote: !inlineImportMapIntoHTML,
78
+ })
79
+ // dynamic import
80
+ featuresReport["import_dynamic"] = await supportsDynamicImport()
81
+ // top level await
82
+ featuresReport["top_level_await"] = await supportsTopLevelAwait()
83
+ // import assertions
84
+ featuresReport["import_assertion_type_json"] =
85
+ await supportsJsonImportAssertions()
86
+ featuresReport["import_assertion_type_css"] =
87
+ await supportsCssImportAssertions()
88
+ return featuresReport
89
+ }
@@ -15,7 +15,7 @@
15
15
  </script>
16
16
  <script
17
17
  type="importmap"
18
- src="../../../node_resolution.importmap"
18
+ src="../../../../node_resolution.importmap"
19
19
  ></script>
20
20
  <script type="module">
21
21
  import { scanBrowserRuntimeFeatures } from "./browser_feature_detection.js"
@@ -0,0 +1,24 @@
1
+ export const executeWithScriptModuleInjection = (code) => {
2
+ const scriptModule = document.createElement("script")
3
+ scriptModule.type = "module"
4
+
5
+ const loadPromise = new Promise((resolve, reject) => {
6
+ scriptModule.onload = () => {
7
+ document.body.removeChild(scriptModule)
8
+ resolve()
9
+ }
10
+ scriptModule.onerror = () => {
11
+ document.body.removeChild(scriptModule)
12
+ reject()
13
+ }
14
+ document.body.appendChild(scriptModule)
15
+ })
16
+
17
+ scriptModule.src = asBase64Url(code)
18
+
19
+ return loadPromise
20
+ }
21
+
22
+ export const asBase64Url = (text, mimeType = "application/javascript") => {
23
+ return `data:${mimeType};base64,${window.btoa(text)}`
24
+ }
@@ -0,0 +1,38 @@
1
+ import { findHighestVersion } from "@jsenv/core/src/internal/semantic_versioning/index.js"
2
+
3
+ import { featuresCompatMap } from "./features_compatibility.js"
4
+
5
+ export const featuresCompatFromRuntime = ({
6
+ runtimeName,
7
+ runtimeVersion,
8
+ featureNames,
9
+ }) => {
10
+ const availableFeatureNames = []
11
+ // "minRuntimeVersion" is the first version where all
12
+ // features in "availableFeatureNames" where available
13
+ // can be lower or equal to "runtimeVersion"
14
+ let minRuntimeVersion
15
+ featureNames.forEach((featureName) => {
16
+ const featureCompat = featuresCompatMap[featureName] || {}
17
+ const runtimeVersionCompatible = featureCompat[runtimeName] || "Infinity"
18
+ const highestVersion = findHighestVersion(
19
+ runtimeVersion,
20
+ runtimeVersionCompatible,
21
+ )
22
+ const compatible = highestVersion === runtimeVersion
23
+ if (compatible) {
24
+ availableFeatureNames.push(featureName)
25
+ if (runtimeVersionCompatible !== "Infinity") {
26
+ // there is a version from which runtime becomes compatible with this feature
27
+ minRuntimeVersion = findHighestVersion(
28
+ minRuntimeVersion || "0.0.0",
29
+ runtimeVersionCompatible,
30
+ )
31
+ }
32
+ }
33
+ })
34
+ return {
35
+ availableFeatureNames,
36
+ minRuntimeVersion: minRuntimeVersion || runtimeVersion,
37
+ }
38
+ }
@@ -0,0 +1,31 @@
1
+ import { featuresCompatFromRuntime } from "./features_compat_from_runtime.js"
2
+
3
+ export const featuresCompatFromRuntimeSupport = ({
4
+ runtimeSupport,
5
+ featureNames,
6
+ }) => {
7
+ const availableFeatureNames = []
8
+ const minRuntimeVersions = {}
9
+ const runtimeNames = Object.keys(runtimeSupport)
10
+ runtimeNames.forEach((runtimeName) => {
11
+ const runtimeVersion = runtimeSupport[runtimeName]
12
+ const runtimeFeaturesCompat = featuresCompatFromRuntime({
13
+ runtimeName,
14
+ runtimeVersion,
15
+ featureNames,
16
+ })
17
+
18
+ minRuntimeVersions[runtimeName] = runtimeFeaturesCompat.minRuntimeVersion
19
+ runtimeFeaturesCompat.availableFeatureNames.forEach(
20
+ (availableFeatureName) => {
21
+ if (!availableFeatureNames.includes(availableFeatureName)) {
22
+ availableFeatureNames.push(availableFeatureName)
23
+ }
24
+ },
25
+ )
26
+ })
27
+ return {
28
+ availableFeatureNames,
29
+ minRuntimeVersions,
30
+ }
31
+ }
@@ -1,7 +1,7 @@
1
- import { jsenvBabelPluginCompatMap } from "./babel_plugins_compatibility.js"
1
+ import { babelPluginCompatMap } from "./babel_plugins_compatibility.js"
2
2
 
3
3
  export const featuresCompatMap = {
4
- module: {
4
+ script_type_module: {
5
5
  edge: "16",
6
6
  firefox: "60",
7
7
  chrome: "61",
@@ -33,5 +33,5 @@ export const featuresCompatMap = {
33
33
  android: "80",
34
34
  },
35
35
  worker_importmap: {},
36
- ...jsenvBabelPluginCompatMap,
36
+ ...babelPluginCompatMap,
37
37
  }
@@ -0,0 +1,66 @@
1
+ import { fetchSource } from "@jsenv/core/src/internal/node_runtime/fetchSource.js"
2
+
3
+ import { nodeSupportsDynamicImport } from "./node_feature_detect_dynamic_import.js"
4
+ import { nodeSupportsTopLevelAwait } from "./node_feature_detect_top_level_await.js"
5
+
6
+ export const scanNodeRuntimeFeatures = async ({
7
+ compileServerOrigin,
8
+ moduleOutFormat,
9
+ forceSource,
10
+ forceCompilation,
11
+ coverageHandledFromOutside,
12
+ }) => {
13
+ const jsenvCompileProfileServerUrl = new URL(
14
+ "__jsenv_compile_profile__",
15
+ compileServerOrigin,
16
+ ).href
17
+ const { compileContext } = await fetchJson(jsenvCompileProfileServerUrl)
18
+ const featuresReport = await detectSupportedFeatures({
19
+ compileContext,
20
+ coverageHandledFromOutside,
21
+ })
22
+ const runtimeReport = {
23
+ env: { node: true },
24
+ name: "node",
25
+ version: process.version.slice(1),
26
+ featuresReport,
27
+ moduleOutFormat,
28
+ forceSource,
29
+ forceCompilation,
30
+ }
31
+ const { compileProfile, compileId } = await fetchJson(
32
+ jsenvCompileProfileServerUrl,
33
+ {
34
+ method: "POST",
35
+ headers: {
36
+ "content-type": "application/json",
37
+ },
38
+ body: JSON.stringify(runtimeReport),
39
+ },
40
+ )
41
+ return {
42
+ compileProfile,
43
+ compileId,
44
+ }
45
+ }
46
+
47
+ const detectSupportedFeatures = async ({ coverageHandledFromOutside }) => {
48
+ const featuresReport = {}
49
+ // Node.js do not support http(s) imports, this information is important
50
+ // so that we know we cannot use dynamic import
51
+ featuresReport["import_http"] = false
52
+ featuresReport["coverage_js"] = coverageHandledFromOutside
53
+ featuresReport["import_dynamic"] = await nodeSupportsDynamicImport()
54
+ featuresReport["top_level_await"] = await nodeSupportsTopLevelAwait()
55
+ return featuresReport
56
+ }
57
+
58
+ const fetchJson = async (url, options) => {
59
+ const response = await fetchSource(url, options)
60
+ const status = response.status
61
+ if (status !== 200) {
62
+ throw new Error(`unexpected response status for ${url}, got ${status}`)
63
+ }
64
+ const object = await response.json()
65
+ return object
66
+ }
@@ -1,15 +1,16 @@
1
1
  import { fork } from "node:child_process"
2
- import { uneval } from "@jsenv/uneval"
3
- import { createLogger, createDetailedMessage } from "@jsenv/logger"
4
2
  import { urlToFileSystemPath, assertFilePresence } from "@jsenv/filesystem"
3
+ import { createLogger, createDetailedMessage } from "@jsenv/logger"
5
4
  import {
6
5
  Abort,
7
6
  raceCallbacks,
8
7
  createCallbackList,
9
8
  createCallbackListNotifiedOnce,
10
9
  } from "@jsenv/abort"
10
+ import { uneval } from "@jsenv/uneval"
11
+
12
+ import { nodeSupportsDynamicImport } from "@jsenv/core/src/internal/features/node_feature_detection/node_feature_detect_dynamic_import.js"
11
13
 
12
- import { nodeSupportsDynamicImport } from "../node_feature_detection/nodeSupportsDynamicImport.js"
13
14
  import { createChildProcessOptions } from "./createChildProcessOptions.js"
14
15
  import {
15
16
  processOptionsFromExecArgv,
@@ -276,7 +277,6 @@ export const createControllableNodeProcess = async ({
276
277
 
277
278
  const sendToProcess = async (childProcess, type, data) => {
278
279
  const source = uneval(data, { functionAllowed: true })
279
-
280
280
  return new Promise((resolve, reject) => {
281
281
  childProcess.send({ type, data: source }, (error) => {
282
282
  if (error) {
@@ -294,12 +294,10 @@ const installProcessOutputListener = (childProcess, callback) => {
294
294
  callback({ type: "log", text: String(chunk) })
295
295
  }
296
296
  childProcess.stdout.on("data", stdoutDataCallback)
297
-
298
297
  const stdErrorDataCallback = (chunk) => {
299
298
  callback({ type: "error", text: String(chunk) })
300
299
  }
301
300
  childProcess.stderr.on("data", stdErrorDataCallback)
302
-
303
301
  return () => {
304
302
  childProcess.stdout.removeListener("data", stdoutDataCallback)
305
303
  childProcess.stderr.removeListener("data", stdoutDataCallback)
@@ -1,17 +1,21 @@
1
- import { scanNodeRuntimeFeatures } from "@jsenv/core/src/internal/node_feature_detection/node_feature_detection.js"
1
+ import { scanNodeRuntimeFeatures } from "@jsenv/core/src/internal/features/node_feature_detection/node_feature_detection.js"
2
2
 
3
3
  export const getNodeRuntimeReport = async ({
4
4
  runtime,
5
5
  compileServerId,
6
6
  compileServerOrigin,
7
- outDirectoryRelativeUrl,
7
+
8
+ moduleOutFormat,
9
+ forceCompilation,
8
10
  coverageHandledFromOutside,
9
11
  }) => {
10
12
  const cache = cacheFromParams({
11
13
  runtime,
12
14
  compileServerId,
13
15
  compileServerOrigin,
14
- outDirectoryRelativeUrl,
16
+
17
+ moduleOutFormat,
18
+ forceCompilation,
15
19
  coverageHandledFromOutside,
16
20
  })
17
21
  const entry = cache.read()
@@ -20,7 +24,8 @@ export const getNodeRuntimeReport = async ({
20
24
  }
21
25
  const nodeRuntimeFeaturesReport = await scanNodeRuntimeFeatures({
22
26
  compileServerOrigin,
23
- outDirectoryRelativeUrl,
27
+ moduleOutFormat,
28
+ forceCompilation,
24
29
  coverageHandledFromOutside,
25
30
  })
26
31
  cache.write(nodeRuntimeFeaturesReport)
@@ -32,16 +37,19 @@ let currentCacheValue
32
37
  const cacheFromParams = ({
33
38
  compileServerId,
34
39
  compileServerOrigin,
35
- outDirectoryRelativeUrl,
40
+
41
+ moduleOutFormat,
42
+ forceCompilation,
36
43
  coverageHandledFromOutside,
37
44
  }) => {
38
45
  const params = {
39
46
  compileServerId,
40
47
  compileServerOrigin,
41
- outDirectoryRelativeUrl,
48
+
49
+ moduleOutFormat,
50
+ forceCompilation,
42
51
  coverageHandledFromOutside,
43
52
  }
44
-
45
53
  if (!currentCacheParams) {
46
54
  currentCacheParams = params
47
55
  return {
@@ -51,7 +59,6 @@ const cacheFromParams = ({
51
59
  },
52
60
  }
53
61
  }
54
-
55
62
  if (JSON.stringify(currentCacheParams) !== JSON.stringify(params)) {
56
63
  return {
57
64
  read: () => null,
@@ -61,7 +68,6 @@ const cacheFromParams = ({
61
68
  },
62
69
  }
63
70
  }
64
-
65
71
  return {
66
72
  read: () => currentCacheValue,
67
73
  write: (value) => {
@@ -1,10 +1,8 @@
1
1
  import { fetchUrl } from "../fetchUrl.js"
2
2
 
3
- export const fetchSource = (url, { executionId } = {}) => {
3
+ export const fetchSource = (url, options) => {
4
4
  return fetchUrl(url, {
5
5
  ignoreHttpsError: true,
6
- headers: {
7
- ...(executionId ? { "x-jsenv-execution-id": executionId } : {}),
8
- },
6
+ ...options,
9
7
  })
10
8
  }
@@ -59,8 +59,7 @@ const sendActionFailed = (error) => {
59
59
  sendToParent(
60
60
  ACTION_RESPONSE_EVENT_NAME,
61
61
  // process.send algorithm does not send non enumerable values
62
- // because it works with JSON.stringify I guess so use uneval
63
-
62
+ // so use @jsenv/uneval
64
63
  uneval(
65
64
  {
66
65
  status: ACTION_RESPONSE_STATUS_FAILED,
@@ -91,7 +90,6 @@ const sendToParent = (type, data) => {
91
90
  if (!process.connected) {
92
91
  return
93
92
  }
94
-
95
93
  // this can keep process alive longer than expected
96
94
  // when source is a long string.
97
95
  // It means node process may stay alive longer than expected
@@ -111,11 +109,9 @@ const onceProcessMessage = (type, callback) => {
111
109
  callback(eval(`(${event.data})`))
112
110
  }
113
111
  }
114
-
115
112
  const removeListener = () => {
116
113
  process.removeListener("message", listener)
117
114
  }
118
-
119
115
  process.on("message", listener)
120
116
  return removeListener
121
117
  }
@@ -12,7 +12,7 @@ export const execute = async ({
12
12
  projectDirectoryUrl,
13
13
  compileServerOrigin,
14
14
  fileRelativeUrl,
15
- outDirectoryRelativeUrl,
15
+ jsenvDirectoryRelativeUrl,
16
16
  compileId,
17
17
  importDefaultExtension,
18
18
  // do not log in the console
@@ -25,7 +25,6 @@ export const execute = async ({
25
25
  collectPerformance,
26
26
  }) => {
27
27
  let finalizeExecutionResult = (result) => result
28
-
29
28
  if (collectPerformance) {
30
29
  const getPerformance = startObservingPerformances()
31
30
  finalizeExecutionResult = async (executionResult) => {
@@ -36,12 +35,10 @@ export const execute = async ({
36
35
  }
37
36
  }
38
37
  }
39
-
40
38
  const { getErrorOriginalStackString } = installNodeErrorStackRemapping({
41
39
  projectDirectoryUrl,
42
40
  })
43
-
44
- const compileDirectoryRelativeUrl = `${outDirectoryRelativeUrl}${compileId}/`
41
+ const compileDirectoryRelativeUrl = `${jsenvDirectoryRelativeUrl}${compileId}/`
45
42
 
46
43
  const errorTransformer = async (error) => {
47
44
  // code can throw something else than an error
@@ -0,0 +1,40 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Jsenv redirector</title>
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <meta charset="utf-8" />
7
+ <link rel="icon" href="data:," />
8
+ </head>
9
+
10
+ <body>
11
+ <script type="importmap" src="../../../node_resolution.importmap"></script>
12
+ <script type="module">
13
+ import { scanBrowserRuntimeFeatures } from "../features/browser_feature_detection/browser_feature_detection.js"
14
+
15
+ const redirect = async () => {
16
+ const searchParams = new URLSearchParams(window.location.search)
17
+ const redirectTarget = searchParams.get("redirect")
18
+ const forceCompilation = searchParams.get("force_compilation")
19
+ const browserRuntimeProfile = await scanBrowserRuntimeFeatures({
20
+ forceCompilation: forceCompilation === "1",
21
+ })
22
+ const href = `${getDirectoryUrl(
23
+ browserRuntimeProfile,
24
+ )}${redirectTarget}`
25
+ // It's IMPORTANT to use location.replace and NOT location.href = url
26
+ // otherwise it would break the back button
27
+ window.location.replace(href)
28
+ }
29
+
30
+ const getDirectoryUrl = ({ jsenvDirectoryRelativeUrl, compileId }) => {
31
+ if (compileId) {
32
+ return `/${jsenvDirectoryRelativeUrl}${compileId}/`
33
+ }
34
+ return `/`
35
+ }
36
+
37
+ redirect()
38
+ </script>
39
+ </body>
40
+ </html>