@jsenv/core 27.0.0-alpha.5 → 27.0.0-alpha.50

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 (146) hide show
  1. package/dist/event_source_client.js +545 -0
  2. package/dist/event_source_client.js.map +187 -0
  3. package/dist/html_supervisor_installer.js +1236 -0
  4. package/dist/html_supervisor_installer.js.map +337 -0
  5. package/dist/html_supervisor_setup.js +95 -0
  6. package/dist/html_supervisor_setup.js.map +57 -0
  7. package/dist/import_meta_hot.js +86 -0
  8. package/dist/import_meta_hot.js.map +42 -0
  9. package/main.js +8 -1
  10. package/package.json +22 -21
  11. package/readme.md +4 -12
  12. package/src/build/build.js +749 -437
  13. package/src/build/build_urls_generator.js +56 -22
  14. package/src/build/graph_utils.js +31 -0
  15. package/src/build/{inject_version_mappings.js → inject_global_version_mappings.js} +33 -15
  16. package/src/build/inject_service_worker_urls.js +79 -0
  17. package/src/build/resync_ressource_hints.js +68 -0
  18. package/src/build/start_build_server.js +255 -0
  19. package/src/dev/plugins/explorer/jsenv_plugin_explorer.js +2 -2
  20. package/src/dev/plugins/toolbar/jsenv_plugin_toolbar.js +3 -1
  21. package/src/dev/start_dev_server.js +136 -30
  22. package/src/execute/execute.js +31 -6
  23. package/src/execute/run.js +19 -56
  24. package/src/execute/runtimes/browsers/from_playwright.js +201 -147
  25. package/src/execute/runtimes/node/controllable_file.mjs +26 -10
  26. package/src/execute/runtimes/node/node_execution_performance.js +67 -0
  27. package/src/execute/runtimes/node/node_process.js +280 -39
  28. package/src/jsenv_root_directory_url.js +1 -0
  29. package/src/omega/{runtime_support/default_runtime_support.js → compat/default_runtime_compat.js} +3 -5
  30. package/src/omega/{runtime_support/features_compatibility.js → compat/features_compats.js} +66 -4
  31. package/src/omega/compat/runtime_compat.js +50 -0
  32. package/src/omega/errors.js +51 -58
  33. package/src/omega/fetched_content_compliance.js +24 -0
  34. package/src/omega/file_url_converter.js +8 -50
  35. package/src/omega/kitchen.js +482 -292
  36. package/src/omega/omega_server.js +2 -3
  37. package/src/omega/server/file_service.js +38 -25
  38. package/src/omega/server/user_agent.js +4 -2
  39. package/src/omega/url_graph/url_graph_load.js +14 -7
  40. package/src/omega/url_graph/url_graph_report.js +17 -15
  41. package/src/omega/url_graph/url_info_transformations.js +26 -9
  42. package/src/omega/url_graph.js +91 -16
  43. package/src/omega/web_workers.js +42 -0
  44. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/autoreload_preference.js +0 -0
  45. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/event_source_client.js +2 -2
  46. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/reload.js +0 -0
  47. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/url_helpers.js +0 -0
  48. package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_client.js +46 -0
  49. package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js +204 -0
  50. package/src/plugins/autoreload/jsenv_plugin_autoreload.js +27 -0
  51. package/src/plugins/autoreload/jsenv_plugin_hmr.js +35 -0
  52. package/src/plugins/bundling/css/bundle_css.js +21 -0
  53. package/src/plugins/bundling/js_classic_workers/bundle_js_classic_workers.js +13 -0
  54. package/src/{build/plugins/bundle_js_module/jsenv_plugin_bundle_js_module.js → plugins/bundling/js_module/bundle_js_module.js} +150 -79
  55. package/src/plugins/bundling/jsenv_plugin_bundling.js +54 -0
  56. package/src/{omega/core_plugins → plugins}/commonjs_globals/jsenv_plugin_commonjs_globals.js +54 -41
  57. package/src/plugins/file_urls/jsenv_plugin_file_urls.js +66 -0
  58. package/src/{omega/core_plugins → plugins}/filesystem_magic/jsenv_plugin_filesystem_magic.js +8 -5
  59. package/src/{omega/core_plugins → plugins}/html_supervisor/client/error_in_document.js +0 -0
  60. package/src/{omega/core_plugins → plugins}/html_supervisor/client/error_in_notification.js +0 -0
  61. package/src/plugins/html_supervisor/client/html_supervisor_installer.js +242 -0
  62. package/src/plugins/html_supervisor/client/html_supervisor_setup.js +79 -0
  63. package/src/{omega/core_plugins → plugins}/html_supervisor/client/perf_browser.js +0 -0
  64. package/src/{omega/core_plugins → plugins}/html_supervisor/client/uneval_exception.js +0 -0
  65. package/src/{omega/core_plugins → plugins}/html_supervisor/jsenv_plugin_html_supervisor.js +83 -58
  66. package/src/plugins/http_urls/jsenv_plugin_http_urls.js +12 -0
  67. package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/babel_plugin_metadata_import_meta_hot.js +4 -5
  68. package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/client/import_meta_hot.js +3 -1
  69. package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/html_hot_dependencies.js +2 -2
  70. package/src/plugins/import_meta_hot/jsenv_plugin_import_meta_hot.js +105 -0
  71. package/src/{omega/core_plugins → plugins}/import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js +33 -8
  72. package/src/plugins/import_meta_url/client/import_meta_url_browser.js +52 -0
  73. package/src/plugins/import_meta_url/client/import_meta_url_commonjs.mjs +9 -0
  74. package/src/{omega/core_plugins → plugins}/importmap/jsenv_plugin_importmap.js +39 -33
  75. package/src/plugins/inject_globals/jsenv_plugin_inject_globals.js +67 -0
  76. package/src/{omega/core_plugins → plugins}/inline/client/inline_content.js +0 -0
  77. package/src/{omega/core_plugins → plugins}/inline/jsenv_plugin_data_urls.js +18 -14
  78. package/src/{omega/core_plugins/inline/jsenv_plugin_js_and_css_inside_html.js → plugins/inline/jsenv_plugin_html_inline_content.js} +65 -44
  79. package/src/plugins/inline/jsenv_plugin_inline.js +36 -0
  80. package/src/{omega/core_plugins → plugins}/inline/jsenv_plugin_inline_query_param.js +6 -6
  81. package/src/plugins/inline/jsenv_plugin_js_inline_content.js +296 -0
  82. package/src/plugins/leading_slash/jsenv_plugin_leading_slash.js +13 -0
  83. package/src/plugins/minification/css/minify_css.js +9 -0
  84. package/src/plugins/minification/html/minify_html.js +15 -0
  85. package/src/{build/plugins/minify_js/jsenv_plugin_minify_js.js → plugins/minification/js/minify_js.js} +6 -22
  86. package/src/plugins/minification/jsenv_plugin_minification.js +78 -0
  87. package/src/plugins/minification/json/minify_json.js +8 -0
  88. package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +146 -0
  89. package/src/{omega → plugins}/plugin_controller.js +42 -11
  90. package/src/plugins/plugins.js +91 -0
  91. package/src/plugins/transpilation/as_js_classic/client/s.js +808 -0
  92. package/src/plugins/transpilation/as_js_classic/client/s.js.md +1 -0
  93. package/src/plugins/transpilation/as_js_classic/helpers/babel_plugin_transform_import_meta_url.js +47 -0
  94. package/src/plugins/transpilation/as_js_classic/helpers/systemjs_old.js +43 -0
  95. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +183 -0
  96. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_script_type_module_as_classic.js +256 -0
  97. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_workers_type_module_as_classic.js +55 -0
  98. package/src/{omega/core_plugins → plugins/transpilation}/babel/global_this/babel_plugin_global_this_as_jsenv_import.js +0 -0
  99. package/src/{omega/core_plugins → plugins/transpilation}/babel/global_this/client/global_this.js +0 -0
  100. package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugin_babel_helpers_as_jsenv_imports.js +0 -0
  101. package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugin_structure.js +4 -22
  102. package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugins_compatibility.js +0 -0
  103. package/src/{omega/core_plugins → plugins/transpilation}/babel/jsenv_plugin_babel.js +37 -21
  104. package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js +30 -6
  105. package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/client/.eslintrc.cjs +0 -0
  106. package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/client/new_stylesheet.js +0 -0
  107. package/src/{omega/core_plugins → plugins/transpilation}/babel/regenerator_runtime/babel_plugin_regenerator_runtime_as_jsenv_import.js +0 -0
  108. package/src/{omega/core_plugins → plugins/transpilation}/babel/regenerator_runtime/client/regenerator_runtime.js +0 -0
  109. package/src/plugins/transpilation/css_parcel/jsenv_plugin_css_parcel.js +18 -0
  110. package/src/plugins/transpilation/fetch_original_url_info.js +30 -0
  111. package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +181 -0
  112. package/src/plugins/transpilation/jsenv_plugin_top_level_await.js +70 -0
  113. package/src/plugins/transpilation/jsenv_plugin_transpilation.js +44 -0
  114. package/src/plugins/url_analysis/css/css_urls.js +42 -0
  115. package/src/plugins/url_analysis/html/html_urls.js +273 -0
  116. package/src/plugins/url_analysis/js/js_urls.js +67 -0
  117. package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +18 -0
  118. package/src/plugins/url_analysis/webmanifest/webmanifest_urls.js +17 -0
  119. package/src/{omega/core_plugins → plugins}/url_resolution/jsenv_plugin_url_resolution.js +12 -5
  120. package/src/{omega/core_plugins → plugins}/url_version/jsenv_plugin_url_version.js +12 -15
  121. package/src/test/execute_plan.js +30 -18
  122. package/src/test/execute_test_plan.js +23 -8
  123. package/src/test/logs_file_execution.js +8 -7
  124. package/src/build/plugins/minify_html/jsenv_plugin_minify_html.js +0 -30
  125. package/src/dev/plugins/autoreload/client/event_source_connection.js +0 -195
  126. package/src/dev/plugins/autoreload/jsenv_plugin_autoreload.js +0 -374
  127. package/src/dev/plugins/autoreload/sse_service.js +0 -149
  128. package/src/execute/runtimes/node/controlled_process.js +0 -316
  129. package/src/omega/core_plugins/file_urls/jsenv_plugin_file_urls.js +0 -67
  130. package/src/omega/core_plugins/html_supervisor/client/html_supervisor_installer.js +0 -168
  131. package/src/omega/core_plugins/html_supervisor/client/html_supervisor_setup.js +0 -77
  132. package/src/omega/core_plugins/import_assertions/helpers/babel_plugin_metadata_import_assertions.js +0 -98
  133. package/src/omega/core_plugins/import_assertions/helpers/json_module.js +0 -12
  134. package/src/omega/core_plugins/import_assertions/helpers/text_module.js +0 -6
  135. package/src/omega/core_plugins/import_assertions/jsenv_plugin_import_assertions.js +0 -211
  136. package/src/omega/core_plugins/inline/jsenv_plugin_inline.js +0 -13
  137. package/src/omega/core_plugins/inline/jsenv_plugin_new_inline_content.js +0 -210
  138. package/src/omega/core_plugins/leading_slash/jsenv_plugin_leading_slash.js +0 -12
  139. package/src/omega/core_plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +0 -77
  140. package/src/omega/core_plugins.js +0 -39
  141. package/src/omega/runtime_support/runtime_support.js +0 -20
  142. package/src/omega/url_mentions/css_url_mentions.js +0 -63
  143. package/src/omega/url_mentions/html_url_mentions.js +0 -185
  144. package/src/omega/url_mentions/js_module_url_mentions.js +0 -91
  145. package/src/omega/url_mentions/parse_url_mentions.js +0 -37
  146. package/src/omega/url_mentions/worker_classic_url_mentions.js +0 -37
