@jsenv/core 27.3.2 → 27.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 (38) hide show
  1. package/README.md +16 -4
  2. package/dist/controllable_child_process.mjs +1 -0
  3. package/dist/controllable_worker_thread.mjs +1 -0
  4. package/dist/js/event_source_client.js +45 -24
  5. package/dist/js/execute_using_dynamic_import.js +5 -3
  6. package/dist/js/html_supervisor_installer.js +368 -139
  7. package/dist/main.js +668 -471
  8. package/package.json +5 -6
  9. package/src/build/build.js +6 -4
  10. package/src/build/graph_utils.js +14 -11
  11. package/src/execute/run.js +29 -28
  12. package/src/execute/runtimes/browsers/from_playwright.js +90 -92
  13. package/src/execute/runtimes/node/execute_using_dynamic_import.js +8 -2
  14. package/src/execute/runtimes/node/node_child_process.js +2 -0
  15. package/src/execute/runtimes/node/node_worker_thread.js +11 -6
  16. package/src/helpers/event_source/event_source.js +38 -17
  17. package/src/omega/errors.js +41 -9
  18. package/src/omega/kitchen.js +35 -19
  19. package/src/omega/omega_server.js +54 -1
  20. package/src/omega/server/file_service.js +30 -3
  21. package/src/omega/url_graph/url_graph_report.js +2 -4
  22. package/src/omega/url_graph.js +29 -16
  23. package/src/plugins/autoreload/dev_sse/client/event_source_client.js +8 -8
  24. package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js +160 -172
  25. package/src/plugins/autoreload/jsenv_plugin_autoreload.js +0 -4
  26. package/src/plugins/bundling/js_module/bundle_js_module.js +0 -1
  27. package/src/plugins/html_supervisor/client/error_in_document.js +268 -121
  28. package/src/plugins/html_supervisor/client/html_supervisor_installer.js +47 -5
  29. package/src/plugins/html_supervisor/jsenv_plugin_html_supervisor.js +37 -12
  30. package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +1 -2
  31. package/src/plugins/plugins.js +0 -2
  32. package/src/plugins/url_analysis/js/js_urls.js +0 -9
  33. package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +3 -1
  34. package/src/test/coverage/report_to_coverage.js +16 -11
  35. package/src/test/execute_plan.js +3 -2
  36. package/src/test/execute_test_plan.js +3 -1
  37. package/src/test/logs_file_execution.js +60 -27
  38. package/src/test/logs_file_execution.test.mjs +41 -0
@@ -1,184 +1,180 @@
1
1
  import { urlToRelativeUrl } from "@jsenv/urls"
2
- import { createCallbackList } from "@jsenv/abort"
3
-
4
- import { createSSEService } from "@jsenv/core/src/helpers/event_source/sse_service.js"
5
2
 
