@jsenv/core 27.3.3 → 27.5.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 (89) hide show
  1. package/dist/js/autoreload.js +359 -0
  2. package/dist/js/execute_using_dynamic_import.js +1 -1
  3. package/dist/js/html_supervisor_installer.js +524 -147
  4. package/dist/js/html_supervisor_setup.js +3 -4
  5. package/dist/js/new_stylesheet.js +26 -58
  6. package/dist/js/server_events_client.js +307 -0
  7. package/dist/main.js +7699 -7307
  8. package/package.json +15 -15
  9. package/{README.md → readme.md} +18 -7
  10. package/src/build/build.js +16 -18
  11. package/src/build/start_build_server.js +24 -28
  12. package/src/dev/start_dev_server.js +30 -94
  13. package/src/execute/execute.js +17 -35
  14. package/src/execute/run.js +2 -0
  15. package/src/omega/errors.js +43 -9
  16. package/src/omega/kitchen.js +42 -25
  17. package/src/omega/omega_server.js +96 -74
  18. package/src/omega/server/file_service.js +256 -28
  19. package/src/omega/url_graph.js +39 -20
  20. package/src/plugins/autoreload/client/autoreload.js +201 -0
  21. package/src/plugins/autoreload/{dev_sse/client → client}/autoreload_preference.js +0 -0
  22. package/src/plugins/autoreload/{dev_sse/client → client}/reload.js +29 -10
  23. package/src/plugins/autoreload/{dev_sse/client → client}/url_helpers.js +0 -0
  24. package/src/plugins/autoreload/jsenv_plugin_autoreload.js +4 -8
  25. package/src/plugins/autoreload/{dev_sse/jsenv_plugin_dev_sse_client.js → jsenv_plugin_autoreload_client.js} +8 -8
  26. package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +196 -0
  27. package/src/{dev/plugins → plugins}/explorer/client/explorer.html +0 -0
  28. package/src/{dev/plugins → plugins}/explorer/client/jsenv.png +0 -0
  29. package/src/{dev/plugins → plugins}/explorer/jsenv_plugin_explorer.js +1 -3
  30. package/src/plugins/html_supervisor/client/error_overlay.js +401 -0
  31. package/src/plugins/html_supervisor/client/html_supervisor_installer.js +138 -23
  32. package/src/plugins/html_supervisor/client/html_supervisor_setup.js +3 -4
  33. package/src/plugins/html_supervisor/jsenv_plugin_html_supervisor.js +55 -23
  34. package/src/plugins/inline/jsenv_plugin_html_inline_content.js +97 -117
  35. package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +66 -58
  36. package/src/plugins/plugin_controller.js +102 -67
  37. package/src/plugins/plugins.js +10 -10
  38. package/src/{helpers/event_source/event_source.js → plugins/server_events/client/event_source_connection.js} +125 -33
  39. package/src/plugins/server_events/client/server_events_client.js +17 -0
  40. package/src/plugins/server_events/jsenv_plugin_server_events_client_injection.js +48 -0
  41. package/src/plugins/server_events/server_events_dispatcher.js +69 -0
  42. package/src/{dev/plugins → plugins}/toolbar/client/animation/toolbar_animation.js +0 -0
  43. package/src/{dev/plugins → plugins}/toolbar/client/eventsource/eventsource.css +0 -0
  44. package/src/{dev/plugins → plugins}/toolbar/client/eventsource/toolbar_eventsource.js +0 -0
  45. package/src/{dev/plugins → plugins}/toolbar/client/execution/execution.css +0 -0
  46. package/src/{dev/plugins → plugins}/toolbar/client/execution/toolbar_execution.js +0 -0
  47. package/src/{dev/plugins → plugins}/toolbar/client/focus/focus.css +0 -0
  48. package/src/{dev/plugins → plugins}/toolbar/client/focus/toolbar_focus.js +0 -0
  49. package/src/{dev/plugins → plugins}/toolbar/client/jsenv_logo.svg +0 -0
  50. package/src/{dev/plugins → plugins}/toolbar/client/notification/toolbar_notification.js +0 -0
  51. package/src/{dev/plugins → plugins}/toolbar/client/responsive/overflow_menu.css +0 -0
  52. package/src/{dev/plugins → plugins}/toolbar/client/responsive/toolbar_responsive.js +0 -0
  53. package/src/{dev/plugins → plugins}/toolbar/client/settings/settings.css +0 -0
  54. package/src/{dev/plugins → plugins}/toolbar/client/settings/toolbar_settings.js +0 -0
  55. package/src/{dev/plugins → plugins}/toolbar/client/theme/jsenv_theme.css +0 -0
  56. package/src/{dev/plugins → plugins}/toolbar/client/theme/light_theme.css +0 -0
  57. package/src/{dev/plugins → plugins}/toolbar/client/theme/toolbar_theme.js +0 -0
  58. package/src/{dev/plugins → plugins}/toolbar/client/toolbar.html +0 -0
  59. package/src/{dev/plugins → plugins}/toolbar/client/toolbar_injector.js +0 -0
  60. package/src/{dev/plugins → plugins}/toolbar/client/toolbar_main.css +0 -0
  61. package/src/{dev/plugins → plugins}/toolbar/client/toolbar_main.js +0 -0
  62. package/src/{dev/plugins → plugins}/toolbar/client/tooltip/tooltip.css +0 -0
  63. package/src/{dev/plugins → plugins}/toolbar/client/tooltip/tooltip.js +0 -0
  64. package/src/{dev/plugins → plugins}/toolbar/client/util/animation.js +0 -0
  65. package/src/{dev/plugins → plugins}/toolbar/client/util/dom.js +0 -0
  66. package/src/{dev/plugins → plugins}/toolbar/client/util/fetch_using_xhr.js +0 -0
  67. package/src/{dev/plugins → plugins}/toolbar/client/util/fetching.js +0 -0
  68. package/src/{dev/plugins → plugins}/toolbar/client/util/iframe_to_parent_href.js +0 -0
  69. package/src/{dev/plugins → plugins}/toolbar/client/util/jsenv_logger.js +0 -0
  70. package/src/{dev/plugins → plugins}/toolbar/client/util/preferences.js +0 -0
  71. package/src/{dev/plugins → plugins}/toolbar/client/util/responsive.js +0 -0
  72. package/src/{dev/plugins → plugins}/toolbar/client/util/util.js +0 -0
  73. package/src/{dev/plugins → plugins}/toolbar/client/variant/variant.js +0 -0
  74. package/src/{dev/plugins → plugins}/toolbar/jsenv_plugin_toolbar.js +0 -0
  75. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_html.js +4 -3
  76. package/src/plugins/transpilation/babel/new_stylesheet/client/new_stylesheet.js +25 -55
  77. package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +44 -24
  78. package/src/plugins/transpilation/jsenv_plugin_transpilation.js +6 -1
  79. package/src/plugins/url_analysis/html/html_urls.js +8 -8
  80. package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +3 -1
  81. package/src/test/execute_plan.js +36 -54
  82. package/src/test/execute_test_plan.js +2 -2
  83. package/src/test/logs_file_execution.js +60 -27
  84. package/src/test/logs_file_execution.test.mjs +41 -0
  85. package/dist/js/event_source_client.js +0 -528
  86. package/src/helpers/event_source/sse_service.js +0 -53
  87. package/src/plugins/autoreload/dev_sse/client/event_source_client.js +0 -193
  88. package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js +0 -203
  89. package/src/plugins/html_supervisor/client/error_in_document.js +0 -198
