@jsenv/core 28.0.0 → 28.1.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 (67) hide show
  1. package/dist/controllable_child_process.mjs +1 -2
  2. package/dist/controllable_worker_thread.mjs +1 -2
  3. package/dist/js/autoreload.js +27 -11
  4. package/dist/js/execute_using_dynamic_import.js +804 -1
  5. package/dist/js/script_type_module_supervisor.js +129 -0
  6. package/dist/js/supervisor.js +921 -0
  7. package/dist/js/{wrapper.mjs → ws.js} +0 -0
  8. package/dist/main.js +555 -616
  9. package/package.json +13 -13
  10. package/readme.md +2 -2
  11. package/src/build/build.js +8 -8
  12. package/src/build/inject_global_version_mappings.js +3 -3
  13. package/src/build/{resync_ressource_hints.js → resync_resource_hints.js} +10 -12
  14. package/src/build/start_build_server.js +4 -7
  15. package/src/dev/start_dev_server.js +2 -2
  16. package/src/execute/execute.js +1 -1
  17. package/src/execute/run.js +26 -38
  18. package/src/execute/runtimes/browsers/from_playwright.js +51 -77
  19. package/src/execute/runtimes/node/node_child_process.js +36 -36
  20. package/src/execute/runtimes/node/node_worker_thread.js +36 -36
  21. package/src/omega/kitchen.js +33 -14
  22. package/src/omega/omega_server.js +2 -2
  23. package/src/omega/server/file_service.js +5 -5
  24. package/src/omega/url_graph/url_graph_load.js +4 -4
  25. package/src/omega/url_graph/url_info_transformations.js +8 -1
  26. package/src/omega/url_graph.js +3 -3
  27. package/src/plugins/autoreload/client/reload.js +22 -9
  28. package/src/plugins/autoreload/jsenv_plugin_autoreload_client.js +5 -5
  29. package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +3 -3
  30. package/src/plugins/autoreload/jsenv_plugin_hmr.js +1 -1
  31. package/src/plugins/explorer/jsenv_plugin_explorer.js +1 -1
  32. package/src/plugins/import_meta_hot/html_hot_dependencies.js +6 -6
  33. package/src/plugins/importmap/jsenv_plugin_importmap.js +5 -3
  34. package/src/plugins/inject_globals/inject_globals.js +3 -3
  35. package/src/plugins/inline/jsenv_plugin_data_urls.js +1 -1
  36. package/src/plugins/inline/jsenv_plugin_html_inline_content.js +10 -5
  37. package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +2 -13
  38. package/src/plugins/plugin_controller.js +2 -2
  39. package/src/plugins/plugins.js +5 -5
  40. package/src/plugins/server_events/jsenv_plugin_server_events_client_injection.js +4 -4
  41. package/src/plugins/supervisor/client/script_type_module_supervisor.js +108 -0
  42. package/src/plugins/supervisor/client/supervisor.js +921 -0
  43. package/src/plugins/{html_supervisor/jsenv_plugin_html_supervisor.js → supervisor/jsenv_plugin_supervisor.js} +131 -105
  44. package/src/plugins/toolbar/client/execution/toolbar_execution.js +1 -1
  45. package/src/plugins/toolbar/jsenv_plugin_toolbar.js +5 -5
  46. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +9 -7
  47. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_html.js +8 -7
  48. package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +13 -7
  49. package/src/plugins/transpilation/babel/new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js +6 -4
  50. package/src/plugins/transpilation/jsenv_plugin_transpilation.js +4 -2
  51. package/src/plugins/url_analysis/html/html_urls.js +13 -12
  52. package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +1 -1
  53. package/src/test/coverage/babel_plugin_instrument.js +1 -35
  54. package/src/test/coverage/empty_coverage_factory.js +1 -1
  55. package/src/test/execute_plan.js +7 -3
  56. package/src/test/execute_test_plan.js +2 -1
  57. package/src/test/logs_file_execution.js +49 -8
  58. package/dist/js/html_supervisor_installer.js +0 -1091
  59. package/dist/js/html_supervisor_setup.js +0 -89
  60. package/dist/js/uneval.js +0 -804
  61. package/src/plugins/html_supervisor/client/error_formatter.js +0 -426
  62. package/src/plugins/html_supervisor/client/error_in_notification.js +0 -21
  63. package/src/plugins/html_supervisor/client/error_overlay.js +0 -191
  64. package/src/plugins/html_supervisor/client/html_supervisor_installer.js +0 -315
  65. package/src/plugins/html_supervisor/client/html_supervisor_setup.js +0 -89
  66. package/src/plugins/html_supervisor/client/perf_browser.js +0 -17
  67. package/src/plugins/html_supervisor/client/uneval_exception.js +0 -8
