@jsenv/core 27.0.0-alpha.61 → 27.0.0-alpha.64
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 +3 -3
- package/dist/event_source_client.js.map +7 -8
- package/dist/html_supervisor_installer.js +1 -1
- package/dist/html_supervisor_installer.js.map +2 -2
- package/dist/s.js +626 -0
- package/dist/s.js.map +207 -0
- package/main.js +1 -0
- package/package.json +8 -8
- package/src/build/build.js +23 -8
- package/src/build/inject_global_version_mappings.js +18 -5
- package/src/build/start_build_server.js +49 -32
- package/src/dev/start_dev_server.js +11 -3
- package/src/execute/runtimes/browsers/from_playwright.js +10 -0
- package/src/execute/runtimes/node/node_process.js +8 -0
- package/src/omega/kitchen.js +57 -150
- package/src/omega/server/file_service.js +34 -17
- package/src/omega/url_graph/url_graph_load.js +10 -17
- package/src/omega/url_graph/url_info_transformations.js +1 -4
- package/src/omega/url_graph.js +6 -2
- package/src/omega/url_specifier_encoding.js +59 -0
- package/src/plugins/autoreload/dev_sse/client/event_source_client.js +7 -3
- package/src/plugins/commonjs_globals/jsenv_plugin_commonjs_globals.js +1 -1
- package/src/plugins/html_supervisor/client/html_supervisor_installer.js +1 -1
- package/src/plugins/importmap/jsenv_plugin_importmap.js +2 -4
- package/src/plugins/inject_globals/jsenv_plugin_inject_globals.js +51 -42
- package/src/plugins/inline/jsenv_plugin_data_urls.js +1 -4
- package/src/plugins/inline/jsenv_plugin_html_inline_content.js +3 -5
- package/src/plugins/inline/jsenv_plugin_inline_query_param.js +1 -4
- package/src/plugins/inline/jsenv_plugin_js_inline_content.js +1 -4
- package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +4 -0
- package/src/plugins/plugins.js +4 -1
- package/src/plugins/transpilation/as_js_classic/client/s.js +362 -807
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +28 -12
- package/src/plugins/transpilation/as_js_classic/{jsenv_plugin_workers_type_module_as_classic.js → jsenv_plugin_as_js_classic_workers.js} +2 -2
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_script_type_module_as_classic.js +165 -133
- package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +5 -2
- package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +1 -2
- package/src/plugins/transpilation/jsenv_plugin_transpilation.js +4 -1
- package/src/test/execute_plan.js +39 -14
- package/src/test/execute_test_plan.js +2 -0
- package/src/test/logs_file_execution.js +47 -38
- package/src/plugins/transpilation/as_js_classic/client/s.js.md +0 -1
- package/src/plugins/transpilation/fetch_original_url_info.js +0 -30
|
@@ -216,9 +216,14 @@ export const createRuntimeFromPlaywright = ({
|
|
|
216
216
|
},
|
|
217
217
|
})
|
|
218
218
|
cleanupCallbackList.add(removeConsoleListener)
|
|
219
|
+
const actionOperation = Abort.startOperation()
|
|
220
|
+
actionOperation.addAbortSignal(signal)
|
|
219
221
|
const winnerPromise = new Promise((resolve, reject) => {
|
|
220
222
|
raceCallbacks(
|
|
221
223
|
{
|
|
224
|
+
aborted: (cb) => {
|
|
225
|
+
return actionOperation.addAbortCallback(cb)
|
|
226
|
+
},
|
|
222
227
|
// https://github.com/GoogleChrome/puppeteer/blob/v1.4.0/docs/api.md#event-error
|
|
223
228
|
error: (cb) => {
|
|
224
229
|
return registerEvent({
|
|
@@ -317,6 +322,11 @@ export const createRuntimeFromPlaywright = ({
|
|
|
317
322
|
|
|
318
323
|
const getResult = async () => {
|
|
319
324
|
const winner = await winnerPromise
|
|
325
|
+
if (winner.name === "aborted") {
|
|
326
|
+
return {
|
|
327
|
+
status: "aborted",
|
|
328
|
+
}
|
|
329
|
+
}
|
|
320
330
|
if (winner.name === "error" || winner.name === "pageerror") {
|
|
321
331
|
const error = winner.data
|
|
322
332
|
return {
|
|
@@ -162,6 +162,9 @@ nodeProcess.run = async ({
|
|
|
162
162
|
const winnerPromise = new Promise((resolve) => {
|
|
163
163
|
raceCallbacks(
|
|
164
164
|
{
|
|
165
|
+
aborted: (cb) => {
|
|
166
|
+
return actionOperation.addAbortCallback(cb)
|
|
167
|
+
},
|
|
165
168
|
// https://nodejs.org/api/child_process.html#child_process_event_disconnect
|
|
166
169
|
// disconnect: (cb) => {
|
|
167
170
|
// return onceProcessEvent(childProcess, "disconnect", cb)
|
|
@@ -194,6 +197,11 @@ nodeProcess.run = async ({
|
|
|
194
197
|
},
|
|
195
198
|
})
|
|
196
199
|
const winner = await winnerPromise
|
|
200
|
+
if (winner.name === "aborted") {
|
|
201
|
+
return {
|
|
202
|
+
status: "aborted",
|
|
203
|
+
}
|
|
204
|
+
}
|
|
197
205
|
if (winner.name === "error") {
|
|
198
206
|
const error = winner.data
|
|
199
207
|
removeOutputListener()
|
package/src/omega/kitchen.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
urlIsInsideOf,
|
|
3
3
|
writeFileSync,
|
|
4
|
-
isFileSystemPath,
|
|
5
|
-
fileSystemPathToUrl,
|
|
6
4
|
moveUrl,
|
|
7
5
|
ensureWindowsDriveLetter,
|
|
8
6
|
} from "@jsenv/filesystem"
|
|
9
7
|
import { createDetailedMessage } from "@jsenv/logger"
|
|
10
8
|
|
|
9
|
+
import { getCallerPosition } from "@jsenv/utils/src/caller_position.js"
|
|
11
10
|
import { stringifyUrlSite } from "@jsenv/utils/urls/url_trace.js"
|
|
12
11
|
import { CONTENT_TYPE } from "@jsenv/utils/content_type/content_type.js"
|
|
13
12
|
import { normalizeUrl, setUrlFilename } from "@jsenv/utils/urls/url_utils.js"
|
|
14
13
|
|
|
15
14
|
import { createPluginController } from "../plugins/plugin_controller.js"
|
|
15
|
+
import { urlSpecifierEncoding } from "./url_specifier_encoding.js"
|
|
16
16
|
import { createUrlInfoTransformer } from "./url_graph/url_info_transformations.js"
|
|
17
17
|
import { RUNTIME_COMPAT } from "./compat/runtime_compat.js"
|
|
18
18
|
import { defaultRuntimeCompat } from "./compat/default_runtime_compat.js"
|
|
@@ -54,7 +54,7 @@ export const createKitchen = ({
|
|
|
54
54
|
scenario,
|
|
55
55
|
})
|
|
56
56
|
const jsenvDirectoryUrl = new URL(".jsenv/", rootDirectoryUrl).href
|
|
57
|
-
const
|
|
57
|
+
const kitchenContext = {
|
|
58
58
|
signal,
|
|
59
59
|
logger,
|
|
60
60
|
rootDirectoryUrl,
|
|
@@ -145,7 +145,7 @@ export const createKitchen = ({
|
|
|
145
145
|
let resolvedUrl = pluginController.callHooksUntil(
|
|
146
146
|
"resolveUrl",
|
|
147
147
|
reference,
|
|
148
|
-
|
|
148
|
+
kitchenContext,
|
|
149
149
|
)
|
|
150
150
|
if (!resolvedUrl) {
|
|
151
151
|
throw new Error(`NO_RESOLVE`)
|
|
@@ -160,7 +160,7 @@ export const createKitchen = ({
|
|
|
160
160
|
pluginController.callHooks(
|
|
161
161
|
"redirectUrl",
|
|
162
162
|
reference,
|
|
163
|
-
|
|
163
|
+
kitchenContext,
|
|
164
164
|
(returnValue) => {
|
|
165
165
|
const normalizedReturnValue = normalizeUrl(returnValue)
|
|
166
166
|
if (normalizedReturnValue === reference.url) {
|
|
@@ -173,7 +173,7 @@ export const createKitchen = ({
|
|
|
173
173
|
)
|
|
174
174
|
|
|
175
175
|
const urlInfo = urlGraph.reuseOrCreateUrlInfo(reference.url)
|
|
176
|
-
applyReferenceEffectsOnUrlInfo(reference, urlInfo,
|
|
176
|
+
applyReferenceEffectsOnUrlInfo(reference, urlInfo, kitchenContext)
|
|
177
177
|
|
|
178
178
|
const referenceUrlObject = new URL(reference.url)
|
|
179
179
|
reference.searchParams = referenceUrlObject.searchParams
|
|
@@ -187,7 +187,7 @@ export const createKitchen = ({
|
|
|
187
187
|
pluginController.callHooks(
|
|
188
188
|
"transformUrlSearchParams",
|
|
189
189
|
reference,
|
|
190
|
-
|
|
190
|
+
kitchenContext,
|
|
191
191
|
(returnValue) => {
|
|
192
192
|
Object.keys(returnValue).forEach((key) => {
|
|
193
193
|
referenceUrlObject.searchParams.set(key, returnValue[key])
|
|
@@ -198,10 +198,10 @@ export const createKitchen = ({
|
|
|
198
198
|
const returnValue = pluginController.callHooksUntil(
|
|
199
199
|
"formatUrl",
|
|
200
200
|
reference,
|
|
201
|
-
|
|
201
|
+
kitchenContext,
|
|
202
202
|
)
|
|
203
203
|
reference.generatedSpecifier = returnValue || reference.generatedUrl
|
|
204
|
-
reference.generatedSpecifier =
|
|
204
|
+
reference.generatedSpecifier = urlSpecifierEncoding.encode(reference)
|
|
205
205
|
return urlInfo
|
|
206
206
|
} catch (error) {
|
|
207
207
|
throw createResolveUrlError({
|
|
@@ -211,7 +211,7 @@ export const createKitchen = ({
|
|
|
211
211
|
})
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
|
-
|
|
214
|
+
kitchenContext.resolveReference = resolveReference
|
|
215
215
|
const urlInfoTransformer = createUrlInfoTransformer({
|
|
216
216
|
logger,
|
|
217
217
|
urlGraph,
|
|
@@ -258,7 +258,7 @@ export const createKitchen = ({
|
|
|
258
258
|
},
|
|
259
259
|
})
|
|
260
260
|
|
|
261
|
-
const fetchUrlContent = async ({ reference,
|
|
261
|
+
const fetchUrlContent = async (urlInfo, { reference, context }) => {
|
|
262
262
|
if (reference.external) {
|
|
263
263
|
urlInfo.external = true
|
|
264
264
|
return
|
|
@@ -343,40 +343,32 @@ export const createKitchen = ({
|
|
|
343
343
|
await urlInfoTransformer.initTransformations(urlInfo, context)
|
|
344
344
|
}
|
|
345
345
|
|
|
346
|
-
const _cook = async ({
|
|
347
|
-
reference,
|
|
348
|
-
urlInfo,
|
|
349
|
-
outDirectoryUrl,
|
|
346
|
+
const _cook = async (urlInfo, dishContext) => {
|
|
350
347
|
// during dev/test clientRuntimeCompat is a single runtime
|
|
351
348
|
// during build clientRuntimeCompat is runtimeCompat
|
|
352
|
-
clientRuntimeCompat = runtimeCompat
|
|
353
|
-
|
|
354
|
-
}) => {
|
|
355
|
-
baseContext.isSupportedOnCurrentClients = (feature) => {
|
|
349
|
+
const { clientRuntimeCompat = runtimeCompat } = dishContext
|
|
350
|
+
kitchenContext.isSupportedOnCurrentClients = (feature) => {
|
|
356
351
|
return RUNTIME_COMPAT.isSupported(clientRuntimeCompat, feature)
|
|
357
352
|
}
|
|
358
353
|
const context = {
|
|
359
|
-
...
|
|
360
|
-
|
|
361
|
-
outDirectoryUrl,
|
|
354
|
+
...kitchenContext,
|
|
355
|
+
...dishContext,
|
|
362
356
|
clientRuntimeCompat,
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
})
|
|
375
|
-
},
|
|
357
|
+
}
|
|
358
|
+
const { cookDuringCook = cook } = dishContext
|
|
359
|
+
context.cook = (urlInfo, nestedDishContext) => {
|
|
360
|
+
return cookDuringCook(urlInfo, {
|
|
361
|
+
outDirectoryUrl: dishContext.outDirectoryUrl,
|
|
362
|
+
clientRuntimeCompat: dishContext.clientRuntimeCompat,
|
|
363
|
+
...nestedDishContext,
|
|
364
|
+
})
|
|
365
|
+
}
|
|
366
|
+
context.fetchUrlContent = (urlInfo, { reference }) => {
|
|
367
|
+
return fetchUrlContent(urlInfo, { reference, context })
|
|
376
368
|
}
|
|
377
369
|
|
|
378
370
|
// "fetchUrlContent" hook
|
|
379
|
-
await fetchUrlContent({ reference
|
|
371
|
+
await fetchUrlContent(urlInfo, { reference: context.reference, context })
|
|
380
372
|
if (urlInfo.external) {
|
|
381
373
|
return
|
|
382
374
|
}
|
|
@@ -504,21 +496,11 @@ export const createKitchen = ({
|
|
|
504
496
|
},
|
|
505
497
|
inject: ({ trace, ...rest }) => {
|
|
506
498
|
if (trace === undefined) {
|
|
507
|
-
const {
|
|
508
|
-
Error.prepareStackTrace = (error, stack) => {
|
|
509
|
-
Error.prepareStackTrace = prepareStackTrace
|
|
510
|
-
return stack
|
|
511
|
-
}
|
|
512
|
-
const { stack } = new Error()
|
|
513
|
-
const callerCallsite = stack[1]
|
|
514
|
-
const fileName = callerCallsite.getFileName()
|
|
499
|
+
const { url, line, column } = getCallerPosition()
|
|
515
500
|
trace = stringifyUrlSite({
|
|
516
|
-
url
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
: fileName,
|
|
520
|
-
line: callerCallsite.getLineNumber(),
|
|
521
|
-
column: callerCallsite.getColumnNumber(),
|
|
501
|
+
url,
|
|
502
|
+
line,
|
|
503
|
+
column,
|
|
522
504
|
})
|
|
523
505
|
}
|
|
524
506
|
return addReference({
|
|
@@ -558,7 +540,7 @@ export const createKitchen = ({
|
|
|
558
540
|
} catch (error) {
|
|
559
541
|
throw createTransformUrlContentError({
|
|
560
542
|
pluginController,
|
|
561
|
-
reference,
|
|
543
|
+
reference: context.reference,
|
|
562
544
|
urlInfo,
|
|
563
545
|
error,
|
|
564
546
|
})
|
|
@@ -581,7 +563,7 @@ export const createKitchen = ({
|
|
|
581
563
|
} catch (error) {
|
|
582
564
|
throw createFinalizeUrlContentError({
|
|
583
565
|
pluginController,
|
|
584
|
-
reference,
|
|
566
|
+
reference: context.reference,
|
|
585
567
|
urlInfo,
|
|
586
568
|
error,
|
|
587
569
|
})
|
|
@@ -609,44 +591,30 @@ export const createKitchen = ({
|
|
|
609
591
|
},
|
|
610
592
|
)
|
|
611
593
|
}
|
|
612
|
-
const cook = memoizeCook(async (
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
if (!writeGeneratedFiles || !outDirectoryUrl) {
|
|
617
|
-
return
|
|
618
|
-
}
|
|
619
|
-
const { generatedUrl } = urlInfo
|
|
620
|
-
// writing result inside ".jsenv" directory (debug purposes)
|
|
621
|
-
if (!generatedUrl || !generatedUrl.startsWith("file:")) {
|
|
622
|
-
return
|
|
623
|
-
}
|
|
624
|
-
// use writeSync to avoid concurrency on writing the file
|
|
625
|
-
const write = gotError ? writeFileSync : writeFileSync
|
|
626
|
-
write(new URL(generatedUrl), urlInfo.content)
|
|
627
|
-
const { sourcemapGeneratedUrl, sourcemap } = urlInfo
|
|
628
|
-
if (sourcemapGeneratedUrl && sourcemap) {
|
|
629
|
-
write(
|
|
630
|
-
new URL(sourcemapGeneratedUrl),
|
|
631
|
-
JSON.stringify(sourcemap, null, " "),
|
|
632
|
-
)
|
|
633
|
-
}
|
|
594
|
+
const cook = memoizeCook(async (urlInfo, context) => {
|
|
595
|
+
if (!writeGeneratedFiles || !context.outDirectoryUrl) {
|
|
596
|
+
await _cook(urlInfo, context)
|
|
597
|
+
return
|
|
634
598
|
}
|
|
635
|
-
|
|
599
|
+
// writing result inside ".jsenv" directory (debug purposes)
|
|
636
600
|
try {
|
|
637
|
-
await _cook(
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
601
|
+
await _cook(urlInfo, context)
|
|
602
|
+
} finally {
|
|
603
|
+
const { generatedUrl } = urlInfo
|
|
604
|
+
if (generatedUrl && generatedUrl.startsWith("file:")) {
|
|
605
|
+
writeFileSync(new URL(generatedUrl), urlInfo.content)
|
|
606
|
+
const { sourcemapGeneratedUrl, sourcemap } = urlInfo
|
|
607
|
+
if (sourcemapGeneratedUrl && sourcemap) {
|
|
608
|
+
writeFileSync(
|
|
609
|
+
new URL(sourcemapGeneratedUrl),
|
|
610
|
+
JSON.stringify(sourcemap, null, " "),
|
|
611
|
+
)
|
|
612
|
+
}
|
|
613
|
+
}
|
|
646
614
|
}
|
|
647
615
|
})
|
|
648
|
-
|
|
649
|
-
|
|
616
|
+
kitchenContext.fetchUrlContent = fetchUrlContent
|
|
617
|
+
kitchenContext.cook = cook
|
|
650
618
|
|
|
651
619
|
const prepareEntryPoint = (params) => {
|
|
652
620
|
const entryReference = createReference(params)
|
|
@@ -665,7 +633,7 @@ export const createKitchen = ({
|
|
|
665
633
|
urlInfoTransformer,
|
|
666
634
|
rootDirectoryUrl,
|
|
667
635
|
jsenvDirectoryUrl,
|
|
668
|
-
|
|
636
|
+
kitchenContext,
|
|
669
637
|
cook,
|
|
670
638
|
prepareEntryPoint,
|
|
671
639
|
injectReference,
|
|
@@ -674,8 +642,7 @@ export const createKitchen = ({
|
|
|
674
642
|
|
|
675
643
|
const memoizeCook = (cook) => {
|
|
676
644
|
const pendingDishes = new Map()
|
|
677
|
-
return async (
|
|
678
|
-
const { urlInfo } = params
|
|
645
|
+
return async (urlInfo, context) => {
|
|
679
646
|
const { url, modifiedTimestamp } = urlInfo
|
|
680
647
|
const pendingDish = pendingDishes.get(url)
|
|
681
648
|
if (pendingDish) {
|
|
@@ -690,7 +657,7 @@ const memoizeCook = (cook) => {
|
|
|
690
657
|
pendingDishes.delete(url)
|
|
691
658
|
}
|
|
692
659
|
const timestamp = Date.now()
|
|
693
|
-
const promise = cook(
|
|
660
|
+
const promise = cook(urlInfo, context)
|
|
694
661
|
pendingDishes.set(url, {
|
|
695
662
|
timestamp,
|
|
696
663
|
promise,
|
|
@@ -844,66 +811,6 @@ const determineFileUrlForOutDirectory = ({ urlInfo, context }) => {
|
|
|
844
811
|
})
|
|
845
812
|
}
|
|
846
813
|
|
|
847
|
-
const urlSpecifierFormat = {
|
|
848
|
-
encode: (reference) => {
|
|
849
|
-
const { generatedSpecifier } = reference
|
|
850
|
-
if (generatedSpecifier.then) {
|
|
851
|
-
return generatedSpecifier.then((value) => {
|
|
852
|
-
reference.generatedSpecifier = value
|
|
853
|
-
return urlSpecifierFormat.encode(reference)
|
|
854
|
-
})
|
|
855
|
-
}
|
|
856
|
-
// allow plugin to return a function to bypas default formatting
|
|
857
|
-
// (which is to use JSON.stringify when url is referenced inside js)
|
|
858
|
-
if (typeof generatedSpecifier === "function") {
|
|
859
|
-
return generatedSpecifier()
|
|
860
|
-
}
|
|
861
|
-
const formatter = formatters[reference.type]
|
|
862
|
-
const value = formatter
|
|
863
|
-
? formatter.encode(generatedSpecifier)
|
|
864
|
-
: generatedSpecifier
|
|
865
|
-
if (reference.escape) {
|
|
866
|
-
return reference.escape(value)
|
|
867
|
-
}
|
|
868
|
-
return value
|
|
869
|
-
},
|
|
870
|
-
decode: (reference) => {
|
|
871
|
-
const formatter = formatters[reference.type]
|
|
872
|
-
return formatter
|
|
873
|
-
? formatter.decode(reference.generatedSpecifier)
|
|
874
|
-
: reference.generatedSpecifier
|
|
875
|
-
},
|
|
876
|
-
}
|
|
877
|
-
const formatters = {
|
|
878
|
-
"js_import_export": { encode: JSON.stringify, decode: JSON.parse },
|
|
879
|
-
"js_url_specifier": { encode: JSON.stringify, decode: JSON.parse },
|
|
880
|
-
"css_@import": { encode: JSON.stringify, code: JSON.stringify },
|
|
881
|
-
// https://github.com/webpack-contrib/css-loader/pull/627/files
|
|
882
|
-
"css_url": {
|
|
883
|
-
encode: (url) => {
|
|
884
|
-
// If url is already wrapped in quotes, remove them
|
|
885
|
-
url = formatters.css_url.decode(url)
|
|
886
|
-
// Should url be wrapped?
|
|
887
|
-
// See https://drafts.csswg.org/css-values-3/#urls
|
|
888
|
-
if (/["'() \t\n]/.test(url)) {
|
|
889
|
-
return `"${url.replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`
|
|
890
|
-
}
|
|
891
|
-
return url
|
|
892
|
-
},
|
|
893
|
-
decode: (url) => {
|
|
894
|
-
const firstChar = url[0]
|
|
895
|
-
const lastChar = url[url.length - 1]
|
|
896
|
-
if (firstChar === `"` && lastChar === `"`) {
|
|
897
|
-
return url.slice(1, -1)
|
|
898
|
-
}
|
|
899
|
-
if (firstChar === `'` && lastChar === `'`) {
|
|
900
|
-
return url.slice(1, -1)
|
|
901
|
-
}
|
|
902
|
-
return url
|
|
903
|
-
},
|
|
904
|
-
},
|
|
905
|
-
}
|
|
906
|
-
|
|
907
814
|
// import { getOriginalPosition } from "@jsenv/core/src/utils/sourcemap/original_position.js"
|
|
908
815
|
// const getUrlSite = async (
|
|
909
816
|
// urlInfo,
|
|
@@ -44,24 +44,32 @@ export const createFileService = ({
|
|
|
44
44
|
if (responseFromPlugin) {
|
|
45
45
|
return responseFromPlugin
|
|
46
46
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
47
|
+
let reference
|
|
48
|
+
const parentUrl = inferParentFromRequest(request, rootDirectoryUrl)
|
|
49
|
+
if (parentUrl) {
|
|
50
|
+
reference = urlGraph.inferReference(request.ressource, parentUrl)
|
|
51
|
+
}
|
|
52
|
+
if (!reference) {
|
|
53
|
+
const entryPoint = kitchen.prepareEntryPoint({
|
|
54
|
+
trace: parentUrl || rootDirectoryUrl,
|
|
55
|
+
parentUrl: parentUrl || rootDirectoryUrl,
|
|
56
|
+
type: "entry_point",
|
|
57
|
+
specifier: request.ressource,
|
|
58
|
+
})
|
|
59
|
+
reference = entryPoint[0]
|
|
60
|
+
}
|
|
61
|
+
const urlInfo = urlGraph.reuseOrCreateUrlInfo(reference.url)
|
|
62
|
+
|
|
52
63
|
const ifNoneMatch = request.headers["if-none-match"]
|
|
53
64
|
if (ifNoneMatch && urlInfo.contentEtag === ifNoneMatch) {
|
|
54
65
|
return {
|
|
55
66
|
status: 304,
|
|
56
67
|
headers: {
|
|
57
68
|
"cache-control": `private,max-age=0,must-revalidate`,
|
|
69
|
+
...urlInfo.responseHeaders,
|
|
58
70
|
},
|
|
59
71
|
}
|
|
60
72
|
}
|
|
61
|
-
const referenceFromGraph = urlGraph.inferReference(
|
|
62
|
-
reference.url,
|
|
63
|
-
reference.parentUrl,
|
|
64
|
-
)
|
|
65
73
|
try {
|
|
66
74
|
// urlInfo objects are reused, they must be "reset" before cooking them again
|
|
67
75
|
if (
|
|
@@ -76,20 +84,21 @@ export const createFileService = ({
|
|
|
76
84
|
urlInfo.type = null
|
|
77
85
|
urlInfo.subtype = null
|
|
78
86
|
urlInfo.timing = {}
|
|
87
|
+
urlInfo.responseHeaders = {}
|
|
79
88
|
}
|
|
80
89
|
const { runtimeName, runtimeVersion } = parseUserAgentHeader(
|
|
81
90
|
request.headers["user-agent"],
|
|
82
91
|
)
|
|
83
|
-
await kitchen.cook({
|
|
84
|
-
|
|
85
|
-
|
|
92
|
+
await kitchen.cook(urlInfo, {
|
|
93
|
+
request,
|
|
94
|
+
reference,
|
|
95
|
+
clientRuntimeCompat: {
|
|
96
|
+
[runtimeName]: runtimeVersion,
|
|
97
|
+
},
|
|
86
98
|
outDirectoryUrl:
|
|
87
99
|
scenario === "dev"
|
|
88
100
|
? `${rootDirectoryUrl}.jsenv/${runtimeName}@${runtimeVersion}/`
|
|
89
101
|
: `${rootDirectoryUrl}.jsenv/${scenario}/${runtimeName}@${runtimeVersion}/`,
|
|
90
|
-
clientRuntimeCompat: {
|
|
91
|
-
[runtimeName]: runtimeVersion,
|
|
92
|
-
},
|
|
93
102
|
})
|
|
94
103
|
let { response, contentType, content, contentEtag } = urlInfo
|
|
95
104
|
if (response) {
|
|
@@ -103,6 +112,7 @@ export const createFileService = ({
|
|
|
103
112
|
"content-length": Buffer.byteLength(content),
|
|
104
113
|
"cache-control": `private,max-age=0,must-revalidate`,
|
|
105
114
|
"eTag": contentEtag,
|
|
115
|
+
...urlInfo.responseHeaders,
|
|
106
116
|
},
|
|
107
117
|
body: content,
|
|
108
118
|
timing: urlInfo.timing,
|
|
@@ -167,7 +177,6 @@ export const createFileService = ({
|
|
|
167
177
|
}
|
|
168
178
|
return async (request) => {
|
|
169
179
|
let response = await getResponse(request)
|
|
170
|
-
|
|
171
180
|
return response
|
|
172
181
|
}
|
|
173
182
|
}
|
|
@@ -175,7 +184,15 @@ export const createFileService = ({
|
|
|
175
184
|
const inferParentFromRequest = (request, rootDirectoryUrl) => {
|
|
176
185
|
const { referer } = request.headers
|
|
177
186
|
if (!referer) {
|
|
178
|
-
return
|
|
187
|
+
return null
|
|
188
|
+
}
|
|
189
|
+
const refererUrlObject = new URL(referer)
|
|
190
|
+
refererUrlObject.searchParams.delete("hmr")
|
|
191
|
+
refererUrlObject.searchParams.delete("v")
|
|
192
|
+
const { pathname, search } = refererUrlObject
|
|
193
|
+
if (pathname.startsWith("/@fs/")) {
|
|
194
|
+
const fsRootRelativeUrl = pathname.slice("/@fs/".length)
|
|
195
|
+
return `file:///${fsRootRelativeUrl}${search}`
|
|
179
196
|
}
|
|
180
197
|
return moveUrl({
|
|
181
198
|
url: referer,
|
|
@@ -5,32 +5,31 @@ export const loadUrlGraph = async ({
|
|
|
5
5
|
urlGraph,
|
|
6
6
|
kitchen,
|
|
7
7
|
startLoading,
|
|
8
|
+
writeGeneratedFiles,
|
|
8
9
|
outDirectoryUrl,
|
|
9
10
|
clientRuntimeCompat,
|
|
10
11
|
}) => {
|
|
11
|
-
if (outDirectoryUrl) {
|
|
12
|
+
if (writeGeneratedFiles && outDirectoryUrl) {
|
|
12
13
|
await ensureEmptyDirectory(outDirectoryUrl)
|
|
13
14
|
}
|
|
14
15
|
const promises = []
|
|
15
16
|
const promiseMap = new Map()
|
|
16
|
-
const cook = (
|
|
17
|
+
const cook = (urlInfo, context) => {
|
|
17
18
|
const promiseFromData = promiseMap.get(urlInfo)
|
|
18
19
|
if (promiseFromData) return promiseFromData
|
|
19
|
-
const promise = _cook({
|
|
20
|
-
urlInfo,
|
|
20
|
+
const promise = _cook(urlInfo, {
|
|
21
21
|
outDirectoryUrl,
|
|
22
22
|
clientRuntimeCompat,
|
|
23
|
-
...
|
|
23
|
+
...context,
|
|
24
24
|
})
|
|
25
25
|
promises.push(promise)
|
|
26
26
|
promiseMap.set(urlInfo, promise)
|
|
27
27
|
return promise
|
|
28
28
|
}
|
|
29
|
-
const _cook = async (
|
|
30
|
-
await kitchen.cook({
|
|
31
|
-
urlInfo,
|
|
29
|
+
const _cook = async (urlInfo, context) => {
|
|
30
|
+
await kitchen.cook(urlInfo, {
|
|
32
31
|
cookDuringCook: cook,
|
|
33
|
-
...
|
|
32
|
+
...context,
|
|
34
33
|
})
|
|
35
34
|
const { references } = urlInfo
|
|
36
35
|
references.forEach((reference) => {
|
|
@@ -46,10 +45,7 @@ export const loadUrlGraph = async ({
|
|
|
46
45
|
const referencedUrlInfo = urlGraph.reuseOrCreateUrlInfo(
|
|
47
46
|
reference.generatedUrl,
|
|
48
47
|
)
|
|
49
|
-
cook({
|
|
50
|
-
reference,
|
|
51
|
-
urlInfo: referencedUrlInfo,
|
|
52
|
-
})
|
|
48
|
+
cook(referencedUrlInfo, { reference })
|
|
53
49
|
})
|
|
54
50
|
}
|
|
55
51
|
startLoading(
|
|
@@ -61,10 +57,7 @@ export const loadUrlGraph = async ({
|
|
|
61
57
|
specifier,
|
|
62
58
|
})
|
|
63
59
|
entryUrlInfo.data.isEntryPoint = true
|
|
64
|
-
cook({
|
|
65
|
-
reference: entryReference,
|
|
66
|
-
urlInfo: entryUrlInfo,
|
|
67
|
-
})
|
|
60
|
+
cook(entryUrlInfo, { reference: entryReference })
|
|
68
61
|
return [entryReference, entryUrlInfo]
|
|
69
62
|
},
|
|
70
63
|
)
|
|
@@ -91,10 +91,7 @@ export const createUrlInfoTransformer = ({
|
|
|
91
91
|
specifierColumn: column,
|
|
92
92
|
})
|
|
93
93
|
try {
|
|
94
|
-
await context.cook({
|
|
95
|
-
reference: sourcemapReference,
|
|
96
|
-
urlInfo: sourcemapUrlInfo,
|
|
97
|
-
})
|
|
94
|
+
await context.cook(sourcemapUrlInfo, { reference: sourcemapReference })
|
|
98
95
|
const sourcemap = JSON.parse(sourcemapUrlInfo.content)
|
|
99
96
|
urlInfo.sourcemap = normalizeSourcemap(urlInfo, sourcemap)
|
|
100
97
|
} catch (e) {
|
package/src/omega/url_graph.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { urlToRelativeUrl } from "@jsenv/filesystem"
|
|
2
|
+
import { urlSpecifierEncoding } from "./url_specifier_encoding.js"
|
|
2
3
|
|
|
3
4
|
export const createUrlGraph = ({
|
|
4
5
|
clientFileChangeCallbackList,
|
|
@@ -23,13 +24,15 @@ export const createUrlGraph = ({
|
|
|
23
24
|
urlInfos[url] = urlInfo
|
|
24
25
|
return urlInfo
|
|
25
26
|
}
|
|
26
|
-
const inferReference = (
|
|
27
|
+
const inferReference = (specifier, parentUrl) => {
|
|
27
28
|
const parentUrlInfo = urlInfos[parentUrl]
|
|
28
29
|
if (!parentUrlInfo) {
|
|
29
30
|
return null
|
|
30
31
|
}
|
|
31
32
|
const firstReferenceOnThatUrl = parentUrlInfo.references.find(
|
|
32
|
-
(reference) =>
|
|
33
|
+
(reference) => {
|
|
34
|
+
return urlSpecifierEncoding.decode(reference) === specifier
|
|
35
|
+
},
|
|
33
36
|
)
|
|
34
37
|
return firstReferenceOnThatUrl
|
|
35
38
|
}
|
|
@@ -192,5 +195,6 @@ const createUrlInfo = (url) => {
|
|
|
192
195
|
sourcemap: null,
|
|
193
196
|
sourcemapReference: null,
|
|
194
197
|
timing: {},
|
|
198
|
+
responseHeaders: {},
|
|
195
199
|
}
|
|
196
200
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export const urlSpecifierEncoding = {
|
|
2
|
+
encode: (reference) => {
|
|
3
|
+
const { generatedSpecifier } = reference
|
|
4
|
+
if (generatedSpecifier.then) {
|
|
5
|
+
return generatedSpecifier.then((value) => {
|
|
6
|
+
reference.generatedSpecifier = value
|
|
7
|
+
return urlSpecifierEncoding.encode(reference)
|
|
8
|
+
})
|
|
9
|
+
}
|
|
10
|
+
// allow plugin to return a function to bypas default formatting
|
|
11
|
+
// (which is to use JSON.stringify when url is referenced inside js)
|
|
12
|
+
if (typeof generatedSpecifier === "function") {
|
|
13
|
+
return generatedSpecifier()
|
|
14
|
+
}
|
|
15
|
+
const formatter = formatters[reference.type]
|
|
16
|
+
const value = formatter
|
|
17
|
+
? formatter.encode(generatedSpecifier)
|
|
18
|
+
: generatedSpecifier
|
|
19
|
+
if (reference.escape) {
|
|
20
|
+
return reference.escape(value)
|
|
21
|
+
}
|
|
22
|
+
return value
|
|
23
|
+
},
|
|
24
|
+
decode: (reference) => {
|
|
25
|
+
const formatter = formatters[reference.type]
|
|
26
|
+
return formatter
|
|
27
|
+
? formatter.decode(reference.generatedSpecifier)
|
|
28
|
+
: reference.generatedSpecifier
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
const formatters = {
|
|
32
|
+
"js_import_export": { encode: JSON.stringify, decode: JSON.parse },
|
|
33
|
+
"js_url_specifier": { encode: JSON.stringify, decode: JSON.parse },
|
|
34
|
+
"css_@import": { encode: JSON.stringify, code: JSON.stringify },
|
|
35
|
+
// https://github.com/webpack-contrib/css-loader/pull/627/files
|
|
36
|
+
"css_url": {
|
|
37
|
+
encode: (url) => {
|
|
38
|
+
// If url is already wrapped in quotes, remove them
|
|
39
|
+
url = formatters.css_url.decode(url)
|
|
40
|
+
// Should url be wrapped?
|
|
41
|
+
// See https://drafts.csswg.org/css-values-3/#urls
|
|
42
|
+
if (/["'() \t\n]/.test(url)) {
|
|
43
|
+
return `"${url.replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`
|
|
44
|
+
}
|
|
45
|
+
return url
|
|
46
|
+
},
|
|
47
|
+
decode: (url) => {
|
|
48
|
+
const firstChar = url[0]
|
|
49
|
+
const lastChar = url[url.length - 1]
|
|
50
|
+
if (firstChar === `"` && lastChar === `"`) {
|
|
51
|
+
return url.slice(1, -1)
|
|
52
|
+
}
|
|
53
|
+
if (firstChar === `'` && lastChar === `'`) {
|
|
54
|
+
return url.slice(1, -1)
|
|
55
|
+
}
|
|
56
|
+
return url
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
}
|