@jsenv/plugin-transpilation 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/package.json +26 -26
  2. package/src/as_js_module/jsenv_plugin_as_js_module.js +14 -28
  3. package/src/babel/babel_helper_directory/README.md +1 -1
  4. package/src/babel/babel_helper_directory/babel_helpers/applyDecs2301/applyDecs2301.js +547 -528
  5. package/src/babel/babel_helper_directory/babel_helpers/applyDecs2305/applyDecs2305.js +681 -0
  6. package/src/babel/babel_plugin_structure.js +1 -1
  7. package/src/babel/jsenv_plugin_babel.js +91 -19
  8. package/src/babel/new_stylesheet/babel_plugin_new_stylesheet_injector.js +11 -135
  9. package/src/babel/new_stylesheet/constructable_stylesheet_usage.js +114 -0
  10. package/src/babel/new_stylesheet/new_stylesheet_client_file_url.js +4 -0
  11. package/src/babel/regenerator_runtime/babel_plugin_regenerator_runtime_injector.js +11 -35
  12. package/src/babel/regenerator_runtime/regenerator_runtime_client_file_url.js +4 -0
  13. package/src/babel/regenerator_runtime/regenerator_runtime_usage.js +23 -0
  14. package/src/babel/{polyfill_injection_in_babel_ast.js → side_effect_injection_in_babel_ast.js} +8 -8
  15. package/src/css/jsenv_plugin_css_transpilation.js +2 -2
  16. package/src/import_assertions/jsenv_plugin_import_assertions.js +39 -78
  17. package/src/import_meta_resolve/jsenv_plugin_import_meta_resolve.js +17 -13
  18. package/src/js_module_fallback/jsenv_plugin_js_module_conversion.js +56 -48
  19. package/src/js_module_fallback/jsenv_plugin_js_module_fallback.js +3 -38
  20. package/src/js_module_fallback/jsenv_plugin_js_module_fallback_inside_html.js +63 -122
  21. package/src/js_module_fallback/jsenv_plugin_js_module_fallback_on_workers.js +15 -6
  22. package/src/babel/apply_js_transpilation.js +0 -74
  23. package/src/babel/global_this/babel_plugin_global_this_injector.js +0 -56
  24. package/src/babel/global_this/client/global_this_js_classic.js +0 -25
  25. package/src/babel/global_this/client/global_this_js_module.js +0 -21
