@jsenv/core 35.0.5 → 36.0.1

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 (50) hide show
  1. package/README.md +1 -1
  2. package/dist/js/inline_content.js +5 -4
  3. package/dist/jsenv_core.js +1127 -1497
  4. package/package.json +8 -8
  5. package/src/build/build.js +49 -41
  6. package/src/dev/file_service.js +7 -17
  7. package/src/dev/start_dev_server.js +12 -7
  8. package/src/kitchen/kitchen.js +38 -19
  9. package/src/kitchen/url_graph.js +1 -1
  10. package/src/plugins/autoreload/jsenv_plugin_hmr.js +2 -2
  11. package/src/plugins/file_urls/jsenv_plugin_file_urls.js +4 -4
  12. package/src/plugins/http_urls/jsenv_plugin_http_urls.js +1 -1
  13. package/src/plugins/importmap/jsenv_plugin_importmap.js +1 -1
  14. package/src/plugins/inlining/jsenv_plugin_inlining.js +1 -1
  15. package/src/plugins/inlining/jsenv_plugin_inlining_as_data_url.js +13 -2
  16. package/src/plugins/plugin_controller.js +19 -10
  17. package/src/plugins/plugins.js +21 -25
  18. package/src/plugins/{url_analysis/css/css_urls.js → reference_analysis/css/jsenv_plugin_css_reference_analysis.js} +11 -1
  19. package/src/plugins/{inline_content_analysis/jsenv_plugin_data_urls.js → reference_analysis/data_urls/jsenv_plugin_data_urls_analysis.js} +19 -19
  20. package/src/plugins/reference_analysis/directory/jsenv_plugin_directory_reference_analysis.js +51 -0
  21. package/src/plugins/reference_analysis/html/jsenv_plugin_html_reference_analysis.js +429 -0
  22. package/src/plugins/reference_analysis/inline_content.js +7 -0
  23. package/src/plugins/reference_analysis/js/jsenv_plugin_js_reference_analysis.js +161 -0
  24. package/src/plugins/reference_analysis/jsenv_plugin_reference_analysis.js +120 -0
  25. package/src/plugins/{url_analysis → reference_analysis}/jsenv_plugin_reference_expected_types.js +19 -12
  26. package/src/plugins/{url_analysis/webmanifest/webmanifest_urls.js → reference_analysis/webmanifest/jsenv_plugin_webmanifest_reference_analysis.js} +13 -1
  27. package/src/plugins/resolution_node_esm/jsenv_plugin_node_esm_resolution.js +74 -0
  28. package/src/plugins/{url_resolution → resolution_node_esm}/node_esm_resolver.js +8 -0
  29. package/src/plugins/resolution_web/jsenv_plugin_web_resolution.js +45 -0
  30. package/src/plugins/transpilation/as_js_module/jsenv_plugin_as_js_module.js +1 -1
  31. package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +1 -1
  32. package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +4 -6
  33. package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_conversion.js +1 -1
  34. package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_fallback_inside_html.js +4 -6
  35. package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_fallback_on_workers.js +1 -1
  36. package/src/plugins/url_type_from_reference.js +13 -0
  37. package/src/plugins/{url_version/jsenv_plugin_url_version.js → version_search_param/jsenv_plugin_version_search_param.js} +4 -4
  38. package/dist/html/explorer.html +0 -559
  39. package/dist/other/jsenv.png +0 -0
  40. package/src/plugins/explorer/client/explorer.html +0 -608
  41. package/src/plugins/explorer/client/jsenv.png +0 -0
  42. package/src/plugins/explorer/jsenv_plugin_explorer.js +0 -86
  43. package/src/plugins/inline_content_analysis/client/inline_content.js +0 -6
  44. package/src/plugins/inline_content_analysis/jsenv_plugin_html_inline_content_analysis.js +0 -206
  45. package/src/plugins/inline_content_analysis/jsenv_plugin_inline_content_analysis.js +0 -34
  46. package/src/plugins/inline_content_analysis/jsenv_plugin_js_inline_content_analysis.js +0 -314
  47. package/src/plugins/url_analysis/html/html_urls.js +0 -313
  48. package/src/plugins/url_analysis/js/js_urls.js +0 -65
  49. package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +0 -116
  50. package/src/plugins/url_resolution/jsenv_plugin_url_resolution.js +0 -140
