@jsenv/core 23.8.2 → 23.8.7

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 (133) hide show
  1. package/dist/jsenv_browser_system.js +46 -39
  2. package/dist/jsenv_browser_system.js.map +14 -14
  3. package/dist/jsenv_compile_proxy.js.map +6 -6
  4. package/dist/jsenv_exploring_index.js.map +5 -5
  5. package/dist/jsenv_exploring_redirector.js.map +12 -12
  6. package/dist/jsenv_toolbar.js.map +7 -7
  7. package/dist/jsenv_toolbar_injector.js.map +5 -5
  8. package/helpers/babel/.eslintrc.cjs +24 -24
  9. package/helpers/babel/AsyncGenerator/AsyncGenerator.js +81 -81
  10. package/helpers/babel/AwaitValue/AwaitValue.js +3 -3
  11. package/helpers/babel/applyDecoratorDescriptor/applyDecoratorDescriptor.js +33 -33
  12. package/helpers/babel/arrayLikeToArray/arrayLikeToArray.js +7 -7
  13. package/helpers/babel/arrayWithHoles/arrayWithHoles.js +4 -4
  14. package/helpers/babel/arrayWithoutHoles/arrayWithoutHoles.js +6 -6
  15. package/helpers/babel/assertThisInitialized/assertThisInitialized.js +7 -7
  16. package/helpers/babel/asyncGeneratorDelegate/asyncGeneratorDelegate.js +40 -40
  17. package/helpers/babel/asyncIterator/asyncIterator.js +12 -12
  18. package/helpers/babel/asyncToGenerator/asyncToGenerator.js +34 -34
  19. package/helpers/babel/awaitAsyncGenerator/awaitAsyncGenerator.js +5 -5
  20. package/helpers/babel/classApplyDescriptorDestructureSet/classApplyDescriptorDestructureSet.js +20 -20
  21. package/helpers/babel/classApplyDescriptorGet/classApplyDescriptorGet.js +6 -6
  22. package/helpers/babel/classApplyDescriptorSet/classApplyDescriptorSet.js +13 -13
  23. package/helpers/babel/classCallCheck/classCallCheck.js +5 -5
  24. package/helpers/babel/classCheckPrivateStaticAccess/classCheckPrivateStaticAccess.js +5 -5
  25. package/helpers/babel/classCheckPrivateStaticFieldDescriptor/classCheckPrivateStaticFieldDescriptor.js +6 -6
  26. package/helpers/babel/classExtractFieldDescriptor/classExtractFieldDescriptor.js +7 -7
  27. package/helpers/babel/classNameTDZError/classNameTDZError.js +4 -4
  28. package/helpers/babel/classPrivateFieldDestructureSet/classPrivateFieldDestructureSet.js +7 -7
  29. package/helpers/babel/classPrivateFieldGet/classPrivateFieldGet.js +7 -7
  30. package/helpers/babel/classPrivateFieldLooseBase/classPrivateFieldLooseBase.js +6 -6
  31. package/helpers/babel/classPrivateFieldLooseKey/classPrivateFieldLooseKey.js +5 -5
  32. package/helpers/babel/classPrivateFieldSet/classPrivateFieldSet.js +8 -8
  33. package/helpers/babel/classPrivateMethodGet/classPrivateMethodGet.js +6 -6
  34. package/helpers/babel/classPrivateMethodSet/classPrivateMethodSet.js +3 -3
  35. package/helpers/babel/classStaticPrivateFieldSpecGet/classStaticPrivateFieldSpecGet.js +9 -9
  36. package/helpers/babel/classStaticPrivateFieldSpecSet/classStaticPrivateFieldSpecSet.js +15 -15
  37. package/helpers/babel/classStaticPrivateMethodGet/classStaticPrivateMethodGet.js +6 -6
  38. package/helpers/babel/classStaticPrivateMethodSet/classStaticPrivateMethodSet.js +3 -3
  39. package/helpers/babel/construct/construct.js +16 -16
  40. package/helpers/babel/createClass/createClass.js +15 -15
  41. package/helpers/babel/createForOfIteratorHelper/createForOfIteratorHelper.js +60 -60
  42. package/helpers/babel/createForOfIteratorHelperLoose/createForOfIteratorHelperLoose.js +23 -23
  43. package/helpers/babel/createRawReactElement/createRawReactElement.js +50 -50
  44. package/helpers/babel/createSuper/createSuper.js +22 -22
  45. package/helpers/babel/decorate/decorate.js +403 -403
  46. package/helpers/babel/defaults/defaults.js +11 -11
  47. package/helpers/babel/defineEnumerableProperties/defineEnumerableProperties.js +23 -23
  48. package/helpers/babel/defineProperty/defineProperty.js +18 -18
  49. package/helpers/babel/extends/extends.js +14 -14
  50. package/helpers/babel/get/get.js +13 -13
  51. package/helpers/babel/getPrototypeOf/getPrototypeOf.js +4 -4
  52. package/helpers/babel/inherits/inherits.js +15 -15
  53. package/helpers/babel/inheritsLoose/inheritsLoose.js +7 -7
  54. package/helpers/babel/initializerDefineProperty/initializerDefineProperty.js +10 -10
  55. package/helpers/babel/initializerWarningHelper/initializerWarningHelper.js +6 -6
  56. package/helpers/babel/instanceof/instanceof.js +6 -6
  57. package/helpers/babel/interopRequireDefault/interopRequireDefault.js +3 -3
  58. package/helpers/babel/interopRequireWildcard/interopRequireWildcard.js +37 -37
  59. package/helpers/babel/isNativeFunction/isNativeFunction.js +4 -4
  60. package/helpers/babel/isNativeReflectConstruct/isNativeReflectConstruct.js +21 -21
  61. package/helpers/babel/iterableToArray/iterableToArray.js +7 -7
  62. package/helpers/babel/iterableToArrayLimit/iterableToArrayLimit.js +36 -36
  63. package/helpers/babel/iterableToArrayLimitLoose/iterableToArrayLimitLoose.js +10 -10
  64. package/helpers/babel/jsx/jsx.js +45 -45
  65. package/helpers/babel/maybeArrayLike/maybeArrayLike.js +10 -10
  66. package/helpers/babel/newArrowCheck/newArrowCheck.js +5 -5
  67. package/helpers/babel/nonIterableRest/nonIterableRest.js +5 -5
  68. package/helpers/babel/nonIterableSpread/nonIterableSpread.js +5 -5
  69. package/helpers/babel/objectDestructuringEmpty/objectDestructuringEmpty.js +3 -3
  70. package/helpers/babel/objectSpread/objectSpread.js +23 -23
  71. package/helpers/babel/objectSpread2/objectSpread2.js +33 -33
  72. package/helpers/babel/objectWithoutProperties/objectWithoutProperties.js +19 -19
  73. package/helpers/babel/objectWithoutPropertiesLoose/objectWithoutPropertiesLoose.js +13 -13
  74. package/helpers/babel/possibleConstructorReturn/possibleConstructorReturn.js +10 -10
  75. package/helpers/babel/readOnlyError/readOnlyError.js +4 -4
  76. package/helpers/babel/readme.md +9 -9
  77. package/helpers/babel/set/set.js +44 -44
  78. package/helpers/babel/setPrototypeOf/setPrototypeOf.js +6 -6
  79. package/helpers/babel/skipFirstGeneratorNext/skipFirstGeneratorNext.js +8 -8
  80. package/helpers/babel/slicedToArray/slicedToArray.js +10 -10
  81. package/helpers/babel/slicedToArrayLoose/slicedToArrayLoose.js +13 -13
  82. package/helpers/babel/superPropBase/superPropBase.js +10 -10
  83. package/helpers/babel/taggedTemplateLiteral/taggedTemplateLiteral.js +10 -10
  84. package/helpers/babel/taggedTemplateLiteralLoose/taggedTemplateLiteralLoose.js +7 -7
  85. package/helpers/babel/tdz/tdz.js +4 -4
  86. package/helpers/babel/temporalRef/temporalRef.js +6 -6
  87. package/helpers/babel/temporalUndefined/temporalUndefined.js +3 -3
  88. package/helpers/babel/toArray/toArray.js +10 -10
  89. package/helpers/babel/toConsumableArray/toConsumableArray.js +10 -10
  90. package/helpers/babel/toPrimitive/toPrimitive.js +10 -10
  91. package/helpers/babel/toPropertyKey/toPropertyKey.js +6 -6
  92. package/helpers/babel/typeof/typeof.js +14 -14
  93. package/helpers/babel/unsupportedIterableToArray/unsupportedIterableToArray.js +12 -12
  94. package/helpers/babel/wrapAsyncGenerator/wrapAsyncGenerator.js +8 -8
  95. package/helpers/babel/wrapNativeSuper/wrapNativeSuper.js +30 -30
  96. package/helpers/babel/wrapRegExp/wrapRegExp.js +63 -63
  97. package/helpers/babel/writeOnlyError/writeOnlyError.js +4 -4
  98. package/helpers/regenerator-runtime/regenerator-runtime.js +748 -748
  99. package/{LICENSE → license} +21 -21
  100. package/package.json +2 -2
  101. package/src/buildProject.js +300 -300
  102. package/src/execute.js +184 -184
  103. package/src/internal/browser-launcher/jsenv-browser-system.js +203 -199
  104. package/src/internal/building/buildUsingRollup.js +2 -10
  105. package/src/internal/compiling/babel_plugin_import_assertions.js +121 -121
  106. package/src/internal/compiling/babel_plugin_import_metadata.js +22 -22
  107. package/src/internal/compiling/babel_plugin_import_visitor.js +84 -84
  108. package/src/internal/compiling/compile-directory/getOrGenerateCompiledFile.js +268 -268
  109. package/src/internal/compiling/compile-directory/updateMeta.js +154 -154
  110. package/src/internal/compiling/compile-directory/validateCache.js +265 -265
  111. package/src/internal/compiling/compileFile.js +233 -224
  112. package/src/internal/compiling/compileHtml.js +550 -550
  113. package/src/internal/compiling/createCompiledFileService.js +291 -291
  114. package/src/internal/compiling/html_source_file_service.js +403 -404
  115. package/src/internal/compiling/js-compilation-service/jsenvTransform.js +272 -270
  116. package/src/internal/compiling/jsenvCompilerForHtml.js +374 -308
  117. package/src/internal/compiling/jsenvCompilerForJavaScript.js +2 -0
  118. package/src/internal/compiling/startCompileServer.js +1086 -1048
  119. package/src/internal/compiling/transformResultToCompilationResult.js +220 -220
  120. package/src/internal/executing/coverage/babel_plugin_instrument.js +90 -90
  121. package/src/internal/executing/coverage/reportToCoverage.js +193 -187
  122. package/src/internal/executing/executePlan.js +183 -183
  123. package/src/internal/executing/launchAndExecute.js +458 -458
  124. package/src/internal/generateGroupMap/featuresCompatMap.js +29 -0
  125. package/src/internal/generateGroupMap/jsenvBabelPluginCompatMap.js +1 -8
  126. package/src/internal/runtime/createBrowserRuntime/scanBrowserRuntimeFeatures.js +246 -246
  127. package/src/internal/runtime/createNodeRuntime/scanNodeRuntimeFeatures.js +112 -112
  128. package/src/internal/runtime/s.js +727 -727
  129. package/src/internal/toolbar/jsenv-logo.svg +144 -144
  130. package/src/internal/toolbar/toolbar.main.css +196 -196
  131. package/src/internal/toolbar/toolbar.main.js +227 -227
  132. package/src/internal/url_conversion.js +317 -317
  133. package/src/startExploring.js +309 -309