@@ -30,10 +30,10 @@ const globalInjectorOnHtml = async (urlInfo, globals) => {
30
30
  injectScriptNodeAsEarlyAsPossible(
31
31
  htmlAst,
32
32
  createHtmlNode({
33
- "tagName": "script",
34
- "textContent": clientCode,
35
- "injected-by": "jsenv:inject_globals",
33
+ tagName: "script",
34
+ textContent: clientCode,
36
35
  }),
36
+ "jsenv:inject_globals",
37
37
  )
38
38
  return stringifyHtmlAst(htmlAst)
39
39
  }
@@ -40,7 +40,7 @@ export const jsenvPluginDataUrls = () => {
40
40
  return reference.generatedUrl
41
41
  }
42
42
  const specifier = DATA_URL.stringify({
43
- contentType: urlInfo.headers["content-type"],
43
+ contentType: urlInfo.contentType,
44
44
  base64Flag: urlInfo.data.base64Flag,
45
45
  data: urlInfo.data.base64Flag
46
46
  ? dataToBase64(urlInfo.content)
@@ -59,7 +59,8 @@ export const jsenvPluginHtmlInlineContent = ({ analyzeConvertedScripts }) => {
59
59
  })
60
60
  setHtmlNodeText(styleNode, inlineStyleUrlInfo.content)
61
61
  setHtmlNodeAttributes(styleNode, {
62
- "generated-by": "jsenv:html_inline_content",
62
+ "jsenv-plugin-owner": "jsenv:html_inline_content",
63
+ "jsenv-plugin-action": "content_cooked",
63
64
  })
64
65
  })
65
66
  },
