@rehearsal-labs/retest 0.1.0 → 0.3.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.
- package/README.md +12 -5
- package/dist/agent/session.d.ts +21 -2
- package/dist/agent/session.d.ts.map +1 -1
- package/dist/agent/session.js +73 -11
- package/dist/api/app-page.d.ts +39 -3
- package/dist/api/app-page.d.ts.map +1 -1
- package/dist/api/app-page.js +108 -0
- package/dist/api/dialog.d.ts +38 -0
- package/dist/api/dialog.d.ts.map +1 -0
- package/dist/api/dialog.js +78 -0
- package/dist/api/drag.d.ts +32 -0
- package/dist/api/drag.d.ts.map +1 -0
- package/dist/api/drag.js +26 -0
- package/dist/api/files.d.ts +49 -0
- package/dist/api/files.d.ts.map +1 -0
- package/dist/api/files.js +168 -0
- package/dist/api/inbox.d.ts +97 -0
- package/dist/api/inbox.d.ts.map +1 -0
- package/dist/api/inbox.js +191 -0
- package/dist/api/locator-recipes.d.ts +1 -1
- package/dist/api/locator-recipes.d.ts.map +1 -1
- package/dist/api/locator-recipes.js +4 -3
- package/dist/api/page.d.ts +214 -4
- package/dist/api/page.d.ts.map +1 -1
- package/dist/api/route.d.ts +21 -0
- package/dist/api/route.d.ts.map +1 -0
- package/dist/api/route.js +99 -0
- package/dist/api/source-location.d.ts.map +1 -1
- package/dist/api/source-location.js +3 -1
- package/dist/api/test-run.d.ts +127 -1
- package/dist/api/test-run.d.ts.map +1 -1
- package/dist/api/test-run.js +293 -0
- package/dist/assertions/expect.d.ts +91 -2
- package/dist/assertions/expect.d.ts.map +1 -1
- package/dist/assertions/expect.js +98 -0
- package/dist/assertions/look-until.d.ts +5 -0
- package/dist/assertions/look-until.d.ts.map +1 -1
- package/dist/assertions/look-until.js +1 -1
- package/dist/assertions/poll-layout.d.ts +24 -0
- package/dist/assertions/poll-layout.d.ts.map +1 -0
- package/dist/assertions/poll-layout.js +63 -0
- package/dist/assertions/screenshot.d.ts +36 -0
- package/dist/assertions/screenshot.d.ts.map +1 -0
- package/dist/assertions/screenshot.js +125 -0
- package/dist/browser/accessibility.d.ts.map +1 -1
- package/dist/browser/accessibility.js +22 -1
- package/dist/browser/actionability.d.ts +9 -6
- package/dist/browser/actionability.d.ts.map +1 -1
- package/dist/browser/actionability.js +17 -8
- package/dist/browser/browser.d.ts.map +1 -1
- package/dist/browser/browser.js +15 -4
- package/dist/browser/builds.d.ts +35 -6
- package/dist/browser/builds.d.ts.map +1 -1
- package/dist/browser/builds.js +115 -16
- package/dist/browser/cdp/connection.d.ts +6 -0
- package/dist/browser/cdp/connection.d.ts.map +1 -1
- package/dist/browser/cdp/connection.js +8 -0
- package/dist/browser/cdp/transport.d.ts.map +1 -1
- package/dist/browser/cdp/transport.js +4 -4
- package/dist/browser/checked-state.d.ts +2 -2
- package/dist/browser/checked-state.d.ts.map +1 -1
- package/dist/browser/chromium-process.d.ts +32 -2
- package/dist/browser/chromium-process.d.ts.map +1 -1
- package/dist/browser/chromium-process.js +95 -17
- package/dist/browser/contract.d.ts +119 -5
- package/dist/browser/contract.d.ts.map +1 -1
- package/dist/browser/dialogs.d.ts +157 -0
- package/dist/browser/dialogs.d.ts.map +1 -0
- package/dist/browser/dialogs.js +271 -0
- package/dist/browser/downloads.d.ts +71 -0
- package/dist/browser/downloads.d.ts.map +1 -0
- package/dist/browser/downloads.js +253 -0
- package/dist/browser/drag.d.ts +50 -0
- package/dist/browser/drag.d.ts.map +1 -0
- package/dist/browser/drag.js +584 -0
- package/dist/browser/electron-window-watch.d.ts +32 -0
- package/dist/browser/electron-window-watch.d.ts.map +1 -0
- package/dist/browser/electron-window-watch.js +93 -0
- package/dist/browser/electron.d.ts +14 -3
- package/dist/browser/electron.d.ts.map +1 -1
- package/dist/browser/electron.js +57 -9
- package/dist/browser/element-queries.d.ts +51 -15
- package/dist/browser/element-queries.d.ts.map +1 -1
- package/dist/browser/element-queries.js +92 -13
- package/dist/browser/emulation.d.ts.map +1 -1
- package/dist/browser/emulation.js +7 -5
- package/dist/browser/executables.d.ts +16 -1
- package/dist/browser/executables.d.ts.map +1 -1
- package/dist/browser/executables.js +50 -18
- package/dist/browser/file-chooser.d.ts +75 -0
- package/dist/browser/file-chooser.d.ts.map +1 -0
- package/dist/browser/file-chooser.js +449 -0
- package/dist/browser/firefox/accessible-names.d.ts +5 -4
- package/dist/browser/firefox/accessible-names.d.ts.map +1 -1
- package/dist/browser/firefox/accessible-names.js +11 -6
- package/dist/browser/firefox/bridge.js +3 -2
- package/dist/browser/firefox/executable.d.ts +14 -14
- package/dist/browser/firefox/executable.d.ts.map +1 -1
- package/dist/browser/firefox/executable.js +29 -21
- package/dist/browser/firefox/input.d.ts +5 -0
- package/dist/browser/firefox/input.d.ts.map +1 -1
- package/dist/browser/firefox/input.js +6 -3
- package/dist/browser/firefox/launch.js +1 -1
- package/dist/browser/firefox/navigation.d.ts +5 -2
- package/dist/browser/firefox/navigation.d.ts.map +1 -1
- package/dist/browser/firefox/navigation.js +48 -14
- package/dist/browser/firefox/orphans.d.ts.map +1 -1
- package/dist/browser/firefox/orphans.js +34 -2
- package/dist/browser/firefox/page.d.ts +11 -1
- package/dist/browser/firefox/page.d.ts.map +1 -1
- package/dist/browser/firefox/page.js +179 -26
- package/dist/browser/firefox/process.d.ts +20 -1
- package/dist/browser/firefox/process.d.ts.map +1 -1
- package/dist/browser/firefox/process.js +124 -22
- package/dist/browser/firefox/profile.d.ts +5 -0
- package/dist/browser/firefox/profile.d.ts.map +1 -1
- package/dist/browser/firefox/profile.js +17 -1
- package/dist/browser/firefox/storage.d.ts.map +1 -1
- package/dist/browser/firefox/storage.js +4 -2
- package/dist/browser/firefox/subscriptions.d.ts +26 -0
- package/dist/browser/firefox/subscriptions.d.ts.map +1 -0
- package/dist/browser/firefox/subscriptions.js +10 -0
- package/dist/browser/frames.d.ts +205 -0
- package/dist/browser/frames.d.ts.map +1 -0
- package/dist/browser/frames.js +657 -0
- package/dist/browser/input-guard.d.ts +18 -5
- package/dist/browser/input-guard.d.ts.map +1 -1
- package/dist/browser/input-guard.js +65 -6
- package/dist/browser/isolated-world.d.ts +8 -1
- package/dist/browser/isolated-world.d.ts.map +1 -1
- package/dist/browser/launch.d.ts +6 -0
- package/dist/browser/launch.d.ts.map +1 -1
- package/dist/browser/launch.js +14 -1
- package/dist/browser/layout.d.ts +120 -0
- package/dist/browser/layout.d.ts.map +1 -0
- package/dist/browser/layout.js +213 -0
- package/dist/browser/locate.d.ts +10 -0
- package/dist/browser/locate.d.ts.map +1 -1
- package/dist/browser/locate.js +24 -6
- package/dist/browser/origin-document.d.ts +4 -0
- package/dist/browser/origin-document.d.ts.map +1 -1
- package/dist/browser/origin-document.js +9 -1
- package/dist/browser/page-scripts.d.ts +48 -0
- package/dist/browser/page-scripts.d.ts.map +1 -1
- package/dist/browser/page-scripts.js +515 -39
- package/dist/browser/page.d.ts +60 -1
- package/dist/browser/page.d.ts.map +1 -1
- package/dist/browser/page.js +275 -32
- package/dist/browser/popups.d.ts +166 -0
- package/dist/browser/popups.d.ts.map +1 -0
- package/dist/browser/popups.js +317 -0
- package/dist/browser/routes.d.ts +97 -0
- package/dist/browser/routes.d.ts.map +1 -0
- package/dist/browser/routes.js +226 -0
- package/dist/browser/screenshot.d.ts +44 -0
- package/dist/browser/screenshot.d.ts.map +1 -0
- package/dist/browser/screenshot.js +51 -0
- package/dist/browser/shadow-candidates.d.ts +20 -0
- package/dist/browser/shadow-candidates.d.ts.map +1 -0
- package/dist/browser/shadow-candidates.js +77 -0
- package/dist/browser/webkit/page.d.ts +11 -1
- package/dist/browser/webkit/page.d.ts.map +1 -1
- package/dist/browser/webkit/page.js +53 -2
- package/dist/browser/webkit/relay.d.ts.map +1 -1
- package/dist/browser/webkit/relay.js +5 -1
- package/dist/cli/commands/doctor.js +3 -3
- package/dist/cli/commands/inspect.js +3 -2
- package/dist/cli/commands/install.d.ts.map +1 -1
- package/dist/cli/commands/install.js +26 -13
- package/dist/cli/commands/licences.d.ts +22 -0
- package/dist/cli/commands/licences.d.ts.map +1 -1
- package/dist/cli/commands/licences.js +62 -20
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +4 -2
- package/dist/cli/doctor/checks.js +4 -1
- package/dist/cli/inspect/diagnostics.js +3 -3
- package/dist/cli/inspect/test-timeline.d.ts.map +1 -1
- package/dist/cli/inspect/test-timeline.js +45 -11
- package/dist/cli/install/doctor-rows.d.ts.map +1 -1
- package/dist/cli/install/doctor-rows.js +5 -4
- package/dist/cli/install/file-changes.d.ts +44 -0
- package/dist/cli/install/file-changes.d.ts.map +1 -0
- package/dist/cli/install/file-changes.js +81 -0
- package/dist/cli/install/install-archive.d.ts +3 -1
- package/dist/cli/install/install-archive.d.ts.map +1 -1
- package/dist/cli/install/install-archive.js +80 -33
- package/dist/cli/install/lock.d.ts.map +1 -1
- package/dist/cli/install/lock.js +108 -21
- package/dist/cli/install/media-doctor.d.ts.map +1 -1
- package/dist/cli/install/media-doctor.js +2 -1
- package/dist/cli/install/media-install.d.ts.map +1 -1
- package/dist/cli/install/media-install.js +38 -19
- package/dist/cli/install/media-pins.d.ts +7 -1
- package/dist/cli/install/media-pins.d.ts.map +1 -1
- package/dist/cli/install/media-pins.js +23 -12
- package/dist/cli/install/media-record.d.ts.map +1 -1
- package/dist/cli/install/media-record.js +10 -9
- package/dist/cli/install/media-report.d.ts +3 -1
- package/dist/cli/install/media-report.d.ts.map +1 -1
- package/dist/cli/install/media-report.js +7 -5
- package/dist/cli/install/media-tools.d.ts.map +1 -1
- package/dist/cli/install/media-tools.js +6 -4
- package/dist/cli/install/process-start.d.ts +3 -2
- package/dist/cli/install/process-start.d.ts.map +1 -1
- package/dist/cli/install/process-start.js +4 -0
- package/dist/cli/install/report.d.ts.map +1 -1
- package/dist/cli/install/report.js +11 -7
- package/dist/cli/install/supervisor-install.d.ts +33 -0
- package/dist/cli/install/supervisor-install.d.ts.map +1 -0
- package/dist/cli/install/supervisor-install.js +158 -0
- package/dist/cli/install/supervisor-locate.d.ts +47 -0
- package/dist/cli/install/supervisor-locate.d.ts.map +1 -0
- package/dist/cli/install/supervisor-locate.js +113 -0
- package/dist/cli/install/supervisor-pins.d.ts +21 -0
- package/dist/cli/install/supervisor-pins.d.ts.map +1 -0
- package/dist/cli/install/supervisor-pins.js +28 -0
- package/dist/cli/install/supervisor-record.d.ts +31 -0
- package/dist/cli/install/supervisor-record.d.ts.map +1 -0
- package/dist/cli/install/supervisor-record.js +104 -0
- package/dist/cli/install/supervisor-report.d.ts +11 -0
- package/dist/cli/install/supervisor-report.d.ts.map +1 -0
- package/dist/cli/install/supervisor-report.js +33 -0
- package/dist/cli/install/supervisor-tools.d.ts +43 -0
- package/dist/cli/install/supervisor-tools.d.ts.map +1 -0
- package/dist/cli/install/supervisor-tools.js +114 -0
- package/dist/cli/install/unpack.d.ts +23 -3
- package/dist/cli/install/unpack.d.ts.map +1 -1
- package/dist/cli/install/unpack.js +124 -10
- package/dist/cli/install/zip-member.d.ts +15 -0
- package/dist/cli/install/zip-member.d.ts.map +1 -0
- package/dist/cli/install/zip-member.js +77 -0
- package/dist/cli/interrupt.d.ts +1 -1
- package/dist/cli/interrupt.d.ts.map +1 -1
- package/dist/cli/interrupt.js +15 -10
- package/dist/cli/terminal.d.ts +9 -1
- package/dist/cli/terminal.d.ts.map +1 -1
- package/dist/cli/terminal.js +14 -0
- package/dist/config/define.d.ts +2 -2
- package/dist/config/define.js +2 -2
- package/dist/config/loaded.d.ts +12 -2
- package/dist/config/loaded.d.ts.map +1 -1
- package/dist/config/read-inboxes.d.ts +10 -0
- package/dist/config/read-inboxes.d.ts.map +1 -0
- package/dist/config/read-inboxes.js +78 -0
- package/dist/config/register.d.ts +5 -1
- package/dist/config/register.d.ts.map +1 -1
- package/dist/config/types.d.ts +36 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/validate.d.ts.map +1 -1
- package/dist/config/validate.js +4 -1
- package/dist/diagnostics/artifact.d.ts.map +1 -1
- package/dist/diagnostics/artifact.js +10 -2
- package/dist/diagnostics/attempt.d.ts +5 -0
- package/dist/diagnostics/attempt.d.ts.map +1 -1
- package/dist/diagnostics/attempt.js +10 -0
- package/dist/diagnostics/chromium-collector.d.ts +9 -1
- package/dist/diagnostics/chromium-collector.d.ts.map +1 -1
- package/dist/diagnostics/chromium-collector.js +19 -4
- package/dist/diagnostics/firefox-collector.d.ts +11 -10
- package/dist/diagnostics/firefox-collector.d.ts.map +1 -1
- package/dist/diagnostics/firefox-collector.js +16 -11
- package/dist/diagnostics/observations.d.ts +8 -0
- package/dist/diagnostics/observations.d.ts.map +1 -1
- package/dist/diagnostics/session-capture.d.ts.map +1 -1
- package/dist/diagnostics/session-capture.js +8 -0
- package/dist/index.d.ts +9 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/media/client.d.ts +2 -1
- package/dist/media/client.d.ts.map +1 -1
- package/dist/media/client.js +16 -5
- package/dist/media/host.d.ts +32 -0
- package/dist/media/host.d.ts.map +1 -0
- package/dist/media/host.js +50 -0
- package/dist/media/locate.d.ts.map +1 -1
- package/dist/media/locate.js +4 -3
- package/dist/media/policy.d.ts +2 -2
- package/dist/media/policy.d.ts.map +1 -1
- package/dist/media/policy.js +1 -1
- package/dist/native/processes.d.ts.map +1 -1
- package/dist/native/processes.js +7 -3
- package/dist/playwright/not-yet.d.ts.map +1 -1
- package/dist/playwright/not-yet.js +5 -2
- package/dist/protocol/commands.d.ts +122 -13
- package/dist/protocol/commands.d.ts.map +1 -1
- package/dist/protocol/commands.js +85 -6
- package/dist/protocol/diagnostics.d.ts +10 -0
- package/dist/protocol/diagnostics.d.ts.map +1 -1
- package/dist/protocol/diagnostics.js +5 -0
- package/dist/protocol/dialogs.d.ts +104 -0
- package/dist/protocol/dialogs.d.ts.map +1 -0
- package/dist/protocol/dialogs.js +101 -0
- package/dist/protocol/drag.d.ts +45 -0
- package/dist/protocol/drag.d.ts.map +1 -0
- package/dist/protocol/drag.js +31 -0
- package/dist/protocol/events.d.ts +153 -1
- package/dist/protocol/events.d.ts.map +1 -1
- package/dist/protocol/events.js +97 -0
- package/dist/protocol/files.d.ts +83 -0
- package/dist/protocol/files.d.ts.map +1 -0
- package/dist/protocol/files.js +73 -0
- package/dist/protocol/inbox.d.ts +87 -0
- package/dist/protocol/inbox.d.ts.map +1 -0
- package/dist/protocol/inbox.js +51 -0
- package/dist/protocol/index.d.ts +4 -1
- package/dist/protocol/index.d.ts.map +1 -1
- package/dist/protocol/layout-checks.d.ts +83 -0
- package/dist/protocol/layout-checks.d.ts.map +1 -0
- package/dist/protocol/layout-checks.js +214 -0
- package/dist/protocol/layout.d.ts +135 -0
- package/dist/protocol/layout.d.ts.map +1 -0
- package/dist/protocol/layout.js +124 -0
- package/dist/protocol/locator-checks.d.ts +19 -2
- package/dist/protocol/locator-checks.d.ts.map +1 -1
- package/dist/protocol/locator-checks.js +23 -1
- package/dist/protocol/locator.d.ts +55 -7
- package/dist/protocol/locator.d.ts.map +1 -1
- package/dist/protocol/locator.js +99 -18
- package/dist/protocol/messages.d.ts +95 -0
- package/dist/protocol/messages.d.ts.map +1 -1
- package/dist/protocol/messages.js +63 -0
- package/dist/protocol/popups.d.ts +43 -0
- package/dist/protocol/popups.d.ts.map +1 -0
- package/dist/protocol/popups.js +27 -0
- package/dist/protocol/result.d.ts +5 -0
- package/dist/protocol/result.d.ts.map +1 -1
- package/dist/protocol/result.js +1 -0
- package/dist/protocol/routes.d.ts +136 -0
- package/dist/protocol/routes.d.ts.map +1 -0
- package/dist/protocol/routes.js +191 -0
- package/dist/protocol/screenshot.d.ts +219 -0
- package/dist/protocol/screenshot.d.ts.map +1 -0
- package/dist/protocol/screenshot.js +335 -0
- package/dist/reporters/actions.d.ts +6 -4
- package/dist/reporters/actions.d.ts.map +1 -1
- package/dist/reporters/actions.js +24 -6
- package/dist/reporters/agent.d.ts.map +1 -1
- package/dist/reporters/agent.js +4 -2
- package/dist/reporters/commands.d.ts +12 -3
- package/dist/reporters/commands.d.ts.map +1 -1
- package/dist/reporters/commands.js +29 -11
- package/dist/reporters/dialogs-popups.d.ts +22 -0
- package/dist/reporters/dialogs-popups.d.ts.map +1 -0
- package/dist/reporters/dialogs-popups.js +30 -0
- package/dist/reporters/failure-card.d.ts +10 -1
- package/dist/reporters/failure-card.d.ts.map +1 -1
- package/dist/reporters/failure-card.js +5 -1
- package/dist/reporters/format.d.ts +33 -0
- package/dist/reporters/format.d.ts.map +1 -1
- package/dist/reporters/format.js +42 -0
- package/dist/reporters/html/comparison-view.d.ts +12 -0
- package/dist/reporters/html/comparison-view.d.ts.map +1 -0
- package/dist/reporters/html/comparison-view.js +21 -0
- package/dist/reporters/html/diagnostics-view.js +8 -0
- package/dist/reporters/html/downloads-view.d.ts +10 -0
- package/dist/reporters/html/downloads-view.d.ts.map +1 -0
- package/dist/reporters/html/downloads-view.js +29 -0
- package/dist/reporters/html/style.d.ts.map +1 -1
- package/dist/reporters/html/style.js +3 -0
- package/dist/reporters/html/summary-view.d.ts.map +1 -1
- package/dist/reporters/html/summary-view.js +3 -2
- package/dist/reporters/html/test-view.d.ts.map +1 -1
- package/dist/reporters/html/test-view.js +6 -3
- package/dist/reporters/html/timeline-view.d.ts.map +1 -1
- package/dist/reporters/html/timeline-view.js +26 -2
- package/dist/reporters/human-card.js +11 -1
- package/dist/reporters/human.d.ts +3 -1
- package/dist/reporters/human.d.ts.map +1 -1
- package/dist/reporters/human.js +11 -9
- package/dist/reporters/routes.d.ts +9 -0
- package/dist/reporters/routes.d.ts.map +1 -0
- package/dist/reporters/routes.js +17 -0
- package/dist/reporters/style.d.ts +21 -2
- package/dist/reporters/style.d.ts.map +1 -1
- package/dist/reporters/style.js +11 -2
- package/dist/runner/app-server.d.ts +27 -7
- package/dist/runner/app-server.d.ts.map +1 -1
- package/dist/runner/app-server.js +74 -24
- package/dist/runner/child-program.js +10 -0
- package/dist/runner/child.js +6 -2
- package/dist/runner/contract.d.ts +5 -0
- package/dist/runner/contract.d.ts.map +1 -1
- package/dist/runner/dialogs.d.ts +71 -0
- package/dist/runner/dialogs.d.ts.map +1 -0
- package/dist/runner/dialogs.js +189 -0
- package/dist/runner/files.d.ts +79 -0
- package/dist/runner/files.d.ts.map +1 -0
- package/dist/runner/files.js +312 -0
- package/dist/runner/inbox-links.d.ts +19 -0
- package/dist/runner/inbox-links.d.ts.map +1 -0
- package/dist/runner/inbox-links.js +63 -0
- package/dist/runner/inbox.d.ts +87 -0
- package/dist/runner/inbox.d.ts.map +1 -0
- package/dist/runner/inbox.js +340 -0
- package/dist/runner/index.d.ts +2 -1
- package/dist/runner/index.d.ts.map +1 -1
- package/dist/runner/media-leftovers.d.ts +7 -3
- package/dist/runner/media-leftovers.d.ts.map +1 -1
- package/dist/runner/media-leftovers.js +27 -6
- package/dist/runner/native-pool.d.ts.map +1 -1
- package/dist/runner/native-pool.js +2 -0
- package/dist/runner/observations.d.ts +15 -2
- package/dist/runner/observations.d.ts.map +1 -1
- package/dist/runner/observations.js +109 -6
- package/dist/runner/popups.d.ts +82 -0
- package/dist/runner/popups.d.ts.map +1 -0
- package/dist/runner/popups.js +236 -0
- package/dist/runner/redactor.d.ts.map +1 -1
- package/dist/runner/redactor.js +10 -6
- package/dist/runner/resources.d.ts +8 -0
- package/dist/runner/resources.d.ts.map +1 -1
- package/dist/runner/resources.js +12 -1
- package/dist/runner/routes.d.ts +23 -0
- package/dist/runner/routes.d.ts.map +1 -0
- package/dist/runner/routes.js +128 -0
- package/dist/runner/run-media.d.ts +6 -0
- package/dist/runner/run-media.d.ts.map +1 -1
- package/dist/runner/run-media.js +21 -0
- package/dist/runner/run-session.d.ts.map +1 -1
- package/dist/runner/run-session.js +102 -12
- package/dist/runner/run.d.ts.map +1 -1
- package/dist/runner/run.js +2 -1
- package/dist/runner/running-test.d.ts +35 -0
- package/dist/runner/running-test.d.ts.map +1 -1
- package/dist/runner/running-test.js +333 -22
- package/dist/runner/screenshot-baselines.d.ts +159 -0
- package/dist/runner/screenshot-baselines.d.ts.map +1 -0
- package/dist/runner/screenshot-baselines.js +357 -0
- package/dist/runner/secrets.d.ts +13 -0
- package/dist/runner/secrets.d.ts.map +1 -1
- package/dist/runner/secrets.js +6 -4
- package/dist/runner/target-drivers.d.ts +5 -2
- package/dist/runner/target-drivers.d.ts.map +1 -1
- package/dist/runner/target-drivers.js +10 -1
- package/dist/runner/test-file-process.d.ts +8 -0
- package/dist/runner/test-file-process.d.ts.map +1 -1
- package/dist/runner/test-file-process.js +26 -3
- package/dist/runner/test-pages.d.ts +3 -1
- package/dist/runner/test-pages.d.ts.map +1 -1
- package/dist/runner/test-pages.js +9 -5
- package/dist/schemas/event-v1.schema.json +118873 -6311
- package/dist/schemas/result-v1.schema.json +4 -0
- package/dist/shared/environment.d.ts +17 -0
- package/dist/shared/environment.d.ts.map +1 -0
- package/dist/shared/environment.js +27 -0
- package/dist/shared/image-diff.d.ts +36 -0
- package/dist/shared/image-diff.d.ts.map +1 -0
- package/dist/shared/image-diff.js +242 -0
- package/dist/shared/metadata-process-worker.js +15 -7
- package/dist/shared/metadata-process.d.ts +9 -1
- package/dist/shared/metadata-process.d.ts.map +1 -1
- package/dist/shared/metadata-process.js +84 -12
- package/dist/shared/png.d.ts +35 -0
- package/dist/shared/png.d.ts.map +1 -0
- package/dist/shared/png.js +251 -0
- package/dist/shared/posix-path.d.ts +12 -0
- package/dist/shared/posix-path.d.ts.map +1 -1
- package/dist/shared/posix-path.js +16 -0
- package/dist/shared/private-file.d.ts +38 -0
- package/dist/shared/private-file.d.ts.map +1 -0
- package/dist/shared/private-file.js +132 -0
- package/dist/shared/process-ownership.d.ts +67 -6
- package/dist/shared/process-ownership.d.ts.map +1 -1
- package/dist/shared/process-ownership.js +227 -45
- package/dist/shared/process-supervisor.d.ts +309 -0
- package/dist/shared/process-supervisor.d.ts.map +1 -0
- package/dist/shared/process-supervisor.js +737 -0
- package/dist/shared/process-system.d.ts +113 -0
- package/dist/shared/process-system.d.ts.map +1 -0
- package/dist/shared/process-system.js +254 -0
- package/dist/shared/regular-file.d.ts +2 -2
- package/dist/shared/regular-file.d.ts.map +1 -1
- package/dist/shared/regular-file.js +19 -2
- package/dist/store/artifacts.d.ts +28 -6
- package/dist/store/artifacts.d.ts.map +1 -1
- package/dist/store/artifacts.js +58 -6
- package/dist/store/rebuild-result.d.ts.map +1 -1
- package/dist/store/rebuild-result.js +6 -0
- package/dist/store/run-store.d.ts +5 -2
- package/dist/store/run-store.d.ts.map +1 -1
- package/dist/store/run-store.js +48 -4
- package/media/Cargo.lock +16 -0
- package/media/Cargo.toml +16 -1
- package/media/src/encoder.rs +56 -12
- package/media/src/frame.rs +7 -1
- package/media/src/main.rs +20 -2
- package/media/src/place.rs +230 -11
- package/media/src/process_ownership_windows.rs +1058 -0
- package/media/src/recording.rs +15 -7
- package/media/src/replies.rs +55 -0
- package/media/src/server.rs +72 -2
- package/media/src/store.rs +71 -2
- package/package.json +9 -4
- package/src/cli/install/media-notices.txt +465 -1
- package/supervisor/Cargo.lock +25 -0
- package/supervisor/Cargo.toml +22 -0
- package/supervisor/NOTICES +464 -0
- package/supervisor/build.rs +44 -0
- package/supervisor/src/command.rs +612 -0
- package/supervisor/src/jobs.rs +1650 -0
- package/supervisor/src/main.rs +71 -0
- package/supervisor/src/reply.rs +367 -0
package/dist/browser/builds.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { closeSync, constants, fstatSync, lstatSync, openSync, readSync } from 'node:fs';
|
|
2
2
|
import { createHash } from 'node:crypto';
|
|
3
3
|
import { access, lstat, readdir, readlink } from 'node:fs/promises';
|
|
4
|
-
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
4
|
+
import { basename, dirname, isAbsolute, join, posix, relative, resolve, sep, win32 } from 'node:path';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
6
|
import { folderChecksum, nativePins, pinKey, readBuildRecord } from "../native/executors.js";
|
|
7
7
|
import { errorMessage } from "../protocol/failures.js";
|
|
@@ -13,6 +13,8 @@ export const buildEngines = ['chromium', 'firefox', 'webkit', 'electron', 'webdr
|
|
|
13
13
|
const chromiumVersion = '153.0.8010.12';
|
|
14
14
|
const chromeForTesting = 'https://storage.googleapis.com/chrome-for-testing-public';
|
|
15
15
|
const macChrome = 'chrome-mac-arm64/Google Chrome for Testing.app';
|
|
16
|
+
const firefoxReleases = 'https://archive.mozilla.org/pub/firefox/releases';
|
|
17
|
+
const electronReleases = 'https://github.com/electron/electron/releases/download';
|
|
16
18
|
// Authorized Linux archive observations, retained beside the pin table without adding unsupported install pins.
|
|
17
19
|
// Firefox 133.0.3: https://archive.mozilla.org/pub/firefox/releases/133.0.3/linux-x86_64/en-US/firefox-133.0.3.tar.bz2
|
|
18
20
|
// 89_495_132 bytes; SHA-256 43713e238d0153fdbf1ab46dd76c6b01ab83fae197b5dc3a95087f51907ba44d.
|
|
@@ -76,6 +78,7 @@ function executorPin(engine) {
|
|
|
76
78
|
* The tested set. Chromium is Chrome for Testing, from Google; Firefox is Mozilla's release; WebKit is Playwright's
|
|
77
79
|
* automation build, the only WebKit build with the inspector pipe Retest drives; Electron is the release its fixture app
|
|
78
80
|
* runs on; the two native executors are built from their pinned commits. Only Chromium is pinned for Linux x64; its archive has been inspected, without a Linux browser execution claim.
|
|
81
|
+
* Windows x64 has Chromium, Firefox and Electron, from the same releases, and no WebKit build.
|
|
79
82
|
*/
|
|
80
83
|
export const pinnedBuilds = [
|
|
81
84
|
{
|
|
@@ -114,23 +117,58 @@ export const pinnedBuilds = [
|
|
|
114
117
|
},
|
|
115
118
|
provenance: 'Archive size and checksum, executable and both licence files read from the Google publisher download. Linux browser execution and installation remain unverified.',
|
|
116
119
|
},
|
|
120
|
+
{
|
|
121
|
+
kind: 'archive',
|
|
122
|
+
engine: 'chromium',
|
|
123
|
+
title: 'Chrome for Testing',
|
|
124
|
+
version: chromiumVersion,
|
|
125
|
+
platform: 'win-x64',
|
|
126
|
+
archive: { format: 'zip', url: `${chromeForTesting}/${chromiumVersion}/win64/chrome-win64.zip`, size: 205_123_748, sha256: '415968b02065d4a9e2c10b85f0ae9f489b8fba500e94d9d0a7b7c4852a7234c1' },
|
|
127
|
+
executable: { path: 'chrome-win64/chrome.exe', sha256: '9b07943f834485b43c9d54caea2951c78715f9f07070a80ab6658465ebd3e711' },
|
|
128
|
+
files: [],
|
|
129
|
+
licences: {
|
|
130
|
+
inspected: true,
|
|
131
|
+
files: [
|
|
132
|
+
{ path: 'chrome-win64/ABOUT', title: "the build's notice, which names chrome://credits, where the licences compiled into the browser are listed", licence: 'BSD-3-Clause and the licences at chrome://credits', sha256: '122b32f3ee3f1e8d65c774f5257fc6cc2127b666148ced0ce2efa3ea57e1d93c', published: true },
|
|
133
|
+
],
|
|
134
|
+
},
|
|
135
|
+
provenance: 'Archive size and checksum, executable and notice read from the Google publisher download of 21 October 2026, here and on a Windows Server 2025 machine, whose own tar.exe unpacks the same files as unzip and libarchive bsdtar do on macOS. The Windows build carries no Widevine module, so there is no Widevine licence to pin. Installed by retest install and run on Windows Server 2025 x64, on a GitHub windows-2025 runner, in the 0.3.0 CI matrix.',
|
|
136
|
+
},
|
|
117
137
|
{
|
|
118
138
|
kind: 'archive',
|
|
119
139
|
engine: 'firefox',
|
|
120
140
|
title: 'Firefox',
|
|
121
|
-
version: '
|
|
122
|
-
build: '
|
|
141
|
+
version: '158.0.1',
|
|
142
|
+
build: '20261019185856',
|
|
123
143
|
platform: 'mac-arm64',
|
|
124
|
-
archive: { format: 'dmg', app: 'Firefox.app', url:
|
|
125
|
-
executable: { path: 'Firefox.app/Contents/MacOS/firefox', sha256: '
|
|
144
|
+
archive: { format: 'dmg', app: 'Firefox.app', url: `${firefoxReleases}/158.0.1/mac/en-US/Firefox%20158.0.1.dmg`, size: 165_038_147, sha256: '1d7aa96b51fc9110185047de18228ac87238fba5e42bba53c9d696f88878cba6', checksums: `${firefoxReleases}/158.0.1/SHA256SUMS` },
|
|
145
|
+
executable: { path: 'Firefox.app/Contents/MacOS/firefox', sha256: '0b406e1d7c88d48c13f6389e05f22dedcb6ab99f06e539150a49e4ba995d0386' },
|
|
126
146
|
files: [],
|
|
127
147
|
licences: {
|
|
128
148
|
inspected: true,
|
|
129
149
|
files: [
|
|
130
|
-
{ path: 'Firefox.app/Contents/Resources/omni.ja', title: "the archive that holds Firefox's about:license page, chrome/toolkit/content/global/license.html", licence: 'MPL-2.0 and the licences at about:license', sha256: '
|
|
150
|
+
{ path: 'Firefox.app/Contents/Resources/omni.ja', title: "the archive that holds Firefox's about:license page, chrome/toolkit/content/global/license.html", licence: 'MPL-2.0 and the licences at about:license', sha256: 'dbfea026a6155b5c8794f55b2e54b19b0120353379a18e343dad381aa84228f5', published: true },
|
|
131
151
|
],
|
|
132
152
|
},
|
|
133
|
-
provenance:
|
|
153
|
+
provenance: "Archive size and checksum from Mozilla's download of 22 October 2026, which matched the release's SHA256SUMS. The image holds Firefox.app at its root, copied to Firefox.app under the installed build. Executable and omni.ja checksums read from the mounted image; its application.ini names Firefox 158.0.1 build 20261019185856.",
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
kind: 'archive',
|
|
157
|
+
engine: 'firefox',
|
|
158
|
+
title: 'Firefox',
|
|
159
|
+
version: '158.0.1',
|
|
160
|
+
build: '20261019185856',
|
|
161
|
+
platform: 'win-x64',
|
|
162
|
+
archive: { format: 'exe', folder: 'core', url: `${firefoxReleases}/158.0.1/win64/en-US/Firefox%20Setup%20158.0.1.exe`, size: 94_890_968, sha256: '3259a2f8508e58cf2e383b6c99bfc64d6ddc86d1407b7c2f86f660af955b5d10', checksums: `${firefoxReleases}/158.0.1/SHA256SUMS` },
|
|
163
|
+
executable: { path: 'core/firefox.exe', sha256: '76732d4e43c864194660c671c52ecf4bad89e43b666d9a0acf89cd4b692ced9b' },
|
|
164
|
+
files: [],
|
|
165
|
+
licences: {
|
|
166
|
+
inspected: true,
|
|
167
|
+
files: [
|
|
168
|
+
{ path: 'core/omni.ja', title: "the archive that holds Firefox's about:license page, chrome/toolkit/content/global/license.html", licence: 'MPL-2.0 and the licences at about:license', sha256: '42f976ac57103698320728a9c134ec8e710ab9a3c48d127ea3e115e1b3b211c3', published: true },
|
|
169
|
+
],
|
|
170
|
+
},
|
|
171
|
+
provenance: "Archive size and checksum from Mozilla's download of 22 October 2026, which matched the release's SHA256SUMS. Mozilla publishes no zip of a Windows release, only this installer: a 7-Zip archive behind a self-extracting stub that Retest never runs. The archive holds setup.exe and the core folder, which is the whole of Firefox and is unpacked alone. Executable and omni.ja checksums read from that folder as libarchive bsdtar unpacked it on macOS, and the same bytes again after retest install unpacked it with tar.exe on a Windows Server 2025 machine; its application.ini names Firefox 158.0.1 build 20261019185856.",
|
|
134
172
|
},
|
|
135
173
|
{
|
|
136
174
|
kind: 'archive',
|
|
@@ -171,6 +209,25 @@ export const pinnedBuilds = [
|
|
|
171
209
|
treeSha256: 'f94a2b748b5f3e41b0ff1938ebd02052bb8af4cf037c2d24d21ffd51c5f7d7b4',
|
|
172
210
|
provenance: "Archive size and checksum from a download of the official release, which matched the release's SHASUMS256.txt; executable, licence and tree checksums read from that archive unpacked with ditto in ~/Library/Caches/retest-proofs/electron/44.5.1.",
|
|
173
211
|
},
|
|
212
|
+
{
|
|
213
|
+
kind: 'archive',
|
|
214
|
+
engine: 'electron',
|
|
215
|
+
title: 'Electron',
|
|
216
|
+
version: '44.5.1',
|
|
217
|
+
platform: 'win-x64',
|
|
218
|
+
archive: { format: 'zip', url: `${electronReleases}/v44.5.1/electron-v44.5.1-win32-x64.zip`, size: 157_998_329, sha256: '9b382492dcfee91f8f9e92c91f7972550a1b95d2299cac72279dab33a600d7db', checksums: `${electronReleases}/v44.5.1/SHASUMS256.txt` },
|
|
219
|
+
executable: { path: 'electron.exe', sha256: '49b61a030a520fc36a4b8fa5cce53fb4e935a7bdbbe4b80e9222f598e49cc7fa' },
|
|
220
|
+
files: [],
|
|
221
|
+
licences: {
|
|
222
|
+
inspected: true,
|
|
223
|
+
files: [
|
|
224
|
+
{ path: 'LICENSE', title: "Electron's licence", licence: 'MIT', sha256: '5154e165bd6c2cc0cfbcd8916498c7abab0497923bafcd5cb07673fe8480087d', published: true },
|
|
225
|
+
{ path: 'LICENSES.chromium.html', title: 'the licences of Chromium and the libraries compiled into it', licence: 'BSD-3-Clause and the licences it lists', sha256: '7b328b8c7463ac9bfc7dc648c751533517c8441a0b5b21047d6c0b2620e60d70', published: true },
|
|
226
|
+
],
|
|
227
|
+
},
|
|
228
|
+
treeSha256: '0a50669f7461801821ab9d01ee2193748d36f45b6235bcfd648ed9a44a175e30',
|
|
229
|
+
provenance: "Archive size and checksum from a download of the official release on 21 October 2026, which matched the release's SHASUMS256.txt, here and on a Windows Server 2025 machine. Executable, licence and tree checksums read on that machine from the archive unpacked with its own tar.exe; unzip and libarchive bsdtar on macOS unpack the same files. Installed by retest install and run on Windows Server 2025 x64, on a GitHub windows-2025 runner, in the 0.3.0 CI matrix.",
|
|
230
|
+
},
|
|
174
231
|
executorPin('webdriveragent'),
|
|
175
232
|
executorPin('mac2'),
|
|
176
233
|
];
|
|
@@ -184,11 +241,14 @@ export function buildPlatform(platform = process.platform, arch = process.arch)
|
|
|
184
241
|
return 'mac-arm64';
|
|
185
242
|
if (platform === 'linux' && arch === 'x64')
|
|
186
243
|
return 'linux-x64';
|
|
244
|
+
if (platform === 'win32' && arch === 'x64')
|
|
245
|
+
return 'win-x64';
|
|
187
246
|
return undefined;
|
|
188
247
|
}
|
|
189
|
-
|
|
248
|
+
const platformNames = { 'mac-arm64': 'macOS arm64', 'linux-x64': 'Linux x64', 'win-x64': 'Windows x64' };
|
|
249
|
+
/** @example describePlatform('win-x64') // 'Windows x64' */
|
|
190
250
|
export function describePlatform(platform) {
|
|
191
|
-
return platform
|
|
251
|
+
return platformNames[platform];
|
|
192
252
|
}
|
|
193
253
|
/**
|
|
194
254
|
* The pin of one engine for one platform, if Retest pins one.
|
|
@@ -198,6 +258,16 @@ export function describePlatform(platform) {
|
|
|
198
258
|
export function findPin(engine, platform, pins = pinnedBuilds) {
|
|
199
259
|
return pins.find((pin) => pin.engine === engine && pin.platform === platform);
|
|
200
260
|
}
|
|
261
|
+
/**
|
|
262
|
+
* Why there is no pin of an engine for a platform, as one sentence for `retest install` to refuse with.
|
|
263
|
+
*
|
|
264
|
+
* @example unpinnedMessage('webkit', 'win-x64') // 'Retest does not run WebKit on Windows, so there is no WebKit build to install.'
|
|
265
|
+
*/
|
|
266
|
+
export function unpinnedMessage(engine, platform) {
|
|
267
|
+
if (engine === 'webkit' && platform === 'win-x64')
|
|
268
|
+
return 'Retest does not run WebKit on Windows, so there is no WebKit build to install.';
|
|
269
|
+
return `Retest pins no ${engine} build for ${describePlatform(platform)}.`;
|
|
270
|
+
}
|
|
201
271
|
/** @example describePin(findPin('electron', 'mac-arm64')) // 'Electron 44.5.1' */
|
|
202
272
|
export function describePin(pin) {
|
|
203
273
|
const build = pin.kind === 'archive' && pin.build !== undefined ? ` (build ${pin.build})` : '';
|
|
@@ -275,17 +345,46 @@ export function readBundledLicence(file) {
|
|
|
275
345
|
}
|
|
276
346
|
/**
|
|
277
347
|
* The cache folders under the user's cache folder: `~/Library/Caches/retest` on macOS, `$XDG_CACHE_HOME/retest` or
|
|
278
|
-
* `~/.cache/retest` on Linux. Undefined without an absolute `HOME`,
|
|
348
|
+
* `~/.cache/retest` on Linux, `%LOCALAPPDATA%\retest` on Windows. Undefined without an absolute `HOME`, or on Windows
|
|
349
|
+
* an absolute `LOCALAPPDATA`, since there is then no user cache folder. Paths are written as `platform` writes them.
|
|
279
350
|
*
|
|
280
351
|
* @example cacheFolders({ HOME: '/Users/ada' }, 'darwin')?.browsers // '/Users/ada/Library/Caches/retest/browsers'
|
|
352
|
+
* @example cacheFolders({ LOCALAPPDATA: 'C:\\Users\\ada\\AppData\\Local' }, 'win32')?.browsers // 'C:\\Users\\ada\\AppData\\Local\\retest\\browsers'
|
|
281
353
|
*/
|
|
282
354
|
export function cacheFolders(env, platform = process.platform) {
|
|
355
|
+
if (platform === 'win32') {
|
|
356
|
+
const local = environmentVariable(env, cacheVariable(platform), platform);
|
|
357
|
+
if (local === undefined || !win32.isAbsolute(local))
|
|
358
|
+
return undefined;
|
|
359
|
+
return { browsers: win32.join(local, 'retest', 'browsers'), executors: win32.join(local, 'retest', 'native-executors') };
|
|
360
|
+
}
|
|
283
361
|
const home = env['HOME'];
|
|
284
|
-
if (home === undefined || !isAbsolute(home))
|
|
362
|
+
if (home === undefined || !posix.isAbsolute(home))
|
|
285
363
|
return undefined;
|
|
286
364
|
const xdg = env['XDG_CACHE_HOME'];
|
|
287
|
-
const root = platform === 'darwin' ? join(home, 'Library', 'Caches') : xdg !== undefined && isAbsolute(xdg) ? xdg : join(home, '.cache');
|
|
288
|
-
return { browsers: join(root, 'retest', 'browsers'), executors: join(root, 'retest', 'native-executors') };
|
|
365
|
+
const root = platform === 'darwin' ? posix.join(home, 'Library', 'Caches') : xdg !== undefined && posix.isAbsolute(xdg) ? xdg : posix.join(home, '.cache');
|
|
366
|
+
return { browsers: posix.join(root, 'retest', 'browsers'), executors: posix.join(root, 'retest', 'native-executors') };
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* The variable `cacheFolders` finds the user's cache folder from, for a message to name when it is not set.
|
|
370
|
+
*
|
|
371
|
+
* @example cacheVariable('win32') // 'LOCALAPPDATA'
|
|
372
|
+
*/
|
|
373
|
+
export function cacheVariable(platform = process.platform) {
|
|
374
|
+
return platform === 'win32' ? 'LOCALAPPDATA' : 'HOME';
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* An environment variable as the system reads it: by its exact name, and on Windows, where names differ only in case
|
|
378
|
+
* for the same variable, by any spelling of it. `process.env` already reads so on Windows; a copy of it does not.
|
|
379
|
+
*
|
|
380
|
+
* @example environmentVariable({ ProgramFiles: 'C:\\Program Files' }, 'PROGRAMFILES', 'win32') // 'C:\\Program Files'
|
|
381
|
+
*/
|
|
382
|
+
export function environmentVariable(env, name, platform = process.platform) {
|
|
383
|
+
const exact = env[name];
|
|
384
|
+
if (exact !== undefined || platform !== 'win32')
|
|
385
|
+
return exact;
|
|
386
|
+
const wanted = name.toUpperCase();
|
|
387
|
+
return Object.entries(env).find(([key]) => key.toUpperCase() === wanted)?.[1];
|
|
289
388
|
}
|
|
290
389
|
/**
|
|
291
390
|
* The folder one pin's build is installed in. A browser or Electron build is named after its engine, version and
|
|
@@ -315,7 +414,7 @@ const installedRecordSchema = s.object({
|
|
|
315
414
|
schemaVersion: s.literal(1),
|
|
316
415
|
engine: s.enum(['chromium', 'firefox', 'webkit', 'electron']),
|
|
317
416
|
version: s.string(),
|
|
318
|
-
platform: s.enum(['mac-arm64', 'linux-x64']),
|
|
417
|
+
platform: s.enum(['mac-arm64', 'linux-x64', 'win-x64']),
|
|
319
418
|
source: s.string(),
|
|
320
419
|
sourceCode: s.optional(s.object({ repository: s.string(), revision: s.string(), patches: s.string() })),
|
|
321
420
|
fetchedFrom: s.string(),
|
|
@@ -483,7 +582,7 @@ export async function inspectBuilds(platform, folders, options = {}, pins = pinn
|
|
|
483
582
|
* `retest install` refuses. The message names the folder, what is wrong and how to fix it. Nothing is downloaded,
|
|
484
583
|
* and nothing is thrown: a folder that cannot be read is damaged.
|
|
485
584
|
*
|
|
486
|
-
* @example await installedBuild('firefox', process.env) // { state: 'damaged', message: 'Firefox
|
|
585
|
+
* @example await installedBuild('firefox', process.env) // { state: 'damaged', message: 'Firefox 158.0.1 … in … is not usable: …' }
|
|
487
586
|
*/
|
|
488
587
|
export async function installedBuild(engine, env, options = {}) {
|
|
489
588
|
const platform = 'platform' in options ? options.platform : buildPlatform();
|
|
@@ -511,7 +610,7 @@ export async function installedBuild(engine, env, options = {}) {
|
|
|
511
610
|
* installed as its pin and record say; undefined otherwise, which a damaged build is too. A driver that must tell a
|
|
512
611
|
* damaged build from a missing one asks `installedBuild`. A target's own `executablePath` always wins over it.
|
|
513
612
|
*
|
|
514
|
-
* @example await installedExecutable('firefox', process.env) // '/Users/ada/Library/Caches/retest/browsers/firefox-
|
|
613
|
+
* @example await installedExecutable('firefox', process.env) // '/Users/ada/Library/Caches/retest/browsers/firefox-158.0.1-mac-arm64/build/Firefox.app/Contents/MacOS/firefox'
|
|
515
614
|
*/
|
|
516
615
|
export async function installedExecutable(engine, env, options = {}) {
|
|
517
616
|
const build = await installedBuild(engine, env, options);
|
|
@@ -51,6 +51,12 @@ export declare class CdpConnection {
|
|
|
51
51
|
* @example const session = await connection.attach(targetId)
|
|
52
52
|
*/
|
|
53
53
|
attach(targetId: string, options?: SendOptions): Promise<CdpSession>;
|
|
54
|
+
/**
|
|
55
|
+
* Takes on a flat session the browser attached by itself, as `Target.setAutoAttach` does, named in its
|
|
56
|
+
* `Target.attachedToTarget` event. Call it while that event is handled, so no event of the session's arrives first.
|
|
57
|
+
* @example const session = connection.adopt(sessionId)
|
|
58
|
+
*/
|
|
59
|
+
adopt(sessionId: string): CdpSession;
|
|
54
60
|
/** Ends the connection. Every waiting command rejects with a `CdpDisconnectedError`. */
|
|
55
61
|
close(): void;
|
|
56
62
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../src/browser/cdp/connection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAehE,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AAE3D;;;;GAIG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC9D;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AAE7F,MAAM,MAAM,iBAAiB,GAAG;IAC9B,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAA;IACjB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,CAAC,UAAU,EAAE,aAAa,KAAK,IAAI,CAAA;CAClD,CAAA;AAED,eAAO,MAAM,mBAAmB,EAAE,MAAa,CAAA;AAc/C,2DAA2D;AAC3D,qBAAa,aAAa;;gBAWZ,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,iBAAiB;IAkB5D,qCAAqC;IACrC,IAAI,WAAW,IAAI,MAAM,GAAG,SAAS,CAEpC;IAED;;;OAGG;IACH,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAI9E;;;OAGG;IACH,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI;IAInE,YAAY,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI;IAI5D;;;OAGG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAMpE,wFAAwF;IACxF,KAAK,IAAI,IAAI;CAkKd"}
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../src/browser/cdp/connection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAehE,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AAE3D;;;;GAIG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC9D;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AAE7F,MAAM,MAAM,iBAAiB,GAAG;IAC9B,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAA;IACjB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,CAAC,UAAU,EAAE,aAAa,KAAK,IAAI,CAAA;CAClD,CAAA;AAED,eAAO,MAAM,mBAAmB,EAAE,MAAa,CAAA;AAc/C,2DAA2D;AAC3D,qBAAa,aAAa;;gBAWZ,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,iBAAiB;IAkB5D,qCAAqC;IACrC,IAAI,WAAW,IAAI,MAAM,GAAG,SAAS,CAEpC;IAED;;;OAGG;IACH,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAI9E;;;OAGG;IACH,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI;IAInE,YAAY,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI;IAI5D;;;OAGG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAMpE;;;;OAIG;IACH,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU;IAIpC,wFAAwF;IACxF,KAAK,IAAI,IAAI;CAkKd"}
|
|
@@ -62,6 +62,14 @@ export class CdpConnection {
|
|
|
62
62
|
attach(targetId, options) {
|
|
63
63
|
return this.#send(this.#root, ATTACH_METHOD, { targetId, flatten: true }, options, (result) => this.#openSession(result));
|
|
64
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Takes on a flat session the browser attached by itself, as `Target.setAutoAttach` does, named in its
|
|
67
|
+
* `Target.attachedToTarget` event. Call it while that event is handled, so no event of the session's arrives first.
|
|
68
|
+
* @example const session = connection.adopt(sessionId)
|
|
69
|
+
*/
|
|
70
|
+
adopt(sessionId) {
|
|
71
|
+
return this.#openSession({ sessionId });
|
|
72
|
+
}
|
|
65
73
|
/** Ends the connection. Every waiting command rejects with a `CdpDisconnectedError`. */
|
|
66
74
|
close() {
|
|
67
75
|
this.#transport.close();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../src/browser/cdp/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAErD,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,iEAAiE;IACjE,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,sDAAsD;IACtD,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,yFAAyF;IACzF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,6EAA6E;IAC7E,QAAQ,IAAI,IAAI,CAAA;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAA;IACzC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAAA;IACnC,KAAK,IAAI,IAAI,CAAA;CACd;AAED,uFAAuF;AACvF,MAAM,MAAM,WAAW,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAAA;AAMpE,6EAA6E;AAC7E,qBAAa,aAAc,YAAW,SAAS;;gBAUjC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,WAAW;
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../src/browser/cdp/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAErD,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,iEAAiE;IACjE,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,sDAAsD;IACtD,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,yFAAyF;IACzF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,6EAA6E;IAC7E,QAAQ,IAAI,IAAI,CAAA;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAA;IACzC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAAA;IACnC,KAAK,IAAI,IAAI,CAAA;CACd;AAED,uFAAuF;AACvF,MAAM,MAAM,WAAW,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAAA;AAMpE,6EAA6E;AAC7E,qBAAa,aAAc,YAAW,SAAS;;gBAUjC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,WAAW;IAkB/C,qFAAqF;IACrF,MAAM,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IAUzC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe;IAgBnC,KAAK,IAAI,IAAI;CAqDd"}
|
|
@@ -12,20 +12,20 @@ export class PipeTransport {
|
|
|
12
12
|
constructor({ readable, writable }) {
|
|
13
13
|
this.#readable = readable;
|
|
14
14
|
this.#writable = writable;
|
|
15
|
+
// A pipe that closes without Retest closing it means the browser went, whichever of its two ends Node hears of first,
|
|
16
|
+
// so a killed browser is told of in one sentence however the ends race.
|
|
15
17
|
readable.on('end', () => this.#end('the browser closed the pipe'));
|
|
16
18
|
readable.on('close', () => this.#end('the browser closed the pipe'));
|
|
17
19
|
readable.on('error', (error) => this.#end(`reading from the browser failed: ${error.message}`));
|
|
18
|
-
writable.on('close', () => this.#end('the
|
|
20
|
+
writable.on('close', () => this.#end('the browser closed the pipe'));
|
|
19
21
|
writable.on('error', (error) => this.#end(`writing to the browser failed: ${error.message}`));
|
|
20
22
|
writable.on('drain', () => {
|
|
21
23
|
this.#blocked = false;
|
|
22
24
|
this.#flush();
|
|
23
25
|
});
|
|
24
26
|
// A stream that ended before this point never emits its events again.
|
|
25
|
-
if (readable.destroyed || readable.readableEnded)
|
|
27
|
+
if (readable.destroyed || readable.readableEnded || writable.destroyed || writable.writableEnded)
|
|
26
28
|
this.#end('the browser closed the pipe');
|
|
27
|
-
else if (writable.destroyed || writable.writableEnded)
|
|
28
|
-
this.#end('the pipe to the browser closed');
|
|
29
29
|
}
|
|
30
30
|
/** Starts reading. Nothing is read before this, so no message can arrive unheard. */
|
|
31
31
|
listen(handlers) {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { ActionIntent } from './element-queries.ts';
|
|
2
|
-
import type {
|
|
2
|
+
import type { PageWorld } from './isolated-world.ts';
|
|
3
3
|
import type { Deadline } from '../protocol/deadline.ts';
|
|
4
4
|
import type { Failure } from '../protocol/failures.ts';
|
|
5
5
|
import type { LocatorRecipe } from '../protocol/locator.ts';
|
|
6
6
|
export type CheckedStateOptions = {
|
|
7
|
-
world:
|
|
7
|
+
world: PageWorld;
|
|
8
8
|
locator: LocatorRecipe;
|
|
9
9
|
intent: Extract<ActionIntent, {
|
|
10
10
|
action: 'check' | 'uncheck';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checked-state.d.ts","sourceRoot":"","sources":["../../src/browser/checked-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"checked-state.d.ts","sourceRoot":"","sources":["../../src/browser/checked-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAM3D,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,SAAS,CAAA;IAChB,OAAO,EAAE,aAAa,CAAA;IACtB,MAAM,EAAE,OAAO,CAAC,YAAY,EAAE;QAAE,MAAM,EAAE,OAAO,GAAG,SAAS,CAAA;KAAE,CAAC,CAAA;IAC9D,4DAA4D;IAC5D,GAAG,EAAE,OAAO,GAAG,SAAS,CAAA;IACxB,QAAQ,EAAE,QAAQ,CAAA;CACnB,CAAA;AAKD;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAgBpI"}
|
|
@@ -70,10 +70,17 @@ export declare class ChromiumProcess {
|
|
|
70
70
|
*/
|
|
71
71
|
gone(): Promise<void>;
|
|
72
72
|
/**
|
|
73
|
-
* Reads descendants while their launched parent is still present
|
|
74
|
-
*
|
|
73
|
+
* Reads descendants while their launched parent is still present, holding the thread, as a process made from a
|
|
74
|
+
* child no owner has read yet does. A helper recorded early is still owned after its parent dies.
|
|
75
75
|
*/
|
|
76
76
|
recordDescendants(deadline?: Deadline): void;
|
|
77
|
+
/**
|
|
78
|
+
* `recordDescendants` from a reading begun now that does not hold the thread, within `deadline`, as a close reads
|
|
79
|
+
* before it asks the browser to quit. A reading that fails is kept, as one that holds the thread is.
|
|
80
|
+
*
|
|
81
|
+
* @example await chromium.recordDescendantsNow(new Deadline(5000))
|
|
82
|
+
*/
|
|
83
|
+
recordDescendantsNow(deadline: Deadline): Promise<void>;
|
|
77
84
|
/**
|
|
78
85
|
* `recordDescendants` from a reading taken without holding the thread, as after each new page, whose renderer the
|
|
79
86
|
* browser has just started. A process-table reading takes tens of milliseconds, which a page open would otherwise wait.
|
|
@@ -105,4 +112,27 @@ export declare function stillThereMessage(groupId: number, stats: () => readonly
|
|
|
105
112
|
export declare function signalGroup(pgid: number, signal: NodeJS.Signals | 0): boolean;
|
|
106
113
|
/** Signals a descendant only after this process recorded it beneath the launched browser. */
|
|
107
114
|
export declare function signalRecordedProcess(browserPid: number, pid: number, signal: NodeJS.Signals): void;
|
|
115
|
+
/**
|
|
116
|
+
* Waits for the output to close. A timer can fire before I/O that is already waiting has been read, when the main thread
|
|
117
|
+
* was busy with other work such as synchronous process readings, so the clock alone is no proof the output is still
|
|
118
|
+
* open: on a busy host every healthy close failed so. When the bound passes, waiting I/O is read first, then the output
|
|
119
|
+
* is judged by whether anything can still write to it. Once nothing can, Retest's own writing gets its own bound.
|
|
120
|
+
* If a writer remains after verified owned shutdown, an output with safe reader finish support may stop its local
|
|
121
|
+
* readers and flush accepted bytes and queued writes within that same writing bound. This does not claim remote
|
|
122
|
+
* EOF or collect bytes an inherited writer sends later. An output without this support still fails and is canceled.
|
|
123
|
+
*/
|
|
124
|
+
export declare function outputWithin(output: BrowserOutput, timeoutMs: number, confirmedGone: () => Promise<boolean>): Promise<string[]>;
|
|
125
|
+
/** How long an exit hook on Windows asks again to remove a folder whose processes it confirmed gone. */
|
|
126
|
+
export declare const exitRemovalMs: number;
|
|
127
|
+
/**
|
|
128
|
+
* Removes a folder from an exit hook on Windows, where a folder whose files processes just ended were using refuses
|
|
129
|
+
* removal for a moment after they left their job, and the synchronous removal does not wait: it is asked again, a poll
|
|
130
|
+
* apart, until the deadline.
|
|
131
|
+
*/
|
|
132
|
+
export declare function removeOnceFree(folder: string, deadline: Deadline): void;
|
|
133
|
+
/**
|
|
134
|
+
* Whether a group is gone, for an exit hook, which cannot await. Processes just sent SIGKILL are still exiting when they
|
|
135
|
+
* are first read, so the group is read again, a poll apart, until it is gone or the deadline passes.
|
|
136
|
+
*/
|
|
137
|
+
export declare function groupEndsNow(ownership: OwnedProcessGroup, deadline: Deadline): boolean;
|
|
108
138
|
//# sourceMappingURL=chromium-process.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chromium-process.d.ts","sourceRoot":"","sources":["../../src/browser/chromium-process.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAQnD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"chromium-process.d.ts","sourceRoot":"","sources":["../../src/browser/chromium-process.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAQnD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAMlD,OAAO,EAAE,iBAAiB,EAA4B,MAAM,gCAAgC,CAAA;AAE5F,OAAO,EAAgB,WAAW,EAAE,MAAM,eAAe,CAAA;AAGzD,MAAM,MAAM,YAAY,GAAG;IACzB,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAA;IACf,sDAAsD;IACtD,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IACjC,+FAA+F;IAC/F,YAAY,CAAC,EAAE,MAAM,cAAc,CAAA;CACpC,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAClC,MAAM,IAAI,IAAI,CAAA;IACd,4GAA4G;IAC5G,aAAa,CAAC,IAAI,IAAI,CAAA;IACtB,aAAa,CAAC,IAAI,OAAO,CAAA;CAC1B,CAAA;AAYD,iHAAiH;AACjH,qBAAa,kBAAmB,SAAQ,WAAW;IACjD,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;gBACzB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG;QAAE,YAAY,CAAC,EAAE,cAAc,GAAG,gBAAgB,CAAA;KAAE,EAAE,aAAa,GAAE,OAAO,CAAC,IAAI,CAAQ;CAKrK;AAED,sGAAsG;AACtG,qBAAa,eAAe;;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IACpC,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;IAC1B,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IACrC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;IAUrC;;;;OAIG;WACU,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC;gBAcvD,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,GAAE,aAAwE,EAAE,SAAS,CAAC,EAAE,iBAAiB;IAuBhM;;;;OAIG;IACH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBrB;;;OAGG;IACH,iBAAiB,CAAC,QAAQ,GAAE,QAAqC,GAAG,IAAI;IAIxE;;;;;OAKG;IACG,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7D;;;OAGG;IACH,qBAAqB,IAAI,IAAI;IAQ7B,uGAAuG;IACjG,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAStE;;;;;OAKG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,QAAyE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAiE9H;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,SAAS,MAAM,EAAE,EAAE,SAAS,GAAE,MAAqB,GAAG,MAAM,CAI3H;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,CAAC,GAAG,OAAO,CA+B7E;AAED,6FAA6F;AAC7F,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAKnG;AAmFD;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAqBrI;AAqCD,wGAAwG;AACxG,eAAO,MAAM,aAAa,EAAE,MAAyB,CAAA;AAmBrD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAYvE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,iBAAiB,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAOtF"}
|
|
@@ -2,15 +2,17 @@ import { spawn } from 'node:child_process';
|
|
|
2
2
|
import { once } from 'node:events';
|
|
3
3
|
import { rmSync } from 'node:fs';
|
|
4
4
|
import { mkdir, open, rm } from 'node:fs/promises';
|
|
5
|
-
import { dirname } from 'node:path';
|
|
5
|
+
import { basename, dirname } from 'node:path';
|
|
6
6
|
import { Readable, Writable } from 'node:stream';
|
|
7
7
|
import { setTimeout as sleep } from 'node:timers/promises';
|
|
8
8
|
import { Deadline } from "../protocol/deadline.js";
|
|
9
9
|
import { maxTimeout } from "../protocol/timeouts.js";
|
|
10
10
|
import { errorMessage } from "../protocol/failures.js";
|
|
11
|
+
import { withoutVariables } from "../shared/environment.js";
|
|
11
12
|
import { errorCode } from "../shared/error-code.js";
|
|
12
13
|
import { onlyUnreaped, procStats } from "../shared/unreaped-group.js";
|
|
13
14
|
import { OwnedProcessGroup, unverifiedMembersProblem } from "../shared/process-ownership.js";
|
|
15
|
+
import { holdLaunch, launchesHeldByJob, prepareOwnedLaunch } from "../shared/process-system.js";
|
|
14
16
|
import { closeGraceMs, LaunchError } from "./contract.js";
|
|
15
17
|
import { writeRedactedLog } from "./redacted-log.js";
|
|
16
18
|
const pollMs = 25;
|
|
@@ -86,7 +88,10 @@ export class ChromiumProcess {
|
|
|
86
88
|
resolve(this.#exit);
|
|
87
89
|
});
|
|
88
90
|
});
|
|
89
|
-
|
|
91
|
+
// A launch hands over the owner it has just read. Reading it again at once found nothing new, and on a loaded host
|
|
92
|
+
// that second reading outlasted its second and failed the browser's close however cleanly it later ended.
|
|
93
|
+
if (!this.#ownership.captured)
|
|
94
|
+
this.recordDescendants();
|
|
90
95
|
this.#lastResort = () => killAtExit(this.#ownership, profile);
|
|
91
96
|
process.on('exit', this.#lastResort);
|
|
92
97
|
}
|
|
@@ -116,12 +121,21 @@ export class ChromiumProcess {
|
|
|
116
121
|
await this.#output.closed;
|
|
117
122
|
}
|
|
118
123
|
/**
|
|
119
|
-
* Reads descendants while their launched parent is still present
|
|
120
|
-
*
|
|
124
|
+
* Reads descendants while their launched parent is still present, holding the thread, as a process made from a
|
|
125
|
+
* child no owner has read yet does. A helper recorded early is still owned after its parent dies.
|
|
121
126
|
*/
|
|
122
127
|
recordDescendants(deadline = new Deadline(closeGraceMs)) {
|
|
123
128
|
this.#keep(this.#ownership.capture(deadline));
|
|
124
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* `recordDescendants` from a reading begun now that does not hold the thread, within `deadline`, as a close reads
|
|
132
|
+
* before it asks the browser to quit. A reading that fails is kept, as one that holds the thread is.
|
|
133
|
+
*
|
|
134
|
+
* @example await chromium.recordDescendantsNow(new Deadline(5000))
|
|
135
|
+
*/
|
|
136
|
+
async recordDescendantsNow(deadline) {
|
|
137
|
+
this.#keep(await this.#ownership.captureAsync(deadline));
|
|
138
|
+
}
|
|
125
139
|
/**
|
|
126
140
|
* `recordDescendants` from a reading taken without holding the thread, as after each new page, whose renderer the
|
|
127
141
|
* browser has just started. A process-table reading takes tens of milliseconds, which a page open would otherwise wait.
|
|
@@ -240,6 +254,22 @@ export function stillThereMessage(groupId, stats, timeoutMs = closeGraceMs) {
|
|
|
240
254
|
* @example signalGroup(browser.pid, 0) // true while any browser process is still there
|
|
241
255
|
*/
|
|
242
256
|
export function signalGroup(pgid, signal) {
|
|
257
|
+
// Windows has no process group to send signal 0 to: a launch held here is asked through its job, and one held by
|
|
258
|
+
// another process only by its own pid.
|
|
259
|
+
if (signal === 0 && launchesHeldByJob) {
|
|
260
|
+
const owner = ownedGroups.get(pgid);
|
|
261
|
+
if (owner !== undefined)
|
|
262
|
+
return owner.remains();
|
|
263
|
+
try {
|
|
264
|
+
process.kill(pgid, 0);
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
if (errorCode(error) === 'ESRCH')
|
|
269
|
+
return false;
|
|
270
|
+
throw error;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
243
273
|
if (signal !== 0) {
|
|
244
274
|
const owner = ownedGroups.get(pgid);
|
|
245
275
|
if (owner === undefined)
|
|
@@ -277,18 +307,33 @@ async function spawnInGroup(options) {
|
|
|
277
307
|
const log = await openLog(options.logFile);
|
|
278
308
|
let logHandedOn = false;
|
|
279
309
|
try {
|
|
280
|
-
const hidden = new Set(options.hiddenVariables);
|
|
281
310
|
// Output to redact comes through Retest; any other goes straight to the log.
|
|
282
311
|
const outputMode = redact === undefined && redactStream === undefined ? log.fd : 'pipe';
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
312
|
+
try {
|
|
313
|
+
prepareOwnedLaunch();
|
|
314
|
+
}
|
|
315
|
+
catch (error) {
|
|
316
|
+
throw new LaunchError(`Cannot start ${options.executable}: ${errorMessage(error)}`, { cause: error });
|
|
317
|
+
}
|
|
318
|
+
let child;
|
|
319
|
+
try {
|
|
320
|
+
child = spawn(options.executable, options.args, {
|
|
321
|
+
env: withoutVariables(process.env, options.hiddenVariables),
|
|
322
|
+
detached: true,
|
|
323
|
+
stdio: ['ignore', outputMode, outputMode, 'pipe', 'pipe'],
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
catch (error) {
|
|
327
|
+
// Windows refuses a program whose access list denies this user running it at the spawn itself, with EPERM; the
|
|
328
|
+
// check before the launch cannot see that there, as it sees a mode on macOS and Linux.
|
|
329
|
+
const refused = errorCode(error) === 'EPERM' || errorCode(error) === 'EACCES';
|
|
330
|
+
throw new LaunchError(refused ? `${options.executable} is not executable. Allow it to run, or pass another browser.` : `Cannot start ${options.executable}: ${errorMessage(error)}`, { cause: error });
|
|
331
|
+
}
|
|
288
332
|
await once(child, 'spawn').catch((error) => {
|
|
289
333
|
throw new LaunchError(`Cannot start ${options.executable}: ${errorMessage(error)}`, { cause: error });
|
|
290
334
|
});
|
|
291
|
-
|
|
335
|
+
// Every process of the browser carries its profile's folder in its command line.
|
|
336
|
+
const ownership = holdLaunch(child, options.profile === undefined ? {} : { marker: basename(options.profile) });
|
|
292
337
|
const ownershipProblems = ownership.capture();
|
|
293
338
|
const [, , , writable, readable] = child.stdio;
|
|
294
339
|
if (!(writable instanceof Writable) || !(readable instanceof Readable)) {
|
|
@@ -354,7 +399,7 @@ async function spawnInGroup(options) {
|
|
|
354
399
|
* readers and flush accepted bytes and queued writes within that same writing bound. This does not claim remote
|
|
355
400
|
* EOF or collect bytes an inherited writer sends later. An output without this support still fails and is canceled.
|
|
356
401
|
*/
|
|
357
|
-
async function outputWithin(output, timeoutMs, confirmedGone) {
|
|
402
|
+
export async function outputWithin(output, timeoutMs, confirmedGone) {
|
|
358
403
|
const first = await settledWithin(output.closed, timeoutMs);
|
|
359
404
|
if (first !== undefined)
|
|
360
405
|
return first;
|
|
@@ -404,7 +449,8 @@ async function openLog(logFile) {
|
|
|
404
449
|
throw new LaunchError(`Cannot open the browser log ${logFile}: ${errorMessage(error)}`, { cause: error });
|
|
405
450
|
}
|
|
406
451
|
}
|
|
407
|
-
//
|
|
452
|
+
// Each look reads the group, or waits for a reading already under way, before the deadline is asked, so a group that
|
|
453
|
+
// ended while the host was busy reads as ended.
|
|
408
454
|
async function groupEnds(ownership, grace, { ref = true, deadline = grace } = {}) {
|
|
409
455
|
while (await ownership.remainsAsync(deadline)) {
|
|
410
456
|
if (grace.expired || deadline.reached || deadline.signal?.aborted === true)
|
|
@@ -413,21 +459,53 @@ async function groupEnds(ownership, grace, { ref = true, deadline = grace } = {}
|
|
|
413
459
|
}
|
|
414
460
|
return true;
|
|
415
461
|
}
|
|
462
|
+
/** How long an exit hook on Windows asks again to remove a folder whose processes it confirmed gone. */
|
|
463
|
+
export const exitRemovalMs = 2 * closeGraceMs;
|
|
416
464
|
// Runs while the Retest process exits, when a failure can neither be awaited nor reported.
|
|
417
465
|
function killAtExit(ownership, profile) {
|
|
418
466
|
try {
|
|
419
467
|
const deadline = new Deadline(closeGraceMs);
|
|
420
468
|
ownership.signalNow('SIGKILL', deadline);
|
|
421
|
-
if (profile
|
|
469
|
+
if (profile === undefined || !groupEndsNow(ownership, deadline))
|
|
470
|
+
return;
|
|
471
|
+
// On Windows the end and its confirmation are runs of retest-supervisor, which a slow host can spend most of the
|
|
472
|
+
// bound on, and the folder refuses removal for up to a second after its processes left their job, as a scanner
|
|
473
|
+
// holds what they wrote; the removal gets a bound of its own, so a profile whose processes are confirmed gone is
|
|
474
|
+
// removed.
|
|
475
|
+
if (launchesHeldByJob)
|
|
476
|
+
removeOnceFree(profile, new Deadline(exitRemovalMs));
|
|
477
|
+
else
|
|
422
478
|
rmSync(profile, { recursive: true, force: true, maxRetries: 3 });
|
|
423
479
|
}
|
|
424
480
|
catch {
|
|
425
481
|
// Throwing here would replace the exit code Retest chose.
|
|
426
482
|
}
|
|
427
483
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
484
|
+
/**
|
|
485
|
+
* Removes a folder from an exit hook on Windows, where a folder whose files processes just ended were using refuses
|
|
486
|
+
* removal for a moment after they left their job, and the synchronous removal does not wait: it is asked again, a poll
|
|
487
|
+
* apart, until the deadline.
|
|
488
|
+
*/
|
|
489
|
+
export function removeOnceFree(folder, deadline) {
|
|
490
|
+
const pause = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
|
491
|
+
for (;;) {
|
|
492
|
+
try {
|
|
493
|
+
rmSync(folder, { recursive: true, force: true });
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
catch (error) {
|
|
497
|
+
const code = errorCode(error);
|
|
498
|
+
if ((code !== 'EPERM' && code !== 'EBUSY' && code !== 'ENOTEMPTY') || deadline.expired)
|
|
499
|
+
throw error;
|
|
500
|
+
Atomics.wait(pause, 0, 0, Math.min(pollMs, deadline.remainingMs));
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Whether a group is gone, for an exit hook, which cannot await. Processes just sent SIGKILL are still exiting when they
|
|
506
|
+
* are first read, so the group is read again, a poll apart, until it is gone or the deadline passes.
|
|
507
|
+
*/
|
|
508
|
+
export function groupEndsNow(ownership, deadline) {
|
|
431
509
|
const pause = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
|
432
510
|
while (ownership.remains(deadline)) {
|
|
433
511
|
if (deadline.expired)
|