@jsenv/core 27.5.3 → 27.7.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/dist/js/autoreload.js +10 -6
- package/dist/js/html_supervisor_installer.js +272 -163
- package/dist/js/html_supervisor_setup.js +10 -2
- package/dist/js/server_events_client.js +249 -216
- package/dist/js/wrapper.mjs +4233 -0
- package/dist/main.js +21342 -21629
- package/package.json +4 -4
- package/src/build/build.js +15 -13
- package/src/dev/start_dev_server.js +10 -10
- package/src/execute/runtimes/browsers/chromium.js +1 -1
- package/src/execute/runtimes/browsers/firefox.js +1 -1
- package/src/execute/runtimes/browsers/webkit.js +1 -1
- package/src/omega/kitchen.js +13 -15
- package/src/omega/omega_server.js +15 -0
- package/src/omega/server/file_service.js +11 -84
- package/src/omega/url_graph/url_graph_load.js +0 -2
- package/src/omega/url_graph/url_info_transformations.js +27 -0
- package/src/omega/url_graph.js +1 -0
- package/src/plugins/autoreload/client/autoreload.js +10 -4
- package/src/plugins/html_supervisor/client/error_formatter.js +187 -66
- package/src/plugins/html_supervisor/client/error_overlay.js +29 -31
- package/src/plugins/html_supervisor/client/html_supervisor_installer.js +22 -67
- package/src/plugins/html_supervisor/client/html_supervisor_setup.js +10 -2
- package/src/plugins/html_supervisor/jsenv_plugin_html_supervisor.js +96 -25
- package/src/plugins/server_events/client/connection_manager.js +165 -0
- package/src/plugins/server_events/client/event_source_connection.js +50 -256
- package/src/plugins/server_events/client/events_manager.js +75 -0
- package/src/plugins/server_events/client/server_events_client.js +12 -11
- package/src/plugins/server_events/client/web_socket_connection.js +81 -0
- package/src/plugins/server_events/server_events_dispatcher.js +70 -54
|
@@ -1,33 +1,62 @@
|
|
|
1
1
|
export const formatError = (
|
|
2
2
|
error,
|
|
3
|
-
{
|
|
4
|
-
rootDirectoryUrl,
|
|
5
|
-
errorBaseUrl,
|
|
6
|
-
openInEditor,
|
|
7
|
-
url,
|
|
8
|
-
line,
|
|
9
|
-
column,
|
|
10
|
-
codeFrame,
|
|
11
|
-
requestedRessource,
|
|
12
|
-
reportedBy,
|
|
13
|
-
},
|
|
3
|
+
{ rootDirectoryUrl, errorBaseUrl, openInEditor, url, line, column },
|
|
14
4
|
) => {
|
|
15
5
|
let { message, stack } = normalizeErrorParts(error)
|
|
16
|
-
let
|
|
17
|
-
let tip =
|
|
6
|
+
let errorDetailsPromiseReference = { current: null }
|
|
7
|
+
let tip = `Reported by the browser while executing <code>${window.location.pathname}${window.location.search}</code>.`
|
|
18
8
|
let errorUrlSite
|
|
19
9
|
|
|
10
|
+
const errorMeta = extractErrorMeta(error, { url, line, column })
|
|
11
|
+
|
|
20
12
|
const resolveUrlSite = ({ url, line, column }) => {
|
|
21
|
-
|
|
13
|
+
if (typeof line === "string") line = parseInt(line)
|
|
14
|
+
if (typeof column === "string") column = parseInt(column)
|
|
15
|
+
|
|
16
|
+
const inlineUrlMatch = url.match(
|
|
17
|
+
/@L([0-9]+)C([0-9]+)\-L([0-9]+)C([0-9]+)(\.[\w]+)$/,
|
|
18
|
+
)
|
|
22
19
|
if (inlineUrlMatch) {
|
|
23
20
|
const htmlUrl = url.slice(0, inlineUrlMatch.index)
|
|
24
|
-
const
|
|
25
|
-
const
|
|
21
|
+
const tagLineStart = parseInt(inlineUrlMatch[1])
|
|
22
|
+
const tagColumnStart = parseInt(inlineUrlMatch[2])
|
|
23
|
+
const tagLineEnd = parseInt(inlineUrlMatch[3])
|
|
24
|
+
const tagColumnEnd = parseInt(inlineUrlMatch[4])
|
|
25
|
+
const extension = inlineUrlMatch[5]
|
|
26
26
|
url = htmlUrl
|
|
27
|
-
line =
|
|
28
|
-
|
|
27
|
+
line = tagLineStart + (typeof line === "number" ? line : 0)
|
|
28
|
+
// stackTrace formatted by V8 (chrome)
|
|
29
|
+
if (Error.captureStackTrace) {
|
|
30
|
+
line--
|
|
31
|
+
}
|
|
32
|
+
if (errorMeta.type === "dynamic_import_syntax_error") {
|
|
33
|
+
// syntax error on inline script need line-1 for some reason
|
|
34
|
+
if (Error.captureStackTrace) {
|
|
35
|
+
line--
|
|
36
|
+
} else {
|
|
37
|
+
// firefox and safari need line-2
|
|
38
|
+
line -= 2
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
column = tagColumnStart + (typeof column === "number" ? column : 0)
|
|
42
|
+
const fileUrl = resolveFileUrl(url)
|
|
43
|
+
return {
|
|
44
|
+
isInline: true,
|
|
45
|
+
originalUrl: `${fileUrl}@L${tagLineStart}C${tagColumnStart}-L${tagLineEnd}C${tagColumnEnd}${extension}`,
|
|
46
|
+
url: fileUrl,
|
|
47
|
+
line,
|
|
48
|
+
column,
|
|
49
|
+
}
|
|
29
50
|
}
|
|
51
|
+
return {
|
|
52
|
+
isInline: false,
|
|
53
|
+
url: resolveFileUrl(url),
|
|
54
|
+
line,
|
|
55
|
+
column,
|
|
56
|
+
}
|
|
57
|
+
}
|
|
30
58
|
|
|
59
|
+
const resolveFileUrl = (url) => {
|
|
31
60
|
let urlObject = new URL(url)
|
|
32
61
|
if (urlObject.origin === window.origin) {
|
|
33
62
|
urlObject = new URL(
|
|
@@ -39,19 +68,10 @@ export const formatError = (
|
|
|
39
68
|
const atFsIndex = urlObject.pathname.indexOf("/@fs/")
|
|
40
69
|
if (atFsIndex > -1) {
|
|
41
70
|
const afterAtFs = urlObject.pathname.slice(atFsIndex + "/@fs/".length)
|
|
42
|
-
|
|
43
|
-
} else {
|
|
44
|
-
url = urlObject.href
|
|
71
|
+
return new URL(afterAtFs, "file:///").href
|
|
45
72
|
}
|
|
46
|
-
} else {
|
|
47
|
-
url = urlObject.href
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
url,
|
|
52
|
-
line,
|
|
53
|
-
column,
|
|
54
73
|
}
|
|
74
|
+
return urlObject.href
|
|
55
75
|
}
|
|
56
76
|
|
|
57
77
|
const generateClickableText = (text) => {
|
|
@@ -59,7 +79,7 @@ export const formatError = (
|
|
|
59
79
|
createLink: (url, { line, column }) => {
|
|
60
80
|
const urlSite = resolveUrlSite({ url, line, column })
|
|
61
81
|
if (!errorUrlSite && text === stack) {
|
|
62
|
-
onErrorLocated(urlSite)
|
|
82
|
+
onErrorLocated(urlSite, "error.stack")
|
|
63
83
|
}
|
|
64
84
|
if (errorBaseUrl) {
|
|
65
85
|
if (urlSite.url.startsWith(rootDirectoryUrl)) {
|
|
@@ -83,21 +103,74 @@ export const formatError = (
|
|
|
83
103
|
return textWithHtmlLinks
|
|
84
104
|
}
|
|
85
105
|
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
if (
|
|
89
|
-
|
|
106
|
+
const formatErrorText = ({ message, stack, codeFrame }) => {
|
|
107
|
+
let text
|
|
108
|
+
if (message && stack) {
|
|
109
|
+
text = `${generateClickableText(message)}\n${generateClickableText(
|
|
110
|
+
stack,
|
|
111
|
+
)}`
|
|
112
|
+
} else if (stack) {
|
|
113
|
+
text = generateClickableText(stack)
|
|
114
|
+
} else {
|
|
115
|
+
text = generateClickableText(message)
|
|
90
116
|
}
|
|
91
|
-
if (
|
|
92
|
-
|
|
117
|
+
if (codeFrame) {
|
|
118
|
+
text += `\n\n${generateClickableText(codeFrame)}`
|
|
93
119
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
120
|
+
return text
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const onErrorLocated = (urlSite) => {
|
|
124
|
+
errorUrlSite = urlSite
|
|
125
|
+
errorDetailsPromiseReference.current = (async () => {
|
|
126
|
+
try {
|
|
127
|
+
if (errorMeta.type === "dynamic_import_fetch_error") {
|
|
128
|
+
const response = await window.fetch(
|
|
129
|
+
`/__get_error_cause__/${
|
|
130
|
+
urlSite.isInline ? urlSite.originalUrl : urlSite.url
|
|
131
|
+
}`,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
if (response.status !== 200) {
|
|
135
|
+
return null
|
|
136
|
+
}
|
|
137
|
+
const causeInfo = await response.json()
|
|
138
|
+
if (!causeInfo) {
|
|
139
|
+
return null
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const causeText =
|
|
143
|
+
causeInfo.code === "NOT_FOUND"
|
|
144
|
+
? formatErrorText({
|
|
145
|
+
message: causeInfo.reason,
|
|
146
|
+
stack: causeInfo.codeFrame,
|
|
147
|
+
})
|
|
148
|
+
: formatErrorText({
|
|
149
|
+
message: causeInfo.stack,
|
|
150
|
+
stack: causeInfo.codeFrame,
|
|
151
|
+
})
|
|
152
|
+
return {
|
|
153
|
+
cause: causeText,
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (urlSite.line !== undefined) {
|
|
157
|
+
let ressourceToFetch = `/__get_code_frame__/${formatUrlWithLineAndColumn(
|
|
158
|
+
urlSite,
|
|
159
|
+
)}`
|
|
160
|
+
if (!Error.captureStackTrace) {
|
|
161
|
+
ressourceToFetch += `?remap`
|
|
162
|
+
}
|
|
163
|
+
const response = await window.fetch(ressourceToFetch)
|
|
164
|
+
const codeFrame = await response.text()
|
|
165
|
+
return {
|
|
166
|
+
codeFrame: formatErrorText({ message: codeFrame }),
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
} catch (e) {
|
|
170
|
+
// happens if server is closed for instance
|
|
171
|
+
return null
|
|
172
|
+
}
|
|
173
|
+
return null
|
|
101
174
|
})()
|
|
102
175
|
}
|
|
103
176
|
|
|
@@ -110,20 +183,8 @@ export const formatError = (
|
|
|
110
183
|
!url.endsWith("html_supervisor_installer.js")
|
|
111
184
|
) {
|
|
112
185
|
onErrorLocated(resolveUrlSite({ url, line, column }))
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
let text
|
|
116
|
-
|
|
117
|
-
if (message && stack) {
|
|
118
|
-
text = `${generateClickableText(message)}\n${generateClickableText(stack)}`
|
|
119
|
-
} else if (stack) {
|
|
120
|
-
text = generateClickableText(stack)
|
|
121
|
-
} else {
|
|
122
|
-
text = generateClickableText(message)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (codeFrame) {
|
|
126
|
-
text += `\n\n${generateClickableText(codeFrame)}`
|
|
186
|
+
} else if (errorMeta.url) {
|
|
187
|
+
onErrorLocated(resolveUrlSite(errorMeta))
|
|
127
188
|
}
|
|
128
189
|
|
|
129
190
|
return {
|
|
@@ -132,12 +193,79 @@ export const formatError = (
|
|
|
132
193
|
? "light"
|
|
133
194
|
: "dark",
|
|
134
195
|
title: "An error occured",
|
|
135
|
-
text,
|
|
136
|
-
codeFramePromise: codeFramePromiseReference.current,
|
|
196
|
+
text: formatErrorText({ message, stack }),
|
|
137
197
|
tip: `${tip}
|
|
138
198
|
<br />
|
|
139
199
|
Click outside to close.`,
|
|
200
|
+
errorDetailsPromise: errorDetailsPromiseReference.current,
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const extractErrorMeta = (error, { line }) => {
|
|
205
|
+
if (!error) {
|
|
206
|
+
return {}
|
|
207
|
+
}
|
|
208
|
+
const { message } = error
|
|
209
|
+
if (!message) {
|
|
210
|
+
return {}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export_missing: {
|
|
214
|
+
// chrome
|
|
215
|
+
if (message.includes("does not provide an export named")) {
|
|
216
|
+
return {
|
|
217
|
+
type: "dynamic_import_export_missing",
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// firefox
|
|
221
|
+
if (message.startsWith("import not found:")) {
|
|
222
|
+
return {
|
|
223
|
+
type: "dynamic_import_export_missing",
|
|
224
|
+
browser: "firefox",
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// safari
|
|
228
|
+
if (message.startsWith("import binding name")) {
|
|
229
|
+
return {
|
|
230
|
+
type: "dynamic_import_export_missing",
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
js_syntax_error: {
|
|
236
|
+
if (error.name === "SyntaxError" && typeof line === "number") {
|
|
237
|
+
return {
|
|
238
|
+
type: "dynamic_import_syntax_error",
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
fetch_error: {
|
|
244
|
+
// chrome
|
|
245
|
+
if (message.startsWith("Failed to fetch dynamically imported module: ")) {
|
|
246
|
+
const url = error.message.slice(
|
|
247
|
+
"Failed to fetch dynamically imported module: ".length,
|
|
248
|
+
)
|
|
249
|
+
return {
|
|
250
|
+
type: "dynamic_import_fetch_error",
|
|
251
|
+
url,
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// firefox
|
|
255
|
+
if (message === "error loading dynamically imported module") {
|
|
256
|
+
return {
|
|
257
|
+
type: "dynamic_import_fetch_error",
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
// safari
|
|
261
|
+
if (message === "Importing a module script failed.") {
|
|
262
|
+
return {
|
|
263
|
+
type: "dynamic_import_fetch_error",
|
|
264
|
+
}
|
|
265
|
+
}
|
|
140
266
|
}
|
|
267
|
+
|
|
268
|
+
return {}
|
|
141
269
|
}
|
|
142
270
|
|
|
143
271
|
const formatUrlWithLineAndColumn = ({ url, line, column }) => {
|
|
@@ -213,13 +341,6 @@ const getErrorStackWithoutErrorMessage = (error) => {
|
|
|
213
341
|
return stack
|
|
214
342
|
}
|
|
215
343
|
|
|
216
|
-
const formatTip = ({ reportedBy, requestedRessource }) => {
|
|
217
|
-
if (reportedBy === "browser") {
|
|
218
|
-
return `Reported by the browser while executing <code>${window.location.pathname}${window.location.search}</code>.`
|
|
219
|
-
}
|
|
220
|
-
return `Reported by the server while serving <code>${requestedRessource}</code>`
|
|
221
|
-
}
|
|
222
|
-
|
|
223
344
|
const makeLinksClickable = (string, { createLink = (url) => url }) => {
|
|
224
345
|
// normalize line breaks
|
|
225
346
|
string = string.replace(/\n/g, "\n")
|
|
@@ -2,8 +2,6 @@ import { formatError } from "./error_formatter.js"
|
|
|
2
2
|
|
|
3
3
|
const JSENV_ERROR_OVERLAY_TAGNAME = "jsenv-error-overlay"
|
|
4
4
|
|
|
5
|
-
let previousErrorInfo = null
|
|
6
|
-
|
|
7
5
|
export const displayErrorInDocument = (
|
|
8
6
|
error,
|
|
9
7
|
{
|
|
@@ -14,30 +12,9 @@ export const displayErrorInDocument = (
|
|
|
14
12
|
line,
|
|
15
13
|
column,
|
|
16
14
|
codeFrame,
|
|
17
|
-
reportedBy,
|
|
18
|
-
requestedRessource,
|
|
19
15
|
},
|
|
20
16
|
) => {
|
|
21
|
-
const
|
|
22
|
-
// ensure error dispatched on window by browser is displayed first
|
|
23
|
-
// then the server error replaces it (because it contains more information)
|
|
24
|
-
if (previousErrorInfo) {
|
|
25
|
-
const previousErrorReportedBy = previousErrorInfo.reportedBy
|
|
26
|
-
const msEllapsedSincePreviousError = nowMs - previousErrorInfo.ms
|
|
27
|
-
if (
|
|
28
|
-
previousErrorReportedBy === "server" &&
|
|
29
|
-
reportedBy === "browser" &&
|
|
30
|
-
msEllapsedSincePreviousError < 50
|
|
31
|
-
) {
|
|
32
|
-
return () => {}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
previousErrorInfo = {
|
|
36
|
-
ms: nowMs,
|
|
37
|
-
reportedBy,
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const { theme, title, text, codeFramePromise, tip } = formatError(error, {
|
|
17
|
+
const { theme, title, text, tip, errorDetailsPromise } = formatError(error, {
|
|
41
18
|
rootDirectoryUrl,
|
|
42
19
|
errorBaseUrl,
|
|
43
20
|
openInEditor,
|
|
@@ -45,16 +22,14 @@ export const displayErrorInDocument = (
|
|
|
45
22
|
line,
|
|
46
23
|
column,
|
|
47
24
|
codeFrame,
|
|
48
|
-
reportedBy,
|
|
49
|
-
requestedRessource,
|
|
50
25
|
})
|
|
51
26
|
|
|
52
27
|
let jsenvErrorOverlay = new JsenvErrorOverlay({
|
|
53
28
|
theme,
|
|
54
29
|
title,
|
|
55
30
|
text,
|
|
56
|
-
codeFramePromise,
|
|
57
31
|
tip,
|
|
32
|
+
errorDetailsPromise,
|
|
58
33
|
})
|
|
59
34
|
document.querySelectorAll(JSENV_ERROR_OVERLAY_TAGNAME).forEach((node) => {
|
|
60
35
|
node.parentNode.removeChild(node)
|
|
@@ -77,7 +52,7 @@ export const displayErrorInDocument = (
|
|
|
77
52
|
}
|
|
78
53
|
|
|
79
54
|
class JsenvErrorOverlay extends HTMLElement {
|
|
80
|
-
constructor({ theme, title, text,
|
|
55
|
+
constructor({ theme, title, text, tip, errorDetailsPromise }) {
|
|
81
56
|
super()
|
|
82
57
|
this.root = this.attachShadow({ mode: "open" })
|
|
83
58
|
this.root.innerHTML = `
|
|
@@ -102,16 +77,39 @@ class JsenvErrorOverlay extends HTMLElement {
|
|
|
102
77
|
this.root.querySelector(".backdrop").onclick = null
|
|
103
78
|
this.parentNode.removeChild(this)
|
|
104
79
|
}
|
|
105
|
-
if (
|
|
106
|
-
|
|
107
|
-
if (this.parentNode) {
|
|
80
|
+
if (errorDetailsPromise) {
|
|
81
|
+
errorDetailsPromise.then((errorDetails) => {
|
|
82
|
+
if (!errorDetails || !this.parentNode) {
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
const { codeFrame, cause } = errorDetails
|
|
86
|
+
if (codeFrame) {
|
|
108
87
|
this.root.querySelector(".text").innerHTML += `\n\n${codeFrame}`
|
|
109
88
|
}
|
|
89
|
+
if (cause) {
|
|
90
|
+
const causeIndented = prefixRemainingLines(cause, " ")
|
|
91
|
+
this.root.querySelector(
|
|
92
|
+
".text",
|
|
93
|
+
).innerHTML += `\n [cause]: ${causeIndented}`
|
|
94
|
+
}
|
|
110
95
|
})
|
|
111
96
|
}
|
|
112
97
|
}
|
|
113
98
|
}
|
|
114
99
|
|
|
100
|
+
const prefixRemainingLines = (text, prefix) => {
|
|
101
|
+
const lines = text.split(/\r?\n/)
|
|
102
|
+
const firstLine = lines.shift()
|
|
103
|
+
let result = firstLine
|
|
104
|
+
let i = 0
|
|
105
|
+
while (i < lines.length) {
|
|
106
|
+
const line = lines[i]
|
|
107
|
+
i++
|
|
108
|
+
result += line.length ? `\n${prefix}${line}` : `\n`
|
|
109
|
+
}
|
|
110
|
+
return result
|
|
111
|
+
}
|
|
112
|
+
|
|
115
113
|
if (customElements && !customElements.get(JSENV_ERROR_OVERLAY_TAGNAME)) {
|
|
116
114
|
customElements.define(JSENV_ERROR_OVERLAY_TAGNAME, JsenvErrorOverlay)
|
|
117
115
|
}
|
|
@@ -88,11 +88,15 @@ export const installHtmlSupervisor = ({
|
|
|
88
88
|
let completed
|
|
89
89
|
let result
|
|
90
90
|
let error
|
|
91
|
+
const urlObject = new URL(src, window.location)
|
|
92
|
+
if (reload) {
|
|
93
|
+
urlObject.searchParams.set("hmr", Date.now())
|
|
94
|
+
}
|
|
95
|
+
__html_supervisor__.currentExecution = {
|
|
96
|
+
type: type === "module" ? "dynamic_import" : "script_injection",
|
|
97
|
+
url: urlObject.href,
|
|
98
|
+
}
|
|
91
99
|
try {
|
|
92
|
-
const urlObject = new URL(src, window.location)
|
|
93
|
-
if (reload) {
|
|
94
|
-
urlObject.searchParams.set("hmr", Date.now())
|
|
95
|
-
}
|
|
96
100
|
result = await execute(urlObject.href)
|
|
97
101
|
completed = true
|
|
98
102
|
} catch (e) {
|
|
@@ -110,6 +114,7 @@ export const installHtmlSupervisor = ({
|
|
|
110
114
|
console.log(`${type} load ended`)
|
|
111
115
|
console.groupEnd()
|
|
112
116
|
}
|
|
117
|
+
__html_supervisor__.currentExecution = null
|
|
113
118
|
return
|
|
114
119
|
}
|
|
115
120
|
const executionResult = {
|
|
@@ -127,9 +132,7 @@ export const installHtmlSupervisor = ({
|
|
|
127
132
|
}
|
|
128
133
|
executionResult.error = error
|
|
129
134
|
onExecutionSettled(src, executionResult)
|
|
130
|
-
onExecutionError(executionResult, {
|
|
131
|
-
currentScript,
|
|
132
|
-
})
|
|
135
|
+
onExecutionError(executionResult, { currentScript })
|
|
133
136
|
if (errorExposureInConsole) {
|
|
134
137
|
if (typeof window.reportError === "function") {
|
|
135
138
|
window.reportError(error)
|
|
@@ -140,6 +143,7 @@ export const installHtmlSupervisor = ({
|
|
|
140
143
|
if (logs) {
|
|
141
144
|
console.groupEnd()
|
|
142
145
|
}
|
|
146
|
+
__html_supervisor__.currentExecution = null
|
|
143
147
|
}
|
|
144
148
|
|
|
145
149
|
const classicExecutionQueue = createExecutionQueue(performExecution)
|
|
@@ -175,7 +179,6 @@ export const installHtmlSupervisor = ({
|
|
|
175
179
|
const useDeferQueue =
|
|
176
180
|
scriptToExecute.defer || scriptToExecute.type === "module"
|
|
177
181
|
if (useDeferQueue) {
|
|
178
|
-
// defer must wait for classic script to be done
|
|
179
182
|
const classicExecutionPromise = classicExecutionQueue.getPromise()
|
|
180
183
|
if (classicExecutionPromise) {
|
|
181
184
|
deferedExecutionQueue.waitFor(classicExecutionPromise)
|
|
@@ -220,76 +223,28 @@ export const installHtmlSupervisor = ({
|
|
|
220
223
|
})
|
|
221
224
|
|
|
222
225
|
if (errorOverlay) {
|
|
226
|
+
const onErrorReportedByBrowser = (error, { url, line, column }) => {
|
|
227
|
+
displayErrorInDocument(error, {
|
|
228
|
+
rootDirectoryUrl,
|
|
229
|
+
errorBaseUrl,
|
|
230
|
+
openInEditor,
|
|
231
|
+
url,
|
|
232
|
+
line,
|
|
233
|
+
column,
|
|
234
|
+
})
|
|
235
|
+
}
|
|
223
236
|
window.addEventListener("error", (errorEvent) => {
|
|
224
237
|
if (!errorEvent.isTrusted) {
|
|
225
238
|
// ignore custom error event (not sent by browser)
|
|
226
239
|
return
|
|
227
240
|
}
|
|
228
241
|
const { error, filename, lineno, colno } = errorEvent
|
|
229
|
-
|
|
230
|
-
rootDirectoryUrl,
|
|
231
|
-
errorBaseUrl,
|
|
232
|
-
openInEditor,
|
|
242
|
+
onErrorReportedByBrowser(error, {
|
|
233
243
|
url: filename,
|
|
234
244
|
line: lineno,
|
|
235
245
|
column: colno,
|
|
236
|
-
reportedBy: "browser",
|
|
237
246
|
})
|
|
238
247
|
})
|
|
239
|
-
if (window.__server_events__) {
|
|
240
|
-
const isExecuting = () => {
|
|
241
|
-
if (pendingExecutionCount > 0) {
|
|
242
|
-
return true
|
|
243
|
-
}
|
|
244
|
-
if (
|
|
245
|
-
document.readyState === "loading" ||
|
|
246
|
-
document.readyState === "interactive"
|
|
247
|
-
) {
|
|
248
|
-
return true
|
|
249
|
-
}
|
|
250
|
-
if (window.__reloader__ && window.__reloader__.status === "reloading") {
|
|
251
|
-
return true
|
|
252
|
-
}
|
|
253
|
-
return false
|
|
254
|
-
}
|
|
255
|
-
window.__server_events__.addEventCallbacks({
|
|
256
|
-
error_while_serving_file: (serverErrorEvent) => {
|
|
257
|
-
if (!isExecuting()) {
|
|
258
|
-
return
|
|
259
|
-
}
|
|
260
|
-
const {
|
|
261
|
-
message,
|
|
262
|
-
stack,
|
|
263
|
-
traceUrl,
|
|
264
|
-
traceLine,
|
|
265
|
-
traceColumn,
|
|
266
|
-
traceMessage,
|
|
267
|
-
requestedRessource,
|
|
268
|
-
isFaviconAutoRequest,
|
|
269
|
-
} = JSON.parse(serverErrorEvent.data)
|
|
270
|
-
if (isFaviconAutoRequest) {
|
|
271
|
-
return
|
|
272
|
-
}
|
|
273
|
-
displayErrorInDocument(
|
|
274
|
-
{
|
|
275
|
-
message,
|
|
276
|
-
stack,
|
|
277
|
-
},
|
|
278
|
-
{
|
|
279
|
-
rootDirectoryUrl,
|
|
280
|
-
errorBaseUrl,
|
|
281
|
-
openInEditor,
|
|
282
|
-
url: traceUrl,
|
|
283
|
-
line: traceLine,
|
|
284
|
-
column: traceColumn,
|
|
285
|
-
codeFrame: traceMessage,
|
|
286
|
-
reportedBy: "server",
|
|
287
|
-
requestedRessource,
|
|
288
|
-
},
|
|
289
|
-
)
|
|
290
|
-
},
|
|
291
|
-
})
|
|
292
|
-
}
|
|
293
248
|
}
|
|
294
249
|
}
|
|
295
250
|
|
|
@@ -9,11 +9,12 @@ window.__html_supervisor__ = {
|
|
|
9
9
|
window.__html_supervisor__.scriptsToExecute.push(scriptToExecute)
|
|
10
10
|
},
|
|
11
11
|
superviseScript: ({ src, isInline, crossorigin, integrity }) => {
|
|
12
|
+
const { currentScript } = document
|
|
12
13
|
window.__html_supervisor__.addScriptToExecute({
|
|
13
14
|
src,
|
|
14
15
|
type: "js_classic",
|
|
15
16
|
isInline,
|
|
16
|
-
currentScript
|
|
17
|
+
currentScript,
|
|
17
18
|
execute: (url) => {
|
|
18
19
|
return new Promise((resolve, reject) => {
|
|
19
20
|
const script = document.createElement("script")
|
|
@@ -50,7 +51,14 @@ window.__html_supervisor__ = {
|
|
|
50
51
|
resolve()
|
|
51
52
|
}
|
|
52
53
|
})
|
|
53
|
-
|
|
54
|
+
if (currentScript) {
|
|
55
|
+
currentScript.parentNode.insertBefore(
|
|
56
|
+
script,
|
|
57
|
+
currentScript.nextSibling,
|
|
58
|
+
)
|
|
59
|
+
} else {
|
|
60
|
+
document.body.appendChild(script)
|
|
61
|
+
}
|
|
54
62
|
})
|
|
55
63
|
},
|
|
56
64
|
})
|