@@ -4,6 +4,7 @@
4
4
  * - scripts are wrapped to be supervised
5
5
  */
6
6
 
7
+ import { fileURLToPath } from "node:url"
7
8
  import {
8
9
  parseHtmlString,
9
10
  stringifyHtmlAst,
@@ -20,9 +21,13 @@ import {
20
21
  } from "@jsenv/ast"
21
22
  import { generateInlineContentUrl } from "@jsenv/urls"
22
23
 
24
+ import { requireFromJsenv } from "@jsenv/core/src/require_from_jsenv.js"
25
+
23
26
  export const jsenvPluginHtmlSupervisor = ({
24
27
  logs = false,
25
28
  measurePerf = false,
29
+ errorOverlay = true,
30
+ openInEditor = true,
26
31
  }) => {
27
32
  const htmlSupervisorSetupFileUrl = new URL(
28
33
  "./client/html_supervisor_setup.js?js_classic",
@@ -40,30 +45,47 @@ export const jsenvPluginHtmlSupervisor = ({
40
45
  dev: true,
41
46
  test: true,
42
47
  },
48
+ serve: (request) => {
49
+ if (!request.ressource.startsWith("/__open_in_editor__/")) {
50
+ return null
51
+ }
52
+ const file = request.ressource.slice("/__open_in_editor__/".length)
53
+ if (!file) {
54
+ return {
55
+ status: 400,
56
+ body: 'Missing "file" in url search params',
57
+ }
58
+ }
59
+ const launch = requireFromJsenv("launch-editor")
60
+ launch(fileURLToPath(file), () => {
61
+ // ignore error for now
62
+ })
63
+ return {
64
+ status: 200,
65
+ }
66
+ },
43
67
  transformUrlContent: {
44
- html: ({ url, content }, { referenceUtils }) => {
68
+ html: ({ url, content }, context) => {
45
69
  const htmlAst = parseHtmlString(content)
46
70
  const scriptsToSupervise = []
47
71
 
48
72
  const handleInlineScript = (node, htmlNodeText) => {
49
- const scriptCategory = analyzeScriptNode(node)
73
+ const { type, extension } = analyzeScriptNode(node)
50
74
  const { line, column, lineEnd, columnEnd, isOriginal } =
51
75
  getHtmlNodePosition(node, {
52
76
  preferOriginal: true,
53
77
  })
54
78
  let inlineScriptUrl = generateInlineContentUrl({
55
79
  url,
56
- extension: ".js",
80
+ extension: extension || ".js",
57
81
  line,
58
82
  column,
59
83
  lineEnd,
60
84
  columnEnd,
61
85
  })
62
- const [inlineScriptReference] = referenceUtils.foundInline({
86
+ const [inlineScriptReference] = context.referenceUtils.foundInline({
63
87
  type: "script_src",
64
- expectedType: { classic: "js_classic", module: "js_module" }[
65
- scriptCategory
66
- ],
88
+ expectedType: type,
67
89
  isOriginalPosition: isOriginal,
68
90
  specifierLine: line - 1,
69
91
  specifierColumn: column,
@@ -72,15 +94,20 @@ export const jsenvPluginHtmlSupervisor = ({
72
94
  content: htmlNodeText,
73
95
  })
74
96
  removeHtmlNodeText(node)
97
+ if (extension) {
98
+ setHtmlNodeAttributes(node, {
99
+ type: type === "js_module" ? "module" : undefined,
100
+ })
101
+ }
75
102
  scriptsToSupervise.push({
76
103
  node,
77
104
  isInline: true,
78
- type: scriptCategory,
105
+ type,
79
106
  src: inlineScriptReference.generatedSpecifier,
80
107
  })
81
108
  }
82
109
  const handleScriptWithSrc = (node, src) => {
83
- const scriptCategory = analyzeScriptNode(node)
110
+ const { type } = analyzeScriptNode(node)
84
111
  const integrity = getHtmlNodeAttribute(node, "integrity")
85
112
  const crossorigin =
86
113
  getHtmlNodeAttribute(node, "crossorigin") !== undefined
@@ -91,7 +118,7 @@ export const jsenvPluginHtmlSupervisor = ({
91
118
  })
92
119
  scriptsToSupervise.push({
93
120
  node,
94
- type: scriptCategory,
121
+ type,
95
122
  src,
96
123
  defer,
97
124
  async,
@@ -101,8 +128,8 @@ export const jsenvPluginHtmlSupervisor = ({
101
128
  }
102
129
  visitHtmlNodes(htmlAst, {
103
130
  script: (node) => {
104
- const scriptCategory = analyzeScriptNode(node)
105
- if (scriptCategory !== "classic" && scriptCategory !== "module") {
131
+ const { type } = analyzeScriptNode(node)
132
+ if (type !== "js_classic" && type !== "js_module") {
106
133
  return
107
134
  }
108
135
  const injectedBy = getHtmlNodeAttribute(node, "injected-by")
@@ -128,11 +155,12 @@ export const jsenvPluginHtmlSupervisor = ({
128
155
  }
129
156
  },
130
157
  })
131
- const [htmlSupervisorInstallerFileReference] = referenceUtils.inject({
132
- type: "js_import_export",
133
- expectedType: "js_module",
134
- specifier: htmlSupervisorInstallerFileUrl,
135
- })
158
+ const [htmlSupervisorInstallerFileReference] =
159
+ context.referenceUtils.inject({
160
+ type: "js_import_export",
161
+ expectedType: "js_module",
162
+ specifier: htmlSupervisorInstallerFileUrl,
163
+ })
136
164
  injectScriptNodeAsEarlyAsPossible(
137
165
  htmlAst,
138
166
  createHtmlNode({
@@ -144,8 +172,11 @@ export const jsenvPluginHtmlSupervisor = ({
144
172
  }
145
173
  installHtmlSupervisor(${JSON.stringify(
146
174
  {
175
+ rootDirectoryUrl: context.rootDirectoryUrl,
147
176
  logs,
148
177
  measurePerf,
178
+ errorOverlay,
179
+ openInEditor,
149
180
  },
150
181
  null,
151
182
  " ",
@@ -153,11 +184,12 @@ export const jsenvPluginHtmlSupervisor = ({
153
184
  "injected-by": "jsenv:html_supervisor",
154
185
  }),
155
186
  )
156
- const [htmlSupervisorSetupFileReference] = referenceUtils.inject({
157
- type: "script_src",
158
- expectedType: "js_classic",
159
- specifier: htmlSupervisorSetupFileUrl,
160
- })
187
+ const [htmlSupervisorSetupFileReference] =
188
+ context.referenceUtils.inject({
189
+ type: "script_src",
190
+ expectedType: "js_classic",
191
+ specifier: htmlSupervisorSetupFileUrl,
192
+ })
161
193
  injectScriptNodeAsEarlyAsPossible(
162
194
  htmlAst,
163
195
  createHtmlNode({
@@ -227,7 +259,7 @@ const generateCodeToSuperviseScript = ({
227
259
  integrity,
228
260
  crossorigin,
229
261
  })
230
- if (type === "module") {
262
+ if (type === "js_module") {
231
263
  return `
232
264
  import { superviseScriptTypeModule } from ${htmlSupervisorInstallerSpecifier}
233
265
  superviseScriptTypeModule(${paramsAsJson})
@@ -20,129 +20,109 @@ export const jsenvPluginHtmlInlineContent = ({ analyzeConvertedScripts }) => {
20
20
  html: async (urlInfo, context) => {
21
21
  const htmlAst = parseHtmlString(urlInfo.content)
22
22
  const actions = []
23
- const handleInlineStyle = (node) => {
24
- const htmlNodeText = getHtmlNodeText(node)
25
- if (!htmlNodeText) {
26
- return
27
- }
28
- actions.push(async () => {
29
- const { line, column, lineEnd, columnEnd, isOriginal } =
30
- getHtmlNodePosition(node, {
31
- preferOriginal: true,
23
+ visitHtmlNodes(htmlAst, {
24
+ style: (styleNode) => {
25
+ const styleNodeText = getHtmlNodeText(styleNode)
26
+ if (!styleNodeText) {
27
+ return
28
+ }
29
+ actions.push(async () => {
30
+ const { line, column, lineEnd, columnEnd, isOriginal } =
31
+ getHtmlNodePosition(styleNode, {
32
+ preferOriginal: true,
33
+ })
34
+ const inlineStyleUrl = generateInlineContentUrl({
35
+ url: urlInfo.url,
36
+ extension: ".css",
37
+ line,
38
+ column,
39
+ lineEnd,
40
+ columnEnd,
32
41
  })
33
- const inlineStyleUrl = generateInlineContentUrl({
34
- url: urlInfo.url,
35
- extension: ".css",
36
- line,
37
- column,
38
- lineEnd,
39
- columnEnd,
40
- })
41
- const [inlineStyleReference, inlineStyleUrlInfo] =
42
- context.referenceUtils.foundInline({
43
- type: "link_href",
44
- expectedType: "css",
45
- isOriginalPosition: isOriginal,
46
- // we remove 1 to the line because imagine the following html:
47
- // <style>body { color: red; }</style>
48
- // -> content starts same line as <style>
49
- specifierLine: line - 1,
50
- specifierColumn: column,
51
- specifier: inlineStyleUrl,
52
- contentType: "text/css",
53
- content: htmlNodeText,
42
+ const [inlineStyleReference, inlineStyleUrlInfo] =
43
+ context.referenceUtils.foundInline({
44
+ node: styleNode,
45
+ type: "link_href",
46
+ expectedType: "css",
47
+ isOriginalPosition: isOriginal,
48
+ // we remove 1 to the line because imagine the following html:
49
+ // <style>body { color: red; }</style>
50
+ // -> content starts same line as <style>
51
+ specifierLine: line - 1,
52
+ specifierColumn: column,
53
+ specifier: inlineStyleUrl,
54
+ contentType: "text/css",
55
+ content: styleNodeText,
56
+ })
57
+ await context.cook(inlineStyleUrlInfo, {
58
+ reference: inlineStyleReference,
54
59
  })
55
- await context.cook(inlineStyleUrlInfo, {
56
- reference: inlineStyleReference,
57
- })
58
- setHtmlNodeText(node, inlineStyleUrlInfo.content)
59
- setHtmlNodeAttributes(node, {
60
- "generated-by": "jsenv:html_inline_content",
61
- })
62
- })
63
- }
64
- const handleInlineScript = (node) => {
65
- const htmlNodeText = getHtmlNodeText(node)
66
- if (!htmlNodeText) {
67
- return
68
- }
69
- // If the inline script was already handled by an other plugin, ignore it
70
- // - we want to preserve inline scripts generated by html supervisor during dev
71
- // - we want to avoid cooking twice a script during build
72
- const generatedBy = getHtmlNodeAttribute(node, "generated-by")
73
- if (
74
- generatedBy === "jsenv:as_js_classic_html" &&
75
- !analyzeConvertedScripts
76
- ) {
77
- return
78
- }
79
- if (generatedBy === "jsenv:html_supervisor") {
80
- return
81
- }
82
- actions.push(async () => {
83
- const scriptCategory = analyzeScriptNode(node)
84
- const { line, column, lineEnd, columnEnd, isOriginal } =
85
- getHtmlNodePosition(node, {
86
- preferOriginal: true,
60
+ setHtmlNodeText(styleNode, inlineStyleUrlInfo.content)
61
+ setHtmlNodeAttributes(styleNode, {
62
+ "generated-by": "jsenv:html_inline_content",
87
63
  })
88
- // from MDN about [type] attribute:
89
- // "Any other value: The embedded content is treated as a data block
90
- // which won't be processed by the browser. Developers must use a valid MIME type
91
- // that is not a JavaScript MIME type to denote data blocks.
92
- // The src attribute will be ignored."
93
- // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-type
94
- const isJs =
95
- scriptCategory === "classic" || scriptCategory === "module"
96
- const isImportmap = scriptCategory === "importmap"
97
- const contentType = isJs
98
- ? "text/javascript"
99
- : isImportmap
100
- ? "application/importmap+json"
101
- : scriptCategory
102
-
103
- let inlineScriptUrl = generateInlineContentUrl({
104
- url: urlInfo.url,
105
- extension: CONTENT_TYPE.asFileExtension(contentType),
106
- line,
107
- column,
108
- lineEnd,
109
- columnEnd,
110
64
  })
111
- const [inlineScriptReference, inlineScriptUrlInfo] =
112
- context.referenceUtils.foundInline({
113
- node,
114
- type: "script_src",
115
- expectedType: {
116
- classic: "js_classic",
117
- module: "js_module",
118
- importmap: "importmap",
119
- }[scriptCategory],
120
- // we remove 1 to the line because imagine the following html:
121
- // <script>console.log('ok')</script>
122
- // -> content starts same line as <script>
123
- specifierLine: line - 1,
124
- specifierColumn: column,
125
- isOriginalPosition: isOriginal,
126
- specifier: inlineScriptUrl,
127
- contentType,
128
- content: htmlNodeText,
65
+ },
66
+ script: (scriptNode) => {
67
+ const scriptNodeText = getHtmlNodeText(scriptNode)
68
+ if (!scriptNodeText) {
69
+ return
70
+ }
71
+ // If the inline script was already handled by an other plugin, ignore it
72
+ // - we want to preserve inline scripts generated by html supervisor during dev
73
+ // - we want to avoid cooking twice a script during build
74
+ const generatedBy = getHtmlNodeAttribute(scriptNode, "generated-by")
75
+ if (
76
+ generatedBy === "jsenv:as_js_classic_html" &&
77
+ !analyzeConvertedScripts
78
+ ) {
79
+ return
80
+ }
81
+ if (generatedBy === "jsenv:html_supervisor") {
82
+ return
83
+ }
84
+ actions.push(async () => {
85
+ const { type, contentType, extension } =
86
+ analyzeScriptNode(scriptNode)
87
+ const { line, column, lineEnd, columnEnd, isOriginal } =
88
+ getHtmlNodePosition(scriptNode, {
89
+ preferOriginal: true,
90
+ })
91
+ let inlineScriptUrl = generateInlineContentUrl({
92
+ url: urlInfo.url,
93
+ extension:
94
+ extension || CONTENT_TYPE.asFileExtension(contentType),
95
+ line,
96
+ column,
97
+ lineEnd,
98
+ columnEnd,
99
+ })
100
+ const [inlineScriptReference, inlineScriptUrlInfo] =
101
+ context.referenceUtils.foundInline({
102
+ node: scriptNode,
103
+ type: "script_src",
104
+ expectedType: type,
105
+ // we remove 1 to the line because imagine the following html:
106
+ // <script>console.log('ok')</script>
107
+ // -> content starts same line as <script>
108
+ specifierLine: line - 1,
109
+ specifierColumn: column,
110
+ isOriginalPosition: isOriginal,
111
+ specifier: inlineScriptUrl,
112
+ contentType,
113
+ content: scriptNodeText,
114
+ })
115
+ await context.cook(inlineScriptUrlInfo, {
116
+ reference: inlineScriptReference,
117
+ })
118
+ setHtmlNodeText(scriptNode, inlineScriptUrlInfo.content)
119
+ setHtmlNodeAttributes(scriptNode, {
120
+ "generated-by": "jsenv:html_inline_content",
121
+ ...(extension
122
+ ? { type: type === "js_module" ? "module" : undefined }
123
+ : {}),
129
124
  })
130
-
131
- await context.cook(inlineScriptUrlInfo, {
132
- reference: inlineScriptReference,
133
- })
134
- setHtmlNodeText(node, inlineScriptUrlInfo.content)
135
- setHtmlNodeAttributes(node, {
136
- "generated-by": "jsenv:html_inline_content",
137
125
  })
138
- })
139
- }
140
- visitHtmlNodes(htmlAst, {
141
- style: (node) => {
142
- handleInlineStyle(node)
143
- },
144
- script: (node) => {
145
- handleInlineScript(node)
146
126
  },
147
127
  })
148
128
  if (actions.length === 0) {
@@ -17,72 +17,78 @@ import {
17
17
  } from "@jsenv/node-esm-resolution"
18
18
 
19
19
  export const jsenvPluginNodeEsmResolution = ({
20
- rootDirectoryUrl,
21
- urlGraph,
22
- runtimeCompat,
23
20
  packageConditions,
24
21
  filesInvalidatingCache = ["package.json", "package-lock.json"],
25
22
  }) => {
26
- const nodeRuntimeEnabled = Object.keys(runtimeCompat).includes("node")
27
- // https://nodejs.org/api/esm.html#resolver-algorithm-specification
28
- packageConditions = packageConditions || [
29
- ...readCustomConditionsFromProcessArgs(),
30
- nodeRuntimeEnabled ? "node" : "browser",
31
- "import",
32
- ]
33
-
34
- const packageScopesCache = new Map()
35
- const lookupPackageScope = (url) => {
36
- const fromCache = packageScopesCache.get(url)
37
- if (fromCache) {
38
- return fromCache
39
- }
40
- const packageScope = defaultLookupPackageScope(url)
41
- packageScopesCache.set(url, packageScope)
42
- return packageScope
43
- }
44
- const packageJsonsCache = new Map()
45
- const readPackageJson = (url) => {
46
- const fromCache = packageJsonsCache.get(url)
47
- if (fromCache) {
48
- return fromCache
49
- }
50
- const packageJson = defaultReadPackageJson(url)
51
- packageJsonsCache.set(url, packageJson)
52
- return packageJson
53
- }
54
-
55
23
  const unregisters = []
56
- const onFileChange = () => {
57
- packageScopesCache.clear()
58
- packageJsonsCache.clear()
59
- urlGraph.urlInfoMap.forEach((urlInfo) => {
60
- if (urlInfo.dependsOnPackageJson) {
61
- urlGraph.considerModified(urlInfo)
62
- }
63
- })
64
- }
65
- filesInvalidatingCache.forEach((file) => {
66
- const unregister = registerFileLifecycle(new URL(file, rootDirectoryUrl), {
67
- added: () => {
68
- onFileChange()
69
- },
70
- updated: () => {
71
- onFileChange()
72
- },
73
- removed: () => {
74
- onFileChange()
75
- },
76
- keepProcessAlive: false,
77
- })
78
- unregisters.push(unregister)
79
- })
24
+ let lookupPackageScope // defined in "init"
25
+ let readPackageJson // defined in "init"
80
26
 
81
27
  return {
82
28
  name: "jsenv:node_esm_resolution",
83
29
  appliesDuring: "*",
30
+ init: ({ rootDirectoryUrl, scenario, runtimeCompat, urlGraph }) => {
31
+ const nodeRuntimeEnabled = Object.keys(runtimeCompat).includes("node")
32
+ // https://nodejs.org/api/esm.html#resolver-algorithm-specification
33
+ packageConditions = packageConditions || [
34
+ ...readCustomConditionsFromProcessArgs(),
35
+ nodeRuntimeEnabled ? "node" : "browser",
36
+ "import",
37
+ ]
38
+
39
+ const packageScopesCache = new Map()
40
+ lookupPackageScope = (url) => {
41
+ const fromCache = packageScopesCache.get(url)
42
+ if (fromCache) {
43
+ return fromCache
44
+ }
45
+ const packageScope = defaultLookupPackageScope(url)
46
+ packageScopesCache.set(url, packageScope)
47
+ return packageScope
48
+ }
49
+ const packageJsonsCache = new Map()
50
+ readPackageJson = (url) => {
51
+ const fromCache = packageJsonsCache.get(url)
52
+ if (fromCache) {
53
+ return fromCache
54
+ }
55
+ const packageJson = defaultReadPackageJson(url)
56
+ packageJsonsCache.set(url, packageJson)
57
+ return packageJson
58
+ }
59
+
60
+ if (scenario === "dev") {
61
+ const onFileChange = () => {
62
+ packageScopesCache.clear()
63
+ packageJsonsCache.clear()
64
+ urlGraph.urlInfoMap.forEach((urlInfo) => {
65
+ if (urlInfo.dependsOnPackageJson) {
66
+ urlGraph.considerModified(urlInfo)
67
+ }
68
+ })
69
+ }
70
+ filesInvalidatingCache.forEach((file) => {
71
+ const unregister = registerFileLifecycle(
72
+ new URL(file, rootDirectoryUrl),
73
+ {
74
+ added: () => {
75
+ onFileChange()
76
+ },
77
+ updated: () => {
78
+ onFileChange()
79
+ },
80
+ removed: () => {
81
+ onFileChange()
82
+ },
83
+ keepProcessAlive: false,
84
+ },
85
+ )
86
+ unregisters.push(unregister)
87
+ })
88
+ }
89
+ },
84
90
  resolveUrl: {
85
- js_import_export: (reference) => {
91
+ js_import_export: (reference, context) => {
86
92
  const { parentUrl, specifier } = reference
87
93
  const { type, url } = applyNodeEsmResolution({
88
94
  conditions: packageConditions,
@@ -100,7 +106,9 @@ export const jsenvPluginNodeEsmResolution = ({
100
106
  type !== "relative_specifier" &&
101
107
  type !== "absolute_specifier" &&
102
108
  type !== "node_builtin_specifier"
103
- const relatedUrlInfos = urlGraph.getRelatedUrlInfos(reference.parentUrl)
109
+ const relatedUrlInfos = context.urlGraph.getRelatedUrlInfos(
110
+ reference.parentUrl,
111
+ )
104
112
  relatedUrlInfos.forEach((relatedUrlInfo) => {
105
113
  if (relatedUrlInfo.dependsOnPackageJson) {
106
114
  // the url may depend due to an other reference