@jsenv/core 24.2.2 → 24.4.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 (156) hide show
  1. package/dist/browser_runtime/browser_runtime-fbd309a1.js +5137 -0
  2. package/dist/browser_runtime/browser_runtime-fbd309a1.js.map +1064 -0
  3. package/dist/{jsenv_browser_system.js → browser_system/browser_system-29eda202.js} +12 -12
  4. package/dist/{jsenv_browser_system.js.map → browser_system/browser_system-29eda202.js.map} +64 -64
  5. package/dist/build_manifest.js +12 -0
  6. package/dist/compile_proxy/assets/s.js-749702e8.map +242 -0
  7. package/dist/compile_proxy/compile_proxy-405777e6.html +2074 -0
  8. package/dist/compile_proxy/compile_proxy.html__inline__20-39c0801c.js.map +385 -0
  9. package/dist/{jsenv_event_source_client.js → event_source_client/event_source_client-9f14c8b9.js} +39 -21
  10. package/dist/event_source_client/event_source_client-9f14c8b9.js.map +127 -0
  11. package/dist/redirector/assets/s.js-749702e8.map +242 -0
  12. package/dist/redirector/redirector-237cd168.html +2118 -0
  13. package/dist/redirector/redirector.html__inline__15-33acb0b9.js.map +390 -0
  14. package/dist/toolbar/assets/compilation.css-209d68b4.map +12 -0
  15. package/dist/toolbar/assets/eventsource.css-38cd0a36.map +12 -0
  16. package/dist/toolbar/assets/execution.css-0ebe522f.map +12 -0
  17. package/dist/toolbar/assets/focus.css-3f9c156d.map +12 -0
  18. package/dist/toolbar/assets/light-theme.css-78b19a80.map +12 -0
  19. package/dist/toolbar/assets/overflow-menu.css-d9688a1c.map +12 -0
  20. package/dist/toolbar/assets/s.js-749702e8.map +242 -0
  21. package/dist/toolbar/assets/settings.css-2b81b245.map +12 -0
  22. package/dist/toolbar/assets/toolbar.main.css-846920e9.map +28 -0
  23. package/dist/toolbar/assets/tooltip.css-03395ee6.map +12 -0
  24. package/dist/toolbar/toolbar-29e91dcd.html +4779 -0
  25. package/dist/toolbar/toolbar.main-53e1ab2b.js.map +795 -0
  26. package/dist/toolbar_injector/assets/jsenv-logo-188b9ca6.svg +95 -0
  27. package/dist/{jsenv_toolbar_injector.js → toolbar_injector/toolbar_injector-0af91b43.js} +87 -65
  28. package/dist/toolbar_injector/toolbar_injector-0af91b43.js.map +294 -0
  29. package/main.js +0 -1
  30. package/package.json +2 -1
  31. package/readme.md +10 -7
  32. package/src/buildProject.js +6 -2
  33. package/src/dev_server.js +22 -130
  34. package/src/execute.js +7 -10
  35. package/src/executeTestPlan.js +7 -1
  36. package/src/importUsingChildProcess.js +1 -1
  37. package/src/internal/{runtime/detectBrowser/detectBrowser.js → browser_detection/browser_detection.js} +0 -0
  38. package/src/internal/{runtime/detectBrowser → browser_detection}/detectAndroid.js +0 -0
  39. package/src/internal/{runtime/detectBrowser → browser_detection}/detectChrome.js +0 -0
  40. package/src/internal/{runtime/detectBrowser → browser_detection}/detectEdge.js +0 -0
  41. package/src/internal/{runtime/detectBrowser → browser_detection}/detectElectron.js +0 -0
  42. package/src/internal/{runtime/detectBrowser → browser_detection}/detectFirefox.js +0 -0
  43. package/src/internal/{runtime/detectBrowser → browser_detection}/detectIOS.js +0 -0
  44. package/src/internal/{runtime/detectBrowser → browser_detection}/detectInternetExplorer.js +0 -0
  45. package/src/internal/{runtime/detectBrowser → browser_detection}/detectOpera.js +0 -0
  46. package/src/internal/{runtime/detectBrowser → browser_detection}/detectSafari.js +0 -0
  47. package/src/internal/{runtime/detectBrowser → browser_detection}/util.js +0 -0
  48. package/src/internal/{runtime/createBrowserRuntime/scanBrowserRuntimeFeatures.js → browser_feature_detection/browser_feature_detection.js} +116 -81
  49. package/src/internal/browser_feature_detection/compile_proxy.html +27 -0
  50. package/src/internal/browser_launcher/browser_runtime_report.js +75 -0
  51. package/src/internal/{browser-launcher → browser_launcher}/executeHtmlFile.js +13 -16
  52. package/src/internal/browser_launcher/from_playwright.js +314 -0
  53. package/src/internal/{browser-launcher → browser_launcher}/trackPageToNotify.js +0 -0
  54. package/src/internal/{browser-launcher/jsenv-browser-system.js → browser_runtime/browser_runtime.js} +4 -4
  55. package/src/internal/{runtime/createBrowserRuntime/createBrowserSystem.js → browser_runtime/browser_system.js} +3 -2
  56. package/src/internal/{runtime/createBrowserRuntime → browser_runtime}/createBrowserRuntime.js +7 -5
  57. package/src/internal/{browser-launcher → browser_runtime}/displayErrorInDocument.js +0 -0
  58. package/src/internal/{browser-launcher → browser_runtime}/displayErrorNotification.js +2 -4
  59. package/src/internal/{runtime/createBrowserRuntime → browser_runtime}/evalSource.js +2 -0
  60. package/src/internal/{runtime/createBrowserRuntime → browser_runtime}/makeNamespaceTransferable.js +0 -0
  61. package/src/internal/{browser-utils → browser_utils}/fetch-browser.js +2 -0
  62. package/src/internal/{browser-utils → browser_utils}/fetchAndEvalUsingFetch.js +3 -0
  63. package/src/internal/{browser-utils → browser_utils}/fetchAndEvalUsingScript.js +2 -0
  64. package/src/internal/{browser-utils → browser_utils}/fetchJson.js +0 -0
  65. package/src/internal/{browser-utils → browser_utils}/fetchUsingXHR.js +4 -4
  66. package/src/internal/building/buildUsingRollup.js +4 -0
  67. package/src/internal/building/createJsenvRollupPlugin.js +19 -9
  68. package/src/internal/building/css/applyPostCss.js +19 -8
  69. package/src/internal/building/css/moveCssUrls.js +44 -0
  70. package/src/internal/building/css/parseCssRessource.js +67 -17
  71. package/src/internal/building/css/parseCssUrls.js +29 -23
  72. package/src/internal/building/css/postcss_plugin_url_visitor.js +11 -20
  73. package/src/internal/building/css/replaceCssUrls.js +38 -19
  74. package/src/internal/building/css_module.js +6 -10
  75. package/src/internal/building/html/parseHtmlRessource.js +37 -11
  76. package/src/internal/building/parseRessource.js +3 -0
  77. package/src/internal/building/ressource_builder.js +12 -3
  78. package/src/internal/compiling/babel_plugin_import_assertions.js +1 -2
  79. package/src/internal/compiling/html_source_file_service.js +23 -21
  80. package/src/internal/compiling/jsenvCompilerForHtml.js +15 -22
  81. package/src/internal/compiling/startCompileServer.js +37 -32
  82. package/src/internal/dev_server/event_source_client/event_source_connection.js +28 -19
  83. package/src/internal/dev_server/exploring/exploring.html +7 -2
  84. package/src/internal/dev_server/exploring/fetchExploringJson.js +4 -9
  85. package/src/internal/dev_server/redirector/redirector.html +37 -2
  86. package/src/internal/dev_server/toolbar/compilation/toolbar.compilation.js +4 -7
  87. package/src/internal/dev_server/toolbar/eventsource/toolbar.eventsource.js +2 -2
  88. package/src/internal/dev_server/toolbar/notification/toolbar.notification.js +75 -44
  89. package/src/internal/dev_server/toolbar/toolbar.html +31 -5
  90. package/src/internal/dev_server/toolbar/toolbar.injector.js +55 -36
  91. package/src/internal/dev_server/toolbar/toolbar.main.js +45 -31
  92. package/src/internal/dev_server/toolbar/util/fetching.js +1 -1
  93. package/src/internal/executing/executeConcurrently.js +15 -11
  94. package/src/internal/executing/executePlan.js +3 -2
  95. package/src/internal/generateGroupMap/one_runtime_compat.js +1 -1
  96. package/src/internal/generateGroupMap/runtime_compat_composition.js +1 -1
  97. package/src/internal/generateGroupMap/runtime_support.js +1 -1
  98. package/src/internal/jsenvInternalFiles.js +0 -26
  99. package/src/internal/jsenv_builds.js +19 -0
  100. package/src/internal/{runtime/node-feature-detect/feature-detect-dynamic-import.mjs → node_feature_detection/feature_detect_dynamic_import.mjs} +0 -0
  101. package/src/internal/{runtime/node-feature-detect/feature-detect-top-level-await.mjs → node_feature_detection/feature_detect_top_level_await.mjs} +0 -0
  102. package/src/internal/{runtime/node-feature-detect → node_feature_detection}/nodeSupportsDynamicImport.js +0 -0
  103. package/src/internal/node_feature_detection/nodeSupportsTopLevelAwait.js +16 -0
  104. package/src/internal/{runtime/createNodeRuntime/scanNodeRuntimeFeatures.js → node_feature_detection/node_feature_detection.js} +12 -13
  105. package/src/internal/{node-launcher → node_launcher}/createChildProcessOptions.js +0 -0
  106. package/src/internal/{node-launcher → node_launcher}/createControllableNodeProcess.js +9 -14
  107. package/src/internal/{node-launcher → node_launcher}/kill_process_tree.js +0 -0
  108. package/src/internal/node_launcher/node_runtime_report.js +71 -0
  109. package/src/internal/{node-launcher → node_launcher}/processOptions.js +0 -0
  110. package/src/internal/{runtime/detectNode → node_runtime}/detectNode.js +0 -0
  111. package/src/internal/{runtime/createNodeRuntime → node_runtime}/evalSource.js +1 -1
  112. package/src/internal/{runtime/createNodeRuntime → node_runtime}/fetchSource.js +1 -1
  113. package/src/internal/{node-launcher → node_runtime}/nodeControllableFile.mjs +14 -11
  114. package/src/internal/{runtime/createNodeRuntime/createNodeExecutionWithDynamicImport.js → node_runtime/node_execution_dynamic_import.js} +34 -6
  115. package/src/internal/node_runtime/node_execution_performance.js +67 -0
  116. package/src/internal/{runtime/createNodeRuntime/createNodeExecutionWithSystemJs.js → node_runtime/node_execution_systemjs.js} +38 -24
  117. package/src/internal/{runtime/createNodeRuntime/createNodeSystem.js → node_runtime/node_system.js} +4 -4
  118. package/src/internal/runtime/computeCompileIdFromGroupId.js +1 -0
  119. package/src/internal/runtime/resolveGroup.js +1 -1
  120. package/src/internal/runtime/resolveRuntimeGroup.js +2 -2
  121. package/src/internal/{semantic-versioning → semantic_versioning}/findHighestVersion.js +0 -0
  122. package/src/internal/{semantic-versioning → semantic_versioning}/findLowestVersion.js +0 -0
  123. package/src/internal/{semantic-versioning → semantic_versioning}/index.js +0 -0
  124. package/src/internal/{semantic-versioning → semantic_versioning}/valueToVersion.js +0 -0
  125. package/src/internal/{semantic-versioning → semantic_versioning}/versionCompare.js +0 -0
  126. package/src/internal/{semantic-versioning → semantic_versioning}/versionIsAbove.js +0 -0
  127. package/src/internal/{semantic-versioning → semantic_versioning}/versionIsBelow.js +0 -0
  128. package/src/internal/{semantic-versioning → semantic_versioning}/versionIsEqual.js +0 -0
  129. package/src/launchBrowser.js +33 -492
  130. package/src/launchNode.js +36 -7
  131. package/src/requireUsingChildProcess.js +1 -1
  132. package/dist/jsenv_compile_proxy.js +0 -1339
  133. package/dist/jsenv_compile_proxy.js.map +0 -378
  134. package/dist/jsenv_event_source_client.js.map +0 -126
  135. package/dist/jsenv_exploring_index.js +0 -1092
  136. package/dist/jsenv_exploring_index.js.map +0 -353
  137. package/dist/jsenv_exploring_redirector.js +0 -1386
  138. package/dist/jsenv_exploring_redirector.js.map +0 -384
  139. package/dist/jsenv_redirector.js +0 -1388
  140. package/dist/jsenv_redirector.js.map +0 -384
  141. package/dist/jsenv_toolbar.js +0 -2880
  142. package/dist/jsenv_toolbar.js.map +0 -771
  143. package/dist/jsenv_toolbar_injector.js.map +0 -301
  144. package/src/internal/browser-launcher/createSharing.js +0 -70
  145. package/src/internal/browser-launcher/jsenv_compile_proxy.html +0 -13
  146. package/src/internal/browser-launcher/jsenv_compile_proxy.js +0 -5
  147. package/src/internal/dev_server/event_source_client/event_source_client_file_info.js +0 -17
  148. package/src/internal/dev_server/exploring/exploring_file_info.js +0 -21
  149. package/src/internal/dev_server/redirector/redirector.js +0 -30
  150. package/src/internal/dev_server/redirector/redirector_file_info.js +0 -24
  151. package/src/internal/dev_server/toolbar/backtolist/toolbar.backtolist.js +0 -33
  152. package/src/internal/dev_server/toolbar/toolbar_file_info.js +0 -37
  153. package/src/internal/node-launcher/node-js-file.js +0 -110
  154. package/src/internal/runtime/createNodeRuntime/createNodeRuntime.js +0 -32
  155. package/src/internal/runtime/node-feature-detect/nodeSupportsTopLevelAwait.js +0 -18
  156. package/src/nodeRuntime.js +0 -5
