@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,12 @@
1
- /* eslint-disable import/max-dependencies */
2
1
  // https://github.com/microsoft/playwright/blob/master/docs/api.md
3
2
 
4
- import {
5
- createCancellationToken,
6
- createStoppableOperation,
7
- } from "@jsenv/cancellation"
8
3
  import { createDetailedMessage } from "@jsenv/logger"
9
- import { teardownSignal } from "@jsenv/node-signals"
10
4
 
11
- import { trackRessources } from "./internal/trackRessources.js"
5
+ import {
6
+ Abortable,
7
+ raceProcessTeardownEvents,
8
+ } from "@jsenv/core/src/abort/main.js"
9
+ import { createSignal } from "@jsenv/core/src/signal/signal.js"
12
10
  import { fetchUrl } from "./internal/fetchUrl.js"
13
11
  import { validateResponse } from "./internal/response_validation.js"
14
12
  import { trackPageToNotify } from "./internal/browser-launcher/trackPageToNotify.js"
@@ -26,8 +24,8 @@ export const chromiumRuntime = {
26
24
  version: PLAYWRIGHT_CHROMIUM_VERSION,
27
25
  }
28
26
  chromiumRuntime.launch = async ({
27
+ signal = new AbortController().signal,
29
28
  browserServerLogLevel,
30
- cancellationToken = createCancellationToken(),
31
29
  chromiumExecutablePath,
32
30
 
33
31
  projectDirectoryUrl,
@@ -47,7 +45,7 @@ chromiumRuntime.launch = async ({
47
45
  stopOnExit = true,
48
46
  share = false,
49
47
  }) => {
50
- const ressourceTracker = trackRessources()
48
+ const launchBrowserOperation = Abortable.fromSignal(signal)
51
49
  const sharingToken = share
52
50
  ? chromiumSharing.getSharingToken({
53
51
  chromiumExecutablePath,
@@ -58,12 +56,11 @@ chromiumRuntime.launch = async ({
58
56
  : chromiumSharing.getUniqueSharingToken()
59
57
 
60
58
  if (!sharingToken.isUsed()) {
59
+ Abortable.throwIfAborted(launchBrowserOperation)
61
60
  const { chromium } = await import("playwright")
62
-
63
61
  const launchOperation = launchBrowser("chromium", {
64
62
  browserClass: chromium,
65
- cancellationToken,
66
- ressourceTracker,
63
+ launchBrowserOperation,
67
64
  options: {
68
65
  headless,
69
66
  executablePath: chromiumExecutablePath,
@@ -81,7 +78,7 @@ chromiumRuntime.launch = async ({
81
78
  }
82
79
 
83
80
  const [launchOperation, stopUsingBrowser] = sharingToken.useSharedValue()
84
- ressourceTracker.registerCleanupCallback(stopUsingBrowser)
81
+ launchBrowserOperation.cleaner.addCallback(stopUsingBrowser)
85
82
 
86
83
  const browser = await launchOperation
87
84
 
@@ -92,7 +89,7 @@ chromiumRuntime.launch = async ({
92
89
  const webSocketUrl = new URL(webSocketEndpoint)
93
90
  const browserEndpoint = `http://${webSocketUrl.host}/json/version`
94
91
  const browserResponse = await fetchUrl(browserEndpoint, {
95
- cancellationToken,
92
+ signal,
96
93
  ignoreHttpsError: true,
97
94
  })
98
95
  const { isValid, message, details } = await validateResponse(
@@ -108,9 +105,8 @@ chromiumRuntime.launch = async ({
108
105
  }
109
106
 
110
107
  const browserHooks = browserToRuntimeHooks(browser, {
108
+ launchBrowserOperation,
111
109
  browserServerLogLevel,
112
- cancellationToken,
113
- ressourceTracker,
114
110
 
115
111
  projectDirectoryUrl,
116
112
  compileServerOrigin,
@@ -144,7 +140,7 @@ export const firefoxRuntime = {
144
140
  version: PLAYWRIGHT_FIREFOX_VERSION,
145
141
  }
146
142
  firefoxRuntime.launch = async ({
147
- cancellationToken = createCancellationToken(),
143
+ signal = new AbortController().signal,
148
144
  firefoxExecutablePath,
149
145
  browserServerLogLevel,
150
146
 
@@ -162,17 +158,18 @@ firefoxRuntime.launch = async ({
162
158
  stopOnExit = true,
163
159
  share = false,
164
160
  }) => {
165
- const ressourceTracker = trackRessources()
161
+ const launchBrowserOperation = Abortable.fromSignal(signal)
166
162
  const sharingToken = share
167
163
  ? firefoxSharing.getSharingToken({ firefoxExecutablePath, headless })
168
164
  : firefoxSharing.getUniqueSharingToken()
169
165
 
170
166
  if (!sharingToken.isUsed()) {
167
+ Abortable.throwIfAborted(launchBrowserOperation)
171
168
  const { firefox } = await import("playwright")
172
169
  const launchOperation = launchBrowser("firefox", {
173
170
  browserClass: firefox,
174
- cancellationToken,
175
- ressourceTracker,
171
+
172
+ launchBrowserOperation,
176
173
  options: {
177
174
  headless,
178
175
  executablePath: firefoxExecutablePath,
@@ -183,14 +180,13 @@ firefoxRuntime.launch = async ({
183
180
  }
184
181
 
185
182
  const [launchOperation, stopUsingBrowser] = sharingToken.useSharedValue()
186
- ressourceTracker.registerCleanupCallback(stopUsingBrowser)
183
+ launchBrowserOperation.cleaner.addCallback(stopUsingBrowser)
187
184
 
188
185
  const browser = await launchOperation
189
186
 
190
187
  const browserHooks = browserToRuntimeHooks(browser, {
188
+ launchBrowserOperation,
191
189
  browserServerLogLevel,
192
- cancellationToken,
193
- ressourceTracker,
194
190
 
195
191
  projectDirectoryUrl,
196
192
  compileServerOrigin,
@@ -223,8 +219,8 @@ export const webkitRuntime = {
223
219
  version: PLAYWRIGHT_WEBKIT_VERSION,
224
220
  }
225
221
  webkitRuntime.launch = async ({
222
+ signal = new AbortController().signal,
226
223
  browserServerLogLevel,
227
- cancellationToken = createCancellationToken(),
228
224
  webkitExecutablePath,
229
225
 
230
226
  projectDirectoryUrl,
@@ -241,17 +237,17 @@ webkitRuntime.launch = async ({
241
237
  stopOnExit = true,
242
238
  share = false,
243
239
  }) => {
244
- const ressourceTracker = trackRessources()
240
+ const launchBrowserOperation = Abortable.fromSignal(signal)
245
241
  const sharingToken = share
246
242
  ? webkitSharing.getSharingToken({ webkitExecutablePath, headless })
247
243
  : webkitSharing.getUniqueSharingToken()
248
244
 
249
245
  if (!sharingToken.isUsed()) {
246
+ Abortable.throwIfAborted(launchBrowserOperation)
250
247
  const { webkit } = await import("playwright")
251
248
  const launchOperation = launchBrowser("webkit", {
252
249
  browserClass: webkit,
253
- cancellationToken,
254
- ressourceTracker,
250
+ launchBrowserOperation,
255
251
  options: {
256
252
  headless,
257
253
  executablePath: webkitExecutablePath,
@@ -262,14 +258,13 @@ webkitRuntime.launch = async ({
262
258
  }
263
259
 
264
260
  const [launchOperation, stopUsingBrowser] = sharingToken.useSharedValue()
265
- ressourceTracker.registerCleanupCallback(stopUsingBrowser)
261
+ launchBrowserOperation.cleaner.addCallback(stopUsingBrowser)
266
262
 
267
263
  const browser = await launchOperation
268
264
 
269
265
  const browserHooks = browserToRuntimeHooks(browser, {
266
+ launchBrowserOperation,
270
267
  browserServerLogLevel,
271
- cancellationToken,
272
- ressourceTracker,
273
268
 
274
269
  projectDirectoryUrl,
275
270
  compileServerOrigin,
@@ -280,6 +275,24 @@ webkitRuntime.launch = async ({
280
275
  collectCoverage,
281
276
  coverageConfig,
282
277
  coverageForceIstanbul,
278
+ ignoreErrorHook: (error) => {
279
+ // we catch error during execution but safari throw unhandled rejection
280
+ // in a non-deterministic way.
281
+ // I suppose it's due to some race condition to decide if the promise is catched or not
282
+ // for now we'll ignore unhandled rejection on wekbkit
283
+ if (error.name === "Unhandled Promise Rejection") {
284
+ return true
285
+ }
286
+ return false
287
+ },
288
+ transformErrorHook: (error) => {
289
+ // Force error stack to contain the error message
290
+ // because it's not the case on webkit
291
+ error.stack = `${error.message}
292
+ at ${error.stack}`
293
+
294
+ return error
295
+ },
283
296
  })
284
297
 
285
298
  return {
@@ -298,68 +311,71 @@ export const webkitTabRuntime = {
298
311
 
299
312
  const launchBrowser = async (
300
313
  browserName,
301
- { cancellationToken, browserClass, ressourceTracker, options, stopOnExit },
314
+ { launchBrowserOperation, browserClass, options, stopOnExit },
302
315
  ) => {
303
- const launchOperation = createStoppableOperation({
304
- cancellationToken,
305
- start: async () => {
306
- if (stopOnExit) {
307
- const unregisterProcessTeardown = teardownSignal.addCallback(
308
- (reason) => {
309
- unregisterProcessTeardown()
310
- launchOperation.stop(`process ${reason}`)
311
- },
312
- )
313
- ressourceTracker.registerCleanupCallback(unregisterProcessTeardown)
314
- cancellationToken.register(unregisterProcessTeardown)
315
- }
316
+ if (stopOnExit) {
317
+ Abortable.effect(launchBrowserOperation, (cb) =>
318
+ raceProcessTeardownEvents(
319
+ {
320
+ SIGHUP: true,
321
+ SIGTERM: true,
322
+ SIGINT: true,
323
+ beforeExit: true,
324
+ exit: true,
325
+ },
326
+ cb,
327
+ ),
328
+ )
329
+ }
316
330
 
317
- try {
318
- const browser = await browserClass.launch({
319
- ...options,
320
- // let's handle them to close properly browser + remove listener
321
- // instead of relying on playwright to do so
322
- handleSIGINT: false,
323
- handleSIGTERM: false,
324
- handleSIGHUP: false,
325
- })
326
- return browser
327
- } catch (e) {
328
- if (cancellationToken.cancellationRequested && isTargetClosedError(e)) {
329
- return e
331
+ try {
332
+ const browser = await browserClass.launch({
333
+ ...options,
334
+ // let's handle them to close properly browser + remove listener
335
+ // instead of relying on playwright to do so
336
+ handleSIGINT: false,
337
+ handleSIGTERM: false,
338
+ handleSIGHUP: false,
339
+ })
340
+ launchBrowserOperation.cleaner.addCallback(async () => {
341
+ await stopBrowser(browser)
342
+ })
343
+ if (launchBrowserOperation.signal.aborted) {
344
+ await launchBrowserOperation.cleaner.clean()
345
+ Abortable.throwIfAborted(launchBrowserOperation)
346
+ }
347
+ return browser
348
+ } catch (e) {
349
+ if (launchBrowserOperation.signal.aborted && isTargetClosedError(e)) {
350
+ return e
351
+ }
352
+ throw e
353
+ }
354
+ }
355
+
356
+ const stopBrowser = async (browser) => {
357
+ const disconnected = browser.isConnected()
358
+ ? new Promise((resolve) => {
359
+ const disconnectedCallback = () => {
360
+ browser.removeListener("disconnected", disconnectedCallback)
361
+ resolve()
330
362
  }
331
- throw e
332
- }
333
- },
334
- stop: async (browser) => {
335
- const disconnected = browser.isConnected()
336
- ? new Promise((resolve) => {
337
- const disconnectedCallback = () => {
338
- browser.removeListener("disconnected", disconnectedCallback)
339
- resolve()
340
- }
341
- browser.on("disconnected", disconnectedCallback)
342
- })
343
- : Promise.resolve()
344
-
345
- // for some reason without this 100ms timeout
346
- // browser.close() never resolves (playwright does not like something)
347
- await new Promise((resolve) => setTimeout(resolve, 100))
348
-
349
- await browser.close()
350
- await disconnected
351
- },
352
- })
353
- ressourceTracker.registerCleanupCallback(launchOperation.stop)
363
+ browser.on("disconnected", disconnectedCallback)
364
+ })
365
+ : Promise.resolve()
366
+
367
+ // for some reason without this 100ms timeout
368
+ // browser.close() never resolves (playwright does not like something)
369
+ await new Promise((resolve) => setTimeout(resolve, 100))
354
370
 
355
- return launchOperation
371
+ await browser.close()
372
+ await disconnected
356
373
  }
357
374
 
358
375
  const browserToRuntimeHooks = (
359
376
  browser,
360
377
  {
361
- cancellationToken,
362
- ressourceTracker,
378
+ launchBrowserOperation,
363
379
 
364
380
  projectDirectoryUrl,
365
381
  compileServerOrigin,
@@ -371,38 +387,30 @@ const browserToRuntimeHooks = (
371
387
  coverageConfig,
372
388
  coverageForceIstanbul,
373
389
  coveragePlaywrightAPIAvailable = false,
390
+ ignoreErrorHook = () => false,
391
+ transformErrorHook = (error) => error,
374
392
  },
375
393
  ) => {
376
- const disconnected = new Promise((resolve) => {
377
- // https://github.com/GoogleChrome/puppeteer/blob/v1.4.0/docs/api.md#event-disconnected
378
- browser.on("disconnected", resolve)
379
- })
394
+ const stoppedSignal = createSignal({ once: true })
395
+ // https://github.com/GoogleChrome/puppeteer/blob/v1.4.0/docs/api.md#event-disconnected
396
+ browser.on("disconnected", stoppedSignal.emit)
380
397
 
381
- const errorCallbackArray = []
382
- const registerErrorCallback = (callback) => {
383
- errorCallbackArray.push(callback)
384
- return () => {
385
- const index = errorCallbackArray.indexOf(callback)
386
- if (index > -1) {
387
- errorCallbackArray.splice(index, 1)
388
- }
389
- }
390
- }
398
+ const errorSignal = createSignal()
391
399
 
392
- const consoleCallbackArray = []
393
- const registerConsoleCallback = (callback) => {
394
- consoleCallbackArray.push(callback)
395
- }
400
+ const outputSignal = createSignal()
396
401
 
397
402
  const execute = async ({
403
+ signal,
398
404
  fileRelativeUrl,
399
- // because we use a self signed certificate
400
- ignoreHTTPSErrors = true,
405
+ ignoreHTTPSErrors = true, // we mostly use self signed certificates during tests
401
406
  }) => {
407
+ const executeOperation = Abortable.fromSignal(signal)
408
+ Abortable.throwIfAborted(executeOperation)
402
409
  // open a tab to execute to the file
403
410
  const browserContext = await browser.newContext({ ignoreHTTPSErrors })
411
+ Abortable.throwIfAborted(executeOperation)
404
412
  const page = await browserContext.newPage()
405
- ressourceTracker.registerCleanupCallback(async () => {
413
+ launchBrowserOperation.cleaner.addCallback(async () => {
406
414
  try {
407
415
  await browserContext.close()
408
416
  } catch (e) {
@@ -415,19 +423,17 @@ const browserToRuntimeHooks = (
415
423
  // track tab error and console
416
424
  const stopTrackingToNotify = trackPageToNotify(page, {
417
425
  onError: (error) => {
418
- errorCallbackArray.forEach((callback) => {
419
- callback(error)
420
- })
421
- },
422
- onConsole: ({ type, text }) => {
423
- consoleCallbackArray.forEach((callback) => {
424
- callback({ type, text })
425
- })
426
+ error = transformErrorHook(error)
427
+ if (!ignoreErrorHook(error)) {
428
+ errorSignal.emit(error)
429
+ }
426
430
  },
431
+ onConsole: outputSignal.emit,
427
432
  })
428
- ressourceTracker.registerCleanupCallback(stopTrackingToNotify)
429
- return executeHtmlFile(fileRelativeUrl, {
430
- cancellationToken,
433
+ launchBrowserOperation.cleaner.addCallback(stopTrackingToNotify)
434
+
435
+ const result = await executeHtmlFile(fileRelativeUrl, {
436
+ launchBrowserOperation,
431
437
 
432
438
  projectDirectoryUrl,
433
439
  compileServerOrigin,
@@ -440,24 +446,22 @@ const browserToRuntimeHooks = (
440
446
  coverageConfig,
441
447
  coverageForceIstanbul,
442
448
  coveragePlaywrightAPIAvailable,
449
+ transformErrorHook,
443
450
  })
451
+ return result
444
452
  }
445
453
 
454
+ Abortable.cleanOnAbort(launchBrowserOperation)
455
+
446
456
  return {
457
+ stoppedSignal,
458
+ errorSignal,
459
+ outputSignal,
460
+ execute,
447
461
  stop: async (reason) => {
448
- let unregisterErrorCallback
449
- await Promise.race([
450
- new Promise((resolve, reject) => {
451
- unregisterErrorCallback = registerErrorCallback(reject)
452
- }),
453
- ressourceTracker.cleanup(reason),
454
- ])
455
- unregisterErrorCallback()
462
+ await launchBrowserOperation.cleaner.clean(reason)
463
+ return { graceful: false }
456
464
  },
457
- disconnected,
458
- registerErrorCallback,
459
- registerConsoleCallback,
460
- execute,
461
465
  }
462
466
  }
463
467
 
package/src/launchNode.js CHANGED
@@ -1,8 +1,6 @@
1
- /* eslint-disable import/max-dependencies */
2
1
  import { Script } from "node:vm"
3
2
  import cuid from "cuid"
4
3
  import { loggerToLogLevel } from "@jsenv/logger"
5
- import { createCancellationToken } from "@jsenv/cancellation"
6
4
  import {
7
5
  writeDirectory,
8
6
  resolveUrl,
@@ -21,9 +19,9 @@ export const nodeRuntime = {
21
19
  version: process.version.slice(1),
22
20
  }
23
21
  nodeRuntime.launch = async ({
22
+ signal = new AbortController().signal,
24
23
  logger,
25
24
  logProcessCommand,
26
- cancellationToken = createCancellationToken(),
27
25
 
28
26
  projectDirectoryUrl,
29
27
  compileServerOrigin,
@@ -100,15 +98,19 @@ nodeRuntime.launch = async ({
100
98
 
101
99
  // the v8 coverage directory is available once the child process is disconnected
102
100
  finalizeExecutionResult = async (executionResult) => {
101
+ if (
102
+ executionResult.status === "timedout" ||
103
+ executionResult.status === "aborted"
104
+ ) {
105
+ return executionResult
106
+ }
107
+
103
108
  const coverage = await ensureV8CoverageDirClean(async () => {
104
109
  // prefer istanbul if available
105
110
  if (executionResult.coverage) {
106
111
  return executionResult.coverage
107
112
  }
108
113
 
109
- // give Node.js more time to write the v8 coverage
110
- await new Promise((resolve) => setTimeout(resolve, 50))
111
-
112
114
  const v8Coverage = await v8CoverageFromNodeV8Directory({
113
115
  projectDirectoryUrl,
114
116
  NODE_V8_COVERAGE,
@@ -128,8 +130,15 @@ nodeRuntime.launch = async ({
128
130
  ]
129
131
 
130
132
  const logLevel = loggerToLogLevel(logger)
131
- const controllableNodeProcess = await createControllableNodeProcess({
132
- cancellationToken,
133
+ const {
134
+ execArgv,
135
+ stoppedSignal,
136
+ errorSignal,
137
+ outputSignal,
138
+ stop,
139
+ requestActionOnChildProcess,
140
+ } = await createControllableNodeProcess({
141
+ signal,
133
142
  logLevel,
134
143
  debugPort,
135
144
  debugMode,
@@ -143,7 +152,7 @@ nodeRuntime.launch = async ({
143
152
  logProcessCommand,
144
153
  })
145
154
 
146
- const execute = async ({ fileRelativeUrl, executionId }) => {
155
+ const execute = async ({ signal, fileRelativeUrl, executionId }) => {
147
156
  const executeParams = {
148
157
  projectDirectoryUrl,
149
158
  compileServerOrigin,
@@ -163,11 +172,11 @@ nodeRuntime.launch = async ({
163
172
  remap,
164
173
  }
165
174
 
166
- let executionResult =
167
- await controllableNodeProcess.requestActionOnChildProcess({
168
- actionType: "execute-using-dynamic-import-fallback-on-systemjs",
169
- actionParams: executeParams,
170
- })
175
+ let executionResult = await requestActionOnChildProcess({
176
+ signal,
177
+ actionType: "execute-using-dynamic-import-fallback-on-systemjs",
178
+ actionParams: executeParams,
179
+ })
171
180
 
172
181
  executionResult = transformExecutionResult(executionResult, {
173
182
  compileServerOrigin,
@@ -178,13 +187,16 @@ nodeRuntime.launch = async ({
178
187
  }
179
188
 
180
189
  return {
181
- ...controllableNodeProcess,
182
190
  options: {
183
- execArgv: controllableNodeProcess.execArgv,
191
+ execArgv,
184
192
  // for now do not pass env, it make debug logs to verbose
185
193
  // because process.env is very big
186
194
  // env,
187
195
  },
196
+ stoppedSignal,
197
+ errorSignal,
198
+ outputSignal,
199
+ stop,
188
200
  execute,
189
201
  finalizeExecutionResult,
190
202
  }
@@ -201,7 +213,7 @@ const ensureV8CoverageDirClean = async (fn, NODE_V8_COVERAGE) => {
201
213
  from: NODE_V8_COVERAGE,
202
214
  to: process.env.NODE_V8_COVERAGE,
203
215
  })
204
- await removeFileSystemNode(NODE_V8_COVERAGE)
216
+ await removeFileSystemNode(NODE_V8_COVERAGE, {})
205
217
  } else {
206
218
  await removeFileSystemNode(NODE_V8_COVERAGE, {
207
219
  recursive: true,
@@ -1,5 +1,5 @@
1
- export const PLAYWRIGHT_CHROMIUM_VERSION = "94.0.4595.0"
1
+ export const PLAYWRIGHT_CHROMIUM_VERSION = "97.0.4666.0"
2
2
 
3
- export const PLAYWRIGHT_FIREFOX_VERSION = "91.0"
3
+ export const PLAYWRIGHT_FIREFOX_VERSION = "93.0"
4
4
 
5
- export const PLAYWRIGHT_WEBKIT_VERSION = "15.0"
5
+ export const PLAYWRIGHT_WEBKIT_VERSION = "15.4"
@@ -36,10 +36,11 @@ export const requireUsingChildProcess = async (
36
36
 
37
37
  return {
38
38
  ...controllableNodeProcess,
39
- execute: async () => {
39
+ execute: async ({ signal }) => {
40
40
  try {
41
41
  const namespace =
42
42
  await controllableNodeProcess.requestActionOnChildProcess({
43
+ signal,
43
44
  actionType: "execute-using-require",
44
45
  actionParams: { fileUrl },
45
46
  })
@@ -0,0 +1,65 @@
1
+ export const createSignal = ({ once = false } = {}) => {
2
+ let callbacks = []
3
+
4
+ const signal = {}
5
+
6
+ const addCallback = (callback) => {
7
+ if (typeof callback !== "function") {
8
+ throw new Error(`callback must be a function, got ${callback}`)
9
+ }
10
+
11
+ // don't register twice
12
+ const existingCallback = callbacks.find((callbackCandidate) => {
13
+ return callbackCandidate === callback
14
+ })
15
+ if (existingCallback) {
16
+ if (typeof process.emitWarning === "object") {
17
+ process.emitWarning(`Trying to register same callback twice`, {
18
+ CODE: "CALLBACK_DUPLICATION",
19
+ detail: `It's often the sign that code is executd more than once`,
20
+ })
21
+ } else {
22
+ console.warn(`Trying to add same callback twice`)
23
+ }
24
+ } else {
25
+ callbacks = [...callbacks, callback]
26
+ }
27
+
28
+ return () => {
29
+ callbacks = arrayWithout(callbacks, callback)
30
+ }
31
+ }
32
+
33
+ const emit = (value) => {
34
+ signal.emitted = true
35
+
36
+ const callbacksCopy = callbacks.slice()
37
+ if (once) {
38
+ callbacks.length = 0
39
+ }
40
+ callbacksCopy.forEach((callback) => {
41
+ callback(value)
42
+ })
43
+ }
44
+
45
+ signal.emitted = false
46
+ signal.addCallback = addCallback
47
+ signal.emit = emit
48
+
49
+ return signal
50
+ }
51
+
52
+ const arrayWithout = (array, item) => {
53
+ if (array.length === 0) return array
54
+ const arrayWithoutItem = []
55
+ let i = 0
56
+ while (i < array.length) {
57
+ const value = array[i]
58
+ i++
59
+ if (value === item) {
60
+ continue
61
+ }
62
+ arrayWithoutItem.push(value)
63
+ }
64
+ return arrayWithoutItem
65
+ }