@jsenv/core 23.1.3 → 23.2.2

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 (82) hide show
  1. package/dist/jsenv_browser_system.js +36 -99
  2. package/dist/jsenv_browser_system.js.map +12 -21
  3. package/dist/jsenv_compile_proxy.js +18 -82
  4. package/dist/jsenv_compile_proxy.js.map +11 -21
  5. package/dist/jsenv_exploring_index.js +127 -274
  6. package/dist/jsenv_exploring_index.js.map +76 -90
  7. package/dist/jsenv_exploring_redirector.js +21 -89
  8. package/dist/jsenv_exploring_redirector.js.map +13 -25
  9. package/dist/jsenv_toolbar.js +81 -149
  10. package/dist/jsenv_toolbar.js.map +50 -61
  11. package/dist/jsenv_toolbar_injector.js +185 -231
  12. package/dist/jsenv_toolbar_injector.js.map +30 -42
  13. package/package.json +8 -9
  14. package/src/abort/abortable.js +172 -0
  15. package/src/abort/callback_list.js +64 -0
  16. package/src/abort/callback_race.js +34 -0
  17. package/src/abort/cleaner.js +22 -0
  18. package/src/abort/main.js +32 -0
  19. package/src/abort/process_teardown_events.js +59 -0
  20. package/src/buildProject.js +132 -123
  21. package/src/execute.js +108 -107
  22. package/src/executeTestPlan.js +107 -125
  23. package/src/importUsingChildProcess.js +2 -1
  24. package/src/internal/browser-launcher/executeHtmlFile.js +33 -12
  25. package/src/internal/browser-utils/fetch-browser.js +4 -29
  26. package/src/internal/browser-utils/fetchUsingXHR.js +5 -7
  27. package/src/internal/building/buildUsingRollup.js +60 -24
  28. package/src/internal/building/createJsenvRollupPlugin.js +13 -31
  29. package/src/internal/building/ressource_builder.js +3 -6
  30. package/src/internal/building/sourcemap_loader.js +4 -5
  31. package/src/internal/building/url_fetcher.js +2 -5
  32. package/src/internal/building/url_loader.js +3 -6
  33. package/src/internal/compiling/compileFile.js +1 -2
  34. package/src/internal/compiling/createCompiledFileService.js +8 -9
  35. package/src/internal/compiling/startCompileServer.js +74 -135
  36. package/src/internal/executing/coverage/generateCoverageJsonFile.js +20 -3
  37. package/src/internal/executing/coverage/relativeUrlToEmptyCoverage.js +19 -30
  38. package/src/internal/executing/coverage/reportToCoverage.js +44 -24
  39. package/src/internal/executing/coverage/v8CoverageFromNodeV8Directory.js +2 -15
  40. package/src/internal/executing/createSummaryLog.js +50 -37
  41. package/src/internal/executing/executeConcurrently.js +89 -47
  42. package/src/internal/executing/executePlan.js +33 -7
  43. package/src/internal/executing/executionLogs.js +25 -28
  44. package/src/internal/executing/execution_colors.js +15 -0
  45. package/src/internal/executing/generateExecutionSteps.js +3 -2
  46. package/src/internal/executing/launchAndExecute.js +217 -261
  47. package/src/internal/exploring/fetchExploringJson.js +3 -4
  48. package/src/internal/fetchUrl.js +6 -2
  49. package/src/internal/logs/log_style.js +16 -28
  50. package/src/internal/logs/msAsDuration.js +1 -1
  51. package/src/internal/node-launcher/createChildProcessOptions.js +4 -5
  52. package/src/internal/node-launcher/createControllableNodeProcess.js +117 -229
  53. package/src/internal/node-launcher/kill_process_tree.js +76 -0
  54. package/src/internal/node-launcher/nodeControllableFile.mjs +16 -10
  55. package/src/internal/{promise_track_race.js → promise_race.js} +2 -2
  56. package/src/internal/runtime/s.js +25 -24
  57. package/src/internal/toolbar/toolbar.html +157 -61
  58. package/src/internal/toolbar/toolbar.injector.js +8 -0
  59. package/src/internal/toolbar/util/animation.js +3 -7
  60. package/src/internal/toolbar/util/fetching.js +1 -30
  61. package/src/jsenvServiceWorkerFinalizer.js +1 -2
  62. package/src/launchBrowser.js +131 -127
  63. package/src/launchNode.js +29 -17
  64. package/src/playwright_browser_versions.js +3 -3
  65. package/src/requireUsingChildProcess.js +2 -1
  66. package/src/signal/signal.js +65 -0
  67. package/src/startExploring.js +70 -72
  68. package/src/internal/executeJsenvAsyncFunction.js +0 -34
  69. package/src/internal/toolbar/animation/toolbar-movie-icon.svg +0 -15
  70. package/src/internal/toolbar/compilation/flask.svg +0 -7
  71. package/src/internal/toolbar/compilation/info.svg +0 -9
  72. package/src/internal/toolbar/compilation/loupe.svg +0 -11
  73. package/src/internal/toolbar/compilation/toolbar_compilation.svg +0 -11
  74. package/src/internal/toolbar/eventsource/toolbar-power-icon.svg +0 -10
  75. package/src/internal/toolbar/eventsource/toolbar-power-off-icon.svg +0 -10
  76. package/src/internal/toolbar/responsive/toolbar-dots-icon.svg +0 -10
  77. package/src/internal/toolbar/settings/toolbar-settings-icon.svg +0 -9
  78. package/src/internal/toolbar/theme/toolbar-palette-icon.svg +0 -10
  79. package/src/internal/toolbar/toolbar-cross-icon.svg +0 -10
  80. package/src/internal/toolbar/toolbar-loading-icon.svg +0 -102
  81. package/src/internal/toolbar/toolbar-notif-icon.svg +0 -9
  82. package/src/internal/trackRessources.js +0 -23
