@jsenv/core 27.0.0-alpha.63 → 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.
Files changed (39) hide show
  1. package/dist/html_supervisor_installer.js +1 -1
  2. package/dist/html_supervisor_installer.js.map +2 -2
  3. package/dist/s.js +626 -0
  4. package/dist/s.js.map +207 -0
  5. package/main.js +1 -0
  6. package/package.json +6 -6
  7. package/src/build/build.js +23 -8
  8. package/src/build/inject_global_version_mappings.js +18 -5
  9. package/src/build/start_build_server.js +38 -29
  10. package/src/dev/start_dev_server.js +1 -1
  11. package/src/execute/runtimes/browsers/from_playwright.js +10 -0
  12. package/src/execute/runtimes/node/node_process.js +8 -0
  13. package/src/omega/kitchen.js +52 -134
  14. package/src/omega/server/file_service.js +34 -17
  15. package/src/omega/url_graph/url_graph_load.js +10 -17
  16. package/src/omega/url_graph/url_info_transformations.js +1 -4
  17. package/src/omega/url_graph.js +6 -2
  18. package/src/omega/url_specifier_encoding.js +59 -0
  19. package/src/plugins/html_supervisor/client/html_supervisor_installer.js +1 -1
  20. package/src/plugins/importmap/jsenv_plugin_importmap.js +2 -4
  21. package/src/plugins/inject_globals/jsenv_plugin_inject_globals.js +51 -42
  22. package/src/plugins/inline/jsenv_plugin_data_urls.js +1 -4
  23. package/src/plugins/inline/jsenv_plugin_html_inline_content.js +3 -5
  24. package/src/plugins/inline/jsenv_plugin_inline_query_param.js +1 -4
  25. package/src/plugins/inline/jsenv_plugin_js_inline_content.js +1 -4
  26. package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +4 -0
  27. package/src/plugins/plugins.js +4 -1
  28. package/src/plugins/transpilation/as_js_classic/client/s.js +362 -807
  29. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +28 -12
  30. package/src/plugins/transpilation/as_js_classic/{jsenv_plugin_workers_type_module_as_classic.js → jsenv_plugin_as_js_classic_workers.js} +2 -2
  31. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_script_type_module_as_classic.js +165 -133
  32. package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +5 -2
  33. package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +1 -2
  34. package/src/plugins/transpilation/jsenv_plugin_transpilation.js +4 -1
  35. package/src/test/execute_plan.js +32 -13
  36. package/src/test/execute_test_plan.js +2 -0
  37. package/src/test/logs_file_execution.js +47 -38
  38. package/src/plugins/transpilation/as_js_classic/client/s.js.md +0 -1
  39. package/src/plugins/transpilation/fetch_original_url_info.js +0 -30
@@ -12,6 +12,7 @@ import { CONTENT_TYPE } from "@jsenv/utils/content_type/content_type.js"
12
12
  import { normalizeUrl, setUrlFilename } from "@jsenv/utils/urls/url_utils.js"
13
13
 
14
14
  import { createPluginController } from "../plugins/plugin_controller.js"
15
+ import { urlSpecifierEncoding } from "./url_specifier_encoding.js"
15
16
  import { createUrlInfoTransformer } from "./url_graph/url_info_transformations.js"
16
17
  import { RUNTIME_COMPAT } from "./compat/runtime_compat.js"
17
18
  import { defaultRuntimeCompat } from "./compat/default_runtime_compat.js"
@@ -53,7 +54,7 @@ export const createKitchen = ({
53
54
  scenario,
54
55
  })
55
56
  const jsenvDirectoryUrl = new URL(".jsenv/", rootDirectoryUrl).href
