@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.
- package/dist/jsenv_browser_system.js +36 -99
- package/dist/jsenv_browser_system.js.map +12 -21
- package/dist/jsenv_compile_proxy.js +18 -82
- package/dist/jsenv_compile_proxy.js.map +11 -21
- package/dist/jsenv_exploring_index.js +127 -274
- package/dist/jsenv_exploring_index.js.map +76 -90
- package/dist/jsenv_exploring_redirector.js +21 -89
- package/dist/jsenv_exploring_redirector.js.map +13 -25
- package/dist/jsenv_toolbar.js +81 -149
- package/dist/jsenv_toolbar.js.map +50 -61
- package/dist/jsenv_toolbar_injector.js +185 -231
- package/dist/jsenv_toolbar_injector.js.map +30 -42
- package/package.json +8 -9
- package/src/abort/abortable.js +172 -0
- package/src/abort/callback_list.js +64 -0
- package/src/abort/callback_race.js +34 -0
- package/src/abort/cleaner.js +22 -0
- package/src/abort/main.js +32 -0
- package/src/abort/process_teardown_events.js +59 -0
- package/src/buildProject.js +132 -123
- package/src/execute.js +108 -107
- package/src/executeTestPlan.js +107 -125
- package/src/importUsingChildProcess.js +2 -1
- package/src/internal/browser-launcher/executeHtmlFile.js +33 -12
- package/src/internal/browser-utils/fetch-browser.js +4 -29
- package/src/internal/browser-utils/fetchUsingXHR.js +5 -7
- package/src/internal/building/buildUsingRollup.js +60 -24
- package/src/internal/building/createJsenvRollupPlugin.js +13 -31
- package/src/internal/building/ressource_builder.js +3 -6
- package/src/internal/building/sourcemap_loader.js +4 -5
- package/src/internal/building/url_fetcher.js +2 -5
- package/src/internal/building/url_loader.js +3 -6
- package/src/internal/compiling/compileFile.js +1 -2
- package/src/internal/compiling/createCompiledFileService.js +8 -9
- package/src/internal/compiling/startCompileServer.js +74 -135
- package/src/internal/executing/coverage/generateCoverageJsonFile.js +20 -3
- package/src/internal/executing/coverage/relativeUrlToEmptyCoverage.js +19 -30
- package/src/internal/executing/coverage/reportToCoverage.js +44 -24
- package/src/internal/executing/coverage/v8CoverageFromNodeV8Directory.js +2 -15
- package/src/internal/executing/createSummaryLog.js +50 -37
- package/src/internal/executing/executeConcurrently.js +89 -47
- package/src/internal/executing/executePlan.js +33 -7
- package/src/internal/executing/executionLogs.js +25 -28
- package/src/internal/executing/execution_colors.js +15 -0
- package/src/internal/executing/generateExecutionSteps.js +3 -2
- package/src/internal/executing/launchAndExecute.js +217 -261
- package/src/internal/exploring/fetchExploringJson.js +3 -4
- package/src/internal/fetchUrl.js +6 -2
- package/src/internal/logs/log_style.js +16 -28
- package/src/internal/logs/msAsDuration.js +1 -1
- package/src/internal/node-launcher/createChildProcessOptions.js +4 -5
- package/src/internal/node-launcher/createControllableNodeProcess.js +117 -229
- package/src/internal/node-launcher/kill_process_tree.js +76 -0
- package/src/internal/node-launcher/nodeControllableFile.mjs +16 -10
- package/src/internal/{promise_track_race.js → promise_race.js} +2 -2
- package/src/internal/runtime/s.js +25 -24
- package/src/internal/toolbar/toolbar.html +157 -61
- package/src/internal/toolbar/toolbar.injector.js +8 -0
- package/src/internal/toolbar/util/animation.js +3 -7
- package/src/internal/toolbar/util/fetching.js +1 -30
- package/src/jsenvServiceWorkerFinalizer.js +1 -2
- package/src/launchBrowser.js +131 -127
- package/src/launchNode.js +29 -17
- package/src/playwright_browser_versions.js +3 -3
- package/src/requireUsingChildProcess.js +2 -1
- package/src/signal/signal.js +65 -0
- package/src/startExploring.js +70 -72
- package/src/internal/executeJsenvAsyncFunction.js +0 -34
- package/src/internal/toolbar/animation/toolbar-movie-icon.svg +0 -15
- package/src/internal/toolbar/compilation/flask.svg +0 -7
- package/src/internal/toolbar/compilation/info.svg +0 -9
- package/src/internal/toolbar/compilation/loupe.svg +0 -11
- package/src/internal/toolbar/compilation/toolbar_compilation.svg +0 -11
- package/src/internal/toolbar/eventsource/toolbar-power-icon.svg +0 -10
- package/src/internal/toolbar/eventsource/toolbar-power-off-icon.svg +0 -10
- package/src/internal/toolbar/responsive/toolbar-dots-icon.svg +0 -10
- package/src/internal/toolbar/settings/toolbar-settings-icon.svg +0 -9
- package/src/internal/toolbar/theme/toolbar-palette-icon.svg +0 -10
- package/src/internal/toolbar/toolbar-cross-icon.svg +0 -10
- package/src/internal/toolbar/toolbar-loading-icon.svg +0 -102
- package/src/internal/toolbar/toolbar-notif-icon.svg +0 -9
- package/src/internal/trackRessources.js +0 -23
package/src/launchBrowser.js
CHANGED
|
@@ -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 {
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
175
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
{
|
|
314
|
+
{ launchBrowserOperation, browserClass, options, stopOnExit },
|
|
302
315
|
) => {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
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
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
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
|
-
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
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
|
-
|
|
371
|
+
await browser.close()
|
|
372
|
+
await disconnected
|
|
356
373
|
}
|
|
357
374
|
|
|
358
375
|
const browserToRuntimeHooks = (
|
|
359
376
|
browser,
|
|
360
377
|
{
|
|
361
|
-
|
|
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
|
|
377
|
-
|
|
378
|
-
|
|
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
|
|
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
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
419
|
-
|
|
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
|
-
|
|
429
|
-
|
|
430
|
-
|
|
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
|
-
|
|
449
|
-
|
|
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
|
|
132
|
-
|
|
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
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
|
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 = "
|
|
1
|
+
export const PLAYWRIGHT_CHROMIUM_VERSION = "97.0.4666.0"
|
|
2
2
|
|
|
3
|
-
export const PLAYWRIGHT_FIREFOX_VERSION = "
|
|
3
|
+
export const PLAYWRIGHT_FIREFOX_VERSION = "93.0"
|
|
4
4
|
|
|
5
|
-
export const PLAYWRIGHT_WEBKIT_VERSION = "15.
|
|
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
|
+
}
|