@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.
- package/README.md +16 -4
- package/dist/controllable_child_process.mjs +1 -0
- package/dist/controllable_worker_thread.mjs +1 -0
- package/dist/js/event_source_client.js +45 -24
- package/dist/js/execute_using_dynamic_import.js +5 -3
- package/dist/js/html_supervisor_installer.js +368 -139
- package/dist/main.js +668 -471
- package/package.json +5 -6
- package/src/build/build.js +6 -4
- package/src/build/graph_utils.js +14 -11
- package/src/execute/run.js +29 -28
- package/src/execute/runtimes/browsers/from_playwright.js +90 -92
- package/src/execute/runtimes/node/execute_using_dynamic_import.js +8 -2
- package/src/execute/runtimes/node/node_child_process.js +2 -0
- package/src/execute/runtimes/node/node_worker_thread.js +11 -6
- package/src/helpers/event_source/event_source.js +38 -17
- package/src/omega/errors.js +41 -9
- package/src/omega/kitchen.js +35 -19
- package/src/omega/omega_server.js +54 -1
- package/src/omega/server/file_service.js +30 -3
- package/src/omega/url_graph/url_graph_report.js +2 -4
- package/src/omega/url_graph.js +29 -16
- package/src/plugins/autoreload/dev_sse/client/event_source_client.js +8 -8
- package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js +160 -172
- package/src/plugins/autoreload/jsenv_plugin_autoreload.js +0 -4
- package/src/plugins/bundling/js_module/bundle_js_module.js +0 -1
- package/src/plugins/html_supervisor/client/error_in_document.js +268 -121
- package/src/plugins/html_supervisor/client/html_supervisor_installer.js +47 -5
- package/src/plugins/html_supervisor/jsenv_plugin_html_supervisor.js +37 -12
- package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +1 -2
- package/src/plugins/plugins.js +0 -2
- package/src/plugins/url_analysis/js/js_urls.js +0 -9
- package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +3 -1
- package/src/test/coverage/report_to_coverage.js +16 -11
- package/src/test/execute_plan.js +3 -2
- package/src/test/execute_test_plan.js +3 -1
- package/src/test/logs_file_execution.js +60 -27
- package/src/test/logs_file_execution.test.mjs +41 -0
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
/* eslint-env browser */
|
|
2
2
|
|
|
3
|
+
const STATUSES = {
|
|
4
|
+
CONNECTING: "connecting",
|
|
5
|
+
CONNECTED: "connected",
|
|
6
|
+
DISCONNECTED: "disconnected",
|
|
7
|
+
}
|
|
8
|
+
|
|
3
9
|
export const createEventSourceConnection = (
|
|
4
10
|
eventSourceUrl,
|
|
5
|
-
events = {},
|
|
6
11
|
{ retryMaxAttempt = Infinity, retryAllocatedMs = Infinity, lastEventId } = {},
|
|
7
12
|
) => {
|
|
8
13
|
const { EventSource } = window
|
|
@@ -10,18 +15,26 @@ export const createEventSourceConnection = (
|
|
|
10
15
|
return () => {}
|
|
11
16
|
}
|
|
12
17
|
|
|
18
|
+
let eventSource
|
|
19
|
+
const events = {}
|
|
13
20
|
const eventSourceOrigin = new URL(eventSourceUrl).origin
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (e.
|
|
19
|
-
|
|
21
|
+
const addEventCallbacks = (eventCallbacks) => {
|
|
22
|
+
Object.keys(eventCallbacks).forEach((eventName) => {
|
|
23
|
+
const eventCallback = eventCallbacks[eventName]
|
|
24
|
+
events[eventName] = (e) => {
|
|
25
|
+
if (e.origin === eventSourceOrigin) {
|
|
26
|
+
if (e.lastEventId) {
|
|
27
|
+
lastEventId = e.lastEventId
|
|
28
|
+
}
|
|
29
|
+
eventCallback(e)
|
|
20
30
|
}
|
|
21
|
-
eventCallback(e)
|
|
22
31
|
}
|
|
23
|
-
|
|
24
|
-
|
|
32
|
+
if (eventSource) {
|
|
33
|
+
eventSource.addEventListener(eventName, events[eventName])
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
addEventCallbacks(events)
|
|
25
38
|
|
|
26
39
|
const status = {
|
|
27
40
|
value: "default",
|
|
@@ -37,11 +50,14 @@ export const createEventSourceConnection = (
|
|
|
37
50
|
let _disconnect = () => {}
|
|
38
51
|
|
|
39
52
|
const attemptConnection = (url) => {
|
|
40
|
-
|
|
53
|
+
eventSource = new EventSource(url, {
|
|
41
54
|
withCredentials: true,
|
|
42
55
|
})
|
|
43
56
|
_disconnect = () => {
|
|
44
|
-
if (
|
|
57
|
+
if (
|
|
58
|
+
status.value !== STATUSES.CONNECTING &&
|
|
59
|
+
status.value !== STATUSES.CONNECTED
|
|
60
|
+
) {
|
|
45
61
|
console.warn(
|
|
46
62
|
`disconnect() ignored because connection is ${status.value}`,
|
|
47
63
|
)
|
|
@@ -52,7 +68,8 @@ export const createEventSourceConnection = (
|
|
|
52
68
|
Object.keys(events).forEach((eventName) => {
|
|
53
69
|
eventSource.removeEventListener(eventName, events[eventName])
|
|
54
70
|
})
|
|
55
|
-
|
|
71
|
+
eventSource = null
|
|
72
|
+
status.goTo(STATUSES.DISCONNECTED)
|
|
56
73
|
}
|
|
57
74
|
let retryCount = 0
|
|
58
75
|
let firstRetryMs = Date.now()
|
|
@@ -78,7 +95,7 @@ export const createEventSourceConnection = (
|
|
|
78
95
|
}
|
|
79
96
|
|
|
80
97
|
retryCount++
|
|
81
|
-
status.goTo(
|
|
98
|
+
status.goTo(STATUSES.CONNECTING)
|
|
82
99
|
return
|
|
83
100
|
}
|
|
84
101
|
|
|
@@ -88,7 +105,7 @@ export const createEventSourceConnection = (
|
|
|
88
105
|
}
|
|
89
106
|
}
|
|
90
107
|
eventSource.onopen = () => {
|
|
91
|
-
status.goTo(
|
|
108
|
+
status.goTo(STATUSES.CONNECTED)
|
|
92
109
|
}
|
|
93
110
|
Object.keys(events).forEach((eventName) => {
|
|
94
111
|
eventSource.addEventListener(eventName, events[eventName])
|
|
@@ -100,7 +117,7 @@ export const createEventSourceConnection = (
|
|
|
100
117
|
}
|
|
101
118
|
})
|
|
102
119
|
}
|
|
103
|
-
status.goTo(
|
|
120
|
+
status.goTo(STATUSES.CONNECTING)
|
|
104
121
|
}
|
|
105
122
|
|
|
106
123
|
let connect = () => {
|
|
@@ -115,7 +132,10 @@ export const createEventSourceConnection = (
|
|
|
115
132
|
}
|
|
116
133
|
|
|
117
134
|
const removePageUnloadListener = listenPageUnload(() => {
|
|
118
|
-
if (
|
|
135
|
+
if (
|
|
136
|
+
status.value === STATUSES.CONNECTING ||
|
|
137
|
+
status.value === STATUSES.CONNECTED
|
|
138
|
+
) {
|
|
119
139
|
_disconnect()
|
|
120
140
|
}
|
|
121
141
|
})
|
|
@@ -128,6 +148,7 @@ export const createEventSourceConnection = (
|
|
|
128
148
|
return {
|
|
129
149
|
status,
|
|
130
150
|
connect,
|
|
151
|
+
addEventCallbacks,
|
|
131
152
|
disconnect: () => _disconnect(),
|
|
132
153
|
destroy,
|
|
133
154
|
}
|
package/src/omega/errors.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createDetailedMessage } from "@jsenv/log"
|
|
2
|
+
import { stringifyUrlSite } from "@jsenv/urls"
|
|
2
3
|
|
|
3
4
|
export const createResolveUrlError = ({
|
|
4
5
|
pluginController,
|
|
@@ -15,7 +16,7 @@ export const createResolveUrlError = ({
|
|
|
15
16
|
reason,
|
|
16
17
|
...details,
|
|
17
18
|
"specifier": `"${reference.specifier}"`,
|
|
18
|
-
"specifier trace": reference.trace,
|
|
19
|
+
"specifier trace": reference.trace.message,
|
|
19
20
|
...detailsFromPluginController(pluginController),
|
|
20
21
|
}),
|
|
21
22
|
)
|
|
@@ -46,19 +47,23 @@ export const createFetchUrlContentError = ({
|
|
|
46
47
|
reason,
|
|
47
48
|
...details
|
|
48
49
|
}) => {
|
|
49
|
-
const
|
|
50
|
+
const fetchError = new Error(
|
|
50
51
|
createDetailedMessage(`Failed to fetch url content`, {
|
|
51
52
|
reason,
|
|
52
53
|
...details,
|
|
53
54
|
"url": urlInfo.url,
|
|
54
|
-
"url reference trace": reference.trace,
|
|
55
|
+
"url reference trace": reference.trace.message,
|
|
55
56
|
...detailsFromPluginController(pluginController),
|
|
56
57
|
}),
|
|
57
58
|
)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
fetchError.name = "FETCH_URL_CONTENT_ERROR"
|
|
60
|
+
fetchError.code = code
|
|
61
|
+
fetchError.reason = reason
|
|
62
|
+
fetchError.url = reference.trace.url
|
|
63
|
+
fetchError.line = reference.trace.line
|
|
64
|
+
fetchError.column = reference.trace.column
|
|
65
|
+
fetchError.contentFrame = reference.trace.message
|
|
66
|
+
return fetchError
|
|
62
67
|
}
|
|
63
68
|
|
|
64
69
|
if (error.code === "EPERM") {
|
|
@@ -103,7 +108,7 @@ export const createTransformUrlContentError = ({
|
|
|
103
108
|
reason,
|
|
104
109
|
...details,
|
|
105
110
|
"url": urlInfo.url,
|
|
106
|
-
"url reference trace": reference.trace,
|
|
111
|
+
"url reference trace": reference.trace.message,
|
|
107
112
|
...detailsFromPluginController(pluginController),
|
|
108
113
|
},
|
|
109
114
|
),
|
|
@@ -111,6 +116,33 @@ export const createTransformUrlContentError = ({
|
|
|
111
116
|
transformError.name = "TRANSFORM_URL_CONTENT_ERROR"
|
|
112
117
|
transformError.code = code
|
|
113
118
|
transformError.reason = reason
|
|
119
|
+
transformError.url = reference.trace.url
|
|
120
|
+
transformError.line = reference.trace.line
|
|
121
|
+
transformError.column = reference.trace.column
|
|
122
|
+
transformError.stack = error.stack
|
|
123
|
+
transformError.contentFrame = reference.trace.message
|
|
124
|
+
if (code === "PARSE_ERROR") {
|
|
125
|
+
transformError.reason = error.message
|
|
126
|
+
if (urlInfo.isInline) {
|
|
127
|
+
transformError.line = reference.trace.line + error.line - 1
|
|
128
|
+
transformError.column = reference.trace.column + error.column
|
|
129
|
+
transformError.contentFrame = stringifyUrlSite({
|
|
130
|
+
url: urlInfo.inlineUrlSite.url,
|
|
131
|
+
line: transformError.line,
|
|
132
|
+
column: transformError.column,
|
|
133
|
+
content: urlInfo.inlineUrlSite.content,
|
|
134
|
+
})
|
|
135
|
+
} else {
|
|
136
|
+
transformError.line = error.line
|
|
137
|
+
transformError.column = error.column
|
|
138
|
+
transformError.contentFrame = stringifyUrlSite({
|
|
139
|
+
url: urlInfo.url,
|
|
140
|
+
line: transformError.line,
|
|
141
|
+
column: transformError.column,
|
|
142
|
+
content: urlInfo.content,
|
|
143
|
+
})
|
|
144
|
+
}
|
|
145
|
+
}
|
|
114
146
|
return transformError
|
|
115
147
|
}
|
|
116
148
|
return createFailedToTransformError({
|
|
@@ -130,7 +162,7 @@ export const createFinalizeUrlContentError = ({
|
|
|
130
162
|
"reason": `An error occured during "finalizeUrlContent"`,
|
|
131
163
|
...detailsFromValueThrown(error),
|
|
132
164
|
"url": urlInfo.url,
|
|
133
|
-
"url reference trace": reference.trace,
|
|
165
|
+
"url reference trace": reference.trace.message,
|
|
134
166
|
...detailsFromPluginController(pluginController),
|
|
135
167
|
}),
|
|
136
168
|
)
|
package/src/omega/kitchen.js
CHANGED
|
@@ -221,7 +221,10 @@ export const createKitchen = ({
|
|
|
221
221
|
sourcemapsRelativeSources,
|
|
222
222
|
injectSourcemapPlaceholder: ({ urlInfo, specifier }) => {
|
|
223
223
|
const sourcemapReference = createReference({
|
|
224
|
-
trace:
|
|
224
|
+
trace: {
|
|
225
|
+
message: `sourcemap comment placeholder`,
|
|
226
|
+
url: urlInfo.url,
|
|
227
|
+
},
|
|
225
228
|
type: "sourcemap_comment",
|
|
226
229
|
subtype: urlInfo.contentType === "text/javascript" ? "js" : "css",
|
|
227
230
|
parentUrl: urlInfo.url,
|
|
@@ -238,15 +241,14 @@ export const createKitchen = ({
|
|
|
238
241
|
specifierLine,
|
|
239
242
|
specifierColumn,
|
|
240
243
|
}) => {
|
|
244
|
+
const sourcemapUrlSite = adjustUrlSite(urlInfo, {
|
|
245
|
+
urlGraph,
|
|
246
|
+
url: urlInfo.url,
|
|
247
|
+
line: specifierLine,
|
|
248
|
+
column: specifierColumn,
|
|
249
|
+
})
|
|
241
250
|
const sourcemapReference = createReference({
|
|
242
|
-
trace:
|
|
243
|
-
adjustUrlSite(urlInfo, {
|
|
244
|
-
urlGraph,
|
|
245
|
-
url: urlInfo.url,
|
|
246
|
-
line: specifierLine,
|
|
247
|
-
column: specifierColumn,
|
|
248
|
-
}),
|
|
249
|
-
),
|
|
251
|
+
trace: traceFromUrlSite(sourcemapUrlSite),
|
|
250
252
|
type,
|
|
251
253
|
parentUrl: urlInfo.url,
|
|
252
254
|
specifier,
|
|
@@ -273,7 +275,7 @@ export const createKitchen = ({
|
|
|
273
275
|
`no plugin has handled url during "fetchUrlContent" hook -> url will be ignored`,
|
|
274
276
|
{
|
|
275
277
|
"url": urlInfo.url,
|
|
276
|
-
"url reference trace": reference.trace,
|
|
278
|
+
"url reference trace": reference.trace.message,
|
|
277
279
|
},
|
|
278
280
|
),
|
|
279
281
|
)
|
|
@@ -408,7 +410,7 @@ export const createKitchen = ({
|
|
|
408
410
|
},
|
|
409
411
|
found: ({ trace, ...rest }) => {
|
|
410
412
|
if (trace === undefined) {
|
|
411
|
-
trace =
|
|
413
|
+
trace = traceFromUrlSite(
|
|
412
414
|
adjustUrlSite(urlInfo, {
|
|
413
415
|
urlGraph,
|
|
414
416
|
url: urlInfo.url,
|
|
@@ -423,7 +425,12 @@ export const createKitchen = ({
|
|
|
423
425
|
...rest,
|
|
424
426
|
})
|
|
425
427
|
},
|
|
426
|
-
foundInline: ({
|
|
428
|
+
foundInline: ({
|
|
429
|
+
isOriginalPosition,
|
|
430
|
+
specifierLine,
|
|
431
|
+
specifierColumn,
|
|
432
|
+
...rest
|
|
433
|
+
}) => {
|
|
427
434
|
const parentUrl = isOriginalPosition
|
|
428
435
|
? urlInfo.url
|
|
429
436
|
: urlInfo.generatedUrl
|
|
@@ -431,15 +438,15 @@ export const createKitchen = ({
|
|
|
431
438
|
? urlInfo.originalContent
|
|
432
439
|
: urlInfo.content
|
|
433
440
|
return addReference({
|
|
434
|
-
trace:
|
|
441
|
+
trace: traceFromUrlSite({
|
|
435
442
|
url: parentUrl,
|
|
436
443
|
content: parentContent,
|
|
437
|
-
line,
|
|
438
|
-
column,
|
|
444
|
+
line: specifierLine,
|
|
445
|
+
column: specifierColumn,
|
|
439
446
|
}),
|
|
440
447
|
isOriginalPosition,
|
|
441
|
-
|
|
442
|
-
|
|
448
|
+
specifierLine,
|
|
449
|
+
specifierColumn,
|
|
443
450
|
isInline: true,
|
|
444
451
|
...rest,
|
|
445
452
|
})
|
|
@@ -487,7 +494,7 @@ export const createKitchen = ({
|
|
|
487
494
|
? urlInfo.originalContent
|
|
488
495
|
: urlInfo.content
|
|
489
496
|
return referenceUtils.update(reference, {
|
|
490
|
-
trace:
|
|
497
|
+
trace: traceFromUrlSite({
|
|
491
498
|
url: parentUrl,
|
|
492
499
|
content: parentContent,
|
|
493
500
|
line: specifierLine,
|
|
@@ -505,7 +512,7 @@ export const createKitchen = ({
|
|
|
505
512
|
inject: ({ trace, ...rest }) => {
|
|
506
513
|
if (trace === undefined) {
|
|
507
514
|
const { url, line, column } = getCallerPosition()
|
|
508
|
-
trace =
|
|
515
|
+
trace = traceFromUrlSite({
|
|
509
516
|
url,
|
|
510
517
|
line,
|
|
511
518
|
column,
|
|
@@ -722,6 +729,15 @@ const memoizeCook = (cook) => {
|
|
|
722
729
|
}
|
|
723
730
|
}
|
|
724
731
|
|
|
732
|
+
const traceFromUrlSite = (urlSite) => {
|
|
733
|
+
return {
|
|
734
|
+
message: stringifyUrlSite(urlSite),
|
|
735
|
+
url: urlSite.url,
|
|
736
|
+
line: urlSite.line,
|
|
737
|
+
column: urlSite.column,
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
|
|
725
741
|
const applyReferenceEffectsOnUrlInfo = (reference, urlInfo, context) => {
|
|
726
742
|
if (reference.shouldHandle) {
|
|
727
743
|
urlInfo.shouldHandle = true
|
|
@@ -7,8 +7,12 @@ import {
|
|
|
7
7
|
pluginCORS,
|
|
8
8
|
} from "@jsenv/server"
|
|
9
9
|
import { convertFileSystemErrorToResponseProperties } from "@jsenv/server/src/internal/convertFileSystemErrorToResponseProperties.js"
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
createCallbackListNotifiedOnce,
|
|
12
|
+
createCallbackList,
|
|
13
|
+
} from "@jsenv/abort"
|
|
11
14
|
|
|
15
|
+
import { createSSEService } from "@jsenv/core/src/helpers/event_source/sse_service.js"
|
|
12
16
|
import { createFileService } from "./server/file_service.js"
|
|
13
17
|
|
|
14
18
|
export const startOmegaServer = async ({
|
|
@@ -33,12 +37,60 @@ export const startOmegaServer = async ({
|
|
|
33
37
|
kitchen,
|
|
34
38
|
}) => {
|
|
35
39
|
const serverStopCallbackList = createCallbackListNotifiedOnce()
|
|
40
|
+
|
|
41
|
+
const serverEventCallbackList = createCallbackList()
|
|
42
|
+
const sseService = createSSEService({ serverEventCallbackList })
|
|
43
|
+
const sendServerEvent = ({ type, data }) => {
|
|
44
|
+
serverEventCallbackList.notify({
|
|
45
|
+
type,
|
|
46
|
+
data: JSON.stringify(data),
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
kitchen.pluginController.addHook("registerServerEvents")
|
|
51
|
+
kitchen.pluginController.callHooks(
|
|
52
|
+
"registerServerEvents",
|
|
53
|
+
{ sendServerEvent },
|
|
54
|
+
{
|
|
55
|
+
rootDirectoryUrl,
|
|
56
|
+
urlGraph,
|
|
57
|
+
scenario,
|
|
58
|
+
},
|
|
59
|
+
() => {},
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
const sendServerErrorEvent = (event) => {
|
|
63
|
+
// setTimeout display first the error
|
|
64
|
+
// dispatched on window by browser
|
|
65
|
+
// then display the jsenv error
|
|
66
|
+
setTimeout(() => {
|
|
67
|
+
sendServerEvent(event)
|
|
68
|
+
}, 10)
|
|
69
|
+
}
|
|
70
|
+
|
|
36
71
|
const coreServices = {
|
|
72
|
+
"service:server_events": (request) => {
|
|
73
|
+
const { accept } = request.headers
|
|
74
|
+
if (accept && accept.includes("text/event-stream")) {
|
|
75
|
+
const room = sseService.getOrCreateSSERoom(request)
|
|
76
|
+
return room.join(request)
|
|
77
|
+
}
|
|
78
|
+
return null
|
|
79
|
+
},
|
|
37
80
|
"service:file": createFileService({
|
|
38
81
|
rootDirectoryUrl,
|
|
39
82
|
urlGraph,
|
|
40
83
|
kitchen,
|
|
41
84
|
scenario,
|
|
85
|
+
onFileNotFound: (data) => {
|
|
86
|
+
sendServerErrorEvent({ type: "file_not_found", data })
|
|
87
|
+
},
|
|
88
|
+
onParseError: (data) => {
|
|
89
|
+
sendServerErrorEvent({ type: "parse_error", data })
|
|
90
|
+
},
|
|
91
|
+
onUnexpectedError: (data) => {
|
|
92
|
+
sendServerErrorEvent({ type: "unexpected_error", data })
|
|
93
|
+
},
|
|
42
94
|
}),
|
|
43
95
|
}
|
|
44
96
|
const server = await startServer({
|
|
@@ -119,6 +171,7 @@ export const startOmegaServer = async ({
|
|
|
119
171
|
}),
|
|
120
172
|
onStop: (reason) => {
|
|
121
173
|
onStop()
|
|
174
|
+
sseService.destroy()
|
|
122
175
|
serverStopCallbackList.notify(reason)
|
|
123
176
|
},
|
|
124
177
|
})
|
|
@@ -12,6 +12,9 @@ export const createFileService = ({
|
|
|
12
12
|
urlGraph,
|
|
13
13
|
kitchen,
|
|
14
14
|
scenario,
|
|
15
|
+
onParseError,
|
|
16
|
+
onFileNotFound,
|
|
17
|
+
onUnexpectedError,
|
|
15
18
|
}) => {
|
|
16
19
|
kitchen.pluginController.addHook("serve")
|
|
17
20
|
kitchen.pluginController.addHook("augmentResponse")
|
|
@@ -51,7 +54,7 @@ export const createFileService = ({
|
|
|
51
54
|
}
|
|
52
55
|
if (!reference) {
|
|
53
56
|
const entryPoint = kitchen.injectReference({
|
|
54
|
-
trace: parentUrl || rootDirectoryUrl,
|
|
57
|
+
trace: { message: parentUrl || rootDirectoryUrl },
|
|
55
58
|
parentUrl: parentUrl || rootDirectoryUrl,
|
|
56
59
|
type: "http_request",
|
|
57
60
|
specifier: request.ressource,
|
|
@@ -135,10 +138,17 @@ export const createFileService = ({
|
|
|
135
138
|
} catch (e) {
|
|
136
139
|
const code = e.code
|
|
137
140
|
if (code === "PARSE_ERROR") {
|
|
138
|
-
|
|
141
|
+
onParseError({
|
|
142
|
+
reason: e.reason,
|
|
143
|
+
message: e.message,
|
|
144
|
+
url: e.url,
|
|
145
|
+
line: e.line,
|
|
146
|
+
column: e.column,
|
|
147
|
+
contentFrame: e.contentFrame,
|
|
148
|
+
})
|
|
139
149
|
return {
|
|
140
150
|
url: reference.url,
|
|
141
|
-
status: 200,
|
|
151
|
+
status: 200, // let the browser re-throw the syntax error
|
|
142
152
|
statusText: e.reason,
|
|
143
153
|
statusMessage: e.message,
|
|
144
154
|
headers: {
|
|
@@ -166,6 +176,14 @@ export const createFileService = ({
|
|
|
166
176
|
}
|
|
167
177
|
}
|
|
168
178
|
if (code === "NOT_FOUND") {
|
|
179
|
+
onFileNotFound({
|
|
180
|
+
reason: e.reason,
|
|
181
|
+
message: e.message,
|
|
182
|
+
url: e.url,
|
|
183
|
+
line: e.line,
|
|
184
|
+
column: e.column,
|
|
185
|
+
contentFrame: e.contentFrame,
|
|
186
|
+
})
|
|
169
187
|
return {
|
|
170
188
|
url: reference.url,
|
|
171
189
|
status: 404,
|
|
@@ -173,6 +191,15 @@ export const createFileService = ({
|
|
|
173
191
|
statusMessage: e.message,
|
|
174
192
|
}
|
|
175
193
|
}
|
|
194
|
+
onUnexpectedError({
|
|
195
|
+
reason: e.reason,
|
|
196
|
+
message: e.message,
|
|
197
|
+
stack: e.stack,
|
|
198
|
+
url: e.url,
|
|
199
|
+
line: e.line,
|
|
200
|
+
column: e.column,
|
|
201
|
+
contentFrame: e.contentFrame,
|
|
202
|
+
})
|
|
176
203
|
return {
|
|
177
204
|
url: reference.url,
|
|
178
205
|
status: 500,
|
|
@@ -11,7 +11,6 @@ ${createRepartitionMessage(graphReport)}
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
const createUrlGraphReport = (urlGraph) => {
|
|
14
|
-
const { urlInfos } = urlGraph
|
|
15
14
|
const countGroups = {
|
|
16
15
|
sourcemaps: 0,
|
|
17
16
|
html: 0,
|
|
@@ -30,11 +29,10 @@ const createUrlGraphReport = (urlGraph) => {
|
|
|
30
29
|
other: 0,
|
|
31
30
|
total: 0,
|
|
32
31
|
}
|
|
33
|
-
|
|
34
|
-
if (url.startsWith("data:")) {
|
|
32
|
+
urlGraph.urlInfoMap.forEach((urlInfo) => {
|
|
33
|
+
if (urlInfo.url.startsWith("data:")) {
|
|
35
34
|
return
|
|
36
35
|
}
|
|
37
|
-
const urlInfo = urlInfos[url]
|
|
38
36
|
// ignore:
|
|
39
37
|
// - inline files: they are already taken into account in the file where they appear
|
|
40
38
|
// - ignored files: we don't know their content
|
package/src/omega/url_graph.js
CHANGED
|
@@ -5,12 +5,12 @@ export const createUrlGraph = ({
|
|
|
5
5
|
clientFileChangeCallbackList,
|
|
6
6
|
clientFilesPruneCallbackList,
|
|
7
7
|
} = {}) => {
|
|
8
|
-
const
|
|
9
|
-
const getUrlInfo = (url) =>
|
|
8
|
+
const urlInfoMap = new Map()
|
|
9
|
+
const getUrlInfo = (url) => urlInfoMap.get(url)
|
|
10
10
|
const deleteUrlInfo = (url) => {
|
|
11
|
-
const urlInfo =
|
|
11
|
+
const urlInfo = urlInfoMap.get(url)
|
|
12
12
|
if (urlInfo) {
|
|
13
|
-
delete
|
|
13
|
+
urlInfoMap.delete(url)
|
|
14
14
|
if (urlInfo.sourcemapReference) {
|
|
15
15
|
deleteUrlInfo(urlInfo.sourcemapReference.url)
|
|
16
16
|
}
|
|
@@ -18,14 +18,14 @@ export const createUrlGraph = ({
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
const reuseOrCreateUrlInfo = (url) => {
|
|
21
|
-
const existingUrlInfo =
|
|
21
|
+
const existingUrlInfo = getUrlInfo(url)
|
|
22
22
|
if (existingUrlInfo) return existingUrlInfo
|
|
23
23
|
const urlInfo = createUrlInfo(url)
|
|
24
|
-
|
|
24
|
+
urlInfoMap.set(url, urlInfo)
|
|
25
25
|
return urlInfo
|
|
26
26
|
}
|
|
27
27
|
const inferReference = (specifier, parentUrl) => {
|
|
28
|
-
const parentUrlInfo =
|
|
28
|
+
const parentUrlInfo = getUrlInfo(parentUrl)
|
|
29
29
|
if (!parentUrlInfo) {
|
|
30
30
|
return null
|
|
31
31
|
}
|
|
@@ -37,13 +37,13 @@ export const createUrlGraph = ({
|
|
|
37
37
|
return firstReferenceOnThatUrl
|
|
38
38
|
}
|
|
39
39
|
const findDependent = (url, predicate) => {
|
|
40
|
-
const urlInfo =
|
|
40
|
+
const urlInfo = getUrlInfo(url)
|
|
41
41
|
if (!urlInfo) {
|
|
42
42
|
return null
|
|
43
43
|
}
|
|
44
44
|
const visitDependents = (urlInfo) => {
|
|
45
45
|
for (const dependentUrl of urlInfo.dependents) {
|
|
46
|
-
const dependent =
|
|
46
|
+
const dependent = getUrlInfo(dependentUrl)
|
|
47
47
|
if (predicate(dependent)) {
|
|
48
48
|
return dependent
|
|
49
49
|
}
|
|
@@ -90,7 +90,7 @@ export const createUrlGraph = ({
|
|
|
90
90
|
const removeDependencies = (urlInfo, urlsToPrune) => {
|
|
91
91
|
urlsToPrune.forEach((urlToPrune) => {
|
|
92
92
|
urlInfo.dependencies.delete(urlToPrune)
|
|
93
|
-
const dependency =
|
|
93
|
+
const dependency = getUrlInfo(urlToPrune)
|
|
94
94
|
if (!dependency) {
|
|
95
95
|
return
|
|
96
96
|
}
|
|
@@ -122,7 +122,7 @@ export const createUrlGraph = ({
|
|
|
122
122
|
|
|
123
123
|
if (clientFileChangeCallbackList) {
|
|
124
124
|
clientFileChangeCallbackList.push(({ url }) => {
|
|
125
|
-
const urlInfo =
|
|
125
|
+
const urlInfo = getUrlInfo(url)
|
|
126
126
|
if (urlInfo) {
|
|
127
127
|
considerModified(urlInfo, Date.now())
|
|
128
128
|
}
|
|
@@ -139,12 +139,18 @@ export const createUrlGraph = ({
|
|
|
139
139
|
urlInfo.modifiedTimestamp = modifiedTimestamp
|
|
140
140
|
urlInfo.contentEtag = undefined
|
|
141
141
|
urlInfo.dependents.forEach((dependentUrl) => {
|
|
142
|
-
const dependentUrlInfo =
|
|
142
|
+
const dependentUrlInfo = getUrlInfo(dependentUrl)
|
|
143
143
|
const { hotAcceptDependencies = [] } = dependentUrlInfo.data
|
|
144
144
|
if (!hotAcceptDependencies.includes(urlInfo.url)) {
|
|
145
145
|
iterate(dependentUrlInfo)
|
|
146
146
|
}
|
|
147
147
|
})
|
|
148
|
+
urlInfo.dependencies.forEach((dependencyUrl) => {
|
|
149
|
+
const dependencyUrlInfo = getUrlInfo(dependencyUrl)
|
|
150
|
+
if (dependencyUrlInfo.isInline) {
|
|
151
|
+
iterate(dependencyUrlInfo)
|
|
152
|
+
}
|
|
153
|
+
})
|
|
148
154
|
}
|
|
149
155
|
iterate(urlInfo)
|
|
150
156
|
}
|
|
@@ -164,7 +170,7 @@ export const createUrlGraph = ({
|
|
|
164
170
|
}
|
|
165
171
|
|
|
166
172
|
return {
|
|
167
|
-
|
|
173
|
+
urlInfoMap,
|
|
168
174
|
reuseOrCreateUrlInfo,
|
|
169
175
|
getUrlInfo,
|
|
170
176
|
deleteUrlInfo,
|
|
@@ -174,12 +180,19 @@ export const createUrlGraph = ({
|
|
|
174
180
|
considerModified,
|
|
175
181
|
getRelatedUrlInfos,
|
|
176
182
|
|
|
183
|
+
toObject: () => {
|
|
184
|
+
const data = {}
|
|
185
|
+
urlInfoMap.forEach((urlInfo) => {
|
|
186
|
+
data[urlInfo.url] = urlInfo
|
|
187
|
+
})
|
|
188
|
+
return data
|
|
189
|
+
},
|
|
177
190
|
toJSON: (rootDirectoryUrl) => {
|
|
178
191
|
const data = {}
|
|
179
|
-
|
|
180
|
-
const dependencyUrls = Array.from(
|
|
192
|
+
urlInfoMap.forEach((urlInfo) => {
|
|
193
|
+
const dependencyUrls = Array.from(urlInfo.dependencies)
|
|
181
194
|
if (dependencyUrls.length) {
|
|
182
|
-
const relativeUrl = urlToRelativeUrl(url, rootDirectoryUrl)
|
|
195
|
+
const relativeUrl = urlToRelativeUrl(urlInfo.url, rootDirectoryUrl)
|
|
183
196
|
data[relativeUrl] = dependencyUrls.map((dependencyUrl) =>
|
|
184
197
|
urlToRelativeUrl(dependencyUrl, rootDirectoryUrl),
|
|
185
198
|
)
|
|
@@ -157,21 +157,21 @@ const addReloadMessage = (reloadMessage) => {
|
|
|
157
157
|
|
|
158
158
|
const eventsourceConnection = createEventSourceConnection(
|
|
159
159
|
document.location.href,
|
|
160
|
-
{
|
|
161
|
-
reload: ({ data }) => {
|
|
162
|
-
const reloadMessage = JSON.parse(data)
|
|
163
|
-
addReloadMessage(reloadMessage)
|
|
164
|
-
},
|
|
165
|
-
},
|
|
166
160
|
{
|
|
167
161
|
retryMaxAttempt: Infinity,
|
|
168
162
|
retryAllocatedMs: 20 * 1000,
|
|
169
163
|
},
|
|
170
164
|
)
|
|
171
|
-
|
|
172
|
-
|
|
165
|
+
const { status, connect, addEventCallbacks, disconnect } = eventsourceConnection
|
|
166
|
+
eventsourceConnection.addEventCallbacks({
|
|
167
|
+
reload: ({ data }) => {
|
|
168
|
+
const reloadMessage = JSON.parse(data)
|
|
169
|
+
addReloadMessage(reloadMessage)
|
|
170
|
+
},
|
|
171
|
+
})
|
|
173
172
|
connect()
|
|
174
173
|
window.__jsenv_event_source_client__ = {
|
|
174
|
+
addEventCallbacks,
|
|
175
175
|
status,
|
|
176
176
|
connect,
|
|
177
177
|
disconnect,
|