56
- const baseContext = {
57
+ const kitchenContext = {
57
58
  signal,
58
59
  logger,
59
60
  rootDirectoryUrl,
@@ -144,7 +145,7 @@ export const createKitchen = ({
144
145
  let resolvedUrl = pluginController.callHooksUntil(
145
146
  "resolveUrl",
146
147
  reference,
147
- baseContext,
148
+ kitchenContext,
148
149
  )
149
150
  if (!resolvedUrl) {
150
151
  throw new Error(`NO_RESOLVE`)
@@ -159,7 +160,7 @@ export const createKitchen = ({
159
160
  pluginController.callHooks(
160
161
  "redirectUrl",
161
162
  reference,
162
- baseContext,
163
+ kitchenContext,
163
164
  (returnValue) => {
164
165
  const normalizedReturnValue = normalizeUrl(returnValue)
165
166
  if (normalizedReturnValue === reference.url) {
@@ -172,7 +173,7 @@ export const createKitchen = ({
172
173
  )
173
174
 
174
175
  const urlInfo = urlGraph.reuseOrCreateUrlInfo(reference.url)
175
- applyReferenceEffectsOnUrlInfo(reference, urlInfo, baseContext)
176
+ applyReferenceEffectsOnUrlInfo(reference, urlInfo, kitchenContext)
176
177
 
177
178
  const referenceUrlObject = new URL(reference.url)
178
179
  reference.searchParams = referenceUrlObject.searchParams
@@ -186,7 +187,7 @@ export const createKitchen = ({
186
187
  pluginController.callHooks(
187
188
  "transformUrlSearchParams",
188
189
  reference,
189
- baseContext,
190
+ kitchenContext,
190
191
  (returnValue) => {
191
192
  Object.keys(returnValue).forEach((key) => {
192
193
  referenceUrlObject.searchParams.set(key, returnValue[key])
@@ -197,10 +198,10 @@ export const createKitchen = ({
197
198
  const returnValue = pluginController.callHooksUntil(
198
199
  "formatUrl",
199
200
  reference,
200
- baseContext,
201
+ kitchenContext,
201
202
  )
202
203
  reference.generatedSpecifier = returnValue || reference.generatedUrl
203
- reference.generatedSpecifier = urlSpecifierFormat.encode(reference)
204
+ reference.generatedSpecifier = urlSpecifierEncoding.encode(reference)
204
205
  return urlInfo
205
206
  } catch (error) {
206
207
  throw createResolveUrlError({
@@ -210,7 +211,7 @@ export const createKitchen = ({
210
211
  })
211
212
  }
212
213
  }
213
- baseContext.resolveReference = resolveReference
214
+ kitchenContext.resolveReference = resolveReference
214
215
  const urlInfoTransformer = createUrlInfoTransformer({
215
216
  logger,
216
217
  urlGraph,
@@ -257,7 +258,7 @@ export const createKitchen = ({
257
258
  },
258
259
  })
259
260
 
260
- const fetchUrlContent = async ({ reference, urlInfo, context }) => {
261
+ const fetchUrlContent = async (urlInfo, { reference, context }) => {
261
262
  if (reference.external) {
262
263
  urlInfo.external = true
263
264
  return
@@ -342,40 +343,32 @@ export const createKitchen = ({
342
343
  await urlInfoTransformer.initTransformations(urlInfo, context)
343
344
  }
344
345
 
345
- const _cook = async ({
346
- reference,
347
- urlInfo,
348
- outDirectoryUrl,
346
+ const _cook = async (urlInfo, dishContext) => {
349
347
  // during dev/test clientRuntimeCompat is a single runtime
350
348
  // during build clientRuntimeCompat is runtimeCompat
351
- clientRuntimeCompat = runtimeCompat,
352
- cookDuringCook = cook,
353
- }) => {
354
- baseContext.isSupportedOnCurrentClients = (feature) => {
349
+ const { clientRuntimeCompat = runtimeCompat } = dishContext
350
+ kitchenContext.isSupportedOnCurrentClients = (feature) => {
355
351
  return RUNTIME_COMPAT.isSupported(clientRuntimeCompat, feature)
356
352
  }
357
353
  const context = {
358
- ...baseContext,
359
- reference,
360
- outDirectoryUrl,
354
+ ...kitchenContext,
355
+ ...dishContext,
361
356
  clientRuntimeCompat,
362
- cook: (params) => {
363
- return cookDuringCook({
364
- outDirectoryUrl,
365
- clientRuntimeCompat,
366
- ...params,
367
- })
368
- },
369
- fetchUrlContent: (params) => {
370
- return fetchUrlContent({
371
- context,
372
- ...params,
373
- })
374
- },
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 })
375
368
  }
376
369
 
377
370
  // "fetchUrlContent" hook
378
- await fetchUrlContent({ reference, urlInfo, context })
371
+ await fetchUrlContent(urlInfo, { reference: context.reference, context })
379
372
  if (urlInfo.external) {
380
373
  return
381
374
  }
@@ -547,7 +540,7 @@ export const createKitchen = ({
547
540
  } catch (error) {
548
541
  throw createTransformUrlContentError({
549
542
  pluginController,
550
- reference,
543
+ reference: context.reference,
551
544
  urlInfo,
552
545
  error,
553
546
  })
@@ -570,7 +563,7 @@ export const createKitchen = ({
570
563
  } catch (error) {
571
564
  throw createFinalizeUrlContentError({
572
565
  pluginController,
573
- reference,
566
+ reference: context.reference,
574
567
  urlInfo,
575
568
  error,
576
569
  })
@@ -598,44 +591,30 @@ export const createKitchen = ({
598
591
  },
599
592
  )
600
593
  }
601
- const cook = memoizeCook(async ({ urlInfo, outDirectoryUrl, ...rest }) => {
602
- outDirectoryUrl = outDirectoryUrl ? String(outDirectoryUrl) : undefined
603
-
604
- const writeFiles = ({ gotError }) => {
605
- if (!writeGeneratedFiles || !outDirectoryUrl) {
606
- return
607
- }
608
- const { generatedUrl } = urlInfo
609
- // writing result inside ".jsenv" directory (debug purposes)
610
- if (!generatedUrl || !generatedUrl.startsWith("file:")) {
611
- return
612
- }
613
- // use writeSync to avoid concurrency on writing the file
614
- const write = gotError ? writeFileSync : writeFileSync
615
- write(new URL(generatedUrl), urlInfo.content)
616
- const { sourcemapGeneratedUrl, sourcemap } = urlInfo
617
- if (sourcemapGeneratedUrl && sourcemap) {
618
- write(
619
- new URL(sourcemapGeneratedUrl),
620
- JSON.stringify(sourcemap, null, " "),
621
- )
622
- }
594
+ const cook = memoizeCook(async (urlInfo, context) => {
595
+ if (!writeGeneratedFiles || !context.outDirectoryUrl) {
596
+ await _cook(urlInfo, context)
597
+ return
623
598
  }
624
-
599
+ // writing result inside ".jsenv" directory (debug purposes)
625
600
  try {
626
- await _cook({
627
- urlInfo,
628
- outDirectoryUrl,
629
- ...rest,
630
- })
631
- writeFiles({ gotError: false })
632
- } catch (e) {
633
- writeFiles({ gotError: true })
634
- throw e
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
+ }
635
614
  }
636
615
  })
637
-
638
- baseContext.cook = cook
616
+ kitchenContext.fetchUrlContent = fetchUrlContent
617
+ kitchenContext.cook = cook
639
618
 
640
619
  const prepareEntryPoint = (params) => {
641
620
  const entryReference = createReference(params)
@@ -654,7 +633,7 @@ export const createKitchen = ({
654
633
  urlInfoTransformer,
655
634
  rootDirectoryUrl,
656
635
  jsenvDirectoryUrl,
657
- baseContext,
636
+ kitchenContext,
658
637
  cook,
659
638
  prepareEntryPoint,
660
639
  injectReference,
@@ -663,8 +642,7 @@ export const createKitchen = ({
663
642
 
664
643
  const memoizeCook = (cook) => {
665
644
  const pendingDishes = new Map()
666
- return async (params) => {
667
- const { urlInfo } = params
645
+ return async (urlInfo, context) => {
668
646
  const { url, modifiedTimestamp } = urlInfo
669
647
  const pendingDish = pendingDishes.get(url)
670
648
  if (pendingDish) {
@@ -679,7 +657,7 @@ const memoizeCook = (cook) => {
679
657
  pendingDishes.delete(url)
680
658
  }
681
659
  const timestamp = Date.now()
682
- const promise = cook(params)
660
+ const promise = cook(urlInfo, context)
683
661
  pendingDishes.set(url, {
684
662
  timestamp,
685
663
  promise,
@@ -833,66 +811,6 @@ const determineFileUrlForOutDirectory = ({ urlInfo, context }) => {
833
811
  })
834
812
  }
835
813
 
836
- const urlSpecifierFormat = {
837
- encode: (reference) => {
838
- const { generatedSpecifier } = reference
839
- if (generatedSpecifier.then) {
840
- return generatedSpecifier.then((value) => {
841
- reference.generatedSpecifier = value
842
- return urlSpecifierFormat.encode(reference)
843
- })
844
- }
845
- // allow plugin to return a function to bypas default formatting
846
- // (which is to use JSON.stringify when url is referenced inside js)
847
- if (typeof generatedSpecifier === "function") {
848
- return generatedSpecifier()
849
- }
850
- const formatter = formatters[reference.type]
851
- const value = formatter
852
- ? formatter.encode(generatedSpecifier)
853
- : generatedSpecifier
854
- if (reference.escape) {
855
- return reference.escape(value)
856
- }
857
- return value
858
- },
859
- decode: (reference) => {
860
- const formatter = formatters[reference.type]
861
- return formatter
862
- ? formatter.decode(reference.generatedSpecifier)
863
- : reference.generatedSpecifier
864
- },
865
- }
866
- const formatters = {
867
- "js_import_export": { encode: JSON.stringify, decode: JSON.parse },
868
- "js_url_specifier": { encode: JSON.stringify, decode: JSON.parse },
869
- "css_@import": { encode: JSON.stringify, code: JSON.stringify },
870
- // https://github.com/webpack-contrib/css-loader/pull/627/files
871
- "css_url": {
872
- encode: (url) => {
873
- // If url is already wrapped in quotes, remove them
874
- url = formatters.css_url.decode(url)
875
- // Should url be wrapped?
876
- // See https://drafts.csswg.org/css-values-3/#urls
877
- if (/["'() \t\n]/.test(url)) {
878
- return `"${url.replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`
879
- }
880
- return url
881
- },
882
- decode: (url) => {
883
- const firstChar = url[0]
884
- const lastChar = url[url.length - 1]
885
- if (firstChar === `"` && lastChar === `"`) {
886
- return url.slice(1, -1)
887
- }
888
- if (firstChar === `'` && lastChar === `'`) {
889
- return url.slice(1, -1)
890
- }
891
- return url
892
- },
893
- },
894
- }
895
-
896
814
  // import { getOriginalPosition } from "@jsenv/core/src/utils/sourcemap/original_position.js"
897
815
  // const getUrlSite = async (
898
816
  // urlInfo,
@@ -44,24 +44,32 @@ export const createFileService = ({
44
44
  if (responseFromPlugin) {
45
45
  return responseFromPlugin
46
46
  }
47
- const [reference, urlInfo] = kitchen.prepareEntryPoint({
48
- parentUrl: inferParentFromRequest(request, rootDirectoryUrl),
49
- type: "entry_point",
50
- specifier: request.ressource,
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
- reference: referenceFromGraph || reference,
85
- urlInfo,
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 rootDirectoryUrl
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 = ({ urlInfo, ...rest }) => {
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
- ...rest,
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 ({ urlInfo, ...rest }) => {
30
- await kitchen.cook({
31
- urlInfo,
29
+ const _cook = async (urlInfo, context) => {
30
+ await kitchen.cook(urlInfo, {
32
31
  cookDuringCook: cook,
33
- ...rest,
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) {
@@ -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 = (url, parentUrl) => {
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) => reference.url === url,
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
+ }
@@ -185,7 +185,7 @@ export const installHtmlSupervisor = ({ logs, measurePerf }) => {
185
185
  dequeue()
186
186
  }
187
187
  if (
188
- document.readyState !== "intractive" &&
188
+ document.readyState !== "interactive" &&
189
189
  document.readyState !== "complete"
190
190
  ) {
191
191
  document.addEventListener("readystatechange", () => {
@@ -130,9 +130,8 @@ export const jsenvPluginImportmap = () => {
130
130
  contentType: "application/importmap+json",
131
131
  content: textNode.value,
132
132
  })
133
- await context.cook({
133
+ await context.cook(inlineImportmapUrlInfo, {
134
134
  reference: inlineImportmapReference,
135
- urlInfo: inlineImportmapUrlInfo,
136
135
  })
137
136
  setHtmlNodeGeneratedText(importmap, {
138
137
  generatedText: inlineImportmapUrlInfo.content,
@@ -154,9 +153,8 @@ export const jsenvPluginImportmap = () => {
154
153
  const importmapUrlInfo = context.urlGraph.getUrlInfo(
155
154
  importmapReference.url,
156
155
  )
157
- await context.cook({
156
+ await context.cook(importmapUrlInfo, {
158
157
  reference: importmapReference,
159
- urlInfo: importmapUrlInfo,
160
158
  })
161
159
  onHtmlImportmapParsed(
162
160
  JSON.parse(importmapUrlInfo.content),