@jsenv/core 27.0.0-alpha.6 → 27.0.0-alpha.60
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/event_source_client.js +545 -0
- package/dist/event_source_client.js.map +187 -0
- package/dist/html_supervisor_installer.js +1236 -0
- package/dist/html_supervisor_installer.js.map +337 -0
- package/dist/html_supervisor_setup.js +95 -0
- package/dist/html_supervisor_setup.js.map +57 -0
- package/dist/import_meta_hot.js +86 -0
- package/dist/import_meta_hot.js.map +42 -0
- package/main.js +8 -1
- package/package.json +30 -28
- package/readme.md +6 -14
- package/src/build/build.js +943 -555
- package/src/build/build_urls_generator.js +48 -23
- package/src/build/graph_utils.js +31 -0
- package/src/build/{inject_version_mappings.js → inject_global_version_mappings.js} +33 -15
- package/src/build/inject_service_worker_urls.js +79 -0
- package/src/build/resync_ressource_hints.js +68 -0
- package/src/build/start_build_server.js +192 -0
- package/src/dev/plugins/explorer/jsenv_plugin_explorer.js +2 -2
- package/src/dev/plugins/toolbar/jsenv_plugin_toolbar.js +3 -1
- package/src/dev/start_dev_server.js +136 -30
- package/src/execute/execute.js +31 -6
- package/src/execute/run.js +19 -56
- package/src/execute/runtimes/browsers/from_playwright.js +207 -147
- package/src/execute/runtimes/node/controllable_file.mjs +26 -10
- package/src/execute/runtimes/node/node_execution_performance.js +67 -0
- package/src/execute/runtimes/node/node_process.js +280 -39
- package/src/jsenv_root_directory_url.js +1 -0
- package/src/omega/{runtime_support/default_runtime_support.js → compat/default_runtime_compat.js} +3 -5
- package/src/omega/{runtime_support/features_compatibility.js → compat/features_compats.js} +66 -4
- package/src/omega/compat/runtime_compat.js +50 -0
- package/src/omega/errors.js +51 -58
- package/src/omega/fetched_content_compliance.js +24 -0
- package/src/omega/file_url_converter.js +8 -50
- package/src/omega/kitchen.js +482 -304
- package/src/omega/omega_server.js +2 -3
- package/src/omega/server/file_service.js +53 -25
- package/src/omega/server/user_agent.js +4 -2
- package/src/omega/url_graph/url_graph_load.js +22 -7
- package/src/omega/url_graph/url_graph_report.js +98 -48
- package/src/omega/url_graph/url_info_transformations.js +26 -9
- package/src/omega/url_graph.js +80 -16
- package/src/omega/web_workers.js +42 -0
- package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/autoreload_preference.js +0 -0
- package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/event_source_client.js +2 -2
- package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/reload.js +0 -0
- package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/url_helpers.js +0 -0
- package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_client.js +46 -0
- package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js +204 -0
- package/src/plugins/autoreload/jsenv_plugin_autoreload.js +27 -0
- package/src/plugins/autoreload/jsenv_plugin_hmr.js +35 -0
- package/src/plugins/bundling/css/bundle_css.js +140 -0
- package/src/plugins/bundling/js_classic_workers/bundle_js_classic_workers.js +13 -0
- package/src/plugins/bundling/js_module/bundle_js_module.js +309 -0
- package/src/plugins/bundling/jsenv_plugin_bundling.js +54 -0
- package/src/plugins/cache_control/jsenv_plugin_cache_control.js +34 -0
- package/src/{omega/core_plugins → plugins}/commonjs_globals/jsenv_plugin_commonjs_globals.js +54 -41
- package/src/plugins/file_urls/jsenv_plugin_file_urls.js +66 -0
- package/src/{omega/core_plugins → plugins}/filesystem_magic/jsenv_plugin_filesystem_magic.js +8 -5
- package/src/{omega/core_plugins → plugins}/html_supervisor/client/error_in_document.js +0 -0
- package/src/{omega/core_plugins → plugins}/html_supervisor/client/error_in_notification.js +0 -0
- package/src/plugins/html_supervisor/client/html_supervisor_installer.js +242 -0
- package/src/plugins/html_supervisor/client/html_supervisor_setup.js +79 -0
- package/src/{omega/core_plugins → plugins}/html_supervisor/client/perf_browser.js +0 -0
- package/src/{omega/core_plugins → plugins}/html_supervisor/client/uneval_exception.js +0 -0
- package/src/{omega/core_plugins → plugins}/html_supervisor/jsenv_plugin_html_supervisor.js +83 -61
- package/src/plugins/http_urls/jsenv_plugin_http_urls.js +12 -0
- package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/babel_plugin_metadata_import_meta_hot.js +4 -5
- package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/client/import_meta_hot.js +3 -1
- package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/html_hot_dependencies.js +2 -2
- package/src/plugins/import_meta_hot/jsenv_plugin_import_meta_hot.js +105 -0
- package/src/{omega/core_plugins → plugins}/import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js +33 -8
- package/src/plugins/import_meta_url/client/import_meta_url_browser.js +52 -0
- package/src/plugins/import_meta_url/client/import_meta_url_commonjs.mjs +9 -0
- package/src/{omega/core_plugins → plugins}/importmap/jsenv_plugin_importmap.js +39 -33
- package/src/plugins/inject_globals/jsenv_plugin_inject_globals.js +67 -0
- package/src/{omega/core_plugins → plugins}/inline/client/inline_content.js +0 -0
- package/src/{omega/core_plugins → plugins}/inline/jsenv_plugin_data_urls.js +18 -14
- package/src/{omega/core_plugins/inline/jsenv_plugin_js_and_css_inside_html.js → plugins/inline/jsenv_plugin_html_inline_content.js} +65 -44
- package/src/plugins/inline/jsenv_plugin_inline.js +36 -0
- package/src/{omega/core_plugins → plugins}/inline/jsenv_plugin_inline_query_param.js +6 -6
- package/src/plugins/inline/jsenv_plugin_js_inline_content.js +297 -0
- package/src/plugins/leading_slash/jsenv_plugin_leading_slash.js +13 -0
- package/src/plugins/minification/css/minify_css.js +9 -0
- package/src/plugins/minification/html/minify_html.js +15 -0
- package/src/{build/plugins/minify_js/jsenv_plugin_minify_js.js → plugins/minification/js/minify_js.js} +6 -22
- package/src/plugins/minification/jsenv_plugin_minification.js +78 -0
- package/src/plugins/minification/json/minify_json.js +8 -0
- package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +146 -0
- package/src/{omega → plugins}/plugin_controller.js +42 -11
- package/src/plugins/plugins.js +92 -0
- package/src/plugins/transpilation/as_js_classic/client/s.js +874 -0
- package/src/plugins/transpilation/as_js_classic/client/s.js.md +1 -0
- package/src/plugins/transpilation/as_js_classic/helpers/babel_plugin_transform_import_meta_url.js +47 -0
- package/src/plugins/transpilation/as_js_classic/helpers/systemjs_old.js +43 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +199 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_script_type_module_as_classic.js +270 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_workers_type_module_as_classic.js +55 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/global_this/babel_plugin_global_this_as_jsenv_import.js +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/global_this/client/global_this.js +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugin_babel_helpers_as_jsenv_imports.js +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugin_structure.js +12 -19
- package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugins_compatibility.js +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/jsenv_plugin_babel.js +45 -27
- package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js +30 -6
- package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/client/.eslintrc.cjs +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/client/new_stylesheet.js +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/regenerator_runtime/babel_plugin_regenerator_runtime_as_jsenv_import.js +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/regenerator_runtime/client/regenerator_runtime.js +0 -0
- package/src/plugins/transpilation/css_parcel/jsenv_plugin_css_parcel.js +18 -0
- package/src/plugins/transpilation/fetch_original_url_info.js +30 -0
- package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +181 -0
- package/src/plugins/transpilation/jsenv_plugin_top_level_await.js +80 -0
- package/src/plugins/transpilation/jsenv_plugin_transpilation.js +44 -0
- package/src/plugins/url_analysis/css/css_urls.js +49 -0
- package/src/plugins/url_analysis/html/html_urls.js +269 -0
- package/src/plugins/url_analysis/js/js_urls.js +67 -0
- package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +18 -0
- package/src/plugins/url_analysis/webmanifest/webmanifest_urls.js +17 -0
- package/src/{omega/core_plugins → plugins}/url_resolution/jsenv_plugin_url_resolution.js +12 -5
- package/src/plugins/url_version/jsenv_plugin_url_version.js +28 -0
- package/src/test/execute_plan.js +30 -18
- package/src/test/execute_test_plan.js +23 -8
- package/src/test/logs_file_execution.js +9 -8
- package/src/build/plugins/bundle_js_module/jsenv_plugin_bundle_js_module.js +0 -225
- package/src/build/plugins/minify_html/jsenv_plugin_minify_html.js +0 -30
- package/src/dev/plugins/autoreload/client/event_source_connection.js +0 -195
- package/src/dev/plugins/autoreload/jsenv_plugin_autoreload.js +0 -374
- package/src/dev/plugins/autoreload/sse_service.js +0 -149
- package/src/execute/runtimes/node/controlled_process.js +0 -316
- package/src/omega/core_plugins/file_urls/jsenv_plugin_file_urls.js +0 -67
- package/src/omega/core_plugins/html_supervisor/client/html_supervisor_installer.js +0 -168
- package/src/omega/core_plugins/html_supervisor/client/html_supervisor_setup.js +0 -77
- package/src/omega/core_plugins/import_assertions/helpers/babel_plugin_metadata_import_assertions.js +0 -98
- package/src/omega/core_plugins/import_assertions/helpers/json_module.js +0 -12
- package/src/omega/core_plugins/import_assertions/helpers/text_module.js +0 -6
- package/src/omega/core_plugins/import_assertions/jsenv_plugin_import_assertions.js +0 -211
- package/src/omega/core_plugins/inline/jsenv_plugin_inline.js +0 -13
- package/src/omega/core_plugins/inline/jsenv_plugin_new_inline_content.js +0 -210
- package/src/omega/core_plugins/leading_slash/jsenv_plugin_leading_slash.js +0 -12
- package/src/omega/core_plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +0 -77
- package/src/omega/core_plugins/url_version/jsenv_plugin_url_version.js +0 -50
- package/src/omega/core_plugins.js +0 -39
- package/src/omega/runtime_support/runtime_support.js +0 -20
- package/src/omega/url_graph/url_graph_sort.js +0 -29
- package/src/omega/url_mentions/css_url_mentions.js +0 -63
- package/src/omega/url_mentions/html_url_mentions.js +0 -185
- package/src/omega/url_mentions/js_module_url_mentions.js +0 -91
- package/src/omega/url_mentions/parse_url_mentions.js +0 -37
- package/src/omega/url_mentions/worker_classic_url_mentions.js +0 -37
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// the following apis are creating js entry points:
|
|
2
|
+
// - new Worker()
|
|
3
|
+
// - new SharedWorker()
|
|
4
|
+
// - navigator.serviceWorker.register()
|
|
5
|
+
export const isWebWorkerEntryPointReference = (reference) => {
|
|
6
|
+
if (reference.subtype === "new_url_first_arg") {
|
|
7
|
+
return ["worker", "service_worker", "shared_worker"].includes(
|
|
8
|
+
reference.expectedSubtype,
|
|
9
|
+
)
|
|
10
|
+
}
|
|
11
|
+
return [
|
|
12
|
+
"new_worker_first_arg",
|
|
13
|
+
"new_shared_worker_first_arg",
|
|
14
|
+
"service_worker_register_first_arg",
|
|
15
|
+
].includes(reference.subtype)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const isWebWorkerUrlInfo = (urlInfo) => {
|
|
19
|
+
return (
|
|
20
|
+
urlInfo.subtype === "worker" ||
|
|
21
|
+
urlInfo.subtype === "service_worker" ||
|
|
22
|
+
urlInfo.subtype === "shared_worker"
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// export const isEntryPoint = (urlInfo, urlGraph) => {
|
|
27
|
+
// if (urlInfo.data.isEntryPoint) {
|
|
28
|
+
// return true
|
|
29
|
+
// }
|
|
30
|
+
// if (isWebWorker(urlInfo)) {
|
|
31
|
+
// // - new Worker("a.js") -> "a.js" is an entry point
|
|
32
|
+
// // - self.importScripts("b.js") -> "b.js" is not an entry point
|
|
33
|
+
// // So the following logic applies to infer if the file is a web worker entry point
|
|
34
|
+
// // "When a non-webworker file references a worker file, the worker file is an entry point"
|
|
35
|
+
// const dependents = Array.from(urlInfo.dependents)
|
|
36
|
+
// return dependents.some((dependentUrl) => {
|
|
37
|
+
// const dependentUrlInfo = urlGraph.getUrlInfo(dependentUrl)
|
|
38
|
+
// return !isWebWorker(dependentUrlInfo)
|
|
39
|
+
// })
|
|
40
|
+
// }
|
|
41
|
+
// return false
|
|
42
|
+
// }
|
package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/autoreload_preference.js
RENAMED
|
File without changes
|
package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/event_source_client.js
RENAMED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { createEventSourceConnection } from "
|
|
1
|
+
import { createEventSourceConnection } from "@jsenv/utils/event_source/event_source.js"
|
|
2
|
+
import { urlHotMetas } from "../../../import_meta_hot/client/import_meta_hot.js"
|
|
2
3
|
import {
|
|
3
4
|
isAutoreloadEnabled,
|
|
4
5
|
setAutoreloadPreference,
|
|
@@ -9,7 +10,6 @@ import {
|
|
|
9
10
|
reloadDOMNodesUsingUrl,
|
|
10
11
|
reloadJsImport,
|
|
11
12
|
} from "./reload.js"
|
|
12
|
-
import { urlHotMetas } from "./import_meta_hot.js"
|
|
13
13
|
|
|
14
14
|
const reloadMessages = []
|
|
15
15
|
const reloadMessagesSignal = { onchange: () => {} }
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { urlIsInsideOf } from "@jsenv/filesystem"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
parseHtmlString,
|
|
5
|
+
stringifyHtmlAst,
|
|
6
|
+
injectScriptAsEarlyAsPossible,
|
|
7
|
+
createHtmlNode,
|
|
8
|
+
} from "@jsenv/utils/html_ast/html_ast.js"
|
|
9
|
+
import { jsenvRootDirectoryUrl } from "@jsenv/core/src/jsenv_root_directory_url.js"
|
|
10
|
+
|
|
11
|
+
export const jsenvPluginDevSSEClient = ({ rootDirectoryUrl }) => {
|
|
12
|
+
const preferSourceFiles =
|
|
13
|
+
rootDirectoryUrl === jsenvRootDirectoryUrl ||
|
|
14
|
+
urlIsInsideOf(rootDirectoryUrl, jsenvRootDirectoryUrl)
|
|
15
|
+
const eventSourceClientFileUrl = preferSourceFiles
|
|
16
|
+
? new URL("./client/event_source_client.js", import.meta.url).href
|
|
17
|
+
: new URL("./dist/event_source_client.js", jsenvRootDirectoryUrl).href
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
name: "jsenv:dev_sse_client",
|
|
21
|
+
appliesDuring: { dev: true },
|
|
22
|
+
transformUrlContent: {
|
|
23
|
+
html: (htmlUrlInfo, context) => {
|
|
24
|
+
const htmlAst = parseHtmlString(htmlUrlInfo.content)
|
|
25
|
+
const [eventSourceClientReference] = context.referenceUtils.inject({
|
|
26
|
+
type: "script_src",
|
|
27
|
+
expectedType: "js_module",
|
|
28
|
+
specifier: eventSourceClientFileUrl,
|
|
29
|
+
})
|
|
30
|
+
injectScriptAsEarlyAsPossible(
|
|
31
|
+
htmlAst,
|
|
32
|
+
createHtmlNode({
|
|
33
|
+
"tagName": "script",
|
|
34
|
+
"type": "module",
|
|
35
|
+
"src": eventSourceClientReference.generatedSpecifier,
|
|
36
|
+
"injected-by": "jsenv:dev_sse_client",
|
|
37
|
+
}),
|
|
38
|
+
)
|
|
39
|
+
const htmlModified = stringifyHtmlAst(htmlAst)
|
|
40
|
+
return {
|
|
41
|
+
content: htmlModified,
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { urlToRelativeUrl } from "@jsenv/filesystem"
|
|
2
|
+
import { createCallbackList } from "@jsenv/abort"
|
|
3
|
+
|
|
4
|
+
import { createSSEService } from "@jsenv/utils/event_source/sse_service.js"
|
|
5
|
+
|
|
6
|
+
export const jsenvPluginDevSSEServer = ({
|
|
7
|
+
rootDirectoryUrl,
|
|
8
|
+
urlGraph,
|
|
9
|
+
clientFileChangeCallbackList,
|
|
10
|
+
clientFilesPruneCallbackList,
|
|
11
|
+
}) => {
|
|
12
|
+
const serverEventCallbackList = createCallbackList()
|
|
13
|
+
const sseService = createSSEService({ serverEventCallbackList })
|
|
14
|
+
|
|
15
|
+
const notifyDeclined = ({ cause, reason, declinedBy }) => {
|
|
16
|
+
serverEventCallbackList.notify({
|
|
17
|
+
type: "reload",
|
|
18
|
+
data: JSON.stringify({
|
|
19
|
+
cause,
|
|
20
|
+
type: "full",
|
|
21
|
+
typeReason: reason,
|
|
22
|
+
declinedBy,
|
|
23
|
+
}),
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
const notifyAccepted = ({ cause, reason, instructions }) => {
|
|
27
|
+
serverEventCallbackList.notify({
|
|
28
|
+
type: "reload",
|
|
29
|
+
data: JSON.stringify({
|
|
30
|
+
cause,
|
|
31
|
+
type: "hot",
|
|
32
|
+
typeReason: reason,
|
|
33
|
+
hotInstructions: instructions,
|
|
34
|
+
}),
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
const propagateUpdate = (firstUrlInfo) => {
|
|
38
|
+
const urlInfos = urlGraph.urlInfos
|
|
39
|
+
const iterate = (urlInfo, trace) => {
|
|
40
|
+
if (urlInfo.data.hotAcceptSelf) {
|
|
41
|
+
return {
|
|
42
|
+
accepted: true,
|
|
43
|
+
reason:
|
|
44
|
+
urlInfo === firstUrlInfo
|
|
45
|
+
? `file accepts hot reload`
|
|
46
|
+
: `a dependent file accepts hot reload`,
|
|
47
|
+
instructions: [
|
|
48
|
+
{
|
|
49
|
+
type: urlInfo.type,
|
|
50
|
+
boundary: urlToRelativeUrl(urlInfo.url, rootDirectoryUrl),
|
|
51
|
+
acceptedBy: urlToRelativeUrl(urlInfo.url, rootDirectoryUrl),
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const { dependents } = urlInfo
|
|
57
|
+
const instructions = []
|
|
58
|
+
for (const dependentUrl of dependents) {
|
|
59
|
+
const dependentUrlInfo = urlInfos[dependentUrl]
|
|
60
|
+
if (dependentUrlInfo.data.hotDecline) {
|
|
61
|
+
return {
|
|
62
|
+
declined: true,
|
|
63
|
+
reason: `a dependent file declines hot reload`,
|
|
64
|
+
declinedBy: dependentUrl,
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const { hotAcceptDependencies = [] } = dependentUrlInfo.data
|
|
68
|
+
if (hotAcceptDependencies.includes(urlInfo.url)) {
|
|
69
|
+
instructions.push({
|
|
70
|
+
type: dependentUrlInfo.type,
|
|
71
|
+
boundary: urlToRelativeUrl(dependentUrl, rootDirectoryUrl),
|
|
72
|
+
acceptedBy: urlToRelativeUrl(urlInfo.url, rootDirectoryUrl),
|
|
73
|
+
})
|
|
74
|
+
continue
|
|
75
|
+
}
|
|
76
|
+
if (trace.includes(dependentUrl)) {
|
|
77
|
+
return {
|
|
78
|
+
declined: true,
|
|
79
|
+
reason: "circular dependency",
|
|
80
|
+
declinedBy: urlToRelativeUrl(dependentUrl, rootDirectoryUrl),
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const dependentPropagationResult = iterate(dependentUrlInfo, [
|
|
84
|
+
...trace,
|
|
85
|
+
dependentUrl,
|
|
86
|
+
])
|
|
87
|
+
if (dependentPropagationResult.accepted) {
|
|
88
|
+
instructions.push(...dependentPropagationResult.instructions)
|
|
89
|
+
continue
|
|
90
|
+
}
|
|
91
|
+
if (
|
|
92
|
+
// declined explicitely by an other file, it must decline the whole update
|
|
93
|
+
dependentPropagationResult.declinedBy
|
|
94
|
+
) {
|
|
95
|
+
return dependentPropagationResult
|
|
96
|
+
}
|
|
97
|
+
// declined by absence of boundary, we can keep searching
|
|
98
|
+
continue
|
|
99
|
+
}
|
|
100
|
+
if (instructions.length === 0) {
|
|
101
|
+
return {
|
|
102
|
+
declined: true,
|
|
103
|
+
reason: `there is no file accepting hot reload while propagating update`,
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
accepted: true,
|
|
108
|
+
reason: `${instructions.length} dependent file(s) accepts hot reload`,
|
|
109
|
+
instructions,
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const trace = []
|
|
113
|
+
return iterate(firstUrlInfo, trace)
|
|
114
|
+
}
|
|
115
|
+
clientFileChangeCallbackList.push(({ url, event }) => {
|
|
116
|
+
const urlInfo = urlGraph.urlInfos[url]
|
|
117
|
+
// file not part of dependency graph
|
|
118
|
+
if (!urlInfo) {
|
|
119
|
+
return
|
|
120
|
+
}
|
|
121
|
+
const relativeUrl = urlToRelativeUrl(url, rootDirectoryUrl)
|
|
122
|
+
const hotUpdate = propagateUpdate(urlInfo)
|
|
123
|
+
if (hotUpdate.declined) {
|
|
124
|
+
notifyDeclined({
|
|
125
|
+
cause: `${relativeUrl} ${event}`,
|
|
126
|
+
reason: hotUpdate.reason,
|
|
127
|
+
declinedBy: hotUpdate.declinedBy,
|
|
128
|
+
})
|
|
129
|
+
} else {
|
|
130
|
+
notifyAccepted({
|
|
131
|
+
cause: `${relativeUrl} ${event}`,
|
|
132
|
+
reason: hotUpdate.reason,
|
|
133
|
+
instructions: hotUpdate.instructions,
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
clientFilesPruneCallbackList.push(({ prunedUrlInfos, firstUrlInfo }) => {
|
|
138
|
+
const mainHotUpdate = propagateUpdate(firstUrlInfo)
|
|
139
|
+
const cause = `following files are no longer referenced: ${prunedUrlInfos.map(
|
|
140
|
+
(prunedUrlInfo) => urlToRelativeUrl(prunedUrlInfo.url, rootDirectoryUrl),
|
|
141
|
+
)}`
|
|
142
|
+
// now check if we can hot update the main ressource
|
|
143
|
+
// then if we can hot update all dependencies
|
|
144
|
+
if (mainHotUpdate.declined) {
|
|
145
|
+
notifyDeclined({
|
|
146
|
+
cause,
|
|
147
|
+
reason: mainHotUpdate.reason,
|
|
148
|
+
declinedBy: mainHotUpdate.declinedBy,
|
|
149
|
+
})
|
|
150
|
+
return
|
|
151
|
+
}
|
|
152
|
+
// main can hot update
|
|
153
|
+
let i = 0
|
|
154
|
+
const instructions = []
|
|
155
|
+
while (i < prunedUrlInfos.length) {
|
|
156
|
+
const prunedUrlInfo = prunedUrlInfos[i++]
|
|
157
|
+
if (prunedUrlInfo.data.hotDecline) {
|
|
158
|
+
notifyDeclined({
|
|
159
|
+
cause,
|
|
160
|
+
reason: `a pruned file declines hot reload`,
|
|
161
|
+
declinedBy: urlToRelativeUrl(prunedUrlInfo.url, rootDirectoryUrl),
|
|
162
|
+
})
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
instructions.push({
|
|
166
|
+
type: "prune",
|
|
167
|
+
boundary: urlToRelativeUrl(prunedUrlInfo.url, rootDirectoryUrl),
|
|
168
|
+
acceptedBy: urlToRelativeUrl(firstUrlInfo.url, rootDirectoryUrl),
|
|
169
|
+
})
|
|
170
|
+
}
|
|
171
|
+
notifyAccepted({
|
|
172
|
+
cause,
|
|
173
|
+
reason: mainHotUpdate.reason,
|
|
174
|
+
instructions,
|
|
175
|
+
})
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
name: "jsenv:sse_server",
|
|
180
|
+
appliesDuring: { dev: true },
|
|
181
|
+
serve: (request) => {
|
|
182
|
+
if (request.ressource === "/__graph__") {
|
|
183
|
+
const graphJson = JSON.stringify(urlGraph.toJSON(rootDirectoryUrl))
|
|
184
|
+
return {
|
|
185
|
+
status: 200,
|
|
186
|
+
headers: {
|
|
187
|
+
"content-type": "application/json",
|
|
188
|
+
"content-length": Buffer.byteLength(graphJson),
|
|
189
|
+
},
|
|
190
|
+
body: graphJson,
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const { accept } = request.headers
|
|
194
|
+
if (accept && accept.includes("text/event-stream")) {
|
|
195
|
+
const room = sseService.getOrCreateSSERoom(request)
|
|
196
|
+
return room.join(request)
|
|
197
|
+
}
|
|
198
|
+
return null
|
|
199
|
+
},
|
|
200
|
+
destroy: () => {
|
|
201
|
+
sseService.destroy()
|
|
202
|
+
},
|
|
203
|
+
}
|
|
204
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsenvPluginHmr } from "./jsenv_plugin_hmr.js"
|
|
2
|
+
import { jsenvPluginDevSSEClient } from "./dev_sse/jsenv_plugin_dev_sse_client.js"
|
|
3
|
+
import { jsenvPluginDevSSEServer } from "./dev_sse/jsenv_plugin_dev_sse_server.js"
|
|
4
|
+
|
|
5
|
+
export const jsenvPluginAutoreload = ({
|
|
6
|
+
rootDirectoryUrl,
|
|
7
|
+
urlGraph,
|
|
8
|
+
scenario,
|
|
9
|
+
clientFileChangeCallbackList,
|
|
10
|
+
clientFilesPruneCallbackList,
|
|
11
|
+
}) => {
|
|
12
|
+
if (scenario === "build") {
|
|
13
|
+
return []
|
|
14
|
+
}
|
|
15
|
+
return [
|
|
16
|
+
jsenvPluginHmr(),
|
|
17
|
+
jsenvPluginDevSSEClient({
|
|
18
|
+
rootDirectoryUrl,
|
|
19
|
+
}),
|
|
20
|
+
jsenvPluginDevSSEServer({
|
|
21
|
+
rootDirectoryUrl,
|
|
22
|
+
urlGraph,
|
|
23
|
+
clientFileChangeCallbackList,
|
|
24
|
+
clientFilesPruneCallbackList,
|
|
25
|
+
}),
|
|
26
|
+
]
|
|
27
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export const jsenvPluginHmr = () => {
|
|
2
|
+
return {
|
|
3
|
+
name: "jsenv:hmr",
|
|
4
|
+
appliesDuring: { dev: true },
|
|
5
|
+
redirectUrl: (reference) => {
|
|
6
|
+
const urlObject = new URL(reference.url)
|
|
7
|
+
if (!urlObject.searchParams.has("hmr")) {
|
|
8
|
+
reference.data.hmr = false
|
|
9
|
+
return null
|
|
10
|
+
}
|
|
11
|
+
reference.data.hmr = true
|
|
12
|
+
// "hmr" search param goal is to mark url as enabling hmr:
|
|
13
|
+
// this goal is achieved when we reach this part of the code
|
|
14
|
+
// We get rid of this params so that urlGraph and other parts of the code
|
|
15
|
+
// recognize the url (it is not considered as a different url)
|
|
16
|
+
urlObject.searchParams.delete("hmr")
|
|
17
|
+
urlObject.searchParams.delete("v")
|
|
18
|
+
return urlObject.href
|
|
19
|
+
},
|
|
20
|
+
transformUrlSearchParams: (reference, context) => {
|
|
21
|
+
const parentUrlInfo = context.urlGraph.getUrlInfo(reference.parentUrl)
|
|
22
|
+
if (!parentUrlInfo || !parentUrlInfo.data.hmr) {
|
|
23
|
+
return null
|
|
24
|
+
}
|
|
25
|
+
const urlInfo = context.urlGraph.getUrlInfo(reference.url)
|
|
26
|
+
if (!urlInfo.modifiedTimestamp) {
|
|
27
|
+
return null
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
hmr: "",
|
|
31
|
+
v: urlInfo.modifiedTimestamp,
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Each @import found in css is replaced by the file content
|
|
3
|
+
* - There is no need to worry about urls (such as background-image: url())
|
|
4
|
+
* because they are absolute (file://*) and will be made relative again by jsenv build
|
|
5
|
+
* - The sourcemap are not generated but ideally they should be
|
|
6
|
+
* It can be quite challenging, see "bundle_sourcemap.js"
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { applyPostCss } from "@jsenv/utils/css_ast/apply_post_css.js"
|
|
10
|
+
import { postCssPluginUrlVisitor } from "@jsenv/utils/css_ast/postcss_plugin_url_visitor.js"
|
|
11
|
+
import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
|
|
12
|
+
import { sortByDependencies } from "@jsenv/utils/graph/sort_by_dependencies.js"
|
|
13
|
+
|
|
14
|
+
// Do not use until https://github.com/parcel-bundler/parcel-css/issues/181
|
|
15
|
+
export const bundleCss = async ({ cssUrlInfos, context }) => {
|
|
16
|
+
const bundledCssUrlInfos = {}
|
|
17
|
+
const cssBundleInfos = await performCssBundling({
|
|
18
|
+
cssEntryUrlInfos: cssUrlInfos,
|
|
19
|
+
context,
|
|
20
|
+
})
|
|
21
|
+
cssUrlInfos.forEach((cssUrlInfo) => {
|
|
22
|
+
bundledCssUrlInfos[cssUrlInfo.url] = {
|
|
23
|
+
data: {
|
|
24
|
+
generatedBy: "parcel",
|
|
25
|
+
},
|
|
26
|
+
contentType: "text/css",
|
|
27
|
+
content: cssBundleInfos[cssUrlInfo.url].bundleContent,
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
return bundledCssUrlInfos
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const performCssBundling = async ({ cssEntryUrlInfos, context }) => {
|
|
34
|
+
const cssBundleInfos = await loadCssUrls({
|
|
35
|
+
cssEntryUrlInfos,
|
|
36
|
+
context,
|
|
37
|
+
})
|
|
38
|
+
const cssUrlsSorted = sortByDependencies(cssBundleInfos)
|
|
39
|
+
cssUrlsSorted.forEach((cssUrl) => {
|
|
40
|
+
const cssBundleInfo = cssBundleInfos[cssUrl]
|
|
41
|
+
const magicSource = createMagicSource(cssBundleInfo.content)
|
|
42
|
+
cssBundleInfo.cssUrls.forEach((cssUrl) => {
|
|
43
|
+
if (cssUrl.type === "@import") {
|
|
44
|
+
magicSource.replace({
|
|
45
|
+
start: cssUrl.atRuleStart,
|
|
46
|
+
end: cssUrl.atRuleEnd,
|
|
47
|
+
replacement: cssBundleInfos[cssUrl.url].bundleContent,
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
const { content } = magicSource.toContentAndSourcemap()
|
|
52
|
+
cssBundleInfo.bundleContent = content.trim()
|
|
53
|
+
})
|
|
54
|
+
return cssBundleInfos
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const parseCssUrls = async ({ css, url }) => {
|
|
58
|
+
const cssUrls = []
|
|
59
|
+
await applyPostCss({
|
|
60
|
+
sourcemaps: false,
|
|
61
|
+
plugins: [
|
|
62
|
+
postCssPluginUrlVisitor({
|
|
63
|
+
urlVisitor: ({
|
|
64
|
+
type,
|
|
65
|
+
specifier,
|
|
66
|
+
specifierStart,
|
|
67
|
+
specifierEnd,
|
|
68
|
+
atRuleStart,
|
|
69
|
+
atRuleEnd,
|
|
70
|
+
}) => {
|
|
71
|
+
cssUrls.push({
|
|
72
|
+
type,
|
|
73
|
+
url: new URL(specifier, url).href,
|
|
74
|
+
specifierStart,
|
|
75
|
+
specifierEnd,
|
|
76
|
+
atRuleStart,
|
|
77
|
+
atRuleEnd,
|
|
78
|
+
})
|
|
79
|
+
},
|
|
80
|
+
}),
|
|
81
|
+
],
|
|
82
|
+
url,
|
|
83
|
+
content: css,
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
return cssUrls
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const loadCssUrls = async ({ cssEntryUrlInfos, context }) => {
|
|
90
|
+
const cssBundleInfos = {}
|
|
91
|
+
const promises = []
|
|
92
|
+
const promiseMap = new Map()
|
|
93
|
+
|
|
94
|
+
const load = (cssUrlInfo) => {
|
|
95
|
+
const promiseFromData = promiseMap.get(cssUrlInfo.url)
|
|
96
|
+
if (promiseFromData) return promiseFromData
|
|
97
|
+
const promise = _load(cssUrlInfo)
|
|
98
|
+
promises.push(promise)
|
|
99
|
+
promiseMap.set(cssUrlInfo.url, promise)
|
|
100
|
+
return promise
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const _load = async (cssUrlInfo) => {
|
|
104
|
+
const cssUrls = await parseCssUrls({
|
|
105
|
+
css: cssUrlInfo.content,
|
|
106
|
+
url: cssUrlInfo.url,
|
|
107
|
+
})
|
|
108
|
+
const cssBundleInfo = {
|
|
109
|
+
content: cssUrlInfo.content,
|
|
110
|
+
cssUrls,
|
|
111
|
+
dependencies: [],
|
|
112
|
+
}
|
|
113
|
+
cssBundleInfos[cssUrlInfo.url] = cssBundleInfo
|
|
114
|
+
cssUrls.forEach((cssUrl) => {
|
|
115
|
+
if (cssUrl.type === "@import") {
|
|
116
|
+
cssBundleInfo.dependencies.push(cssUrl.url)
|
|
117
|
+
const importedCssUrlInfo = context.urlGraph.getUrlInfo(cssUrl.url)
|
|
118
|
+
load(importedCssUrlInfo)
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
cssEntryUrlInfos.forEach((cssEntryUrlInfo) => {
|
|
124
|
+
load(cssEntryUrlInfo)
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
const waitAll = async () => {
|
|
128
|
+
if (promises.length === 0) {
|
|
129
|
+
return
|
|
130
|
+
}
|
|
131
|
+
const promisesToWait = promises.slice()
|
|
132
|
+
promises.length = 0
|
|
133
|
+
await Promise.all(promisesToWait)
|
|
134
|
+
await waitAll()
|
|
135
|
+
}
|
|
136
|
+
await waitAll()
|
|
137
|
+
promiseMap.clear()
|
|
138
|
+
|
|
139
|
+
return cssBundleInfos
|
|
140
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* TODO:
|
|
3
|
+
* for each js_classic where subtype is a worker
|
|
4
|
+
* take the url info and find importScripts calls
|
|
5
|
+
* and replace them with the corresponding url info file content
|
|
6
|
+
* we'll ikely need to save the importScripts node location to be able to do that
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
|
|
10
|
+
|
|
11
|
+
export const bundleJsClassicWorkers = () => {
|
|
12
|
+
return {}
|
|
13
|
+
}
|