@@ -1,14 +1,7 @@
1
- import {
2
- createCancellationToken,
3
- createOperation,
4
- createStoppableOperation,
5
- createCancellationSource,
6
- composeCancellationToken,
7
- errorToCancelReason,
8
- } from "@jsenv/cancellation"
9
1
  import { createLogger, createDetailedMessage } from "@jsenv/logger"
10
2
 
11
- import { promiseTrackRace } from "../promise_track_race.js"
3
+ import { Abortable } from "@jsenv/core/src/abort/main.js"
4
+ import { raceCallbacks } from "../../abort/callback_race.js"
12
5
  import { composeIstanbulCoverages } from "./coverage/composeIstanbulCoverages.js"
13
6
 
14
7
  const TIMING_BEFORE_EXECUTION = "before-execution"
@@ -16,8 +9,8 @@ const TIMING_DURING_EXECUTION = "during-execution"
16
9
  const TIMING_AFTER_EXECUTION = "after-execution"
17
10
 
18
11
  export const launchAndExecute = async ({
12
+ signal = new AbortController().signal,
19
13
  launchAndExecuteLogLevel,
20
- cancellationToken = createCancellationToken(),
21
14
 
22
15
  runtime,
23
16
  runtimeParams,
@@ -39,7 +32,7 @@ export const launchAndExecute = async ({
39
32
  // however unit test will pass true because they want to move on
40
33
  stopAfterExecute = false,
41
34
  stopAfterExecuteReason = "stop after execute",
42
- // when launch returns { disconnected, gracefulStop, stop }
35
+ // when launch returns { stoppedSignal, gracefulStop, stop }
43
36
  // the launched runtime have that amount of ms for disconnected to resolve
44
37
  // before we call stop
45
38
  gracefulStopAllocatedMs = 4000,
@@ -51,7 +44,6 @@ export const launchAndExecute = async ({
51
44
  // by default throw on error after execution
52
45
  throw error
53
46
  },
54
- runtimeDisconnectCallback = () => {},
55
47
 
56
48
  coverageV8MergeConflictIsExpected,
57
49
  } = {}) => {
@@ -68,14 +60,24 @@ export const launchAndExecute = async ({
68
60
 
69
61
  let executionResultTransformer = (executionResult) => executionResult
70
62
 
71
- if (measureDuration) {
72
- const startMs = Date.now()
63
+ const launchAndExecuteOperation = Abortable.fromSignal(signal)
64
+
65
+ const hasAllocatedMs =
66
+ typeof allocatedMs === "number" && allocatedMs !== Infinity
67
+ let timeoutAbortEffect
68
+
69
+ if (hasAllocatedMs) {
70
+ timeoutAbortEffect = Abortable.timeout(
71
+ launchAndExecuteOperation,
72
+ // FIXME: if allocatedMs is veryyyyyy big
73
+ // setTimeout may be called immediatly
74
+ // in that case we should just throw that the number is too big
75
+ allocatedMs,
76
+ )
73
77
  executionResultTransformer = composeTransformer(
74
78
  executionResultTransformer,
75
79
  (executionResult) => {
76
- const endMs = Date.now()
77
- executionResult.startMs = startMs
78
- executionResult.endMs = endMs
80
+ timeoutAbortEffect.cleanup()
79
81
  return executionResult
80
82
  },
81
83
  )
@@ -166,7 +168,7 @@ export const launchAndExecute = async ({
166
168
  executionResultTransformer = composeTransformer(
167
169
  executionResultTransformer,
168
170
  (executionResult) => {
169
- const { coverage, indirectCoverage } = executionResult
171
+ const { coverage = {}, indirectCoverage } = executionResult
170
172
  if (indirectCoverage) {
171
173
  executionResult.coverage = composeIstanbulCoverages(
172
174
  [coverage, indirectCoverage],
@@ -191,274 +193,212 @@ export const launchAndExecute = async ({
191
193
  )
192
194
  }
193
195
 
194
- let executionResult
195
- const executionParams = {
196
- logger,
197
- cancellationToken,
198
-
199
- runtime,
200
- runtimeParams: {
201
- measurePerformance,
202
- collectPerformance,
203
- ...runtimeParams,
204
- },
205
- executeParams,
206
-
207
- stopAfterExecute,
208
- stopAfterExecuteReason,
209
- gracefulStopAllocatedMs,
210
- runtimeConsoleCallback,
211
- runtimeErrorAfterExecutionCallback,
212
- runtimeDisconnectCallback,
213
- runtimeStartedCallback,
214
- runtimeStoppedCallback,
215
- }
216
- const hasAllocatedMs =
217
- typeof allocatedMs === "number" && allocatedMs !== Infinity
218
- if (hasAllocatedMs) {
219
- const TIMEOUT_CANCEL_REASON = "timeout"
220
-
221
- const timeoutCancellationSource = createCancellationSource()
222
-
223
- const id = setTimeout(() => {
224
- // here if allocatedMs is very big
225
- // setTimeout may be called immediatly
226
- // in that case we should just throw that hte number is too big
227
- timeoutCancellationSource.cancel(TIMEOUT_CANCEL_REASON)
228
- }, allocatedMs)
229
- const timeoutCancel = () => clearTimeout(id)
230
-
231
- cancellationToken.register(timeoutCancel)
232
-
233
- const externalOrTimeoutCancellationToken = composeCancellationToken(
234
- cancellationToken,
235
- timeoutCancellationSource.token,
196
+ if (stopAfterExecute) {
197
+ executionResultTransformer = composeTransformer(
198
+ executionResultTransformer,
199
+ async (executionResult) => {
200
+ // if there is an error while cleaning (stopping the runtime)
201
+ // the execution is considered as failed
202
+ try {
203
+ await launchAndExecuteOperation.cleaner.clean(stopAfterExecuteReason)
204
+ return executionResult
205
+ } catch (e) {
206
+ return executionResultTransformer(
207
+ createErroredExecutionResult({
208
+ error: e,
209
+ }),
210
+ )
211
+ }
212
+ },
236
213
  )
237
-
238
- try {
239
- executionResult = await computeExecutionResult({
240
- ...executionParams,
241
- cancellationToken: externalOrTimeoutCancellationToken,
242
- })
243
- timeoutCancel()
244
- } catch (e) {
245
- if (errorToCancelReason(e) === TIMEOUT_CANCEL_REASON) {
246
- executionResult = createTimedoutExecutionResult()
247
- } else {
248
- throw e
249
- }
250
- }
251
- } else {
252
- executionResult = await computeExecutionResult(executionParams)
253
- }
254
-
255
- return executionResultTransformer(executionResult)
256
- }
257
-
258
- const composeCallback = (previousCallback, callback) => {
259
- return (...args) => {
260
- previousCallback(...args)
261
- return callback(...args)
262
214
  }
263
- }
264
215
 
265
- const composeTransformer = (previousTransformer, transformer) => {
266
- return (value) => {
267
- const transformedValue = previousTransformer(value)
268
- return transformer(transformedValue)
216
+ if (measureDuration) {
217
+ const startMs = Date.now()
218
+ executionResultTransformer = composeTransformer(
219
+ executionResultTransformer,
220
+ (executionResult) => {
221
+ const endMs = Date.now()
222
+ executionResult.startMs = startMs
223
+ executionResult.endMs = endMs
224
+ return executionResult
225
+ },
226
+ )
269
227
  }
270
- }
271
-
272
- const computeExecutionResult = async ({
273
- logger,
274
- cancellationToken,
275
228
 
276
- runtime,
277
- runtimeParams,
278
- executeParams,
229
+ try {
230
+ const runtimeLabel = `${runtime.name}/${runtime.version}`
231
+ logger.debug(`launch ${runtimeLabel} to execute something in it`)
279
232
 
280
- stopAfterExecute,
281
- stopAfterExecuteReason,
282
- gracefulStopAllocatedMs,
283
- runtimeStartedCallback,
284
- runtimeStoppedCallback,
285
- runtimeConsoleCallback,
286
- runtimeErrorAfterExecutionCallback,
287
- runtimeDisconnectCallback,
288
- }) => {
289
- const runtimeLabel = `${runtime.name}/${runtime.version}`
290
-
291
- logger.debug(`launch ${runtimeLabel} to execute something in it`)
292
-
293
- const launchOperation = createStoppableOperation({
294
- cancellationToken,
295
- start: async () => {
296
- const value = await runtime.launch({
233
+ Abortable.throwIfAborted(launchAndExecuteOperation)
234
+ const launchReturnValue = await runtime.launch({
235
+ signal: launchAndExecuteOperation.signal,
236
+ logger,
237
+ stopAfterExecute,
238
+ measurePerformance,
239
+ collectPerformance,
240
+ ...runtimeParams,
241
+ })
242
+ validateLaunchReturnValue(launchReturnValue)
243
+ launchAndExecuteOperation.cleaner.addCallback(async (reason) => {
244
+ await stopRuntime({
297
245
  logger,
298
- cancellationToken,
299
- stopAfterExecute,
300
- ...runtimeParams,
246
+ runtimeLabel,
247
+ launchReturnValue,
248
+ gracefulStopAllocatedMs,
249
+ reason,
301
250
  })
302
- runtimeStartedCallback()
303
- return value
304
- },
305
- stop: async ({ gracefulStop, stop }, reason) => {
306
- // external code can cancel using cancellationToken at any time.
307
- // it is important to keep the code inside this stop function because once cancelled
308
- // all code after the operation won't execute because it will be rejected with
309
- // the cancellation error
310
-
311
- let stoppedGracefully
312
-
313
- if (gracefulStop && gracefulStopAllocatedMs) {
314
- logger.debug(
315
- `${runtimeLabel}: runtime.gracefulStop() because ${reason}`,
316
- )
317
-
318
- const gracefulStopPromise = (async () => {
319
- await gracefulStop({ reason })
320
- return true
321
- })()
322
-
323
- const stopPromise = (async () => {
324
- stoppedGracefully = await new Promise(async (resolve) => {
325
- const timeoutId = setTimeout(() => {
326
- resolve(false)
327
- }, gracefulStopAllocatedMs)
328
- try {
329
- await gracefulStopPromise
330
- resolve(true)
331
- } finally {
332
- clearTimeout(timeoutId)
251
+ })
252
+
253
+ logger.debug(createDetailedMessage(`${runtimeLabel}: runtime launched`))
254
+ runtimeStartedCallback()
255
+
256
+ logger.debug(`${runtimeLabel}: start execution`)
257
+ const {
258
+ errorSignal,
259
+ outputSignal,
260
+ stoppedSignal,
261
+ execute,
262
+ finalizeExecutionResult = (executionResult) => executionResult,
263
+ } = launchReturnValue
264
+ executionResultTransformer = composeTransformer(
265
+ executionResultTransformer,
266
+ finalizeExecutionResult,
267
+ )
268
+ outputSignal.addCallback(runtimeConsoleCallback)
269
+
270
+ let timing = TIMING_BEFORE_EXECUTION
271
+ stoppedSignal.addCallback(() => {
272
+ logger.debug(`${runtimeLabel}: runtime stopped ${timing}`)
273
+ runtimeStoppedCallback()
274
+ })
275
+
276
+ const winnerPromise = new Promise((resolve, reject) => {
277
+ raceCallbacks(
278
+ {
279
+ aborted: (cb) => {
280
+ launchAndExecuteOperation.signal.addEventListener("abort", cb)
281
+ return () => {
282
+ launchAndExecuteOperation.signal.removeEventListener("abort", cb)
333
283
  }
334
- })
335
- if (stoppedGracefully) {
336
- return stoppedGracefully
337
- }
338
-
339
- logger.debug(
340
- `${runtimeLabel}: runtime.stop() because gracefulStop still pending after ${gracefulStopAllocatedMs}ms`,
341
- )
342
- await stop({ reason, gracefulFailed: true })
343
- return false
344
- })()
345
-
346
- stoppedGracefully = await Promise.race([
347
- gracefulStopPromise,
348
- stopPromise,
349
- ])
350
- } else {
351
- await stop({ reason, gracefulFailed: false })
352
- stoppedGracefully = false
353
- }
354
-
355
- logger.debug(
356
- `${runtimeLabel}: runtime stopped${
357
- stoppedGracefully ? " gracefully" : ""
358
- }`,
284
+ },
285
+ error: (cb) => {
286
+ return errorSignal.addCallback(cb)
287
+ },
288
+ stopped: (cb) => {
289
+ return stoppedSignal.addCallback(cb)
290
+ },
291
+ executed: (cb) => {
292
+ timing = TIMING_DURING_EXECUTION
293
+ const executed = execute({
294
+ signal: launchAndExecuteOperation.signal,
295
+ ...executeParams,
296
+ })
297
+ executed.then(cb, reject)
298
+ },
299
+ },
300
+ resolve,
359
301
  )
360
- runtimeStoppedCallback({ stoppedGracefully })
361
- },
362
- })
302
+ })
363
303
 
364
- const launchReturnValue = await launchOperation
365
- validateLaunchReturnValue(launchReturnValue)
366
- const {
367
- execute,
368
- disconnected,
369
- registerErrorCallback = () => {},
370
- registerConsoleCallback = () => {},
371
- finalizeExecutionResult = (executionResult) => executionResult,
372
- } = launchReturnValue
373
-
374
- logger.debug(createDetailedMessage(`${runtimeLabel}: runtime launched.`))
375
-
376
- logger.debug(`${runtimeLabel}: start execution.`)
377
- registerConsoleCallback(runtimeConsoleCallback)
378
-
379
- const executeOperation = createOperation({
380
- cancellationToken,
381
- start: async () => {
382
- let timing = TIMING_BEFORE_EXECUTION
383
-
384
- disconnected.then(() => {
385
- logger.debug(`${runtimeLabel}: runtime disconnected ${timing}.`)
386
- runtimeDisconnectCallback({ timing })
387
- })
304
+ Abortable.throwIfAborted(launchAndExecuteOperation)
388
305
 
389
- const executed = execute(executeParams)
306
+ const winner = await winnerPromise
390
307
 
391
- timing = TIMING_DURING_EXECUTION
308
+ if (winner.name === "aborted") {
309
+ Abortable.throwIfAborted(launchAndExecuteOperation)
310
+ }
392
311
 
393
- const raceResult = await promiseTrackRace([disconnected, executed])
394
- timing = TIMING_AFTER_EXECUTION
312
+ if (winner.name === "error") {
313
+ return executionResultTransformer(
314
+ createErroredExecutionResult({
315
+ error: winner.data,
316
+ }),
317
+ )
318
+ }
395
319
 
396
- if (raceResult.winner === disconnected) {
397
- return createDisconnectedExecutionResult()
398
- }
320
+ if (winner.name === "stopped") {
321
+ return executionResultTransformer(
322
+ createErroredExecutionResult({
323
+ error: new Error(`runtime stopped during execution`),
324
+ }),
325
+ )
326
+ }
399
327
 
400
- if (stopAfterExecute) {
401
- // if there is an error while stopping the runtine
402
- // the execution is considered as failed
403
- try {
404
- await launchOperation.stop(stopAfterExecuteReason)
405
- } catch (e) {
406
- return finalizeExecutionResult(
407
- createErroredExecutionResult({
408
- error: e,
409
- }),
410
- )
411
- }
412
- } else {
413
- // when the process is still alive
414
- // we want to catch error to notify runtimeErrorAfterExecutionCallback
415
- // and throw that error by default
416
- registerErrorCallback((error) => {
417
- runtimeErrorAfterExecutionCallback(error)
418
- })
419
- }
328
+ timing = TIMING_AFTER_EXECUTION
420
329
 
421
- const executionResult = raceResult.value
422
- const { status } = executionResult
423
-
424
- if (status === "errored") {
425
- // debug log level because this error happens during execution
426
- // there is no need to log it.
427
- // the code will know the execution errored because it receives
428
- // an errored execution result
429
- logger.debug(
430
- createDetailedMessage(`error ${TIMING_DURING_EXECUTION}.`, {
431
- ["error stack"]: executionResult.error.stack,
432
- ["execute params"]: JSON.stringify(executeParams, null, " "),
433
- ["runtime"]: runtime,
434
- }),
435
- )
436
- return finalizeExecutionResult(
437
- createErroredExecutionResult(executionResult),
438
- )
439
- }
330
+ if (!stopAfterExecute) {
331
+ // when the process is still alive
332
+ // we want to catch error to notify runtimeErrorAfterExecutionCallback
333
+ // and throw that error by default
334
+ errorSignal.addCallback((error) => {
335
+ runtimeErrorAfterExecutionCallback(error)
336
+ })
337
+ }
338
+
339
+ const executeResult = winner.data
340
+ const { status } = executeResult
440
341
 
441
- logger.debug(`${runtimeLabel}: execution completed.`)
442
- return finalizeExecutionResult(
443
- createCompletedExecutionResult(executionResult),
342
+ if (status === "errored") {
343
+ // debug log level because this error happens during execution
344
+ // there is no need to log it.
345
+ // the code will know the execution errored because it receives
346
+ // an errored execution result
347
+ logger.debug(
348
+ createDetailedMessage(`error ${TIMING_DURING_EXECUTION}`, {
349
+ ["error stack"]: executeResult.error.stack,
350
+ ["execute params"]: JSON.stringify(executeParams, null, " "),
351
+ ["runtime"]: runtime,
352
+ }),
444
353
  )
445
- },
446
- })
354
+ return executionResultTransformer(
355
+ createErroredExecutionResult(executeResult),
356
+ )
357
+ }
447
358
 
448
- const executionResult = await executeOperation
359
+ logger.debug(`${runtimeLabel}: execution completed`)
360
+ return executionResultTransformer(
361
+ createCompletedExecutionResult(executeResult),
362
+ )
363
+ } catch (e) {
364
+ if (e.name === "AbortError") {
365
+ if (timeoutAbortEffect && timeoutAbortEffect.signal.aborted) {
366
+ const executionResult = createTimedoutExecutionResult()
367
+ return executionResultTransformer(executionResult)
368
+ }
369
+ const executionResult = createAbortedExecutionResult()
370
+ return executionResultTransformer(executionResult)
371
+ }
372
+ throw e
373
+ }
374
+ }
449
375
 
450
- return executionResult
376
+ const stopRuntime = async ({
377
+ logger,
378
+ runtimeLabel,
379
+ launchReturnValue,
380
+ gracefulStopAllocatedMs,
381
+ reason,
382
+ }) => {
383
+ const { stop } = launchReturnValue
384
+ logger.debug(`${runtimeLabel}: stop() because ${reason}`)
385
+ const { graceful } = await stop({ reason, gracefulStopAllocatedMs })
386
+ if (graceful) {
387
+ logger.debug(`${runtimeLabel}: runtime stopped gracefully`)
388
+ } else {
389
+ logger.debug(`${runtimeLabel}: runtime stopped`)
390
+ }
451
391
  }
452
392
 
453
- const createTimedoutExecutionResult = () => {
393
+ const createAbortedExecutionResult = () => {
454
394
  return {
455
- status: "timedout",
395
+ status: "aborted",
456
396
  }
457
397
  }
458
398
 
459
- const createDisconnectedExecutionResult = () => {
399
+ const createTimedoutExecutionResult = () => {
460
400
  return {
461
- status: "disconnected",
401
+ status: "timedout",
462
402
  }
463
403
  }
464
404
 
@@ -488,6 +428,20 @@ const normalizeNamespace = (namespace) => {
488
428
  return normalized
489
429
  }
490
430
 
431
+ const composeCallback = (previousCallback, callback) => {
432
+ return (...args) => {
433
+ previousCallback(...args)
434
+ return callback(...args)
435
+ }
436
+ }
437
+
438
+ const composeTransformer = (previousTransformer, transformer) => {
439
+ return async (value) => {
440
+ const transformedValue = await previousTransformer(value)
441
+ return transformer(transformedValue)
442
+ }
443
+ }
444
+
491
445
  const validateLaunchReturnValue = (launchReturnValue) => {
492
446
  if (launchReturnValue === null) {
493
447
  throw new Error(`launch must return an object, got null`)
@@ -502,8 +456,10 @@ const validateLaunchReturnValue = (launchReturnValue) => {
502
456
  throw new Error(`launch must return an execute function, got ${execute}`)
503
457
  }
504
458
 
505
- const { disconnected } = launchReturnValue
506
- if (!disconnected || typeof disconnected.then !== "function") {
507
- throw new Error(`launch must return a disconnected promise, got ${execute}`)
459
+ const { stoppedSignal } = launchReturnValue
460
+ if (!stoppedSignal) {
461
+ throw new Error(
462
+ `launch must return a stoppedSignal object, got ${stoppedSignal}`,
463
+ )
508
464
  }
509
465
  }
@@ -1,16 +1,15 @@
1
1
  import { createDetailedMessage } from "@jsenv/logger"
2
- import { isCancelError } from "@jsenv/cancellation/main.browser.js"
3
2
 
4
3
  import { fetchJson } from "../browser-utils/fetchJson.js"
5
4
 
6
- export const fetchExploringJson = async ({ cancellationToken } = {}) => {
5
+ export const fetchExploringJson = async ({ signal } = {}) => {
7
6
  try {
8
7
  const exploringInfo = await fetchJson("/.jsenv/exploring.json", {
9
- cancellationToken,
8
+ signal,
10
9
  })
11
10
  return exploringInfo
12
11
  } catch (e) {
13
- if (isCancelError(e)) {
12
+ if (signal && signal.aborted && e.name === "AbortError") {
14
13
  throw e
15
14
  }
16
15
  throw new Error(
@@ -1,5 +1,6 @@
1
1
  import { globalAgent } from "node:https"
2
- import { fetchUrl as serverFetchUrl, headersToObject } from "@jsenv/server"
2
+ import { fetchUrl as serverFetchUrl } from "@jsenv/server"
3
+ import { headersToObject } from "@jsenv/server/src/internal/headersToObject.js"
3
4
 
4
5
  // ideally we should only pass this to the fetch below
5
6
  globalAgent.options.rejectUnauthorized = false
@@ -8,7 +9,10 @@ export const fetchUrl = async (
8
9
  url,
9
10
  { ignoreHttpsError = true, ...rest } = {},
10
11
  ) => {
11
- const response = await serverFetchUrl(url, { ignoreHttpsError, ...rest })
12
+ const response = await serverFetchUrl(url, {
13
+ ignoreHttpsError,
14
+ ...rest,
15
+ })
12
16
 
13
17
  return {
14
18
  url: response.url,
@@ -16,37 +16,25 @@ if (process.env.GITHUB_WORKFLOW) {
16
16
  }
17
17
  }
18
18
 
19
- const ansiStyles = {
20
- red: { open: 31, close: 39 },
21
- green: { open: 32, close: 39 },
22
- yellow: { open: 33, close: 39 },
23
- blue: { open: 34, close: 39 },
24
- magenta: { open: 35, close: 39 },
25
- grey: { open: 39, close: 39 },
26
- }
27
-
28
- export const ANSI_RED = ansiStyles.red
29
- export const ANSI_GREEN = ansiStyles.green
30
- export const ANSI_YELLOW = ansiStyles.yellow
31
- export const ANSI_BLUE = ansiStyles.blue
32
- export const ANSI_MAGENTA = ansiStyles.magenta
33
- export const ANSI_GREY = ansiStyles.grey
34
-
19
+ // https://github.com/Marak/colors.js/blob/master/lib/styles.js
20
+ export const ANSI_RED = "\x1b[31m"
21
+ export const ANSI_GREEN = "\x1b[32m"
22
+ export const ANSI_YELLOW = "\x1b[33m"
23
+ export const ANSI_BLUE = "\x1b[34m"
24
+ export const ANSI_MAGENTA = "\x1b[35m"
25
+ export const ANSI_GREY = "\x1b[90m"
35
26
  export const ANSI_RESET = "\x1b[0m"
36
27
 
37
28
  export const setANSIColor = canUseColors
38
- ? (text, ansiColor) =>
39
- `\x1b[${ansiColor.open}m${text}\x1b[${ansiColor.close}m`
29
+ ? (text, ANSI_COLOR) => `${ANSI_COLOR}${text}${ANSI_RESET}`
40
30
  : (text) => text
41
31
 
42
- export const commandSignDefault = canUseUnicode ? `❯` : `>`
43
- export const okSignDefault = canUseUnicode ? `✔` : `√`
44
- export const failureSignDefault = canUseUnicode ? `✖` : `×`
45
- export const infoSignDefault = canUseUnicode ? `ℹ` : `i`
46
- export const warningSignDefault = canUseUnicode ? `⚠` : `‼`
32
+ export const commandSignColorLess = canUseUnicode ? `❯` : `>`
33
+ export const okSignColorLess = canUseUnicode ? `✔` : `√`
34
+ export const failureSignColorLess = canUseUnicode ? `✖` : `×`
47
35
 
48
- export const commandSign = setANSIColor(commandSignDefault, ANSI_GREY) // ANSI_MAGENTA)
49
- export const okSign = setANSIColor(okSignDefault, ANSI_GREEN)
50
- export const failureSign = setANSIColor(failureSignDefault, ANSI_RED)
51
- export const infoSign = setANSIColor(infoSignDefault, ANSI_BLUE)
52
- export const warningSign = setANSIColor(warningSignDefault, ANSI_YELLOW)
36
+ export const commandSign = setANSIColor(commandSignColorLess, ANSI_GREY) // ANSI_MAGENTA)
37
+ export const okSign = setANSIColor(okSignColorLess, ANSI_GREEN)
38
+ export const failureSign = setANSIColor(failureSignColorLess, ANSI_RED)
39
+ export const infoSign = setANSIColor(canUseUnicode ? `ℹ` : `i`, ANSI_BLUE)
40
+ export const warningSign = setANSIColor(canUseUnicode ? `⚠` : `‼`, ANSI_YELLOW)
@@ -5,7 +5,7 @@ const humanizeDuration = require("humanize-duration")
5
5
  export const msAsDuration = (metricValue) => {
6
6
  return humanizeDuration(metricValue, {
7
7
  largest: 2,
8
- maxDecimalPoints: metricValue < 1 ? 4 : metricValue < 1000 ? 3 : 2,
8
+ maxDecimalPoints: metricValue < 0.1 ? 3 : metricValue < 1000 ? 2 : 1,
9
9
  // units: ["s"]
10
10
  })
11
11
  }