@@ -0,0 +1,75 @@
1
+ export const getBrowserRuntimeReport = async ({
2
+ page,
3
+ coverageHandledFromOutside,
4
+ runtime,
5
+ compileServerId,
6
+ }) => {
7
+ const cache = cacheFromParams({
8
+ runtime,
9
+ compileServerId,
10
+ coverageHandledFromOutside,
11
+ })
12
+ const entry = cache.read()
13
+ if (entry) {
14
+ return entry
15
+ }
16
+ const browserRuntimeFeaturesReport = await page.evaluate(
17
+ /* istanbul ignore next */
18
+ async ({ coverageHandledFromOutside }) => {
19
+ // eslint-disable-next-line no-undef
20
+ await window.readyPromise
21
+
22
+ // eslint-disable-next-line no-undef
23
+ return window.scanBrowserRuntimeFeatures({
24
+ coverageHandledFromOutside,
25
+ failFastOnFeatureDetection: true,
26
+ })
27
+ },
28
+ { coverageHandledFromOutside },
29
+ )
30
+ cache.write(browserRuntimeFeaturesReport)
31
+ return browserRuntimeFeaturesReport
32
+ }
33
+
34
+ let currentCacheParams
35
+ let currentCacheValue
36
+ const cacheFromParams = ({
37
+ runtime,
38
+ compileServerId,
39
+ coverageHandledFromOutside,
40
+ }) => {
41
+ const params = {
42
+ compileServerId,
43
+ coverageHandledFromOutside,
44
+ }
45
+ const runtimeLabel = `${runtime.name}/${runtime.version}`
46
+
47
+ if (!currentCacheParams) {
48
+ currentCacheParams = params
49
+ currentCacheValue = {}
50
+ return {
51
+ read: () => null,
52
+ write: (value) => {
53
+ currentCacheValue[runtimeLabel] = value
54
+ },
55
+ }
56
+ }
57
+
58
+ if (JSON.stringify(currentCacheParams) !== JSON.stringify(params)) {
59
+ return {
60
+ read: () => null,
61
+ write: (value) => {
62
+ currentCacheParams = params
63
+ currentCacheValue = {}
64
+ currentCacheValue[runtimeLabel] = value
65
+ },
66
+ }
67
+ }
68
+
69
+ return {
70
+ read: () => currentCacheValue[runtimeLabel],
71
+ write: (value) => {
72
+ currentCacheValue[runtimeLabel] = value
73
+ },
74
+ }
75
+ }
@@ -5,18 +5,21 @@ import {
5
5
  urlToExtension,
6
6
  } from "@jsenv/filesystem"
