@jsenv/core 34.2.2 → 35.0.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 +1 -1
- package/dist/html/explorer.html +5 -4
- package/dist/{jsenv.js → jsenv_core.js} +840 -3914
- package/package.json +7 -21
- package/src/build/build.js +34 -16
- package/src/build/version_mappings_injection.js +20 -27
- package/src/dev/file_service.js +9 -9
- package/src/dev/start_dev_server.js +3 -3
- package/src/dev/user_agent.js +1 -1
- package/src/kitchen/kitchen.js +5 -3
- package/src/main.js +0 -23
- package/src/plugins/autoreload/jsenv_plugin_autoreload_client.js +2 -2
- package/src/plugins/importmap/jsenv_plugin_importmap.js +6 -2
- package/src/plugins/{inline/jsenv_plugin_html_inline_content.js → inline_content_analysis/jsenv_plugin_html_inline_content_analysis.js} +12 -6
- package/src/plugins/{inline/jsenv_plugin_inline.js → inline_content_analysis/jsenv_plugin_inline_content_analysis.js} +8 -10
- package/src/plugins/{inline/jsenv_plugin_js_inline_content.js → inline_content_analysis/jsenv_plugin_js_inline_content_analysis.js} +4 -2
- package/src/plugins/inlining/jsenv_plugin_inlining.js +22 -0
- package/src/plugins/{inline/jsenv_plugin_inline_query_param.js → inlining/jsenv_plugin_inlining_as_data_url.js} +16 -9
- package/src/plugins/inlining/jsenv_plugin_inlining_into_html.js +149 -0
- package/src/plugins/plugins.js +5 -2
- package/src/plugins/ribbon/jsenv_plugin_ribbon.js +11 -10
- package/src/plugins/server_events/jsenv_plugin_server_events_client_injection.js +2 -2
- package/src/plugins/supervisor/html_supervisor_injection.js +23 -25
- package/src/plugins/supervisor/jsenv_plugin_supervisor.js +1 -1
- package/src/plugins/transpilation/babel/require_babel_plugin.js +1 -1
- package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +20 -5
- package/src/plugins/transpilation/js_module_fallback/convert_js_module_to_js_classic.js +1 -1
- package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_fallback_inside_html.js +2 -2
- package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_fallback_on_workers.js +3 -3
- package/src/plugins/url_analysis/html/html_urls.js +1 -1
- package/dist/controllable_child_process.mjs +0 -129
- package/dist/controllable_worker_thread.mjs +0 -91
- package/dist/js/execute_using_dynamic_import.js +0 -850
- package/dist/js/v8_coverage.js +0 -508
- package/src/execute/execute.js +0 -109
- package/src/execute/run.js +0 -161
- package/src/execute/runtimes/browsers/chromium.js +0 -10
- package/src/execute/runtimes/browsers/firefox.js +0 -9
- package/src/execute/runtimes/browsers/from_playwright.js +0 -574
- package/src/execute/runtimes/browsers/middleware_istanbul.js +0 -65
- package/src/execute/runtimes/browsers/middleware_js_supervisor.js +0 -100
- package/src/execute/runtimes/browsers/webkit.js +0 -26
- package/src/execute/runtimes/node/child_exec_options.js +0 -166
- package/src/execute/runtimes/node/controllable_child_process.mjs +0 -135
- package/src/execute/runtimes/node/controllable_worker_thread.mjs +0 -103
- package/src/execute/runtimes/node/exec_options.js +0 -44
- package/src/execute/runtimes/node/execute_using_dynamic_import.js +0 -55
- package/src/execute/runtimes/node/exit_codes.js +0 -9
- package/src/execute/runtimes/node/kill_process_tree.js +0 -76
- package/src/execute/runtimes/node/node_child_process.js +0 -348
- package/src/execute/runtimes/node/node_execution_performance.js +0 -67
- package/src/execute/runtimes/node/node_worker_thread.js +0 -282
- package/src/execute/runtimes/node/profiler_v8_coverage.js +0 -56
- package/src/execute/runtimes/readme.md +0 -13
- package/src/execute/web_server_param.js +0 -74
- package/src/test/coverage/babel_plugin_instrument.js +0 -48
- package/src/test/coverage/coverage_reporter_html_directory.js +0 -32
- package/src/test/coverage/coverage_reporter_json_file.js +0 -17
- package/src/test/coverage/coverage_reporter_text_log.js +0 -19
- package/src/test/coverage/empty_coverage_factory.js +0 -52
- package/src/test/coverage/file_by_file_coverage.js +0 -25
- package/src/test/coverage/istanbul_coverage_composition.js +0 -28
- package/src/test/coverage/istanbul_coverage_map_from_coverage.js +0 -16
- package/src/test/coverage/list_files_not_covered.js +0 -15
- package/src/test/coverage/missing_coverage.js +0 -41
- package/src/test/coverage/report_to_coverage.js +0 -198
- package/src/test/coverage/v8_and_istanbul.js +0 -37
- package/src/test/coverage/v8_coverage.js +0 -26
- package/src/test/coverage/v8_coverage_composition.js +0 -24
- package/src/test/coverage/v8_coverage_node_directory.js +0 -85
- package/src/test/coverage/v8_coverage_to_istanbul.js +0 -99
- package/src/test/execute_steps.js +0 -425
- package/src/test/execute_test_plan.js +0 -372
- package/src/test/execution_colors.js +0 -10
- package/src/test/execution_steps.js +0 -65
- package/src/test/gc.js +0 -9
- package/src/test/logs_file_execution.js +0 -427
- package/src/test/logs_file_execution.test.mjs +0 -41
- package/src/test/readme.md +0 -3
- /package/src/{basic_fetch.js → helpers/basic_fetch.js} +0 -0
- /package/src/{lookup_package_directory.js → helpers/lookup_package_directory.js} +0 -0
- /package/src/{ping_server.js → helpers/ping_server.js} +0 -0
- /package/src/{require_from_jsenv.js → helpers/require_from_jsenv.js} +0 -0
- /package/src/{watch_source_files.js → helpers/watch_source_files.js} +0 -0
- /package/src/{web_url_converter.js → helpers/web_url_converter.js} +0 -0
- /package/src/plugins/{inline → inline_content_analysis}/client/inline_content.js +0 -0
- /package/src/plugins/{inline → inline_content_analysis}/jsenv_plugin_data_urls.js +0 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import {
|
|
2
|
+
parseHtmlString,
|
|
3
|
+
stringifyHtmlAst,
|
|
4
|
+
visitHtmlNodes,
|
|
5
|
+
getHtmlNodeText,
|
|
6
|
+
analyzeScriptNode,
|
|
7
|
+
getHtmlNodeAttribute,
|
|
8
|
+
setHtmlNodeAttributes,
|
|
9
|
+
setHtmlNodeText,
|
|
10
|
+
getHtmlNodePosition,
|
|
11
|
+
} from "@jsenv/ast"
|
|
12
|
+
|
|
13
|
+
export const jsenvPluginInliningIntoHtml = () => {
|
|
14
|
+
return {
|
|
15
|
+
name: "jsenv:inlining_into_html",
|
|
16
|
+
appliesDuring: "*",
|
|
17
|
+
transformUrlContent: {
|
|
18
|
+
html: async (urlInfo, context) => {
|
|
19
|
+
const htmlAst = parseHtmlString(urlInfo.content)
|
|
20
|
+
const mutations = []
|
|
21
|
+
const actions = []
|
|
22
|
+
|
|
23
|
+
const onStyleSheet = (linkNode, { href }) => {
|
|
24
|
+
const linkReference = context.referenceUtils.find(
|
|
25
|
+
(ref) =>
|
|
26
|
+
ref.generatedSpecifier === href &&
|
|
27
|
+
ref.type === "link_href" &&
|
|
28
|
+
ref.subtype === "stylesheet",
|
|
29
|
+
)
|
|
30
|
+
if (
|
|
31
|
+
!linkReference.original ||
|
|
32
|
+
!linkReference.original.searchParams.has("inline")
|
|
33
|
+
) {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
const linkUrlInfo = context.urlGraph.getUrlInfo(linkReference.url)
|
|
37
|
+
actions.push(async () => {
|
|
38
|
+
await context.cook(linkUrlInfo, {
|
|
39
|
+
reference: linkReference,
|
|
40
|
+
})
|
|
41
|
+
const { line, column, isOriginal } = getHtmlNodePosition(linkNode, {
|
|
42
|
+
preferOriginal: true,
|
|
43
|
+
})
|
|
44
|
+
context.referenceUtils.becomesInline(linkReference, {
|
|
45
|
+
line: line - 1,
|
|
46
|
+
column,
|
|
47
|
+
isOriginal,
|
|
48
|
+
specifier: linkReference.generatedSpecifier,
|
|
49
|
+
content: linkUrlInfo.content,
|
|
50
|
+
contentType: linkUrlInfo.contentType,
|
|
51
|
+
})
|
|
52
|
+
mutations.push(() => {
|
|
53
|
+
setHtmlNodeAttributes(linkNode, {
|
|
54
|
+
"inlined-from-href": href,
|
|
55
|
+
"href": undefined,
|
|
56
|
+
"rel": undefined,
|
|
57
|
+
"type": undefined,
|
|
58
|
+
"as": undefined,
|
|
59
|
+
"crossorigin": undefined,
|
|
60
|
+
"integrity": undefined,
|
|
61
|
+
"jsenv-inlined-by": "jsenv:inlining_into_html",
|
|
62
|
+
})
|
|
63
|
+
linkNode.nodeName = "style"
|
|
64
|
+
linkNode.tagName = "style"
|
|
65
|
+
setHtmlNodeText(linkNode, linkUrlInfo.content, {
|
|
66
|
+
indentation: "auto",
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
const onScriptWithSrc = (scriptNode, { src }) => {
|
|
72
|
+
const scriptReference = context.referenceUtils.find(
|
|
73
|
+
(ref) => ref.generatedSpecifier === src && ref.type === "script",
|
|
74
|
+
)
|
|
75
|
+
if (
|
|
76
|
+
!scriptReference.original ||
|
|
77
|
+
!scriptReference.original.searchParams.has("inline")
|
|
78
|
+
) {
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
const scriptUrlInfo = context.urlGraph.getUrlInfo(scriptReference.url)
|
|
82
|
+
actions.push(async () => {
|
|
83
|
+
await context.cook(scriptUrlInfo, {
|
|
84
|
+
reference: scriptReference,
|
|
85
|
+
})
|
|
86
|
+
const { line, column, isOriginal } = getHtmlNodePosition(
|
|
87
|
+
scriptNode,
|
|
88
|
+
{
|
|
89
|
+
preferOriginal: true,
|
|
90
|
+
},
|
|
91
|
+
)
|
|
92
|
+
context.referenceUtils.becomesInline(scriptReference, {
|
|
93
|
+
line: line - 1,
|
|
94
|
+
column,
|
|
95
|
+
isOriginal,
|
|
96
|
+
specifier: scriptReference.generatedSpecifier,
|
|
97
|
+
content: scriptUrlInfo.content,
|
|
98
|
+
contentType: scriptUrlInfo.contentType,
|
|
99
|
+
})
|
|
100
|
+
mutations.push(() => {
|
|
101
|
+
setHtmlNodeAttributes(scriptNode, {
|
|
102
|
+
"inlined-from-src": src,
|
|
103
|
+
"src": undefined,
|
|
104
|
+
"crossorigin": undefined,
|
|
105
|
+
"integrity": undefined,
|
|
106
|
+
"jsenv-inlined-by": "jsenv:inlining_into_html",
|
|
107
|
+
})
|
|
108
|
+
setHtmlNodeText(scriptNode, scriptUrlInfo.content, {
|
|
109
|
+
indentation: "auto",
|
|
110
|
+
})
|
|
111
|
+
})
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
visitHtmlNodes(htmlAst, {
|
|
116
|
+
link: (linkNode) => {
|
|
117
|
+
const rel = getHtmlNodeAttribute(linkNode, "rel")
|
|
118
|
+
if (rel !== "stylesheet") {
|
|
119
|
+
return
|
|
120
|
+
}
|
|
121
|
+
const href = getHtmlNodeAttribute(linkNode, "href")
|
|
122
|
+
if (!href) {
|
|
123
|
+
return
|
|
124
|
+
}
|
|
125
|
+
onStyleSheet(linkNode, { href })
|
|
126
|
+
},
|
|
127
|
+
script: (scriptNode) => {
|
|
128
|
+
const { type } = analyzeScriptNode(scriptNode)
|
|
129
|
+
const scriptNodeText = getHtmlNodeText(scriptNode)
|
|
130
|
+
if (scriptNodeText) {
|
|
131
|
+
return
|
|
132
|
+
}
|
|
133
|
+
const src = getHtmlNodeAttribute(scriptNode, "src")
|
|
134
|
+
if (!src) {
|
|
135
|
+
return
|
|
136
|
+
}
|
|
137
|
+
onScriptWithSrc(scriptNode, { type, src })
|
|
138
|
+
},
|
|
139
|
+
})
|
|
140
|
+
if (actions.length > 0) {
|
|
141
|
+
await Promise.all(actions.map((action) => action()))
|
|
142
|
+
}
|
|
143
|
+
mutations.forEach((mutation) => mutation())
|
|
144
|
+
const htmlModified = stringifyHtmlAst(htmlAst)
|
|
145
|
+
return htmlModified
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
}
|
|
149
|
+
}
|
package/src/plugins/plugins.js
CHANGED
|
@@ -4,7 +4,8 @@ import { jsenvPluginUrlResolution } from "./url_resolution/jsenv_plugin_url_reso
|
|
|
4
4
|
import { jsenvPluginUrlVersion } from "./url_version/jsenv_plugin_url_version.js"
|
|
5
5
|
import { jsenvPluginFileUrls } from "./file_urls/jsenv_plugin_file_urls.js"
|
|
6
6
|
import { jsenvPluginHttpUrls } from "./http_urls/jsenv_plugin_http_urls.js"
|
|
7
|
-
import {
|
|
7
|
+
import { jsenvPluginInlineContentAnalysis } from "./inline_content_analysis/jsenv_plugin_inline_content_analysis.js"
|
|
8
|
+
import { jsenvPluginInlining } from "./inlining/jsenv_plugin_inlining.js"
|
|
8
9
|
import { jsenvPluginSupervisor } from "./supervisor/jsenv_plugin_supervisor.js"
|
|
9
10
|
import { jsenvPluginCommonJsGlobals } from "./commonjs_globals/jsenv_plugin_commonjs_globals.js"
|
|
10
11
|
import { jsenvPluginImportMetaScenarios } from "./import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js"
|
|
@@ -31,6 +32,7 @@ export const getCorePlugins = ({
|
|
|
31
32
|
directoryReferenceAllowed,
|
|
32
33
|
supervisor,
|
|
33
34
|
transpilation = true,
|
|
35
|
+
inlining = true,
|
|
34
36
|
|
|
35
37
|
clientAutoreload = false,
|
|
36
38
|
clientFileChangeCallbackList,
|
|
@@ -66,7 +68,8 @@ export const getCorePlugins = ({
|
|
|
66
68
|
jsenvPluginImportmap(),
|
|
67
69
|
// before node esm to handle bare specifiers
|
|
68
70
|
// + before node esm to handle importmap before inline content
|
|
69
|
-
|
|
71
|
+
jsenvPluginInlineContentAnalysis(), // before "file urls" to resolve and load inline urls
|
|
72
|
+
...(inlining ? [jsenvPluginInlining()] : []),
|
|
70
73
|
...(supervisor ? [jsenvPluginSupervisor(supervisor)] : []), // after inline as it needs inline script to be cooked
|
|
71
74
|
jsenvPluginFileUrls({
|
|
72
75
|
directoryReferenceAllowed,
|
|
@@ -47,16 +47,17 @@ export const jsenvPluginRibbon = ({
|
|
|
47
47
|
null,
|
|
48
48
|
" ",
|
|
49
49
|
)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
50
|
+
injectHtmlNode(
|
|
51
|
+
htmlAst,
|
|
52
|
+
createHtmlNode({
|
|
53
|
+
tagName: "script",
|
|
54
|
+
type: "module",
|
|
55
|
+
textContent: `import { injectRibbon } from "${ribbonClientFileReference.generatedSpecifier}"
|
|
56
|
+
|
|
57
|
+
injectRibbon(${paramsJson});`,
|
|
58
|
+
}),
|
|
59
|
+
"jsenv:ribbon",
|
|
60
|
+
)
|
|
60
61
|
return stringifyHtmlAst(htmlAst)
|
|
61
62
|
},
|
|
62
63
|
},
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import {
|
|
7
7
|
parseHtmlString,
|
|
8
8
|
stringifyHtmlAst,
|
|
9
|
-
|
|
9
|
+
injectHtmlNodeAsEarlyAsPossible,
|
|
10
10
|
createHtmlNode,
|
|
11
11
|
} from "@jsenv/ast"
|
|
12
12
|
|
|
@@ -30,7 +30,7 @@ export const jsenvPluginServerEventsClientInjection = () => {
|
|
|
30
30
|
specifier: serverEventsClientFileUrl,
|
|
31
31
|
},
|
|
32
32
|
)
|
|
33
|
-
|
|
33
|
+
injectHtmlNodeAsEarlyAsPossible(
|
|
34
34
|
htmlAst,
|
|
35
35
|
createHtmlNode({
|
|
36
36
|
tagName: "script",
|
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
getHtmlNodeAttribute,
|
|
53
53
|
setHtmlNodeAttributes,
|
|
54
54
|
analyzeScriptNode,
|
|
55
|
-
|
|
55
|
+
injectHtmlNodeAsEarlyAsPossible,
|
|
56
56
|
createHtmlNode,
|
|
57
57
|
getHtmlNodePosition,
|
|
58
58
|
getHtmlNodeText,
|
|
@@ -125,7 +125,9 @@ export const injectSupervisorIntoHTML = async (
|
|
|
125
125
|
src: inlineScriptSrc,
|
|
126
126
|
})
|
|
127
127
|
mutations.push(() => {
|
|
128
|
-
setHtmlNodeText(scriptNode, remoteJsSupervised
|
|
128
|
+
setHtmlNodeText(scriptNode, remoteJsSupervised, {
|
|
129
|
+
indentation: "auto",
|
|
130
|
+
})
|
|
129
131
|
setHtmlNodeAttributes(scriptNode, {
|
|
130
132
|
"jsenv-cooked-by": "jsenv:supervisor",
|
|
131
133
|
"src": undefined,
|
|
@@ -144,7 +146,9 @@ export const injectSupervisorIntoHTML = async (
|
|
|
144
146
|
inlineSrc: inlineScriptSrc,
|
|
145
147
|
})
|
|
146
148
|
mutations.push(() => {
|
|
147
|
-
setHtmlNodeText(scriptNode, inlineJsSupervised
|
|
149
|
+
setHtmlNodeText(scriptNode, inlineJsSupervised, {
|
|
150
|
+
indentation: "auto",
|
|
151
|
+
})
|
|
148
152
|
setHtmlNodeAttributes(scriptNode, {
|
|
149
153
|
"jsenv-cooked-by": "jsenv:supervisor",
|
|
150
154
|
})
|
|
@@ -171,7 +175,7 @@ export const injectSupervisorIntoHTML = async (
|
|
|
171
175
|
src,
|
|
172
176
|
})
|
|
173
177
|
mutations.push(() => {
|
|
174
|
-
setHtmlNodeText(scriptNode, remoteJsSupervised)
|
|
178
|
+
setHtmlNodeText(scriptNode, remoteJsSupervised, { indentation: "auto" })
|
|
175
179
|
setHtmlNodeAttributes(scriptNode, {
|
|
176
180
|
"jsenv-cooked-by": "jsenv:supervisor",
|
|
177
181
|
"src": undefined,
|
|
@@ -204,6 +208,10 @@ export const injectSupervisorIntoHTML = async (
|
|
|
204
208
|
}
|
|
205
209
|
const src = getHtmlNodeAttribute(scriptNode, "src")
|
|
206
210
|
if (src) {
|
|
211
|
+
const urlObject = new URL(src, "http://example.com")
|
|
212
|
+
if (urlObject.searchParams.has("inline")) {
|
|
213
|
+
return
|
|
214
|
+
}
|
|
207
215
|
handleScriptWithSrc(scriptNode, { type, src })
|
|
208
216
|
return
|
|
209
217
|
}
|
|
@@ -219,27 +227,22 @@ export const injectSupervisorIntoHTML = async (
|
|
|
219
227
|
rootDirectoryUrl: webServer.rootDirectoryUrl,
|
|
220
228
|
scriptInfos,
|
|
221
229
|
},
|
|
222
|
-
"
|
|
230
|
+
" ",
|
|
223
231
|
)
|
|
224
|
-
|
|
232
|
+
injectHtmlNodeAsEarlyAsPossible(
|
|
225
233
|
htmlAst,
|
|
226
234
|
createHtmlNode({
|
|
227
235
|
tagName: "script",
|
|
228
|
-
textContent: `
|
|
229
|
-
window.__supervisor__.setup({
|
|
230
|
-
${setupParamsSource}
|
|
231
|
-
})
|
|
232
|
-
`,
|
|
236
|
+
textContent: `window.__supervisor__.setup({${setupParamsSource}})`,
|
|
233
237
|
}),
|
|
234
238
|
"jsenv:supervisor",
|
|
235
239
|
)
|
|
236
|
-
|
|
237
|
-
tagName: "script",
|
|
238
|
-
src: supervisorScriptSrc,
|
|
239
|
-
})
|
|
240
|
-
injectScriptNodeAsEarlyAsPossible(
|
|
240
|
+
injectHtmlNodeAsEarlyAsPossible(
|
|
241
241
|
htmlAst,
|
|
242
|
-
|
|
242
|
+
createHtmlNode({
|
|
243
|
+
tagName: "script",
|
|
244
|
+
src: supervisorScriptSrc,
|
|
245
|
+
}),
|
|
243
246
|
"jsenv:supervisor",
|
|
244
247
|
)
|
|
245
248
|
}
|
|
@@ -268,14 +271,9 @@ const stringifyParams = (params, prefix = "") => {
|
|
|
268
271
|
}
|
|
269
272
|
|
|
270
273
|
const generateCodeToSuperviseScriptWithSrc = ({ type, src }) => {
|
|
274
|
+
const srcEncoded = JSON.stringify(src)
|
|
271
275
|
if (type === "js_module") {
|
|
272
|
-
return `
|
|
273
|
-
window.__supervisor__.superviseScriptTypeModule(${JSON.stringify(
|
|
274
|
-
src,
|
|
275
|
-
)}, (url) => import(url));
|
|
276
|
-
`
|
|
276
|
+
return `window.__supervisor__.superviseScriptTypeModule(${srcEncoded}, (url) => import(url));`
|
|
277
277
|
}
|
|
278
|
-
return `
|
|
279
|
-
window.__supervisor__.superviseScript(${JSON.stringify(src)});
|
|
280
|
-
`
|
|
278
|
+
return `window.__supervisor__.superviseScript(${srcEncoded});`
|
|
281
279
|
}
|
|
@@ -7,7 +7,7 @@ import { getOriginalPosition } from "@jsenv/sourcemap"
|
|
|
7
7
|
import { stringifyUrlSite } from "@jsenv/urls"
|
|
8
8
|
|
|
9
9
|
import { injectSupervisorIntoHTML } from "./html_supervisor_injection.js"
|
|
10
|
-
import { requireFromJsenv } from "@jsenv/core/src/require_from_jsenv.js"
|
|
10
|
+
import { requireFromJsenv } from "@jsenv/core/src/helpers/require_from_jsenv.js"
|
|
11
11
|
|
|
12
12
|
export const supervisorFileUrl = new URL(
|
|
13
13
|
"./client/supervisor.js",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createRequire } from "node:module"
|
|
2
2
|
import { pathToFileURL } from "node:url"
|
|
3
|
-
import { requireFromJsenv } from "@jsenv/core/src/require_from_jsenv.js"
|
|
3
|
+
import { requireFromJsenv } from "@jsenv/core/src/helpers/require_from_jsenv.js"
|
|
4
4
|
|
|
5
5
|
const babelPluginPackagePath = requireFromJsenv.resolve("@jsenv/babel-plugins")
|
|
6
6
|
const babelPluginPackageUrl = pathToFileURL(babelPluginPackagePath)
|
|
@@ -36,10 +36,25 @@ export const jsenvPluginImportAssertions = ({
|
|
|
36
36
|
}
|
|
37
37
|
const turnIntoJsModuleProxy = (reference, type) => {
|
|
38
38
|
reference.mutation = (magicSource) => {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
const { assertNode } = reference
|
|
40
|
+
if (reference.subtype === "import_dynamic") {
|
|
41
|
+
const assertPropertyNode = assertNode.properties.find(
|
|
42
|
+
(prop) => prop.key.name === "assert",
|
|
43
|
+
)
|
|
44
|
+
const assertPropertyValue = assertPropertyNode.value
|
|
45
|
+
const typePropertyNode = assertPropertyValue.properties.find(
|
|
46
|
+
(prop) => prop.key.name === "type",
|
|
47
|
+
)
|
|
48
|
+
magicSource.remove({
|
|
49
|
+
start: typePropertyNode.start,
|
|
50
|
+
end: typePropertyNode.end,
|
|
51
|
+
})
|
|
52
|
+
} else {
|
|
53
|
+
magicSource.remove({
|
|
54
|
+
start: assertNode.start,
|
|
55
|
+
end: assertNode.end,
|
|
56
|
+
})
|
|
57
|
+
}
|
|
43
58
|
}
|
|
44
59
|
const newUrl = injectQueryParams(reference.url, {
|
|
45
60
|
[`as_${type}_module`]: "",
|
|
@@ -88,7 +103,7 @@ export const jsenvPluginImportAssertions = ({
|
|
|
88
103
|
|
|
89
104
|
const jsenvPluginAsModules = () => {
|
|
90
105
|
const inlineContentClientFileUrl = new URL(
|
|
91
|
-
"../../
|
|
106
|
+
"../../inline_content_analysis/client/inline_content.js",
|
|
92
107
|
import.meta.url,
|
|
93
108
|
).href
|
|
94
109
|
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "@jsenv/sourcemap"
|
|
8
8
|
import { applyBabelPlugins } from "@jsenv/ast"
|
|
9
9
|
|
|
10
|
-
import { requireFromJsenv } from "@jsenv/core/src/require_from_jsenv.js"
|
|
10
|
+
import { requireFromJsenv } from "@jsenv/core/src/helpers/require_from_jsenv.js"
|
|
11
11
|
import { requireBabelPlugin } from "../babel/require_babel_plugin.js"
|
|
12
12
|
import { babelPluginTransformImportMetaUrl } from "./helpers/babel_plugin_transform_import_meta_url.js"
|
|
13
13
|
import { babelPluginTransformImportMetaResolve } from "./helpers/babel_plugin_transform_import_meta_resolve.js"
|
package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_fallback_inside_html.js
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
getHtmlNodeAttribute,
|
|
14
14
|
setHtmlNodeAttributes,
|
|
15
15
|
analyzeScriptNode,
|
|
16
|
-
|
|
16
|
+
injectHtmlNodeAsEarlyAsPossible,
|
|
17
17
|
createHtmlNode,
|
|
18
18
|
} from "@jsenv/ast"
|
|
19
19
|
import { injectQueryParams, urlToRelativeUrl } from "@jsenv/urls"
|
|
@@ -202,7 +202,7 @@ export const jsenvPluginJsModuleFallbackInsideHtml = ({
|
|
|
202
202
|
await context.cook(systemJsUrlInfo, {
|
|
203
203
|
reference: systemJsReference,
|
|
204
204
|
})
|
|
205
|
-
|
|
205
|
+
injectHtmlNodeAsEarlyAsPossible(
|
|
206
206
|
htmlAst,
|
|
207
207
|
createHtmlNode({
|
|
208
208
|
tagName: "script",
|
package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_fallback_on_workers.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* when {type: "module"} cannot be used on web workers:
|
|
3
3
|
* - new Worker("worker.js", { type: "module" })
|
|
4
4
|
* transformed into
|
|
5
|
-
* new Worker("worker.js?
|
|
5
|
+
* new Worker("worker.js?js_module_fallback", { type: " lassic" })
|
|
6
6
|
* - navigator.serviceWorker.register("service_worker.js", { type: "module" })
|
|
7
7
|
* transformed into
|
|
8
|
-
* navigator.serviceWorker.register("service_worker.js?
|
|
8
|
+
* navigator.serviceWorker.register("service_worker.js?js_module_fallback", { type: "classic" })
|
|
9
9
|
* - new SharedWorker("shared_worker.js", { type: "module" })
|
|
10
10
|
* transformed into
|
|
11
|
-
* new SharedWorker("shared_worker.js?
|
|
11
|
+
* new SharedWorker("shared_worker.js?js_module_fallback", { type: "classic" })
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { injectQueryParams } from "@jsenv/urls"
|
|
@@ -208,7 +208,7 @@ const visitHtmlUrls = ({ url, htmlAst }) => {
|
|
|
208
208
|
if (type === "text") {
|
|
209
209
|
// ignore <script type="whatever" src="./file.js">
|
|
210
210
|
// per HTML spec https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-type
|
|
211
|
-
// this will be handled by
|
|
211
|
+
// this will be handled by jsenv_plugin_html_inline_content_analysis
|
|
212
212
|
return
|
|
213
213
|
}
|
|
214
214
|
visitAttributeAsUrlSpecifier({
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import { uneval, executeUsingDynamicImport } from "./js/execute_using_dynamic_import.js";
|
|
2
|
-
import "node:fs";
|
|
3
|
-
import "node:inspector";
|
|
4
|
-
import "node:perf_hooks";
|
|
5
|
-
|
|
6
|
-
const ACTIONS_AVAILABLE = {
|
|
7
|
-
"execute-using-dynamic-import": executeUsingDynamicImport,
|
|
8
|
-
"execute-using-require": async ({
|
|
9
|
-
fileUrl
|
|
10
|
-
}) => {
|
|
11
|
-
const {
|
|
12
|
-
createRequire
|
|
13
|
-
} = await import("node:module");
|
|
14
|
-
const {
|
|
15
|
-
fileURLToPath
|
|
16
|
-
} = await import("node:url");
|
|
17
|
-
const filePath = fileURLToPath(fileUrl);
|
|
18
|
-
const require = createRequire(fileUrl);
|
|
19
|
-
// eslint-disable-next-line import/no-dynamic-require
|
|
20
|
-
const namespace = require(filePath);
|
|
21
|
-
const namespaceResolved = {};
|
|
22
|
-
await Promise.all(Object.keys(namespace).map(async key => {
|
|
23
|
-
const value = await namespace[key];
|
|
24
|
-
namespaceResolved[key] = value;
|
|
25
|
-
}));
|
|
26
|
-
return namespaceResolved;
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
const ACTION_REQUEST_EVENT_NAME = "action";
|
|
30
|
-
const ACTION_RESPONSE_EVENT_NAME = "action-result";
|
|
31
|
-
const ACTION_RESPONSE_STATUS_FAILED = "action-failed";
|
|
32
|
-
const ACTION_RESPONSE_STATUS_COMPLETED = "action-completed";
|
|
33
|
-
const sendActionFailed = error => {
|
|
34
|
-
if (error.hasOwnProperty("toString")) {
|
|
35
|
-
delete error.toString;
|
|
36
|
-
}
|
|
37
|
-
sendToParent(ACTION_RESPONSE_EVENT_NAME,
|
|
38
|
-
// process.send algorithm does not send non enumerable values
|
|
39
|
-
// so use @jsenv/uneval
|
|
40
|
-
uneval({
|
|
41
|
-
status: ACTION_RESPONSE_STATUS_FAILED,
|
|
42
|
-
value: error
|
|
43
|
-
}, {
|
|
44
|
-
ignoreSymbols: true
|
|
45
|
-
}));
|
|
46
|
-
};
|
|
47
|
-
const sendActionCompleted = value => {
|
|
48
|
-
sendToParent(ACTION_RESPONSE_EVENT_NAME,
|
|
49
|
-
// here we use JSON.stringify because we should not
|
|
50
|
-
// have non enumerable value (unlike there is on Error objects)
|
|
51
|
-
// otherwise uneval is quite slow to turn a giant object
|
|
52
|
-
// into a string (and value can be giant when using coverage)
|
|
53
|
-
JSON.stringify({
|
|
54
|
-
status: ACTION_RESPONSE_STATUS_COMPLETED,
|
|
55
|
-
value
|
|
56
|
-
}));
|
|
57
|
-
};
|
|
58
|
-
const sendToParent = (type, data) => {
|
|
59
|
-
// https://nodejs.org/api/process.html#process_process_connected
|
|
60
|
-
// not connected anymore, cannot communicate with parent
|
|
61
|
-
if (!process.connected) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
// this can keep process alive longer than expected
|
|
65
|
-
// when source is a long string.
|
|
66
|
-
// It means node process may stay alive longer than expected
|
|
67
|
-
// the time to send the data to the parent.
|
|
68
|
-
process.send({
|
|
69
|
-
jsenv: true,
|
|
70
|
-
type,
|
|
71
|
-
data
|
|
72
|
-
});
|
|
73
|
-
};
|
|
74
|
-
const onceParentMessage = (type, callback) => {
|
|
75
|
-
const listener = message => {
|
|
76
|
-
if (message && message.jsenv && message.type === type) {
|
|
77
|
-
removeListener(); // commenting this line keep this process alive
|
|
78
|
-
callback(message.data);
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
const removeListener = () => {
|
|
82
|
-
process.removeListener("message", listener);
|
|
83
|
-
};
|
|
84
|
-
process.on("message", listener);
|
|
85
|
-
return removeListener;
|
|
86
|
-
};
|
|
87
|
-
const removeActionRequestListener = onceParentMessage(ACTION_REQUEST_EVENT_NAME, async ({
|
|
88
|
-
actionType,
|
|
89
|
-
actionParams
|
|
90
|
-
}) => {
|
|
91
|
-
const action = ACTIONS_AVAILABLE[actionType];
|
|
92
|
-
if (!action) {
|
|
93
|
-
sendActionFailed(new Error(`unknown action ${actionType}`));
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
let value;
|
|
97
|
-
let failed = false;
|
|
98
|
-
try {
|
|
99
|
-
value = await action(actionParams);
|
|
100
|
-
} catch (e) {
|
|
101
|
-
failed = true;
|
|
102
|
-
value = e;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// setTimeout(() => {}, 100)
|
|
106
|
-
|
|
107
|
-
if (failed) {
|
|
108
|
-
sendActionFailed(value);
|
|
109
|
-
} else {
|
|
110
|
-
sendActionCompleted(value);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// removeActionRequestListener()
|
|
114
|
-
if (actionParams.exitAfterAction) {
|
|
115
|
-
removeActionRequestListener();
|
|
116
|
-
// for some reason this fixes v8 coverage directory sometimes empty on Ubuntu
|
|
117
|
-
// process.exit()
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
// remove listener to process.on('message')
|
|
122
|
-
// which is sufficient to let child process die
|
|
123
|
-
// assuming nothing else keeps it alive
|
|
124
|
-
// process.once("SIGTERM", removeActionRequestListener)
|
|
125
|
-
// process.once("SIGINT", removeActionRequestListener)
|
|
126
|
-
|
|
127
|
-
setTimeout(() => {
|
|
128
|
-
sendToParent("ready");
|
|
129
|
-
});
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { parentPort } from "node:worker_threads";
|
|
2
|
-
import { uneval, executeUsingDynamicImport } from "./js/execute_using_dynamic_import.js";
|
|
3
|
-
import "node:fs";
|
|
4
|
-
import "node:inspector";
|
|
5
|
-
import "node:perf_hooks";
|
|
6
|
-
|
|
7
|
-
const ACTIONS_AVAILABLE = {
|
|
8
|
-
"execute-using-dynamic-import": executeUsingDynamicImport
|
|
9
|
-
};
|
|
10
|
-
const ACTION_REQUEST_EVENT_NAME = "action";
|
|
11
|
-
const ACTION_RESPONSE_EVENT_NAME = "action-result";
|
|
12
|
-
const ACTION_RESPONSE_STATUS_FAILED = "action-failed";
|
|
13
|
-
const ACTION_RESPONSE_STATUS_COMPLETED = "action-completed";
|
|
14
|
-
const sendActionFailed = error => {
|
|
15
|
-
if (error.hasOwnProperty("toString")) {
|
|
16
|
-
delete error.toString;
|
|
17
|
-
}
|
|
18
|
-
sendToParent(ACTION_RESPONSE_EVENT_NAME,
|
|
19
|
-
// process.send algorithm does not send non enumerable values
|
|
20
|
-
// so use @jsenv/uneval
|
|
21
|
-
uneval({
|
|
22
|
-
status: ACTION_RESPONSE_STATUS_FAILED,
|
|
23
|
-
value: error
|
|
24
|
-
}, {
|
|
25
|
-
ignoreSymbols: true
|
|
26
|
-
}));
|
|
27
|
-
};
|
|
28
|
-
const sendActionCompleted = value => {
|
|
29
|
-
sendToParent(ACTION_RESPONSE_EVENT_NAME,
|
|
30
|
-
// here we use JSON.stringify because we should not
|
|
31
|
-
// have non enumerable value (unlike there is on Error objects)
|
|
32
|
-
// otherwise uneval is quite slow to turn a giant object
|
|
33
|
-
// into a string (and value can be giant when using coverage)
|
|
34
|
-
JSON.stringify({
|
|
35
|
-
status: ACTION_RESPONSE_STATUS_COMPLETED,
|
|
36
|
-
value
|
|
37
|
-
}));
|
|
38
|
-
};
|
|
39
|
-
const sendToParent = (type, data) => {
|
|
40
|
-
// this can keep process alive longer than expected
|
|
41
|
-
// when source is a long string.
|
|
42
|
-
// It means node process may stay alive longer than expected
|
|
43
|
-
// the time to send the data to the parent.
|
|
44
|
-
parentPort.postMessage({
|
|
45
|
-
jsenv: true,
|
|
46
|
-
type,
|
|
47
|
-
data
|
|
48
|
-
});
|
|
49
|
-
};
|
|
50
|
-
const onceParentMessage = (type, callback) => {
|
|
51
|
-
const listener = message => {
|
|
52
|
-
if (message && message.jsenv && message.type === type) {
|
|
53
|
-
removeListener(); // commenting this line keep this worker alive
|
|
54
|
-
callback(message.data);
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
const removeListener = () => {
|
|
58
|
-
parentPort.removeListener("message", listener);
|
|
59
|
-
};
|
|
60
|
-
parentPort.on("message", listener);
|
|
61
|
-
return removeListener;
|
|
62
|
-
};
|
|
63
|
-
const removeActionRequestListener = onceParentMessage(ACTION_REQUEST_EVENT_NAME, async ({
|
|
64
|
-
actionType,
|
|
65
|
-
actionParams
|
|
66
|
-
}) => {
|
|
67
|
-
const action = ACTIONS_AVAILABLE[actionType];
|
|
68
|
-
if (!action) {
|
|
69
|
-
sendActionFailed(new Error(`unknown action ${actionType}`));
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
let value;
|
|
73
|
-
let failed = false;
|
|
74
|
-
try {
|
|
75
|
-
value = await action(actionParams);
|
|
76
|
-
} catch (e) {
|
|
77
|
-
failed = true;
|
|
78
|
-
value = e;
|
|
79
|
-
}
|
|
80
|
-
if (failed) {
|
|
81
|
-
sendActionFailed(value);
|
|
82
|
-
} else {
|
|
83
|
-
sendActionCompleted(value);
|
|
84
|
-
}
|
|
85
|
-
if (actionParams.exitAfterAction) {
|
|
86
|
-
removeActionRequestListener();
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
setTimeout(() => {
|
|
90
|
-
sendToParent("ready");
|
|
91
|
-
});
|