@@ -71,14 +72,17 @@ export const jsenvPluginHtmlInlineContent = ({ analyzeConvertedScripts }) => {
71
72
  // If the inline script was already handled by an other plugin, ignore it
72
73
  // - we want to preserve inline scripts generated by html supervisor during dev
73
74
  // - we want to avoid cooking twice a script during build
74
- const generatedBy = getHtmlNodeAttribute(scriptNode, "generated-by")
75
+ const jsenvPluginOwner = getHtmlNodeAttribute(
76
+ scriptNode,
77
+ "jsenv-plugin-owner",
78
+ )
75
79
  if (
76
- generatedBy === "jsenv:as_js_classic_html" &&
80
+ jsenvPluginOwner === "jsenv:as_js_classic_html" &&
77
81
  !analyzeConvertedScripts
78
82
  ) {
79
83
  return
80
84
  }
81
- if (generatedBy === "jsenv:html_supervisor") {
85
+ if (jsenvPluginOwner === "jsenv:supervisor") {
82
86
  return
83
87
  }
84
88
  actions.push(async () => {
@@ -117,7 +121,8 @@ export const jsenvPluginHtmlInlineContent = ({ analyzeConvertedScripts }) => {
117
121
  })
118
122
  setHtmlNodeText(scriptNode, inlineScriptUrlInfo.content)
119
123
  setHtmlNodeAttributes(scriptNode, {
120
- "generated-by": "jsenv:html_inline_content",
124
+ "jsenv-plugin-owner": "jsenv:html_inline_content",
125
+ "jsenv-plugin-action": "content_cooked",
121
126
  ...(extension
122
127
  ? { type: type === "js_module" ? "module" : undefined }
123
128
  : {}),
@@ -90,7 +90,7 @@ export const jsenvPluginNodeEsmResolution = ({
90
90
  }
91
91
  },
92
92
  resolveUrl: {
93
- js_import_export: (reference, context) => {
93
+ js_import_export: (reference) => {
94
94
  const { parentUrl, specifier } = reference
95
95
  const { type, url } = applyNodeEsmResolution({
96
96
  conditions: packageConditions,
@@ -99,7 +99,6 @@ export const jsenvPluginNodeEsmResolution = ({
99
99
  lookupPackageScope,
100
100
  readPackageJson,
101
101
  })
102
-
103
102
  // this reference depend on package.json and node_modules
104
103
  // to be resolved. Each file using this specifier
105
104
  // must be invalidated when package.json or package_lock.json
@@ -108,17 +107,7 @@ export const jsenvPluginNodeEsmResolution = ({
108
107
  type !== "relative_specifier" &&
109
108
  type !== "absolute_specifier" &&
110
109
  type !== "node_builtin_specifier"
111
- const relatedUrlInfos = context.urlGraph.getRelatedUrlInfos(
112
- reference.parentUrl,
113
- )
114
- relatedUrlInfos.forEach((relatedUrlInfo) => {
115
- if (relatedUrlInfo.dependsOnPackageJson) {
116
- // the url may depend due to an other reference
117
- // in that case keep dependsOnPackageJson to true
118
- return
119
- }
120
- relatedUrlInfo.dependsOnPackageJson = dependsOnPackageJson
121
- })
110
+ reference.dependsOnPackageJson = dependsOnPackageJson
122
111
  return url
123
112
  },
124
113
  },
@@ -208,9 +208,9 @@ const flattenAndFilterPlugins = (plugins, { scenarios }) => {
208
208
  return
209
209
  }
210
210
  if (typeof appliesDuring === "string") {
211
- if (!["dev", "test", "build"].includes(appliesDuring)) {
211
+ if (!["dev", "build"].includes(appliesDuring)) {
212
212
  throw new Error(
213
- `"appliesDuring" must be "dev", "test" or "build", got ${appliesDuring}`,
213
+ `"appliesDuring" must be "dev" or "build", got ${appliesDuring}`,
214
214
  )
215
215
  }
216
216
  if (scenarios[appliesDuring]) {
@@ -7,7 +7,7 @@ import { jsenvPluginUrlVersion } from "./url_version/jsenv_plugin_url_version.js
7
7
  import { jsenvPluginFileUrls } from "./file_urls/jsenv_plugin_file_urls.js"
8
8
  import { jsenvPluginHttpUrls } from "./http_urls/jsenv_plugin_http_urls.js"
9
9
  import { jsenvPluginInline } from "./inline/jsenv_plugin_inline.js"
10
- import { jsenvPluginHtmlSupervisor } from "./html_supervisor/jsenv_plugin_html_supervisor.js"
10
+ import { jsenvPluginSupervisor } from "./supervisor/jsenv_plugin_supervisor.js"
11
11
  import { jsenvPluginCommonJsGlobals } from "./commonjs_globals/jsenv_plugin_commonjs_globals.js"
12
12
  import { jsenvPluginImportMetaScenarios } from "./import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js"
13
13
  import { jsenvPluginTranspilation } from "./transpilation/jsenv_plugin_transpilation.js"
@@ -27,7 +27,7 @@ export const getCorePlugins = ({
27
27
  runtimeCompat,
28
28
 
29
29
  urlAnalysis = {},
30
- htmlSupervisor,
30
+ supervisor,
31
31
  nodeEsmResolution = true,
32
32
  fileSystemMagicResolution,
33
33
  directoryReferenceAllowed,
@@ -40,8 +40,8 @@ export const getCorePlugins = ({
40
40
  clientFilesPruneCallbackList,
41
41
  explorer,
42
42
  } = {}) => {
43
- if (htmlSupervisor === true) {
44
- htmlSupervisor = {}
43
+ if (supervisor === true) {
44
+ supervisor = {}
45
45
  }
46
46
  if (nodeEsmResolution === true) {
47
47
  nodeEsmResolution = {}
@@ -56,7 +56,7 @@ export const getCorePlugins = ({
56
56
  return [
57
57
  jsenvPluginUrlAnalysis({ rootDirectoryUrl, ...urlAnalysis }),
58
58
  jsenvPluginTranspilation(transpilation),
59
- ...(htmlSupervisor ? [jsenvPluginHtmlSupervisor(htmlSupervisor)] : []), // before inline as it turns inline <script> into <script src>
59
+ ...(supervisor ? [jsenvPluginSupervisor(supervisor)] : []), // before inline as it turns inline <script> into <script src>
60
60
  jsenvPluginImportmap(),
61
61
  // before node esm to handle bare specifiers
62
62
  // + before node esm to handle importmap before inline content
@@ -32,11 +32,11 @@ export const jsenvPluginServerEventsClientInjection = () => {
32
32
  injectScriptNodeAsEarlyAsPossible(
33
33
  htmlAst,
34
34
  createHtmlNode({
35
- "tagName": "script",
36
- "type": "module",
37
- "src": serverEventsClientFileReference.generatedSpecifier,
38
- "injected-by": "jsenv:server_events",
35
+ tagName: "script",
36
+ type: "module",
37
+ src: serverEventsClientFileReference.generatedSpecifier,
39
38
  }),
39
+ "jsenv:server_events",
40
40
  )
41
41
  const htmlModified = stringifyHtmlAst(htmlAst)
42
42
  return {
@@ -0,0 +1,108 @@
1
+ let previousExecutionPromise
2
+
3
+ // https://twitter.com/damienmaillard/status/1554752482273787906
4
+ const isWebkitOrSafari =
5
+ typeof window.webkitConvertPointFromNodeToPage === "function"
6
+
7
+ export const superviseScriptTypeModule = async ({ src, async }) => {
8
+ const execute = isWebkitOrSafari
9
+ ? createExecuteWithDynamicImport({ src })
10
+ : createExecuteWithScript({ src })
11
+ const startExecution = () => {
12
+ const execution = window.__supervisor__.createExecution({
13
+ src,
14
+ type: "js_module",
15
+ execute,
16
+ })
17
+ return execution.start()
18
+ }
19
+ if (async) {
20
+ startExecution()
21
+ return
22
+ }
23
+ // there is guaranteed execution order for non async script type="module"
24
+ // see https://gist.github.com/jakub-g/385ee6b41085303a53ad92c7c8afd7a6#typemodule-vs-non-module-typetextjavascript-vs-script-nomodule
25
+ if (previousExecutionPromise) {
26
+ await previousExecutionPromise
27
+ previousExecutionPromise = null
28
+ }
29
+ previousExecutionPromise = startExecution()
30
+ }
31
+
32
+ const createExecuteWithScript = ({ src }) => {
33
+ const currentScript = document.querySelector(
34
+ `script[type="module"][inlined-from-src="${src}"]`,
35
+ )
36
+ const parentNode = currentScript.parentNode
37
+ let nodeToReplace
38
+ let currentScriptClone
39
+
40
+ return async ({ isReload }) => {
41
+ const urlObject = new URL(src, window.location)
42
+ const loadPromise = new Promise((resolve, reject) => {
43
+ currentScriptClone = document.createElement("script")
44
+ Array.from(currentScript.attributes).forEach((attribute) => {
45
+ currentScriptClone.setAttribute(attribute.nodeName, attribute.nodeValue)
46
+ })
47
+ if (isReload) {
48
+ urlObject.searchParams.set("hmr", Date.now())
49
+ nodeToReplace = currentScriptClone
50
+ currentScriptClone.src = urlObject.href
51
+ } else {
52
+ currentScriptClone.removeAttribute("jsenv-plugin-owner")
53
+ currentScriptClone.removeAttribute("jsenv-plugin-action")
54
+ currentScriptClone.removeAttribute("inlined-from-src")
55
+ currentScriptClone.removeAttribute("original-position")
56
+ currentScriptClone.removeAttribute("original-src-position")
57
+ nodeToReplace = currentScript
58
+ currentScriptClone.src = src
59
+ }
60
+ currentScriptClone.addEventListener("error", reject)
61
+ currentScriptClone.addEventListener("load", resolve)
62
+ parentNode.replaceChild(currentScriptClone, nodeToReplace)
63
+ })
64
+ try {
65
+ await loadPromise
66
+ } catch (e) {
67
+ // eslint-disable-next-line no-throw-literal
68
+ throw {
69
+ message: `Failed to fetch module: ${urlObject.href}`,
70
+ reportedBy: "script_error_event",
71
+ url: urlObject.href,
72
+ // window.error won't be dispatched for this error
73
+ needsReport: true,
74
+ }
75
+ }
76
+ // do not resolve right away, wait for top level execution
77
+ try {
78
+ const namespace = await import(urlObject.href)
79
+ return namespace
80
+ } catch (e) {
81
+ e.reportedBy = "dynamic_import"
82
+ throw e
83
+ }
84
+ }
85
+ }
86
+
87
+ const createExecuteWithDynamicImport = ({ src }) => {
88
+ return async ({ isReload }) => {
89
+ const urlObject = new URL(src, window.location)
90
+ if (isReload) {
91
+ urlObject.searchParams.set("hmr", Date.now())
92
+ }
93
+ try {
94
+ const namespace = await import(urlObject.href)
95
+ return namespace
96
+ } catch (e) {
97
+ e.reportedBy = "dynamic_import"
98
+ // dynamic import would hide the error to the browser
99
+ // so it must be re-reported using window.reportError
100
+ if (typeof window.reportError === "function") {
101
+ window.reportError(e)
102
+ } else {
103
+ console.error(e)
104
+ }
105
+ throw e
106
+ }
107
+ }
108
+ }