@jsenv/core 27.5.3 → 27.7.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 (30) hide show
  1. package/dist/js/autoreload.js +10 -6
  2. package/dist/js/html_supervisor_installer.js +272 -163
  3. package/dist/js/html_supervisor_setup.js +10 -2
  4. package/dist/js/server_events_client.js +249 -216
  5. package/dist/js/wrapper.mjs +4233 -0
  6. package/dist/main.js +21342 -21629
  7. package/package.json +4 -4
  8. package/src/build/build.js +15 -13
  9. package/src/dev/start_dev_server.js +10 -10
  10. package/src/execute/runtimes/browsers/chromium.js +1 -1
  11. package/src/execute/runtimes/browsers/firefox.js +1 -1
  12. package/src/execute/runtimes/browsers/webkit.js +1 -1
  13. package/src/omega/kitchen.js +13 -15
  14. package/src/omega/omega_server.js +15 -0
  15. package/src/omega/server/file_service.js +11 -84
  16. package/src/omega/url_graph/url_graph_load.js +0 -2
  17. package/src/omega/url_graph/url_info_transformations.js +27 -0
  18. package/src/omega/url_graph.js +1 -0
  19. package/src/plugins/autoreload/client/autoreload.js +10 -4
  20. package/src/plugins/html_supervisor/client/error_formatter.js +187 -66
  21. package/src/plugins/html_supervisor/client/error_overlay.js +29 -31
  22. package/src/plugins/html_supervisor/client/html_supervisor_installer.js +22 -67
  23. package/src/plugins/html_supervisor/client/html_supervisor_setup.js +10 -2
  24. package/src/plugins/html_supervisor/jsenv_plugin_html_supervisor.js +96 -25
  25. package/src/plugins/server_events/client/connection_manager.js +165 -0
  26. package/src/plugins/server_events/client/event_source_connection.js +50 -256
  27. package/src/plugins/server_events/client/events_manager.js +75 -0
  28. package/src/plugins/server_events/client/server_events_client.js +12 -11
  29. package/src/plugins/server_events/client/web_socket_connection.js +81 -0
  30. package/src/plugins/server_events/server_events_dispatcher.js +70 -54
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "27.5.3",
3
+ "version": "27.7.0",
4
4
  "description": "Tool to develop, test and build js projects",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -73,8 +73,8 @@
73
73
  "@jsenv/integrity": "0.0.1",
74
74
  "@jsenv/log": "3.1.0",
75
75
  "@jsenv/node-esm-resolution": "0.1.0",
76
- "@jsenv/server": "13.0.0",
77
- "@jsenv/sourcemap": "1.0.2",
76
+ "@jsenv/server": "13.1.0",
77
+ "@jsenv/sourcemap": "1.0.4",
78
78
  "@jsenv/uneval": "1.6.0",
79
79
  "@jsenv/url-meta": "7.0.0",
80
80
  "@jsenv/urls": "1.2.7",
@@ -109,7 +109,7 @@
109
109
  "eslint-plugin-html": "7.0.0",
110
110
  "eslint-plugin-import": "2.26.0",
111
111
  "eslint-plugin-react": "7.30.1",
112
- "playwright": "1.23.4",
112
+ "playwright": "1.24.1",
113
113
  "prettier": "2.7.1"
114
114
  }
115
115
  }
@@ -47,6 +47,20 @@ import { createVersionGenerator } from "./version_generator.js"
47
47
  import { injectServiceWorkerUrls } from "./inject_service_worker_urls.js"
48
48
  import { resyncRessourceHints } from "./resync_ressource_hints.js"
49
49
 
