@jsenv/core 28.0.2 → 28.1.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/controllable_child_process.mjs +1 -2
- package/dist/controllable_worker_thread.mjs +1 -2
- package/dist/js/autoreload.js +25 -9
- package/dist/js/execute_using_dynamic_import.js +804 -1
- package/dist/js/script_type_module_supervisor.js +129 -0
- package/dist/js/supervisor.js +921 -0
- package/dist/main.js +432 -492
- package/package.json +13 -13
- package/readme.md +1 -1
- package/src/build/inject_global_version_mappings.js +3 -3
- package/src/dev/start_dev_server.js +2 -2
- package/src/execute/execute.js +1 -1
- package/src/execute/run.js +26 -38
- package/src/execute/runtimes/browsers/from_playwright.js +51 -77
- package/src/execute/runtimes/node/node_child_process.js +36 -36
- package/src/execute/runtimes/node/node_worker_thread.js +36 -36
- package/src/omega/kitchen.js +12 -9
- package/src/omega/omega_server.js +2 -2
- package/src/omega/server/file_service.js +2 -2
- package/src/omega/url_graph/url_info_transformations.js +8 -1
- package/src/plugins/autoreload/client/reload.js +20 -7
- package/src/plugins/autoreload/jsenv_plugin_autoreload_client.js +4 -4
- package/src/plugins/import_meta_hot/html_hot_dependencies.js +2 -2
- package/src/plugins/importmap/jsenv_plugin_importmap.js +5 -3
- package/src/plugins/inject_globals/inject_globals.js +3 -3
- package/src/plugins/inline/jsenv_plugin_data_urls.js +1 -1
- package/src/plugins/inline/jsenv_plugin_html_inline_content.js +10 -5
- package/src/plugins/plugins.js +5 -5
- package/src/plugins/server_events/jsenv_plugin_server_events_client_injection.js +4 -4
- package/src/plugins/supervisor/client/script_type_module_supervisor.js +108 -0
- package/src/plugins/supervisor/client/supervisor.js +921 -0
- package/src/plugins/{html_supervisor/jsenv_plugin_html_supervisor.js → supervisor/jsenv_plugin_supervisor.js} +128 -102
- package/src/plugins/toolbar/client/execution/toolbar_execution.js +1 -1
- package/src/plugins/toolbar/jsenv_plugin_toolbar.js +4 -4
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +7 -5
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_html.js +5 -4
- package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +13 -7
- package/src/plugins/transpilation/babel/new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js +6 -4
- package/src/plugins/transpilation/jsenv_plugin_transpilation.js +4 -2
- package/src/plugins/url_analysis/html/html_urls.js +11 -10
- package/src/test/coverage/babel_plugin_instrument.js +1 -35
- package/src/test/coverage/empty_coverage_factory.js +1 -1
- package/src/test/execute_plan.js +7 -3
- package/src/test/execute_test_plan.js +2 -1
- package/src/test/logs_file_execution.js +49 -8
- package/dist/js/html_supervisor_installer.js +0 -1091
- package/dist/js/html_supervisor_setup.js +0 -89
- package/dist/js/uneval.js +0 -804
- package/src/plugins/html_supervisor/client/error_formatter.js +0 -426
- package/src/plugins/html_supervisor/client/error_in_notification.js +0 -21
- package/src/plugins/html_supervisor/client/error_overlay.js +0 -191
- package/src/plugins/html_supervisor/client/html_supervisor_installer.js +0 -315
- package/src/plugins/html_supervisor/client/html_supervisor_setup.js +0 -89
- package/src/plugins/html_supervisor/client/perf_browser.js +0 -17
- package/src/plugins/html_supervisor/client/uneval_exception.js +0 -8
package/src/omega/kitchen.js
CHANGED
|
@@ -143,12 +143,12 @@ export const createKitchen = ({
|
|
|
143
143
|
newReference.original = reference.original || reference
|
|
144
144
|
// newReference.isEntryPoint = reference.isEntryPoint
|
|
145
145
|
}
|
|
146
|
-
const resolveReference = (reference) => {
|
|
146
|
+
const resolveReference = (reference, context = kitchenContext) => {
|
|
147
147
|
try {
|
|
148
148
|
let resolvedUrl = pluginController.callHooksUntil(
|
|
149
149
|
"resolveUrl",
|
|
150
150
|
reference,
|
|
151
|
-
|
|
151
|
+
context,
|
|
152
152
|
)
|
|
153
153
|
if (!resolvedUrl) {
|
|
154
154
|
throw new Error(`NO_RESOLVE`)
|
|
@@ -158,7 +158,7 @@ export const createKitchen = ({
|
|
|
158
158
|
pluginController.callHooks(
|
|
159
159
|
"redirectUrl",
|
|
160
160
|
reference,
|
|
161
|
-
|
|
161
|
+
context,
|
|
162
162
|
(returnValue) => {
|
|
163
163
|
const normalizedReturnValue = normalizeUrl(returnValue)
|
|
164
164
|
if (normalizedReturnValue === reference.url) {
|
|
@@ -178,7 +178,7 @@ export const createKitchen = ({
|
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
const urlInfo = urlGraph.reuseOrCreateUrlInfo(reference.url)
|
|
181
|
-
applyReferenceEffectsOnUrlInfo(reference, urlInfo,
|
|
181
|
+
applyReferenceEffectsOnUrlInfo(reference, urlInfo, context)
|
|
182
182
|
|
|
183
183
|
// This hook must touch reference.generatedUrl, NOT reference.url
|
|
184
184
|
// And this is because this hook inject query params used to:
|
|
@@ -189,7 +189,7 @@ export const createKitchen = ({
|
|
|
189
189
|
pluginController.callHooks(
|
|
190
190
|
"transformUrlSearchParams",
|
|
191
191
|
reference,
|
|
192
|
-
|
|
192
|
+
context,
|
|
193
193
|
(returnValue) => {
|
|
194
194
|
Object.keys(returnValue).forEach((key) => {
|
|
195
195
|
referenceUrlObject.searchParams.set(key, returnValue[key])
|
|
@@ -200,7 +200,7 @@ export const createKitchen = ({
|
|
|
200
200
|
const returnValue = pluginController.callHooksUntil(
|
|
201
201
|
"formatUrl",
|
|
202
202
|
reference,
|
|
203
|
-
|
|
203
|
+
context,
|
|
204
204
|
)
|
|
205
205
|
reference.generatedSpecifier = returnValue || reference.generatedUrl
|
|
206
206
|
reference.generatedSpecifier = urlSpecifierEncoding.encode(reference)
|
|
@@ -386,7 +386,7 @@ export const createKitchen = ({
|
|
|
386
386
|
...props,
|
|
387
387
|
})
|
|
388
388
|
references.push(reference)
|
|
389
|
-
const referencedUrlInfo = resolveReference(reference)
|
|
389
|
+
const referencedUrlInfo = resolveReference(reference, context)
|
|
390
390
|
return [reference, referencedUrlInfo]
|
|
391
391
|
}
|
|
392
392
|
const referenceUtils = {
|
|
@@ -460,7 +460,7 @@ export const createKitchen = ({
|
|
|
460
460
|
})
|
|
461
461
|
references[index] = nextReference
|
|
462
462
|
mutateReference(previousReference, nextReference)
|
|
463
|
-
const newUrlInfo = resolveReference(nextReference)
|
|
463
|
+
const newUrlInfo = resolveReference(nextReference, context)
|
|
464
464
|
const currentUrlInfo = context.urlGraph.getUrlInfo(
|
|
465
465
|
currentReference.url,
|
|
466
466
|
)
|
|
@@ -677,7 +677,10 @@ export const createKitchen = ({
|
|
|
677
677
|
await context.fetchUrlContent(originalUrlInfo, {
|
|
678
678
|
reference: originalReference,
|
|
679
679
|
})
|
|
680
|
-
if (
|
|
680
|
+
if (
|
|
681
|
+
originalUrlInfo.dependents.size === 0
|
|
682
|
+
// && context.scenarios.build
|
|
683
|
+
) {
|
|
681
684
|
context.urlGraph.deleteUrlInfo(originalUrlInfo.url)
|
|
682
685
|
}
|
|
683
686
|
return originalUrlInfo
|
|
@@ -30,7 +30,7 @@ export const startOmegaServer = async ({
|
|
|
30
30
|
|
|
31
31
|
plugins,
|
|
32
32
|
urlAnalysis,
|
|
33
|
-
|
|
33
|
+
supervisor,
|
|
34
34
|
nodeEsmResolution,
|
|
35
35
|
fileSystemMagicResolution,
|
|
36
36
|
transpilation,
|
|
@@ -92,7 +92,7 @@ export const startOmegaServer = async ({
|
|
|
92
92
|
|
|
93
93
|
plugins,
|
|
94
94
|
urlAnalysis,
|
|
95
|
-
|
|
95
|
+
supervisor,
|
|
96
96
|
nodeEsmResolution,
|
|
97
97
|
fileSystemMagicResolution,
|
|
98
98
|
transpilation,
|
|
@@ -25,7 +25,7 @@ export const createFileService = ({
|
|
|
25
25
|
|
|
26
26
|
plugins,
|
|
27
27
|
urlAnalysis,
|
|
28
|
-
|
|
28
|
+
supervisor,
|
|
29
29
|
nodeEsmResolution,
|
|
30
30
|
fileSystemMagicResolution,
|
|
31
31
|
transpilation,
|
|
@@ -118,7 +118,7 @@ export const createFileService = ({
|
|
|
118
118
|
runtimeCompat,
|
|
119
119
|
|
|
120
120
|
urlAnalysis,
|
|
121
|
-
|
|
121
|
+
supervisor,
|
|
122
122
|
nodeEsmResolution,
|
|
123
123
|
fileSystemMagicResolution,
|
|
124
124
|
transpilation,
|
|
@@ -81,6 +81,9 @@ export const createUrlInfoTransformer = ({
|
|
|
81
81
|
if (!SOURCEMAP.enabledOnContentType(urlInfo.contentType)) {
|
|
82
82
|
return
|
|
83
83
|
}
|
|
84
|
+
if (urlInfo.generatedUrl.startsWith("data:")) {
|
|
85
|
+
return
|
|
86
|
+
}
|
|
84
87
|
// sourcemap is a special kind of reference:
|
|
85
88
|
// It's a reference to a content generated dynamically the content itself.
|
|
86
89
|
// For this reason sourcemap are not added to urlInfo.references
|
|
@@ -173,7 +176,11 @@ export const createUrlInfoTransformer = ({
|
|
|
173
176
|
if (transformations) {
|
|
174
177
|
await applyIntermediateTransformations(urlInfo, transformations)
|
|
175
178
|
}
|
|
176
|
-
if (
|
|
179
|
+
if (
|
|
180
|
+
sourcemapsEnabled &&
|
|
181
|
+
urlInfo.sourcemap &&
|
|
182
|
+
!urlInfo.generatedUrl.startsWith("data:")
|
|
183
|
+
) {
|
|
177
184
|
// during build this function can be called after the file is cooked
|
|
178
185
|
// - to update content and sourcemap after "optimize" hook
|
|
179
186
|
// - to inject versioning into the entry point content
|
|
@@ -32,7 +32,20 @@ export const getDOMNodesUsingUrl = (urlToReload) => {
|
|
|
32
32
|
nodes.push({
|
|
33
33
|
node,
|
|
34
34
|
reload: () => {
|
|
35
|
-
|
|
35
|
+
if (node.nodeName === "SCRIPT") {
|
|
36
|
+
const copy = document.createElement("script")
|
|
37
|
+
Array.from(node.attributes).forEach((attribute) => {
|
|
38
|
+
copy.setAttribute(attribute.nodeName, attribute.nodeValue)
|
|
39
|
+
})
|
|
40
|
+
copy.src = injectQuery(node.src, { hmr: Date.now() })
|
|
41
|
+
if (node.parentNode) {
|
|
42
|
+
node.parentNode.replaceChild(copy, node)
|
|
43
|
+
} else {
|
|
44
|
+
document.body.appendChild(copy)
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
node[attributeName] = injectQuery(attribute, { hmr: Date.now() })
|
|
48
|
+
}
|
|
36
49
|
},
|
|
37
50
|
})
|
|
38
51
|
}
|
|
@@ -46,17 +59,17 @@ export const getDOMNodesUsingUrl = (urlToReload) => {
|
|
|
46
59
|
})
|
|
47
60
|
Array.from(document.querySelectorAll("script")).forEach((script) => {
|
|
48
61
|
visitNodeAttributeAsUrl(script, "src")
|
|
49
|
-
const
|
|
50
|
-
if (
|
|
51
|
-
const
|
|
62
|
+
const inlinedFromSrc = script.getAttribute("inlined-from-src")
|
|
63
|
+
if (inlinedFromSrc) {
|
|
64
|
+
const inlinedFromUrl = new URL(inlinedFromSrc, window.location.origin)
|
|
52
65
|
.href
|
|
53
|
-
if (shouldReloadUrl(
|
|
66
|
+
if (shouldReloadUrl(inlinedFromUrl)) {
|
|
54
67
|
nodes.push({
|
|
55
68
|
node: script,
|
|
56
69
|
reload: () =>
|
|
57
|
-
window.
|
|
70
|
+
window.__supervisor__.reloadSupervisedScript({
|
|
58
71
|
type: script.type,
|
|
59
|
-
src:
|
|
72
|
+
src: inlinedFromSrc,
|
|
60
73
|
}),
|
|
61
74
|
})
|
|
62
75
|
}
|
|
@@ -25,11 +25,11 @@ export const jsenvPluginAutoreloadClient = () => {
|
|
|
25
25
|
injectScriptNodeAsEarlyAsPossible(
|
|
26
26
|
htmlAst,
|
|
27
27
|
createHtmlNode({
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"injected-by": "jsenv:autoreload_client",
|
|
28
|
+
tagName: "script",
|
|
29
|
+
type: "module",
|
|
30
|
+
src: autoreloadClientReference.generatedSpecifier,
|
|
32
31
|
}),
|
|
32
|
+
"jsenv:autoreload_client",
|
|
33
33
|
)
|
|
34
34
|
const htmlModified = stringifyHtmlAst(htmlAst)
|
|
35
35
|
return {
|
|
@@ -48,7 +48,7 @@ export const collectHotDataFromHtmlAst = (htmlAst) => {
|
|
|
48
48
|
})
|
|
49
49
|
visitUrlSpecifierAttribute({
|
|
50
50
|
node,
|
|
51
|
-
attributeName: "
|
|
51
|
+
attributeName: "inlined-from-href",
|
|
52
52
|
hotAccepted,
|
|
53
53
|
})
|
|
54
54
|
}
|
|
@@ -60,7 +60,7 @@ export const collectHotDataFromHtmlAst = (htmlAst) => {
|
|
|
60
60
|
})
|
|
61
61
|
visitUrlSpecifierAttribute({
|
|
62
62
|
node,
|
|
63
|
-
attributeName: "
|
|
63
|
+
attributeName: "inlined-from-src",
|
|
64
64
|
hotAccepted,
|
|
65
65
|
})
|
|
66
66
|
}
|
|
@@ -134,7 +134,8 @@ export const jsenvPluginImportmap = () => {
|
|
|
134
134
|
})
|
|
135
135
|
setHtmlNodeText(importmap, inlineImportmapUrlInfo.content)
|
|
136
136
|
setHtmlNodeAttributes(importmap, {
|
|
137
|
-
"
|
|
137
|
+
"jsenv-plugin-owner": "jsenv:importmap",
|
|
138
|
+
"jsenv-plugin-action": "content_cooked",
|
|
138
139
|
})
|
|
139
140
|
onHtmlImportmapParsed(
|
|
140
141
|
JSON.parse(inlineImportmapUrlInfo.content),
|
|
@@ -162,8 +163,9 @@ export const jsenvPluginImportmap = () => {
|
|
|
162
163
|
setHtmlNodeText(importmap, importmapUrlInfo.content)
|
|
163
164
|
setHtmlNodeAttributes(importmap, {
|
|
164
165
|
"src": undefined,
|
|
165
|
-
"
|
|
166
|
-
"
|
|
166
|
+
"jsenv-plugin-owner": "jsenv:importmap",
|
|
167
|
+
"jsenv-plugin-action": "inlined",
|
|
168
|
+
"inlined-from-src": src,
|
|
167
169
|
})
|
|
168
170
|
|
|
169
171
|
const { line, column, lineEnd, columnEnd, isOriginal } =
|
|
@@ -30,10 +30,10 @@ const globalInjectorOnHtml = async (urlInfo, globals) => {
|
|
|
30
30
|
injectScriptNodeAsEarlyAsPossible(
|
|
31
31
|
htmlAst,
|
|
32
32
|
createHtmlNode({
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"injected-by": "jsenv:inject_globals",
|
|
33
|
+
tagName: "script",
|
|
34
|
+
textContent: clientCode,
|
|
36
35
|
}),
|
|
36
|
+
"jsenv:inject_globals",
|
|
37
37
|
)
|
|
38
38
|
return stringifyHtmlAst(htmlAst)
|
|
39
39
|
}
|
|
@@ -40,7 +40,7 @@ export const jsenvPluginDataUrls = () => {
|
|
|
40
40
|
return reference.generatedUrl
|
|
41
41
|
}
|
|
42
42
|
const specifier = DATA_URL.stringify({
|
|
43
|
-
contentType: urlInfo.
|
|
43
|
+
contentType: urlInfo.contentType,
|
|
44
44
|
base64Flag: urlInfo.data.base64Flag,
|
|
45
45
|
data: urlInfo.data.base64Flag
|
|
46
46
|
? dataToBase64(urlInfo.content)
|
|
@@ -59,7 +59,8 @@ export const jsenvPluginHtmlInlineContent = ({ analyzeConvertedScripts }) => {
|
|
|
59
59
|
})
|
|
60
60
|
setHtmlNodeText(styleNode, inlineStyleUrlInfo.content)
|
|
61
61
|
setHtmlNodeAttributes(styleNode, {
|
|
62
|
-
"
|
|
62
|
+
"jsenv-plugin-owner": "jsenv:html_inline_content",
|
|
63
|
+
"jsenv-plugin-action": "content_cooked",
|
|
63
64
|
})
|
|
64
65
|
})
|
|
65
66
|
},
|
|
@@ -71,14 +72,17 @@ export const jsenvPluginHtmlInlineContent = ({ analyzeConvertedScripts }) => {
|
|
|
71
72
|
// If the inline script was already handled by an other plugin, ignore it
|
|
72
73
|
// - we want to preserve inline scripts generated by html supervisor during dev
|
|
73
74
|
// - we want to avoid cooking twice a script during build
|
|
74
|
-
const
|
|
75
|
+
const jsenvPluginOwner = getHtmlNodeAttribute(
|
|
76
|
+
scriptNode,
|
|
77
|
+
"jsenv-plugin-owner",
|
|
78
|
+
)
|
|
75
79
|
if (
|
|
76
|
-
|
|
80
|
+
jsenvPluginOwner === "jsenv:as_js_classic_html" &&
|
|
77
81
|
!analyzeConvertedScripts
|
|
78
82
|
) {
|
|
79
83
|
return
|
|
80
84
|
}
|
|
81
|
-
if (
|
|
85
|
+
if (jsenvPluginOwner === "jsenv:supervisor") {
|
|
82
86
|
return
|
|
83
87
|
}
|
|
84
88
|
actions.push(async () => {
|
|
@@ -117,7 +121,8 @@ export const jsenvPluginHtmlInlineContent = ({ analyzeConvertedScripts }) => {
|
|
|
117
121
|
})
|
|
118
122
|
setHtmlNodeText(scriptNode, inlineScriptUrlInfo.content)
|
|
119
123
|
setHtmlNodeAttributes(scriptNode, {
|
|
120
|
-
"
|
|
124
|
+
"jsenv-plugin-owner": "jsenv:html_inline_content",
|
|
125
|
+
"jsenv-plugin-action": "content_cooked",
|
|
121
126
|
...(extension
|
|
122
127
|
? { type: type === "js_module" ? "module" : undefined }
|
|
123
128
|
: {}),
|
package/src/plugins/plugins.js
CHANGED
|
@@ -7,7 +7,7 @@ import { jsenvPluginUrlVersion } from "./url_version/jsenv_plugin_url_version.js
|
|
|
7
7
|
import { jsenvPluginFileUrls } from "./file_urls/jsenv_plugin_file_urls.js"
|
|
8
8
|
import { jsenvPluginHttpUrls } from "./http_urls/jsenv_plugin_http_urls.js"
|
|
9
9
|
import { jsenvPluginInline } from "./inline/jsenv_plugin_inline.js"
|
|
10
|
-
import {
|
|
10
|
+
import { jsenvPluginSupervisor } from "./supervisor/jsenv_plugin_supervisor.js"
|
|
11
11
|
import { jsenvPluginCommonJsGlobals } from "./commonjs_globals/jsenv_plugin_commonjs_globals.js"
|
|
12
12
|
import { jsenvPluginImportMetaScenarios } from "./import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js"
|
|
13
13
|
import { jsenvPluginTranspilation } from "./transpilation/jsenv_plugin_transpilation.js"
|
|
@@ -27,7 +27,7 @@ export const getCorePlugins = ({
|
|
|
27
27
|
runtimeCompat,
|
|
28
28
|
|
|
29
29
|
urlAnalysis = {},
|
|
30
|
-
|
|
30
|
+
supervisor,
|
|
31
31
|
nodeEsmResolution = true,
|
|
32
32
|
fileSystemMagicResolution,
|
|
33
33
|
directoryReferenceAllowed,
|
|
@@ -40,8 +40,8 @@ export const getCorePlugins = ({
|
|
|
40
40
|
clientFilesPruneCallbackList,
|
|
41
41
|
explorer,
|
|
42
42
|
} = {}) => {
|
|
43
|
-
if (
|
|
44
|
-
|
|
43
|
+
if (supervisor === true) {
|
|
44
|
+
supervisor = {}
|
|
45
45
|
}
|
|
46
46
|
if (nodeEsmResolution === true) {
|
|
47
47
|
nodeEsmResolution = {}
|
|
@@ -56,7 +56,7 @@ export const getCorePlugins = ({
|
|
|
56
56
|
return [
|
|
57
57
|
jsenvPluginUrlAnalysis({ rootDirectoryUrl, ...urlAnalysis }),
|
|
58
58
|
jsenvPluginTranspilation(transpilation),
|
|
59
|
-
...(
|
|
59
|
+
...(supervisor ? [jsenvPluginSupervisor(supervisor)] : []), // before inline as it turns inline <script> into <script src>
|
|
60
60
|
jsenvPluginImportmap(),
|
|
61
61
|
// before node esm to handle bare specifiers
|
|
62
62
|
// + before node esm to handle importmap before inline content
|
|
@@ -32,11 +32,11 @@ export const jsenvPluginServerEventsClientInjection = () => {
|
|
|
32
32
|
injectScriptNodeAsEarlyAsPossible(
|
|
33
33
|
htmlAst,
|
|
34
34
|
createHtmlNode({
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"injected-by": "jsenv:server_events",
|
|
35
|
+
tagName: "script",
|
|
36
|
+
type: "module",
|
|
37
|
+
src: serverEventsClientFileReference.generatedSpecifier,
|
|
39
38
|
}),
|
|
39
|
+
"jsenv:server_events",
|
|
40
40
|
)
|
|
41
41
|
const htmlModified = stringifyHtmlAst(htmlAst)
|
|
42
42
|
return {
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
let previousExecutionPromise
|
|
2
|
+
|
|
3
|
+
// https://twitter.com/damienmaillard/status/1554752482273787906
|
|
4
|
+
const isWebkitOrSafari =
|
|
5
|
+
typeof window.webkitConvertPointFromNodeToPage === "function"
|
|
6
|
+
|
|
7
|
+
export const superviseScriptTypeModule = async ({ src, async }) => {
|
|
8
|
+
const execute = isWebkitOrSafari
|
|
9
|
+
? createExecuteWithDynamicImport({ src })
|
|
10
|
+
: createExecuteWithScript({ src })
|
|
11
|
+
const startExecution = () => {
|
|
12
|
+
const execution = window.__supervisor__.createExecution({
|
|
13
|
+
src,
|
|
14
|
+
type: "js_module",
|
|
15
|
+
execute,
|
|
16
|
+
})
|
|
17
|
+
return execution.start()
|
|
18
|
+
}
|
|
19
|
+
if (async) {
|
|
20
|
+
startExecution()
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
// there is guaranteed execution order for non async script type="module"
|
|
24
|
+
// see https://gist.github.com/jakub-g/385ee6b41085303a53ad92c7c8afd7a6#typemodule-vs-non-module-typetextjavascript-vs-script-nomodule
|
|
25
|
+
if (previousExecutionPromise) {
|
|
26
|
+
await previousExecutionPromise
|
|
27
|
+
previousExecutionPromise = null
|
|
28
|
+
}
|
|
29
|
+
previousExecutionPromise = startExecution()
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const createExecuteWithScript = ({ src }) => {
|
|
33
|
+
const currentScript = document.querySelector(
|
|
34
|
+
`script[type="module"][inlined-from-src="${src}"]`,
|
|
35
|
+
)
|
|
36
|
+
const parentNode = currentScript.parentNode
|
|
37
|
+
let nodeToReplace
|
|
38
|
+
let currentScriptClone
|
|
39
|
+
|
|
40
|
+
return async ({ isReload }) => {
|
|
41
|
+
const urlObject = new URL(src, window.location)
|
|
42
|
+
const loadPromise = new Promise((resolve, reject) => {
|
|
43
|
+
currentScriptClone = document.createElement("script")
|
|
44
|
+
Array.from(currentScript.attributes).forEach((attribute) => {
|
|
45
|
+
currentScriptClone.setAttribute(attribute.nodeName, attribute.nodeValue)
|
|
46
|
+
})
|
|
47
|
+
if (isReload) {
|
|
48
|
+
urlObject.searchParams.set("hmr", Date.now())
|
|
49
|
+
nodeToReplace = currentScriptClone
|
|
50
|
+
currentScriptClone.src = urlObject.href
|
|
51
|
+
} else {
|
|
52
|
+
currentScriptClone.removeAttribute("jsenv-plugin-owner")
|
|
53
|
+
currentScriptClone.removeAttribute("jsenv-plugin-action")
|
|
54
|
+
currentScriptClone.removeAttribute("inlined-from-src")
|
|
55
|
+
currentScriptClone.removeAttribute("original-position")
|
|
56
|
+
currentScriptClone.removeAttribute("original-src-position")
|
|
57
|
+
nodeToReplace = currentScript
|
|
58
|
+
currentScriptClone.src = src
|
|
59
|
+
}
|
|
60
|
+
currentScriptClone.addEventListener("error", reject)
|
|
61
|
+
currentScriptClone.addEventListener("load", resolve)
|
|
62
|
+
parentNode.replaceChild(currentScriptClone, nodeToReplace)
|
|
63
|
+
})
|
|
64
|
+
try {
|
|
65
|
+
await loadPromise
|
|
66
|
+
} catch (e) {
|
|
67
|
+
// eslint-disable-next-line no-throw-literal
|
|
68
|
+
throw {
|
|
69
|
+
message: `Failed to fetch module: ${urlObject.href}`,
|
|
70
|
+
reportedBy: "script_error_event",
|
|
71
|
+
url: urlObject.href,
|
|
72
|
+
// window.error won't be dispatched for this error
|
|
73
|
+
needsReport: true,
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// do not resolve right away, wait for top level execution
|
|
77
|
+
try {
|
|
78
|
+
const namespace = await import(urlObject.href)
|
|
79
|
+
return namespace
|
|
80
|
+
} catch (e) {
|
|
81
|
+
e.reportedBy = "dynamic_import"
|
|
82
|
+
throw e
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const createExecuteWithDynamicImport = ({ src }) => {
|
|
88
|
+
return async ({ isReload }) => {
|
|
89
|
+
const urlObject = new URL(src, window.location)
|
|
90
|
+
if (isReload) {
|
|
91
|
+
urlObject.searchParams.set("hmr", Date.now())
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
const namespace = await import(urlObject.href)
|
|
95
|
+
return namespace
|
|
96
|
+
} catch (e) {
|
|
97
|
+
e.reportedBy = "dynamic_import"
|
|
98
|
+
// dynamic import would hide the error to the browser
|
|
99
|
+
// so it must be re-reported using window.reportError
|
|
100
|
+
if (typeof window.reportError === "function") {
|
|
101
|
+
window.reportError(e)
|
|
102
|
+
} else {
|
|
103
|
+
console.error(e)
|
|
104
|
+
}
|
|
105
|
+
throw e
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|