@@ -1,308 +1,374 @@
1
- import { resolveUrl, urlToRelativeUrl } from "@jsenv/filesystem"
2
-
3
- import {
4
- jsenvBrowserSystemFileInfo,
5
- jsenvToolbarHtmlFileInfo,
6
- jsenvToolbarInjectorFileInfo,
7
- } from "@jsenv/core/src/internal/jsenvInternalFiles.js"
8
- import { getDefaultImportMap } from "@jsenv/core/src/internal/import-resolution/importmap-default.js"
9
- import {
10
- setJavaScriptSourceMappingUrl,
11
- sourcemapToBase64Url,
12
- } from "../sourceMappingURLUtils.js"
13
- import { transformJs } from "./js-compilation-service/transformJs.js"
14
- import {
15
- parseHtmlString,
16
- parseHtmlAstRessources,
17
- collectHtmlDependenciesFromAst,
18
- manipulateHtmlAst,
19
- stringifyHtmlAst,
20
- getHtmlNodeAttributeByName,
21
- getHtmlNodeTextNode,
22
- getUniqueNameForInlineHtmlNode,
23
- removeHtmlNodeAttribute,
24
- setHtmlNodeText,
25
- visitHtmlAst,
26
- replaceHtmlNode,
27
- } from "./compileHtml.js"
28
- import { generateCompiledFileAssetUrl } from "./compile-directory/compile-asset.js"
29
- import { composeTwoImportMaps } from "@jsenv/importmap"
30
-
31
- export const compileHtml = async ({
32
- // cancellationToken,
33
- // logger,
34
- // request,
35
- code,
36
- url,
37
- compiledUrl,
38
- projectDirectoryUrl,
39
- outDirectoryRelativeUrl,
40
- compileId,
41
-
42
- transformTopLevelAwait,
43
- moduleOutFormat,
44
- importMetaFormat,
45
- babelPluginMap,
46
-
47
- sourcemapMethod,
48
-
49
- jsenvScriptInjection = true,
50
- jsenvToolbarInjection,
51
- }) => {
52
- const jsenvBrowserBuildUrlRelativeToProject = urlToRelativeUrl(
53
- jsenvBrowserSystemFileInfo.jsenvBuildUrl,
54
- projectDirectoryUrl,
55
- )
56
- const jsenvToolbarInjectorBuildRelativeUrlForProject = urlToRelativeUrl(
57
- jsenvToolbarInjectorFileInfo.jsenvBuildUrl,
58
- projectDirectoryUrl,
59
- )
60
-
61
- // ideally we should try/catch html syntax error
62
- const htmlAst = parseHtmlString(code)
63
-
64
- if (moduleOutFormat !== "esmodule") {
65
- await mutateRessourceHints(htmlAst)
66
- }
67
-
68
- manipulateHtmlAst(htmlAst, {
69
- scriptInjections: [
70
- ...(url !== jsenvToolbarHtmlFileInfo.url && jsenvScriptInjection
71
- ? [
72
- {
73
- src: `/${jsenvBrowserBuildUrlRelativeToProject}`,
74
- },
75
- ]
76
- : []),
77
- ...(url !== jsenvToolbarHtmlFileInfo.url && jsenvToolbarInjection
78
- ? [
79
- {
80
- src: `/${jsenvToolbarInjectorBuildRelativeUrlForProject}`,
81
- },
82
- ]
83
- : []),
84
- ],
85
- })
86
-
87
- const { scripts } = parseHtmlAstRessources(htmlAst)
88
- const htmlDependencies = collectHtmlDependenciesFromAst(htmlAst)
89
-
90
- let hasImportmap = false
91
- const inlineScriptsContentMap = {}
92
- scripts.forEach((script) => {
93
- const typeAttribute = getHtmlNodeAttributeByName(script, "type")
94
- const srcAttribute = getHtmlNodeAttributeByName(script, "src")
95
-
96
- // importmap
97
- if (typeAttribute && typeAttribute.value === "importmap") {
98
- if (srcAttribute) {
99
- hasImportmap = true
100
- typeAttribute.value = "jsenv-importmap"
101
- return
102
- }
103
- const defaultImportMap = getDefaultImportMap({
104
- importMapFileUrl: compiledUrl,
105
- projectDirectoryUrl,
106
- compileDirectoryRelativeUrl: `${outDirectoryRelativeUrl}${compileId}/`,
107
- })
108
- const inlineImportMap = JSON.parse(getHtmlNodeTextNode(script).value)
109
- const mappings = composeTwoImportMaps(defaultImportMap, inlineImportMap)
110
- hasImportmap = true
111
- typeAttribute.value = "jsenv-importmap"
112
- setHtmlNodeText(script, JSON.stringify(mappings, null, " "))
113
- return
114
- }
115
-
116
- if (typeAttribute && typeAttribute.value === "module" && srcAttribute) {
117
- removeHtmlNodeAttribute(script, typeAttribute)
118
- removeHtmlNodeAttribute(script, srcAttribute)
119
- setHtmlNodeText(
120
- script,
121
- `window.__jsenv__.executeFileUsingSystemJs(${JSON.stringify(
122
- srcAttribute.value,
123
- )})`,
124
- )
125
- return
126
- }
127
- // inline
128
- const textNode = getHtmlNodeTextNode(script)
129
- if (typeAttribute && typeAttribute.value === "module" && textNode) {
130
- const scriptAssetUrl = generateCompiledFileAssetUrl(
131
- compiledUrl,
132
- getUniqueNameForInlineHtmlNode(script, scripts, `[id].js`),
133
- )
134
- const specifier = `./${urlToRelativeUrl(scriptAssetUrl, compiledUrl)}`
135
- inlineScriptsContentMap[specifier] = textNode.value
136
-
137
- removeHtmlNodeAttribute(script, typeAttribute)
138
- removeHtmlNodeAttribute(script, srcAttribute)
139
- setHtmlNodeText(
140
- script,
141
- `window.__jsenv__.executeFileUsingSystemJs(${JSON.stringify(
142
- specifier,
143
- )})`,
144
- )
145
- htmlDependencies.push({
146
- htmlNode: script,
147
- specifier,
148
- })
149
- return
150
- }
151
- })
152
- if (hasImportmap === false) {
153
- const defaultImportMap = getDefaultImportMap({
154
- importMapFileUrl: compiledUrl,
155
- projectDirectoryUrl,
156
- compileDirectoryRelativeUrl: `${outDirectoryRelativeUrl}${compileId}/`,
157
- })
158
-
159
- manipulateHtmlAst(htmlAst, {
160
- scriptInjections: [
161
- {
162
- type: "jsenv-importmap",
163
- // in case there is no importmap, force the presence
164
- // so that '@jsenv/core/' are still remapped
165
- text: JSON.stringify(defaultImportMap, null, " "),
166
- },
167
- ],
168
- })
169
- }
170
-
171
- const htmlAfterTransformation = stringifyHtmlAst(htmlAst)
172
-
173
- let assets = []
174
- let assetsContent = []
175
- await Promise.all(
176
- Object.keys(inlineScriptsContentMap).map(async (scriptSrc) => {
177
- const scriptAssetUrl = resolveUrl(scriptSrc, compiledUrl)
178
- const scriptBasename = urlToRelativeUrl(scriptAssetUrl, compiledUrl)
179
- const scriptOriginalFileUrl = resolveUrl(scriptBasename, url)
180
- const scriptCompiledFileUrl = resolveUrl(scriptBasename, compiledUrl)
181
-
182
- const scriptBeforeCompilation = inlineScriptsContentMap[scriptSrc]
183
- let scriptTransformResult
184
- try {
185
- scriptTransformResult = await transformJs({
186
- code: scriptBeforeCompilation,
187
- url: scriptOriginalFileUrl,
188
- compiledUrl: scriptCompiledFileUrl,
189
- projectDirectoryUrl,
190
-
191
- transformTopLevelAwait,
192
- moduleOutFormat,
193
- importMetaFormat,
194
- babelPluginMap,
195
- })
196
- } catch (e) {
197
- // If there is a syntax error in inline script
198
- // we put the raw script without transformation.
199
- // when systemjs will try to instantiate to script it
200
- // will re-throw this syntax error.
201
- // Thanks to this we see the syntax error in the
202
- // document and livereloading still works
203
- // because we gracefully handle this error
204
- if (e.code === "PARSE_ERROR") {
205
- const code = scriptBeforeCompilation
206
- assets = [...assets, scriptAssetUrl]
207
- assetsContent = [...assetsContent, code]
208
- return
209
- }
210
- throw e
211
- }
212
- const sourcemapFileUrl = resolveUrl(
213
- `${scriptBasename}.map`,
214
- scriptCompiledFileUrl,
215
- )
216
-
217
- let { code, map } = scriptTransformResult
218
- const sourcemapFileRelativePathForModule = urlToRelativeUrl(
219
- sourcemapFileUrl,
220
- compiledUrl,
221
- )
222
-
223
- if (sourcemapMethod === "inline") {
224
- code = setJavaScriptSourceMappingUrl(code, sourcemapToBase64Url(map))
225
- } else {
226
- // TODO: respect "sourcemapMethod" parameter
227
- code = setJavaScriptSourceMappingUrl(
228
- code,
229
- sourcemapFileRelativePathForModule,
230
- )
231
- assets = [...assets, scriptAssetUrl, sourcemapFileUrl]
232
- assetsContent = [
233
- ...assetsContent,
234
- code,
235
- JSON.stringify(map, null, " "),
236
- ]
237
- }
238
- }),
239
- )
240
-
241
- return {
242
- contentType: "text/html",
243
- compiledSource: htmlAfterTransformation,
244
- sources: [url],
245
- sourcesContent: [code],
246
- assets,
247
- assetsContent,
248
- dependencies: htmlDependencies.map(({ specifier }) => {
249
- return specifier
250
- }),
251
- }
252
- }
253
-
254
- // transform <link type="modulepreload"> into <link type="preload">
255
- const mutateRessourceHints = async (htmlAst) => {
256
- const ressourceHints = []
257
- visitHtmlAst(htmlAst, (htmlNode) => {
258
- if (htmlNode.nodeName !== "link") return
259
- const relAttribute = getHtmlNodeAttributeByName(htmlNode, "rel")
260
- const rel = relAttribute ? relAttribute.value : ""
261
- const isRessourceHint = [
262
- "preconnect",
263
- "dns-prefetch",
264
- "prefetch",
265
- "preload",
266
- "modulepreload",
267
- ].includes(rel)
268
- if (!isRessourceHint) return
269
-
270
- ressourceHints.push({ rel, htmlNode })
271
- })
272
-
273
- const mutations = []
274
- await Promise.all(
275
- ressourceHints.map(async (ressourceHint) => {
276
- const hrefAttribute = getHtmlNodeAttributeByName(
277
- ressourceHint.htmlNode,
278
- "href",
279
- )
280
- const href = hrefAttribute ? hrefAttribute.value : ""
281
- if (!href) return
282
-
283
- // - "modulepreload" -> "preload" because it's now regular js script
284
- const asAttribute = getHtmlNodeAttributeByName(
285
- ressourceHint.htmlNode,
286
- "as",
287
- )
288
-
289
- if (ressourceHint.rel === "modulepreload") {
290
- mutations.push(() => {
291
- replaceHtmlNode(
292
- ressourceHint.htmlNode,
293
- `<link rel="preload" as="script" />`,
294
- )
295
- })
296
- return
297
- }
298
-
299
- if (asAttribute && asAttribute.value === "script") {
300
- mutations.push(() => {
301
- replaceHtmlNode(ressourceHint.htmlNode, `<link as="script" />`)
302
- })
303
- return
304
- }
305
- }),
306
- )
307
- mutations.forEach((mutation) => mutation())
308
- }
1
+ import { resolveUrl, urlToRelativeUrl } from "@jsenv/filesystem"
2
+ import { moveImportMap, composeTwoImportMaps } from "@jsenv/importmap"
3
+ import { createDetailedMessage } from "@jsenv/logger"
4
+
5
+ import {
6
+ jsenvBrowserSystemFileInfo,
7
+ jsenvToolbarHtmlFileInfo,
8
+ jsenvToolbarInjectorFileInfo,
9
+ } from "@jsenv/core/src/internal/jsenvInternalFiles.js"
10
+ import { fetchUrl } from "@jsenv/core/src/internal/fetchUrl.js"
11
+ import { getDefaultImportMap } from "@jsenv/core/src/internal/import-resolution/importmap-default.js"
12
+ import {
13
+ setJavaScriptSourceMappingUrl,
14
+ sourcemapToBase64Url,
15
+ } from "../sourceMappingURLUtils.js"
16
+ import { transformJs } from "./js-compilation-service/transformJs.js"
17
+ import {
18
+ parseHtmlString,
19
+ parseHtmlAstRessources,
20
+ collectHtmlDependenciesFromAst,
21
+ manipulateHtmlAst,
22
+ stringifyHtmlAst,
23
+ getHtmlNodeAttributeByName,
24
+ getHtmlNodeTextNode,
25
+ getUniqueNameForInlineHtmlNode,
26
+ removeHtmlNodeAttribute,
27
+ setHtmlNodeText,
28
+ visitHtmlAst,
29
+ replaceHtmlNode,
30
+ } from "./compileHtml.js"
31
+ import { generateCompiledFileAssetUrl } from "./compile-directory/compile-asset.js"
32
+
33
+ export const compileHtml = async ({
34
+ // cancellationToken,
35
+ logger,
36
+ // request,
37
+ code,
38
+ url,
39
+ compiledUrl,
40
+ projectDirectoryUrl,
41
+ outDirectoryRelativeUrl,
42
+ compileId,
43
+
44
+ transformTopLevelAwait,
45
+ moduleOutFormat,
46
+ importMetaFormat,
47
+ babelPluginMap,
48
+
49
+ sourcemapMethod,
50
+
51
+ jsenvScriptInjection = true,
52
+ jsenvToolbarInjection,
53
+ }) => {
54
+ const jsenvBrowserBuildUrlRelativeToProject = urlToRelativeUrl(
55
+ jsenvBrowserSystemFileInfo.jsenvBuildUrl,
56
+ projectDirectoryUrl,
57
+ )
58
+ const jsenvToolbarInjectorBuildRelativeUrlForProject = urlToRelativeUrl(
59
+ jsenvToolbarInjectorFileInfo.jsenvBuildUrl,
60
+ projectDirectoryUrl,
61
+ )
62
+
63
+ // ideally we should try/catch html syntax error
64
+ const htmlAst = parseHtmlString(code)
65
+
66
+ if (moduleOutFormat !== "esmodule") {
67
+ await mutateRessourceHints(htmlAst)
68
+ }
69
+
70
+ manipulateHtmlAst(htmlAst, {
71
+ scriptInjections: [
72
+ ...(url !== jsenvToolbarHtmlFileInfo.url && jsenvScriptInjection
73
+ ? [
74
+ {
75
+ src: `/${jsenvBrowserBuildUrlRelativeToProject}`,
76
+ },
77
+ ]
78
+ : []),
79
+ ...(url !== jsenvToolbarHtmlFileInfo.url && jsenvToolbarInjection
80
+ ? [
81
+ {
82
+ src: `/${jsenvToolbarInjectorBuildRelativeUrlForProject}`,
83
+ },
84
+ ]
85
+ : []),
86
+ ],
87
+ })
88
+
89
+ const { scripts } = parseHtmlAstRessources(htmlAst)
90
+ const htmlDependencies = collectHtmlDependenciesFromAst(htmlAst)
91
+
92
+ let hasImportmap = false
93
+ const inlineScriptsContentMap = {}
94
+ const importmapsToInline = []
95
+ scripts.forEach((script) => {
96
+ const typeAttribute = getHtmlNodeAttributeByName(script, "type")
97
+ const srcAttribute = getHtmlNodeAttributeByName(script, "src")
98
+
99
+ // importmap
100
+ if (typeAttribute && typeAttribute.value === "importmap") {
101
+ hasImportmap = true
102
+
103
+ if (srcAttribute) {
104
+ if (moduleOutFormat === "systemjs") {
105
+ typeAttribute.value = "jsenv-importmap"
106
+ return // no need to inline
107
+ }
108
+
109
+ // we force inline because browsers supporting importmap supports only when they are inline
110
+ importmapsToInline.push({
111
+ script,
112
+ src: srcAttribute.value,
113
+ })
114
+ return
115
+ }
116
+
117
+ const defaultImportMap = getDefaultImportMap({
118
+ importMapFileUrl: compiledUrl,
119
+ projectDirectoryUrl,
120
+ compileDirectoryRelativeUrl: `${outDirectoryRelativeUrl}${compileId}/`,
121
+ })
122
+ const inlineImportMap = JSON.parse(getHtmlNodeTextNode(script).value)
123
+ const mappings = composeTwoImportMaps(defaultImportMap, inlineImportMap)
124
+ if (moduleOutFormat === "systemjs") {
125
+ typeAttribute.value = "jsenv-importmap"
126
+ }
127
+ setHtmlNodeText(script, JSON.stringify(mappings, null, " "))
128
+ return
129
+ }
130
+
131
+ // remote module script
132
+ if (typeAttribute && typeAttribute.value === "module" && srcAttribute) {
133
+ if (moduleOutFormat === "systemjs") {
134
+ removeHtmlNodeAttribute(script, typeAttribute)
135
+ }
136
+ removeHtmlNodeAttribute(script, srcAttribute)
137
+ const src = srcAttribute.value
138
+ const jsenvMethod =
139
+ moduleOutFormat === "systemjs"
140
+ ? "executeFileUsingSystemJs"
141
+ : "executeFileUsingDynamicImport"
142
+ setHtmlNodeText(
143
+ script,
144
+ `window.__jsenv__.${jsenvMethod}(${JSON.stringify(src)})`,
145
+ )
146
+ return
147
+ }
148
+
149
+ // inline module script
150
+ const textNode = getHtmlNodeTextNode(script)
151
+ if (typeAttribute && typeAttribute.value === "module" && textNode) {
152
+ if (moduleOutFormat === "systemjs") {
153
+ removeHtmlNodeAttribute(script, typeAttribute)
154
+ }
155
+ removeHtmlNodeAttribute(script, srcAttribute)
156
+ const scriptAssetUrl = generateCompiledFileAssetUrl(
157
+ compiledUrl,
158
+ getUniqueNameForInlineHtmlNode(script, scripts, `[id].js`),
159
+ )
160
+ const specifier = `./${urlToRelativeUrl(scriptAssetUrl, compiledUrl)}`
161
+ inlineScriptsContentMap[specifier] = textNode.value
162
+ const jsenvMethod =
163
+ moduleOutFormat === "systemjs"
164
+ ? "executeFileUsingSystemJs"
165
+ : "executeFileUsingDynamicImport"
166
+ setHtmlNodeText(
167
+ script,
168
+ `window.__jsenv__.${jsenvMethod}(${JSON.stringify(specifier)})`,
169
+ )
170
+ htmlDependencies.push({
171
+ htmlNode: script,
172
+ specifier,
173
+ })
174
+ return
175
+ }
176
+ })
177
+
178
+ if (hasImportmap === false) {
179
+ const defaultImportMap = getDefaultImportMap({
180
+ importMapFileUrl: compiledUrl,
181
+ projectDirectoryUrl,
182
+ compileDirectoryRelativeUrl: `${outDirectoryRelativeUrl}${compileId}/`,
183
+ })
184
+ manipulateHtmlAst(htmlAst, {
185
+ scriptInjections: [
186
+ {
187
+ type:
188
+ moduleOutFormat === "systemjs" ? "jsenv-importmap" : "importmap",
189
+ // in case there is no importmap, force the presence
190
+ // so that '@jsenv/core/' are still remapped
191
+ text: JSON.stringify(defaultImportMap, null, " "),
192
+ },
193
+ ],
194
+ })
195
+ }
196
+
197
+ await Promise.all(
198
+ importmapsToInline.map(async ({ script, src }) => {
199
+ const importMapUrl = resolveUrl(src, url)
200
+ const importMapResponse = await fetchUrl(importMapUrl)
201
+ if (importMapResponse.status !== 200) {
202
+ logger.warn(
203
+ createDetailedMessage(
204
+ importMapResponse.status === 404
205
+ ? `Cannot inline importmap script because file cannot be found.`
206
+ : `Cannot inline importmap script due to unexpected response status (${importMapResponse.status}).`,
207
+ {
208
+ "importmap script src": src,
209
+ "importmap url": importMapUrl,
210
+ "html url": url,
211
+ },
212
+ ),
213
+ )
214
+ return
215
+ }
216
+
217
+ const importMapContent = await importMapResponse.json()
218
+ const importMapInlined = moveImportMap(
219
+ importMapContent,
220
+ importMapUrl,
221
+ url,
222
+ )
223
+ replaceHtmlNode(
224
+ script,
225
+ `<script type="importmap">${JSON.stringify(
226
+ importMapInlined,
227
+ null,
228
+ " ",
229
+ )}</script>`,
230
+ {
231
+ attributesToIgnore: ["src"],
232
+ },
233
+ )
234
+ }),
235
+ )
236
+
237
+ const htmlAfterTransformation = stringifyHtmlAst(htmlAst)
238
+
239
+ let assets = []
240
+ let assetsContent = []
241
+ await Promise.all(
242
+ Object.keys(inlineScriptsContentMap).map(async (scriptSrc) => {
243
+ const scriptAssetUrl = resolveUrl(scriptSrc, compiledUrl)
244
+ const scriptBasename = urlToRelativeUrl(scriptAssetUrl, compiledUrl)
245
+ const scriptOriginalFileUrl = resolveUrl(scriptBasename, url)
246
+ const scriptCompiledFileUrl = resolveUrl(scriptBasename, compiledUrl)
247
+
248
+ const scriptBeforeCompilation = inlineScriptsContentMap[scriptSrc]
249
+ let scriptTransformResult
250
+ try {
251
+ scriptTransformResult = await transformJs({
252
+ code: scriptBeforeCompilation,
253
+ url: scriptOriginalFileUrl,
254
+ compiledUrl: scriptCompiledFileUrl,
255
+ projectDirectoryUrl,
256
+
257
+ transformTopLevelAwait,
258
+ moduleOutFormat,
259
+ importMetaFormat,
260
+ babelPluginMap,
261
+ })
262
+ } catch (e) {
263
+ // If there is a syntax error in inline script
264
+ // we put the raw script without transformation.
265
+ // when systemjs will try to instantiate to script it
266
+ // will re-throw this syntax error.
267
+ // Thanks to this we see the syntax error in the
268
+ // document and livereloading still works
269
+ // because we gracefully handle this error
270
+ if (e.code === "PARSE_ERROR") {
271
+ const code = scriptBeforeCompilation
272
+ assets = [...assets, scriptAssetUrl]
273
+ assetsContent = [...assetsContent, code]
274
+ return
275
+ }
276
+ throw e
277
+ }
278
+ const sourcemapFileUrl = resolveUrl(
279
+ `${scriptBasename}.map`,
280
+ scriptCompiledFileUrl,
281
+ )
282
+
283
+ let { code, map } = scriptTransformResult
284
+ const sourcemapFileRelativePathForModule = urlToRelativeUrl(
285
+ sourcemapFileUrl,
286
+ compiledUrl,
287
+ )
288
+
289
+ if (sourcemapMethod === "inline") {
290
+ code = setJavaScriptSourceMappingUrl(code, sourcemapToBase64Url(map))
291
+ } else {
292
+ // TODO: respect "sourcemapMethod" parameter
293
+ code = setJavaScriptSourceMappingUrl(
294
+ code,
295
+ sourcemapFileRelativePathForModule,
296
+ )
297
+ assets = [...assets, scriptAssetUrl, sourcemapFileUrl]
298
+ assetsContent = [
299
+ ...assetsContent,
300
+ code,
301
+ JSON.stringify(map, null, " "),
302
+ ]
303
+ }
304
+ }),
305
+ )
306
+
307
+ return {
308
+ contentType: "text/html",
309
+ compiledSource: htmlAfterTransformation,
310
+ sources: [url],
311
+ sourcesContent: [code],
312
+ assets,
313
+ assetsContent,
314
+ dependencies: htmlDependencies.map(({ specifier }) => {
315
+ return specifier
316
+ }),
317
+ }
318
+ }
319
+
320
+ // transform <link type="modulepreload"> into <link type="preload">
321
+ const mutateRessourceHints = async (htmlAst) => {
322
+ const ressourceHints = []
323
+ visitHtmlAst(htmlAst, (htmlNode) => {
324
+ if (htmlNode.nodeName !== "link") return
325
+ const relAttribute = getHtmlNodeAttributeByName(htmlNode, "rel")
326
+ const rel = relAttribute ? relAttribute.value : ""
327
+ const isRessourceHint = [
328
+ "preconnect",
329
+ "dns-prefetch",
330
+ "prefetch",
331
+ "preload",
332
+ "modulepreload",
333
+ ].includes(rel)
334
+ if (!isRessourceHint) return
335
+
336
+ ressourceHints.push({ rel, htmlNode })
337
+ })
338
+
339
+ const mutations = []
340
+ await Promise.all(
341
+ ressourceHints.map(async (ressourceHint) => {
342
+ const hrefAttribute = getHtmlNodeAttributeByName(
343
+ ressourceHint.htmlNode,
344
+ "href",
345
+ )
346
+ const href = hrefAttribute ? hrefAttribute.value : ""
347
+ if (!href) return
348
+
349
+ // - "modulepreload" -> "preload" because it's now regular js script
350
+ const asAttribute = getHtmlNodeAttributeByName(
351
+ ressourceHint.htmlNode,
352
+ "as",
353
+ )
354
+
355
+ if (ressourceHint.rel === "modulepreload") {
356
+ mutations.push(() => {
357
+ replaceHtmlNode(
358
+ ressourceHint.htmlNode,
359
+ `<link rel="preload" as="script" />`,
360
+ )
361
+ })
362
+ return
363
+ }
364
+
365
+ if (asAttribute && asAttribute.value === "script") {
366
+ mutations.push(() => {
367
+ replaceHtmlNode(ressourceHint.htmlNode, `<link as="script" />`)
368
+ })
369
+ return
370
+ }
371
+ }),
372
+ )
373
+ mutations.forEach((mutation) => mutation())
374
+ }