@@ -0,0 +1,429 @@
1
+ import {
2
+ parseHtmlString,
3
+ visitHtmlNodes,
4
+ getHtmlNodeText,
5
+ setHtmlNodeText,
6
+ removeHtmlNodeText,
7
+ getHtmlNodeAttribute,
8
+ getHtmlNodePosition,
9
+ setHtmlNodeAttributes,
10
+ getHtmlNodeAttributePosition,
11
+ analyzeScriptNode,
12
+ parseSrcSet,
13
+ stringifyHtmlAst,
14
+ } from "@jsenv/ast";
15
+ import { generateInlineContentUrl } from "@jsenv/urls";
16
+ import { CONTENT_TYPE } from "@jsenv/utils/src/content_type/content_type.js";
17
+
18
+ export const jsenvPluginHtmlReferenceAnalysis = ({
19
+ inlineContent,
20
+ inlineConvertedScript,
21
+ }) => {
22
+ return {
23
+ name: "jsenv:html_reference_analysis",
24
+ appliesDuring: "*",
25
+ transformUrlContent: {
26
+ html: (urlInfo, context) =>
27
+ parseAndTransformHtmlReferences(urlInfo, context, {
28
+ inlineContent,
29
+ inlineConvertedScript,
30
+ }),
31
+ },
32
+ };
33
+ };
34
+
35
+ const parseAndTransformHtmlReferences = async (
36
+ urlInfo,
37
+ context,
38
+ { inlineContent, inlineConvertedScript },
39
+ ) => {
40
+ const url = urlInfo.originalUrl;
41
+ const content = urlInfo.content;
42
+ const htmlAst = parseHtmlString(content);
43
+
44
+ const mutations = [];
45
+ const actions = [];
46
+ const finalizeCallbacks = [];
47
+
48
+ const createExternalReference = (
49
+ node,
50
+ attributeName,
51
+ attributeValue,
52
+ { type, subtype, expectedType },
53
+ ) => {
54
+ let position;
55
+ if (getHtmlNodeAttribute(node, "jsenv-cooked-by")) {
56
+ // when generated from inline content,
57
+ // line, column is not "src" nor "inlined-from-src" but "original-position"
58
+ position = getHtmlNodePosition(node);
59
+ } else {
60
+ position = getHtmlNodeAttributePosition(node, attributeName);
61
+ }
62
+ const {
63
+ line,
64
+ column,
65
+ // originalLine, originalColumn
66
+ } = position;
67
+ const debug = getHtmlNodeAttribute(node, "jsenv-debug") !== undefined;
68
+
69
+ const { crossorigin, integrity } = readFetchMetas(node);
70
+ const isResourceHint = [
71
+ "preconnect",
72
+ "dns-prefetch",
73
+ "prefetch",
74
+ "preload",
75
+ "modulepreload",
76
+ ].includes(subtype);
77
+ const [reference] = context.referenceUtils.found({
78
+ type,
79
+ subtype,
80
+ expectedType,
81
+ specifier: attributeValue,
82
+ specifierLine: line,
83
+ specifierColumn: column,
84
+ isResourceHint,
85
+ crossorigin,
86
+ integrity,
87
+ debug,
88
+ });
89
+ actions.push(async () => {
90
+ await context.referenceUtils.readGeneratedSpecifier(reference);
91
+ mutations.push(() => {
92
+ setHtmlNodeAttributes(node, {
93
+ [attributeName]: reference.generatedSpecifier,
94
+ });
95
+ });
96
+ });
97
+ };
98
+ const visitHref = (node, referenceProps) => {
99
+ const href = getHtmlNodeAttribute(node, "href");
100
+ if (href) {
101
+ return createExternalReference(node, "href", href, referenceProps);
102
+ }
103
+ const inlinedFromHref = getHtmlNodeAttribute(node, "inlined-from-href");
104
+ if (inlinedFromHref) {
105
+ return createExternalReference(
106
+ node,
107
+ "inlined-from-href",
108
+ new URL(inlinedFromHref, url).href,
109
+ referenceProps,
110
+ );
111
+ }
112
+ return null;
113
+ };
114
+ const visitSrc = (node, referenceProps) => {
115
+ const src = getHtmlNodeAttribute(node, "src");
116
+ if (src) {
117
+ return createExternalReference(node, "src", src, referenceProps);
118
+ }
119
+ const inlinedFromSrc = getHtmlNodeAttribute(node, "inlined-from-src");
120
+ if (inlinedFromSrc) {
121
+ return createExternalReference(
122
+ node,
123
+ "inlined-from-src",
124
+ new URL(inlinedFromSrc, url).href,
125
+ referenceProps,
126
+ );
127
+ }
128
+ return null;
129
+ };
130
+ const visitSrcset = (node, referenceProps) => {
131
+ const srcset = getHtmlNodeAttribute(node, "srcset");
132
+ if (srcset) {
133
+ const srcCandidates = parseSrcSet(srcset);
134
+ return srcCandidates.map((srcCandidate) => {
135
+ return createExternalReference(
136
+ node,
137
+ "srcset",
138
+ srcCandidate.specifier,
139
+ referenceProps,
140
+ );
141
+ });
142
+ }
143
+ return null;
144
+ };
145
+
146
+ const createInlineReference = (
147
+ node,
148
+ inlineContent,
149
+ { extension, type, expectedType, contentType },
150
+ ) => {
151
+ const hotAccept = getHtmlNodeAttribute(node, "hot-accept") !== undefined;
152
+ const { line, column, lineEnd, columnEnd, isOriginal } =
153
+ getHtmlNodePosition(node, { preferOriginal: true });
154
+ const inlineContentUrl = generateInlineContentUrl({
155
+ url: urlInfo.url,
156
+ extension,
157
+ line,
158
+ column,
159
+ lineEnd,
160
+ columnEnd,
161
+ });
162
+ const debug = getHtmlNodeAttribute(node, "jsenv-debug") !== undefined;
163
+ const [inlineReference, inlineUrlInfo] = context.referenceUtils.foundInline(
164
+ {
165
+ node,
166
+ type,
167
+ expectedType,
168
+ isOriginalPosition: isOriginal,
169
+ // we remove 1 to the line because imagine the following html:
170
+ // <style>body { color: red; }</style>
171
+ // -> content starts same line as <style> (same for <script>)
172
+ specifierLine: line - 1,
173
+ specifierColumn: column,
174
+ specifier: inlineContentUrl,
175
+ contentType,
176
+ content: inlineContent,
177
+ debug,
178
+ },
179
+ );
180
+ actions.push(async () => {
181
+ await cookInlineContent({
182
+ context,
183
+ inlineContentUrlInfo: inlineUrlInfo,
184
+ inlineContentReference: inlineReference,
185
+ });
186
+ mutations.push(() => {
187
+ if (hotAccept) {
188
+ removeHtmlNodeText(node);
189
+ setHtmlNodeAttributes(node, {
190
+ "jsenv-cooked-by": "jsenv:html_inline_content_analysis",
191
+ });
192
+ } else {
193
+ setHtmlNodeText(node, inlineUrlInfo.content, {
194
+ indentation: false, // indentation would decrease stack trace precision
195
+ });
196
+ setHtmlNodeAttributes(node, {
197
+ "jsenv-cooked-by": "jsenv:html_inline_content_analysis",
198
+ });
199
+ }
200
+ });
201
+ });
202
+
203
+ return inlineReference;
204
+ };
205
+ const visitTextContent = (
206
+ node,
207
+ { extension, type, expectedType, contentType },
208
+ ) => {
209
+ const inlineContent = getHtmlNodeText(node);
210
+ if (!inlineContent) {
211
+ return null;
212
+ }
213
+ return createInlineReference(node, inlineContent, {
214
+ extension,
215
+ type,
216
+ expectedType,
217
+ contentType,
218
+ });
219
+ };
220
+
221
+ visitHtmlNodes(htmlAst, {
222
+ link: (linkNode) => {
223
+ const rel = getHtmlNodeAttribute(linkNode, "rel");
224
+ const type = getHtmlNodeAttribute(linkNode, "type");
225
+ const ref = visitHref(linkNode, {
226
+ type: "link_href",
227
+ subtype: rel,
228
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload#including_a_mime_type
229
+ expectedContentType: type,
230
+ });
231
+ if (ref) {
232
+ finalizeCallbacks.push(() => {
233
+ ref.expectedType = decideLinkExpectedType(ref, context);
234
+ });
235
+ }
236
+ },
237
+ style: inlineContent
238
+ ? (styleNode) => {
239
+ visitTextContent(styleNode, {
240
+ extension: ".css",
241
+ type: "style",
242
+ expectedType: "css",
243
+ contentType: "text/css",
244
+ });
245
+ }
246
+ : null,
247
+ script: (scriptNode) => {
248
+ // during build the importmap is inlined
249
+ // and shoud not be considered as a dependency anymore
250
+ if (
251
+ getHtmlNodeAttribute(scriptNode, "jsenv-inlined-by") ===
252
+ "jsenv:importmap"
253
+ ) {
254
+ return;
255
+ }
256
+
257
+ const { type, contentType, extension } = analyzeScriptNode(scriptNode);
258
+ // ignore <script type="whatever">foobar</script>
259
+ // per HTML spec https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-type
260
+ if (type !== "text") {
261
+ const externalRef = visitSrc(scriptNode, {
262
+ type: "script",
263
+ subtype: type,
264
+ expectedType: type,
265
+ });
266
+ if (externalRef) {
267
+ return;
268
+ }
269
+ }
270
+
271
+ // now visit the content, if any
272
+ if (!inlineContent) {
273
+ return;
274
+ }
275
+ // If the inline script was already handled by an other plugin, ignore it
276
+ // - we want to preserve inline scripts generated by html supervisor during dev
277
+ // - we want to avoid cooking twice a script during build
278
+ if (
279
+ !inlineConvertedScript &&
280
+ getHtmlNodeAttribute(scriptNode, "jsenv-injected-by") ===
281
+ "jsenv:js_module_fallback"
282
+ ) {
283
+ return;
284
+ }
285
+
286
+ const inlineRef = visitTextContent(scriptNode, {
287
+ extension: extension || CONTENT_TYPE.asFileExtension(contentType),
288
+ type: "script",
289
+ expectedType: type,
290
+ contentType,
291
+ });
292
+ if (inlineRef && extension) {
293
+ // 1. <script type="jsx"> becomes <script>
294
+ // 2. <script type="module/jsx"> becomes <script type="module">
295
+ mutations.push(() => {
296
+ setHtmlNodeAttributes(scriptNode, {
297
+ type: type === "js_module" ? "module" : undefined,
298
+ });
299
+ });
300
+ }
301
+ },
302
+ a: (aNode) => {
303
+ visitHref(aNode, {
304
+ type: "a_href",
305
+ });
306
+ },
307
+ iframe: (iframeNode) => {
308
+ visitSrc(iframeNode, {
309
+ type: "iframe_src",
310
+ });
311
+ },
312
+ img: (imgNode) => {
313
+ visitSrc(imgNode, {
314
+ type: "img_src",
315
+ });
316
+ visitSrcset(imgNode, {
317
+ type: "img_srcset",
318
+ });
319
+ },
320
+ source: (sourceNode) => {
321
+ visitSrc(sourceNode, {
322
+ type: "source_src",
323
+ });
324
+ visitSrcset(sourceNode, {
325
+ type: "source_srcset",
326
+ });
327
+ },
328
+ // svg <image> tag
329
+ image: (imageNode) => {
330
+ visitHref(imageNode, {
331
+ type: "image_href",
332
+ });
333
+ },
334
+ use: (useNode) => {
335
+ visitHref(useNode, {
336
+ type: "use_href",
337
+ });
338
+ },
339
+ });
340
+ finalizeCallbacks.forEach((finalizeCallback) => {
341
+ finalizeCallback();
342
+ });
343
+
344
+ if (actions.length > 0) {
345
+ await Promise.all(actions.map((action) => action()));
346
+ }
347
+ if (mutations.length === 0) {
348
+ return null;
349
+ }
350
+ mutations.forEach((mutation) => mutation());
351
+ return stringifyHtmlAst(htmlAst);
352
+ };
353
+
354
+ const cookInlineContent = async ({
355
+ context,
356
+ inlineContentUrlInfo,
357
+ inlineContentReference,
358
+ }) => {
359
+ try {
360
+ await context.cook(inlineContentUrlInfo, {
361
+ reference: inlineContentReference,
362
+ });
363
+ } catch (e) {
364
+ if (e.code === "PARSE_ERROR") {
365
+ // When something like <style> or <script> contains syntax error
366
+ // the HTML in itself it still valid
367
+ // keep the syntax error and continue with the HTML
368
+ const messageStart =
369
+ inlineContentUrlInfo.type === "css"
370
+ ? `Syntax error on css declared inside <style>`
371
+ : `Syntax error on js declared inside <script>`;
372
+
373
+ context.logger.error(`${messageStart}: ${e.cause.reasonCode}
374
+ ${e.traceMessage}`);
375
+ } else {
376
+ throw e;
377
+ }
378
+ }
379
+ };
380
+
381
+ const crossOriginCompatibleTagNames = ["script", "link", "img", "source"];
382
+ const integrityCompatibleTagNames = ["script", "link", "img", "source"];
383
+ const readFetchMetas = (node) => {
384
+ const meta = {};
385
+ if (crossOriginCompatibleTagNames.includes(node.nodeName)) {
386
+ const crossorigin = getHtmlNodeAttribute(node, "crossorigin") !== undefined;
387
+ meta.crossorigin = crossorigin;
388
+ }
389
+ if (integrityCompatibleTagNames.includes(node.nodeName)) {
390
+ const integrity = getHtmlNodeAttribute(node, "integrity");
391
+ meta.integrity = integrity;
392
+ }
393
+ return meta;
394
+ };
395
+
396
+ const decideLinkExpectedType = (linkReference, context) => {
397
+ const rel = getHtmlNodeAttribute(linkReference.node, "rel");
398
+ if (rel === "webmanifest") {
399
+ return "webmanifest";
400
+ }
401
+ if (rel === "modulepreload") {
402
+ return "js_module";
403
+ }
404
+ if (rel === "stylesheet") {
405
+ return "css";
406
+ }
407
+ if (rel === "preload") {
408
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload#what_types_of_content_can_be_preloaded
409
+ const as = getHtmlNodeAttribute(linkReference.node, "as");
410
+ if (as === "document") {
411
+ return "html";
412
+ }
413
+ if (as === "style") {
414
+ return "css";
415
+ }
416
+ if (as === "script") {
417
+ const firstScriptOnThisUrl = context.referenceUtils.find(
418
+ (refCandidate) =>
419
+ refCandidate.url === linkReference.url &&
420
+ refCandidate.type === "script",
421
+ );
422
+ if (firstScriptOnThisUrl) {
423
+ return firstScriptOnThisUrl.expectedType;
424
+ }
425
+ return undefined;
426
+ }
427
+ }
428
+ return undefined;
429
+ };
@@ -0,0 +1,7 @@
1
+ /* eslint-env browser,node */
2
+
3
+ const globalObject = typeof self === "object" ? self : process;
4
+ globalObject.__InlineContent__ = function (content, { type = "text/plain" }) {
5
+ this.text = content;
6
+ this.type = type;
7
+ };
@@ -0,0 +1,161 @@
1
+ import { createMagicSource } from "@jsenv/sourcemap";
2
+ import { parseJsUrls } from "@jsenv/ast";
3
+ import { generateInlineContentUrl } from "@jsenv/urls";
4
+ import { JS_QUOTES } from "@jsenv/utils/src/string/js_quotes.js";
5
+ import { CONTENT_TYPE } from "@jsenv/utils/src/content_type/content_type.js";
6
+
7
+ import { isWebWorkerUrlInfo } from "@jsenv/core/src/kitchen/web_workers.js";
8
+
9
+ export const jsenvPluginJsReferenceAnalysis = ({
10
+ inlineContent,
11
+ allowEscapeForVersioning,
12
+ }) => {
13
+ return [
14
+ {
15
+ name: "jsenv:js_reference_analysis",
16
+ appliesDuring: "*",
17
+ transformUrlContent: {
18
+ js_classic: (urlInfo, context) =>
19
+ parseAndTransformJsReferences(urlInfo, context, {
20
+ inlineContent,
21
+ allowEscapeForVersioning,
22
+ }),
23
+ js_module: (urlInfo, context) =>
24
+ parseAndTransformJsReferences(urlInfo, context, {
25
+ inlineContent,
26
+ allowEscapeForVersioning,
27
+ }),
28
+ },
29
+ },
30
+ ];
31
+ };
32
+
33
+ const parseAndTransformJsReferences = async (
34
+ urlInfo,
35
+ context,
36
+ { inlineContent, allowEscapeForVersioning },
37
+ ) => {
38
+ const magicSource = createMagicSource(urlInfo.content);
39
+ const parallelActions = [];
40
+ const sequentialActions = [];
41
+
42
+ const onInlineReference = (inlineReferenceInfo) => {
43
+ const inlineUrl = generateInlineContentUrl({
44
+ url: urlInfo.url,
45
+ extension: CONTENT_TYPE.asFileExtension(inlineReferenceInfo.contentType),
46
+ line: inlineReferenceInfo.line,
47
+ column: inlineReferenceInfo.column,
48
+ lineEnd: inlineReferenceInfo.lineEnd,
49
+ columnEnd: inlineReferenceInfo.columnEnd,
50
+ });
51
+ let { quote } = inlineReferenceInfo;
52
+ if (
53
+ quote === "`" &&
54
+ !context.isSupportedOnCurrentClients("template_literals")
55
+ ) {
56
+ // if quote is "`" and template literals are not supported
57
+ // we'll use a regular string (single or double quote)
58
+ // when rendering the string
59
+ quote = JS_QUOTES.pickBest(inlineReferenceInfo.content);
60
+ }
61
+ const [inlineReference, inlineUrlInfo] = context.referenceUtils.foundInline(
62
+ {
63
+ type: "js_inline_content",
64
+ subtype: inlineReferenceInfo.type, // "new_blob_first_arg", "new_inline_content_first_arg", "json_parse_first_arg"
65
+ isOriginalPosition: urlInfo.content === urlInfo.originalContent,
66
+ specifierLine: inlineReferenceInfo.line,
67
+ specifierColumn: inlineReferenceInfo.column,
68
+ specifier: inlineUrl,
69
+ contentType: inlineReferenceInfo.contentType,
70
+ content: inlineReferenceInfo.content,
71
+ },
72
+ );
73
+ inlineUrlInfo.jsQuote = quote;
74
+ inlineReference.escape = (value) =>
75
+ JS_QUOTES.escapeSpecialChars(value.slice(1, -1), { quote });
76
+
77
+ sequentialActions.push(async () => {
78
+ await context.cook(inlineUrlInfo, { reference: inlineReference });
79
+ const replacement = JS_QUOTES.escapeSpecialChars(inlineUrlInfo.content, {
80
+ quote,
81
+ allowEscapeForVersioning,
82
+ });
83
+ magicSource.replace({
84
+ start: inlineReferenceInfo.start,
85
+ end: inlineReferenceInfo.end,
86
+ replacement,
87
+ });
88
+ });
89
+ };
90
+ const onExternalReference = (externalReferenceInfo) => {
91
+ if (
92
+ externalReferenceInfo.subtype === "import_static" ||
93
+ externalReferenceInfo.subtype === "import_dynamic"
94
+ ) {
95
+ urlInfo.data.usesImport = true;
96
+ }
97
+ const [reference] = context.referenceUtils.found({
98
+ node: externalReferenceInfo.node,
99
+ type: externalReferenceInfo.type,
100
+ subtype: externalReferenceInfo.subtype,
101
+ expectedType: externalReferenceInfo.expectedType,
102
+ expectedSubtype: externalReferenceInfo.expectedSubtype || urlInfo.subtype,
103
+ specifier: externalReferenceInfo.specifier,
104
+ specifierStart: externalReferenceInfo.start,
105
+ specifierEnd: externalReferenceInfo.end,
106
+ specifierLine: externalReferenceInfo.line,
107
+ specifierColumn: externalReferenceInfo.column,
108
+ data: externalReferenceInfo.data,
109
+ baseUrl: {
110
+ "StringLiteral": externalReferenceInfo.baseUrl,
111
+ "window.location": urlInfo.url,
112
+ "window.origin": context.rootDirectoryUrl,
113
+ "import.meta.url": urlInfo.url,
114
+ "context.meta.url": urlInfo.url,
115
+ "document.currentScript.src": urlInfo.url,
116
+ }[externalReferenceInfo.baseUrlType],
117
+ assert: externalReferenceInfo.assert,
118
+ assertNode: externalReferenceInfo.assertNode,
119
+ typePropertyNode: externalReferenceInfo.typePropertyNode,
120
+ });
121
+ parallelActions.push(async () => {
122
+ const replacement = await context.referenceUtils.readGeneratedSpecifier(
123
+ reference,
124
+ );
125
+ magicSource.replace({
126
+ start: externalReferenceInfo.start,
127
+ end: externalReferenceInfo.end,
128
+ replacement,
129
+ });
130
+ if (reference.mutation) {
131
+ reference.mutation(magicSource);
132
+ }
133
+ });
134
+ };
135
+ const jsReferenceInfos = await parseJsUrls({
136
+ js: urlInfo.content,
137
+ url: urlInfo.originalUrl,
138
+ isJsModule: urlInfo.type === "js_module",
139
+ isWebWorker: isWebWorkerUrlInfo(urlInfo),
140
+ inlineContent,
141
+ });
142
+ for (const jsReferenceInfo of jsReferenceInfos) {
143
+ if (jsReferenceInfo.isInline) {
144
+ onInlineReference(jsReferenceInfo);
145
+ } else {
146
+ onExternalReference(jsReferenceInfo);
147
+ }
148
+ }
149
+ if (parallelActions.length > 0) {
150
+ await Promise.all(parallelActions.map((action) => action()));
151
+ }
152
+ if (sequentialActions.length > 0) {
153
+ await sequentialActions.reduce(async (previous, action) => {
154
+ await previous;
155
+ await action();
156
+ }, Promise.resolve());
157
+ }
158
+
159
+ const { content, sourcemap } = magicSource.toContentAndSourcemap();
160
+ return { content, sourcemap };
161
+ };