@@ -19,39 +19,45 @@ export const jsenvPluginImportAssertions = ({
19
19
  text = "auto",
20
20
  }) => {
21
21
  const transpilations = { json, css, text };
22
- const shouldTranspileImportAssertion = (context, type) => {
22
+ const shouldTranspileImportAssertion = (reference, type) => {
23
23
  const transpilation = transpilations[type];
24
24
  if (transpilation === true) {
25
25
  return true;
26
26
  }
27
27
  if (transpilation === "auto") {
28
- return !context.isSupportedOnCurrentClients(`import_type_${type}`);
28
+ return !reference.ownerUrlInfo.context.isSupportedOnCurrentClients(
29
+ `import_type_${type}`,
30
+ );
29
31
  }
30
32
  return false;
31
33
  };
32
34
  const markAsJsModuleProxy = (reference) => {
33
35
  reference.expectedType = "js_module";
34
- reference.filename = `${urlToFilename(reference.url)}.js`;
36
+ if (!reference.filename) {
37
+ reference.filename = `${urlToFilename(reference.url)}.js`;
38
+ }
35
39
  };
36
40
  const turnIntoJsModuleProxy = (reference, type) => {
37
41
  reference.mutation = (magicSource) => {
38
- const { assertNode } = reference;
42
+ const { importTypeAttributeNode } = reference.astInfo;
39
43
  if (reference.subtype === "import_dynamic") {
40
- const assertPropertyNode = assertNode.properties.find(
41
- (prop) => prop.key.name === "assert",
42
- );
43
- const assertPropertyValue = assertPropertyNode.value;
44
- const typePropertyNode = assertPropertyValue.properties.find(
45
- (prop) => prop.key.name === "type",
46
- );
47
44
  magicSource.remove({
48
- start: typePropertyNode.start,
49
- end: typePropertyNode.end,
45
+ start: importTypeAttributeNode.start,
46
+ end: importTypeAttributeNode.end,
50
47
  });
51
48
  } else {
49
+ const content = reference.ownerUrlInfo.content;
50
+ const assertKeyboardStart = content.indexOf(
51
+ "assert",
52
+ importTypeAttributeNode.start - " assert { ".length,
53
+ );
54
+ const assertKeywordEnd = content.indexOf(
55
+ "}",
56
+ importTypeAttributeNode.end,
57
+ );
52
58
  magicSource.remove({
53
- start: assertNode.start,
54
- end: assertNode.end,
59
+ start: assertKeyboardStart,
60
+ end: assertKeywordEnd + 1,
55
61
  });
56
62
  }
57
63
  };
@@ -77,8 +83,8 @@ export const jsenvPluginImportAssertions = ({
77
83
  transpilations.text = true;
78
84
  }
79
85
  },
80
- redirectReference: (reference, context) => {
81
- if (!reference.assert) {
86
+ redirectReference: (reference) => {
87
+ if (!reference.importAttributes) {
82
88
  return null;
83
89
  }
84
90
  const { searchParams } = reference;
@@ -90,8 +96,8 @@ export const jsenvPluginImportAssertions = ({
90
96
  markAsJsModuleProxy(reference);
91
97
  return null;
92
98
  }
93
- const type = reference.assert.type;
94
- if (shouldTranspileImportAssertion(context, type)) {
99
+ const type = reference.importAttributes.type;
100
+ if (shouldTranspileImportAssertion(reference, type)) {
95
101
  return turnIntoJsModuleProxy(reference, type);
96
102
  }
97
103
  return null;
@@ -104,29 +110,14 @@ const jsenvPluginAsModules = () => {
104
110
  const asJsonModule = {
105
111
  name: `jsenv:as_json_module`,
106
112
  appliesDuring: "*",
107
- fetchUrlContent: async (urlInfo, context) => {
108
- const [jsonReference, jsonUrlInfo] = context.getWithoutSearchParam({
109
- urlInfo,
110
- context,
111
- searchParam: "as_json_module",
113
+ fetchUrlContent: async (urlInfo) => {
114
+ const jsonUrlInfo = urlInfo.getWithoutSearchParam("as_json_module", {
112
115
  expectedType: "json",
113
116
  });
114
- if (!jsonReference) {
117
+ if (!jsonUrlInfo) {
115
118
  return null;
116
119
  }
117
- await context.fetchUrlContent(jsonUrlInfo, {
118
- reference: jsonReference,
119
- });
120
- if (context.dev) {
121
- context.referenceUtils.found({
122
- type: "js_import",
123
- subtype: jsonReference.subtype,
124
- specifier: jsonReference.url,
125
- expectedType: "js_module",
126
- });
127
- } else if (context.build && jsonUrlInfo.dependents.size === 0) {
128
- context.urlGraph.deleteUrlInfo(jsonUrlInfo.url);
129
- }
120
+ await jsonUrlInfo.fetchContent();
130
121
  const jsonText = JSON.stringify(jsonUrlInfo.content.trim());
131
122
  return {
132
123
  // here we could `export default ${jsonText}`:
@@ -145,29 +136,14 @@ const jsenvPluginAsModules = () => {
145
136
  const asCssModule = {
146
137
  name: `jsenv:as_css_module`,
147
138
  appliesDuring: "*",
148
- fetchUrlContent: async (urlInfo, context) => {
149
- const [cssReference, cssUrlInfo] = context.getWithoutSearchParam({
150
- urlInfo,
151
- context,
152
- searchParam: "as_css_module",
139
+ fetchUrlContent: async (urlInfo) => {
140
+ const cssUrlInfo = urlInfo.getWithoutSearchParam("as_css_module", {
153
141
  expectedType: "css",
154
142
  });
155
- if (!cssReference) {
143
+ if (!cssUrlInfo) {
156
144
  return null;
157
145
  }
158
- await context.fetchUrlContent(cssUrlInfo, {
159
- reference: cssReference,
160
- });
161
- if (context.dev) {
162
- context.referenceUtils.found({
163
- type: "js_import",
164
- subtype: cssReference.subtype,
165
- specifier: cssReference.url,
166
- expectedType: "js_module",
167
- });
168
- } else if (context.build && cssUrlInfo.dependents.size === 0) {
169
- context.urlGraph.deleteUrlInfo(cssUrlInfo.url);
170
- }
146
+ await cssUrlInfo.fetchContent();
171
147
  const cssText = JS_QUOTES.escapeSpecialChars(cssUrlInfo.content, {
172
148
  // If template string is choosen and runtime do not support template literals
173
149
  // it's ok because "jsenv:new_inline_content" plugin executes after this one
@@ -176,7 +152,7 @@ const jsenvPluginAsModules = () => {
176
152
  });
177
153
  return {
178
154
  content: `import ${JSON.stringify(
179
- context.referenceUtils.inlineContentClientFileUrl,
155
+ urlInfo.context.inlineContentClientFileUrl,
180
156
  )};
181
157
 
182
158
  const inlineContent = new __InlineContent__(${cssText}, { type: "text/css" });
@@ -195,29 +171,14 @@ export default stylesheet;`,
195
171
  const asTextModule = {
196
172
  name: `jsenv:as_text_module`,
197
173
  appliesDuring: "*",
198
- fetchUrlContent: async (urlInfo, context) => {
199
- const [textReference, textUrlInfo] = context.getWithoutSearchParam({
200
- urlInfo,
201
- context,
202
- searchParam: "as_text_module",
174
+ fetchUrlContent: async (urlInfo) => {
175
+ const textUrlInfo = urlInfo.getWithoutSearchParam("as_text_module", {
203
176
  expectedType: "text",
204
177
  });
205
- if (!textReference) {
178
+ if (!textUrlInfo) {
206
179
  return null;
207
180
  }
208
- await context.fetchUrlContent(textUrlInfo, {
209
- reference: textReference,
210
- });
211
- if (context.dev) {
212
- context.referenceUtils.found({
213
- type: "js_import",
214
- subtype: textReference.subtype,
215
- specifier: textReference.url,
216
- expectedType: "js_module",
217
- });
218
- } else if (context.build && textUrlInfo.dependents.size === 0) {
219
- context.urlGraph.deleteUrlInfo(textUrlInfo.url);
220
- }
181
+ await textUrlInfo.fetchContent();
221
182
  const textPlain = JS_QUOTES.escapeSpecialChars(urlInfo.content, {
222
183
  // If template string is choosen and runtime do not support template literals
223
184
  // it's ok because "jsenv:new_inline_content" plugin executes after this one
@@ -226,7 +187,7 @@ export default stylesheet;`,
226
187
  });
227
188
  return {
228
189
  content: `import ${JSON.stringify(
229
- context.referenceUtils.inlineContentClientFileUrl,
190
+ urlInfo.context.inlineContentClientFileUrl,
230
191
  )};
231
192
 
232
193
  const inlineContent = new InlineContent(${textPlain}, { type: "text/plain" });
@@ -15,32 +15,36 @@ export const jsenvPluginImportMetaResolve = () => {
15
15
  return true;
16
16
  },
17
17
  transformUrlContent: {
18
- js_module: async (urlInfo, context) => {
18
+ js_module: async (urlInfo) => {
19
19
  const magicSource = createMagicSource(urlInfo.content);
20
- context.referenceUtils._references.forEach((ref) => {
21
- if (ref.subtype === "import_meta_resolve") {
22
- const originalSpecifierLength = Buffer.byteLength(ref.specifier);
20
+ for (const referenceToOther of urlInfo.referenceToOthersSet) {
21
+ if (referenceToOther.subtype === "import_meta_resolve") {
22
+ const originalSpecifierLength = Buffer.byteLength(
23
+ referenceToOther.specifier,
24
+ );
23
25
  const specifierLength = Buffer.byteLength(
24
- ref.generatedSpecifier.slice(1, -1), // remove `"` around
26
+ referenceToOther.generatedSpecifier.slice(1, -1), // remove `"` around
25
27
  );
26
28
  const specifierLengthDiff =
27
29
  specifierLength - originalSpecifierLength;
28
- const end = ref.node.end + specifierLengthDiff;
30
+ const { node } = referenceToOther.astInfo;
31
+ const end = node.end + specifierLengthDiff;
29
32
  magicSource.replace({
30
- start: ref.node.start,
33
+ start: node.start,
31
34
  end,
32
- replacement: `new URL(${ref.generatedSpecifier}, import.meta.url).href`,
35
+ replacement: `new URL(${referenceToOther.generatedSpecifier}, import.meta.url).href`,
33
36
  });
34
37
  const currentLengthBeforeSpecifier = "import.meta.resolve(".length;
35
38
  const newLengthBeforeSpecifier = "new URL(".length;
36
39
  const lengthDiff =
37
40
  currentLengthBeforeSpecifier - newLengthBeforeSpecifier;
38
- ref.specifierColumn -= lengthDiff;
39
- ref.specifierStart -= lengthDiff;
40
- ref.specifierEnd =
41
- ref.specifierStart + Buffer.byteLength(ref.generatedSpecifier);
41
+ referenceToOther.specifierColumn -= lengthDiff;
42
+ referenceToOther.specifierStart -= lengthDiff;
43
+ referenceToOther.specifierEnd =
44
+ referenceToOther.specifierStart +
45
+ Buffer.byteLength(referenceToOther.generatedSpecifier);
42
46
  }
43
- });
47
+ }
44
48
  return magicSource.toContentAndSourcemap();
45
49
  },
46
50
  },
@@ -3,14 +3,13 @@
3
3
  * - perform conversion from js module to js classic when url uses "?js_module_fallback"
4
4
  */
5
5
 
6
- import { injectQueryParams } from "@jsenv/urls";
7
- import { convertJsModuleToJsClassic } from "@jsenv/js-module-fallback";
6
+ import { urlToFilename, injectQueryParams } from "@jsenv/urls";
7
+ import {
8
+ convertJsModuleToJsClassic,
9
+ systemJsClientFileUrlDefault,
10
+ } from "@jsenv/js-module-fallback";
8
11
 
9
- export const jsenvPluginJsModuleConversion = ({
10
- systemJsInjection,
11
- systemJsClientFileUrl,
12
- generateJsClassicFilename,
13
- }) => {
12
+ export const jsenvPluginJsModuleConversion = () => {
14
13
  const isReferencingJsModule = (reference) => {
15
14
  if (
16
15
  reference.type === "js_import" ||
@@ -25,23 +24,20 @@ export const jsenvPluginJsModuleConversion = ({
25
24
  return false;
26
25
  };
27
26
 
28
- const shouldPropagateJsModuleConversion = (reference, context) => {
29
- if (isReferencingJsModule(reference, context)) {
30
- const parentUrlInfo = context.urlGraph.getUrlInfo(reference.parentUrl);
31
- if (!parentUrlInfo) {
32
- return false;
33
- }
34
- const parentGotAsJsClassic = new URL(parentUrlInfo.url).searchParams.has(
35
- "js_module_fallback",
36
- );
37
- return parentGotAsJsClassic;
27
+ const shouldPropagateJsModuleConversion = (reference) => {
28
+ if (isReferencingJsModule(reference)) {
29
+ const insideJsClassic =
30
+ reference.ownerUrlInfo.searchParams.has("js_module_fallback");
31
+ return insideJsClassic;
38
32
  }
39
33
  return false;
40
34
  };
41
35
 
42
36
  const markAsJsClassicProxy = (reference) => {
43
37
  reference.expectedType = "js_classic";
44
- reference.filename = generateJsClassicFilename(reference.url);
38
+ if (!reference.filename) {
39
+ reference.filename = generateJsClassicFilename(reference.url);
40
+ }
45
41
  };
46
42
 
47
43
  const turnIntoJsClassicProxy = (reference) => {
@@ -55,7 +51,7 @@ export const jsenvPluginJsModuleConversion = ({
55
51
  return {
56
52
  name: "jsenv:js_module_conversion",
57
53
  appliesDuring: "*",
58
- redirectReference: (reference, context) => {
54
+ redirectReference: (reference) => {
59
55
  if (reference.searchParams.has("js_module_fallback")) {
60
56
  markAsJsClassicProxy(reference);
61
57
  return null;
@@ -66,39 +62,25 @@ export const jsenvPluginJsModuleConversion = ({
66
62
  // (because it's the transpiled equivalent of static and dynamic imports)
67
63
  // And not other references otherwise we could try to transform inline resources
68
64
  // or specifiers inside new URL()...
69
- if (shouldPropagateJsModuleConversion(reference, context)) {
70
- return turnIntoJsClassicProxy(reference, context);
65
+ if (shouldPropagateJsModuleConversion(reference)) {
66
+ return turnIntoJsClassicProxy(reference);
71
67
  }
72
68
  return null;
73
69
  },
74
- fetchUrlContent: async (urlInfo, context) => {
75
- const [jsModuleReference, jsModuleUrlInfo] =
76
- context.getWithoutSearchParam({
77
- urlInfo,
78
- context,
79
- searchParam: "js_module_fallback",
70
+ fetchUrlContent: async (urlInfo) => {
71
+ const jsModuleUrlInfo = urlInfo.getWithoutSearchParam(
72
+ "js_module_fallback",
73
+ {
80
74
  // override the expectedType to "js_module"
81
75
  // because when there is ?js_module_fallback it means the underlying resource
82
76
  // is a js_module
83
77
  expectedType: "js_module",
84
- });
85
- if (!jsModuleReference) {
78
+ },
79
+ );
80
+ if (!jsModuleUrlInfo) {
86
81
  return null;
87
82
  }
88
- await context.fetchUrlContent(jsModuleUrlInfo, {
89
- reference: jsModuleReference,
90
- });
91
- if (context.dev) {
92
- context.referenceUtils.found({
93
- type: "js_import",
94
- subtype: jsModuleReference.subtype,
95
- specifier: jsModuleReference.url,
96
- expectedType: "js_module",
97
- });
98
- } else if (context.build && jsModuleUrlInfo.dependents.size === 0) {
99
- context.urlGraph.deleteUrlInfo(jsModuleUrlInfo.url);
100
- }
101
-
83
+ await jsModuleUrlInfo.fetchContent();
102
84
  let outputFormat;
103
85
  if (urlInfo.isEntryPoint && !jsModuleUrlInfo.data.usesImport) {
104
86
  // if it's an entry point without dependency (it does not use import)
@@ -109,17 +91,21 @@ export const jsenvPluginJsModuleConversion = ({
109
91
  // by an other file (for entry points)
110
92
  // or to be able to import when it uses import
111
93
  outputFormat = "system";
94
+ urlInfo.type = "js_classic";
95
+ urlInfo.dependencies.foundSideEffectFile({
96
+ sideEffectFileUrl: systemJsClientFileUrlDefault,
97
+ expectedType: "js_classic",
98
+ line: 0,
99
+ column: 0,
100
+ });
112
101
  }
113
- urlInfo.data.jsClassicFormat = outputFormat;
114
102
  const { content, sourcemap } = await convertJsModuleToJsClassic({
115
- rootDirectoryUrl: context.rootDirectoryUrl,
116
- systemJsInjection,
117
- systemJsClientFileUrl,
103
+ rootDirectoryUrl: urlInfo.context.rootDirectoryUrl,
118
104
  input: jsModuleUrlInfo.content,
119
105
  inputIsEntryPoint: urlInfo.isEntryPoint,
120
106
  inputSourcemap: jsModuleUrlInfo.sourcemap,
121
107
  inputUrl: jsModuleUrlInfo.url,
122
- outputUrl: jsModuleUrlInfo.generatedUrl,
108
+ outputUrl: urlInfo.url,
123
109
  outputFormat,
124
110
  });
125
111
  return {
@@ -134,3 +120,25 @@ export const jsenvPluginJsModuleConversion = ({
134
120
  },
135
121
  };
136
122
  };
123
+
124
+ const generateJsClassicFilename = (url) => {
125
+ const filename = urlToFilename(url);
126
+ let [basename, extension] = splitFileExtension(filename);
127
+ const { searchParams } = new URL(url);
128
+ if (
129
+ searchParams.has("as_json_module") ||
130
+ searchParams.has("as_css_module") ||
131
+ searchParams.has("as_text_module")
132
+ ) {
133
+ extension = ".js";
134
+ }
135
+ return `${basename}.nomodule${extension}`;
136
+ };
137
+
138
+ const splitFileExtension = (filename) => {
139
+ const dotLastIndex = filename.lastIndexOf(".");
140
+ if (dotLastIndex === -1) {
141
+ return [filename, ""];
142
+ }
143
+ return [filename.slice(0, dotLastIndex), filename.slice(dotLastIndex)];
144
+ };
@@ -1,46 +1,11 @@
1
- import { urlToFilename } from "@jsenv/urls";
2
- import { systemJsClientFileUrlDefault } from "@jsenv/js-module-fallback";
3
-
4
1
  import { jsenvPluginJsModuleConversion } from "./jsenv_plugin_js_module_conversion.js";
5
2
  import { jsenvPluginJsModuleFallbackInsideHtml } from "./jsenv_plugin_js_module_fallback_inside_html.js";
6
3
  import { jsenvPluginJsModuleFallbackOnWorkers } from "./jsenv_plugin_js_module_fallback_on_workers.js";
7
4
 
8
- export const jsenvPluginJsModuleFallback = ({
9
- systemJsInjection = true,
10
- systemJsClientFileUrl = systemJsClientFileUrlDefault,
11
- }) => {
5
+ export const jsenvPluginJsModuleFallback = () => {
12
6
  return [
13
- jsenvPluginJsModuleFallbackInsideHtml({
14
- systemJsInjection,
15
- systemJsClientFileUrl,
16
- }),
7
+ jsenvPluginJsModuleFallbackInsideHtml(),
17
8
  jsenvPluginJsModuleFallbackOnWorkers(),
18
- jsenvPluginJsModuleConversion({
19
- systemJsInjection,
20
- systemJsClientFileUrl,
21
- generateJsClassicFilename,
22
- }),
9
+ jsenvPluginJsModuleConversion(),
23
10
  ];
24
11
  };
25
-
26
- const generateJsClassicFilename = (url) => {
27
- const filename = urlToFilename(url);
28
- let [basename, extension] = splitFileExtension(filename);
29
- const { searchParams } = new URL(url);
30
- if (
31
- searchParams.has("as_json_module") ||
32
- searchParams.has("as_css_module") ||
33
- searchParams.has("as_text_module")
34
- ) {
35
- extension = ".js";
36
- }
37
- return `${basename}.nomodule${extension}`;
38
- };
39
-
40
- const splitFileExtension = (filename) => {
41
- const dotLastIndex = filename.lastIndexOf(".");
42
- if (dotLastIndex === -1) {
43
- return [filename, ""];
44
- }
45
- return [filename.slice(0, dotLastIndex), filename.slice(dotLastIndex)];
46
- };