@jsenv/core 27.0.0-alpha.5 → 27.0.0-alpha.50
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 +22 -21
- package/readme.md +4 -12
- package/src/build/build.js +749 -437
- package/src/build/build_urls_generator.js +56 -22
- 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 +255 -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 +201 -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 -292
- package/src/omega/omega_server.js +2 -3
- package/src/omega/server/file_service.js +38 -25
- package/src/omega/server/user_agent.js +4 -2
- package/src/omega/url_graph/url_graph_load.js +14 -7
- package/src/omega/url_graph/url_graph_report.js +17 -15
- package/src/omega/url_graph/url_info_transformations.js +26 -9
- package/src/omega/url_graph.js +91 -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 +21 -0
- package/src/plugins/bundling/js_classic_workers/bundle_js_classic_workers.js +13 -0
- package/src/{build/plugins/bundle_js_module/jsenv_plugin_bundle_js_module.js → plugins/bundling/js_module/bundle_js_module.js} +150 -79
- package/src/plugins/bundling/jsenv_plugin_bundling.js +54 -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 -58
- 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 +296 -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 +91 -0
- package/src/plugins/transpilation/as_js_classic/client/s.js +808 -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 +183 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_script_type_module_as_classic.js +256 -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 +4 -22
- 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 +37 -21
- 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 +70 -0
- package/src/plugins/transpilation/jsenv_plugin_transpilation.js +44 -0
- package/src/plugins/url_analysis/css/css_urls.js +42 -0
- package/src/plugins/url_analysis/html/html_urls.js +273 -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/{omega/core_plugins → plugins}/url_version/jsenv_plugin_url_version.js +12 -15
- package/src/test/execute_plan.js +30 -18
- package/src/test/execute_test_plan.js +23 -8
- package/src/test/logs_file_execution.js +8 -7
- 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.js +0 -39
- package/src/omega/runtime_support/runtime_support.js +0 -20
- 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
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import { createSSERoom } from "@jsenv/server"
|
|
2
|
-
import { registerDirectoryLifecycle } from "@jsenv/filesystem"
|
|
3
|
-
import {
|
|
4
|
-
createCallbackList,
|
|
5
|
-
createCallbackListNotifiedOnce,
|
|
6
|
-
} from "@jsenv/abort"
|
|
7
|
-
|
|
8
|
-
export const createSSEService = ({
|
|
9
|
-
rootDirectoryUrl,
|
|
10
|
-
autoreloadPatterns,
|
|
11
|
-
onFileChange,
|
|
12
|
-
hotUpdateCallbackList,
|
|
13
|
-
}) => {
|
|
14
|
-
const destroyCallbackList = createCallbackListNotifiedOnce()
|
|
15
|
-
const projectFileModified = createCallbackList()
|
|
16
|
-
const projectFileRemoved = createCallbackList()
|
|
17
|
-
const projectFileAdded = createCallbackList()
|
|
18
|
-
const watchProjectFiles = (callback) => {
|
|
19
|
-
const removeModifiedCallback = projectFileModified.add((relativeUrl) => {
|
|
20
|
-
callback({
|
|
21
|
-
event: "modified",
|
|
22
|
-
relativeUrl,
|
|
23
|
-
})
|
|
24
|
-
})
|
|
25
|
-
const removeRemovedCallback = projectFileRemoved.add((relativeUrl) => {
|
|
26
|
-
callback({
|
|
27
|
-
event: "removed",
|
|
28
|
-
relativeUrl,
|
|
29
|
-
})
|
|
30
|
-
})
|
|
31
|
-
const removeAddedCallback = projectFileRemoved.add((relativeUrl) => {
|
|
32
|
-
callback({
|
|
33
|
-
event: "added",
|
|
34
|
-
relativeUrl,
|
|
35
|
-
})
|
|
36
|
-
})
|
|
37
|
-
return () => {
|
|
38
|
-
removeModifiedCallback()
|
|
39
|
-
removeRemovedCallback()
|
|
40
|
-
removeAddedCallback()
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
// wait 100ms to actually start watching
|
|
44
|
-
// otherwise server starting is delayed by the filesystem scan done in
|
|
45
|
-
// registerDirectoryLifecycle
|
|
46
|
-
const timeout = setTimeout(() => {
|
|
47
|
-
const unregisterDirectoryLifecyle = registerDirectoryLifecycle(
|
|
48
|
-
rootDirectoryUrl,
|
|
49
|
-
{
|
|
50
|
-
watchDescription: {
|
|
51
|
-
...autoreloadPatterns,
|
|
52
|
-
".jsenv/": false,
|
|
53
|
-
},
|
|
54
|
-
updated: ({ relativeUrl }) => {
|
|
55
|
-
projectFileModified.notify(relativeUrl)
|
|
56
|
-
},
|
|
57
|
-
removed: ({ relativeUrl }) => {
|
|
58
|
-
projectFileRemoved.notify(relativeUrl)
|
|
59
|
-
},
|
|
60
|
-
added: ({ relativeUrl }) => {
|
|
61
|
-
projectFileAdded.notify(relativeUrl)
|
|
62
|
-
},
|
|
63
|
-
keepProcessAlive: false,
|
|
64
|
-
recursive: true,
|
|
65
|
-
},
|
|
66
|
-
)
|
|
67
|
-
destroyCallbackList.add(unregisterDirectoryLifecyle)
|
|
68
|
-
}, 100)
|
|
69
|
-
destroyCallbackList.add(() => {
|
|
70
|
-
clearTimeout(timeout)
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
const cache = []
|
|
74
|
-
const sseRoomLimit = 100
|
|
75
|
-
const getOrCreateSSERoom = (request) => {
|
|
76
|
-
const htmlFileRelativeUrl = request.ressource.slice(1)
|
|
77
|
-
const cacheEntry = cache.find(
|
|
78
|
-
(cacheEntryCandidate) =>
|
|
79
|
-
cacheEntryCandidate.htmlFileRelativeUrl === htmlFileRelativeUrl,
|
|
80
|
-
)
|
|
81
|
-
if (cacheEntry) {
|
|
82
|
-
return cacheEntry.sseRoom
|
|
83
|
-
}
|
|
84
|
-
const sseRoom = createSSERoom({
|
|
85
|
-
retryDuration: 2000,
|
|
86
|
-
historyLength: 100,
|
|
87
|
-
welcomeEventEnabled: true,
|
|
88
|
-
effect: () => {
|
|
89
|
-
const removeHotUpdateCallback = hotUpdateCallbackList.add(
|
|
90
|
-
(hotUpdate) => {
|
|
91
|
-
if (hotUpdate.declined) {
|
|
92
|
-
sseRoom.sendEvent({
|
|
93
|
-
type: "reload",
|
|
94
|
-
data: JSON.stringify({
|
|
95
|
-
cause: hotUpdate.cause,
|
|
96
|
-
type: "full",
|
|
97
|
-
typeReason: hotUpdate.reason,
|
|
98
|
-
declinedBy: hotUpdate.declinedBy,
|
|
99
|
-
}),
|
|
100
|
-
})
|
|
101
|
-
} else {
|
|
102
|
-
sseRoom.sendEvent({
|
|
103
|
-
type: "reload",
|
|
104
|
-
data: JSON.stringify({
|
|
105
|
-
cause: hotUpdate.cause,
|
|
106
|
-
type: "hot",
|
|
107
|
-
typeReason: hotUpdate.reason,
|
|
108
|
-
hotInstructions: hotUpdate.instructions,
|
|
109
|
-
}),
|
|
110
|
-
})
|
|
111
|
-
}
|
|
112
|
-
},
|
|
113
|
-
)
|
|
114
|
-
const stopWatching = watchProjectFiles(({ relativeUrl, event }) => {
|
|
115
|
-
onFileChange({ relativeUrl, event })
|
|
116
|
-
})
|
|
117
|
-
return () => {
|
|
118
|
-
removeHotUpdateCallback()
|
|
119
|
-
stopWatching()
|
|
120
|
-
}
|
|
121
|
-
},
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
const removeSSECleanupCallback = destroyCallbackList.add(() => {
|
|
125
|
-
removeSSECleanupCallback()
|
|
126
|
-
sseRoom.close()
|
|
127
|
-
})
|
|
128
|
-
cache.push({
|
|
129
|
-
htmlFileRelativeUrl,
|
|
130
|
-
sseRoom,
|
|
131
|
-
cleanup: () => {
|
|
132
|
-
removeSSECleanupCallback()
|
|
133
|
-
sseRoom.close()
|
|
134
|
-
},
|
|
135
|
-
})
|
|
136
|
-
if (cache.length >= sseRoomLimit) {
|
|
137
|
-
const firstCacheEntry = cache.shift()
|
|
138
|
-
firstCacheEntry.cleanup()
|
|
139
|
-
}
|
|
140
|
-
return sseRoom
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return {
|
|
144
|
-
getOrCreateSSERoom,
|
|
145
|
-
destroy: () => {
|
|
146
|
-
destroyCallbackList.notify()
|
|
147
|
-
},
|
|
148
|
-
}
|
|
149
|
-
}
|
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
import { fork } from "node:child_process"
|
|
2
|
-
import { urlToFileSystemPath } from "@jsenv/filesystem"
|
|
3
|
-
import { createDetailedMessage } from "@jsenv/logger"
|
|
4
|
-
import {
|
|
5
|
-
Abort,
|
|
6
|
-
raceCallbacks,
|
|
7
|
-
createCallbackListNotifiedOnce,
|
|
8
|
-
} from "@jsenv/abort"
|
|
9
|
-
import { uneval } from "@jsenv/uneval"
|
|
10
|
-
|
|
11
|
-
import { memoize } from "@jsenv/utils/memoize/memoize.js"
|
|
12
|
-
|
|
13
|
-
import { createChildExecOptions } from "./child_exec_options.js"
|
|
14
|
-
import { ExecOptions } from "./exec_options.js"
|
|
15
|
-
import { killProcessTree } from "./kill_process_tree.js"
|
|
16
|
-
|
|
17
|
-
const NODE_CONTROLLABLE_FILE_URL = new URL(
|
|
18
|
-
"./controllable_file.mjs",
|
|
19
|
-
import.meta.url,
|
|
20
|
-
).href
|
|
21
|
-
|
|
22
|
-
export const createControlledProcess = async ({
|
|
23
|
-
signal = new AbortController().signal,
|
|
24
|
-
logger,
|
|
25
|
-
logProcessCommand = false,
|
|
26
|
-
|
|
27
|
-
onStop,
|
|
28
|
-
onError,
|
|
29
|
-
onConsole,
|
|
30
|
-
|
|
31
|
-
debugPort,
|
|
32
|
-
debugMode,
|
|
33
|
-
debugModeInheritBreak,
|
|
34
|
-
commandLineOptions = [],
|
|
35
|
-
env,
|
|
36
|
-
inheritProcessEnv = true,
|
|
37
|
-
|
|
38
|
-
stdin = "pipe",
|
|
39
|
-
stdout = "pipe",
|
|
40
|
-
stderr = "pipe",
|
|
41
|
-
}) => {
|
|
42
|
-
if (env !== undefined && typeof env !== "object") {
|
|
43
|
-
throw new TypeError(`env must be an object, got ${env}`)
|
|
44
|
-
}
|
|
45
|
-
const cleanupCallbackList = createCallbackListNotifiedOnce()
|
|
46
|
-
const cleanup = async (reason) => {
|
|
47
|
-
await cleanupCallbackList.notify({ reason })
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const childExecOptions = await createChildExecOptions({
|
|
51
|
-
signal,
|
|
52
|
-
debugPort,
|
|
53
|
-
debugMode,
|
|
54
|
-
debugModeInheritBreak,
|
|
55
|
-
})
|
|
56
|
-
const execArgv = ExecOptions.toExecArgv({
|
|
57
|
-
...childExecOptions,
|
|
58
|
-
...ExecOptions.fromExecArgv(commandLineOptions),
|
|
59
|
-
})
|
|
60
|
-
const envForChildProcess = {
|
|
61
|
-
...(inheritProcessEnv ? process.env : {}),
|
|
62
|
-
...env,
|
|
63
|
-
}
|
|
64
|
-
logger[logProcessCommand ? "info" : "debug"](
|
|
65
|
-
`${process.argv[0]} ${execArgv.join(" ")} ${urlToFileSystemPath(
|
|
66
|
-
NODE_CONTROLLABLE_FILE_URL,
|
|
67
|
-
)}`,
|
|
68
|
-
)
|
|
69
|
-
const childProcess = fork(urlToFileSystemPath(NODE_CONTROLLABLE_FILE_URL), {
|
|
70
|
-
execArgv,
|
|
71
|
-
// silent: true
|
|
72
|
-
stdio: ["pipe", "pipe", "pipe", "ipc"],
|
|
73
|
-
env: envForChildProcess,
|
|
74
|
-
})
|
|
75
|
-
logger.debug(
|
|
76
|
-
createDetailedMessage(`child process forked (pid ${childProcess.pid})`, {
|
|
77
|
-
"execArgv": execArgv.join(`\n`),
|
|
78
|
-
"custom env": JSON.stringify(env, null, " "),
|
|
79
|
-
}),
|
|
80
|
-
)
|
|
81
|
-
// if we pass stream, pipe them https://github.com/sindresorhus/execa/issues/81
|
|
82
|
-
if (typeof stdin === "object") {
|
|
83
|
-
stdin.pipe(childProcess.stdin)
|
|
84
|
-
}
|
|
85
|
-
if (typeof stdout === "object") {
|
|
86
|
-
childProcess.stdout.pipe(stdout)
|
|
87
|
-
}
|
|
88
|
-
if (typeof stderr === "object") {
|
|
89
|
-
childProcess.stderr.pipe(stderr)
|
|
90
|
-
}
|
|
91
|
-
const childProcessReadyPromise = new Promise((resolve) => {
|
|
92
|
-
onceProcessMessage(childProcess, "ready", resolve)
|
|
93
|
-
})
|
|
94
|
-
const removeOutputListener = installProcessOutputListener(
|
|
95
|
-
childProcess,
|
|
96
|
-
({ type, text }) => {
|
|
97
|
-
onConsole({ type, text })
|
|
98
|
-
},
|
|
99
|
-
)
|
|
100
|
-
const stop = memoize(async ({ gracefulStopAllocatedMs } = {}) => {
|
|
101
|
-
// all libraries are facing problem on windows when trying
|
|
102
|
-
// to kill a process spawning other processes.
|
|
103
|
-
// "killProcessTree" is theorically correct but sometimes keep process handing forever.
|
|
104
|
-
// Inside GitHub workflow the whole Virtual machine gets unresponsive and ends up being killed
|
|
105
|
-
// There is no satisfying solution to this problem so we stick to the basic
|
|
106
|
-
// childProcess.kill()
|
|
107
|
-
if (process.platform === "win32") {
|
|
108
|
-
childProcess.kill()
|
|
109
|
-
return
|
|
110
|
-
}
|
|
111
|
-
if (gracefulStopAllocatedMs) {
|
|
112
|
-
try {
|
|
113
|
-
await killProcessTree(childProcess.pid, {
|
|
114
|
-
signal: GRACEFUL_STOP_SIGNAL,
|
|
115
|
-
timeout: gracefulStopAllocatedMs,
|
|
116
|
-
})
|
|
117
|
-
return
|
|
118
|
-
} catch (e) {
|
|
119
|
-
if (e.code === "TIMEOUT") {
|
|
120
|
-
logger.debug(
|
|
121
|
-
`kill with SIGTERM because gracefulStop still pending after ${gracefulStopAllocatedMs}ms`,
|
|
122
|
-
)
|
|
123
|
-
await killProcessTree(childProcess.pid, {
|
|
124
|
-
signal: GRACEFUL_STOP_FAILED_SIGNAL,
|
|
125
|
-
})
|
|
126
|
-
return
|
|
127
|
-
}
|
|
128
|
-
throw e
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
await killProcessTree(childProcess.pid, { signal: STOP_SIGNAL })
|
|
132
|
-
return
|
|
133
|
-
})
|
|
134
|
-
raceCallbacks(
|
|
135
|
-
{
|
|
136
|
-
// https://nodejs.org/api/child_process.html#child_process_event_disconnect
|
|
137
|
-
// disconnect: (cb) => {
|
|
138
|
-
// return onceProcessEvent(childProcess, "disconnect", cb)
|
|
139
|
-
// },
|
|
140
|
-
// https://nodejs.org/api/child_process.html#child_process_event_error
|
|
141
|
-
error: (cb) => {
|
|
142
|
-
return onceProcessEvent(childProcess, "error", cb)
|
|
143
|
-
},
|
|
144
|
-
exit: (cb) => {
|
|
145
|
-
return onceProcessEvent(childProcess, "exit", (code, signal) => {
|
|
146
|
-
cb({ code, signal })
|
|
147
|
-
})
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
(winner) => {
|
|
151
|
-
const raceEffects = {
|
|
152
|
-
// disconnect: () => {
|
|
153
|
-
// stoppedCallbackList.notify()
|
|
154
|
-
// },
|
|
155
|
-
error: (error) => {
|
|
156
|
-
removeOutputListener()
|
|
157
|
-
if (
|
|
158
|
-
!childProcess.connected &&
|
|
159
|
-
error.code === "ERR_IPC_DISCONNECTED"
|
|
160
|
-
) {
|
|
161
|
-
return
|
|
162
|
-
}
|
|
163
|
-
onError(error)
|
|
164
|
-
},
|
|
165
|
-
exit: async ({ code, signal }) => {
|
|
166
|
-
// process.exit(1) in child process or process.exitCode = 1 + process.exit()
|
|
167
|
-
// means there was an error even if we don't know exactly what.
|
|
168
|
-
if (
|
|
169
|
-
code !== null &&
|
|
170
|
-
code !== 0 &&
|
|
171
|
-
code !== SIGINT_EXIT_CODE &&
|
|
172
|
-
code !== SIGTERM_EXIT_CODE &&
|
|
173
|
-
code !== SIGABORT_EXIT_CODE
|
|
174
|
-
) {
|
|
175
|
-
onError(createExitWithFailureCodeError(code))
|
|
176
|
-
}
|
|
177
|
-
await cleanup("process exit")
|
|
178
|
-
onStop({ code, signal })
|
|
179
|
-
},
|
|
180
|
-
}
|
|
181
|
-
raceEffects[winner.name](winner.data)
|
|
182
|
-
},
|
|
183
|
-
)
|
|
184
|
-
const requestActionOnChildProcess = async ({
|
|
185
|
-
signal,
|
|
186
|
-
actionType,
|
|
187
|
-
actionParams,
|
|
188
|
-
}) => {
|
|
189
|
-
const actionOperation = Abort.startOperation()
|
|
190
|
-
actionOperation.addAbortSignal(signal)
|
|
191
|
-
try {
|
|
192
|
-
const result = await new Promise(async (resolve, reject) => {
|
|
193
|
-
actionOperation.throwIfAborted()
|
|
194
|
-
await childProcessReadyPromise
|
|
195
|
-
onceProcessMessage(
|
|
196
|
-
childProcess,
|
|
197
|
-
"action-result",
|
|
198
|
-
({ status, value }) => {
|
|
199
|
-
if (status === "action-completed") {
|
|
200
|
-
resolve(value)
|
|
201
|
-
} else {
|
|
202
|
-
reject(value)
|
|
203
|
-
}
|
|
204
|
-
},
|
|
205
|
-
)
|
|
206
|
-
logger.debug(
|
|
207
|
-
createDetailedMessage(`ask child process to perform an action`, {
|
|
208
|
-
actionType,
|
|
209
|
-
actionParams: JSON.stringify(actionParams, null, " "),
|
|
210
|
-
}),
|
|
211
|
-
)
|
|
212
|
-
try {
|
|
213
|
-
actionOperation.throwIfAborted()
|
|
214
|
-
await sendToProcess(childProcess, "action", {
|
|
215
|
-
actionType,
|
|
216
|
-
actionParams,
|
|
217
|
-
})
|
|
218
|
-
} catch (e) {
|
|
219
|
-
if (Abort.isAbortError(e) && actionOperation.signal.aborted) {
|
|
220
|
-
throw e
|
|
221
|
-
}
|
|
222
|
-
logger.error(
|
|
223
|
-
createDetailedMessage(`error while sending message to child`, {
|
|
224
|
-
["error stack"]: e.stack,
|
|
225
|
-
}),
|
|
226
|
-
)
|
|
227
|
-
throw e
|
|
228
|
-
}
|
|
229
|
-
})
|
|
230
|
-
return result
|
|
231
|
-
} finally {
|
|
232
|
-
await actionOperation.end()
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
return {
|
|
236
|
-
execArgv,
|
|
237
|
-
stop,
|
|
238
|
-
requestActionOnChildProcess,
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// https://nodejs.org/api/process.html#process_signal_events
|
|
243
|
-
const SIGINT_SIGNAL_NUMBER = 2
|
|
244
|
-
const SIGABORT_SIGNAL_NUMBER = 6
|
|
245
|
-
const SIGTERM_SIGNAL_NUMBER = 15
|
|
246
|
-
const SIGINT_EXIT_CODE = 128 + SIGINT_SIGNAL_NUMBER
|
|
247
|
-
const SIGABORT_EXIT_CODE = 128 + SIGABORT_SIGNAL_NUMBER
|
|
248
|
-
const SIGTERM_EXIT_CODE = 128 + SIGTERM_SIGNAL_NUMBER
|
|
249
|
-
// http://man7.org/linux/man-pages/man7/signal.7.html
|
|
250
|
-
// https:// github.com/nodejs/node/blob/1d9511127c419ec116b3ddf5fc7a59e8f0f1c1e4/lib/internal/child_process.js#L472
|
|
251
|
-
const GRACEFUL_STOP_SIGNAL = "SIGTERM"
|
|
252
|
-
const STOP_SIGNAL = "SIGKILL"
|
|
253
|
-
// it would be more correct if GRACEFUL_STOP_FAILED_SIGNAL was SIGHUP instead of SIGKILL.
|
|
254
|
-
// but I'm not sure and it changes nothing so just use SIGKILL
|
|
255
|
-
const GRACEFUL_STOP_FAILED_SIGNAL = "SIGKILL"
|
|
256
|
-
|
|
257
|
-
const sendToProcess = async (childProcess, type, data) => {
|
|
258
|
-
const source = uneval(data, { functionAllowed: true })
|
|
259
|
-
return new Promise((resolve, reject) => {
|
|
260
|
-
childProcess.send({ type, data: source }, (error) => {
|
|
261
|
-
if (error) {
|
|
262
|
-
reject(error)
|
|
263
|
-
} else {
|
|
264
|
-
resolve()
|
|
265
|
-
}
|
|
266
|
-
})
|
|
267
|
-
})
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
const installProcessOutputListener = (childProcess, callback) => {
|
|
271
|
-
// beware that we may receive ansi output here, should not be a problem but keep that in mind
|
|
272
|
-
const stdoutDataCallback = (chunk) => {
|
|
273
|
-
callback({ type: "log", text: String(chunk) })
|
|
274
|
-
}
|
|
275
|
-
childProcess.stdout.on("data", stdoutDataCallback)
|
|
276
|
-
const stdErrorDataCallback = (chunk) => {
|
|
277
|
-
callback({ type: "error", text: String(chunk) })
|
|
278
|
-
}
|
|
279
|
-
childProcess.stderr.on("data", stdErrorDataCallback)
|
|
280
|
-
return () => {
|
|
281
|
-
childProcess.stdout.removeListener("data", stdoutDataCallback)
|
|
282
|
-
childProcess.stderr.removeListener("data", stdoutDataCallback)
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
const createExitWithFailureCodeError = (code) => {
|
|
287
|
-
if (code === 12) {
|
|
288
|
-
return new Error(
|
|
289
|
-
`child exited with 12: forked child wanted to use a non available port for debug`,
|
|
290
|
-
)
|
|
291
|
-
}
|
|
292
|
-
const error = new Error(`child exited with ${code}`)
|
|
293
|
-
error.exitCode = code
|
|
294
|
-
return error
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
const onceProcessMessage = (childProcess, type, callback) => {
|
|
298
|
-
const onmessage = (message) => {
|
|
299
|
-
if (message.type === type) {
|
|
300
|
-
childProcess.removeListener("message", onmessage)
|
|
301
|
-
// eslint-disable-next-line no-eval
|
|
302
|
-
callback(message.data ? eval(`(${message.data})`) : "")
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
childProcess.on("message", onmessage)
|
|
306
|
-
return () => {
|
|
307
|
-
childProcess.removeListener("message", onmessage)
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
const onceProcessEvent = (childProcess, type, callback) => {
|
|
312
|
-
childProcess.once(type, callback)
|
|
313
|
-
return () => {
|
|
314
|
-
childProcess.removeListener(type, callback)
|
|
315
|
-
}
|
|
316
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs"
|
|
2
|
-
import { urlToContentType } from "@jsenv/server"
|
|
3
|
-
import {
|
|
4
|
-
urlIsInsideOf,
|
|
5
|
-
urlToRelativeUrl,
|
|
6
|
-
fileSystemRootUrl,
|
|
7
|
-
} from "@jsenv/filesystem"
|
|
8
|
-
import { ContentType } from "@jsenv/utils/src/content_type.js"
|
|
9
|
-
|
|
10
|
-
export const jsenvPluginFileUrls = () => {
|
|
11
|
-
return [jsenvPluginResolveAbsoluteFileUrls(), jsenvPluginLoadFileUrls()]
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const jsenvPluginResolveAbsoluteFileUrls = () => {
|
|
15
|
-
return {
|
|
16
|
-
name: "jsenv:resolve_absolute_file_urls",
|
|
17
|
-
appliesDuring: {
|
|
18
|
-
// during dev and test it's a browser running the code
|
|
19
|
-
// so absolute file urls needs to be relativized
|
|
20
|
-
dev: true,
|
|
21
|
-
test: true,
|
|
22
|
-
// during build it's fine to use file:// urls
|
|
23
|
-
build: false,
|
|
24
|
-
},
|
|
25
|
-
resolve: ({ specifier }, { rootDirectoryUrl }) => {
|
|
26
|
-
if (!specifier.startsWith("/@fs/")) {
|
|
27
|
-
return null
|
|
28
|
-
}
|
|
29
|
-
const url = new URL(specifier.slice("/@fs".length), rootDirectoryUrl).href
|
|
30
|
-
return url
|
|
31
|
-
},
|
|
32
|
-
formatReferencedUrl: ({ url }, { rootDirectoryUrl }) => {
|
|
33
|
-
if (!url.startsWith("file:")) {
|
|
34
|
-
return null
|
|
35
|
-
}
|
|
36
|
-
const specifier = urlIsInsideOf(url, rootDirectoryUrl)
|
|
37
|
-
? `/${urlToRelativeUrl(url, rootDirectoryUrl)}`
|
|
38
|
-
: `/@fs/${url.slice(fileSystemRootUrl.length)}`
|
|
39
|
-
return specifier
|
|
40
|
-
},
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const jsenvPluginLoadFileUrls = () => {
|
|
45
|
-
return {
|
|
46
|
-
name: "jsenv:load_file_urls",
|
|
47
|
-
appliesDuring: "*",
|
|
48
|
-
load: ({ url }) => {
|
|
49
|
-
if (!url.startsWith("file:")) {
|
|
50
|
-
return null
|
|
51
|
-
}
|
|
52
|
-
const urlObject = new URL(url)
|
|
53
|
-
const fileBuffer = readFileSync(urlObject)
|
|
54
|
-
const contentType = urlToContentType(url)
|
|
55
|
-
if (ContentType.isTextual(contentType)) {
|
|
56
|
-
return {
|
|
57
|
-
contentType,
|
|
58
|
-
content: String(fileBuffer),
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return {
|
|
62
|
-
contentType,
|
|
63
|
-
content: fileBuffer,
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
|
-
}
|
|
67
|
-
}
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import { unevalException } from "./uneval_exception.js"
|
|
2
|
-
import { displayErrorInDocument } from "./error_in_document.js"
|
|
3
|
-
import { displayErrorNotification } from "./error_in_notification.js"
|
|
4
|
-
|
|
5
|
-
const { __html_supervisor__ } = window
|
|
6
|
-
|
|
7
|
-
export const installHtmlSupervisor = ({ logs, measurePerf }) => {
|
|
8
|
-
const errorTransformer = null // could implement error stack remapping if needed
|
|
9
|
-
const scriptExecutionResults = {}
|
|
10
|
-
let collectCalled = false
|
|
11
|
-
let pendingExecutionCount = 0
|
|
12
|
-
let resolveScriptExecutionsPromise
|
|
13
|
-
const scriptExecutionsPromise = new Promise((resolve) => {
|
|
14
|
-
resolveScriptExecutionsPromise = resolve
|
|
15
|
-
})
|
|
16
|
-
const onExecutionStart = (name) => {
|
|
17
|
-
scriptExecutionResults[name] = null // ensure execution order is reflected into the object
|
|
18
|
-
pendingExecutionCount++
|
|
19
|
-
if (measurePerf) {
|
|
20
|
-
performance.mark(`execution_start`)
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
const onExecutionSettled = (name, executionResult) => {
|
|
24
|
-
if (measurePerf) {
|
|
25
|
-
performance.measure(`execution`, `execution_start`)
|
|
26
|
-
}
|
|
27
|
-
scriptExecutionResults[name] = executionResult
|
|
28
|
-
pendingExecutionCount--
|
|
29
|
-
if (pendingExecutionCount === 0 && collectCalled) {
|
|
30
|
-
resolveScriptExecutionsPromise()
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
const onExecutionError = (
|
|
34
|
-
executionResult,
|
|
35
|
-
{
|
|
36
|
-
currentScript,
|
|
37
|
-
errorExposureInNotification = false,
|
|
38
|
-
errorExposureInDocument = true,
|
|
39
|
-
},
|
|
40
|
-
) => {
|
|
41
|
-
const error = executionResult.error
|
|
42
|
-
if (error && error.code === "NETWORK_FAILURE") {
|
|
43
|
-
if (currentScript) {
|
|
44
|
-
const errorEvent = new Event("error")
|
|
45
|
-
currentScript.dispatchEvent(errorEvent)
|
|
46
|
-
}
|
|
47
|
-
} else if (typeof error === "object") {
|
|
48
|
-
const globalErrorEvent = new Event("error")
|
|
49
|
-
globalErrorEvent.filename = error.filename
|
|
50
|
-
globalErrorEvent.lineno = error.line || error.lineno
|
|
51
|
-
globalErrorEvent.colno = error.column || error.columnno
|
|
52
|
-
globalErrorEvent.message = error.message
|
|
53
|
-
window.dispatchEvent(globalErrorEvent)
|
|
54
|
-
}
|
|
55
|
-
if (errorExposureInNotification) {
|
|
56
|
-
displayErrorNotification(error)
|
|
57
|
-
}
|
|
58
|
-
if (errorExposureInDocument) {
|
|
59
|
-
displayErrorInDocument(error)
|
|
60
|
-
}
|
|
61
|
-
executionResult.exceptionSource = unevalException(error)
|
|
62
|
-
delete executionResult.error
|
|
63
|
-
}
|
|
64
|
-
const getNavigationStartTime = () => {
|
|
65
|
-
try {
|
|
66
|
-
return window.performance.timing.navigationStart
|
|
67
|
-
} catch (e) {
|
|
68
|
-
return Date.now()
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
__html_supervisor__.addExecution = async ({
|
|
73
|
-
type,
|
|
74
|
-
src,
|
|
75
|
-
currentScript,
|
|
76
|
-
promise,
|
|
77
|
-
}) => {
|
|
78
|
-
if (logs) {
|
|
79
|
-
console.group(`[jsenv] loading ${type} ${src}`)
|
|
80
|
-
}
|
|
81
|
-
onExecutionStart(src)
|
|
82
|
-
promise.then(
|
|
83
|
-
(namespace) => {
|
|
84
|
-
const executionResult = {
|
|
85
|
-
status: "completed",
|
|
86
|
-
namespace,
|
|
87
|
-
coverage: window.__coverage__,
|
|
88
|
-
}
|
|
89
|
-
onExecutionSettled(src, executionResult)
|
|
90
|
-
if (logs) {
|
|
91
|
-
console.log(`${type} load ended`)
|
|
92
|
-
|
|
93
|
-
console.groupEnd()
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
async (e) => {
|
|
97
|
-
let error = e
|
|
98
|
-
const executionResult = {
|
|
99
|
-
status: "errored",
|
|
100
|
-
coverage: window.__coverage__,
|
|
101
|
-
}
|
|
102
|
-
let errorExposureInConsole = true
|
|
103
|
-
if (e.name === "SyntaxError") {
|
|
104
|
-
// errorExposureInConsole = false
|
|
105
|
-
}
|
|
106
|
-
if (errorTransformer) {
|
|
107
|
-
try {
|
|
108
|
-
error = await errorTransformer(e)
|
|
109
|
-
} catch (e) {}
|
|
110
|
-
}
|
|
111
|
-
executionResult.error = error
|
|
112
|
-
onExecutionSettled(src, executionResult)
|
|
113
|
-
onExecutionError(executionResult, {
|
|
114
|
-
currentScript,
|
|
115
|
-
})
|
|
116
|
-
if (errorExposureInConsole) {
|
|
117
|
-
if (typeof window.reportError === "function") {
|
|
118
|
-
window.reportError(error)
|
|
119
|
-
} else {
|
|
120
|
-
console.error(error)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
console.groupEnd()
|
|
124
|
-
},
|
|
125
|
-
)
|
|
126
|
-
}
|
|
127
|
-
__html_supervisor__.collectScriptResults = async () => {
|
|
128
|
-
collectCalled = true
|
|
129
|
-
if (pendingExecutionCount === 0) {
|
|
130
|
-
resolveScriptExecutionsPromise()
|
|
131
|
-
} else {
|
|
132
|
-
await scriptExecutionsPromise
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
let status = "completed"
|
|
136
|
-
let exceptionSource = ""
|
|
137
|
-
Object.keys(scriptExecutionResults).forEach((key) => {
|
|
138
|
-
const scriptExecutionResult = scriptExecutionResults[key]
|
|
139
|
-
if (scriptExecutionResult.status === "errored") {
|
|
140
|
-
status = "errored"
|
|
141
|
-
exceptionSource = scriptExecutionResult.exceptionSource
|
|
142
|
-
}
|
|
143
|
-
})
|
|
144
|
-
return {
|
|
145
|
-
status,
|
|
146
|
-
...(status === "errored" ? { exceptionSource } : {}),
|
|
147
|
-
startTime: getNavigationStartTime(),
|
|
148
|
-
endTime: Date.now(),
|
|
149
|
-
scriptExecutionResults,
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export const superviseScriptTypeModule = ({ src }) => {
|
|
155
|
-
__html_supervisor__.addExecution({
|
|
156
|
-
type: "js_module",
|
|
157
|
-
currentScript: null,
|
|
158
|
-
improveErrorWithFetch: true,
|
|
159
|
-
src,
|
|
160
|
-
promise: import(new URL(src, document.location.href).href),
|
|
161
|
-
})
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const { executions } = __html_supervisor__
|
|
165
|
-
executions.forEach((execution) => {
|
|
166
|
-
__html_supervisor__.addExecution(execution)
|
|
167
|
-
})
|
|
168
|
-
executions.length = 0
|