@jsenv/core 28.0.0 → 28.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/controllable_child_process.mjs +1 -2
- package/dist/controllable_worker_thread.mjs +1 -2
- package/dist/js/autoreload.js +27 -11
- package/dist/js/execute_using_dynamic_import.js +804 -1
- package/dist/js/script_type_module_supervisor.js +129 -0
- package/dist/js/supervisor.js +921 -0
- package/dist/js/{wrapper.mjs → ws.js} +0 -0
- package/dist/main.js +555 -616
- package/package.json +13 -13
- package/readme.md +2 -2
- package/src/build/build.js +8 -8
- package/src/build/inject_global_version_mappings.js +3 -3
- package/src/build/{resync_ressource_hints.js → resync_resource_hints.js} +10 -12
- package/src/build/start_build_server.js +4 -7
- package/src/dev/start_dev_server.js +2 -2
- package/src/execute/execute.js +1 -1
- package/src/execute/run.js +26 -38
- package/src/execute/runtimes/browsers/from_playwright.js +51 -77
- package/src/execute/runtimes/node/node_child_process.js +36 -36
- package/src/execute/runtimes/node/node_worker_thread.js +36 -36
- package/src/omega/kitchen.js +33 -14
- package/src/omega/omega_server.js +2 -2
- package/src/omega/server/file_service.js +5 -5
- package/src/omega/url_graph/url_graph_load.js +4 -4
- package/src/omega/url_graph/url_info_transformations.js +8 -1
- package/src/omega/url_graph.js +3 -3
- package/src/plugins/autoreload/client/reload.js +22 -9
- package/src/plugins/autoreload/jsenv_plugin_autoreload_client.js +5 -5
- package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +3 -3
- package/src/plugins/autoreload/jsenv_plugin_hmr.js +1 -1
- package/src/plugins/explorer/jsenv_plugin_explorer.js +1 -1
- package/src/plugins/import_meta_hot/html_hot_dependencies.js +6 -6
- package/src/plugins/importmap/jsenv_plugin_importmap.js +5 -3
- package/src/plugins/inject_globals/inject_globals.js +3 -3
- package/src/plugins/inline/jsenv_plugin_data_urls.js +1 -1
- package/src/plugins/inline/jsenv_plugin_html_inline_content.js +10 -5
- package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +2 -13
- package/src/plugins/plugin_controller.js +2 -2
- package/src/plugins/plugins.js +5 -5
- package/src/plugins/server_events/jsenv_plugin_server_events_client_injection.js +4 -4
- package/src/plugins/supervisor/client/script_type_module_supervisor.js +108 -0
- package/src/plugins/supervisor/client/supervisor.js +921 -0
- package/src/plugins/{html_supervisor/jsenv_plugin_html_supervisor.js → supervisor/jsenv_plugin_supervisor.js} +131 -105
- package/src/plugins/toolbar/client/execution/toolbar_execution.js +1 -1
- package/src/plugins/toolbar/jsenv_plugin_toolbar.js +5 -5
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +9 -7
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_html.js +8 -7
- package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +13 -7
- package/src/plugins/transpilation/babel/new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js +6 -4
- package/src/plugins/transpilation/jsenv_plugin_transpilation.js +4 -2
- package/src/plugins/url_analysis/html/html_urls.js +13 -12
- package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +1 -1
- package/src/test/coverage/babel_plugin_instrument.js +1 -35
- package/src/test/coverage/empty_coverage_factory.js +1 -1
- package/src/test/execute_plan.js +7 -3
- package/src/test/execute_test_plan.js +2 -1
- package/src/test/logs_file_execution.js +49 -8
- package/dist/js/html_supervisor_installer.js +0 -1091
- package/dist/js/html_supervisor_setup.js +0 -89
- package/dist/js/uneval.js +0 -804
- package/src/plugins/html_supervisor/client/error_formatter.js +0 -426
- package/src/plugins/html_supervisor/client/error_in_notification.js +0 -21
- package/src/plugins/html_supervisor/client/error_overlay.js +0 -191
- package/src/plugins/html_supervisor/client/html_supervisor_installer.js +0 -315
- package/src/plugins/html_supervisor/client/html_supervisor_setup.js +0 -89
- package/src/plugins/html_supervisor/client/perf_browser.js +0 -17
- package/src/plugins/html_supervisor/client/uneval_exception.js +0 -8
|
@@ -185,7 +185,13 @@ nodeChildProcess.run = async ({
|
|
|
185
185
|
resolve,
|
|
186
186
|
)
|
|
187
187
|
})
|
|
188
|
-
const
|
|
188
|
+
const result = {
|
|
189
|
+
status: "executing",
|
|
190
|
+
errors: [],
|
|
191
|
+
namespace: null,
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const writeResult = async () => {
|
|
189
195
|
actionOperation.throwIfAborted()
|
|
190
196
|
await childProcessReadyPromise
|
|
191
197
|
actionOperation.throwIfAborted()
|
|
@@ -207,28 +213,27 @@ nodeChildProcess.run = async ({
|
|
|
207
213
|
})
|
|
208
214
|
const winner = await winnerPromise
|
|
209
215
|
if (winner.name === "aborted") {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}
|
|
216
|
+
result.status = "aborted"
|
|
217
|
+
return
|
|
213
218
|
}
|
|
214
219
|
if (winner.name === "error") {
|
|
215
220
|
const error = winner.data
|
|
216
221
|
removeOutputListener()
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
}
|
|
222
|
+
result.status = "errored"
|
|
223
|
+
result.errors.push(error)
|
|
224
|
+
return
|
|
221
225
|
}
|
|
222
226
|
if (winner.name === "exit") {
|
|
223
227
|
const { code } = winner.data
|
|
224
228
|
await cleanup("process exit")
|
|
225
229
|
if (code === 12) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
230
|
+
result.status = "errored"
|
|
231
|
+
result.errors.push(
|
|
232
|
+
new Error(
|
|
229
233
|
`node process exited with 12 (the forked child process wanted to use a non-available port for debug)`,
|
|
230
234
|
),
|
|
231
|
-
|
|
235
|
+
)
|
|
236
|
+
return
|
|
232
237
|
}
|
|
233
238
|
if (
|
|
234
239
|
code === null ||
|
|
@@ -237,41 +242,36 @@ nodeChildProcess.run = async ({
|
|
|
237
242
|
code === EXIT_CODES.SIGTERM ||
|
|
238
243
|
code === EXIT_CODES.SIGABORT
|
|
239
244
|
) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
}
|
|
245
|
+
result.status = "errored"
|
|
246
|
+
result.errors.push(new Error(`node process exited during execution`))
|
|
247
|
+
return
|
|
244
248
|
}
|
|
245
249
|
// process.exit(1) in child process or process.exitCode = 1 + process.exit()
|
|
246
250
|
// means there was an error even if we don't know exactly what.
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
251
|
+
result.status = "errored"
|
|
252
|
+
result.errors.push(
|
|
253
|
+
new Error(`node process exited with code ${code} during execution`),
|
|
254
|
+
)
|
|
255
|
+
return
|
|
253
256
|
}
|
|
254
257
|
const { status, value } = winner.data
|
|
255
258
|
if (status === "action-failed") {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
return {
|
|
262
|
-
status: "completed",
|
|
263
|
-
...value,
|
|
259
|
+
result.status = "errored"
|
|
260
|
+
result.errors.push(value)
|
|
261
|
+
return
|
|
264
262
|
}
|
|
263
|
+
const { namespace, performance, coverage } = value
|
|
264
|
+
result.status = "completed"
|
|
265
|
+
result.namespace = namespace
|
|
266
|
+
result.performance = performance
|
|
267
|
+
result.coverage = coverage
|
|
265
268
|
}
|
|
266
269
|
|
|
267
|
-
let result
|
|
268
270
|
try {
|
|
269
|
-
|
|
271
|
+
await writeResult()
|
|
270
272
|
} catch (e) {
|
|
271
|
-
result =
|
|
272
|
-
|
|
273
|
-
error: e,
|
|
274
|
-
}
|
|
273
|
+
result.status = "errored"
|
|
274
|
+
result.errors.push(e)
|
|
275
275
|
}
|
|
276
276
|
if (keepRunning) {
|
|
277
277
|
stopSignal.notify = stop
|
|
@@ -137,7 +137,13 @@ nodeWorkerThread.run = async ({
|
|
|
137
137
|
)
|
|
138
138
|
})
|
|
139
139
|
|
|
140
|
-
const
|
|
140
|
+
const result = {
|
|
141
|
+
status: "executing",
|
|
142
|
+
errors: [],
|
|
143
|
+
namespace: null,
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const writeResult = async () => {
|
|
141
147
|
actionOperation.throwIfAborted()
|
|
142
148
|
await workerThreadReadyPromise
|
|
143
149
|
actionOperation.throwIfAborted()
|
|
@@ -159,28 +165,27 @@ nodeWorkerThread.run = async ({
|
|
|
159
165
|
})
|
|
160
166
|
const winner = await winnerPromise
|
|
161
167
|
if (winner.name === "aborted") {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
168
|
+
result.status = "aborted"
|
|
169
|
+
return
|
|
165
170
|
}
|
|
166
171
|
if (winner.name === "error") {
|
|
167
172
|
const error = winner.data
|
|
168
173
|
removeOutputListener()
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
174
|
+
result.status = "errored"
|
|
175
|
+
result.errors.push(error)
|
|
176
|
+
return
|
|
173
177
|
}
|
|
174
178
|
if (winner.name === "exit") {
|
|
175
179
|
const { code } = winner.data
|
|
176
180
|
await cleanup("process exit")
|
|
177
181
|
if (code === 12) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
182
|
+
result.status = "errored"
|
|
183
|
+
result.errors.push(
|
|
184
|
+
new Error(
|
|
181
185
|
`node process exited with 12 (the forked child process wanted to use a non-available port for debug)`,
|
|
182
186
|
),
|
|
183
|
-
|
|
187
|
+
)
|
|
188
|
+
return
|
|
184
189
|
}
|
|
185
190
|
if (
|
|
186
191
|
code === null ||
|
|
@@ -189,44 +194,39 @@ nodeWorkerThread.run = async ({
|
|
|
189
194
|
code === EXIT_CODES.SIGTERM ||
|
|
190
195
|
code === EXIT_CODES.SIGABORT
|
|
191
196
|
) {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
197
|
+
result.status = "errored"
|
|
198
|
+
result.errors.push(
|
|
199
|
+
new Error(`node worker thread exited during execution`),
|
|
200
|
+
)
|
|
201
|
+
return
|
|
196
202
|
}
|
|
197
203
|
// process.exit(1) in child process or process.exitCode = 1 + process.exit()
|
|
198
204
|
// means there was an error even if we don't know exactly what.
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
205
|
+
result.status = "errored"
|
|
206
|
+
result.errors.push(
|
|
207
|
+
new Error(
|
|
202
208
|
`node worker thread exited with code ${code} during execution`,
|
|
203
209
|
),
|
|
204
|
-
|
|
210
|
+
)
|
|
205
211
|
}
|
|
206
212
|
const { status, value } = winner.data
|
|
207
213
|
if (status === "action-failed") {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}
|
|
214
|
+
result.status = "errored"
|
|
215
|
+
result.errors.push(value)
|
|
216
|
+
return
|
|
212
217
|
}
|
|
213
218
|
const { namespace, performance, coverage } = value
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
coverage,
|
|
219
|
-
}
|
|
219
|
+
result.status = "completed"
|
|
220
|
+
result.namespace = namespace
|
|
221
|
+
result.performance = performance
|
|
222
|
+
result.coverage = coverage
|
|
220
223
|
}
|
|
221
224
|
|
|
222
|
-
let result
|
|
223
225
|
try {
|
|
224
|
-
|
|
226
|
+
await writeResult()
|
|
225
227
|
} catch (e) {
|
|
226
|
-
result =
|
|
227
|
-
|
|
228
|
-
error: e,
|
|
229
|
-
}
|
|
228
|
+
result.status = "errored"
|
|
229
|
+
result.errors.push(e)
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
if (keepRunning) {
|
package/src/omega/kitchen.js
CHANGED
|
@@ -88,7 +88,8 @@ export const createKitchen = ({
|
|
|
88
88
|
isEntryPoint = false,
|
|
89
89
|
isInline = false,
|
|
90
90
|
injected = false,
|
|
91
|
-
|
|
91
|
+
isResourceHint = false,
|
|
92
|
+
dependsOnPackageJson,
|
|
92
93
|
content,
|
|
93
94
|
contentType,
|
|
94
95
|
assert,
|
|
@@ -125,8 +126,9 @@ export const createKitchen = ({
|
|
|
125
126
|
isEntryPoint,
|
|
126
127
|
isInline,
|
|
127
128
|
injected,
|
|
128
|
-
|
|
129
|
-
|
|
129
|
+
isResourceHint,
|
|
130
|
+
dependsOnPackageJson,
|
|
131
|
+
// for inline resources the reference contains the content
|
|
130
132
|
content,
|
|
131
133
|
contentType,
|
|
132
134
|
timing: {},
|
|
@@ -141,12 +143,12 @@ export const createKitchen = ({
|
|
|
141
143
|
newReference.original = reference.original || reference
|
|
142
144
|
// newReference.isEntryPoint = reference.isEntryPoint
|
|
143
145
|
}
|
|
144
|
-
const resolveReference = (reference) => {
|
|
146
|
+
const resolveReference = (reference, context = kitchenContext) => {
|
|
145
147
|
try {
|
|
146
148
|
let resolvedUrl = pluginController.callHooksUntil(
|
|
147
149
|
"resolveUrl",
|
|
148
150
|
reference,
|
|
149
|
-
|
|
151
|
+
context,
|
|
150
152
|
)
|
|
151
153
|
if (!resolvedUrl) {
|
|
152
154
|
throw new Error(`NO_RESOLVE`)
|
|
@@ -156,7 +158,7 @@ export const createKitchen = ({
|
|
|
156
158
|
pluginController.callHooks(
|
|
157
159
|
"redirectUrl",
|
|
158
160
|
reference,
|
|
159
|
-
|
|
161
|
+
context,
|
|
160
162
|
(returnValue) => {
|
|
161
163
|
const normalizedReturnValue = normalizeUrl(returnValue)
|
|
162
164
|
if (normalizedReturnValue === reference.url) {
|
|
@@ -176,18 +178,18 @@ export const createKitchen = ({
|
|
|
176
178
|
}
|
|
177
179
|
|
|
178
180
|
const urlInfo = urlGraph.reuseOrCreateUrlInfo(reference.url)
|
|
179
|
-
applyReferenceEffectsOnUrlInfo(reference, urlInfo,
|
|
181
|
+
applyReferenceEffectsOnUrlInfo(reference, urlInfo, context)
|
|
180
182
|
|
|
181
183
|
// This hook must touch reference.generatedUrl, NOT reference.url
|
|
182
184
|
// And this is because this hook inject query params used to:
|
|
183
185
|
// - bypass browser cache (?v)
|
|
184
186
|
// - convey information (?hmr)
|
|
185
|
-
// But do not represent an other
|
|
186
|
-
// the same
|
|
187
|
+
// But do not represent an other resource, it is considered as
|
|
188
|
+
// the same resource under the hood
|
|
187
189
|
pluginController.callHooks(
|
|
188
190
|
"transformUrlSearchParams",
|
|
189
191
|
reference,
|
|
190
|
-
|
|
192
|
+
context,
|
|
191
193
|
(returnValue) => {
|
|
192
194
|
Object.keys(returnValue).forEach((key) => {
|
|
193
195
|
referenceUrlObject.searchParams.set(key, returnValue[key])
|
|
@@ -198,7 +200,7 @@ export const createKitchen = ({
|
|
|
198
200
|
const returnValue = pluginController.callHooksUntil(
|
|
199
201
|
"formatUrl",
|
|
200
202
|
reference,
|
|
201
|
-
|
|
203
|
+
context,
|
|
202
204
|
)
|
|
203
205
|
reference.generatedSpecifier = returnValue || reference.generatedUrl
|
|
204
206
|
reference.generatedSpecifier = urlSpecifierEncoding.encode(reference)
|
|
@@ -384,7 +386,7 @@ export const createKitchen = ({
|
|
|
384
386
|
...props,
|
|
385
387
|
})
|
|
386
388
|
references.push(reference)
|
|
387
|
-
const referencedUrlInfo = resolveReference(reference)
|
|
389
|
+
const referencedUrlInfo = resolveReference(reference, context)
|
|
388
390
|
return [reference, referencedUrlInfo]
|
|
389
391
|
}
|
|
390
392
|
const referenceUtils = {
|
|
@@ -458,7 +460,7 @@ export const createKitchen = ({
|
|
|
458
460
|
})
|
|
459
461
|
references[index] = nextReference
|
|
460
462
|
mutateReference(previousReference, nextReference)
|
|
461
|
-
const newUrlInfo = resolveReference(nextReference)
|
|
463
|
+
const newUrlInfo = resolveReference(nextReference, context)
|
|
462
464
|
const currentUrlInfo = context.urlGraph.getUrlInfo(
|
|
463
465
|
currentReference.url,
|
|
464
466
|
)
|
|
@@ -675,7 +677,10 @@ export const createKitchen = ({
|
|
|
675
677
|
await context.fetchUrlContent(originalUrlInfo, {
|
|
676
678
|
reference: originalReference,
|
|
677
679
|
})
|
|
678
|
-
if (
|
|
680
|
+
if (
|
|
681
|
+
originalUrlInfo.dependents.size === 0
|
|
682
|
+
// && context.scenarios.build
|
|
683
|
+
) {
|
|
679
684
|
context.urlGraph.deleteUrlInfo(originalUrlInfo.url)
|
|
680
685
|
}
|
|
681
686
|
return originalUrlInfo
|
|
@@ -772,6 +777,20 @@ const applyReferenceEffectsOnUrlInfo = (reference, urlInfo, context) => {
|
|
|
772
777
|
: reference.content
|
|
773
778
|
urlInfo.content = reference.content
|
|
774
779
|
}
|
|
780
|
+
|
|
781
|
+
const { dependsOnPackageJson } = reference
|
|
782
|
+
urlInfo.dependsOnPackageJson = dependsOnPackageJson
|
|
783
|
+
const relatedUrlInfos = context.urlGraph.getRelatedUrlInfos(
|
|
784
|
+
reference.parentUrl,
|
|
785
|
+
)
|
|
786
|
+
relatedUrlInfos.forEach((relatedUrlInfo) => {
|
|
787
|
+
if (relatedUrlInfo.dependsOnPackageJson) {
|
|
788
|
+
// the url may depend due to an other reference
|
|
789
|
+
// in that case keep dependsOnPackageJson to true
|
|
790
|
+
return
|
|
791
|
+
}
|
|
792
|
+
relatedUrlInfo.dependsOnPackageJson = dependsOnPackageJson
|
|
793
|
+
})
|
|
775
794
|
}
|
|
776
795
|
|
|
777
796
|
const adjustUrlSite = (urlInfo, { urlGraph, url, line, column }) => {
|
|
@@ -30,7 +30,7 @@ export const startOmegaServer = async ({
|
|
|
30
30
|
|
|
31
31
|
plugins,
|
|
32
32
|
urlAnalysis,
|
|
33
|
-
|
|
33
|
+
supervisor,
|
|
34
34
|
nodeEsmResolution,
|
|
35
35
|
fileSystemMagicResolution,
|
|
36
36
|
transpilation,
|
|
@@ -92,7 +92,7 @@ export const startOmegaServer = async ({
|
|
|
92
92
|
|
|
93
93
|
plugins,
|
|
94
94
|
urlAnalysis,
|
|
95
|
-
|
|
95
|
+
supervisor,
|
|
96
96
|
nodeEsmResolution,
|
|
97
97
|
fileSystemMagicResolution,
|
|
98
98
|
transpilation,
|
|
@@ -25,7 +25,7 @@ export const createFileService = ({
|
|
|
25
25
|
|
|
26
26
|
plugins,
|
|
27
27
|
urlAnalysis,
|
|
28
|
-
|
|
28
|
+
supervisor,
|
|
29
29
|
nodeEsmResolution,
|
|
30
30
|
fileSystemMagicResolution,
|
|
31
31
|
transpilation,
|
|
@@ -118,7 +118,7 @@ export const createFileService = ({
|
|
|
118
118
|
runtimeCompat,
|
|
119
119
|
|
|
120
120
|
urlAnalysis,
|
|
121
|
-
|
|
121
|
+
supervisor,
|
|
122
122
|
nodeEsmResolution,
|
|
123
123
|
fileSystemMagicResolution,
|
|
124
124
|
transpilation,
|
|
@@ -185,7 +185,7 @@ export const createFileService = ({
|
|
|
185
185
|
|
|
186
186
|
return async (request) => {
|
|
187
187
|
// serve file inside ".jsenv" directory
|
|
188
|
-
const requestFileUrl = new URL(request.
|
|
188
|
+
const requestFileUrl = new URL(request.resource.slice(1), rootDirectoryUrl)
|
|
189
189
|
.href
|
|
190
190
|
if (urlIsInsideOf(requestFileUrl, jsenvDirectoryUrl)) {
|
|
191
191
|
return fetchFileSystem(requestFileUrl, {
|
|
@@ -206,14 +206,14 @@ export const createFileService = ({
|
|
|
206
206
|
let reference
|
|
207
207
|
const parentUrl = inferParentFromRequest(request, rootDirectoryUrl)
|
|
208
208
|
if (parentUrl) {
|
|
209
|
-
reference = urlGraph.inferReference(request.
|
|
209
|
+
reference = urlGraph.inferReference(request.resource, parentUrl)
|
|
210
210
|
}
|
|
211
211
|
if (!reference) {
|
|
212
212
|
const entryPoint = kitchen.injectReference({
|
|
213
213
|
trace: { message: parentUrl || rootDirectoryUrl },
|
|
214
214
|
parentUrl: parentUrl || rootDirectoryUrl,
|
|
215
215
|
type: "http_request",
|
|
216
|
-
specifier: request.
|
|
216
|
+
specifier: request.resource,
|
|
217
217
|
})
|
|
218
218
|
reference = entryPoint[0]
|
|
219
219
|
}
|
|
@@ -31,11 +31,11 @@ export const loadUrlGraph = async ({
|
|
|
31
31
|
})
|
|
32
32
|
const { references } = urlInfo
|
|
33
33
|
references.forEach((reference) => {
|
|
34
|
-
// we don't cook
|
|
35
|
-
// because they might refer to
|
|
34
|
+
// we don't cook resource hints
|
|
35
|
+
// because they might refer to resource that will be modified during build
|
|
36
36
|
// It also means something else have to reference that url in order to cook it
|
|
37
|
-
// so that the preload is deleted by "
|
|
38
|
-
if (reference.
|
|
37
|
+
// so that the preload is deleted by "resync_resource_hints.js" otherwise
|
|
38
|
+
if (reference.isResourceHint) {
|
|
39
39
|
return
|
|
40
40
|
}
|
|
41
41
|
// we use reference.generatedUrl to mimic what a browser would do:
|
|
@@ -81,6 +81,9 @@ export const createUrlInfoTransformer = ({
|
|
|
81
81
|
if (!SOURCEMAP.enabledOnContentType(urlInfo.contentType)) {
|
|
82
82
|
return
|
|
83
83
|
}
|
|
84
|
+
if (urlInfo.generatedUrl.startsWith("data:")) {
|
|
85
|
+
return
|
|
86
|
+
}
|
|
84
87
|
// sourcemap is a special kind of reference:
|
|
85
88
|
// It's a reference to a content generated dynamically the content itself.
|
|
86
89
|
// For this reason sourcemap are not added to urlInfo.references
|
|
@@ -173,7 +176,11 @@ export const createUrlInfoTransformer = ({
|
|
|
173
176
|
if (transformations) {
|
|
174
177
|
await applyIntermediateTransformations(urlInfo, transformations)
|
|
175
178
|
}
|
|
176
|
-
if (
|
|
179
|
+
if (
|
|
180
|
+
sourcemapsEnabled &&
|
|
181
|
+
urlInfo.sourcemap &&
|
|
182
|
+
!urlInfo.generatedUrl.startsWith("data:")
|
|
183
|
+
) {
|
|
177
184
|
// during build this function can be called after the file is cooked
|
|
178
185
|
// - to update content and sourcemap after "optimize" hook
|
|
179
186
|
// - to inject versioning into the entry point content
|
package/src/omega/url_graph.js
CHANGED
|
@@ -70,10 +70,10 @@ export const createUrlGraph = ({
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
references.forEach((reference) => {
|
|
73
|
-
if (reference.
|
|
74
|
-
//
|
|
73
|
+
if (reference.isResourceHint) {
|
|
74
|
+
// resource hint are a special kind of reference.
|
|
75
75
|
// They are a sort of weak reference to an url.
|
|
76
|
-
// We ignore them so that url referenced only by
|
|
76
|
+
// We ignore them so that url referenced only by resource hints
|
|
77
77
|
// have url.dependents.size === 0 and can be considered as not used
|
|
78
78
|
// It means html won't consider url referenced solely
|
|
79
79
|
// by <link> as dependency and it's fine
|
|
@@ -32,7 +32,20 @@ export const getDOMNodesUsingUrl = (urlToReload) => {
|
|
|
32
32
|
nodes.push({
|
|
33
33
|
node,
|
|
34
34
|
reload: () => {
|
|
35
|
-
|
|
35
|
+
if (node.nodeName === "SCRIPT") {
|
|
36
|
+
const copy = document.createElement("script")
|
|
37
|
+
Array.from(node.attributes).forEach((attribute) => {
|
|
38
|
+
copy.setAttribute(attribute.nodeName, attribute.nodeValue)
|
|
39
|
+
})
|
|
40
|
+
copy.src = injectQuery(node.src, { hmr: Date.now() })
|
|
41
|
+
if (node.parentNode) {
|
|
42
|
+
node.parentNode.replaceChild(copy, node)
|
|
43
|
+
} else {
|
|
44
|
+
document.body.appendChild(copy)
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
node[attributeName] = injectQuery(attribute, { hmr: Date.now() })
|
|
48
|
+
}
|
|
36
49
|
},
|
|
37
50
|
})
|
|
38
51
|
}
|
|
@@ -46,24 +59,24 @@ export const getDOMNodesUsingUrl = (urlToReload) => {
|
|
|
46
59
|
})
|
|
47
60
|
Array.from(document.querySelectorAll("script")).forEach((script) => {
|
|
48
61
|
visitNodeAttributeAsUrl(script, "src")
|
|
49
|
-
const
|
|
50
|
-
if (
|
|
51
|
-
const
|
|
62
|
+
const inlinedFromSrc = script.getAttribute("inlined-from-src")
|
|
63
|
+
if (inlinedFromSrc) {
|
|
64
|
+
const inlinedFromUrl = new URL(inlinedFromSrc, window.location.origin)
|
|
52
65
|
.href
|
|
53
|
-
if (shouldReloadUrl(
|
|
66
|
+
if (shouldReloadUrl(inlinedFromUrl)) {
|
|
54
67
|
nodes.push({
|
|
55
68
|
node: script,
|
|
56
69
|
reload: () =>
|
|
57
|
-
window.
|
|
70
|
+
window.__supervisor__.reloadSupervisedScript({
|
|
58
71
|
type: script.type,
|
|
59
|
-
src:
|
|
72
|
+
src: inlinedFromSrc,
|
|
60
73
|
}),
|
|
61
74
|
})
|
|
62
75
|
}
|
|
63
76
|
}
|
|
64
77
|
})
|
|
65
|
-
// There is no real need to update a.href because the
|
|
66
|
-
// But in a scenario where the
|
|
78
|
+
// There is no real need to update a.href because the resource will be fetched when clicked.
|
|
79
|
+
// But in a scenario where the resource was already visited and is in browser cache, adding
|
|
67
80
|
// the dynamic query param ensure the cache is invalidated
|
|
68
81
|
Array.from(document.querySelectorAll("a")).forEach((a) => {
|
|
69
82
|
visitNodeAttributeAsUrl(a, "href")
|
|
@@ -13,7 +13,7 @@ export const jsenvPluginAutoreloadClient = () => {
|
|
|
13
13
|
|
|
14
14
|
return {
|
|
15
15
|
name: "jsenv:autoreload_client",
|
|
16
|
-
appliesDuring:
|
|
16
|
+
appliesDuring: "dev",
|
|
17
17
|
transformUrlContent: {
|
|
18
18
|
html: (htmlUrlInfo, context) => {
|
|
19
19
|
const htmlAst = parseHtmlString(htmlUrlInfo.content)
|
|
@@ -25,11 +25,11 @@ export const jsenvPluginAutoreloadClient = () => {
|
|
|
25
25
|
injectScriptNodeAsEarlyAsPossible(
|
|
26
26
|
htmlAst,
|
|
27
27
|
createHtmlNode({
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"injected-by": "jsenv:autoreload_client",
|
|
28
|
+
tagName: "script",
|
|
29
|
+
type: "module",
|
|
30
|
+
src: autoreloadClientReference.generatedSpecifier,
|
|
32
31
|
}),
|
|
32
|
+
"jsenv:autoreload_client",
|
|
33
33
|
)
|
|
34
34
|
const htmlModified = stringifyHtmlAst(htmlAst)
|
|
35
35
|
return {
|
|
@@ -6,7 +6,7 @@ export const jsenvPluginAutoreloadServer = ({
|
|
|
6
6
|
}) => {
|
|
7
7
|
return {
|
|
8
8
|
name: "jsenv:autoreload_server",
|
|
9
|
-
appliesDuring:
|
|
9
|
+
appliesDuring: "dev",
|
|
10
10
|
serverEvents: {
|
|
11
11
|
reload: ({ sendServerEvent, rootDirectoryUrl, urlGraph }) => {
|
|
12
12
|
const formatUrlForClient = (url) => {
|
|
@@ -140,7 +140,7 @@ export const jsenvPluginAutoreloadServer = ({
|
|
|
140
140
|
const cause = `following files are no longer referenced: ${prunedUrlInfos.map(
|
|
141
141
|
(prunedUrlInfo) => formatUrlForClient(prunedUrlInfo.url),
|
|
142
142
|
)}`
|
|
143
|
-
// now check if we can hot update the main
|
|
143
|
+
// now check if we can hot update the main resource
|
|
144
144
|
// then if we can hot update all dependencies
|
|
145
145
|
if (mainHotUpdate.declined) {
|
|
146
146
|
notifyDeclined({
|
|
@@ -179,7 +179,7 @@ export const jsenvPluginAutoreloadServer = ({
|
|
|
179
179
|
},
|
|
180
180
|
},
|
|
181
181
|
serve: (request, { rootDirectoryUrl, urlGraph }) => {
|
|
182
|
-
if (request.
|
|
182
|
+
if (request.pathname === "/__graph__") {
|
|
183
183
|
const graphJson = JSON.stringify(urlGraph.toJSON(rootDirectoryUrl))
|
|
184
184
|
return {
|
|
185
185
|
status: 200,
|
|
@@ -11,7 +11,7 @@ export const jsenvPluginExplorer = ({ groups }) => {
|
|
|
11
11
|
name: "jsenv:explorer",
|
|
12
12
|
appliesDuring: "dev",
|
|
13
13
|
serve: async (request, { rootDirectoryUrl }) => {
|
|
14
|
-
if (request.
|
|
14
|
+
if (request.pathname !== "/") {
|
|
15
15
|
return null
|
|
16
16
|
}
|
|
17
17
|
const associationsForExplorable = {}
|
|
@@ -48,7 +48,7 @@ export const collectHotDataFromHtmlAst = (htmlAst) => {
|
|
|
48
48
|
})
|
|
49
49
|
visitUrlSpecifierAttribute({
|
|
50
50
|
node,
|
|
51
|
-
attributeName: "
|
|
51
|
+
attributeName: "inlined-from-href",
|
|
52
52
|
hotAccepted,
|
|
53
53
|
})
|
|
54
54
|
}
|
|
@@ -60,7 +60,7 @@ export const collectHotDataFromHtmlAst = (htmlAst) => {
|
|
|
60
60
|
})
|
|
61
61
|
visitUrlSpecifierAttribute({
|
|
62
62
|
node,
|
|
63
|
-
attributeName: "
|
|
63
|
+
attributeName: "inlined-from-src",
|
|
64
64
|
hotAccepted,
|
|
65
65
|
})
|
|
66
66
|
}
|
|
@@ -119,14 +119,14 @@ const getNodeContext = (node) => {
|
|
|
119
119
|
|
|
120
120
|
const htmlNodeCanHotReload = (node) => {
|
|
121
121
|
if (node.nodeName === "link") {
|
|
122
|
-
const { isStylesheet,
|
|
122
|
+
const { isStylesheet, isResourceHint, rel } = analyzeLinkNode(node)
|
|
123
123
|
if (isStylesheet) {
|
|
124
124
|
// stylesheets can be hot replaced by default
|
|
125
125
|
return true
|
|
126
126
|
}
|
|
127
|
-
if (
|
|
128
|
-
// for
|
|
129
|
-
// but we won't do anything (if the
|
|
127
|
+
if (isResourceHint) {
|
|
128
|
+
// for resource hints html will be notified the underlying resource has changed
|
|
129
|
+
// but we won't do anything (if the resource is deleted we should?)
|
|
130
130
|
return true
|
|
131
131
|
}
|
|
132
132
|
if (rel === "icon") {
|
|
@@ -134,7 +134,8 @@ export const jsenvPluginImportmap = () => {
|
|
|
134
134
|
})
|
|
135
135
|
setHtmlNodeText(importmap, inlineImportmapUrlInfo.content)
|
|
136
136
|
setHtmlNodeAttributes(importmap, {
|
|
137
|
-
"
|
|
137
|
+
"jsenv-plugin-owner": "jsenv:importmap",
|
|
138
|
+
"jsenv-plugin-action": "content_cooked",
|
|
138
139
|
})
|
|
139
140
|
onHtmlImportmapParsed(
|
|
140
141
|
JSON.parse(inlineImportmapUrlInfo.content),
|
|
@@ -162,8 +163,9 @@ export const jsenvPluginImportmap = () => {
|
|
|
162
163
|
setHtmlNodeText(importmap, importmapUrlInfo.content)
|
|
163
164
|
setHtmlNodeAttributes(importmap, {
|
|
164
165
|
"src": undefined,
|
|
165
|
-
"
|
|
166
|
-
"
|
|
166
|
+
"jsenv-plugin-owner": "jsenv:importmap",
|
|
167
|
+
"jsenv-plugin-action": "inlined",
|
|
168
|
+
"inlined-from-src": src,
|
|
167
169
|
})
|
|
168
170
|
|
|
169
171
|
const { line, column, lineEnd, columnEnd, isOriginal } =
|