@jsenv/core 27.4.0 → 27.5.2
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 +359 -0
- package/dist/js/execute_using_dynamic_import.js +1 -1
- package/dist/js/html_supervisor_installer.js +469 -254
- package/dist/js/html_supervisor_setup.js +3 -4
- package/dist/js/new_stylesheet.js +26 -58
- package/dist/js/server_events_client.js +307 -0
- package/dist/main.js +7558 -7311
- package/package.json +12 -10
- package/{README.md → readme.md} +8 -9
- package/src/build/build.js +12 -16
- package/src/build/start_build_server.js +24 -28
- package/src/dev/start_dev_server.js +34 -96
- package/src/execute/execute.js +17 -35
- package/src/omega/errors.js +20 -18
- package/src/omega/kitchen.js +7 -6
- package/src/omega/omega_server.js +96 -127
- package/src/omega/server/file_service.js +247 -46
- package/src/omega/url_graph.js +33 -20
- package/src/plugins/autoreload/client/autoreload.js +201 -0
- package/src/plugins/autoreload/{dev_sse/client → client}/autoreload_preference.js +0 -0
- package/src/plugins/autoreload/{dev_sse/client → client}/reload.js +29 -10
- package/src/plugins/autoreload/{dev_sse/client → client}/url_helpers.js +0 -0
- package/src/plugins/autoreload/jsenv_plugin_autoreload.js +4 -4
- package/src/plugins/autoreload/{dev_sse/jsenv_plugin_dev_sse_client.js → jsenv_plugin_autoreload_client.js} +8 -8
- package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +196 -0
- package/src/{dev/plugins → plugins}/explorer/client/explorer.html +0 -0
- package/src/{dev/plugins → plugins}/explorer/client/jsenv.png +0 -0
- package/src/{dev/plugins → plugins}/explorer/jsenv_plugin_explorer.js +1 -3
- package/src/plugins/html_supervisor/client/error_formatter.js +300 -0
- package/src/plugins/html_supervisor/client/error_overlay.js +172 -0
- package/src/plugins/html_supervisor/client/html_supervisor_installer.js +124 -54
- package/src/plugins/html_supervisor/client/html_supervisor_setup.js +3 -4
- package/src/plugins/html_supervisor/jsenv_plugin_html_supervisor.js +72 -27
- package/src/plugins/inline/jsenv_plugin_html_inline_content.js +97 -117
- package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +66 -58
- package/src/plugins/plugin_controller.js +102 -67
- package/src/plugins/plugins.js +10 -8
- package/src/{helpers/event_source/event_source.js → plugins/server_events/client/event_source_connection.js} +102 -31
- package/src/plugins/server_events/client/server_events_client.js +17 -0
- package/src/plugins/server_events/jsenv_plugin_server_events_client_injection.js +48 -0
- package/src/plugins/server_events/server_events_dispatcher.js +69 -0
- package/src/{dev/plugins → plugins}/toolbar/client/animation/toolbar_animation.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/eventsource/eventsource.css +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/eventsource/toolbar_eventsource.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/execution/execution.css +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/execution/toolbar_execution.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/focus/focus.css +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/focus/toolbar_focus.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/jsenv_logo.svg +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/notification/toolbar_notification.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/responsive/overflow_menu.css +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/responsive/toolbar_responsive.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/settings/settings.css +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/settings/toolbar_settings.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/theme/jsenv_theme.css +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/theme/light_theme.css +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/theme/toolbar_theme.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/toolbar.html +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/toolbar_injector.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/toolbar_main.css +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/toolbar_main.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/tooltip/tooltip.css +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/tooltip/tooltip.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/util/animation.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/util/dom.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/util/fetch_using_xhr.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/util/fetching.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/util/iframe_to_parent_href.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/util/jsenv_logger.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/util/preferences.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/util/responsive.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/util/util.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/variant/variant.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/jsenv_plugin_toolbar.js +0 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_html.js +4 -3
- package/src/plugins/transpilation/babel/new_stylesheet/client/new_stylesheet.js +25 -55
- package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +44 -24
- package/src/plugins/transpilation/jsenv_plugin_transpilation.js +6 -1
- package/src/plugins/url_analysis/html/html_urls.js +8 -8
- package/src/test/execute_plan.js +36 -54
- package/src/test/execute_test_plan.js +2 -2
- package/dist/js/event_source_client.js +0 -549
- package/src/helpers/event_source/sse_service.js +0 -53
- package/src/plugins/autoreload/dev_sse/client/event_source_client.js +0 -193
- package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js +0 -192
- package/src/plugins/html_supervisor/client/error_in_document.js +0 -345
|
@@ -10,158 +10,169 @@ const unevalException = value => {
|
|
|
10
10
|
});
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
const
|
|
14
|
-
const displayErrorInDocument = (error, {
|
|
13
|
+
const formatError = (error, {
|
|
15
14
|
rootDirectoryUrl,
|
|
15
|
+
errorBaseUrl,
|
|
16
|
+
openInEditor,
|
|
16
17
|
url,
|
|
17
18
|
line,
|
|
18
|
-
column
|
|
19
|
+
column,
|
|
20
|
+
codeFrame,
|
|
21
|
+
requestedRessource,
|
|
22
|
+
reportedBy
|
|
19
23
|
}) => {
|
|
20
|
-
|
|
21
|
-
node.parentNode.removeChild(node);
|
|
22
|
-
});
|
|
23
|
-
const {
|
|
24
|
-
theme,
|
|
25
|
-
title,
|
|
24
|
+
let {
|
|
26
25
|
message,
|
|
27
26
|
stack
|
|
28
|
-
} =
|
|
27
|
+
} = normalizeErrorParts(error);
|
|
28
|
+
let codeFramePromiseReference = {
|
|
29
|
+
current: null
|
|
30
|
+
};
|
|
31
|
+
let tip = formatTip({
|
|
32
|
+
reportedBy,
|
|
33
|
+
requestedRessource
|
|
34
|
+
});
|
|
35
|
+
let errorUrlSite;
|
|
36
|
+
|
|
37
|
+
const resolveUrlSite = ({
|
|
29
38
|
url,
|
|
30
39
|
line,
|
|
31
40
|
column
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
document.body.appendChild(jsenvErrorOverlay);
|
|
45
|
-
};
|
|
41
|
+
}) => {
|
|
42
|
+
const inlineUrlMatch = url.match(/@L([0-9]+)\-L([0-9]+)\.[\w]+$/);
|
|
43
|
+
|
|
44
|
+
if (inlineUrlMatch) {
|
|
45
|
+
const htmlUrl = url.slice(0, inlineUrlMatch.index);
|
|
46
|
+
const tagLine = parseInt(inlineUrlMatch[1]);
|
|
47
|
+
const tagColumn = parseInt(inlineUrlMatch[2]);
|
|
48
|
+
url = htmlUrl;
|
|
49
|
+
line = tagLine + parseInt(line) - 1;
|
|
50
|
+
column = tagColumn + parseInt(column);
|
|
51
|
+
}
|
|
46
52
|
|
|
47
|
-
|
|
48
|
-
constructor({
|
|
49
|
-
title,
|
|
50
|
-
stack,
|
|
51
|
-
theme = "dark"
|
|
52
|
-
}) {
|
|
53
|
-
super();
|
|
54
|
-
this.root = this.attachShadow({
|
|
55
|
-
mode: "open"
|
|
56
|
-
});
|
|
57
|
-
this.root.innerHTML = overlayHtml;
|
|
58
|
-
this.root.querySelector(".overlay").setAttribute("data-theme", theme);
|
|
59
|
-
this.root.querySelector(".title").innerHTML = title;
|
|
60
|
-
this.root.querySelector(".stack").innerHTML = stack;
|
|
53
|
+
let urlObject = new URL(url);
|
|
61
54
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
55
|
+
if (urlObject.origin === window.origin) {
|
|
56
|
+
urlObject = new URL(`${urlObject.pathname.slice(1)}${urlObject.search}`, rootDirectoryUrl);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (urlObject.href.startsWith("file:")) {
|
|
60
|
+
const atFsIndex = urlObject.pathname.indexOf("/@fs/");
|
|
61
|
+
|
|
62
|
+
if (atFsIndex > -1) {
|
|
63
|
+
const afterAtFs = urlObject.pathname.slice(atFsIndex + "/@fs/".length);
|
|
64
|
+
url = new URL(afterAtFs, "file:///").href;
|
|
65
|
+
} else {
|
|
66
|
+
url = urlObject.href;
|
|
66
67
|
}
|
|
68
|
+
} else {
|
|
69
|
+
url = urlObject.href;
|
|
70
|
+
}
|
|
67
71
|
|
|
68
|
-
|
|
69
|
-
|
|
72
|
+
return {
|
|
73
|
+
url,
|
|
74
|
+
line,
|
|
75
|
+
column
|
|
70
76
|
};
|
|
71
|
-
}
|
|
77
|
+
};
|
|
72
78
|
|
|
73
|
-
|
|
79
|
+
const generateClickableText = text => {
|
|
80
|
+
const textWithHtmlLinks = makeLinksClickable(text, {
|
|
81
|
+
createLink: (url, {
|
|
82
|
+
line,
|
|
83
|
+
column
|
|
84
|
+
}) => {
|
|
85
|
+
const urlSite = resolveUrlSite({
|
|
86
|
+
url,
|
|
87
|
+
line,
|
|
88
|
+
column
|
|
89
|
+
});
|
|
74
90
|
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
}
|
|
91
|
+
if (!errorUrlSite && text === stack) {
|
|
92
|
+
onErrorLocated(urlSite);
|
|
93
|
+
}
|
|
78
94
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
width: 100%;
|
|
87
|
-
height: 100%;
|
|
88
|
-
overflow-y: scroll;
|
|
89
|
-
margin: 0;
|
|
90
|
-
background: rgba(0, 0, 0, 0.66);
|
|
91
|
-
}
|
|
95
|
+
if (errorBaseUrl) {
|
|
96
|
+
if (urlSite.url.startsWith(rootDirectoryUrl)) {
|
|
97
|
+
urlSite.url = `${errorBaseUrl}${urlSite.url.slice(rootDirectoryUrl.length)}`;
|
|
98
|
+
} else {
|
|
99
|
+
urlSite.url = "file:///mocked_for_snapshots";
|
|
100
|
+
}
|
|
101
|
+
}
|
|
92
102
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
103
|
+
const urlWithLineAndColumn = formatUrlWithLineAndColumn(urlSite);
|
|
104
|
+
return {
|
|
105
|
+
href: url.startsWith("file:") && openInEditor ? `javascript:window.fetch('/__open_in_editor__/${urlWithLineAndColumn}')` : urlSite.url,
|
|
106
|
+
text: urlWithLineAndColumn
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
return textWithHtmlLinks;
|
|
111
|
+
};
|
|
100
112
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
background: rgba(0, 0, 0, 0.95);
|
|
104
|
-
width: 800px;
|
|
105
|
-
margin: 30px auto;
|
|
106
|
-
padding: 25px 40px;
|
|
107
|
-
padding-top: 0;
|
|
108
|
-
overflow: hidden; /* for h1 margins */
|
|
109
|
-
border-radius: 4px 8px;
|
|
110
|
-
box-shadow: 0 20px 40px rgb(0 0 0 / 30%), 0 15px 12px rgb(0 0 0 / 20%);
|
|
111
|
-
box-sizing: border-box;
|
|
112
|
-
font-family: monospace;
|
|
113
|
-
direction: ltr;
|
|
114
|
-
}
|
|
113
|
+
const onErrorLocated = urlSite => {
|
|
114
|
+
errorUrlSite = urlSite;
|
|
115
115
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
116
|
+
if (codeFrame) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
120
119
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
/* padding is nice + prevents scrollbar from hiding the text behind it */
|
|
125
|
-
/* does not work nicely on firefox though https://bugzilla.mozilla.org/show_bug.cgi?id=748518 */
|
|
126
|
-
padding: 20px;
|
|
127
|
-
}
|
|
120
|
+
if (reportedBy !== "browser") {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
128
123
|
|
|
129
|
-
.
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
124
|
+
codeFramePromiseReference.current = (async () => {
|
|
125
|
+
const response = await window.fetch(`/__get_code_frame__/${formatUrlWithLineAndColumn(urlSite)}`);
|
|
126
|
+
const codeFrame = await response.text();
|
|
127
|
+
const codeFrameClickable = generateClickableText(codeFrame);
|
|
128
|
+
return codeFrameClickable;
|
|
129
|
+
})();
|
|
130
|
+
}; // error.stack is more reliable than url/line/column reported on window error events
|
|
131
|
+
// so use it only when error.stack is not available
|
|
133
132
|
|
|
134
|
-
[data-theme="dark"] {
|
|
135
|
-
color: #999;
|
|
136
|
-
}
|
|
137
|
-
[data-theme="dark"] pre {
|
|
138
|
-
background: #111;
|
|
139
|
-
border: 1px solid #333;
|
|
140
|
-
color: #eee;
|
|
141
|
-
}
|
|
142
133
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
134
|
+
if (url && !stack) {
|
|
135
|
+
onErrorLocated(resolveUrlSite({
|
|
136
|
+
url,
|
|
137
|
+
line,
|
|
138
|
+
column
|
|
139
|
+
}));
|
|
140
|
+
}
|
|
151
141
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
142
|
+
let text;
|
|
143
|
+
|
|
144
|
+
if (message && stack) {
|
|
145
|
+
text = `${generateClickableText(message)}\n${generateClickableText(stack)}`;
|
|
146
|
+
} else if (stack) {
|
|
147
|
+
text = generateClickableText(stack);
|
|
148
|
+
} else {
|
|
149
|
+
text = generateClickableText(message);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (codeFrame) {
|
|
153
|
+
text += `\n\n${generateClickableText(codeFrame)}`;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
theme: error && error.cause && error.cause.code === "PARSE_ERROR" ? "light" : "dark",
|
|
158
|
+
title: "An error occured",
|
|
159
|
+
text,
|
|
160
|
+
codeFramePromise: codeFramePromiseReference.current,
|
|
161
|
+
tip: `${tip}
|
|
162
|
+
<br />
|
|
163
|
+
Click outside to close.`
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const formatUrlWithLineAndColumn = ({
|
|
168
|
+
url,
|
|
169
|
+
line,
|
|
170
|
+
column
|
|
171
|
+
}) => {
|
|
172
|
+
return line === undefined && column === undefined ? url : column === undefined ? `${url}:${line}` : `${url}:${line}:${column}`;
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const normalizeErrorParts = error => {
|
|
165
176
|
if (error === undefined) {
|
|
166
177
|
return {
|
|
167
178
|
message: "undefined"
|
|
@@ -239,35 +250,19 @@ const getErrorStackWithoutErrorMessage = error => {
|
|
|
239
250
|
return stack;
|
|
240
251
|
};
|
|
241
252
|
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
column
|
|
253
|
+
const formatTip = ({
|
|
254
|
+
reportedBy,
|
|
255
|
+
requestedRessource
|
|
246
256
|
}) => {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
stack
|
|
250
|
-
} = parseErrorInfo(error);
|
|
251
|
-
|
|
252
|
-
if (url) {
|
|
253
|
-
if (!stack || error && error.name === "SyntaxError") {
|
|
254
|
-
stack = ` at ${appendLineAndColumn(url, {
|
|
255
|
-
line,
|
|
256
|
-
column
|
|
257
|
-
})}`;
|
|
258
|
-
}
|
|
257
|
+
if (reportedBy === "browser") {
|
|
258
|
+
return `Reported by the browser while executing <code>${window.location.pathname}${window.location.search}</code>.`;
|
|
259
259
|
}
|
|
260
260
|
|
|
261
|
-
return {
|
|
262
|
-
theme: error && error.cause && error.cause.code === "PARSE_ERROR" ? "light" : "dark",
|
|
263
|
-
title: "An error occured",
|
|
264
|
-
message,
|
|
265
|
-
stack
|
|
266
|
-
};
|
|
261
|
+
return `Reported by the server while serving <code>${requestedRessource}</code>`;
|
|
267
262
|
};
|
|
268
263
|
|
|
269
|
-
const
|
|
270
|
-
|
|
264
|
+
const makeLinksClickable = (string, {
|
|
265
|
+
createLink = url => url
|
|
271
266
|
}) => {
|
|
272
267
|
// normalize line breaks
|
|
273
268
|
string = string.replace(/\n/g, "\n");
|
|
@@ -278,44 +273,16 @@ const replaceLinks = (string, {
|
|
|
278
273
|
line,
|
|
279
274
|
column
|
|
280
275
|
}) => {
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
const afterAtFs = fileUrlObject.pathname.slice(atFsIndex + "/@fs/".length);
|
|
289
|
-
fileUrl = new URL(afterAtFs, "file:///").href;
|
|
290
|
-
} else {
|
|
291
|
-
fileUrl = fileUrlObject.href;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
fileUrl = appendLineAndColumn(fileUrl, {
|
|
295
|
-
line,
|
|
296
|
-
column
|
|
297
|
-
});
|
|
298
|
-
return link({
|
|
299
|
-
href: `javascript:window.fetch('/__open_in_editor__/${fileUrl}')`,
|
|
300
|
-
text: fileUrl
|
|
301
|
-
});
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
if (urlObject.origin === window.origin) {
|
|
305
|
-
const fileUrlObject = new URL(`${urlObject.pathname.slice(1)}${urlObject.search}`, rootDirectoryUrl);
|
|
306
|
-
return onFileUrl(fileUrlObject);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
if (urlObject.href.startsWith("file:")) {
|
|
310
|
-
return onFileUrl(urlObject);
|
|
311
|
-
}
|
|
312
|
-
|
|
276
|
+
const {
|
|
277
|
+
href,
|
|
278
|
+
text
|
|
279
|
+
} = createLink(url, {
|
|
280
|
+
line,
|
|
281
|
+
column
|
|
282
|
+
});
|
|
313
283
|
return link({
|
|
314
|
-
href
|
|
315
|
-
text
|
|
316
|
-
line,
|
|
317
|
-
column
|
|
318
|
-
})
|
|
284
|
+
href,
|
|
285
|
+
text
|
|
319
286
|
});
|
|
320
287
|
}
|
|
321
288
|
});
|
|
@@ -324,21 +291,6 @@ const replaceLinks = (string, {
|
|
|
324
291
|
|
|
325
292
|
const escapeHtml = string => {
|
|
326
293
|
return string.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
const appendLineAndColumn = (url, {
|
|
330
|
-
line,
|
|
331
|
-
column
|
|
332
|
-
}) => {
|
|
333
|
-
if (line !== undefined && column !== undefined) {
|
|
334
|
-
return `${url}:${line}:${column}`;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
if (line !== undefined) {
|
|
338
|
-
return `${url}:${line}`;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
return url;
|
|
342
294
|
}; // `Error: yo
|
|
343
295
|
// at Object.execute (http://127.0.0.1:57300/build/src/__test__/file-throw.js:9:13)
|
|
344
296
|
// at doExec (http://127.0.0.1:3000/src/__test__/file-throw.js:452:38)
|
|
@@ -405,6 +357,193 @@ const link = ({
|
|
|
405
357
|
text = href
|
|
406
358
|
}) => `<a href="${href}">${text}</a>`;
|
|
407
359
|
|
|
360
|
+
const JSENV_ERROR_OVERLAY_TAGNAME = "jsenv-error-overlay";
|
|
361
|
+
const displayErrorInDocument = (error, {
|
|
362
|
+
rootDirectoryUrl,
|
|
363
|
+
errorBaseUrl,
|
|
364
|
+
openInEditor,
|
|
365
|
+
url,
|
|
366
|
+
line,
|
|
367
|
+
column,
|
|
368
|
+
codeFrame,
|
|
369
|
+
reportedBy,
|
|
370
|
+
requestedRessource
|
|
371
|
+
}) => {
|
|
372
|
+
const {
|
|
373
|
+
theme,
|
|
374
|
+
title,
|
|
375
|
+
text,
|
|
376
|
+
codeFramePromise,
|
|
377
|
+
tip
|
|
378
|
+
} = formatError(error, {
|
|
379
|
+
rootDirectoryUrl,
|
|
380
|
+
errorBaseUrl,
|
|
381
|
+
openInEditor,
|
|
382
|
+
url,
|
|
383
|
+
line,
|
|
384
|
+
column,
|
|
385
|
+
codeFrame,
|
|
386
|
+
reportedBy,
|
|
387
|
+
requestedRessource
|
|
388
|
+
});
|
|
389
|
+
let jsenvErrorOverlay = new JsenvErrorOverlay({
|
|
390
|
+
theme,
|
|
391
|
+
title,
|
|
392
|
+
text,
|
|
393
|
+
codeFramePromise,
|
|
394
|
+
tip
|
|
395
|
+
});
|
|
396
|
+
document.querySelectorAll(JSENV_ERROR_OVERLAY_TAGNAME).forEach(node => {
|
|
397
|
+
node.parentNode.removeChild(node);
|
|
398
|
+
});
|
|
399
|
+
document.body.appendChild(jsenvErrorOverlay);
|
|
400
|
+
|
|
401
|
+
const removeErrorOverlay = () => {
|
|
402
|
+
if (jsenvErrorOverlay && jsenvErrorOverlay.parentNode) {
|
|
403
|
+
document.body.removeChild(jsenvErrorOverlay);
|
|
404
|
+
jsenvErrorOverlay = null;
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
if (window.__reloader__) {
|
|
409
|
+
window.__reloader__.onstatuschange = () => {
|
|
410
|
+
if (window.__reloader__.status === "reloading") {
|
|
411
|
+
removeErrorOverlay();
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return removeErrorOverlay;
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
class JsenvErrorOverlay extends HTMLElement {
|
|
420
|
+
constructor({
|
|
421
|
+
theme,
|
|
422
|
+
title,
|
|
423
|
+
text,
|
|
424
|
+
codeFramePromise,
|
|
425
|
+
tip
|
|
426
|
+
}) {
|
|
427
|
+
super();
|
|
428
|
+
this.root = this.attachShadow({
|
|
429
|
+
mode: "open"
|
|
430
|
+
});
|
|
431
|
+
this.root.innerHTML = `
|
|
432
|
+
<style>
|
|
433
|
+
${overlayCSS}
|
|
434
|
+
</style>
|
|
435
|
+
<div class="backdrop"></div>
|
|
436
|
+
<div class="overlay" data-theme=${theme}>
|
|
437
|
+
<h1 class="title">
|
|
438
|
+
${title}
|
|
439
|
+
</h1>
|
|
440
|
+
<pre class="text">${text}</pre>
|
|
441
|
+
<div class="tip">
|
|
442
|
+
${tip}
|
|
443
|
+
</div>
|
|
444
|
+
</div>`;
|
|
445
|
+
|
|
446
|
+
this.root.querySelector(".backdrop").onclick = () => {
|
|
447
|
+
if (!this.parentNode) {
|
|
448
|
+
// not in document anymore
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
this.root.querySelector(".backdrop").onclick = null;
|
|
453
|
+
this.parentNode.removeChild(this);
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
if (codeFramePromise) {
|
|
457
|
+
codeFramePromise.then(codeFrame => {
|
|
458
|
+
if (this.parentNode) {
|
|
459
|
+
this.root.querySelector(".text").innerHTML += `\n\n${codeFrame}`;
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
if (customElements && !customElements.get(JSENV_ERROR_OVERLAY_TAGNAME)) {
|
|
468
|
+
customElements.define(JSENV_ERROR_OVERLAY_TAGNAME, JsenvErrorOverlay);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
const overlayCSS = `
|
|
472
|
+
:host {
|
|
473
|
+
position: fixed;
|
|
474
|
+
z-index: 99999;
|
|
475
|
+
top: 0;
|
|
476
|
+
left: 0;
|
|
477
|
+
width: 100%;
|
|
478
|
+
height: 100%;
|
|
479
|
+
overflow-y: scroll;
|
|
480
|
+
margin: 0;
|
|
481
|
+
background: rgba(0, 0, 0, 0.66);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
.backdrop {
|
|
485
|
+
position: absolute;
|
|
486
|
+
left: 0;
|
|
487
|
+
right: 0;
|
|
488
|
+
top: 0;
|
|
489
|
+
bottom: 0;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
.overlay {
|
|
493
|
+
position: relative;
|
|
494
|
+
background: rgba(0, 0, 0, 0.95);
|
|
495
|
+
width: 800px;
|
|
496
|
+
margin: 30px auto;
|
|
497
|
+
padding: 25px 40px;
|
|
498
|
+
padding-top: 0;
|
|
499
|
+
overflow: hidden; /* for h1 margins */
|
|
500
|
+
border-radius: 4px 8px;
|
|
501
|
+
box-shadow: 0 20px 40px rgb(0 0 0 / 30%), 0 15px 12px rgb(0 0 0 / 20%);
|
|
502
|
+
box-sizing: border-box;
|
|
503
|
+
font-family: monospace;
|
|
504
|
+
direction: ltr;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
h1 {
|
|
508
|
+
color: red;
|
|
509
|
+
text-align: center;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
pre {
|
|
513
|
+
overflow: auto;
|
|
514
|
+
max-width: 100%;
|
|
515
|
+
/* padding is nice + prevents scrollbar from hiding the text behind it */
|
|
516
|
+
/* does not work nicely on firefox though https://bugzilla.mozilla.org/show_bug.cgi?id=748518 */
|
|
517
|
+
padding: 20px;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
.tip {
|
|
521
|
+
border-top: 1px solid #999;
|
|
522
|
+
padding-top: 12px;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
[data-theme="dark"] {
|
|
526
|
+
color: #999;
|
|
527
|
+
}
|
|
528
|
+
[data-theme="dark"] pre {
|
|
529
|
+
background: #111;
|
|
530
|
+
border: 1px solid #333;
|
|
531
|
+
color: #eee;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
[data-theme="light"] {
|
|
535
|
+
color: #EEEEEE;
|
|
536
|
+
}
|
|
537
|
+
[data-theme="light"] pre {
|
|
538
|
+
background: #1E1E1E;
|
|
539
|
+
border: 1px solid white;
|
|
540
|
+
color: #EEEEEE;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
pre a {
|
|
544
|
+
color: inherit;
|
|
545
|
+
}`;
|
|
546
|
+
|
|
408
547
|
const {
|
|
409
548
|
Notification
|
|
410
549
|
} = window;
|
|
@@ -432,10 +571,14 @@ const displayErrorNotification = typeof Notification === "function" ? displayErr
|
|
|
432
571
|
const {
|
|
433
572
|
__html_supervisor__
|
|
434
573
|
} = window;
|
|
574
|
+
const supervisedScripts = [];
|
|
435
575
|
const installHtmlSupervisor = ({
|
|
576
|
+
rootDirectoryUrl,
|
|
436
577
|
logs,
|
|
437
578
|
measurePerf,
|
|
438
|
-
|
|
579
|
+
errorOverlay,
|
|
580
|
+
errorBaseUrl,
|
|
581
|
+
openInEditor
|
|
439
582
|
}) => {
|
|
440
583
|
|
|
441
584
|
const scriptExecutionResults = {};
|
|
@@ -471,8 +614,7 @@ const installHtmlSupervisor = ({
|
|
|
471
614
|
|
|
472
615
|
const onExecutionError = (executionResult, {
|
|
473
616
|
currentScript,
|
|
474
|
-
errorExposureInNotification = false
|
|
475
|
-
errorExposureInDocument = false
|
|
617
|
+
errorExposureInNotification = false
|
|
476
618
|
}) => {
|
|
477
619
|
const error = executionResult.error;
|
|
478
620
|
|
|
@@ -494,12 +636,6 @@ const installHtmlSupervisor = ({
|
|
|
494
636
|
displayErrorNotification(error);
|
|
495
637
|
}
|
|
496
638
|
|
|
497
|
-
if (errorExposureInDocument) {
|
|
498
|
-
displayErrorInDocument(error, {
|
|
499
|
-
rootDirectoryUrl
|
|
500
|
-
});
|
|
501
|
-
}
|
|
502
|
-
|
|
503
639
|
executionResult.exceptionSource = unevalException(error);
|
|
504
640
|
delete executionResult.error;
|
|
505
641
|
};
|
|
@@ -518,7 +654,9 @@ const installHtmlSupervisor = ({
|
|
|
518
654
|
currentScript,
|
|
519
655
|
execute // https://developer.mozilla.org/en-US/docs/web/html/element/script
|
|
520
656
|
|
|
521
|
-
}
|
|
657
|
+
}, {
|
|
658
|
+
reload = false
|
|
659
|
+
} = {}) => {
|
|
522
660
|
if (logs) {
|
|
523
661
|
console.group(`[jsenv] loading ${type} ${src}`);
|
|
524
662
|
}
|
|
@@ -529,7 +667,13 @@ const installHtmlSupervisor = ({
|
|
|
529
667
|
let error;
|
|
530
668
|
|
|
531
669
|
try {
|
|
532
|
-
|
|
670
|
+
const urlObject = new URL(src, window.location);
|
|
671
|
+
|
|
672
|
+
if (reload) {
|
|
673
|
+
urlObject.searchParams.set("hmr", Date.now());
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
result = await execute(urlObject.href);
|
|
533
677
|
completed = true;
|
|
534
678
|
} catch (e) {
|
|
535
679
|
completed = false;
|
|
@@ -593,12 +737,22 @@ const installHtmlSupervisor = ({
|
|
|
593
737
|
}));
|
|
594
738
|
|
|
595
739
|
__html_supervisor__.addScriptToExecute = async scriptToExecute => {
|
|
740
|
+
if (!supervisedScripts.includes(scriptToExecute)) {
|
|
741
|
+
supervisedScripts.push(scriptToExecute);
|
|
742
|
+
|
|
743
|
+
scriptToExecute.reload = () => {
|
|
744
|
+
return performExecution(scriptToExecute, {
|
|
745
|
+
reload: true
|
|
746
|
+
});
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
|
|
596
750
|
if (scriptToExecute.async) {
|
|
597
751
|
performExecution(scriptToExecute);
|
|
598
752
|
return;
|
|
599
753
|
}
|
|
600
754
|
|
|
601
|
-
const useDeferQueue = scriptToExecute.defer || scriptToExecute.type === "
|
|
755
|
+
const useDeferQueue = scriptToExecute.defer || scriptToExecute.type === "module";
|
|
602
756
|
|
|
603
757
|
if (useDeferQueue) {
|
|
604
758
|
// defer must wait for classic script to be done
|
|
@@ -652,60 +806,121 @@ const installHtmlSupervisor = ({
|
|
|
652
806
|
copy.forEach(scriptToExecute => {
|
|
653
807
|
__html_supervisor__.addScriptToExecute(scriptToExecute);
|
|
654
808
|
});
|
|
655
|
-
window.addEventListener("error", errorEvent => {
|
|
656
|
-
if (!errorEvent.isTrusted) {
|
|
657
|
-
// ignore custom error event (not sent by browser)
|
|
658
|
-
return;
|
|
659
|
-
}
|
|
660
809
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
line: errorEvent.lineno,
|
|
668
|
-
column: errorEvent.colno
|
|
669
|
-
});
|
|
670
|
-
});
|
|
810
|
+
if (errorOverlay) {
|
|
811
|
+
window.addEventListener("error", errorEvent => {
|
|
812
|
+
if (!errorEvent.isTrusted) {
|
|
813
|
+
// ignore custom error event (not sent by browser)
|
|
814
|
+
return;
|
|
815
|
+
}
|
|
671
816
|
|
|
672
|
-
if (window.__jsenv_event_source_client__) {
|
|
673
|
-
const onServerErrorEvent = serverErrorEvent => {
|
|
674
817
|
const {
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
line,
|
|
679
|
-
column,
|
|
680
|
-
contentFrame
|
|
681
|
-
} = JSON.parse(serverErrorEvent.data);
|
|
682
|
-
displayErrorInDocument({
|
|
683
|
-
message: reason,
|
|
684
|
-
stack: stack ? `${stack}\n\n${contentFrame}` : contentFrame
|
|
685
|
-
}, {
|
|
818
|
+
error
|
|
819
|
+
} = errorEvent;
|
|
820
|
+
displayErrorInDocument(error, {
|
|
686
821
|
rootDirectoryUrl,
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
822
|
+
errorBaseUrl,
|
|
823
|
+
openInEditor,
|
|
824
|
+
url: errorEvent.filename,
|
|
825
|
+
line: errorEvent.lineno,
|
|
826
|
+
column: errorEvent.colno,
|
|
827
|
+
reportedBy: "browser"
|
|
690
828
|
});
|
|
691
|
-
};
|
|
692
|
-
|
|
693
|
-
window.__jsenv_event_source_client__.addEventCallbacks({
|
|
694
|
-
file_not_found: onServerErrorEvent,
|
|
695
|
-
parse_error: onServerErrorEvent,
|
|
696
|
-
unexpected_error: onServerErrorEvent
|
|
697
829
|
});
|
|
830
|
+
|
|
831
|
+
if (window.__server_events__) {
|
|
832
|
+
const isExecuting = () => {
|
|
833
|
+
if (pendingExecutionCount > 0) {
|
|
834
|
+
return true;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
if (document.readyState === "loading" || document.readyState === "interactive") {
|
|
838
|
+
return true;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
if (window.__reloader__ && window.__reloader__.status === "reloading") {
|
|
842
|
+
return true;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
return false;
|
|
846
|
+
};
|
|
847
|
+
|
|
848
|
+
window.__server_events__.addEventCallbacks({
|
|
849
|
+
error_while_serving_file: serverErrorEvent => {
|
|
850
|
+
if (!isExecuting()) {
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
const {
|
|
855
|
+
message,
|
|
856
|
+
stack,
|
|
857
|
+
traceUrl,
|
|
858
|
+
traceLine,
|
|
859
|
+
traceColumn,
|
|
860
|
+
traceMessage,
|
|
861
|
+
requestedRessource,
|
|
862
|
+
isFaviconAutoRequest
|
|
863
|
+
} = JSON.parse(serverErrorEvent.data);
|
|
864
|
+
|
|
865
|
+
if (isFaviconAutoRequest) {
|
|
866
|
+
return;
|
|
867
|
+
} // setTimeout is to ensure the error
|
|
868
|
+
// dispatched on window by browser is displayed first,
|
|
869
|
+
// then the server error replaces it (because it contains more information)
|
|
870
|
+
|
|
871
|
+
|
|
872
|
+
setTimeout(() => {
|
|
873
|
+
displayErrorInDocument({
|
|
874
|
+
message,
|
|
875
|
+
stack
|
|
876
|
+
}, {
|
|
877
|
+
rootDirectoryUrl,
|
|
878
|
+
errorBaseUrl,
|
|
879
|
+
openInEditor,
|
|
880
|
+
url: traceUrl,
|
|
881
|
+
line: traceLine,
|
|
882
|
+
column: traceColumn,
|
|
883
|
+
codeFrame: traceMessage,
|
|
884
|
+
reportedBy: "server",
|
|
885
|
+
requestedRessource
|
|
886
|
+
});
|
|
887
|
+
}, 10);
|
|
888
|
+
}
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
};
|
|
893
|
+
|
|
894
|
+
__html_supervisor__.reloadSupervisedScript = ({
|
|
895
|
+
type,
|
|
896
|
+
src
|
|
897
|
+
}) => {
|
|
898
|
+
const supervisedScript = supervisedScripts.find(supervisedScriptCandidate => {
|
|
899
|
+
if (type && supervisedScriptCandidate.type !== type) {
|
|
900
|
+
return false;
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
if (supervisedScriptCandidate.src !== src) {
|
|
904
|
+
return false;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
return true;
|
|
908
|
+
});
|
|
909
|
+
|
|
910
|
+
if (supervisedScript) {
|
|
911
|
+
supervisedScript.reload();
|
|
698
912
|
}
|
|
699
913
|
};
|
|
914
|
+
|
|
700
915
|
const superviseScriptTypeModule = ({
|
|
701
916
|
src,
|
|
702
917
|
isInline
|
|
703
918
|
}) => {
|
|
704
919
|
__html_supervisor__.addScriptToExecute({
|
|
705
920
|
src,
|
|
706
|
-
type: "
|
|
921
|
+
type: "module",
|
|
707
922
|
isInline,
|
|
708
|
-
execute:
|
|
923
|
+
execute: url => import(url)
|
|
709
924
|
});
|
|
710
925
|
};
|
|
711
926
|
|