7
7
 
8
- import { jsenvCompileProxyHtmlFileInfo } from "@jsenv/core/src/internal/jsenvInternalFiles.js"
8
+ import { COMPILE_PROXY_BUILD_URL } from "@jsenv/core/dist/build_manifest.js"
9
9
  import { filterV8Coverage } from "@jsenv/core/src/internal/executing/coverage_utils/v8_coverage_from_directory.js"
10
10
  import { composeTwoFileByFileIstanbulCoverages } from "@jsenv/core/src/internal/executing/coverage_utils/istanbul_coverage_composition.js"
11
- import { evalSource } from "../runtime/createNodeRuntime/evalSource.js"
11
+ import { evalSource } from "../node_runtime/evalSource.js"
12
12
  import { escapeRegexpSpecialCharacters } from "../escapeRegexpSpecialCharacters.js"
13
+ import { getBrowserRuntimeReport } from "./browser_runtime_report.js"
13
14
 
14
15
  export const executeHtmlFile = async (
15
16
  fileRelativeUrl,
16
17
  {
18
+ runtime,
17
19
  executeOperation,
18
20
  projectDirectoryUrl,
19
21
  compileServerOrigin,
22
+ compileServerId,
20
23
  outDirectoryRelativeUrl,
21
24
  page,
22
25
 
@@ -39,7 +42,7 @@ export const executeHtmlFile = async (
39
42
  await assertFilePresence(fileUrl)
40
43
 
41
44
  const compileProxyProjectRelativeUrl = urlToRelativeUrl(
42
- jsenvCompileProxyHtmlFileInfo.url,
45
+ COMPILE_PROXY_BUILD_URL,
43
46
  projectDirectoryUrl,
44
47
  )
45
48
  const compileProxyClientUrl = resolveUrl(
@@ -48,22 +51,16 @@ export const executeHtmlFile = async (
48
51
  )
49
52
  executeOperation.throwIfAborted()
50
53
  await page.goto(compileProxyClientUrl)
54
+ executeOperation.throwIfAborted()
51
55
 
52
56
  const coverageHandledFromOutside =
53
57
  coveragePlaywrightAPIAvailable && !coverageForceIstanbul
54
-
55
- executeOperation.throwIfAborted()
56
- const browserRuntimeFeaturesReport = await page.evaluate(
57
- /* istanbul ignore next */
58
- ({ coverageHandledFromOutside }) => {
59
- // eslint-disable-next-line no-undef
60
- return window.scanBrowserRuntimeFeatures({
61
- coverageHandledFromOutside,
62
- failFastOnFeatureDetection: true,
63
- })
64
- },
65
- { coverageHandledFromOutside },
66
- )
58
+ const browserRuntimeFeaturesReport = await getBrowserRuntimeReport({
59
+ page,
60
+ coverageHandledFromOutside,
61
+ compileServerId,
62
+ runtime,
63
+ })
67
64
 
68
65
  try {
69
66
  let executionResult
@@ -0,0 +1,314 @@
1
+ // https://github.com/microsoft/playwright/blob/master/docs/api.md
2
+
3
+ import { createDetailedMessage } from "@jsenv/logger"
4
+ import {
5
+ Abort,
6
+ createCallbackListNotifiedOnce,
7
+ createCallbackList,
8
+ raceProcessTeardownEvents,
9
+ } from "@jsenv/abort"
10
+ import { memoize } from "@jsenv/filesystem"
11
+
12
+ import { trackPageToNotify } from "./trackPageToNotify.js"
13
+ import { executeHtmlFile } from "./executeHtmlFile.js"
14
+
15
+ export const createRuntimeFromPlaywright = ({
16
+ browserName,
17
+ browserVersion,
18
+ coveragePlaywrightAPIAvailable = false,
19
+ ignoreErrorHook = () => false,
20
+ transformErrorHook = (error) => error,
21
+ tab = false,
22
+ }) => {
23
+ const runtime = {
24
+ name: browserName,
25
+ version: browserVersion,
26
+ }
27
+
28
+ let browserAndContextPromise
29
+ runtime.launch = async ({
30
+ signal = new AbortController().signal,
31
+ executablePath,
32
+ browserServerLogLevel,
33
+
34
+ projectDirectoryUrl,
35
+ compileServerOrigin,
36
+ outDirectoryRelativeUrl,
37
+
38
+ collectPerformance,
39
+ measurePerformance,
40
+ collectCoverage,
41
+ coverageIgnorePredicate,
42
+ coverageForceIstanbul,
43
+
44
+ headless = true,
45
+ stopOnExit = true,
46
+ ignoreHTTPSErrors = true,
47
+ stopAfterAllExecutionCallbackList,
48
+ }) => {
49
+ const stopCallbackList = createCallbackListNotifiedOnce()
50
+ const stoppedCallbackList = createCallbackListNotifiedOnce()
51
+ const errorCallbackList = createCallbackList()
52
+ const outputCallbackList = createCallbackList()
53
+
54
+ const stop = memoize(async (reason) => {
55
+ await stopCallbackList.notify({ reason })
56
+ stoppedCallbackList.notify({ reason })
57
+ return { graceful: false }
58
+ })
59
+ const closeBrowser = async () => {
60
+ const { browser } = await browserAndContextPromise
61
+ browserAndContextPromise = null
62
+ await stopBrowser(browser)
63
+ }
64
+
65
+ if (
66
+ !browserAndContextPromise ||
67
+ !tab ||
68
+ !stopAfterAllExecutionCallbackList
69
+ ) {
70
+ browserAndContextPromise = (async () => {
71
+ const browser = await launchBrowserUsingPlaywright({
72
+ signal,
73
+ browserName,
74
+ stopOnExit,
75
+ playwrightOptions: {
76
+ headless,
77
+ executablePath,
78
+ },
79
+ })
80
+ const browserContext = await browser.newContext({ ignoreHTTPSErrors })
81
+ return { browser, browserContext }
82
+ })()
83
+
84
+ // when using chromium tab during multiple executions we reuse the chromium browser
85
+ // and only once all executions are done we close the browser
86
+ if (tab && stopAfterAllExecutionCallbackList) {
87
+ stopAfterAllExecutionCallbackList.add(async () => {
88
+ await closeBrowser()
89
+ })
90
+ } else {
91
+ stopCallbackList.add(async () => {
92
+ await closeBrowser()
93
+ })
94
+ }
95
+ }
96
+
97
+ const { browser, browserContext } = await browserAndContextPromise
98
+ // https://github.com/GoogleChrome/puppeteer/blob/v1.4.0/docs/api.md#event-disconnected
99
+ browser.on("disconnected", () => {
100
+ stop()
101
+ })
102
+
103
+ const page = await browserContext.newPage()
104
+ stoppedCallbackList.add(async () => {
105
+ try {
106
+ await page.close()
107
+ } catch (e) {
108
+ if (isTargetClosedError(e)) {
109
+ return
110
+ }
111
+ throw e
112
+ }
113
+ })
114
+ const stopTrackingToNotify = trackPageToNotify(page, {
115
+ onError: (error) => {
116
+ error = transformErrorHook(error)
117
+ if (!ignoreErrorHook(error)) {
118
+ errorCallbackList.notify(error)
119
+ }
120
+ },
121
+ onConsole: outputCallbackList.notify,
122
+ })
123
+ stoppedCallbackList.add(stopTrackingToNotify)
124
+
125
+ const execute = createExecuteHook({
126
+ page,
127
+ runtime,
128
+ browserServerLogLevel,
129
+
130
+ projectDirectoryUrl,
131
+ compileServerOrigin,
132
+ outDirectoryRelativeUrl,
133
+
134
+ collectPerformance,
135
+ measurePerformance,
136
+ collectCoverage,
137
+ coverageIgnorePredicate,
138
+ coverageForceIstanbul,
139
+
140
+ coveragePlaywrightAPIAvailable,
141
+ transformErrorHook,
142
+ })
143
+
144
+ return {
145
+ stopCallbackList,
146
+ stoppedCallbackList,
147
+ errorCallbackList,
148
+ outputCallbackList,
149
+ execute,
150
+ stop,
151
+ }
152
+ }
153
+ if (!tab) {
154
+ runtime.tab = createRuntimeFromPlaywright({
155
+ browserName,
156
+ browserVersion,
157
+ coveragePlaywrightAPIAvailable,
158
+ ignoreErrorHook,
159
+ transformErrorHook,
160
+ tab: true,
161
+ })
162
+ }
163
+ return runtime
164
+ }
165
+
166
+ const stopBrowser = async (browser) => {
167
+ const disconnected = browser.isConnected()
168
+ ? new Promise((resolve) => {
169
+ const disconnectedCallback = () => {
170
+ browser.removeListener("disconnected", disconnectedCallback)
171
+ resolve()
172
+ }
173
+ browser.on("disconnected", disconnectedCallback)
174
+ })
175
+ : Promise.resolve()
176
+
177
+ // for some reason without this 100ms timeout
178
+ // browser.close() never resolves (playwright does not like something)
179
+ await new Promise((resolve) => setTimeout(resolve, 100))
180
+
181
+ try {
182
+ await browser.close()
183
+ } catch (e) {
184
+ if (isTargetClosedError(e)) {
185
+ return
186
+ }
187
+ throw e
188
+ }
189
+ await disconnected
190
+ }
191
+
192
+ const launchBrowserUsingPlaywright = async ({
193
+ signal,
194
+ browserName,
195
+ stopOnExit,
196
+ playwrightOptions,
197
+ }) => {
198
+ const launchBrowserOperation = Abort.startOperation()
199
+ launchBrowserOperation.addAbortSignal(signal)
200
+ const playwright = await importPlaywright({ browserName })
201
+ if (stopOnExit) {
202
+ launchBrowserOperation.addAbortSource((abort) => {
203
+ return raceProcessTeardownEvents(
204
+ {
205
+ SIGHUP: true,
206
+ SIGTERM: true,
207
+ SIGINT: true,
208
+ beforeExit: true,
209
+ exit: true,
210
+ },
211
+ abort,
212
+ )
213
+ })
214
+ }
215
+
216
+ const browserClass = playwright[browserName]
217
+ try {
218
+ const browser = await browserClass.launch({
219
+ ...playwrightOptions,
220
+ // let's handle them to close properly browser + remove listener
221
+ // instead of relying on playwright to do so
222
+ handleSIGINT: false,
223
+ handleSIGTERM: false,
224
+ handleSIGHUP: false,
225
+ })
226
+ launchBrowserOperation.throwIfAborted()
227
+ return browser
228
+ } catch (e) {
229
+ if (launchBrowserOperation.signal.aborted && isTargetClosedError(e)) {
230
+ // rethrow the abort error
231
+ launchBrowserOperation.throwIfAborted()
232
+ }
233
+ throw e
234
+ } finally {
235
+ await launchBrowserOperation.end()
236
+ }
237
+ }
238
+
239
+ const importPlaywright = async ({ browserName }) => {
240
+ try {
241
+ const namespace = await import("playwright")
242
+ return namespace
243
+ } catch (e) {
244
+ if (e.code === "ERR_MODULE_NOT_FOUND") {
245
+ throw new Error(
246
+ createDetailedMessage(
247
+ `"playwright" not found. You need playwright in your dependencies when using "${browserName}Runtime"`,
248
+ {
249
+ suggestion: `npm install --save-dev playwright`,
250
+ },
251
+ ),
252
+ { cause: e },
253
+ )
254
+ }
255
+ throw e
256
+ }
257
+ }
258
+
259
+ const createExecuteHook = ({
260
+ page,
261
+ runtime,
262
+ projectDirectoryUrl,
263
+ compileServerOrigin,
264
+ compileServerId,
265
+ outDirectoryRelativeUrl,
266
+
267
+ collectPerformance,
268
+ measurePerformance,
269
+ collectCoverage,
270
+ coverageIgnorePredicate,
271
+ coverageForceIstanbul,
272
+
273
+ coveragePlaywrightAPIAvailable,
274
+ transformErrorHook,
275
+ }) => {
276
+ const execute = async ({ signal, fileRelativeUrl }) => {
277
+ const executeOperation = Abort.startOperation()
278
+ executeOperation.addAbortSignal(signal)
279
+ executeOperation.throwIfAborted()
280
+ const result = await executeHtmlFile(fileRelativeUrl, {
281
+ runtime,
282
+ executeOperation,
283
+
284
+ projectDirectoryUrl,
285
+ compileServerOrigin,
286
+ compileServerId,
287
+ outDirectoryRelativeUrl,
288
+
289
+ page,
290
+ measurePerformance,
291
+ collectPerformance,
292
+ collectCoverage,
293
+ coverageForceIstanbul,
294
+ coveragePlaywrightAPIAvailable,
295
+ coverageIgnorePredicate,
296
+ transformErrorHook,
297
+ })
298
+ return result
299
+ }
300
+ return execute
301
+ }
302
+
303
+ const isTargetClosedError = (error) => {
304
+ if (error.message.match(/Protocol error \(.*?\): Target closed/)) {
305
+ return true
306
+ }
307
+ if (error.message.match(/Protocol error \(.*?\): Browser.*?closed/)) {
308
+ return true
309
+ }
310
+ if (error.message.includes("browserContext.close: Browser closed")) {
311
+ return true
312
+ }
313
+ return false
314
+ }
@@ -1,14 +1,14 @@
1
1
  /* eslint-env browser */
2
2
 
3
- import { unevalException } from "../unevalException.js"
4
- import { createBrowserRuntime } from "../runtime/createBrowserRuntime/createBrowserRuntime.js"
5
3
  import { installBrowserErrorStackRemapping } from "../error-stack-remapping/installBrowserErrorStackRemapping.js"
6
- import { fetchUrl } from "../browser-utils/fetch-browser.js"
7
- import { fetchAndEvalUsingFetch } from "../browser-utils/fetchAndEvalUsingFetch.js"
4
+ import { fetchUrl } from "../browser_utils/fetch-browser.js"
5
+ import { fetchAndEvalUsingFetch } from "../browser_utils/fetchAndEvalUsingFetch.js"
6
+ import { unevalException } from "../unevalException.js"
8
7
  import { memoize } from "../memoize.js"
9
8
 
10
9
  import { displayErrorInDocument } from "./displayErrorInDocument.js"
11
10
  import { displayErrorNotification } from "./displayErrorNotification.js"
11
+ import { createBrowserRuntime } from "./createBrowserRuntime.js"
12
12
 
13
13
  const getNavigationStartTime = () => {
14
14
  try {
@@ -1,6 +1,7 @@
1
- import { getJavaScriptModuleResponseError } from "../module-registration.js"
1
+ /* eslint-env browser */
2
2
 
3
- import "../s.js"
3
+ import { getJavaScriptModuleResponseError } from "../runtime/module-registration.js"
4
+ import "../runtime/s.js"
4
5
 
5
6
  export const createBrowserSystem = ({
6
7
  compileServerOrigin,
@@ -1,12 +1,14 @@
1
+ /* eslint-env browser */
2
+
1
3
  import { normalizeImportMap } from "@jsenv/importmap/src/normalizeImportMap.js"
2
4
 
3
5
  // do not use memoize from @jsenv/filesystem to avoid pulling @jsenv/filesystem code into the browser build
4
- import { memoize } from "../../memoize.js"
5
- import { fetchUrl } from "../../browser-utils/fetch-browser.js"
6
- import { createImportResolverForImportmap } from "../../import-resolution/import-resolver-importmap.js"
7
- import { measureAsyncFnPerf } from "../../perf_browser.js"
6
+ import { fetchUrl } from "../browser_utils/fetch-browser.js"
7
+ import { createImportResolverForImportmap } from "../import-resolution/import-resolver-importmap.js"
8
+ import { memoize } from "../memoize.js"
9
+ import { measureAsyncFnPerf } from "../perf_browser.js"
8
10
 
9
- import { createBrowserSystem } from "./createBrowserSystem.js"
11
+ import { createBrowserSystem } from "./browser_system.js"
10
12
  import { makeNamespaceTransferable } from "./makeNamespaceTransferable.js"
11
13
 
12
14
  const memoizedCreateBrowserSystem = memoize(createBrowserSystem)
@@ -3,10 +3,8 @@ const { Notification } = window
3
3
 
4
4
  const displayErrorNotificationNotAvailable = () => {}
5
5
 
6
- const displayErrorNotificationImplementation = async (error, { icon } = {}) => {
7
- const permission = await Notification.requestPermission()
8
-
9
- if (permission === "granted") {
6
+ const displayErrorNotificationImplementation = (error, { icon } = {}) => {
7
+ if (Notification.permission === "granted") {
10
8
  const notification = new Notification("An error occured", {
11
9
  lang: "en",
12
10
  body: error.stack,
@@ -1,3 +1,5 @@
1
+ /* eslint-env browser */
2
+
1
3
  export const evalSource = (code, href) => {
2
4
  // eslint-disable-next-line no-eval
3
5
  return window.eval(appendSourceURL(code, href))
@@ -1,3 +1,5 @@
1
+ /* eslint-env browser */
2
+
1
3
  import { fetchUsingXHR } from "./fetchUsingXHR.js"
2
4
 
3
5
  const fetchNative = async (url, { mode = "cors", ...options } = {}) => {
@@ -1,4 +1,7 @@
1
+ /* eslint-env browser */
2
+
1
3
  import { createDetailedMessage } from "@jsenv/logger"
4
+
2
5
  import { fetchUrl } from "./fetch-browser.js"
3
6
 
4
7
  export const fetchAndEvalUsingFetch = async (url) => {
@@ -1,3 +1,5 @@
1
+ /* eslint-env browser */
2
+
1
3
  export const fetchAndEvalUsingScript = async (src) => {
2
4
  return new Promise((resolve, reject) => {
3
5
  const script = document.createElement("script")
@@ -1,4 +1,4 @@
1
- import { createDetailedMessage } from "@jsenv/logger"
1
+ /* eslint-env browser */
2
2
 
3
3
  export const fetchUsingXHR = async (
4
4
  url,
@@ -206,9 +206,9 @@ const hasSearchParams = typeof window.URLSearchParams === "function"
206
206
 
207
207
  const createRequestError = (error, { url }) => {
208
208
  return new Error(
209
- createDetailedMessage(`error during xhr request on ${url}.`, {
210
- ["error stack"]: error.stack,
211
- }),
209
+ `error during xhr request on ${url}.
210
+ --- error stack ---
211
+ ${error.stack}`,
212
212
  )
213
213
  }
214
214
 
@@ -50,8 +50,10 @@ export const buildUsingRollup = async ({
50
50
  importPaths,
51
51
 
52
52
  urlVersioning,
53
+ urlVersionningForEntryPoints,
53
54
  lineBreakNormalization,
54
55
  jsConcatenation,
56
+ cssConcatenation,
55
57
  useImportMapToMaximizeCacheReuse,
56
58
  preserveEntrySignatures,
57
59
  treeshake,
@@ -121,8 +123,10 @@ export const buildUsingRollup = async ({
121
123
  importPaths,
122
124
 
123
125
  urlVersioning,
126
+ urlVersionningForEntryPoints,
124
127
  lineBreakNormalization,
125
128
  jsConcatenation,
129
+ cssConcatenation,
126
130
  useImportMapToMaximizeCacheReuse,
127
131
 
128
132
  minify,
@@ -12,6 +12,7 @@ import {
12
12
  urlIsInsideOf,
13
13
  normalizeStructuredMetaMap,
14
14
  urlToMeta,
15
+ urlToBasename,
15
16
  } from "@jsenv/filesystem"
16
17
  import { UNICODE } from "@jsenv/log"
17
18
 
@@ -72,8 +73,10 @@ export const createJsenvRollupPlugin = async ({
72
73
  importAssertionsSupport,
73
74
 
74
75
  urlVersioning,
76
+ urlVersionningForEntryPoints,
75
77
  lineBreakNormalization,
76
78
  jsConcatenation,
79
+ cssConcatenation,
77
80
  useImportMapToMaximizeCacheReuse,
78
81
 
79
82
  minify,
@@ -468,6 +471,7 @@ export const createJsenvRollupPlugin = async ({
468
471
  minifyJs,
469
472
  minifyHtml,
470
473
  minifyCssOptions,
474
+ cssConcatenation,
471
475
  })
472
476
  },
473
477
  },
@@ -586,9 +590,10 @@ export const createJsenvRollupPlugin = async ({
586
590
  atleastOneChunkEmitted = true
587
591
  emitChunk({
588
592
  id: ensureRelativeUrlNotation(entryProjectRelativeUrl),
589
- name: entryBuildRelativeUrl,
590
- // don't hash js entry points
591
- fileName: entryBuildRelativeUrl,
593
+ name: urlToBasename(`file:///${entryBuildRelativeUrl}`),
594
+ ...(urlVersionningForEntryPoints
595
+ ? {}
596
+ : { fileName: entryBuildRelativeUrl }),
592
597
  })
593
598
  return
594
599
  }
@@ -601,15 +606,16 @@ export const createJsenvRollupPlugin = async ({
601
606
  `Unusual content type for entry point, got "${entryContentType}" for ${entryProjectRelativeUrl}`,
602
607
  )
603
608
  }
604
- const entryUrl = resolveUrl(
605
- entryProjectRelativeUrl,
606
- compileServerOrigin,
607
- )
609
+ const entryUrl =
610
+ entryContentType === "text/html"
611
+ ? resolveUrl(entryProjectRelativeUrl, compileServerOrigin)
612
+ : resolveUrl(entryProjectRelativeUrl, compileDirectoryRemoteUrl)
608
613
  await ressourceBuilder.createReferenceForEntryPoint({
609
614
  entryContentType,
610
615
  entryUrl,
611
616
  entryBuffer,
612
617
  entryBuildRelativeUrl,
618
+ urlVersionningForEntryPoints,
613
619
  })
614
620
  },
615
621
  ),
@@ -1015,6 +1021,9 @@ export const createJsenvRollupPlugin = async ({
1015
1021
  return id
1016
1022
  }
1017
1023
  outputOptions.entryFileNames = () => {
1024
+ if (urlVersionningForEntryPoints) {
1025
+ return `[name]-[hash]${outputExtension}`
1026
+ }
1018
1027
  return `[name]${outputExtension}`
1019
1028
  }
1020
1029
  outputOptions.chunkFileNames = () => {
@@ -1097,7 +1106,9 @@ export const createJsenvRollupPlugin = async ({
1097
1106
  const file = jsChunks[fileName]
1098
1107
  let buildRelativeUrl
1099
1108
  const canBeVersioned =
1100
- asRollupUrl(file.url) in jsModulesFromEntry || !file.isEntry
1109
+ asRollupUrl(file.url) in jsModulesFromEntry ||
1110
+ urlVersionningForEntryPoints ||
1111
+ !file.isEntry
1101
1112
 
1102
1113
  if (urlVersioning) {
1103
1114
  if (canBeVersioned && useImportMapToMaximizeCacheReuse) {
@@ -1133,7 +1144,6 @@ export const createJsenvRollupPlugin = async ({
1133
1144
  buildInlineFileContents[buildRelativeUrl] = file.code
1134
1145
  } else {
1135
1146
  markBuildRelativeUrlAsUsedByJs(buildRelativeUrl)
1136
- buildManifest[fileName] = buildRelativeUrl
1137
1147
  buildMappings[originalProjectRelativeUrl] = buildRelativeUrl
1138
1148
  }
1139
1149
  })