6
3
  export const jsenvPluginDevSSEServer = ({
7
- rootDirectoryUrl,
8
- urlGraph,
9
4
  clientFileChangeCallbackList,
10
5
  clientFilesPruneCallbackList,
11
6
  }) => {
12
- const serverEventCallbackList = createCallbackList()
13
- const sseService = createSSEService({ serverEventCallbackList })
14
-
15
- const notifyDeclined = ({ cause, reason, declinedBy }) => {
16
- serverEventCallbackList.notify({
17
- type: "reload",
18
- data: JSON.stringify({
19
- cause,
20
- type: "full",
21
- typeReason: reason,
22
- declinedBy,
23
- }),
24
- })
25
- }
26
- const notifyAccepted = ({ cause, reason, instructions }) => {
27
- serverEventCallbackList.notify({
28
- type: "reload",
29
- data: JSON.stringify({
30
- cause,
31
- type: "hot",
32
- typeReason: reason,
33
- hotInstructions: instructions,
34
- }),
35
- })
36
- }
37
- const propagateUpdate = (firstUrlInfo) => {
38
- const urlInfos = urlGraph.urlInfos
39
- const iterate = (urlInfo, trace) => {
40
- if (urlInfo.data.hotAcceptSelf) {
41
- return {
42
- accepted: true,
43
- reason:
44
- urlInfo === firstUrlInfo
45
- ? `file accepts hot reload`
46
- : `a dependent file accepts hot reload`,
47
- instructions: [
48
- {
49
- type: urlInfo.type,
50
- boundary: urlToRelativeUrl(urlInfo.url, rootDirectoryUrl),
51
- acceptedBy: urlToRelativeUrl(urlInfo.url, rootDirectoryUrl),
52
- },
53
- ],
54
- }
7
+ return {
8
+ name: "jsenv:sse_server",
9
+ appliesDuring: { dev: true },
10
+ registerServerEvents: (
11
+ { sendServerEvent },
12
+ { rootDirectoryUrl, urlGraph },
13
+ ) => {
14
+ const notifyDeclined = ({ cause, reason, declinedBy }) => {
15
+ sendServerEvent({
16
+ type: "reload",
17
+ data: {
18
+ cause,
19
+ type: "full",
20
+ typeReason: reason,
21
+ declinedBy,
22
+ },
23
+ })
55
24
  }
56
- const { dependents } = urlInfo
57
- const instructions = []
58
- for (const dependentUrl of dependents) {
59
- const dependentUrlInfo = urlInfos[dependentUrl]
60
- if (dependentUrlInfo.data.hotDecline) {
61
- return {
62
- declined: true,
63
- reason: `a dependent file declines hot reload`,
64
- declinedBy: dependentUrl,
25
+ const notifyAccepted = ({ cause, reason, instructions }) => {
26
+ sendServerEvent({
27
+ type: "reload",
28
+ data: {
29
+ cause,
30
+ type: "hot",
31
+ typeReason: reason,
32
+ hotInstructions: instructions,
33
+ },
34
+ })
35
+ }
36
+ const propagateUpdate = (firstUrlInfo) => {
37
+ const iterate = (urlInfo, seen) => {
38
+ if (urlInfo.data.hotAcceptSelf) {
39
+ return {
40
+ accepted: true,
41
+ reason:
42
+ urlInfo === firstUrlInfo
43
+ ? `file accepts hot reload`
44
+ : `a dependent file accepts hot reload`,
45
+ instructions: [
46
+ {
47
+ type: urlInfo.type,
48
+ boundary: urlToRelativeUrl(urlInfo.url, rootDirectoryUrl),
49
+ acceptedBy: urlToRelativeUrl(urlInfo.url, rootDirectoryUrl),
50
+ },
51
+ ],
52
+ }
53
+ }
54
+ const { dependents } = urlInfo
55
+ const instructions = []
56
+ for (const dependentUrl of dependents) {
57
+ const dependentUrlInfo = urlGraph.getUrlInfo(dependentUrl)
58
+ if (dependentUrlInfo.data.hotDecline) {
59
+ return {
60
+ declined: true,
61
+ reason: `a dependent file declines hot reload`,
62
+ declinedBy: dependentUrl,
63
+ }
64
+ }
65
+ const { hotAcceptDependencies = [] } = dependentUrlInfo.data
66
+ if (hotAcceptDependencies.includes(urlInfo.url)) {
67
+ instructions.push({
68
+ type: dependentUrlInfo.type,
69
+ boundary: urlToRelativeUrl(dependentUrl, rootDirectoryUrl),
70
+ acceptedBy: urlToRelativeUrl(urlInfo.url, rootDirectoryUrl),
71
+ })
72
+ continue
73
+ }
74
+ if (seen.includes(dependentUrl)) {
75
+ return {
76
+ declined: true,
77
+ reason: "circular dependency",
78
+ declinedBy: urlToRelativeUrl(dependentUrl, rootDirectoryUrl),
79
+ }
80
+ }
81
+ const dependentPropagationResult = iterate(dependentUrlInfo, [
82
+ ...seen,
83
+ dependentUrl,
84
+ ])
85
+ if (dependentPropagationResult.accepted) {
86
+ instructions.push(...dependentPropagationResult.instructions)
87
+ continue
88
+ }
89
+ if (
90
+ // declined explicitely by an other file, it must decline the whole update
91
+ dependentPropagationResult.declinedBy
92
+ ) {
93
+ return dependentPropagationResult
94
+ }
95
+ // declined by absence of boundary, we can keep searching
96
+ continue
97
+ }
98
+ if (instructions.length === 0) {
99
+ return {
100
+ declined: true,
101
+ reason: `there is no file accepting hot reload while propagating update`,
102
+ }
65
103
  }
66
- }
67
- const { hotAcceptDependencies = [] } = dependentUrlInfo.data
68
- if (hotAcceptDependencies.includes(urlInfo.url)) {
69
- instructions.push({
70
- type: dependentUrlInfo.type,
71
- boundary: urlToRelativeUrl(dependentUrl, rootDirectoryUrl),
72
- acceptedBy: urlToRelativeUrl(urlInfo.url, rootDirectoryUrl),
73
- })
74
- continue
75
- }
76
- if (trace.includes(dependentUrl)) {
77
104
  return {
78
- declined: true,
79
- reason: "circular dependency",
80
- declinedBy: urlToRelativeUrl(dependentUrl, rootDirectoryUrl),
105
+ accepted: true,
106
+ reason: `${instructions.length} dependent file(s) accepts hot reload`,
107
+ instructions,
81
108
  }
82
109
  }
83
- const dependentPropagationResult = iterate(dependentUrlInfo, [
84
- ...trace,
85
- dependentUrl,
86
- ])
87
- if (dependentPropagationResult.accepted) {
88
- instructions.push(...dependentPropagationResult.instructions)
89
- continue
90
- }
91
- if (
92
- // declined explicitely by an other file, it must decline the whole update
93
- dependentPropagationResult.declinedBy
94
- ) {
95
- return dependentPropagationResult
96
- }
97
- // declined by absence of boundary, we can keep searching
98
- continue
110
+ const seen = []
111
+ return iterate(firstUrlInfo, seen)
99
112
  }
100
- if (instructions.length === 0) {
101
- return {
102
- declined: true,
103
- reason: `there is no file accepting hot reload while propagating update`,
113
+ clientFileChangeCallbackList.push(({ url, event }) => {
114
+ const urlInfo = urlGraph.getUrlInfo(url)
115
+ // file not part of dependency graph
116
+ if (!urlInfo) {
117
+ return
118
+ }
119
+ const relativeUrl = urlToRelativeUrl(url, rootDirectoryUrl)
120
+ const hotUpdate = propagateUpdate(urlInfo)
121
+ if (hotUpdate.declined) {
122
+ notifyDeclined({
123
+ cause: `${relativeUrl} ${event}`,
124
+ reason: hotUpdate.reason,
125
+ declinedBy: hotUpdate.declinedBy,
126
+ })
127
+ } else {
128
+ notifyAccepted({
129
+ cause: `${relativeUrl} ${event}`,
130
+ reason: hotUpdate.reason,
131
+ instructions: hotUpdate.instructions,
132
+ })
104
133
  }
105
- }
106
- return {
107
- accepted: true,
108
- reason: `${instructions.length} dependent file(s) accepts hot reload`,
109
- instructions,
110
- }
111
- }
112
- const trace = []
113
- return iterate(firstUrlInfo, trace)
114
- }
115
- clientFileChangeCallbackList.push(({ url, event }) => {
116
- const urlInfo = urlGraph.getUrlInfo(url)
117
- // file not part of dependency graph
118
- if (!urlInfo) {
119
- return
120
- }
121
- const relativeUrl = urlToRelativeUrl(url, rootDirectoryUrl)
122
- const hotUpdate = propagateUpdate(urlInfo)
123
- if (hotUpdate.declined) {
124
- notifyDeclined({
125
- cause: `${relativeUrl} ${event}`,
126
- reason: hotUpdate.reason,
127
- declinedBy: hotUpdate.declinedBy,
128
- })
129
- } else {
130
- notifyAccepted({
131
- cause: `${relativeUrl} ${event}`,
132
- reason: hotUpdate.reason,
133
- instructions: hotUpdate.instructions,
134
- })
135
- }
136
- })
137
- clientFilesPruneCallbackList.push(({ prunedUrlInfos, firstUrlInfo }) => {
138
- const mainHotUpdate = propagateUpdate(firstUrlInfo)
139
- const cause = `following files are no longer referenced: ${prunedUrlInfos.map(
140
- (prunedUrlInfo) => urlToRelativeUrl(prunedUrlInfo.url, rootDirectoryUrl),
141
- )}`
142
- // now check if we can hot update the main ressource
143
- // then if we can hot update all dependencies
144
- if (mainHotUpdate.declined) {
145
- notifyDeclined({
146
- cause,
147
- reason: mainHotUpdate.reason,
148
- declinedBy: mainHotUpdate.declinedBy,
149
134
  })
150
- return
151
- }
152
- // main can hot update
153
- let i = 0
154
- const instructions = []
155
- while (i < prunedUrlInfos.length) {
156
- const prunedUrlInfo = prunedUrlInfos[i++]
157
- if (prunedUrlInfo.data.hotDecline) {
158
- notifyDeclined({
135
+ clientFilesPruneCallbackList.push(({ prunedUrlInfos, firstUrlInfo }) => {
136
+ const mainHotUpdate = propagateUpdate(firstUrlInfo)
137
+ const cause = `following files are no longer referenced: ${prunedUrlInfos.map(
138
+ (prunedUrlInfo) =>
139
+ urlToRelativeUrl(prunedUrlInfo.url, rootDirectoryUrl),
140
+ )}`
141
+ // now check if we can hot update the main ressource
142
+ // then if we can hot update all dependencies
143
+ if (mainHotUpdate.declined) {
144
+ notifyDeclined({
145
+ cause,
146
+ reason: mainHotUpdate.reason,
147
+ declinedBy: mainHotUpdate.declinedBy,
148
+ })
149
+ return
150
+ }
151
+ // main can hot update
152
+ let i = 0
153
+ const instructions = []
154
+ while (i < prunedUrlInfos.length) {
155
+ const prunedUrlInfo = prunedUrlInfos[i++]
156
+ if (prunedUrlInfo.data.hotDecline) {
157
+ notifyDeclined({
158
+ cause,
159
+ reason: `a pruned file declines hot reload`,
160
+ declinedBy: urlToRelativeUrl(prunedUrlInfo.url, rootDirectoryUrl),
161
+ })
162
+ return
163
+ }
164
+ instructions.push({
165
+ type: "prune",
166
+ boundary: urlToRelativeUrl(prunedUrlInfo.url, rootDirectoryUrl),
167
+ acceptedBy: urlToRelativeUrl(firstUrlInfo.url, rootDirectoryUrl),
168
+ })
169
+ }
170
+ notifyAccepted({
159
171
  cause,
160
- reason: `a pruned file declines hot reload`,
161
- declinedBy: urlToRelativeUrl(prunedUrlInfo.url, rootDirectoryUrl),
172
+ reason: mainHotUpdate.reason,
173
+ instructions,
162
174
  })
163
- return
164
- }
165
- instructions.push({
166
- type: "prune",
167
- boundary: urlToRelativeUrl(prunedUrlInfo.url, rootDirectoryUrl),
168
- acceptedBy: urlToRelativeUrl(firstUrlInfo.url, rootDirectoryUrl),
169
175
  })
170
- }
171
- notifyAccepted({
172
- cause,
173
- reason: mainHotUpdate.reason,
174
- instructions,
175
- })
176
- })
177
-
178
- return {
179
- name: "jsenv:sse_server",
180
- appliesDuring: { dev: true },
181
- serve: (request) => {
176
+ },
177
+ serve: (request, { rootDirectoryUrl, urlGraph }) => {
182
178
  if (request.ressource === "/__graph__") {
183
179
  const graphJson = JSON.stringify(urlGraph.toJSON(rootDirectoryUrl))
184
180
  return {
@@ -190,15 +186,7 @@ export const jsenvPluginDevSSEServer = ({
190
186
  body: graphJson,
191
187
  }
192
188
  }
193
- const { accept } = request.headers
194
- if (accept && accept.includes("text/event-stream")) {
195
- const room = sseService.getOrCreateSSERoom(request)
196
- return room.join(request)
197
- }
198
189
  return null
199
190
  },
200
- destroy: () => {
201
- sseService.destroy()
202
- },
203
191
  }
204
192
  }
@@ -3,8 +3,6 @@ import { jsenvPluginDevSSEClient } from "./dev_sse/jsenv_plugin_dev_sse_client.j
3
3
  import { jsenvPluginDevSSEServer } from "./dev_sse/jsenv_plugin_dev_sse_server.js"
4
4
 
5
5
  export const jsenvPluginAutoreload = ({
6
- rootDirectoryUrl,
7
- urlGraph,
8
6
  scenario,
9
7
  clientFileChangeCallbackList,
10
8
  clientFilesPruneCallbackList,
@@ -16,8 +14,6 @@ export const jsenvPluginAutoreload = ({
16
14
  jsenvPluginHmr(),
17
15
  jsenvPluginDevSSEClient(),
18
16
  jsenvPluginDevSSEServer({
19
- rootDirectoryUrl,
20
- urlGraph,
21
17
  clientFileChangeCallbackList,
22
18
  clientFilesPruneCallbackList,
23
19
  }),
@@ -125,7 +125,6 @@ const rollupPluginJsenv = ({
125
125
  usesImport:
126
126
  rollupFileInfo.imports.length > 0 ||
127
127
  rollupFileInfo.dynamicImports.length > 0,
128
- usesExport: rollupFileInfo.exports.length > 0,
129
128
  },
130
129
  contentType: "text/javascript",
131
130
  content: rollupFileInfo.code,