@jsenv/core 27.0.0-alpha.21 → 27.0.0-alpha.24
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/package.json +4 -5
- package/src/build/start_build_server.js +136 -128
- package/src/dev/start_dev_server.js +39 -4
- package/src/execute/execute.js +8 -1
- package/src/execute/run.js +2 -2
- package/src/execute/runtimes/browsers/from_playwright.js +34 -1
- 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 +2 -5
- package/src/omega/kitchen.js +5 -3
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +0 -2
- package/src/plugins/transpilation/babel/helpers/babel_plugin_structure.js +6 -3
- package/src/plugins/transpilation/{as_js_classic/jsenv_plugin_top_level_await.js → jsenv_plugin_top_level_await.js} +0 -0
- package/src/plugins/transpilation/jsenv_plugin_transpilation.js +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/core",
|
|
3
|
-
"version": "27.0.0-alpha.
|
|
3
|
+
"version": "27.0.0-alpha.24",
|
|
4
4
|
"description": "Tool to develop, test and build js projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -11,8 +11,7 @@
|
|
|
11
11
|
"node": ">=16.13.0"
|
|
12
12
|
},
|
|
13
13
|
"publishConfig": {
|
|
14
|
-
"access": "public"
|
|
15
|
-
"registry": "https://registry.npmjs.org"
|
|
14
|
+
"access": "public"
|
|
16
15
|
},
|
|
17
16
|
"type": "module",
|
|
18
17
|
"imports": {},
|
|
@@ -67,7 +66,7 @@
|
|
|
67
66
|
"@jsenv/node-esm-resolution": "0.0.4",
|
|
68
67
|
"@jsenv/server": "12.6.1",
|
|
69
68
|
"@jsenv/uneval": "1.6.0",
|
|
70
|
-
"@jsenv/utils": "1.4.
|
|
69
|
+
"@jsenv/utils": "1.4.1",
|
|
71
70
|
"construct-style-sheets-polyfill": "3.1.0",
|
|
72
71
|
"cssnano": "5.1.7",
|
|
73
72
|
"cssnano-preset-default": "5.2.7",
|
|
@@ -111,4 +110,4 @@
|
|
|
111
110
|
"redux": "4.1.2",
|
|
112
111
|
"rollup": "2.70.1"
|
|
113
112
|
}
|
|
114
|
-
}
|
|
113
|
+
}
|
|
@@ -21,12 +21,11 @@ import {
|
|
|
21
21
|
pluginCORS,
|
|
22
22
|
fetchFileSystem,
|
|
23
23
|
} from "@jsenv/server"
|
|
24
|
-
import { Abort, raceProcessTeardownEvents } from "@jsenv/abort"
|
|
25
24
|
import { createLogger } from "@jsenv/logger"
|
|
26
25
|
|
|
26
|
+
import { initProcessAutorestart } from "@jsenv/utils/file_watcher/process_auto_restart.js"
|
|
27
27
|
import { createTaskLog } from "@jsenv/utils/logs/task_log.js"
|
|
28
28
|
import { watchFiles } from "@jsenv/utils/file_watcher/file_watcher.js"
|
|
29
|
-
import { setupFileRestart } from "@jsenv/utils/file_watcher/file_restart.js"
|
|
30
29
|
import { executeCommand } from "@jsenv/utils/command/command.js"
|
|
31
30
|
|
|
32
31
|
export const startBuildServer = async ({
|
|
@@ -34,155 +33,164 @@ export const startBuildServer = async ({
|
|
|
34
33
|
handleSIGINT = true,
|
|
35
34
|
logLevel,
|
|
36
35
|
buildCommandLogLevel = "warn",
|
|
37
|
-
protocol,
|
|
36
|
+
protocol = "http",
|
|
38
37
|
http2,
|
|
39
38
|
certificate,
|
|
40
39
|
privateKey,
|
|
41
40
|
listenAnyIp,
|
|
42
41
|
ip,
|
|
43
|
-
port,
|
|
42
|
+
port = 9779,
|
|
44
43
|
|
|
45
44
|
rootDirectoryUrl,
|
|
46
45
|
buildDirectoryUrl,
|
|
47
46
|
buildCommand,
|
|
47
|
+
mainBuildFile,
|
|
48
48
|
watchedFilePatterns,
|
|
49
49
|
cooldownBetweenFileEvents,
|
|
50
50
|
autorestart,
|
|
51
51
|
}) => {
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
52
|
+
const autorestartProcess = await initProcessAutorestart({
|
|
53
|
+
signal,
|
|
54
|
+
handleSIGINT,
|
|
55
|
+
...(autorestart
|
|
56
|
+
? {
|
|
57
|
+
enabled: true,
|
|
58
|
+
logLevel: autorestart.logLevel,
|
|
59
|
+
urlToRestart: autorestart.url,
|
|
60
|
+
urlsToWatch: [
|
|
61
|
+
...(autorestart.urlsToWatch || []),
|
|
62
|
+
new URL("package.json", rootDirectoryUrl),
|
|
63
|
+
new URL("jsenv.config.mjs", rootDirectoryUrl),
|
|
64
|
+
],
|
|
65
|
+
}
|
|
66
|
+
: {
|
|
67
|
+
enabled: false,
|
|
68
|
+
}),
|
|
69
|
+
})
|
|
70
|
+
if (autorestartProcess.isPrimary) {
|
|
71
|
+
return {
|
|
72
|
+
origin: `${protocol}://127.0.0.1:${port}`,
|
|
73
|
+
stop: () => {
|
|
74
|
+
autorestartProcess.stop()
|
|
75
|
+
},
|
|
76
|
+
}
|
|
63
77
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
autorestart,
|
|
67
|
-
injectedUrlsToWatch: [
|
|
68
|
-
new URL("package.json", rootDirectoryUrl),
|
|
69
|
-
new URL("jsenv.config.mjs", rootDirectoryUrl),
|
|
70
|
-
],
|
|
71
|
-
job: async () => {
|
|
72
|
-
const logger = createLogger({ logLevel })
|
|
78
|
+
signal = autorestartProcess.signal
|
|
79
|
+
const logger = createLogger({ logLevel })
|
|
73
80
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
buildTask.fail(`execute build command aborted`)
|
|
93
|
-
} else {
|
|
94
|
-
buildTask.fail()
|
|
95
|
-
throw e
|
|
96
|
-
}
|
|
97
|
-
}
|
|
81
|
+
let buildPromise
|
|
82
|
+
let abortController
|
|
83
|
+
const runBuild = async () => {
|
|
84
|
+
const buildTask = createTaskLog(logger, `execute build command`)
|
|
85
|
+
buildPromise = executeCommand(buildCommand, {
|
|
86
|
+
cwd: rootDirectoryUrl,
|
|
87
|
+
logLevel: buildCommandLogLevel,
|
|
88
|
+
signal,
|
|
89
|
+
})
|
|
90
|
+
try {
|
|
91
|
+
await buildPromise
|
|
92
|
+
buildTask.done()
|
|
93
|
+
} catch (e) {
|
|
94
|
+
if (e.code === "ABORT_ERR") {
|
|
95
|
+
buildTask.fail(`execute build command aborted`)
|
|
96
|
+
} else {
|
|
97
|
+
buildTask.fail()
|
|
98
|
+
throw e
|
|
98
99
|
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
99
102
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
protocol,
|
|
111
|
-
http2,
|
|
112
|
-
certificate,
|
|
113
|
-
privateKey,
|
|
114
|
-
listenAnyIp,
|
|
115
|
-
ip,
|
|
116
|
-
port,
|
|
117
|
-
plugins: {
|
|
118
|
-
...pluginCORS({
|
|
119
|
-
accessControlAllowRequestOrigin: true,
|
|
120
|
-
accessControlAllowRequestMethod: true,
|
|
121
|
-
accessControlAllowRequestHeaders: true,
|
|
122
|
-
accessControlAllowedRequestHeaders: [
|
|
123
|
-
...jsenvAccessControlAllowedHeaders,
|
|
124
|
-
"x-jsenv-execution-id",
|
|
125
|
-
],
|
|
126
|
-
accessControlAllowCredentials: true,
|
|
127
|
-
}),
|
|
128
|
-
...pluginServerTiming(),
|
|
129
|
-
...pluginRequestWaitingCheck({
|
|
130
|
-
requestWaitingMs: 60 * 1000,
|
|
131
|
-
}),
|
|
132
|
-
},
|
|
133
|
-
sendErrorDetails: true,
|
|
134
|
-
requestToResponse: async (request) => {
|
|
135
|
-
await buildPromise
|
|
136
|
-
const urlIsVersioned = new URL(
|
|
137
|
-
request.ressource,
|
|
138
|
-
request.origin,
|
|
139
|
-
).searchParams.has("v")
|
|
103
|
+
const startServerTask = createTaskLog(logger, "start build server")
|
|
104
|
+
const server = await startServer({
|
|
105
|
+
signal,
|
|
106
|
+
stopOnExit: false,
|
|
107
|
+
stopOnSIGINT: false,
|
|
108
|
+
stopOnInternalError: false,
|
|
109
|
+
keepProcessAlive: true,
|
|
110
|
+
logLevel,
|
|
111
|
+
startLog: false,
|
|
140
112
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
113
|
+
protocol,
|
|
114
|
+
http2,
|
|
115
|
+
certificate,
|
|
116
|
+
privateKey,
|
|
117
|
+
listenAnyIp,
|
|
118
|
+
ip,
|
|
119
|
+
port,
|
|
120
|
+
plugins: {
|
|
121
|
+
...pluginCORS({
|
|
122
|
+
accessControlAllowRequestOrigin: true,
|
|
123
|
+
accessControlAllowRequestMethod: true,
|
|
124
|
+
accessControlAllowRequestHeaders: true,
|
|
125
|
+
accessControlAllowedRequestHeaders: [
|
|
126
|
+
...jsenvAccessControlAllowedHeaders,
|
|
127
|
+
"x-jsenv-execution-id",
|
|
128
|
+
],
|
|
129
|
+
accessControlAllowCredentials: true,
|
|
130
|
+
}),
|
|
131
|
+
...pluginServerTiming(),
|
|
132
|
+
...pluginRequestWaitingCheck({
|
|
133
|
+
requestWaitingMs: 60 * 1000,
|
|
134
|
+
}),
|
|
135
|
+
},
|
|
136
|
+
sendErrorDetails: true,
|
|
137
|
+
requestToResponse: async (request) => {
|
|
138
|
+
await buildPromise
|
|
139
|
+
const urlIsVersioned = new URL(
|
|
140
|
+
request.ressource,
|
|
141
|
+
request.origin,
|
|
142
|
+
).searchParams.has("v")
|
|
143
|
+
if (mainBuildFile && request.ressource === "/") {
|
|
144
|
+
request = {
|
|
145
|
+
...request,
|
|
146
|
+
ressource: `/${mainBuildFile}`,
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return fetchFileSystem(
|
|
150
|
+
new URL(request.ressource.slice(1), buildDirectoryUrl),
|
|
151
|
+
{
|
|
152
|
+
headers: request.headers,
|
|
153
|
+
cacheControl: urlIsVersioned
|
|
154
|
+
? `private,max-age=${SECONDS_IN_30_DAYS},immutable`
|
|
155
|
+
: "private,max-age=0,must-revalidate",
|
|
156
|
+
etagEnabled: true,
|
|
157
|
+
compressionEnabled: !request.pathname.endsWith(".mp4"),
|
|
158
|
+
rootDirectoryUrl: buildDirectoryUrl,
|
|
159
|
+
canReadDirectory: true,
|
|
154
160
|
},
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
161
|
+
)
|
|
162
|
+
},
|
|
163
|
+
})
|
|
164
|
+
startServerTask.done()
|
|
165
|
+
logger.info(``)
|
|
166
|
+
Object.keys(server.origins).forEach((key) => {
|
|
167
|
+
logger.info(`- ${server.origins[key]}`)
|
|
168
|
+
})
|
|
169
|
+
logger.info(``)
|
|
162
170
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
)
|
|
176
|
-
runBuild()
|
|
177
|
-
})
|
|
178
|
-
},
|
|
171
|
+
const unregisterDirectoryLifecyle = watchFiles({
|
|
172
|
+
rootDirectoryUrl,
|
|
173
|
+
watchedFilePatterns,
|
|
174
|
+
cooldownBetweenFileEvents,
|
|
175
|
+
fileChangeCallback: ({ url, event }) => {
|
|
176
|
+
abortController.abort()
|
|
177
|
+
// setTimeout is to ensure the abortController.abort() above
|
|
178
|
+
// is properly taken into account so that logs about abort comes first
|
|
179
|
+
// then logs about re-running the build happens
|
|
180
|
+
setTimeout(() => {
|
|
181
|
+
logger.info(`${url.slice(rootDirectoryUrl.length)} ${event} -> rebuild`)
|
|
182
|
+
runBuild()
|
|
179
183
|
})
|
|
180
|
-
operation.addAbortCallback(() => {
|
|
181
|
-
unregisterDirectoryLifecyle()
|
|
182
|
-
})
|
|
183
|
-
runBuild()
|
|
184
184
|
},
|
|
185
185
|
})
|
|
186
|
+
signal.addEventListener("abort", () => {
|
|
187
|
+
unregisterDirectoryLifecyle()
|
|
188
|
+
})
|
|
189
|
+
runBuild()
|
|
190
|
+
return {
|
|
191
|
+
origin: server.origin,
|
|
192
|
+
stop: () => server.stop(),
|
|
193
|
+
}
|
|
186
194
|
}
|
|
187
195
|
|
|
188
196
|
const SECONDS_IN_30_DAYS = 60 * 60 * 24 * 30
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { assertAndNormalizeDirectoryUrl } from "@jsenv/filesystem"
|
|
2
2
|
import { createLogger } from "@jsenv/logger"
|
|
3
3
|
|
|
4
|
+
import { initProcessAutorestart } from "@jsenv/utils/file_watcher/process_auto_restart.js"
|
|
4
5
|
import { createTaskLog } from "@jsenv/utils/logs/task_log.js"
|
|
5
6
|
import { getCorePlugins } from "@jsenv/core/src/plugins/plugins.js"
|
|
6
7
|
import { createUrlGraph } from "@jsenv/core/src/omega/url_graph.js"
|
|
@@ -12,9 +13,10 @@ import { jsenvPluginToolbar } from "./plugins/toolbar/jsenv_plugin_toolbar.js"
|
|
|
12
13
|
|
|
13
14
|
export const startDevServer = async ({
|
|
14
15
|
signal = new AbortController().signal,
|
|
16
|
+
handleSIGINT,
|
|
15
17
|
logLevel,
|
|
16
|
-
port,
|
|
17
|
-
protocol,
|
|
18
|
+
port = 3456,
|
|
19
|
+
protocol = "http",
|
|
18
20
|
listenAnyIp,
|
|
19
21
|
// it's better to use http1 by default because it allows to get statusText in devtools
|
|
20
22
|
// which gives valuable information when there is errors
|
|
@@ -30,6 +32,7 @@ export const startDevServer = async ({
|
|
|
30
32
|
injectedGlobals,
|
|
31
33
|
nodeEsmResolution,
|
|
32
34
|
fileSystemMagicResolution,
|
|
35
|
+
transpilation,
|
|
33
36
|
autoreload = true,
|
|
34
37
|
explorerGroups = {
|
|
35
38
|
source: {
|
|
@@ -41,11 +44,39 @@ export const startDevServer = async ({
|
|
|
41
44
|
},
|
|
42
45
|
},
|
|
43
46
|
toolbar = false,
|
|
47
|
+
autorestart,
|
|
44
48
|
}) => {
|
|
49
|
+
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl)
|
|
50
|
+
const autorestartProcess = await initProcessAutorestart({
|
|
51
|
+
signal,
|
|
52
|
+
handleSIGINT,
|
|
53
|
+
...(autorestart
|
|
54
|
+
? {
|
|
55
|
+
enabled: true,
|
|
56
|
+
logLevel: autorestart.logLevel,
|
|
57
|
+
urlToRestart: autorestart.url,
|
|
58
|
+
urlsToWatch: [
|
|
59
|
+
...(autorestart.urlsToWatch || []),
|
|
60
|
+
new URL("package.json", rootDirectoryUrl),
|
|
61
|
+
new URL("jsenv.config.mjs", rootDirectoryUrl),
|
|
62
|
+
],
|
|
63
|
+
}
|
|
64
|
+
: {
|
|
65
|
+
enabled: false,
|
|
66
|
+
}),
|
|
67
|
+
})
|
|
68
|
+
if (autorestartProcess.isPrimary) {
|
|
69
|
+
return {
|
|
70
|
+
origin: `${protocol}://127.0.0.1:${port}`,
|
|
71
|
+
stop: () => {
|
|
72
|
+
autorestartProcess.stop()
|
|
73
|
+
},
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
45
77
|
const logger = createLogger({ logLevel })
|
|
46
78
|
const startServerTask = createTaskLog(logger, "start server")
|
|
47
79
|
|
|
48
|
-
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl)
|
|
49
80
|
const urlGraph = createUrlGraph()
|
|
50
81
|
const kitchen = createKitchen({
|
|
51
82
|
signal,
|
|
@@ -65,6 +96,7 @@ export const startDevServer = async ({
|
|
|
65
96
|
injectedGlobals,
|
|
66
97
|
nodeEsmResolution,
|
|
67
98
|
fileSystemMagicResolution,
|
|
99
|
+
transpilation,
|
|
68
100
|
autoreload,
|
|
69
101
|
}),
|
|
70
102
|
jsenvPluginExplorer({
|
|
@@ -98,5 +130,8 @@ export const startDevServer = async ({
|
|
|
98
130
|
kitchen.pluginController.callHooks("destroy")
|
|
99
131
|
}
|
|
100
132
|
})
|
|
101
|
-
return
|
|
133
|
+
return {
|
|
134
|
+
origin: server.origin,
|
|
135
|
+
stop: server.stop,
|
|
136
|
+
}
|
|
102
137
|
}
|
package/src/execute/execute.js
CHANGED
|
@@ -23,6 +23,7 @@ export const execute = async ({
|
|
|
23
23
|
collectConsole,
|
|
24
24
|
collectCoverage,
|
|
25
25
|
coverageTempDirectoryUrl,
|
|
26
|
+
collectPerformance = false,
|
|
26
27
|
runtime,
|
|
27
28
|
runtimeParams,
|
|
28
29
|
|
|
@@ -33,6 +34,7 @@ export const execute = async ({
|
|
|
33
34
|
fileSystemMagicResolution,
|
|
34
35
|
injectedGlobals,
|
|
35
36
|
transpilation,
|
|
37
|
+
htmlSupervisor = true,
|
|
36
38
|
|
|
37
39
|
port,
|
|
38
40
|
protocol,
|
|
@@ -75,10 +77,14 @@ export const execute = async ({
|
|
|
75
77
|
plugins: [
|
|
76
78
|
...plugins,
|
|
77
79
|
...getCorePlugins({
|
|
80
|
+
rootDirectoryUrl,
|
|
81
|
+
urlGraph,
|
|
78
82
|
scenario,
|
|
83
|
+
|
|
84
|
+
htmlSupervisor,
|
|
85
|
+
injectedGlobals,
|
|
79
86
|
nodeEsmResolution,
|
|
80
87
|
fileSystemMagicResolution,
|
|
81
|
-
injectedGlobals,
|
|
82
88
|
transpilation,
|
|
83
89
|
}),
|
|
84
90
|
],
|
|
@@ -120,6 +126,7 @@ export const execute = async ({
|
|
|
120
126
|
collectConsole,
|
|
121
127
|
collectCoverage,
|
|
122
128
|
coverageTempDirectoryUrl,
|
|
129
|
+
collectPerformance,
|
|
123
130
|
runtime,
|
|
124
131
|
runtimeParams,
|
|
125
132
|
})
|
package/src/execute/run.js
CHANGED
|
@@ -11,8 +11,7 @@ export const run = async ({
|
|
|
11
11
|
collectConsole = false,
|
|
12
12
|
collectCoverage = false,
|
|
13
13
|
coverageTempDirectoryUrl,
|
|
14
|
-
|
|
15
|
-
// collectPerformance = false,
|
|
14
|
+
collectPerformance = false,
|
|
16
15
|
|
|
17
16
|
runtime,
|
|
18
17
|
runtimeParams,
|
|
@@ -117,6 +116,7 @@ export const run = async ({
|
|
|
117
116
|
signal: runOperation.signal,
|
|
118
117
|
logger,
|
|
119
118
|
...runtimeParams,
|
|
119
|
+
collectPerformance,
|
|
120
120
|
keepRunning,
|
|
121
121
|
stopSignal,
|
|
122
122
|
onConsole: (log) => onConsoleRef.current(log),
|
|
@@ -35,7 +35,7 @@ export const createRuntimeFromPlaywright = ({
|
|
|
35
35
|
server,
|
|
36
36
|
|
|
37
37
|
// measurePerformance,
|
|
38
|
-
|
|
38
|
+
collectPerformance,
|
|
39
39
|
collectCoverage = false,
|
|
40
40
|
coverageForceIstanbul,
|
|
41
41
|
urlShouldBeCovered,
|
|
@@ -167,6 +167,39 @@ export const createRuntimeFromPlaywright = ({
|
|
|
167
167
|
return result
|
|
168
168
|
})
|
|
169
169
|
}
|
|
170
|
+
|
|
171
|
+
if (collectPerformance) {
|
|
172
|
+
resultTransformer = composeTransformer(
|
|
173
|
+
resultTransformer,
|
|
174
|
+
async (result) => {
|
|
175
|
+
const performance = await page.evaluate(
|
|
176
|
+
/* eslint-disable no-undef */
|
|
177
|
+
/* istanbul ignore next */
|
|
178
|
+
() => {
|
|
179
|
+
const { performance } = window
|
|
180
|
+
if (!performance) {
|
|
181
|
+
return null
|
|
182
|
+
}
|
|
183
|
+
const measures = {}
|
|
184
|
+
const measurePerfEntries = performance.getEntriesByType("measure")
|
|
185
|
+
measurePerfEntries.forEach((measurePerfEntry) => {
|
|
186
|
+
measures[measurePerfEntry.name] = measurePerfEntry.duration
|
|
187
|
+
})
|
|
188
|
+
return {
|
|
189
|
+
timeOrigin: performance.timeOrigin,
|
|
190
|
+
timing: performance.timing.toJSON(),
|
|
191
|
+
navigation: performance.navigation.toJSON(),
|
|
192
|
+
measures,
|
|
193
|
+
}
|
|
194
|
+
/* eslint-enable no-undef */
|
|
195
|
+
},
|
|
196
|
+
)
|
|
197
|
+
result.performance = performance
|
|
198
|
+
return result
|
|
199
|
+
},
|
|
200
|
+
)
|
|
201
|
+
}
|
|
202
|
+
|
|
170
203
|
const fileClientUrl = new URL(fileRelativeUrl, `${server.origin}/`).href
|
|
171
204
|
|
|
172
205
|
// https://github.com/GoogleChrome/puppeteer/blob/v1.4.0/docs/api.md#event-console
|
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
import v8 from "node:v8"
|
|
2
2
|
import { uneval } from "@jsenv/uneval"
|
|
3
|
+
import { startObservingPerformances } from "./node_execution_performance.js"
|
|
3
4
|
|
|
4
5
|
const ACTIONS_AVAILABLE = {
|
|
5
|
-
"execute-using-dynamic-import": async ({ fileUrl }) => {
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
"execute-using-dynamic-import": async ({ fileUrl, collectPerformance }) => {
|
|
7
|
+
const getNamespace = async () => {
|
|
8
|
+
const namespace = await import(fileUrl)
|
|
9
|
+
const namespaceResolved = {}
|
|
10
|
+
await Promise.all([
|
|
11
|
+
...Object.keys(namespace).map(async (key) => {
|
|
12
|
+
const value = await namespace[key]
|
|
13
|
+
namespaceResolved[key] = value
|
|
14
|
+
}),
|
|
15
|
+
])
|
|
16
|
+
return namespaceResolved
|
|
17
|
+
}
|
|
18
|
+
if (collectPerformance) {
|
|
19
|
+
const getPerformance = startObservingPerformances()
|
|
20
|
+
const namespace = await getNamespace()
|
|
21
|
+
const performance = await getPerformance()
|
|
22
|
+
return {
|
|
23
|
+
namespace,
|
|
24
|
+
performance,
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const namespace = await getNamespace()
|
|
28
|
+
return {
|
|
29
|
+
namespace,
|
|
30
|
+
}
|
|
15
31
|
},
|
|
16
32
|
"execute-using-require": async ({ fileUrl }) => {
|
|
17
33
|
const { createRequire } = await import("module")
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { PerformanceObserver, performance } from "node:perf_hooks"
|
|
2
|
+
|
|
3
|
+
export const startObservingPerformances = () => {
|
|
4
|
+
const measureEntries = []
|
|
5
|
+
// https://nodejs.org/dist/latest-v16.x/docs/api/perf_hooks.html
|
|
6
|
+
const perfObserver = new PerformanceObserver(
|
|
7
|
+
(
|
|
8
|
+
// https://nodejs.org/dist/latest-v16.x/docs/api/perf_hooks.html#perf_hooks_class_performanceobserverentrylist
|
|
9
|
+
list,
|
|
10
|
+
) => {
|
|
11
|
+
const perfMeasureEntries = list.getEntriesByType("measure")
|
|
12
|
+
measureEntries.push(...perfMeasureEntries)
|
|
13
|
+
},
|
|
14
|
+
)
|
|
15
|
+
perfObserver.observe({
|
|
16
|
+
entryTypes: ["measure"],
|
|
17
|
+
})
|
|
18
|
+
return async () => {
|
|
19
|
+
// wait for node to call the performance observer
|
|
20
|
+
await new Promise((resolve) => {
|
|
21
|
+
setTimeout(resolve)
|
|
22
|
+
})
|
|
23
|
+
performance.clearMarks()
|
|
24
|
+
perfObserver.disconnect()
|
|
25
|
+
return {
|
|
26
|
+
...readNodePerformance(),
|
|
27
|
+
measures: measuresFromMeasureEntries(measureEntries),
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const readNodePerformance = () => {
|
|
33
|
+
const nodePerformance = {
|
|
34
|
+
nodeTiming: asPlainObject(performance.nodeTiming),
|
|
35
|
+
timeOrigin: performance.timeOrigin,
|
|
36
|
+
eventLoopUtilization: performance.eventLoopUtilization(),
|
|
37
|
+
}
|
|
38
|
+
return nodePerformance
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// remove getters that cannot be stringified
|
|
42
|
+
const asPlainObject = (objectWithGetters) => {
|
|
43
|
+
const objectWithoutGetters = {}
|
|
44
|
+
Object.keys(objectWithGetters).forEach((key) => {
|
|
45
|
+
objectWithoutGetters[key] = objectWithGetters[key]
|
|
46
|
+
})
|
|
47
|
+
return objectWithoutGetters
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const measuresFromMeasureEntries = (measureEntries) => {
|
|
51
|
+
const measures = {}
|
|
52
|
+
// Sort to ensure measures order is predictable
|
|
53
|
+
// It seems to be already predictable on Node 16+ but
|
|
54
|
+
// it's not the case on Node 14.
|
|
55
|
+
measureEntries.sort((a, b) => {
|
|
56
|
+
return a.startTime - b.startTime
|
|
57
|
+
})
|
|
58
|
+
measureEntries.forEach(
|
|
59
|
+
(
|
|
60
|
+
// https://nodejs.org/dist/latest-v16.x/docs/api/perf_hooks.html#perf_hooks_class_performanceentry
|
|
61
|
+
perfMeasureEntry,
|
|
62
|
+
) => {
|
|
63
|
+
measures[perfMeasureEntry.name] = perfMeasureEntry.duration
|
|
64
|
+
},
|
|
65
|
+
)
|
|
66
|
+
return measures
|
|
67
|
+
}
|
|
@@ -35,10 +35,9 @@ nodeProcess.run = async ({
|
|
|
35
35
|
stopSignal,
|
|
36
36
|
onConsole,
|
|
37
37
|
|
|
38
|
-
measurePerformance,
|
|
39
|
-
collectPerformance,
|
|
40
38
|
collectCoverage = false,
|
|
41
39
|
coverageForceIstanbul,
|
|
40
|
+
collectPerformance,
|
|
42
41
|
|
|
43
42
|
debugPort,
|
|
44
43
|
debugMode,
|
|
@@ -191,9 +190,7 @@ nodeProcess.run = async ({
|
|
|
191
190
|
actionType: "execute-using-dynamic-import",
|
|
192
191
|
actionParams: {
|
|
193
192
|
fileUrl: new URL(fileRelativeUrl, rootDirectoryUrl).href,
|
|
194
|
-
measurePerformance,
|
|
195
193
|
collectPerformance,
|
|
196
|
-
collectCoverage,
|
|
197
194
|
},
|
|
198
195
|
})
|
|
199
196
|
const winner = await winnerPromise
|
|
@@ -246,7 +243,7 @@ nodeProcess.run = async ({
|
|
|
246
243
|
}
|
|
247
244
|
return {
|
|
248
245
|
status: "completed",
|
|
249
|
-
|
|
246
|
+
...value,
|
|
250
247
|
}
|
|
251
248
|
}
|
|
252
249
|
|
package/src/omega/kitchen.js
CHANGED
|
@@ -670,9 +670,11 @@ const applyReferenceEffectsOnUrlInfo = (reference, urlInfo, context) => {
|
|
|
670
670
|
}
|
|
671
671
|
urlInfo.contentType = reference.contentType
|
|
672
672
|
urlInfo.originalContent =
|
|
673
|
-
|
|
674
|
-
?
|
|
675
|
-
|
|
673
|
+
context === "build"
|
|
674
|
+
? urlInfo.originalContent === undefined
|
|
675
|
+
? reference.content
|
|
676
|
+
: urlInfo.originalContent
|
|
677
|
+
: reference.content
|
|
676
678
|
urlInfo.content = reference.content
|
|
677
679
|
}
|
|
678
680
|
if (isWebWorkerEntryPointReference(reference)) {
|
|
@@ -23,7 +23,6 @@ import { composeTwoSourcemaps } from "@jsenv/utils/sourcemap/sourcemap_compositi
|
|
|
23
23
|
import { babelPluginTransformImportMetaUrl } from "./helpers/babel_plugin_transform_import_meta_url.js"
|
|
24
24
|
import { jsenvPluginScriptTypeModuleAsClassic } from "./jsenv_plugin_script_type_module_as_classic.js"
|
|
25
25
|
import { jsenvPluginWorkersTypeModuleAsClassic } from "./jsenv_plugin_workers_type_module_as_classic.js"
|
|
26
|
-
import { jsenvPluginTopLevelAwait } from "./jsenv_plugin_top_level_await.js"
|
|
27
26
|
|
|
28
27
|
const require = createRequire(import.meta.url)
|
|
29
28
|
|
|
@@ -40,7 +39,6 @@ export const jsenvPluginAsJsClassic = ({ systemJsInjection }) => {
|
|
|
40
39
|
jsenvPluginWorkersTypeModuleAsClassic({
|
|
41
40
|
generateJsClassicFilename,
|
|
42
41
|
}),
|
|
43
|
-
jsenvPluginTopLevelAwait(),
|
|
44
42
|
]
|
|
45
43
|
}
|
|
46
44
|
|
|
@@ -31,9 +31,12 @@ export const getBaseBabelPluginStructure = ({ url, isSupported }) => {
|
|
|
31
31
|
requireBabelPlugin("@babel/plugin-proposal-unicode-property-regex")
|
|
32
32
|
}
|
|
33
33
|
if (isBabelPluginNeeded("transform-async-to-promises")) {
|
|
34
|
-
babelPluginStructure["transform-async-to-promises"] =
|
|
35
|
-
"babel-plugin-transform-async-to-promises",
|
|
36
|
-
|
|
34
|
+
babelPluginStructure["transform-async-to-promises"] = [
|
|
35
|
+
requireBabelPlugin("babel-plugin-transform-async-to-promises"),
|
|
36
|
+
{
|
|
37
|
+
topLevelAwait: "ignore", // will be handled by "jsenv:top_level_await" plugin
|
|
38
|
+
},
|
|
39
|
+
]
|
|
37
40
|
}
|
|
38
41
|
if (isBabelPluginNeeded("transform-arrow-functions")) {
|
|
39
42
|
babelPluginStructure["transform-arrow-functions"] = requireBabelPlugin(
|
|
File without changes
|
|
@@ -11,6 +11,7 @@ import { jsenvPluginCssParcel } from "./css_parcel/jsenv_plugin_css_parcel.js"
|
|
|
11
11
|
import { jsenvPluginImportAssertions } from "./import_assertions/jsenv_plugin_import_assertions.js"
|
|
12
12
|
import { jsenvPluginAsJsClassic } from "./as_js_classic/jsenv_plugin_as_js_classic.js"
|
|
13
13
|
import { jsenvPluginBabel } from "./babel/jsenv_plugin_babel.js"
|
|
14
|
+
import { jsenvPluginTopLevelAwait } from "./jsenv_plugin_top_level_await.js"
|
|
14
15
|
|
|
15
16
|
export const jsenvPluginTranspilation = ({
|
|
16
17
|
importAssertions = true,
|
|
@@ -35,6 +36,9 @@ export const jsenvPluginTranspilation = ({
|
|
|
35
36
|
...(jsModuleAsJsClassic
|
|
36
37
|
? [jsenvPluginAsJsClassic({ systemJsInjection })]
|
|
37
38
|
: []),
|
|
39
|
+
// topLevelAwait must come after js_module_as_js_classic because it's related to the module format
|
|
40
|
+
// so we want to wait to know the module format before transforming things related to top level await
|
|
41
|
+
...(topLevelAwait ? [jsenvPluginTopLevelAwait(topLevelAwait)] : []),
|
|
38
42
|
...(css ? [jsenvPluginCssParcel()] : []),
|
|
39
43
|
]
|
|
40
44
|
}
|