@@ -11,50 +11,63 @@ import { applyBabelPlugins } from "@jsenv/utils/js_ast/apply_babel_plugins.js"
11
11
  import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
12
12
 
13
13
  export const jsenvPluginCommonJsGlobals = () => {
14
+ const transformCommonJsGlobals = async (urlInfo, { scenario }) => {
15
+ if (
16
+ !urlInfo.content.includes("process.env.NODE_ENV") &&
17
+ !urlInfo.content.includes("__filename") &&
18
+ !urlInfo.content.includes("__dirname")
19
+ ) {
20
+ return null
21
+ }
22
+ const isJsModule = urlInfo.type === "js_module"
23
+ const replaceMap = {
24
+ "process.env.NODE_ENV": `("${
25
+ scenario === "dev" || scenario === "test" ? "dev" : "prod"
26
+ }")`,
27
+ "global": "globalThis",
28
+ "__filename": isJsModule
29
+ ? `import.meta.url.slice('file:///'.length)`
30
+ : `document.currentScript.src`,
31
+ "__dirname": isJsModule
32
+ ? `import.meta.url.slice('file:///'.length).replace(/[\\\/\\\\][^\\\/\\\\]*$/, '')`
33
+ : `new URL('./', document.currentScript.src).href`,
34
+ }
35
+ const { metadata } = await applyBabelPlugins({
36
+ babelPlugins: [
37
+ [
38
+ babelPluginMetadataExpressionPaths,
39
+ {
40
+ replaceMap,
41
+ allowConflictingReplacements: true,
42
+ },
43
+ ],
44
+ ],
45
+ urlInfo,
46
+ })
47
+ const { expressionPaths } = metadata
48
+ const keys = Object.keys(expressionPaths)
49
+ if (keys.length === 0) {
50
+ return null
51
+ }
52
+ const magicSource = createMagicSource(urlInfo.content)
53
+ keys.forEach((key) => {
54
+ expressionPaths[key].forEach((path) => {
55
+ magicSource.replace({
56
+ start: path.node.start,
57
+ end: path.node.end,
58
+ replacement: replaceMap[key],
59
+ })
60
+ })
61
+ })
62
+ return magicSource.toContentAndSourcemap()
63
+ }
64
+
14
65
  return {
15
66
  name: "jsenv:commonjs_globals",
16
67
  appliesDuring: "*",
17
- transform: {
18
- js_module: async ({ url, generatedUrl, content }, { scenario }) => {
19
- const replaceMap = {
20
- "process.env.NODE_ENV": `("${
21
- scenario === "dev" || scenario === "test" ? "dev" : "prod"
22
- }")`,
23
- "global": "globalThis",
24
- "__filename": `import.meta.url.slice('file:///'.length)`,
25
- "__dirname": `import.meta.url.slice('file:///'.length).replace(/[\\\/\\\\][^\\\/\\\\]*$/, '')`,
26
- }
27
- const { metadata } = await applyBabelPlugins({
28
- babelPlugins: [
29
- [
30
- babelPluginMetadataExpressionPaths,
31
- {
32
- replaceMap,
33
- allowConflictingReplacements: true,
34
- },
35
- ],
36
- ],
37
- url,
38
- generatedUrl,
39
- content,
40
- })
41
- const { expressionPaths } = metadata
42
- const keys = Object.keys(expressionPaths)
43
- if (keys.length === 0) {
44
- return null
45
- }
46
- const magicSource = createMagicSource(content)
47
- keys.forEach((key) => {
48
- expressionPaths[key].forEach((path) => {
49
- magicSource.replace({
50
- start: path.node.start,
51
- end: path.node.end,
52
- replacement: replaceMap[key],
53
- })
54
- })
55
- })
56
- return magicSource.toContentAndSourcemap()
57
- },
68
+ transformUrlContent: {
69
+ js_classic: transformCommonJsGlobals,
70
+ js_module: transformCommonJsGlobals,
58
71
  },
59
72
  }
60
73
  }
@@ -0,0 +1,66 @@
1
+ import { readFileSync } from "node:fs"
2
+ import { urlIsInsideOf, urlToRelativeUrl } from "@jsenv/filesystem"
3
+
4
+ import { CONTENT_TYPE } from "@jsenv/utils/content_type/content_type.js"
5
+
6
+ export const jsenvPluginFileUrls = () => {
7
+ return [jsenvPluginResolveAbsoluteFileUrls(), jsenvPluginFetchFileUrls()]
8
+ }
9
+
10
+ const jsenvPluginResolveAbsoluteFileUrls = () => {
11
+ return {
12
+ name: "jsenv:resolve_absolute_file_urls",
13
+ appliesDuring: {
14
+ // during dev and test it's a browser running the code
15
+ // so absolute file urls needs to be relativized
16
+ dev: true,
17
+ test: true,
18
+ // during build it's fine to use file:// urls
19
+ build: false,
20
+ },
21
+ resolveUrl: (reference) => {
22
+ if (!reference.specifier.startsWith("/@fs/")) {
23
+ return null
24
+ }
25
+ const fsRootRelativeUrl = reference.specifier.slice("/@fs/".length)
26
+ return `file:///${fsRootRelativeUrl}`
27
+ },
28
+ formatUrl: (reference, context) => {
29
+ if (!reference.generatedUrl.startsWith("file:")) {
30
+ return null
31
+ }
32
+ if (urlIsInsideOf(reference.generatedUrl, context.rootDirectoryUrl)) {
33
+ return `/${urlToRelativeUrl(
34
+ reference.generatedUrl,
35
+ context.rootDirectoryUrl,
36
+ )}`
37
+ }
38
+ return `/@fs/${reference.generatedUrl.slice("file:///".length)}`
39
+ },
40
+ }
41
+ }
42
+
43
+ const jsenvPluginFetchFileUrls = () => {
44
+ return {
45
+ name: "jsenv:fetch_file_urls",
46
+ appliesDuring: "*",
47
+ fetchUrlContent: (urlInfo) => {
48
+ if (!urlInfo.url.startsWith("file:")) {
49
+ return null
50
+ }
51
+ const urlObject = new URL(urlInfo.url)
52
+ const fileBuffer = readFileSync(urlObject)
53
+ const contentType = CONTENT_TYPE.fromUrlExtension(urlInfo.url)
54
+ if (CONTENT_TYPE.isTextual(contentType)) {
55
+ return {
56
+ contentType,
57
+ content: String(fileBuffer),
58
+ }
59
+ }
60
+ return {
61
+ contentType,
62
+ content: fileBuffer,
63
+ }
64
+ },
65
+ }
66
+ }
@@ -6,19 +6,19 @@ import { urlToExtension } from "@jsenv/filesystem"
6
6
  import { applyFileSystemMagicResolution } from "@jsenv/node-esm-resolution"
7
7
 
8
8
  export const jsenvPluginFileSystemMagic = ({
9
- magicExtensions = ["inherit"],
9
+ magicExtensions = ["inherit", ".js"],
10
10
  magicDirectoryIndex = true,
11
11
  preservesSymlink = true,
12
12
  } = {}) => {
13
13
  return {
14
14
  name: "jsenv:filesystem_magic",
15
15
  appliesDuring: "*",
16
- normalize: ({ parentUrl, url }) => {
16
+ normalizeUrl: (reference) => {
17
17
  // http, https, data, about, etc
18
- if (!url.startsWith("file:")) {
18
+ if (!reference.url.startsWith("file:")) {
19
19
  return null
20
20
  }
21
- const urlObject = new URL(url)
21
+ const urlObject = new URL(reference.url)
22
22
  const { search, hash } = urlObject
23
23
  urlObject.search = ""
24
24
  urlObject.hash = ""
@@ -26,7 +26,10 @@ export const jsenvPluginFileSystemMagic = ({
26
26
  urlObject.href,
27
27
  {
28
28
  magicDirectoryIndex,
29
- magicExtensions: getExtensionsToTry(magicExtensions, parentUrl),
29
+ magicExtensions: getExtensionsToTry(
30
+ magicExtensions,
31
+ reference.parentUrl,
32
+ ),
30
33
  },
31
34
  )
32
35
  if (!filesystemResolution.found) {
@@ -0,0 +1,242 @@
1
+ import { unevalException } from "./uneval_exception.js"
2
+ import { displayErrorInDocument } from "./error_in_document.js"
3
+ import { displayErrorNotification } from "./error_in_notification.js"
4
+
5
+ const { __html_supervisor__ } = window
6
+
7
+ export const installHtmlSupervisor = ({ logs, measurePerf }) => {
8
+ const errorTransformer = null // could implement error stack remapping if needed
9
+ const scriptExecutionResults = {}
10
+ let collectCalled = false
11
+ let pendingExecutionCount = 0
12
+ let resolveScriptExecutionsPromise
13
+ const scriptExecutionsPromise = new Promise((resolve) => {
14
+ resolveScriptExecutionsPromise = resolve
15
+ })
16
+ const onExecutionStart = (name) => {
17
+ scriptExecutionResults[name] = null // ensure execution order is reflected into the object
18
+ pendingExecutionCount++
19
+ if (measurePerf) {
20
+ performance.mark(`execution_start`)
21
+ }
22
+ }
23
+ const onExecutionSettled = (name, executionResult) => {
24
+ if (measurePerf) {
25
+ performance.measure(`execution`, `execution_start`)
26
+ }
27
+ scriptExecutionResults[name] = executionResult
28
+ pendingExecutionCount--
29
+ if (pendingExecutionCount === 0 && collectCalled) {
30
+ resolveScriptExecutionsPromise()
31
+ }
32
+ }
33
+ const onExecutionError = (
34
+ executionResult,
35
+ {
36
+ currentScript,
37
+ errorExposureInNotification = false,
38
+ errorExposureInDocument = true,
39
+ },
40
+ ) => {
41
+ const error = executionResult.error
42
+ if (error && error.code === "NETWORK_FAILURE") {
43
+ if (currentScript) {
44
+ const errorEvent = new Event("error")
45
+ currentScript.dispatchEvent(errorEvent)
46
+ }
47
+ } else if (typeof error === "object") {
48
+ const globalErrorEvent = new Event("error")
49
+ globalErrorEvent.filename = error.filename
50
+ globalErrorEvent.lineno = error.line || error.lineno
51
+ globalErrorEvent.colno = error.column || error.columnno
52
+ globalErrorEvent.message = error.message
53
+ window.dispatchEvent(globalErrorEvent)
54
+ }
55
+ if (errorExposureInNotification) {
56
+ displayErrorNotification(error)
57
+ }
58
+ if (errorExposureInDocument) {
59
+ displayErrorInDocument(error)
60
+ }
61
+ executionResult.exceptionSource = unevalException(error)
62
+ delete executionResult.error
63
+ }
64
+ const getNavigationStartTime = () => {
65
+ try {
66
+ return window.performance.timing.navigationStart
67
+ } catch (e) {
68
+ return Date.now()
69
+ }
70
+ }
71
+
72
+ const performExecution = async ({
73
+ src,
74
+ type,
75
+ currentScript,
76
+ execute,
77
+ // https://developer.mozilla.org/en-US/docs/web/html/element/script
78
+ }) => {
79
+ if (logs) {
80
+ console.group(`[jsenv] loading ${type} ${src}`)
81
+ }
82
+ onExecutionStart(src)
83
+ let completed
84
+ let result
85
+ let error
86
+ try {
87
+ result = await execute()
88
+ completed = true
89
+ } catch (e) {
90
+ completed = false
91
+ error = e
92
+ }
93
+ if (completed) {
94
+ const executionResult = {
95
+ status: "completed",
96
+ namespace: result,
97
+ coverage: window.__coverage__,
98
+ }
99
+ onExecutionSettled(src, executionResult)
100
+ if (logs) {
101
+ console.log(`${type} load ended`)
102
+ console.groupEnd()
103
+ }
104
+ return
105
+ }
106
+ const executionResult = {
107
+ status: "errored",
108
+ coverage: window.__coverage__,
109
+ }
110
+ let errorExposureInConsole = true
111
+ if (error.name === "SyntaxError") {
112
+ // errorExposureInConsole = false
113
+ }
114
+ if (errorTransformer) {
115
+ try {
116
+ error = await errorTransformer(error)
117
+ } catch (e) {}
118
+ }
119
+ executionResult.error = error
120
+ onExecutionSettled(src, executionResult)
121
+ onExecutionError(executionResult, {
122
+ currentScript,
123
+ })
124
+ if (errorExposureInConsole) {
125
+ if (typeof window.reportError === "function") {
126
+ window.reportError(error)
127
+ } else {
128
+ console.error(error)
129
+ }
130
+ }
131
+ if (logs) {
132
+ console.groupEnd()
133
+ }
134
+ }
135
+
136
+ const queue = []
137
+ let previousDonePromise = null
138
+ const dequeue = () => {
139
+ const next = queue.shift()
140
+ if (next) {
141
+ __html_supervisor__.addScriptToExecute(next)
142
+ } else {
143
+ const nextDefered = deferQueue.shift()
144
+ if (nextDefered) {
145
+ __html_supervisor__.addScriptToExecute(nextDefered)
146
+ }
147
+ }
148
+ }
149
+ const deferQueue = []
150
+ let previousDeferDonePromise = null
151
+ __html_supervisor__.addScriptToExecute = async (scriptToExecute) => {
152
+ if (scriptToExecute.async) {
153
+ performExecution(scriptToExecute)
154
+ return
155
+ }
156
+ const useDeferQueue =
157
+ scriptToExecute.defer || scriptToExecute.type === "js_module"
158
+ if (useDeferQueue) {
159
+ if (document.readyState !== "interactive") {
160
+ deferQueue.push(scriptToExecute)
161
+ return
162
+ }
163
+ if (previousDonePromise) {
164
+ // defer must wait for the regular script to be done
165
+ deferQueue.push(scriptToExecute)
166
+ return
167
+ }
168
+ if (previousDeferDonePromise) {
169
+ deferQueue.push(scriptToExecute)
170
+ return
171
+ }
172
+ previousDeferDonePromise = performExecution(scriptToExecute)
173
+ await previousDeferDonePromise
174
+ previousDeferDonePromise = null
175
+ dequeue()
176
+ return
177
+ }
178
+ if (previousDonePromise) {
179
+ queue.push(scriptToExecute)
180
+ return
181
+ }
182
+ previousDonePromise = performExecution(scriptToExecute)
183
+ await previousDonePromise
184
+ previousDonePromise = null
185
+ dequeue()
186
+ }
187
+ if (
188
+ document.readyState !== "intractive" &&
189
+ document.readyState !== "complete"
190
+ ) {
191
+ document.addEventListener("readystatechange", () => {
192
+ if (document.readyState === "interactive") {
193
+ const nextDefered = deferQueue.shift()
194
+ if (nextDefered) {
195
+ __html_supervisor__.addScriptToExecute(nextDefered)
196
+ }
197
+ }
198
+ })
199
+ }
200
+
201
+ __html_supervisor__.collectScriptResults = async () => {
202
+ collectCalled = true
203
+ if (pendingExecutionCount === 0) {
204
+ resolveScriptExecutionsPromise()
205
+ } else {
206
+ await scriptExecutionsPromise
207
+ }
208
+
209
+ let status = "completed"
210
+ let exceptionSource = ""
211
+ Object.keys(scriptExecutionResults).forEach((key) => {
212
+ const scriptExecutionResult = scriptExecutionResults[key]
213
+ if (scriptExecutionResult.status === "errored") {
214
+ status = "errored"
215
+ exceptionSource = scriptExecutionResult.exceptionSource
216
+ }
217
+ })
218
+ return {
219
+ status,
220
+ ...(status === "errored" ? { exceptionSource } : {}),
221
+ startTime: getNavigationStartTime(),
222
+ endTime: Date.now(),
223
+ scriptExecutionResults,
224
+ }
225
+ }
226
+
227
+ const { scriptsToExecute } = __html_supervisor__
228
+ const copy = scriptsToExecute.slice()
229
+ scriptsToExecute.length = 0
230
+ copy.forEach((scriptToExecute) => {
231
+ __html_supervisor__.addScriptToExecute(scriptToExecute)
232
+ })
233
+ }
234
+
235
+ export const superviseScriptTypeModule = ({ src, isInline }) => {
236
+ __html_supervisor__.addScriptToExecute({
237
+ src,
238
+ type: "js_module",
239
+ isInline,
240
+ execute: () => import(new URL(src, document.location.href).href),
241
+ })
242
+ }
@@ -0,0 +1,79 @@
1
+ window.__html_supervisor__ = {
2
+ // "html_supervisor_installer.js" will implement
3
+ // - "addScriptToExecute"
4
+ // - "superviseScriptTypeModule"
5
+ // - "collectScriptResults"
6
+ // and take all executions in "scriptsToExecute" and implement their supervision
7
+ scriptsToExecute: [],
8
+ addScriptToExecute: (scriptToExecute) => {
9
+ window.__html_supervisor__.scriptsToExecute.push(scriptToExecute)
10
+ },
11
+ superviseScript: ({ src, isInline, crossorigin, integrity }) => {
12
+ window.__html_supervisor__.addScriptToExecute({
13
+ src,
14
+ type: "js_classic",
15
+ isInline,
16
+ currentScript: document.currentScript,
17
+ execute: () => {
18
+ return new Promise((resolve, reject) => {
19
+ const script = document.createElement("script")
20
+ if (crossorigin) {
21
+ script.crossorigin = crossorigin
22
+ }
23
+ if (integrity) {
24
+ script.integrity = integrity
25
+ }
26
+ script.src = src
27
+ const scriptUrl = new URL(src, window.location).href
28
+ let lastWindowErrorUrl
29
+ let lastWindowError
30
+ const windowErrorCallback = (e) => {
31
+ lastWindowErrorUrl = e.filename
32
+ lastWindowError = e.error
33
+ }
34
+ const cleanup = () => {
35
+ document.body.removeChild(script)
36
+ window.removeEventListener("error", windowErrorCallback)
37
+ }
38
+ window.addEventListener("error", windowErrorCallback)
39
+ script.addEventListener("error", () => {
40
+ cleanup()
41
+ reject(src)
42
+ })
43
+ script.addEventListener("load", () => {
44
+ cleanup()
45
+ if (lastWindowErrorUrl === scriptUrl) {
46
+ reject(lastWindowError)
47
+ } else {
48
+ resolve()
49
+ }
50
+ })
51
+ document.body.appendChild(script)
52
+ })
53
+ },
54
+ })
55
+ },
56
+ superviseScriptTypeModule: () => {
57
+ throw new Error("htmlSupervisor not installed")
58
+ },
59
+ getScriptExecutionResults: () => {
60
+ // wait for page to load before collecting script execution results
61
+ const htmlReadyPromise = new Promise((resolve) => {
62
+ if (document.readyState === "complete") {
63
+ resolve()
64
+ return
65
+ }
66
+ const loadCallback = () => {
67
+ window.removeEventListener("load", loadCallback)
68
+ resolve()
69
+ }
70
+ window.addEventListener("load", loadCallback)
71
+ })
72
+ return htmlReadyPromise.then(() => {
73
+ return window.__html_supervisor__.collectScriptResults()
74
+ })
75
+ },
76
+ collectScriptResults: () => {
77
+ throw new Error("htmlSupervisor not installed")
78
+ },
79
+ }