50
+ // default runtimeCompat corresponds to
51
+ // "we can keep <script type="module"> intact":
52
+ // so script_type_module + dynamic_import + import_meta
53
+ export const defaultRuntimeCompat = {
54
+ // android: "8",
55
+ chrome: "64",
56
+ edge: "79",
57
+ firefox: "67",
58
+ ios: "12",
59
+ opera: "51",
60
+ safari: "11.3",
61
+ samsung: "9.2",
62
+ }
63
+
50
64
  /**
51
65
  * Generate an optimized version of source files into a directory
52
66
  * @param {Object} buildParameters
@@ -85,19 +99,7 @@ export const build = async ({
85
99
  entryPoints = {},
86
100
  baseUrl = "/",
87
101
 
88
- // default runtimeCompat corresponds to
89
- // "we can keep <script type="module"> intact":
90
- // so script_type_module + dynamic_import + import_meta
91
- runtimeCompat = {
92
- // android: "8",
93
- chrome: "64",
94
- edge: "79",
95
- firefox: "67",
96
- ios: "12",
97
- opera: "51",
98
- safari: "11.3",
99
- samsung: "9.2",
100
- },
102
+ runtimeCompat = defaultRuntimeCompat,
101
103
  plugins = [],
102
104
  sourcemaps = false,
103
105
  sourcemapsSourcesContent,
@@ -7,6 +7,7 @@ import { Abort, raceProcessTeardownEvents } from "@jsenv/abort"
7
7
  import { createLogger, loggerToLevels, createTaskLog } from "@jsenv/log"
8
8
  import { getCallerPosition } from "@jsenv/urls"
9
9
 
10
+ import { defaultRuntimeCompat } from "@jsenv/core/src/build/build.js"
10
11
  import { createReloadableWorker } from "@jsenv/core/src/helpers/worker_reload.js"
11
12
  import { startOmegaServer } from "@jsenv/core/src/omega/omega_server.js"
12
13
 
@@ -41,16 +42,10 @@ export const startDevServer = async ({
41
42
  devServerMainFile = getCallerPosition().url,
42
43
  cooldownBetweenFileEvents,
43
44
 
44
- // default runtimeCompat assume dev server will be request by recent browsers
45
- // Used by "jsenv_plugin_node_runtime.js" to deactivate itself
46
- // If dev server can be requested by Node.js to exec files
47
- // we would add "node" to the potential runtimes. For now it's out of the scope of the dev server
48
- // and "jsenv_plugin_node_runtime.js" applies only during build made for node.js
49
- runtimeCompat = {
50
- chrome: "100",
51
- firefox: "100",
52
- safari: "15.5",
53
- },
45
+ // runtimeCompat is the runtimeCompat for the build
46
+ // when specified, dev server use it to warn in case
47
+ // code would be supported during dev but not after build
48
+ runtimeCompat = defaultRuntimeCompat,
54
49
  plugins = [],
55
50
  urlAnalysis = {},
56
51
  htmlSupervisor = true,
@@ -70,6 +65,8 @@ export const startDevServer = async ({
70
65
  // toolbar = false,
71
66
 
72
67
  sourcemaps = "inline",
68
+ sourcemapsSourcesProtocol,
69
+ sourcemapsSourcesContent,
73
70
  writeGeneratedFiles = true,
74
71
  }) => {
75
72
  const logger = createLogger({ logLevel })
@@ -160,6 +157,7 @@ export const startDevServer = async ({
160
157
  rootDirectoryUrl,
161
158
  scenario: "dev",
162
159
  runtimeCompat,
160
+
163
161
  plugins,
164
162
  urlAnalysis,
165
163
  htmlSupervisor,
@@ -171,6 +169,8 @@ export const startDevServer = async ({
171
169
  cooldownBetweenFileEvents,
172
170
  explorer,
173
171
  sourcemaps,
172
+ sourcemapsSourcesProtocol,
173
+ sourcemapsSourcesContent,
174
174
  writeGeneratedFiles,
175
175
  })
176
176
  startDevServerTask.done()
@@ -2,7 +2,7 @@ import { createRuntimeFromPlaywright } from "./from_playwright.js"
2
2
 
3
3
  export const chromium = createRuntimeFromPlaywright({
4
4
  browserName: "chromium",
5
- browserVersion: "104.0.5112.20", // to update, check https://github.com/microsoft/playwright/releases
5
+ browserVersion: "104.0.5112.48", // to update, check https://github.com/microsoft/playwright/releases
6
6
  coveragePlaywrightAPIAvailable: true,
7
7
  })
8
8
  export const chromiumIsolatedTab = chromium.isolatedTab
@@ -2,6 +2,6 @@ import { createRuntimeFromPlaywright } from "./from_playwright.js"
2
2
 
3
3
  export const firefox = createRuntimeFromPlaywright({
4
4
  browserName: "firefox",
5
- browserVersion: "100.0.2", // to update, check https://github.com/microsoft/playwright/releases
5
+ browserVersion: "102.0", // to update, check https://github.com/microsoft/playwright/releases
6
6
  })
7
7
  export const firefoxIsolatedTab = firefox.isolatedTab
@@ -2,7 +2,7 @@ import { createRuntimeFromPlaywright } from "./from_playwright.js"
2
2
 
3
3
  export const webkit = createRuntimeFromPlaywright({
4
4
  browserName: "webkit",
5
- browserVersion: "15.4", // to update, check https://github.com/microsoft/playwright/releases
5
+ browserVersion: "16.0", // to update, check https://github.com/microsoft/playwright/releases
6
6
  ignoreErrorHook: (error) => {
7
7
  // we catch error during execution but safari throw unhandled rejection
8
8
  // in a non-deterministic way.
@@ -30,6 +30,9 @@ export const createKitchen = ({
30
30
  rootDirectoryUrl,
31
31
  scenario,
32
32
  runtimeCompat,
33
+ // during dev/test clientRuntimeCompat is a single runtime
34
+ // during build clientRuntimeCompat is runtimeCompat
35
+ clientRuntimeCompat = runtimeCompat,
33
36
  urlGraph,
34
37
  plugins,
35
38
  sourcemaps = {
@@ -37,13 +40,8 @@ export const createKitchen = ({
37
40
  test: "inline",
38
41
  build: "none",
39
42
  }[scenario],
40
- sourcemapsSourcesContent = {
41
- // during dev/test, chrome is able to find the sourcemap sources
42
- // as long as they use file:// protocol in the sourcemap files
43
- dev: false,
44
- test: false,
45
- build: true,
46
- }[scenario],
43
+ sourcemapsSourcesProtocol,
44
+ sourcemapsSourcesContent,
47
45
  sourcemapsRelativeSources,
48
46
  writeGeneratedFiles,
49
47
  }) => {
@@ -60,6 +58,10 @@ export const createKitchen = ({
60
58
  urlGraph,
61
59
  scenario,
62
60
  runtimeCompat,
61
+ clientRuntimeCompat,
62
+ isSupportedOnCurrentClients: (feature) => {
63
+ return RUNTIME_COMPAT.isSupported(clientRuntimeCompat, feature)
64
+ },
63
65
  isSupportedOnFutureClients: (feature) => {
64
66
  return RUNTIME_COMPAT.isSupported(runtimeCompat, feature)
65
67
  },
@@ -214,12 +216,15 @@ export const createKitchen = ({
214
216
  }
215
217
  }
216
218
  kitchenContext.resolveReference = resolveReference
219
+
217
220
  const urlInfoTransformer = createUrlInfoTransformer({
218
221
  logger,
219
222
  urlGraph,
220
223
  sourcemaps,
224
+ sourcemapsSourcesProtocol,
221
225
  sourcemapsSourcesContent,
222
226
  sourcemapsRelativeSources,
227
+ clientRuntimeCompat,
223
228
  injectSourcemapPlaceholder: ({ urlInfo, specifier }) => {
224
229
  const sourcemapReference = createReference({
225
230
  trace: {
@@ -356,16 +361,9 @@ export const createKitchen = ({
356
361
  }
357
362
 
358
363
  const _cook = async (urlInfo, dishContext) => {
359
- // during dev/test clientRuntimeCompat is a single runtime
360
- // during build clientRuntimeCompat is runtimeCompat
361
- const { clientRuntimeCompat = runtimeCompat } = dishContext
362
- kitchenContext.isSupportedOnCurrentClients = (feature) => {
363
- return RUNTIME_COMPAT.isSupported(clientRuntimeCompat, feature)
364
- }
365
364
  const context = {
366
365
  ...kitchenContext,
367
366
  ...dishContext,
368
- clientRuntimeCompat,
369
367
  }
370
368
  const { cookDuringCook = cook } = dishContext
371
369
  context.cook = (urlInfo, nestedDishContext) => {
@@ -772,7 +770,7 @@ const applyReferenceEffectsOnUrlInfo = (reference, urlInfo, context) => {
772
770
  }
773
771
  urlInfo.contentType = reference.contentType
774
772
  urlInfo.originalContent =
775
- context === "build"
773
+ context.scenario === "build"
776
774
  ? urlInfo.originalContent === undefined
777
775
  ? reference.content
778
776
  : urlInfo.originalContent
@@ -5,6 +5,7 @@ import {
5
5
  jsenvServiceErrorHandler,
6
6
  } from "@jsenv/server"
7
7
  import { convertFileSystemErrorToResponseProperties } from "@jsenv/server/src/internal/convertFileSystemErrorToResponseProperties.js"
8
+ import { createServerEventsDispatcher } from "@jsenv/core/src/plugins/server_events/server_events_dispatcher.js"
8
9
 
9
10
  import { createFileService } from "./server/file_service.js"
10
11
 
@@ -38,9 +39,15 @@ export const startOmegaServer = async ({
38
39
  cooldownBetweenFileEvents,
39
40
  explorer,
40
41
  sourcemaps,
42
+ sourcemapsSourcesProtocol,
43
+ sourcemapsSourcesContent,
41
44
  writeGeneratedFiles,
42
45
  }) => {
43
46
  const serverStopCallbacks = []
47
+ const serverEventsDispatcher = createServerEventsDispatcher()
48
+ serverStopCallbacks.push(() => {
49
+ serverEventsDispatcher.destroy()
50
+ })
44
51
  const server = await startServer({
45
52
  signal,
46
53
  stopOnExit: false,
@@ -77,6 +84,7 @@ export const startOmegaServer = async ({
77
84
  signal,
78
85
  logLevel,
79
86
  serverStopCallbacks,
87
+ serverEventsDispatcher,
80
88
 
81
89
  rootDirectoryUrl,
82
90
  scenario,
@@ -93,8 +101,15 @@ export const startOmegaServer = async ({
93
101
  cooldownBetweenFileEvents,
94
102
  explorer,
95
103
  sourcemaps,
104
+ sourcemapsSourcesProtocol,
105
+ sourcemapsSourcesContent,
96
106
  writeGeneratedFiles,
97
107
  }),
108
+ handleWebsocket: (websocket, { request }) => {
109
+ if (request.headers["sec-websocket-protocol"] === "jsenv") {
110
+ serverEventsDispatcher.addWebsocket(websocket, request)
111
+ }
112
+ },
98
113
  },
99
114
  {
100
115
  name: "jsenv:omega_error_handler",
@@ -10,7 +10,6 @@ import { URL_META } from "@jsenv/url-meta"
10
10
  import { getCorePlugins } from "@jsenv/core/src/plugins/plugins.js"
11
11
  import { createUrlGraph } from "@jsenv/core/src/omega/url_graph.js"
12
12
  import { createKitchen } from "@jsenv/core/src/omega/kitchen.js"
13
- import { createServerEventsDispatcher } from "@jsenv/core/src/plugins/server_events/server_events_dispatcher.js"
14
13
  import { jsenvPluginServerEventsClientInjection } from "@jsenv/core/src/plugins/server_events/jsenv_plugin_server_events_client_injection.js"
15
14
  import { parseUserAgentHeader } from "./user_agent.js"
16
15
 
@@ -18,6 +17,7 @@ export const createFileService = ({
18
17
  signal,
19
18
  logLevel,
20
19
  serverStopCallbacks,
20
+ serverEventsDispatcher,
21
21
 
22
22
  rootDirectoryUrl,
23
23
  scenario,
@@ -34,17 +34,11 @@ export const createFileService = ({
34
34
  cooldownBetweenFileEvents,
35
35
  explorer,
36
36
  sourcemaps,
37
+ sourcemapsSourcesProtocol,
38
+ sourcemapsSourcesContent,
37
39
  writeGeneratedFiles,
38
40
  }) => {
39
41
  const jsenvDirectoryUrl = new URL(".jsenv/", rootDirectoryUrl).href
40
- const onErrorWhileServingFileCallbacks = []
41
- const onErrorWhileServingFile = (data) => {
42
- onErrorWhileServingFileCallbacks.forEach(
43
- (onErrorWhileServingFileCallback) => {
44
- onErrorWhileServingFileCallback(data)
45
- },
46
- )
47
- }
48
42
 
49
43
  const clientFileChangeCallbackList = []
50
44
  const clientFilesPruneCallbackList = []
@@ -113,6 +107,9 @@ export const createFileService = ({
113
107
  rootDirectoryUrl,
114
108
  scenario,
115
109
  runtimeCompat,
110
+ clientRuntimeCompat: {
111
+ [runtimeName]: runtimeVersion,
112
+ },
116
113
  urlGraph,
117
114
  plugins: [
118
115
  ...plugins,
@@ -134,6 +131,8 @@ export const createFileService = ({
134
131
  }),
135
132
  ],
136
133
  sourcemaps,
134
+ sourcemapsSourcesProtocol,
135
+ sourcemapsSourcesContent,
137
136
  writeGeneratedFiles,
138
137
  })
139
138
  serverStopCallbacks.push(() => {
@@ -153,10 +152,6 @@ export const createFileService = ({
153
152
  })
154
153
  const serverEventNames = Object.keys(allServerEvents)
155
154
  if (serverEventNames.length > 0) {
156
- const serverEventsDispatcher = createServerEventsDispatcher()
157
- serverStopCallbacks.push(() => {
158
- serverEventsDispatcher.destroy()
159
- })
160
155
  Object.keys(allServerEvents).forEach((serverEventName) => {
161
156
  allServerEvents[serverEventName]({
162
157
  rootDirectoryUrl,
@@ -170,41 +165,7 @@ export const createFileService = ({
170
165
  },
171
166
  })
172
167
  })
173
- onErrorWhileServingFileCallbacks.push((data) => {
174
- serverEventsDispatcher.dispatchToRoomsMatching(
175
- {
176
- type: "error_while_serving_file",
177
- data,
178
- },
179
- (room) => {
180
- // send only to page depending on this file
181
- const errorFileUrl = data.url
182
- const roomEntryPointUrl = new URL(
183
- room.request.ressource.slice(1),
184
- rootDirectoryUrl,
185
- ).href
186
- const isErrorRelatedToEntryPoint = Boolean(
187
- urlGraph.findDependent(errorFileUrl, (dependentUrlInfo) => {
188
- return dependentUrlInfo.url === roomEntryPointUrl
189
- }),
190
- )
191
- return isErrorRelatedToEntryPoint
192
- },
193
- )
194
- })
195
- // "unshift" because serve must come first to catch event source client request
196
- kitchen.pluginController.unshiftPlugin({
197
- name: "jsenv:provide_server_events",
198
- serve: (request) => {
199
- const { accept } = request.headers
200
- if (accept && accept.includes("text/event-stream")) {
201
- const room = serverEventsDispatcher.addRoom(request)
202
- return room.join(request)
203
- }
204
- return null
205
- },
206
- })
207
- // "push" so that event source client connection can be put as early as possible in html
168
+ // "pushPlugin" so that event source client connection can be put as early as possible in html
208
169
  kitchen.pluginController.pushPlugin(
209
170
  jsenvPluginServerEventsClientInjection(),
210
171
  )
@@ -286,6 +247,7 @@ export const createFileService = ({
286
247
  !urlInfo.isInline &&
287
248
  urlInfo.type !== "sourcemap"
288
249
  ) {
250
+ urlInfo.error = null
289
251
  urlInfo.sourcemap = null
290
252
  urlInfo.sourcemapReference = null
291
253
  urlInfo.content = null
@@ -298,9 +260,6 @@ export const createFileService = ({
298
260
  await kitchen.cook(urlInfo, {
299
261
  request,
300
262
  reference,
301
- clientRuntimeCompat: {
302
- [runtimeName]: runtimeVersion,
303
- },
304
263
  outDirectoryUrl:
305
264
  scenario === "dev"
306
265
  ? `${rootDirectoryUrl}.jsenv/${runtimeName}@${runtimeVersion}/`
@@ -333,18 +292,9 @@ export const createFileService = ({
333
292
  )
334
293
  return response
335
294
  } catch (e) {
295
+ urlInfo.error = e
336
296
  const code = e.code
337
297
  if (code === "PARSE_ERROR") {
338
- onErrorWhileServingFile({
339
- requestedRessource: request.ressource,
340
- code: "PARSE_ERROR",
341
- message: e.reason,
342
- url: e.url,
343
- traceUrl: e.traceUrl,
344
- traceLine: e.traceLine,
345
- traceColumn: e.traceColumn,
346
- traceMessage: e.traceMessage,
347
- })
348
298
  return {
349
299
  url: reference.url,
350
300
  status: 200, // let the browser re-throw the syntax error
@@ -375,19 +325,6 @@ export const createFileService = ({
375
325
  }
376
326
  }
377
327
  if (code === "NOT_FOUND") {
378
- onErrorWhileServingFile({
379
- requestedRessource: request.ressource,
380
- isFaviconAutoRequest:
381
- request.ressource === "/favicon.ico" &&
382
- reference.type === "http_request",
383
- code: "NOT_FOUND",
384
- message: e.reason,
385
- url: e.url,
386
- traceUrl: e.traceUrl,
387
- traceLine: e.traceLine,
388
- traceColumn: e.traceColumn,
389
- traceMessage: e.traceMessage,
390
- })
391
328
  return {
392
329
  url: reference.url,
393
330
  status: 404,
@@ -395,16 +332,6 @@ export const createFileService = ({
395
332
  statusMessage: e.message,
396
333
  }
397
334
  }
398
- onErrorWhileServingFile({
399
- requestedRessource: request.ressource,
400
- code: "UNEXPECTED",
401
- stack: e.stack,
402
- url: e.url,
403
- traceUrl: e.traceUrl,
404
- traceLine: e.traceLine,
405
- traceColumn: e.traceColumn,
406
- traceMessage: e.traceMessage,
407
- })
408
335
  return {
409
336
  url: reference.url,
410
337
  status: 500,
@@ -7,7 +7,6 @@ export const loadUrlGraph = async ({
7
7
  startLoading,
8
8
  writeGeneratedFiles,
9
9
  outDirectoryUrl,
10
- clientRuntimeCompat,
11
10
  }) => {
12
11
  if (writeGeneratedFiles && outDirectoryUrl) {
13
12
  await ensureEmptyDirectory(outDirectoryUrl)
@@ -19,7 +18,6 @@ export const loadUrlGraph = async ({
19
18
  if (promiseFromData) return promiseFromData
20
19
  const promise = _cook(urlInfo, {
21
20
  outDirectoryUrl,
22
- clientRuntimeCompat,
23
21
  ...context,
24
22
  })
25
23
  promises.push(promise)
@@ -11,12 +11,29 @@ import {
11
11
  export const createUrlInfoTransformer = ({
12
12
  logger,
13
13
  sourcemaps,
14
+ sourcemapsSourcesProtocol,
14
15
  sourcemapsSourcesContent,
15
16
  sourcemapsRelativeSources,
16
17
  urlGraph,
18
+ clientRuntimeCompat,
17
19
  injectSourcemapPlaceholder,
18
20
  foundSourcemap,
19
21
  }) => {
22
+ const runtimeNames = Object.keys(clientRuntimeCompat)
23
+ const chromeAsSingleRuntime =
24
+ runtimeNames.length === 1 && runtimeNames[0] === "chrome"
25
+ if (sourcemapsSourcesProtocol === undefined) {
26
+ sourcemapsSourcesProtocol = "file:///"
27
+ }
28
+ if (sourcemapsSourcesContent === undefined) {
29
+ if (chromeAsSingleRuntime && sourcemapsSourcesProtocol === "file:///") {
30
+ // chrome is able to fetch source when referenced with "file:"
31
+ sourcemapsSourcesContent = false
32
+ } else {
33
+ sourcemapsSourcesContent = true
34
+ }
35
+ }
36
+
20
37
  const sourcemapsEnabled =
21
38
  sourcemaps === "inline" ||
22
39
  sourcemaps === "file" ||
@@ -172,6 +189,16 @@ export const createUrlInfoTransformer = ({
172
189
  return sourceRelative || "."
173
190
  })
174
191
  }
192
+ if (sourcemapsSourcesProtocol !== "file:///") {
193
+ sourcemap.sources = sourcemap.sources.map((source) => {
194
+ if (source.startsWith("file:///")) {
195
+ return `${sourcemapsSourcesProtocol}${source.slice(
196
+ "file:///".length,
197
+ )}`
198
+ }
199
+ return source
200
+ })
201
+ }
175
202
  sourcemapUrlInfo.content = JSON.stringify(sourcemap, null, " ")
176
203
  if (!urlInfo.sourcemapIsWrong) {
177
204
  if (sourcemaps === "inline") {
@@ -218,6 +218,7 @@ export const createUrlGraph = ({
218
218
 
219
219
  const createUrlInfo = (url) => {
220
220
  return {
221
+ error: null,
221
222
  modifiedTimestamp: 0,
222
223
  contentEtag: null,
223
224
  dependsOnPackageJson: false,
@@ -15,6 +15,7 @@ const reloader = {
15
15
  isAutoreloadEnabled,
16
16
  setAutoreloadPreference,
17
17
  status: "idle",
18
+ currentExecution: null,
18
19
  onstatuschange: () => {},
19
20
  setStatus: (status) => {
20
21
  reloader.status = status
@@ -49,6 +50,7 @@ const reloader = {
49
50
  promise.then(
50
51
  () => {
51
52
  onApplied(reloadMessage)
53
+ reloader.currentExecution = null
52
54
  },
53
55
  (e) => {
54
56
  reloader.setStatus("failed")
@@ -61,6 +63,7 @@ const reloader = {
61
63
  `[jsenv] Hot reload failed after ${reloadMessage.reason}.
62
64
  This could be due to syntax errors or importing non-existent modules (see errors in console)`,
63
65
  )
66
+ reloader.currentExecution = null
64
67
  },
65
68
  )
66
69
  }
@@ -146,6 +149,10 @@ const applyHotReload = async ({ hotInstructions }) => {
146
149
  await urlHotMeta.disposeCallback()
147
150
  }
148
151
  console.log(`importing js module`)
152
+ reloader.currentExecution = {
153
+ type: "dynamic_import",
154
+ url: urlToFetch,
155
+ }
149
156
  const namespace = await reloadJsImport(urlToFetch)
150
157
  if (urlHotMeta.acceptCallback) {
151
158
  await urlHotMeta.acceptCallback(namespace)
@@ -185,10 +192,9 @@ const applyHotReload = async ({ hotInstructions }) => {
185
192
  }
186
193
 
187
194
  window.__reloader__ = reloader
188
- window.__server_events__.addEventCallbacks({
189
- reload: ({ data }) => {
190
- const reloadMessage = JSON.parse(data)
191
- reloader.addMessage(reloadMessage)
195
+ window.__server_events__.listenEvents({
196
+ reload: (reloadServerEvent) => {
197
+ reloader.addMessage(reloadServerEvent.data)
192
198
  },
193
199
  })
194
200